概述
- 低代码系统开发之前,我们首先要进行一些准备
- 我们首先知道我们软件开发的一般流程
- 同时,我们还要知道,我们整个系统平台的需求如何
- 之后,我们要基于需求进行设计,包含UI设计与系统架构设计
一般开发流程
- 系统开发一般要经过如下几个步骤,低代码系统平台也不例外
- 我们来看下软件开发的生命周期 (SDLC)
1 )需求分析
- 需求调研
- 技术架构讨论
2 )软件设计
- 技术架构设计
- 原型/UX/UI 设计
3 )研发
- 业务系统详细设计
- 业务系统开发
- 单元测试
- 增加CI构建文件和镜像构建文件DockerFile
- 提交代码到代码仓GitLab
4 )测试和预生产测试
4.1 测试环境
- 创建应用,创建配置
- 配置CICD流程,填写仓库地址,用户名密码等
- 触发CI构建镜像,CD自动发布应用到测试环境
- 测试环境应用测试
- 代码迭代,问题修复后再测试
- 测试通过,转预生产
4.2 预生产测试
- 预生产测试
- 迭代回归
- 生产上线
5 )生产部署
- 上线流程申请
- 配置修改以及确认
- 上线准备 (应用, 设备, 人员, 网络等)
6 )运营
- 服务用户
- 持续测试
- 技术支持
需求分析
这里,我们拆分来说
1 )B端需求
1.1 用户
- 用户的登录和注册
- 获取验证码
- 成功后获取用户信息并跳转到首页
- 在首页顶部导航中展示用户名称
- 用户角色:
- 普通用户: 查看,分享
- 运营人员: 发布作品,查看统计
- 管理员: 下线作品,公开模板,设置模板状态为Hot等
1.2 首页
- 模板列表和详情
- 列表可以翻页,搜索,单项模板可以进入详情
- 详情中展示模板缩略图,有二维码预览, 下载模板图片,使用模板按钮
1.3 个人中心
- 我的作品和模板
- 作品是已经做好的作品,发布后的作品
- 模板是具有特殊属性的作品
- 可以创建,保存,发布,获取作品列表和详情
- 分享到 H5 (这里可以创建渠道,比如微信,QQ等不同的渠道) 可以通过新域名来展示作品
- 可以在分享的时候创建和删除渠道,方便用户
- 作品数据信息
- PV、UV
- 分渠道统计数据
- 消息中心
- 用于管理一些关于自己的消息通知
- 比如:系统消息,他人点赞使用了你的作品
- 回收站
- 一个简单的表格,列出自己删除的项目,每个项目给一个“恢复”功能。
- 个人信息管理
- 信息修改
2 )编辑器需求
-
这个编辑器是在B端需求中单独拆分出来的,因为其设计的复杂性,这里单独拿出来说
-
编辑器页面顶部有预览和设置,保存,发布功能
-
编辑器主题分左中右, 原型如下
-
预览和设置功能
-
设置基本信息功能
- 可修改封面图、标题和副标题。
- 这些基本信息,也会体现到页面分享时。
- 所以,当编辑基本信息时,预览界面要显示成分享的样子。
-
保存功能
- 点击“保存”按钮,保存当前内容到服务端。
- 每隔几秒自动保存到服务端(现在的 web 编辑工具,都是实时自动保存的)
- 关闭时未保存的提示
-
发布功能
- 点击发布按钮,即可将该作品发布为 h5 界面,状态也变为“已发布”
- 发布成功之后,弹出该界面
-
设置渠道
- 渠道,就是一个唯一的标识,放在 url 上,让该渠道的 url 和其他的 url 区分开来,好做区分统计。
- 例如,一个作品发布为 h5 的 url 是 xxx/index.html ,但是这个 h5 要作为广告投放在不同的地方(微信,头条,支付宝等)
- 活动结束后,运营人员不仅要看这个 h5 总的统计数据,还要看不同地方的数据,以区分哪里投放效果好
- 这是运营的基本需求,解决方案就是渠道
- 我们创建一个“微信”的渠道,让它对应的 url 是 xxx/index.html?channel=aaa
- 再创建一个“支付宝”的渠道,让它对应的 url 是 xxx/index.html?channel=bbb
- 渠道名是中文的,便于标识记录,渠道号就是一个 url 参数,参数名是 channel ,参数值是 uuid 形式,不可重复
- 这样,如果要投放在不同的地方,我们就创建多个渠道,把渠道对应的唯一链接投放过去,这样就可以根据 channel 参数来区分统计了
- 功能描述
- 初次发布时,只有一个“默认”渠道
- 可以输入渠道名称,添加新的渠道。渠道名称不能和已有的重复
- 渠道号都是 uuid 就直接自动生成了
- 可以删除已有的渠道
- 但如果此时只剩下一个渠道了,则不能继续删除,即至少保留一个渠道
- 注意:重新发布时,渠道不能丢失,而且链接不能变,分渠道统计数,可以在作品统计页查看
-
发布为模板
- 模板就不需要渠道了,只有链接即可
- tag 列表由后台管理维护,即:官方 tag
- 公开的模板可以被别人看到,私有的只能自己看到
- 注意:重新发布时,tag 和公开设置不能丢失
-
编辑器组件面板
-
组件面板里放所有的组件,点击每个组件,即可将组件放在画布里。
-
-
画布
- 画布展示当前作品的内容,都是以一个一个组件的形式。
- 选中的组件,也就是点击组件即可选中,只能一次选中一个组件,选中的组件要高亮显示。
-
新建/删除组件功能
- 点击组件面板中的组件,可添加到画布中。
- 选中组件后,键盘删除键,即可删除组件。
-
复制/粘贴
- 选中一个组件,ctrl + c 可复制该组件,ctrl + v 可以粘贴到画布中
- 组件属性、内容和复制的组件一样
-
修改内容功能
- 针对文本组件、标题组件,双击后可编辑内容
-
调整大小功能
- 针对图形、图片组件,选中后可拖拽四周的触手,来调整大小
- 拖拽定位
- 选中组件后,可拖拽调整位置
-
右键菜单功能
- 复制
- 粘贴(仅当复制过组件之后,才可用)
- 删除
- 隐藏
- 锁定/解锁
-
图层面板
- 图层即画布中的组件,数据源是一样的,只不过此处用列表的形式列出来
-
选中关联功能
- 画布中选中组件时,对应的图层也会被选中
- 同理,选中图层时,对应的画布中的组件,也要被选中
-
删除关联功能
- 画布中删除组件时,对应的图层也会被删除。(同理于新增组件,也会增加图层)
- 选中图层,键盘删除键可删除,同时也要删除画布中的组件
-
图层隐藏/可见功能
- 点击“眼睛”图标可隐藏该图层,再点击可再次显示
- 隐藏的图层,在画布中也不可见。预览、发布时,组件也要隐藏。
-
锁定
- 点击“锁”图标可锁定图层,再次点击可解锁。
- 锁定的图层,只能选中、复制,不能修改任何内容、属性,不能拖拽、修改大小。
- 即,在画布中不能操作,属性面板也不能操作。
-
图层重命名功能
- 双击图层,图层名称变为输入框,可修改图层名称
-
右键菜单
- 参考画布的右键菜单,相同
-
属性面板
- 背景属性:如果当前没有任何组件被选中,则属性面板显示“背景设置”,可设置:
- 背景颜色
- 背景图片
- 背景属性:如果当前没有任何组件被选中,则属性面板显示“背景设置”,可设置:
-
组件属性
- 当选中某个组件时,属性面板会自动切换到该组件的属性设置
- 而且,每种组件的属性都不一样,例如文本组件
- 每个组件的详细属性,还需在设计组件时定义
-
功能菜单功能
- 撤销/重做:对于画布操作的撤销和重做,常见功能,不再赘述
- 放大/缩小:放大缩小画布的比例
3 )业务组件库需求
- 编辑器 和 h5 页面其实整个就是一系列元素构成的,这些元素的自然应该抽象成组件
- 同时满足各个环境的使用,包含B端,C端(包含手机端)
- 业务组件库大多数都是展示型组件,其实就是把对应的 template 加上属性(大部分是 css 属性)展示出来
- 少有的组件会有一些行为,比如音频播放等,而且这些组件会在多个不同的端进行展示,所以业务组件库就是从简的原则
- 必须避免和编辑器编辑流程的耦合,难点在于这些组件属性在编辑器中的编辑
- 组件分类:基础组件 + 高级组件
3.1 )基础组件
- 组件:文本, 图片(用户主动上传的图片,支持 gif),形状
- 通用属性
- 尺寸:
- 长度 - 输入数字(同下面5项)
- 宽度
- 左边距
- 右边距
- 上边距
- 下边距
- 边框:
- 边框类型 - 无 | 实线 | 破折线 | 点状线 下拉菜单
- 边框颜色 - 颜色选择
- 边框宽度 - 滑动选择
- 边框圆角 - 滑动选择
- 阴影与透明度
- 透明度 - 滑动选择 100 - 0 倒排
- 阴影 - 滑动选择
- 位置
- X 坐标 - 输入数字
- Y 坐标 - 输入数字
- 事件功能
- 事件类型 - 无 | 跳转 URL 下拉菜单
- url 地址 - 输入框
- 尺寸:
- 特有属性
- 文本
- 文字内容 - 多行输入框
- 字号 - 输入数字
- 字体 - 宋体 | 黑体 | 楷体 | 仿宋 …下拉菜单
- 加粗 - 特殊 checkbox
- 斜体 - 同上
- 下划线 - 同上
- 行高 - slider
- 对齐 - 左 | 中 | 右 radio group
- 文字颜色 - 颜色选择
- 背景颜色 - 颜色选择
- 图片:上传图片 - 上传以及编辑控件
- 形状:背景颜色 - 颜色选择
- 文本
3.2 )高级组件
- 日期显示
- 特有属性
- 样式 - 下拉菜单 1 | 2
- 时间 - 默认为当前日期 日期选择器
- 字体颜色 - 颜色选择器
4 )管理后台需求
- 首页 dashboard: 统计全局使用信息,如:PV, UV, 模板总数,发布总数, 活跃用户,每月新增等关键数据
- 用户管理:用户列表,用户操作(CRUD, 账号禁用,冻结),用户搜索
- 作品管理:作品列表,作品操作(发布/下线),作品搜索
- 模板管理:模板列表,模板搜索,模板操作(排序,CRUD, 设置标签: NEW/HOT)
- 渠道管理:用于分享和数据统计时的渠道
- 用于单独进行渠道管理的功能
- 可以增删查改
- 数据管理:数据监控相关
复杂度分析
- 交互的复杂性
- 数据结构和状态的复杂性
- 多项目互相依赖的复杂性
- 针对不同项目(web 还是 library)怎样完成打包
- 性能优化: 大型项目的要点, 省的流量就是公司的真金白银
- 第三方库的调研,使用以及二次开发
制定标准流程
- 制定 git flow 流程
- 标准 lint 工具
- 单元测试
- 代码提交的 commit 信息
- PR review - 工程师之间互相交流和学习的重要步骤
- CI/CD - 持续集成和部署
核心技术架构
1 )项目拆分
- 基于上述分析,我们可以把项目拆分成不同的项目
1.1 前端-B端系统仓库
- 可以采用简单的SPA模型,基于 Vue 或 React
- 这里可以集成下面的编辑器项目,但是会成为一个巨石仓库
- 建议采用微前端的模式,集成下面的编辑器项目
1.2 前端-编辑器
- 用于实现复杂的编辑器项目
- 可以再上述B端中耦合,但推荐使用微前端拆分出来单独成一个项目
1.3 前端-组件库项目
- 复用于 B端,C端(包含移动端)
1.4 后端项目
- 基于 Restful API 提供接口服务
- 基于SSR 提供H5页面
2 )项目间的关系
3 ) 核心问题分析
3.1 编辑器细节问题
3.1.1页面的组成
- 可能存在背景的设定:由图片或者纯色组成
- 关于页面的元素
- 由各种不同的元素(组件)组成。在这里面有属性的配置
- 一部分属性界定它的位置(position)
- 一部分属性界定它的展示(looks),比如宽高,内容等
- 由各种不同的元素(组件)组成。在这里面有属性的配置
3.1.2 由此,我们可以设计相关JSON数据模型
{
"page": {
"title": "作品1",
"props":{
"backgroundImage":"",
"backgroundPostion": "",
"backgroundMusic":"2.mp3", // 可能有的网页背景音乐
"backgroundMusicAutoStart": "true" // 背景音乐是否可以自动播放
//...
},
}
// 该采用对象还是数组?
"components":[
{
//指代对应的组件类型-可以和公共组件库的组件命名对应
"name": "text",
//要有特殊的ID,因为每个组件都是独特的,需要使用ID筛选组件
"id":"1",
"props": {
//位置属性
"left": "10px", "top": "10px",
//展示属性
"text": "hello world", "fontSize": "16px"
},
},
{
"name": "image",
"id": "2",
"props": {
"left": "5px","top": "20px",
"src": "cdn.url", "width": "100px", "height": "100px"
},
},
{
"name":"date", // 日期组件
"props": {
"left": "5px", "top": "20px",
"date": "now", "width": "100px", "height": "100px", "style":1
}
}
]
}
3.1.3 数据的流转
- 向画布添加组件或者删除组件(向 components 数组添加或者删除特定的组件)
- 更新组件的某个属性 (找到对应的 component,然后更新它的 props)
- 渲染画布或者作品(循环保存的作品信息,使用每个组件特定的属性进行渲染)
3.2 业务组件库实现方案
设计原则
- 业务组件库大多数都是展示型组件,其实就是把对应的 template 加上属性(大部分是 css 属性)展示出来,会有少量行为,比如点击跳转等
- 而且这些组件会在多个不同的端进行展示,所以业务组件库就是从简的原则
- 必须避免和编辑器编辑流程的耦合
组件命名
- 使用一个字母(X)加组件的名称:比如 XText 或 x-text
- 这个 X 可以是你的域名,公司名,部门名等有意义的名称
属性设计
- 属性其实可以分为两大类
-
伪代码
// 方案一,将 css 作为一个统一的对象传入 <LText css={{color: '#fff' ...}} text="nihao" /> // 内部实现比较简单 <p style={props.css}></p> // 方案二,将 所有属性全部平铺传入 <LText :text="nihao" :color="#fff" ... /> // 内部实现会复杂一点 const styles = stylePick(props) <p style={styles}></p>
-
方案一内部实现简单,但是保存的时候要多一层结构
-
并且更新数据的时候要知道是样式还是其他属性
-
方案二 内部实现稍微复杂一点,但是保存简单,更新数据不需要在做辨别
-
这些组件目前有一些共有的属性,称之为公共属性
-
提到公共属性我们就要注意代码重用的问题
- 伪代码
// 比如 在 Xtext 和 XImage 中都点击跳转的功能,属于公共属性的行为 // 抽象出一些通用的函数,在组件中完成通用的功能 import useClick from 'useClick' useClick(props)
4 ) 技术方案设计注意事项
- 技术方案设计,为的就是寻找一个方向,论证:可行性、扩展性、复杂度高低。
- 不要一直沉浸在细节里,要站在上帝的视角来看问题