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

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

上一篇笔记简略完成了一个多页面办理,页面数据经过调接口来获取,后端项目运用 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

    $ cnpm i --save egg-mysql
    

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

    plugin.js
    ​
    module.exports = {
     mysql: {
      enable: true,
      package: "egg-mysql",
      },
    };
    
    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改为你自己的暗码:

    mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your password';
    

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

    mysql> FLUSH PRIVILEGES;
    

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

  1. 接着开始写 controller 层的逻辑,新建 admin.js :

    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对应的路由:

    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 ,进行数据库操作:

    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:

    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中:

    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]

    plugin-editor-init/index.tsxconst 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);
       },
      };
    };
    
    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/