【阿里低代码引擎实战】— 自定义插件-多页面管理(二)

【阿里低代码引擎实战】--- 自定义插件-多页面管理(二)

本文正在参加阿里低代码引擎征文活动

上一篇笔记简单实现了一个多页面管理,页面数据通过调接口来获取,后端项目使用 egg.js 搭建,上篇指路:juejin.cn/post/734457...

这篇我们在上一篇的基础上,使用低代码引擎demo拖拉拽生成自已的页面,通过调接口将不同页面的schema数据保存在 mysql 数据库中,并且根据不同页面路由回显相对应的页面数据。

本篇代码github地址:github.com/JoeXu727/al...

github.com/JoeXu727/lo...

一. 新建数据库表

  1. 安装 MySQLnavicat 的过程不做赘述,本文使用 MySQL8.0版本;

  2. 新建数据库表 lowcodepage_schema 字段用于存储页面schema,page_type 用于存储页面类型,延续上一篇,页面有两种类型(home 和 user),并且 page_type 还可以直接作为该表的主键;

  1. 直接在表里新增两条数据,如图:

二. 在eggjs项目中操作数据库

egg官方文档:www.eggjs.org/zh-CN/tutor...

  1. egg.js 项目使用mysql8.0,首先安装 egg-mysql

    css 复制代码
    $ cnpm i --save egg-mysql

    分别在 plugin.js 和 config.default.js 添加如下代码:

    java 复制代码
    plugin.js
    ​
    module.exports = {
      mysql: {
        enable: true,
        package: "egg-mysql",
      },
    };
    arduino 复制代码
    config.default.js
    ​
    module.exports = (appInfo) => {
      // mysql数据库配置
      config.mysql = {
        // 单数据库信息配置
        client: {
          // host
          host: '127.0.0.1',
          // 端口号
          port: '3306',
          // 用户名
          user: 'root',
          // 密码
          password: '123456',
          // 数据库名
          database: 'lowcode',
        },
        // 是否加载到 app 上,默认开启
        app: true,
        // 是否加载到 agent 上,默认关闭
        agent: false,
      }
    }

    配置完成后,启动egg项目可能会遇到如下报错:nodejs.ER_NOT_SUPPORTED_AUTH_MODEError: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client;

    报错原因:登录数据库的客户端跟mysql8.0不兼容了,mysql8.0密码认证采用了新的密码格式;

    解决方法:登录数据库后输入如下命令,将your password改为你自己的密码:

    sql 复制代码
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your password';

    最后再输入以下命令,回车,现在就可以正常启动egg项目连接数据库了;

    ini 复制代码
    mysql> FLUSH PRIVILEGES;
  1. 接着开始写 controller 层的逻辑,新建 admin.js :

    csharp 复制代码
    controller/admin.js
    ​
    const { Controller } = require('egg');
    ​
    class AdminController extends Controller {
        // 查询页面schema
        async getSchema() {
            const { ctx } = this;
            const { page_type } = ctx.query;
            const result = await ctx.service.admin.getPageSchema(page_type);
            ctx.body = {
                status: 200,
                msg: '查询成功',
                data: result,
            };
        }
        // 保存页面schema
        async saveSchema() {
            const { ctx } = this;
            const params = ctx.request.body;
            const result = await ctx.service.admin.savePageSchema(params);
            if (result) {
                ctx.body = {
                    status: 200,
                    msg: '保存成功',
                    data: result,
                };
            } else {
                ctx.body = {
                    status: 201,
                    msg: '保存失败',
                    data: {},
                };
            }
        }
    ​
    }
    ​
    module.exports = AdminController;
  2. 加上admin对应的路由:

    ini 复制代码
    router.js
    ​
    module.exports = app => {
      const { router, controller } = app;
      router.get('/admin', controller.admin.getSchema);
      router.post('/admin', controller.admin.saveSchema);
    };
  3. 在 service 层新建 admin.js ,进行数据库操作:

    csharp 复制代码
    service/admin.js
    ​
    const Service = require('egg').Service;
    ​
    class AdminService extends Service {
    ​
        // 查询页面schema
        async getPageSchema(page_type) {
            try {
                const params = {
                    page_type
                };
                const result = await this.app.mysql.get('lowcode', params);
                return result;
            } catch (error) {
                console.log(error);
            }
        }
    ​
        // 保存页面schema
        async savePageSchema(params) {
            try {
                const row = {
                    page_schema: params.page_schema,
                };
                // 主键是自定义的page_type,需要在 `where` 里配置
                const options = {
                    where: {
                        page_type: params.page_type
                    }
                };
                const result = await this.app.mysql.update('lowcode', row, options);
                return result;
            } catch (error) {
                console.log(error);
            }
        }
    }
    ​
    module.exports = AdminService;
  4. 在postman中测试下查询和保存这两个接口:

    查询页面schema:

    保存页面schema:

三. lowcode-demo 项目

  1. 将项目里本来的 保存到本地 功能改为 保存,存入数据库中;在代码中修改按钮名称,并传入页面类型pageType:

    javascript 复制代码
    plugin-save-sample/index.tsx
    ​
    // 保存功能示例
    const SaveSamplePlugin = (ctx: IPublicModelPluginContext) => {
      return {
        async init() {
          const { skeleton, hotkey, config } = ctx;
          const scenarioName = config.get('scenarioName');
    ​
          const match = location.search.match(/?page=([^&#]+)/);
          const menuType = match ? match[1] : 'home';
          const pageType = menuType === 'home' ? 1 : 2;
    ​
          skeleton.add({
            name: 'saveSample',
            area: 'topArea',
            type: 'Widget',
            props: {
              align: 'right',
            },
            content: (
              <Button onClick={() => saveSchema(pageType)}>
                保存
              </Button>
            ),
          });
          ...
        },
      };
    }
  2. 修改 mockService 中的 saveSchema 方法,调接口保存在mysql中:

    php 复制代码
    mockService.ts
    ​
    export const saveSchema = async (page_type: number = 1) => {
      const schema = project.exportSchema();
      const url = 'http://127.0.0.1:7001/admin';
      const response = await fetch(url, {
        method: 'POST',
        mode: 'cors',
        cache: 'no-cache',
        credentials: 'same-origin',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          page_schema: JSON.stringify(schema),
          page_type: page_type,
        })
      });
      Message.success('成功保存页面schema');
    };
  3. 处理页面查询逻辑,注意从 project.exportSchema() 获取到的 schema 在使用的时候要用 schema.componentsTree[0]

    typescript 复制代码
    plugin-editor-init/index.tsx
    ​
    const EditorInitPlugin = (ctx: IPublicModelPluginContext, options: any) => {
      return {
        async init() {
          ...
    ​
          const match = location.search.match(/?page=([^&#]+)/);
          const menuType = match ? match[1] : 'home';
          const pageType = menuType === 'home' ? 1 : 2;
          const schema = await getProjectSchema(pageType, scenarioName);
          // 加载 schema
          project.importSchema(schema as any);
        },
      };
    };
    ini 复制代码
    mockService.ts
    ​
    export const getProjectSchema = async (
      pageType: number = 1,
      scenarioName: string = 'unknown',
    ): Promise<IPublicTypeProjectSchema> => {
      const pageSchema = await getPageSchema(pageType, scenarioName);
      return generateProjectSchema(pageSchema, DefaultI18nSchema);
    };
    ​
    export const getPageSchema = async (
      pageType: number = 1,
      scenarioName: string = 'unknown',
    ) => {
      let pageSchema;
      let url = `http://127.0.0.1:7001/admin?page_type=${pageType}`;
      pageSchema = await fetchData(url).then((res) => {
        let schema = JSON.parse(res.data.page_schema)
        return schema.componentsTree[0];
      });
    ​
      if (pageSchema) {
        return pageSchema;
      }
    };

四. 结果演示

在demo中随意搭建一个home页面,点击右上角保存后刷新页面,查看页面是否保存成功:

左侧菜单切换到user页面,再搭建一个,点击保存:

切换菜单,正确展示出对应页面,大功告成~

==========================================================

以上为个人工作学习笔记总结,供学习参考交流,未经允许禁止转载或商用。

个人博客地址:joexu727.github.io/

相关推荐
热爱编程的小曾25 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin37 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox1 小时前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行2 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_593758102 小时前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox