云之家表单通用解析规则

云之家(YunZhijia)表单数据解析与构建技能。用于解析云之家表单JSON结构,支持双向转换:推送数据解析和审批发起数据构建。触发场景:(1) 解析云之家审批推送数据 (2) 构建发起审批接口的表单数据 (3) 理解云之家表单widgetMap和detailMap结构 (4) 处理各类控件:文本、单选、多选、日期、人员、部门、明细表等。

Audits

Pass

Install

openclaw skills install yzj-form-parser

云之家表单数据解析与构建

概述

云之家表单结构在推送数据和发起审批接口中是完全一致的,只是数据流向不同:

  • 推送解析: widgetMap → 业务字段(读取数据)
  • 发起审批: 业务字段 → widgetMap(写入数据)

表单整体结构

{
  "formInfo": {
    "widgetMap": { /* 主表单控件 */ },
    "detailMap": { /* 明细表控件 */ }
  },
  "basicInfo": { /* 基本信息 */ }
}

basicInfo 字段说明

字段类型说明
eventIdString推送事件ID,全局唯一
formInstIdString表单实例ID
flowInstIdString流程实例ID
formDefIdString表单模版ID
formCodeIdString表单模版codeId
dataTypeInteger0=测试数据,1=正式数据
actionTypeStringreach/agree/submit/delete/abandon/withdraw/disagree
titleString表单标题
eventTimeLong时间戳(毫秒)

主表单控件 (widgetMap)

widgetMap 是一个 Map,key 为控件的 codeId

通用字段

每个控件都包含:

  • codeId: 控件唯一标识
  • title: 控件标题
  • type: 控件类型
  • value: 控件值
  • extendFieldMap: 扩展配置

控件类型详解

详见 references/widget-types.md

1. 文本控件

type说明value类型示例
textWidget单行文本String"一行文字"
textAreaWidget多行文本String"多行文字"

解析: 直接读取 value 构建: 直接设置 value

// 解析
String text = widget.getValue().toString();
// 构建
widget.setValue("文本内容");

2. 日期控件

type说明value类型
dateWidget日期Long (毫秒时间戳)
dateRangeWidget日期区间Long[] [开始,结束]

解析: 时间戳转Date 构建: Date转时间戳

// 解析
Long timestamp = (Long) widget.getValue();
Date date = new Date(timestamp);

// 构建
widget.setValue(date.getTime());

3. 数字/金额控件

type说明value类型
numberWidget数字String
moneyWidget金额String
arithmeticWidget运算String

注意: value 是字符串类型!

// 解析
BigDecimal amount = new BigDecimal(widget.getValue().toString());
// 构建
widget.setValue("100.50");

4. 单选控件 (radioWidget)

数据结构:

{
  "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

5. 多选控件 (checkboxWidget)

数据结构:

{
  "type": "checkboxWidget",
  "value": ["AaBaCcDd", "EeFfGgHh"],  // 选中的key数组
  "options": [
    { "key": "AaBaCcDd", "value": "选项1", "checked": true },
    { "key": "EeFfGgHh", "value": "选项2", "checked": true }
  ]
}

解析: value 是 key 数组,遍历匹配 构建: 设置 key 数组

6. 人员选择控件 (personSelectWidget)

数据结构:

{
  "type": "personSelectWidget",
  "option": "single",  // single或multi
  "personInfo": [
    {
      "name": "张三",
      "userId": "xxx",
      "oid": "xxx",
      "image": "头像URL"
    }
  ],
  "value": ["xxx"]  // oid数组
}

解析: 从 personInfo 获取详细信息 构建: 设置 value 为 oid 数组,同时填充 personInfo

7. 部门选择控件 (departmentSelectWidget)

数据结构:

{
  "type": "departmentSelectWidget",
  "option": "single",
  "deptInfo": [
    {
      "name": "财务部",
      "orgId": "xxx",
      "longName": "公司/中心/部门"
    }
  ],
  "value": ["xxx"]  // orgId数组
}

8. 附件控件 (attachmentWidget)

详见 references/file-widget.md

数据结构:

{
  "type": "attachmentWidget",
  "maximum": 200,
  "value": [
    {
      "fileId": "69f06679d0c3b700014ec175",
      "fileName": "document.pdf",
      "fileSize": "482",
      "fileExt": "pdf",
      "fileType": "application/pdf"
    }
  ]
}

9. 图片控件 (imageWidget)

{
  "type": "imageWidget",
  "maximum": 12,
  "value": ["fileId1", "fileId2"]
}

注意: 图片控件的 value 是文件ID数组。

10. 关联审批控件 (relatedWidget)

{
  "type": "relatedWidget",
  "value": [
    {
      "flowInstId": "xxx",
      "formInstId": "xxx",
      "formDefId": "xxx",
      "formCodeId": "xxx",
      "title": "关联单据标题"
    }
  ]
}

11. 流水号控件 (serialNumWidget)

{
  "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<String, WidgetInfo> 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<String, WidgetInfo> widgetVos = detail.getWidgetVos(); // 列定义
List<Map<String, Object>> rows = detail.getWidgetValue();  // 行数据

for (Map<String, Object> row : rows) {
    String name = (String) row.get("Te_1");
    String radioKey = (String) row.get("Ra_0");
    // 从widgetVos获取options进行匹配
}

构建发起审批数据

// 1. 构建主表
Map<String, Object> widgetMap = new HashMap<>();

// 文本
widgetMap.put("_S_TITLE", createTextWidget("标题内容"));

// 日期
widgetMap.put("Da_0", createDateWidget(System.currentTimeMillis()));

// 单选
widgetMap.put("Ra_0", createRadioWidget("AaBaCcDd", options));

// 人员
widgetMap.put("Ps_0", createPersonWidget(oid, name));

// 2. 构建明细表
List<Map<String, Object>> rows = new ArrayList<>();
for (Item item : items) {
    Map<String, Object> row = new HashMap<>();
    row.put("Te_1", item.getName());
    row.put("Ra_0", item.getRadioKey());
    rows.add(row);
}

注意事项

  1. 数字类型: numberWidgetmoneyWidget 的 value 是字符串
  2. 时间戳: 日期控件的 value 是毫秒级时间戳
  3. 选项key: 单选/多选的 value 是选项的 key,不是显示文本
  4. 明细表行ID: 每行有 _id_ 字段,构建时可不设置
  5. 数组类型: 多选、人员、部门、附件的 value 都是数组