低代碼平臺表單引擎與業務事件設計實踐
- 低代碼平臺表單引擎與業務事件設計實踐
- 一、什么是低代碼?它能做什么?
- 二、請假系統案例介紹
- 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 業務流程
- 員工發起請假申請,填寫表單。
- 系統根據申請人自動帶出一級審批人。
- 若請假天數>3天,自動增加二級、三級審批人。
- 審批人依次審批,全部通過后流程結束。
- 審批拒絕則流程回退,通知申請人。
三、表單元數據、實例數據與業務事件聯動設計
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
);
示例數據:
id | app_id | form_id | user_id | applicant | manager1 | manager2 | manager3 | reason | start_time | end_time | result1 | result2 | result3 | status | current_node | created_at | updated_at |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | app_001 | form_001 | u_001 | 張三 | 李四 | 王五 | 趙六 | 家中有事 | 2024-06-01 09:00:00 | 2024-06-03 18:00:00 | 同意 | 同意 | pending | manager1 | 2024-06-10 10:00:00 | 2024-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 字段會被自動賦值
五、架構設計總結
- 表單元數據:存儲表單結構、字段、字段事件,字段與事件通過 eventId 關聯,支持靈活擴展。
- 表單實例數據:采用寬表結構,每個字段單獨一列,便于查詢和統計。
- 業務事件:存儲事件觸發條件、動作、目標、策略、參數等,支持靈活配置和復用。
- 原子策略:每個業務事件由一個或多個原子策略組成,策略可擴展、可復用,解耦業務邏輯。
- 事件引擎:根據事件配置,動態組裝并執行策略鏈,實現“配置即邏輯”,大幅提升開發效率。
- 工廠+策略模式: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"}
}
八、結語
通過本案例,我們可以看到低代碼平臺在表單引擎、業務事件、原子策略等方面的強大能力。通過“元數據+事件+策略”驅動的架構,極大提升了業務靈活性和開發效率。未來,低代碼平臺將成為企業數字化轉型的重要基礎設施。