云之家表单数据解析与构建概述
云之家表单结构在推送数据和发起审批接口中是完全一致的,只是数据流向不同:
推送解析:widgetMap → 业务字段(读取数据)
发起审批:业务字段 → widgetMap(写入数据)
表单整体结构
{
"formInfo": {
"widgetMap": { / 主表单控件 / },
"detailMap": { / 明细表控件 / }
},
"basicInfo": { / 基本信息 / }
}
basicInfo 字段说明
字段 类型 说明
eventId String 推送事件ID,全局唯一
formInstId String 表单实例ID
flowInstId String 流程实例ID
formDefId String 表单模版ID
formCodeId String 表单模版codeId
dataType Integer 0=测试数据,1=正式数据
actionType String reach/agree/submit/delete/abandon/withdraw/disagree
title String 表单标题
eventTime Long 时间戳(毫秒)
主表单控件 (widgetMap)
widgetMap 是一个 Map,key 为控件的 codeId。
通用字段
每个控件都包含:
codeId:控件唯一标识
title:控件标题
type:控件类型
value:控件值
extendFieldMap:扩展配置
控件类型详解
详见 references/widget-types.md
type 说明 value类型 示例
textWidget 单行文本 String "一行文字"
textAreaWidget 多行文本 String "多行文字"
解析:直接读取 value
构建:直接设置 value
// 解析
String text = widget.getValue().toString();
// 构建
widget.setValue("文本内容");
type 说明 value类型
dateWidget 日期 Long (毫秒时间戳)
dateRangeWidget 日期区间 Long[] [开始,结束]
解析:时间戳转Date
构建:Date转时间戳
// 解析
Long timestamp = (Long) widget.getValue();
Date date = new Date(timestamp);
// 构建
widget.setValue(date.getTime());
type 说明 value类型
numberWidget 数字 String
moneyWidget 金额 String
arithmeticWidget 运算 String
注意:value 是字符串类型!
// 解析
BigDecimal amount = new BigDecimal(widget.getValue().toString());
// 构建
widget.setValue("100.50");
数据结构:
{
"type": "radioWidget",
"value": "AaBaCcDd", // 选中的key
"options": [
{
"key": "AaBaCcDd",
"value": "选项1",
"checked": true
},
{
"key": "EeFfGgHh",
"value": "选项2",
"checked": false
}
]
}
解析流程:value(key) → options匹配 → value(显示文本) → 字典匹配 → 业务值
构建流程:业务值 → 字典匹配 → 显示文本 → options匹配 → key → 设置value
数据结构:
{
"type": "checkboxWidget",
"value": ["AaBaCcDd", "EeFfGgHh"], // 选中的key数组
"options": [
{
"key": "AaBaCcDd",
"value": "选项1",
"checked": true
},
{
"key": "EeFfGgHh",
"value": "选项2",
"checked": true
}
]
}
解析:value 是 key 数组,遍历匹配
构建:设置 key 数组
- 人员选择控件 (personSelectWidget)
数据结构:
{
"type": "personSelectWidget",
"option": "single", // single或multi
"personInfo": [
{
"name": "张三",
"userId": "xxx",
"oid": "xxx",
"image": "头像URL"
}
],
"value": ["xxx"] // oid数组
}
解析:从 personInfo 获取详细信息
构建:设置 value 为 oid 数组,同时填充 personInfo
- 部门选择控件 (departmentSelectWidget)
数据结构:
{
"type": "departmentSelectWidget",
"option": "single",
"deptInfo": [
{
"name": "财务部",
"orgId": "xxx",
"longName": "公司/中心/部门"
}
],
"value": ["xxx"] // orgId数组
}
详见 references/file-widget.md
数据结构:
{
"type": "attachmentWidget",
"maximum": 200,
"value": [
{
"fileId": "69f06679d0c3b700014ec175",
"fileName": "document.pdf",
"fileSize": "482",
"fileExt": "pdf",
"fileType": "application/pdf"
}
]
}
{
"type": "imageWidget",
"maximum": 12,
"value": ["fileId1", "fileId2"]
}
注意:图片控件的 value 是文件ID数组。
{
"type": "relatedWidget",
"value": [
{
"flowInstId": "xxx",
"formInstId": "xxx",
"formDefId": "xxx",
"formCodeId": "xxx",
"title": "关联单据标题"
}
]
}
{
"type": "serialNumWidget",
"value": "1-20171023-002" // 系统自动生成
}
明细表控件 (detailMap)
详见 references/detail-widget.md
数据结构:
{
"Dd_0": {
"codeId": "Dd_0",
"title": "明细表名称",
"type": "detailedWidget",
"buttonName": "添加明细",
"widgetVos": { /
列定义 / },
"widgetValue": [ /
行数据 / ]
}
}
widgetVos (列定义)
定义明细表中每列的控件结构,与主表控件结构相同:
{
"Te_1": {
"codeId": "Te_1",
"type": "textWidget",
"title": "姓名"
}
}
widgetValue (行数据)
数组,每行是一个对象,key 为控件的 codeId:
[
{
"_id_": "1", // 行ID
"Te_1": "张三", // 文本值
"Ra_0": "AaBaCcDd", // 单选key
"Da_0": 1508688000000 // 日期时间戳
}
]
数据解析示例
解析推送数据
// 1. 解析主表
Map widgetMap = formInfo.getWidgetMap();
// 文本
String title = (String) widgetMap.get("_S_TITLE").getValue();
// 日期
Long timestamp = (Long) widgetMap.get("Da_0").getValue();
Date date = new Date(timestamp);
// 单选
WidgetInfo radio = widgetMap.get("Ra_0");
String key = (String) radio.getValue();
String label = getOptionLabel(radio.getOptions(), key);
// 人员
WidgetInfo person = widgetMap.get("Ps_0");
String name = person.getPersonInfo().get(0).getName();
// 2. 解析明细表
DetailWidget detail = detailMap.get("Dd_0");
Map widgetVos = detail.getWidgetVos();
// 列定义
List> rows = detail.getWidgetValue();
// 行数据
for (Map row : rows) {
String name = (String) row.get("Te_1");
String radioKey = (String) row.get("Ra_0");
// 从widgetVos获取options进行匹配
}
构建发起审批数据
// 1. 构建主表
Map widgetMap = new HashMap<>();
// 文本
widgetMap.put("_S_TITLE", createTextWidget("标题内容"));
// 日期
widgetMap.put("Da_0", createDateWidget(System.currentTimeMillis()));
// 单选
w...