当前位置: 首页 > news >正文

构建低代码平台的技术解析

低代码平台表单引擎与业务事件设计实践

  • 低代码平台表单引擎与业务事件设计实践
    • 一、什么是低代码?它能做什么?
    • 二、请假系统案例介绍
      • 2.1 主要功能
      • 2.2 业务流程
    • 三、表单元数据、实例数据与业务事件联动设计
      • 3.1 表单元数据(Meta)如何设计
      • 3.2 表单实例数据(Data)如何保存(宽表结构)
      • 3.3 业务事件与数据节点的联动
    • 四、业务事件与原子策略的实现(详细Java代码)
      • 4.1 业务事件类型举例
      • 4.2 详细Java实现
        • 4.2.1 事件上下文对象
        • 4.2.2 原子策略接口
        • 4.2.3 具体策略实现
        • 4.2.4 策略工厂
        • 4.2.5 事件配置对象
        • 4.2.6 事件引擎
        • 4.2.7 事件驱动示例
    • 五、架构设计总结
    • 六、常见业务事件场景举例
    • 七、数据结构建议(最终版)
      • 7.1 表单元数据(MongoDB)
      • 7.2 表单实例数据(MySQL,宽表结构)
      • 7.3 业务事件(MongoDB)
    • 八、结语

低代码平台表单引擎与业务事件设计实践

一、什么是低代码?它能做什么?

低代码(Low-Code)是一种通过可视化拖拽、配置和少量代码开发应用的方式。它极大地降低了开发门槛,让业务人员也能参与到应用搭建中。低代码平台通常具备以下能力:

  • 可视化表单设计:通过拖拽组件快速搭建业务表单。
  • 流程编排:配置化定义审批流、业务流转。
  • 业务规则配置:通过“事件-动作-条件”方式实现复杂业务逻辑。
  • 数据集成:对接外部系统、数据库,实现数据互通。
  • 快速上线与迭代:大幅缩短开发周期,支持敏捷变更。

低代码平台适用于OA审批、报销、请假、合同、CRM等大量表单驱动的业务场景。


二、请假系统案例介绍

为了更好地理解低代码平台的能力,我们以“请假申请系统”为例,介绍其功能和业务逻辑。

2.1 主要功能

  • 员工提交请假申请,填写请假人、请假时间、请假原因等信息。
  • 系统自动带出直属领导作为审批人。
  • 请假天数超过3天时,自动增加二级、三级审批人。
  • 审批人可在系统中审批,审批结果自动流转到下一级。
  • 审批通过/拒绝后,自动通知相关人员。

2.2 业务流程

  1. 员工发起请假申请,填写表单。
  2. 系统根据申请人自动带出一级审批人。
  3. 若请假天数>3天,自动增加二级、三级审批人。
  4. 审批人依次审批,全部通过后流程结束。
  5. 审批拒绝则流程回退,通知申请人。

三、表单元数据、实例数据与业务事件联动设计

3.1 表单元数据(Meta)如何设计

表单元数据描述了表单的结构、字段、字段属性和字段事件。每个字段可以挂载多个业务事件(如 onChange、onBlur、onSubmit 等),事件与字段通过 eventId 关联。

表单元数据(MongoDB示例):

{"_id": "form_001","appId": "app_001","name": "请假申请表","fields": [{"fieldId": "f1","name": "applicant","type": "input","label": "请假人","required": true,"events": [{"eventId": "event_001"}]},{"fieldId": "f2","name": "manager1","type": "input","label": "第一审批人","required": true},{"fieldId": "f3","name": "manager2","type": "input","label": "第二审批人","required": true},{"fieldId": "f4","name": "manager3","type": "input","label": "第三审批人","required": false},{"fieldId": "f5","name": "reason","type": "textarea","label": "请假原因","required": true},{"fieldId": "f6","name": "startTime","type": "datetime","label": "请假开始时间","required": true},{"fieldId": "f7","name": "endTime","type": "datetime","label": "请假结束时间","required": true},{"fieldId": "f8","name": "result1","type": "select","label": "第一审批结果","required": false},{"fieldId": "f9","name": "result2","type": "select","label": "第二审批结果","required": false},{"fieldId": "f10","name": "result3","type": "select","label": "第三审批结果","required": false}],"formEvents": [{"eventId": "event_002"}],"createdAt": "...","updatedAt": "..."
}

说明:

  • 每个字段可配置 events,events 里存 eventId,eventId 指向业务事件配置。
  • formEvents 是表单级别的事件(如提交时触发)。

3.2 表单实例数据(Data)如何保存(宽表结构)

表单实例数据采用宽表结构,每个字段单独一列,便于查询和统计。

MySQL表结构(宽表):

CREATE TABLE form_leave (id BIGINT PRIMARY KEY AUTO_INCREMENT,app_id VARCHAR(64),form_id VARCHAR(64),user_id VARCHAR(64),applicant VARCHAR(64),manager1 VARCHAR(64),manager2 VARCHAR(64),manager3 VARCHAR(64),reason VARCHAR(255),start_time DATETIME,end_time DATETIME,result1 VARCHAR(32),result2 VARCHAR(32),result3 VARCHAR(32),status VARCHAR(32),current_node VARCHAR(64),created_at DATETIME,updated_at DATETIME
);

示例数据:

idapp_idform_iduser_idapplicantmanager1manager2manager3reasonstart_timeend_timeresult1result2result3statuscurrent_nodecreated_atupdated_at
1app_001form_001u_001张三李四王五赵六家中有事2024-06-01 09:00:002024-06-03 18:00:00同意同意pendingmanager12024-06-10 10:00:002024-06-10 10:00:00

3.3 业务事件与数据节点的联动

业务事件是低代码平台的核心,描述了“何时触发、触发什么、如何处理”。

业务事件配置(MongoDB示例):

{"_id": "event_001","formId": "form_001","trigger": "onChange","sourceField": "applicant","action": "setValue","targetField": "manager1","strategy": "fromEmployeeTable","params": {"sourceField": "applicant","lookupTable": "employee","lookupField": "manager1"}
}

说明:

  • trigger:事件触发时机(如 onChange、onSubmit、onApprove 等)
  • sourceField:事件源字段
  • action:动作类型(如 setValue、validate、block、branch、aggregate 等)
  • targetField:目标字段
  • strategy:具体的原子策略(如 fromEmployeeTable、calculate、validateRule 等)
  • params:策略参数

字段与事件的联动:

  • 在表单元数据的字段 events 中,配置 eventId。
  • 前端监听字段变化,触发事件,后端根据 eventId 查找事件配置,执行对应策略。

四、业务事件与原子策略的实现(详细Java代码)

4.1 业务事件类型举例

  • 字段赋值(setValue):如 applicant 变更时自动填充 manager1/manager2
  • 字段校验(validate):如请假天数不能超过 10 天
  • 节点新增(addNode):如并签时动态增加审批节点
  • 节点聚合(aggregate):如并签节点全部通过后流转
  • 流程推进(advance):如审批通过后流转到下一个节点
  • 流程阻塞(block):如审批未通过阻塞流程
  • 分支判断(branch):如请假天数大于 3 天需三级审批
  • 消息通知(notify):如审批人收到待办通知
  • 数据计算(calculate):如自动计算请假天数
  • 回退(rollback):如审批拒绝回退到上一步

4.2 详细Java实现

4.2.1 事件上下文对象
public class EventContext {private Map<String, Object> fieldValues = new HashMap<>();private Map<String, Object> extra = new HashMap<>();public Object getFieldValue(String fieldName) {return fieldValues.get(fieldName);}public void setFieldValue(String fieldName, Object value) {fieldValues.put(fieldName, value);}public Map<String, Object> getAllFieldValues() {return fieldValues;}public void setExtra(String key, Object value) {extra.put(key, value);}public Object getExtra(String key) {return extra.get(key);}
}
4.2.2 原子策略接口
public interface AtomicStrategy {void execute(EventContext context, Map<String, Object> params);
}
4.2.3 具体策略实现
// 字段赋值策略:根据申请人自动带出直属领导
public class SetValueStrategy implements AtomicStrategy {@Overridepublic void execute(EventContext context, Map<String, Object> params) {String sourceField = (String) params.get("sourceField");String targetField = (String) params.get("targetField");String lookupTable = (String) params.get("lookupTable");String lookupField = (String) params.get("lookupField");String applicant = (String) context.getFieldValue(sourceField);// 假设EmployeeService.getManager(applicant)能查到直属领导String manager = EmployeeService.getManager(applicant);context.setFieldValue(targetField, manager);}
}// 字段校验策略:请假天数不能超过10天
public class ValidateStrategy implements AtomicStrategy {@Overridepublic void execute(EventContext context, Map<String, Object> params) {String startField = (String) params.get("startField");String endField = (String) params.get("endField");int maxDays = (int) params.getOrDefault("maxDays", 10);LocalDateTime start = (LocalDateTime) context.getFieldValue(startField);LocalDateTime end = (LocalDateTime) context.getFieldValue(endField);long days = Duration.between(start, end).toDays();if (days > maxDays) {throw new RuntimeException("请假天数不能超过" + maxDays + "天");}}
}// 分支判断策略:请假天数大于3天需三级审批
public class BranchStrategy implements AtomicStrategy {@Overridepublic void execute(EventContext context, Map<String, Object> params) {String startField = (String) params.get("startField");String endField = (String) params.get("endField");int threshold = (int) params.getOrDefault("threshold", 3);LocalDateTime start = (LocalDateTime) context.getFieldValue(startField);LocalDateTime end = (LocalDateTime) context.getFieldValue(endField);long days = Duration.between(start, end).toDays();if (days > threshold) {context.setFieldValue("needManager3", true);} else {context.setFieldValue("needManager3", false);}}
}// 消息通知策略
public class NotifyStrategy implements AtomicStrategy {@Overridepublic void execute(EventContext context, Map<String, Object> params) {String userField = (String) params.get("userField");String message = (String) params.get("message");String userId = (String) context.getFieldValue(userField);NotificationService.send(userId, message);}
}// 更多策略可按需扩展...
4.2.4 策略工厂
public class StrategyFactory {private static final Map<String, AtomicStrategy> STRATEGY_MAP = new HashMap<>();static {STRATEGY_MAP.put("setValue", new SetValueStrategy());STRATEGY_MAP.put("validate", new ValidateStrategy());STRATEGY_MAP.put("branch", new BranchStrategy());STRATEGY_MAP.put("notify", new NotifyStrategy());// ...注册其他策略}public static AtomicStrategy getStrategy(String strategyName) {return STRATEGY_MAP.get(strategyName);}
}
4.2.5 事件配置对象
public class EventConfig {private String strategy;private Map<String, Object> params;// ...getter/setter
}
4.2.6 事件引擎
public class EventEngine {public void handleEvent(EventConfig eventConfig, EventContext context) {String strategyName = eventConfig.getStrategy();Map<String, Object> params = eventConfig.getParams();AtomicStrategy strategy = StrategyFactory.getStrategy(strategyName);if (strategy != null) {strategy.execute(context, params);} else {throw new RuntimeException("未找到策略: " + strategyName);}}
}
4.2.7 事件驱动示例
// 假设前端触发 applicant 字段 onChange,后端收到事件
EventConfig eventConfig = eventConfigRepository.findById("event_001");
EventContext context = new EventContext();
context.setFieldValue("applicant", "张三");
EventEngine engine = new EventEngine();
engine.handleEvent(eventConfig, context);
// manager1 字段会被自动赋值

五、架构设计总结

  1. 表单元数据:存储表单结构、字段、字段事件,字段与事件通过 eventId 关联,支持灵活扩展。
  2. 表单实例数据:采用宽表结构,每个字段单独一列,便于查询和统计。
  3. 业务事件:存储事件触发条件、动作、目标、策略、参数等,支持灵活配置和复用。
  4. 原子策略:每个业务事件由一个或多个原子策略组成,策略可扩展、可复用,解耦业务逻辑。
  5. 事件引擎:根据事件配置,动态组装并执行策略链,实现“配置即逻辑”,大幅提升开发效率。
  6. 工厂+策略模式:Java 端通过工厂+策略模式实现原子策略的注册与调用,保证系统高扩展性和解耦性。

六、常见业务事件场景举例

  • 字段变更自动赋值
  • 字段变更自动校验
  • 字段变更动态显示/隐藏其他字段
  • 审批节点并签/或签
  • 审批节点动态新增/聚合
  • 审批拒绝回退
  • 流程自动推进
  • 消息/通知推送
  • 数据自动计算
  • 数据自动填充(如带出员工信息)

七、数据结构建议(最终版)

7.1 表单元数据(MongoDB)

{"_id": "form_001","appId": "app_001","name": "请假申请表","fields": [{"fieldId": "f1","name": "applicant","type": "input","label": "请假人","required": true,"events": [{"eventId": "event_001"}]},{"fieldId": "f2","name": "manager1","type": "input","label": "第一审批人","required": true},{"fieldId": "f3","name": "manager2","type": "input","label": "第二审批人","required": true},{"fieldId": "f4","name": "manager3","type": "input","label": "第三审批人","required": false},{"fieldId": "f5","name": "reason","type": "textarea","label": "请假原因","required": true},{"fieldId": "f6","name": "startTime","type": "datetime","label": "请假开始时间","required": true},{"fieldId": "f7","name": "endTime","type": "datetime","label": "请假结束时间","required": true},{"fieldId": "f8","name": "result1","type": "select","label": "第一审批结果","required": false},{"fieldId": "f9","name": "result2","type": "select","label": "第二审批结果","required": false},{"fieldId": "f10","name": "result3","type": "select","label": "第三审批结果","required": false}],"formEvents": [{"eventId": "event_002"}],"createdAt": "...","updatedAt": "..."
}

7.2 表单实例数据(MySQL,宽表结构)

CREATE TABLE form_leave (id BIGINT PRIMARY KEY AUTO_INCREMENT,app_id VARCHAR(64),form_id VARCHAR(64),user_id VARCHAR(64),applicant VARCHAR(64),manager1 VARCHAR(64),manager2 VARCHAR(64),manager3 VARCHAR(64),reason VARCHAR(255),start_time DATETIME,end_time DATETIME,result1 VARCHAR(32),result2 VARCHAR(32),result3 VARCHAR(32),status VARCHAR(32),current_node VARCHAR(64),created_at DATETIME,updated_at DATETIME
);

7.3 业务事件(MongoDB)

{"_id": "event_001","formId": "form_001","trigger": "onChange","sourceField": "applicant","action": "setValue","targetField": "manager1","strategy": "fromEmployeeTable","params": {"sourceField": "applicant","lookupTable": "employee","lookupField": "manager1"}
}

八、结语

通过本案例,我们可以看到低代码平台在表单引擎、业务事件、原子策略等方面的强大能力。通过“元数据+事件+策略”驱动的架构,极大提升了业务灵活性和开发效率。未来,低代码平台将成为企业数字化转型的重要基础设施。


相关文章:

  • 龙蜥OS搭建Technitium DNS全指南
  • git的使用——初步认识git和基础操作
  • 计算机视觉课程总结
  • python实现将COQE数据转换成字符串的格式
  • ollama在win10中使用
  • 前端面试专栏-主流框架:10. React状态管理方案(Redux、Mobx、Zustand)
  • 错误监控----比如实现sentry一些思路
  • web和uniapp接入腾讯云直播
  • 腾讯云TCCA认证考试报名 - TDSQL数据库交付运维工程师(MySQL版)
  • Matlab学习笔记
  • 解决idea无法正常加载lombok包
  • CTF解题:[NSSCTF 2022 Spring Recruit]弱类型比较绕过
  • TikTok 矩阵如何快速涨粉
  • MySQL存储引擎深度解析:InnoDB、MyISAM、MEMORY 与 ARCHIVE 的全面对比与选型建议
  • YOLOv11改进系列---Conv篇---2024最新深度可分卷积与多尺度卷积结合的模块MSCB助力yolov11有效涨点
  • 微信中 qrcode 生成二维码长按无效果的解决方案
  • python函数(II)
  • Jira 需求处理全流程解析:从入门到实践
  • google ADK Agent间传参数
  • 利用cpolar实现Talebook数字图书馆的实时访问
  • 怎么创建网页的快捷方式/天津seo网站推广
  • 网站建设与网站制作/济南特大最新消息
  • dede 百度网站地图/品牌宣传策划方案
  • 合肥专业网站排名推广/b站视频推广网站2023年
  • 湖南网站建设欧黎明/win7优化工具哪个好用
  • wordpress主题pacify/seo方案