低代码引擎实战

基于 Low-Code Engine 快速打造高生产力的低代码研发平台

官网

https://lowcode-engine.cn/

实践

1. 把低代码部署到服务端

1
2
3
4
5
6
7
8
9
// 低代码模版
// 1. 复制lowcode-demo的public/index.ejs到服务端
// 2. 以下文件替换为本地文件, 或者通过npm发包的方式,详见下面注释~
// <link href="./css/<%= scenario %>.css" rel="stylesheet" /> - http://localhost:5556/build/css/index.css
// <script type="text/javascript" src="./js/<%= scenario %>.js"></script> - http://localhost:5556/build/js/index.js

app.get('/lowcode', async function (req, res) {
res.render('index.ejs'); // 使用ejs模版引擎
})

2. 保存schema到服务端

1
2
3
4
5
6
7
8
9
10
11
12
// 客户端
// lowcode-demo/src/universal/utils.ts
export const saveSchema = async () => {
let currentPage = 'home';
if (location.search) {
currentPage = new URLSearchParams(location.search.slice(1)).get('page') || 'home'
}
const schema = project.exportSchema();
const url = 'http://localhost:3000/api/v1/schemas';
const response = await request2.post(url, { page: currentPage, schema})
Message.success('成功保存');
};
1
2
3
4
5
6
7
8
9
10
11
// 服务端
// lowcode-express/index.js
app.post('/api/v1/schemas', async function (req, res) {
const { page, schema } = req.body;
const response = await fs.writeFileSync(`./schemas/${page}.json`, JSON.stringify(schema))
res.send({
code: 0,
data: response
});
});

3. 从服务器获取资产包

1
2
3
4
5
6
7
8
9
10
11
// 客户端 伪代码
// src/universal/plugin.tsx
- import assets from './assets.json' // 删除
......
+ const assets = getAssets();

// 获取资产包 src/universal/utils.ts
export const getAssets = async ()=> {
return request2.get('http://localhost:3000/assets.json');
}

1
2
3
4
5
6
7
8
9
// 服务端
// 3. 获取资产包
// index.js
app.get('/assets.json', async function (req, res) {
res.send({
code: 0,
data: assets,
});
})

4. 页面预览

1
2
3
4
5
// 把lowcode-demo/public/preview.html拷贝到服务端
app.get('/preview.html', async function (req, res) {
res.render('preview.ejs'); // 通过模板引擎渲染预览页面
})

1
2
3
4
5
6
7
8
9
10
// 客户端
// src/preview.tsx
async function init() {
const { data: { packages } } = await getAssets(); // 获取资产包信息
const { data: projectSchema } = await getCurrentPageSchema(); // 获取当前页面schema
...
const { componentsMap: componentsMapArray, componentsTree } = projectSchema;
...
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 获取资产包
// index.js
app.get('/assets.json', async function (req, res) {
res.send({
code: 0,
data: assets,
});
})

// 获取页面schema
app.get('/get-page-schema', async function (req, res) {
console.log('req---', req.query)
const { page } = req.query;
const data = require(`./schemas/${page}.json`);
res.send({
code: 0,
data
});
})

5. 新增面板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// src/plugins/nav/index.tsx
import * as React from 'react';
import { Nav } from '@alifd/next';
const { Item } = Nav;
export default () => {
const queryString = location.search || '';
const defaultCurrentPage = queryString.includes('home') ? 'home' : 'login';
const onSelect = (keys : string[]) => {
const key: string = keys[0];
location.href = `${location.pathname}?page=${key}`;
};
return <Nav type='line' selectedKeys={[defaultCurrentPage]} onSelect={onSelect}>
<Item key='home' >首页</Item>
<Item key='login' >登录页</Item>
</Nav>
}

// src/universal/plugin.tsx
import navPage from 'src/plugins/nav/index';
...
// 新增导航
skeleton.add({
index: -1,
area: 'leftArea',
type: 'PanelDock',
name: 'navPage',
content: navPage,
contentProps: {},
props: {
align: 'top',
icon: 'kaiwenjianjia',
description: '页面导航',
},
});

6. 自定义物料

初始化物料仓库
npm init @alilc/element lowcode-material-example

1
2
3
4
5
6
7
// lowcode-material-example/package.json
{
"lowcode:build": "build-scripts build --config ./build.lowcode.js",
}
# npm run lowcode:build
# npm login // 登陆npm账号,npm源指向官方源

发布完成后,查看资产包:
https://unpkg.com/browse/lowcode-material-example@1.1.3/build/lowcode/assets-prod.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 服务端
// lowcode-express/schemas/assets.json
// 把lowcode-material-example资产包配置到schemas/assets.json
{
"packages": [
...
// 新增包信息
{
"package": "lowcode-material-example",
"version": "1.1.3",
"library": "BizComp",
"urls": [
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/render/default/view.js",
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/render/default/view.css"
],
"editUrls": [
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/view.js",
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/view.css"
],
"advancedUrls": {
"default": [
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/render/default/view.js",
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/render/default/view.css"
]
},
"advancedEditUrls": {}
}
],
"components": [
...
// 新增组件信息
{
"exportName": "LowcodeMaterialExampleMeta",
"npm": {
"package": "lowcode-material-example",
"version": "1.1.3"
},
"url": "https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/meta.js",
"urls": {
"default": "https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/meta.js"
},
"advancedUrls": {
"default": [
"https://unpkg.com/lowcode-material-example@1.1.3/build/lowcode/meta.js"
]
}
}
]
}

7. 获取远程数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 源码面板
class LowcodeComponent extends Component {
state = {
brands: []
}
componentDidMount() {
// 品牌可选项
fetch('http://127.0.0.1:3000/api/brands')
.then(response => response.json())
.then(response => {
console.log('data__', response)
const { data: { list = [] } } = response;
this.setState({
brands: list
})
});
}
componentWillUnmount() {
console.log('will unmount');
}
testFunc() {
console.log('test func');
}
onClick() {
this.setState({
isShowDialog: true
})
}
closeDialog() {
this.setState({
isShowDialog: false
})
}
}