【阿里低代码引擎实战】--- 自定义插件-多页面管理(二)
本文正在参加阿里低代码引擎征文活动
上一篇笔记简单实现了一个多页面管理,页面数据通过调接口来获取,后端项目使用 egg.js
搭建,上篇指路:juejin.cn/post/734457...
这篇我们在上一篇的基础上,使用低代码引擎demo拖拉拽生成自已的页面,通过调接口将不同页面的schema数据保存在 mysql
数据库中,并且根据不同页面路由回显相对应的页面数据。
本篇代码github地址:github.com/JoeXu727/al...
一. 新建数据库表
-
安装
MySQL
与navicat
的过程不做赘述,本文使用 MySQL8.0版本; -
新建数据库表
lowcode
,page_schema
字段用于存储页面schema,page_type
用于存储页面类型,延续上一篇,页面有两种类型(home 和 user),并且page_type
还可以直接作为该表的主键;
-
直接在表里新增两条数据,如图:
二. 在eggjs项目中操作数据库
egg官方文档:www.eggjs.org/zh-CN/tutor...
-
egg.js 项目使用mysql8.0,首先安装
egg-mysql
:css$ cnpm i --save egg-mysql
分别在 plugin.js 和 config.default.js 添加如下代码:
javaplugin.js module.exports = { mysql: { enable: true, package: "egg-mysql", }, };
arduinoconfig.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改为你自己的密码:
sqlmysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your password';
最后再输入以下命令,回车,现在就可以正常启动egg项目连接数据库了;
inimysql> FLUSH PRIVILEGES;
-
接着开始写 controller 层的逻辑,新建 admin.js :
csharpcontroller/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;
-
加上admin对应的路由:
inirouter.js module.exports = app => { const { router, controller } = app; router.get('/admin', controller.admin.getSchema); router.post('/admin', controller.admin.saveSchema); };
-
在 service 层新建 admin.js ,进行数据库操作:
csharpservice/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;
-
在postman中测试下查询和保存这两个接口:
查询页面schema:
保存页面schema:
三. lowcode-demo 项目
-
将项目里本来的
保存到本地
功能改为保存
,存入数据库中;在代码中修改按钮名称,并传入页面类型pageType:javascriptplugin-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> ), }); ... }, }; }
-
修改
mockService
中的saveSchema
方法,调接口保存在mysql中:phpmockService.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'); };
-
处理页面查询逻辑,注意从
project.exportSchema()
获取到的 schema 在使用的时候要用schema.componentsTree[0]
:typescriptplugin-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); }, }; };
inimockService.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/