# low-code
**Repository Path**: turn-into-an-island/low-code
## Basic Information
- **Project Name**: low-code
- **Description**: 青训营低代码案例
- **Primary Language**: JavaScript
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-07-25
- **Last Updated**: 2023-03-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
一、项目介绍
低代码平台项目核心信息:本项目旨在开发一个供运营、产品快速搭建网站的可视化平台,利用可视化的拖拽与属性配置完成构建和日常运营,而开发只进行平台的维护、业务组件的新增和迭代。
项目服务地址-必须:http://116.62.226.254/
gitee地址:low-code: 青训营低代码学习案例,仅供学习 (gitee.com)
二、项目分工
团队成员
主要贡献
王盈
物料区与相应属性配置等
薛彬
项目拖拽搭建平台等
汪文松
无
谭晶
无
田诗圆
无
三、项目实现
3.1 技术选型与相关开发文档
Vue3+Sass+jsx+Webpack
选择Vue的考虑:
体积小,复杂度低
Vue 的体积小,网络性能角度相比 React 更适合移动端
移动端一般巨型项目很少,从代码结构上来讲,使用 Vue 实现更符合我们的场景复杂度, React 更适合大型相对更复杂的 SPA
上手成本和迁移成本低
Vue 的学习和上手成本相对更低,团队成员对于 Vue 的认可度和热情也比较高
组件内双向绑定、数据依赖收集
组件内支持双向绑定,更方便的去进行组件内的数据响应与交互
独有的数据依赖收集模式使其默认的数据响应和渲染效率都要比 React 高一些
组件库:
Element Plus
统一规范:
主要就是操作json配置文件;渲染区 使用json文件动态渲染成对应的组件
{
"label": "button",
"icon": "icon-button",
props: {
"text":...
"type":...
"size":...
}
}
[图片]
属性控制面板生成过程
进阶方式解耦、工业化,这样才能在后面使大量组件接入平台。然而有一个风险点「JSON是无规则的」,组件描述JSON应该「按平台定的规则」来写「平台才能识别」,所以我们需要用规则来标准化JSON。 解决办法就是通过JSON Schema协议来约束JSON,让它根据我们定的标准来编写。
「Schema协议」,是我们「平台规范」的工具,也就是我们可视化开发平台的核心。
3.2 架构设计
可视化搭建平台主要有三块:
- 项目拖拽搭建平台的构建
- 物料接入平台流水线的构建
- 属性配置区的构建
[图片]
3.3 项目代码介绍
组件结构
schema,一种 JSON 数据结构,我用于描述画布信息,以及画布中拖拽添加的组件元素信息。这里我们使用到了画布的宽高信息,在 schema JSON 中结构如下:
{
"container": {
"width": ...
"height": ...
},
"blocks": [
// 画布中拖拽的元素集合,下面介绍
]
}
基本上
组件设计包含以下3个部分组件:
1、component 组件主体
2、schema 组件的DSL,结构协议层
3、render里的定义了组件的类型、外观、从属关系,后期考虑纳入schema
registerConfig.register({
label: '按钮',
resize: {
width: true,
height: true
},
preview: () => ,
render: ({ props, size }) => {props.text || '渲染按钮'},
key: 'button',
props: {
text: createInputProp('按钮内容'),
type: createSelectProp('按钮类型', [
{ label: 'primary', value: 'primary' },
{ label: 'success', value: 'success' },
{ label: 'warning', value: 'warning' },
{ label: 'danger', value: 'danger' },
]),
size: createSelectProp('按钮尺寸', [
{ label: '默认', value: '' },
{ label: '大', value: 'large' },
{ label: '小', value: 'small' },
])
}
})
我们只需要按照上面的方式编写组件即可,props是定义的数据层,用来控制组件的shape,也就是组件的表现。
function createEditorConfig() {
const componentList = [];
const componentMap = {}
return {
componentList,
componentMap,
register: (component) => {
componentList.push(component);
componentMap[component.key] = component;
}
}
}
两个关键变量:
- componentList: 物料组件的集合,用于渲染编辑器左侧物料的数据源;
- componentMap: 是一个 map 映射关系,根据 type 字段进行映射,有了它,就可以在画布中通过 Schema 数据去匹配物料组件来渲染画布视图。
有了数据,我们就可以通过 map 渲染左侧区物料组件:
......
if (component && component.props) {
content.push(Object.entries(component.props).map(([propName, propConfig]) => {
return
....
}[propConfig.type]()}
}))
}
if(component && component.model){
content.push(Object.entries(component.model).map(([modelName,label])=>{
return
{}
}))
}
}
editData表示组件的可编辑属性, 我们可以自定义哪些组件可编辑. propConfig为组件接收的属性, 和editData数组项中的key一一对应.
1、关于辅助线:
当画布中存在两个或多个 block,拖动其中一个 block 至另一个 block(参照物)周围时,能够显示出上下,或者居中的参考线,便于对两个 block 进行对齐排版。
2、关于吸附:
当拖动 block 的移动位置非常接近另一个 block 的位置时(比如两个 block 的相差距离 < 5px),能够直接让它们紧挨在一起(吸附),而非手动去拖动实现精准对齐。这是一个很好的体验!
思路
辅助线显示的规则是拿选中的 blocks 与其余未选中的 blocks,在拖动移动过程中进行位置比对。
在拖动一个或多个 block(focus blocks)前,画布上其余的 block(unfocused blocks)需要提供自身周围的参考线(即辅助线,下文中的 lines);
每次拖动 focus blocks 时,会根据当前移动到的位置,与 unfocused blocks 提供的辅助线集合(lines)中的位置进行比较,若满足临近条件,显示其辅助线;
每一个 unfocused blocks 周围都可能存在10种辅助线,横向、纵向分别各5条。
定义 Hooks
这里需要用到两个 Hook:
- selectIndex:记录当前选中拖动的 block 索引;
- markLine:记录水平、垂直辅助线显示的位置,因为涉及到视图更新
const selectIndex = ref(-1);
let markLine = reactive({
x: null,
y: null
})
菜单功能:
删除,导出json,导入json,置顶,置后,关闭(发布),预览。
后端
spring-boot
用户登录接口
- `POST` /api/login
| 参数名 | 是否必选 | 类型 | 说明 |
| ------------- |:-------------:|:-----:| -------------:|
| username | true | string | 用户名 |
| password | true | string | 密码 |
返回示例
{
"code": 1,
"msg": "登录成功",
"data": ""
}
- `GET` /api/register
| 参数名 | 是否必选 | 类型 | 说明 |
| ------------- |:-------------:|:-----:| -------------:|
| username | true | string | 用户名 |
| password | true | string | 密码 |
{
"code": 0,
"msg": "注册失败",
"data": "用户已存在"
}
未完成的
## 模版管理
### 获取模版库
- `GET` /api/tpls/free
返回示例
``` json
{
"state": 200,
"result": [
{
"img": "http://xxx/uploads/",
"name": "合作模版",
"tid": "B73349B6"
}
]
}
```
### 保存模版
- `POST` /api/tpl/save
先决条件:
- 用户已登陆
| 参数名 | 是否必选 | 类型 | 说明 |
| ------------- |:-------------:|:-----:| -------------:|
| name | true | string | 模版名称 |
| cate | true | string | 模版分类 |
| img | false | string | 模版封面图 |
| tpl | true | array | 模版数据 |
| pageConfig | false | object | 模版全局配置 |
返回示例
``` json
{
"state": 200,
"result": {
"tid": ""
},
"msg": "保存成功"
}
```
### 删除模版
- `DELETE` /api/tpl/del
先决条件:
- 用户已登陆
| 参数名 | 是否必选 | 类型 | 说明 |
| ------------- |:-------------:|:-----:| -------------:|
| tid | true | string | H5模版id |
返回示例
``` json
{
"state": 200,
"result": null,
"msg": "删除成功"
}
```
## 文件上传
- `POST` /files/upload/free
先决条件:
- 用户已登陆
| 参数名 | 是否必选 | 类型 | 说明 |
| ------------- |:-------------:|:-----:| -------------:|
| File | true | File | 文件对象 |
返回示例
``` json
{
"state": 200,
"result": {
"filename": "",
"url": "",
"size":
},
"msg": "文件上传成功"
}
```
四、测试结果
建议从功能测试和性能测试两部分分析,其中功能测试补充测试用例,性能测试补充性能分析报告、可优化点等内容。
待完善Vitest
五、Demo 演示视频 (必填)
暂时无法在飞书文档外展示此内容
六、项目总结与反思
1. 目前仍存在的问题
项目后端很多未完成,用户自定义组件或者是嵌套组件较难实现。
2. 已识别出的优化项
1.优化了编辑器拖拽移动体验:实现辅助线和吸附功能
2图片懒加载
3支持鼠标快捷键操作
3. 架构演进的可能性
4. 项目过程中的反思与总结
团队确实协作出现问题,后端接触时间太短,还离开了几个,由于时间问题,导致项目有些功能没有实现,之后我们会继续学习,提高自身的能力。
七、其他补充资料(选填)