weaver-e10-builder 1.1.3 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/commands/check.d.ts.map +1 -1
  2. package/dist/commands/check.js +48 -15
  3. package/dist/commands/check.js.map +1 -1
  4. package/dist/commands/designer-common.d.ts +56 -0
  5. package/dist/commands/designer-common.d.ts.map +1 -0
  6. package/dist/commands/designer-common.js +165 -0
  7. package/dist/commands/designer-common.js.map +1 -0
  8. package/dist/commands/designer-setters.d.ts +13 -0
  9. package/dist/commands/designer-setters.d.ts.map +1 -0
  10. package/dist/commands/designer-setters.js +593 -0
  11. package/dist/commands/designer-setters.js.map +1 -0
  12. package/dist/commands/designer.d.ts +17 -0
  13. package/dist/commands/designer.d.ts.map +1 -0
  14. package/dist/commands/designer.js +448 -0
  15. package/dist/commands/designer.js.map +1 -0
  16. package/dist/commands/form-add-detail-table.d.ts.map +1 -1
  17. package/dist/commands/form-add-detail-table.js +59 -0
  18. package/dist/commands/form-add-detail-table.js.map +1 -1
  19. package/dist/commands/form-association.d.ts.map +1 -1
  20. package/dist/commands/form-association.js +3 -2
  21. package/dist/commands/form-association.js.map +1 -1
  22. package/dist/commands/form-button.d.ts.map +1 -1
  23. package/dist/commands/form-button.js +86 -1
  24. package/dist/commands/form-button.js.map +1 -1
  25. package/dist/commands/form-data.d.ts.map +1 -1
  26. package/dist/commands/form-data.js +13 -1
  27. package/dist/commands/form-data.js.map +1 -1
  28. package/dist/commands/form-ebuilder-scope.js +3 -3
  29. package/dist/commands/form-ebuilder-scope.js.map +1 -1
  30. package/dist/commands/form-formula.js +4 -4
  31. package/dist/commands/form-formula.js.map +1 -1
  32. package/dist/commands/form-list-click.d.ts.map +1 -1
  33. package/dist/commands/form-list-click.js +30 -2
  34. package/dist/commands/form-list-click.js.map +1 -1
  35. package/dist/commands/form-list-filter.js +1 -1
  36. package/dist/commands/form-list-filter.js.map +1 -1
  37. package/dist/commands/form-list-hierarchy.d.ts +3 -0
  38. package/dist/commands/form-list-hierarchy.d.ts.map +1 -0
  39. package/dist/commands/form-list-hierarchy.js +133 -0
  40. package/dist/commands/form-list-hierarchy.js.map +1 -0
  41. package/dist/commands/form-list-permission.d.ts.map +1 -1
  42. package/dist/commands/form-list-permission.js +17 -3
  43. package/dist/commands/form-list-permission.js.map +1 -1
  44. package/dist/commands/form-list.d.ts.map +1 -1
  45. package/dist/commands/form-list.js +2 -0
  46. package/dist/commands/form-list.js.map +1 -1
  47. package/dist/commands/form-nlist.d.ts.map +1 -1
  48. package/dist/commands/form-nlist.js +47 -15
  49. package/dist/commands/form-nlist.js.map +1 -1
  50. package/dist/commands/form-option-template.d.ts +3 -0
  51. package/dist/commands/form-option-template.d.ts.map +1 -0
  52. package/dist/commands/form-option-template.js +291 -0
  53. package/dist/commands/form-option-template.js.map +1 -0
  54. package/dist/commands/form-permission.d.ts.map +1 -1
  55. package/dist/commands/form-permission.js +214 -2
  56. package/dist/commands/form-permission.js.map +1 -1
  57. package/dist/commands/form-view.d.ts.map +1 -1
  58. package/dist/commands/form-view.js +23 -1
  59. package/dist/commands/form-view.js.map +1 -1
  60. package/dist/commands/form.d.ts.map +1 -1
  61. package/dist/commands/form.js +259 -59
  62. package/dist/commands/form.js.map +1 -1
  63. package/dist/commands/icon.d.ts.map +1 -1
  64. package/dist/commands/icon.js +9 -13
  65. package/dist/commands/icon.js.map +1 -1
  66. package/dist/commands/menu-permission.d.ts.map +1 -1
  67. package/dist/commands/menu-permission.js +19 -12
  68. package/dist/commands/menu-permission.js.map +1 -1
  69. package/dist/commands/page.d.ts +14 -0
  70. package/dist/commands/page.d.ts.map +1 -0
  71. package/dist/commands/page.js +175 -0
  72. package/dist/commands/page.js.map +1 -0
  73. package/dist/commands/wf-form.js +1 -1
  74. package/dist/commands/wf-form.js.map +1 -1
  75. package/dist/commands/workflow-condition.js +9 -8
  76. package/dist/commands/workflow-condition.js.map +1 -1
  77. package/dist/commands/workflow-node-overtime.d.ts.map +1 -1
  78. package/dist/commands/workflow-node-overtime.js +16 -8
  79. package/dist/commands/workflow-node-overtime.js.map +1 -1
  80. package/dist/commands/workflow-node.d.ts.map +1 -1
  81. package/dist/commands/workflow-node.js +35 -5
  82. package/dist/commands/workflow-node.js.map +1 -1
  83. package/dist/commands/workflow-numbering.d.ts.map +1 -1
  84. package/dist/commands/workflow-numbering.js +63 -30
  85. package/dist/commands/workflow-numbering.js.map +1 -1
  86. package/dist/commands/workflow-operator-sign.d.ts.map +1 -1
  87. package/dist/commands/workflow-operator-sign.js +2 -1
  88. package/dist/commands/workflow-operator-sign.js.map +1 -1
  89. package/dist/commands/workflow.d.ts.map +1 -1
  90. package/dist/commands/workflow.js +78 -38
  91. package/dist/commands/workflow.js.map +1 -1
  92. package/dist/core/client.d.ts +9 -0
  93. package/dist/core/client.d.ts.map +1 -1
  94. package/dist/core/client.js +16 -1
  95. package/dist/core/client.js.map +1 -1
  96. package/dist/index.js +6 -0
  97. package/dist/index.js.map +1 -1
  98. package/dist/services/actionflow/preflight_service.d.ts.map +1 -1
  99. package/dist/services/actionflow/preflight_service.js +40 -17
  100. package/dist/services/actionflow/preflight_service.js.map +1 -1
  101. package/dist/services/actionflow/workflow_compiler.d.ts.map +1 -1
  102. package/dist/services/actionflow/workflow_compiler.js +4 -2
  103. package/dist/services/actionflow/workflow_compiler.js.map +1 -1
  104. package/dist/services/form-button-action.d.ts +17 -0
  105. package/dist/services/form-button-action.d.ts.map +1 -0
  106. package/dist/services/form-button-action.js +111 -0
  107. package/dist/services/form-button-action.js.map +1 -0
  108. package/dist/services/form-create.d.ts +15 -1
  109. package/dist/services/form-create.d.ts.map +1 -1
  110. package/dist/services/form-create.js +40 -5
  111. package/dist/services/form-create.js.map +1 -1
  112. package/dist/services/form-list-stats.d.ts.map +1 -1
  113. package/dist/services/form-list-stats.js +29 -6
  114. package/dist/services/form-list-stats.js.map +1 -1
  115. package/dist/services/form-nlist.d.ts +8 -2
  116. package/dist/services/form-nlist.d.ts.map +1 -1
  117. package/dist/services/form-nlist.js +32 -7
  118. package/dist/services/form-nlist.js.map +1 -1
  119. package/dist/services/form-sub-detail.d.ts +36 -0
  120. package/dist/services/form-sub-detail.d.ts.map +1 -0
  121. package/dist/services/form-sub-detail.js +132 -0
  122. package/dist/services/form-sub-detail.js.map +1 -0
  123. package/dist/services/form-view.d.ts +6 -0
  124. package/dist/services/form-view.d.ts.map +1 -1
  125. package/dist/services/form-view.js +24 -0
  126. package/dist/services/form-view.js.map +1 -1
  127. package/dist/services/workflow-operator.d.ts +9 -0
  128. package/dist/services/workflow-operator.d.ts.map +1 -1
  129. package/dist/services/workflow-operator.js +33 -0
  130. package/dist/services/workflow-operator.js.map +1 -1
  131. package/package.json +1 -1
  132. package/skill-docs/SKILL.md +27 -45
  133. package/skill-docs/assets/factory/chart-dimensions.json +536 -0
  134. package/skill-docs/assets/factory/example-btn-progress-collapse-configured.json +2515 -0
  135. package/skill-docs/assets/factory/example-configured-2.json +13805 -0
  136. package/skill-docs/assets/factory/example-configured.json +6735 -0
  137. package/skill-docs/assets/factory/factory-bar-stack.json +326 -0
  138. package/skill-docs/assets/factory/factory-bar.json +222 -0
  139. package/skill-docs/assets/factory/factory-bubble.json +322 -0
  140. package/skill-docs/assets/factory/factory-calendar.json +325 -0
  141. package/skill-docs/assets/factory/factory-circular.json +320 -0
  142. package/skill-docs/assets/factory/factory-collapse-panel.json +132 -0
  143. package/skill-docs/assets/factory/factory-comment.json +388 -0
  144. package/skill-docs/assets/factory/factory-count-down.json +198 -0
  145. package/skill-docs/assets/factory/factory-digital-panel.json +108 -0
  146. package/skill-docs/assets/factory/factory-eb-button.json +150 -0
  147. package/skill-docs/assets/factory/factory-fast-create.json +62 -0
  148. package/skill-docs/assets/factory/factory-gauge.json +312 -0
  149. package/skill-docs/assets/factory/factory-h-bar-stack.json +328 -0
  150. package/skill-docs/assets/factory/factory-h-bar.json +326 -0
  151. package/skill-docs/assets/factory/factory-line.json +212 -0
  152. package/skill-docs/assets/factory/factory-nav-bar.json +167 -0
  153. package/skill-docs/assets/factory/factory-nav-menu.json +144 -0
  154. package/skill-docs/assets/factory/factory-nav-panel.json +338 -0
  155. package/skill-docs/assets/factory/factory-new-tab.json +163 -0
  156. package/skill-docs/assets/factory/factory-nightingale.json +312 -0
  157. package/skill-docs/assets/factory/factory-nlist.json +112 -0
  158. package/skill-docs/assets/factory/factory-page-header.json +171 -0
  159. package/skill-docs/assets/factory/factory-picture.json +169 -0
  160. package/skill-docs/assets/factory/factory-pie.json +212 -0
  161. package/skill-docs/assets/factory/factory-progress-chart.json +162 -0
  162. package/skill-docs/assets/factory/factory-search-global.json +104 -0
  163. package/skill-docs/assets/factory/factory-slide.json +164 -0
  164. package/skill-docs/assets/factory/factory-treemap.json +322 -0
  165. package/skill-docs/assets/icons.db +0 -0
  166. package/skill-docs/references/coding/guide-page-code.md +21 -1
  167. package/skill-docs/references/coding/ref-compile-rules.md +24 -0
  168. package/skill-docs/references/common/guide-plan-template.md +219 -201
  169. package/skill-docs/references/common/ref-cli-commands.md +366 -320
  170. package/skill-docs/references/ebuilder-designer/guide-designer-components.md +110 -0
  171. package/skill-docs/references/ebuilder-designer/guide-designer-factory.md +460 -0
  172. package/skill-docs/references/ebuilder-designer/guide-designer-version.md +111 -0
  173. package/skill-docs/references/ebuilder-designer/guide-designer.md +287 -0
  174. package/skill-docs/references/form/guide-create-form.md +464 -409
  175. package/skill-docs/references/form/guide-form-button.md +82 -54
  176. package/skill-docs/references/form/guide-form-view.md +299 -284
  177. package/skill-docs/references/workflow/guide-workflow.md +59 -0
@@ -1,409 +1,464 @@
1
- # 新建 Ebuilder 表单
2
-
3
- 通过 `e10-cli form create` 创建表单。
4
-
5
- 建表自带默认台账;方案要求同一表单的普通列表时,查询 `form list-view <objId> <appId>` 并复用,名称略有差异也不另建。默认保留名称,记录实际 listId,详见[视图指南](guide-form-view.md)。
6
-
7
- > **重要**:字段定义一次性写全(含选项、默认值等)。不要先建空表再逐个 `add-field` —— add-field 只用于罕见补救。
8
-
9
- ## 基本用法
10
-
11
- ```bash
12
- e10-cli form create {应用ID} "表单名" --fields @fields.json
13
- # 默认不加菜单;要入口传 --menu(台账菜单 VIEWPORT,指向数据列表页)。漏加可用 `e10-cli menu add-table <appId> <objId>` 补
14
- ```
15
-
16
- 不传 `--fields` 时使用默认字段:名称(Text)、数量(Number)、日期(Date)、状态(Select)。
17
-
18
- ### 布局类型(流式/表格式)
19
-
20
- ```bash
21
- e10-cli form create {应用ID} "表单名" --fields @fields.json --layout FLOW # 流式
22
- e10-cli form create {应用ID} "表单名" --fields @fields.json --layout EXCEL # 表格(缺省)
23
- ```
24
-
25
- | 要点 | 说明 |
26
- |------|------|
27
- | **布局类型建表时定死** | 平台建表后不可切换(流式↔表格式),只能创建时选。`--layout` 写在建表请求里(`layoutType` + `isAdvance:false`) |
28
- | **流式模板** | FLOW 用特殊模板 `820000000000000001`(非通用版本 id,跨环境一致);CLI 自动配 |
29
- | 缺省 | 不传 `--layout` 时缺省 `EXCEL`(表格,行为不变) |
30
-
31
- ## 自定义字段
32
-
33
- ```bash
34
- e10-cli form create {应用ID} "表单名" --fields @fields.json
35
- ```
36
-
37
- 字段 JSON 格式(保存在 `fields.json` 中):
38
-
39
- ```json
40
- [
41
- {"componentKey": "Text", "fieldName": "客户名称"},
42
- {"componentKey": "Phone", "fieldName": "联系电话"},
43
- {"componentKey": "Mobile", "fieldName": "手机号码"},
44
- {"componentKey": "IDCard", "fieldName": "身份证号"},
45
- {"componentKey": "Employee", "fieldName": "负责人"},
46
- {"componentKey": "Department", "fieldName": "所属部门"},
47
- {"componentKey": "Date", "fieldName": "签订日期"},
48
- {"componentKey": "Money", "fieldName": "合同金额"},
49
- {"componentKey": "Select", "fieldName": "客户等级", "fieldOptions": [{"name":"A级"},{"name":"B级"}]}
50
- ]
51
- ```
52
-
53
- > **明细表(DetailTable)放最下面**:主表字段在前、明细表放数组末尾。布局/铺列按数组顺序处理,明细在前会打乱主表字段排布。
54
- > ```json
55
- > [
56
- > {"componentKey":"Text","fieldName":"合同名称"},
57
- > {"componentKey":"Money","fieldName":"合同金额"},
58
- > {"componentKey":"DetailTable","fieldName":"付款明细","formFields":[
59
- > {"componentKey":"Text","fieldName":"付款条件"},
60
- > {"componentKey":"Number","fieldName":"付款金额","precision":2}
61
- > ]}
62
- > ]
63
- > ```
64
-
65
- > **`valueKey` 可选**:Select/RadioBox/CheckBox 的 `fieldOptions` 只需写 `name`,`valueKey` 由 CLI 自动生成。也可以手动指定短码如 `"valueKey":"a"`。
66
-
67
- **字段读写属性**:`required` 必填 / `readOnly` 只读 / `hidden` 隐藏(字段不展示但保留参与计算,如运算/派生字段):
68
- ```json
69
- {"componentKey":"Number","fieldName":"请假时长(小时)","readOnly":true,"hidden":true},
70
- {"componentKey":"FileComponent","fieldName":"证明材料","required":true}
71
- ```
72
- > `hidden:true` → 布局属性"显示"取消(show:false);`readOnly` → 布局"禁止手工编辑";`required` → 布局"必填"。这些是**布局属性**(优先级:字段在布局中的设置 > 字段管理中字段设置 > 模块默认),建表时一次配好,勿依赖平台默认值。
73
-
74
- **独占一行**:字段写 `"singleRow":true` → 该字段整行显示(对齐平台布局 singleRow 属性),其余字段仍两列:
75
- ```json
76
- {"componentKey":"Text","fieldName":"项目名称","singleRow":true},
77
- {"componentKey":"TextArea","fieldName":"项目描述","singleRow":true},
78
- {"componentKey":"Text","fieldName":"负责人"}
79
- ```
80
- > 不加 `singleRow` 的普通字段两列排布。明细表 / 落单字段(奇数最后一个)本来就独占一行。add-field 加字段可用 `--single-row`。
81
- >
82
- > **规划阶段就该判断,勿默认全两列**:长文本/备注/项目描述/地址/富文本/长说明 → 默认 `singleRow:true`(两列挤一起难看);标题类(项目名称、合同名称)也常独占。AI 常漏标 singleRow,建表前过一遍字段语义。
83
-
84
- **字段分组**(按表单结构判断,**勿默认全平铺**):6+ 字段、或字段有明显逻辑分段(基本信息/合同信息/系统设置/付款信息…)→ 按 `group` 名分组,建表时自动生成折叠容器,字段收进对应分组。用户没明确要求时,按字段语义自然分组(别每张表都加,也别 3 字段小表加)。建表时 fields.json 一并写 `group`,勿留到建后用 `form group` 补(那是对齐补救手段)。
85
- ```json
86
- [
87
- {"componentKey":"Text","fieldName":"客户名称","group":"基本信息"},
88
- {"componentKey":"Phone","fieldName":"联系电话","group":"基本信息"},
89
- {"componentKey":"Select","fieldName":"客户状态","group":"基本信息","fieldOptions":[{"name":"潜在"},{"name":"正式"}]},
90
- {"componentKey":"Date","fieldName":"签订日期"},
91
- {"componentKey":"TextArea","fieldName":"备注"}
92
- ]
93
- ```
94
- > 不写 `group` 的字段归「未分组」平铺在分组之后。分组内字段**默认两列**(一行两个),要独占一行写 `"singleRow":true`。明细表不参与分组(独立区块)。EXCEL/FLOW 布局都按 singleRow 控制两列/整行(对齐浏览器 initLayout payload)。
95
-
96
-
97
- **Number/Money 精度**:用 `precision` 指定小数位数(缺省 Number=0 整数、Money=2):
98
- ```json
99
- {"componentKey":"Number","fieldName":"单价","precision":2},
100
- {"componentKey":"Money","fieldName":"金额"}
101
- ```
102
- > 不设 precision 时 Number 建出来是整数(pointSize=0)、Money 是 2 位小数。主表/明细子字段都支持。
103
- > **Number 与 Money 是两种类型**:Number=纯数字(默认无千分位/大写),Money=金额(千分位默认开)。字段名叫"金额"不代表必须用 Money 类型——类型由方案数据语义定,名称只是展示文本。
104
-
105
- **Number/Money 千分位与大写**(按需开启,**由字段类型决定默认,与字段名无关**):
106
- `"delimiter":true` 开千分位(**Number 默认关、Money 默认开**,`"delimiter":false` 关 Money 的);`"capital":true` 开大写金额显示(`isCapital` + `capitalFormat onlyUpperCase`):
107
- ```json
108
- {"componentKey":"Number","fieldName":"费用金额","precision":2},
109
- {"componentKey":"Money","fieldName":"费用金额"}
110
- ```
111
- > - **类型决定默认,不是字段名**:上面两个字段**同名**"费用金额",但前者是 Number(千分位/大写关)、后者是 Money(千分位默认开)。判断看 `componentKey`,不看字段名。
112
- > - **千分位/大写是 opt-in**:只在方案文档**明确要求**"显示千分位/金额大写"时才加 `delimiter`/`capital`,不要因字段名含"金额/费用/收款"就自动套用。
113
- > - **Number 类型的金额语义字段缺省就是裸数字**:`{"componentKey":"Number","fieldName":"项目费用","precision":2}` —— 不带 delimiter/capital,这是正确写法。
114
- > - add-field 用 `--delimiter` / `--no-delimiter` / `--capital`。
115
-
116
- **Number 百分比显示**:`"percent":true` → `numberType=percentage`(缺省 pointSize=1,可再配 `precision`):
117
- ```json
118
- {"componentKey":"Number","fieldName":"付款比例","percent":true,"precision":1}
119
- ```
120
- > ⚠️ **百分比字段的公式要 ×100**:平台百分比字段是「数值直接拼 %」(不自动 ×100)。如 付款比例=付款金额/项目金额,10000/20000=0.5,会显示「**0.5%**」而非 50%。公式必须 ×100:
121
- > ```json
122
- > {"componentKey":"Number","fieldName":"付款比例","percent":true,"precision":1,"formula":"{付款信息.付款金额}/{主表.项目金额}*100"}
123
- > ```
124
- > 这样 0.5×100=50 → 显示「50%」。累加校验「比例累加=100%」也基于百分比数(50+50=100),不是比值。
125
-
126
- **Number/Money 默认值**:`"defaultValue":1000` → 存 `content` + `isDefault:true`(如 工时单价默认 1000 元):
127
- ```json
128
- {"componentKey":"Number","fieldName":"工时单价","defaultValue":1000}
129
- ```
130
- > 平台机制:设默认值必须连 `isDelimiter/stepMode/step/isCapital` 一起发,否则默认值不落库(CLI 已处理)。
131
- > 单位没有独立字段属性 —— 显示单位直接写在字段名里,如 `"fieldName":"工时数量(天)"`。
132
- > **台账列单位显示**(绕法):平台字段无单位属性,但台账列可配显示后缀,用 `form list-unit <objId> <appId> <listId> <fieldId> "(元)"` 设置(走列表列配置 `showTrans.ruleConfig.suffix`,极简结构平台即接受)。
133
-
134
- ## 支持的字段类型
135
-
136
- | componentKey | 说明 |
137
- |---|---|
138
- | Text | 文本 |
139
- | TextArea | 多行文本 |
140
- | Email | 邮箱 |
141
- | Phone | 电话 |
142
- | Mobile | 手机 |
143
- | IDCard | 身份证号 |
144
- | Number | 数字(千分位/大写默认关,按需开;precision 缺省 0 整数) |
145
- | Money | 金额(千分位默认开,大写按需开;precision 缺省 2) |
146
- | Date | 日期(默认精度**年月日**,format `yyyy-MM-dd`;要带时间用 `"format"` 覆盖) |
147
- | DateTime | 日期-时间(`Date` 的别名,默认带 时:分,format `yyyy-MM-dd HH:mm` 不含秒) |
148
- | Employee | 人员选择 |
149
- | Department | 部门选择 |
150
- | FileComponent | 附件上传(**注意是 FileComponent 不是 File**) |
151
- | Select | 下拉选择 |
152
- | RadioBox | 单选按钮 |
153
- | CheckBox | 多选按钮 |
154
- | EInvoice | 电子发票(创建后无需额外配置,平台自动处理) |
155
- | AudioRecord | 语音(极简字段,无特殊配置。注意不是 FileComponent 附件) |
156
- | VideoRecord | 视频(极简字段,无特殊配置) |
157
- | DetailTable | 明细表 |
158
- | DateRange | 日期区间 |
159
- | Time | 时间 |
160
- | EBuilder | 关联 EB 表单(见下节) |
161
- | Flow | **浏览-流程**(关联流程,如"数据来源"来自项目立项流程;`--sform-id` 为目标流程绑定的表单 objId,点击自动跳流程)。**form create 的 fields.json 直接写 `"sformId":"<流程表单objId>"` 即可**(建表后 CLI 自动绑 sformId/relateExt,与 EBuilder 同机制);add-field 用 `--sform-id`。⚠ sformId 必须是**流程绑定的表单 objId**(不是 workflowId),即"仅允许关联某流程"=Flow 字段 + sformId 指向该流程的表单 |
162
-
163
- 正常情况下,人相关的 都是用Employee
164
- Time 的格式固定为 HH:mm:ss 如 17:00:00
165
- > **人员/部门默认值**:默认**不配默认值**(没写就没有)。要默认当前用户/部门写 `"defaultValue": true`(建表时自动配 `defaultExtend`)。
166
- > **Date/DateTime 精度与默认值**:默认**不填默认值**。要带时间用 `"format"` 覆盖精度(如 `"format":"yyyy-MM-dd HH:mm"`、`yyyy-MM-dd HH:mm:ss`);要配动态当天默认值写 `"defaultValue": true`(建表时自动配 `defaultExtend`)。add-field 加字段用 `--format` 覆盖精度。
167
- > ```json
168
- > {"componentKey":"Date","fieldName":"签订日期"},
169
- > {"componentKey":"Date","fieldName":"精确到秒","format":"yyyy-MM-dd HH:mm:ss"},
170
- > {"componentKey":"Date","fieldName":"默认今天","defaultValue":true}
171
- > ```
172
- >
173
- > **日期限制**:A 字段**最早不得早于** B 字段写 `"minField":"B字段名"`,**最晚不得晚于**写 `"maxField":"B字段名"`(对齐平台 `min/max.dateField`,自动解析 B 的 fieldId)。**子表字段同样支持**,可指向主表字段或同子表字段。add-field 用 `--min-field` / `--max-field`。
174
- > ```json
175
- > {"componentKey":"Date","fieldName":"计划开始日期"},
176
- > {"componentKey":"Date","fieldName":"计划结束日期","minField":"计划开始日期"},
177
- > {"componentKey":"Date","fieldName":"完成日期","maxField":"计划结束日期"},
178
- > {"componentKey":"DetailTable","fieldName":"行程明细","formFields":[
179
- > {"componentKey":"Date","fieldName":"明细开始日期","minField":"计划开始日期"},
180
- > {"componentKey":"Date","fieldName":"明细结束日期","minField":"明细开始日期"}
181
- > ]}
182
- > ```
183
-
184
- **多选**:人员(Employee)/部门(Department)/关联ebuilder(EBuilder)/浏览(Browser)/下拉(Select) 默认单选,要选多个加 `"multiple": true`:
185
- ```json
186
- {"componentKey":"Employee","fieldName":"参与人员","multiple":true},
187
- {"componentKey":"Department","fieldName":"会签部门","multiple":true},
188
- {"componentKey":"EBuilder","fieldName":"关联客户","sformId":"<目标表单objId>","dataTitle":"name","multiple":true},
189
- {"componentKey":"Select","fieldName":"标签","multiple":true,"fieldOptions":[{"name":"A"},{"name":"B"}]}
190
- ```
191
- > 不写 `multiple` 即单选。多选 EBuilder 选中多条记录,字段存数组值。**下拉 Select 多选 = 独立类型 `SelectMultiple`**(CLI 自动转,非 Select+开关)。
192
-
193
- **文本最大长度**:Text 缺省 100、TextArea 缺省 4000,用 `"maxLen"` 覆盖(主表 + 明细子字段都支持):
194
- ```json
195
- {"componentKey":"Text","fieldName":"备注","maxLen":500},
196
- {"componentKey":"TextArea","fieldName":"详情","maxLen":8000}
197
- ```
198
- > add-field 用 `--max-len <n>`。
199
-
200
- ## EBuilder 关联字段
201
-
202
- 关联其他表单记录(下拉选择/搜索),选中后展示目标表单的某个字段值。
203
-
204
- ```json
205
- {
206
- "componentKey": "EBuilder",
207
- "fieldName": "关联客户",
208
- "sformId": "1296220571782152199",
209
- "dataTitle": "客户名称"
210
- }
211
- ```
212
-
213
- | 字段 | 必填 | 说明 |
214
- |------|------|------|
215
- | `sformId` | 是 | **目标表单的 objId**(不是 appId/formId) |
216
- | `dataTitle` | 是 | 目标表单中用于显示的字段名,选中记录后展示该字段值。传 `"name"`(或不写)默认取目标表**字段名含"名称"**的字段(如 客户名称/类型名称),无则取第一个业务字段 |
217
- | `displayColumns` | 否 | **关联浏览弹窗显示列**(字段名列表)。缺省自动用目标表业务字段**最多 5 个**(去系统字段),建好即生效;要指定用这个 |
218
-
219
- > **关联浏览弹窗显示列默认自动配好**:`form create` 建表和 `form add-field` 加 EBuilder 字段时都自动写入 `ffDisplayColumns` = 目标表**业务字段前 5 个**(排除创建者/创建时间/数据ID等系统字段),浏览弹窗直接生效。`fields.json` 里显式写 `displayColumns` 指定列不受 5 个限制。事后想改可用 `e10-cli form ebuilder-columns <objId> <appId> <fieldId> <列...>` 或 `--clear` 清空。
220
-
221
- ### EBuilder + 值带出(relateFrom)
222
-
223
- 选关联记录后自动带出其他字段值(如选客户→带出联系人/地址):
224
-
225
- ```json
226
- {
227
- "componentKey": "Text",
228
- "fieldName": "联系人",
229
- "relateFrom": { "ebuilderField": "关联客户", "sourceFieldId": "1296220571782152194" }
230
- }
231
- ```
232
-
233
- - `ebuilderField`:本表单中的 EBuilder 字段名
234
- - `sourceFieldId`:目标表单中要复制值的字段 **fieldId(数字 ID)**。⚠️ **不能传字段名**,用 `form read --app-id` 获取
235
-
236
- 创建后补配值带出:`e10-cli form edit-field ... --relate-from <EBuilder字段名> --relate-from-source <源字段fieldId>`
237
- > ⚠️ `--relate-from-source` 必须传字段的**数字 fieldId**,不能传字段名。
238
-
239
- ## Select/RadioBox/CheckBox 带选项
240
-
241
- ```json
242
- {
243
- "componentKey": "Select",
244
- "fieldName": "客户等级",
245
- "fieldOptions": [
246
- {"name": "A级"},
247
- {"name": "B级"},
248
- {"name": "C级"}
249
- ]
250
- }
251
- ```
252
-
253
- ## 明细表 DetailTable
254
-
255
- 明细表包含嵌套子字段,子字段写在其 `formFields` 数组内:
256
-
257
- ```json
258
- {
259
- "componentKey": "DetailTable",
260
- "fieldName": "订单明细",
261
- "formFields": [
262
- {"componentKey": "Text", "fieldName": "商品名称"},
263
- {"componentKey": "Number", "fieldName": "数量"},
264
- {"componentKey": "Number", "fieldName": "单价"},
265
- {"componentKey": "Date", "fieldName": "交付日期"}
266
- ]
267
- }
268
- ```
269
-
270
- 子字段也支持带选项的类型。
271
-
272
- ## 复杂编号(年份编号):serial-mark
273
-
274
- 编号(如 `XM-2026-001`、`YF-2026-0001`)走**复杂编号**机制:在任意文本字段上配编码段,`form serial-mark set --segments` 用 JSON 数组组合任意规则,**数组顺序即编号拼接顺序**,一条命令配完(含代字),重跑全量替换不累积。
275
-
276
- ### 配置:`set --segments`
277
-
278
- ```bash
279
- e10-cli form serial-mark set <objId> <appId> <字段ID> --segments @segments.json
280
- # 也支持内联 JSON:--segments '[{"type":"fixed","value":"XM-"},{"type":"serial","digits":4}]'
281
- ```
282
-
283
- segments.json 示例(生成如 `YF-2026-0001`,按年单独流水):
284
- ```json
285
- [
286
- {"type":"field","fieldId":"<选择框字段ID>","shortName":{"研发":"YF","实施":"SS","运维":"YW","咨询":"ZX"}},
287
- {"type":"fixed","value":"-"},
288
- {"type":"year","format":"four","alone":true},
289
- {"type":"serial","digits":4,"zero":true}
290
- ]
291
- ```
292
-
293
- ### 段类型参考(任意组合,数组顺序决定拼接顺序)
294
-
295
- | type | 含义 | 属性 | 平台 markFieldType |
296
- |------|------|------|-------------------|
297
- | `fixed` | 固定内容 | `value`(文本,如 `"XM-"`/`"-"`) | FIX_CONTEXT |
298
- | `year` | 年份 | `format`:`four`(四位 2026,缺省)/`two`(两位 26);`alone`:true 按年单独流水(缺省 true) | DATE_YEAR |
299
- | `serial` | 流水号 | `digits`(位数,如 4→0001);`zero`:true 补零(缺省)/false 不补零;`alone`:true 机构单独流水 | SERIAL_NUMBER |
300
- | `field` | 表单字段值 | `fieldId`(取值字段);`alone`:true 机构单独流水;`shortName`:inline 代字映射(选项名→简称,见下) | FORM_FIELD |
301
- | `system` | 系统字段 | `systemField`:`creator`(创建人)/`creator-dept`(创建人所属部门,自动部门代字);`alone` | SYSTEM_FIELD |
302
- | `date` | 日期 | `format`:`yyyy`/`yyyyMM`/`yyyyMMdd`;`source`:`current`(当前)/`<字段ID>`;`alone` | DATE |
303
-
304
- > - **任意规则直接组合**:把规则拆成段,按拼接顺序写入数组即可。如 `项目类型-年份-4位流水` = field + fixed("-") + year + serial
305
- > - **代字自动**:field 段 markExtend=103(选项值取简称)、system creator-dept markExtend=101(部门取代字),无需手填
306
- > - **inline 代字**:field 段带 `shortName` 自动配置代字映射,无需再跑 short-name
307
- > - **按年单独流水**:year 段 `alone:true`(DATE_YEAR seqAlone,流水号每年重新计数)
308
- > - **全量替换**:重跑时旧段进 delDefIds 清除,markDefId 复用,绑定/代字不丢失
309
- > - 段对象来自 `getMarkFieldAddData` 预生成;markDefId 来自 `saveSingleMarkDef`;已有绑定时复用持久化 markDef(getMarkContext 优先用绑定记录的 targetId)
310
-
311
- ### 增量调整(可选)
312
-
313
- `set` 是全量重建;需在已有编号上追加/微调单段用 `add-segment`,单独查/改代字用 `short-name`:
314
-
315
- ```bash
316
- e10-cli form serial-mark add-segment <objId> <appId> <绑定字段ID> --type field --field-id <取值字段ID> [--position 0]
317
- e10-cli form serial-mark add-segment <objId> <appId> <绑定字段ID> --type system --system-field creator-dept
318
- e10-cli form serial-mark short-name list <objId> <appId> <选择框字段ID>
319
- e10-cli form serial-mark short-name set <objId> <appId> <选择框字段ID> --map '{"研发":"YF","实施":"SS"}'
320
- ```
321
- add-segment 段类型与 set 一致(fixed/year/serial/field/system/date),`--position` 插入位置(缺省追加末尾)。
322
-
323
- ### 查询与解除
324
-
325
- ```bash
326
- e10-cli form serial-mark read <objId> <appId> # 查看编号配置(绑定字段+组成段+代字)
327
- e10-cli form serial-mark fields <objId> <appId> # 查可作为编号目标的字段
328
- e10-cli form serial-mark clear <objId> <appId> <字段ID> # 解除编号绑定
329
- ```
330
-
331
- **注意**:
332
- - 被编码字段平台自动设为只读(编号自动生成,不可手工改)
333
- - 流水号按 `前缀+年份+流水` 组合查重累进
334
- - 机制:markField 复杂编号(getEbMarkTargetId → getMarkSetForm → saveSingleMarkDef → saveOrUpdate → saveMarkField);段对象必须来自 getMarkFieldAddData 预生成;已有绑定时复用持久化 markDef,段/代字不丢失
335
-
336
- ## 日期区间 DateRange
337
-
338
- 日期区间字段**必须**指定精度格式,通过 `format` 配置:
339
-
340
- ```json
341
- {
342
- "componentKey": "DateRange",
343
- "fieldName": "出差时间",
344
- "format": "yyyy-MM-dd HH:mm"
345
- }
346
- ```
347
-
348
- | 字段 | 必填 | 说明 |
349
- |------|------|------|
350
- | `format` | 否 | 区间精度。缺省 `yyyy-MM-dd`(年-月-日);到分钟写 `yyyy-MM-dd HH:mm`;到秒 `yyyy-MM-dd HH:mm:ss` |
351
- | `startPlaceholder` / `endPlaceholder` | 否 | 开始/结束控件占位符。缺省按 format 自动生成中文(如 `年-月-日 时:分`) |
352
-
353
- > **CLI 自动展开**:创建时无需手写 `start`/`end`/`rangeInterval`——CLI 会把该字段展开为平台要求的 3 字段结构(主字段 + 「(开始时间)」「(结束时间)」两个 DateComponent,各带独立 fieldId),这是之前报 `DateIntervalFieldDto.getEnd()==null` 的根因(缺了 end 组件)。
354
- >
355
- > **事后补加**:`e10-cli form add-field <objId> <appId> "回程时间" DateRange --format "yyyy-MM-dd HH:mm"`
356
-
357
- ## 字段公式(fields.json 的 formula 属性)
358
-
359
- 创建表单时直接给字段绑定计算公式,CLI 自动完成「创建公式 + 绑定字段」两步(字段配置会带上 `ffExpress`):
360
-
361
- ```json
362
- {
363
- "componentKey": "Number",
364
- "fieldName": "出差天数",
365
- "formula": "DAYS({主表.出差时间(开始时间)},{主表.出差时间(结束时间)})"
366
- }
367
- ```
368
-
369
- 或对象形式指定返回类型:
370
-
371
- ```json
372
- "formula": { "expression": "DAYS({主表.出差时间(开始时间)},{主表.出差时间(结束时间)})", "returnType": "Number" }
373
- ```
374
-
375
- | 要点 | 说明 |
376
- |------|------|
377
- | 表达式语法 | 与 `form formula set --expression` 一致,用 `{主表.字段名}` 引用主表字段、`{明细表名.字段名}` 引用**明细表**字段(如 `DAYS({行程明细.行程开始时间},{行程明细.行程结束时间})`)。**fields.json create 与 formula set 两条路径都支持明细引用** |
378
- | **明细列求和** | **`SUM({明细表名.字段})`** 可对明细表某列跨行求和(如 `SUM({付款信息.付款金额})`),生效。可配合 `workflow node validate` 做"明细累加=主表字段"校验 |
379
- | **日期差** | 两个日期相减**不直接支持**,要用平台函数 **`DAYS({主表.开始},{主表.结束})`** |
380
- | 返回类型 | 缺省 `Number`;文本/日期类用对象形式指定 |
381
- | 事后补加 | `e10-cli form formula set <objId> <appId> --expression "..." --target <fieldId>` |
382
-
383
- > **明细表子字段选项**:`DetailTable` 的 `formFields` 里的 `Select/RadioBox/CheckBox` 也支持 `fieldOptions`,CLI 会自动给子字段配置选项(创建时无需额外操作)。
384
-
385
- ## 完整示例
386
-
387
- ```bash
388
- e10-cli form create 1283840156707348480 "采购合同" --fields @fields.json
389
- ```
390
-
391
- `fields.json` 内容:
392
-
393
- ```json
394
- [
395
- {"componentKey":"Text","fieldName":"合同编号"},
396
- {"componentKey":"Text","fieldName":"供应商名称"},
397
- {"componentKey":"Employee","fieldName":"采购负责人"},
398
- {"componentKey":"Date","fieldName":"签订日期"},
399
- {"componentKey":"Money","fieldName":"总金额"},
400
- {"componentKey":"Select","fieldName":"合同状态","fieldOptions":[{"name":"待审批"},{"name":"已审批"},{"name":"已完成"}]},
401
- {"componentKey":"DetailTable","fieldName":"采购明细","formFields":[{"componentKey":"Text","fieldName":"物品名称"},{"componentKey":"Number","fieldName":"数量"},{"componentKey":"Number","fieldName":"单价"}]}
402
- ]
403
- ```
404
-
405
- ## 创建成功后
406
-
407
- - 返回表单 ID
408
- - 用 `e10-cli form read <objId> --app-id <appId> --out fields.json` 导出字段信息(机器可读 JSON)
409
- - 在代码中通过 `formApi.js` 读写该表单数据
1
+ # 新建 Ebuilder 表单
2
+
3
+ 通过 `e10-cli form create` 创建表单。
4
+
5
+ 建表自带默认台账;方案要求同一表单的普通列表时,查询 `form list-view <objId> <appId>` 并复用,名称略有差异也不另建。默认保留名称,记录实际 listId,详见[视图指南](guide-form-view.md)。
6
+
7
+ > **重要**:字段定义一次性写全(含选项、默认值等)。不要先建空表再逐个 `add-field` —— add-field 只用于罕见补救。
8
+
9
+ ## 基本用法
10
+
11
+ ```bash
12
+ e10-cli form create {应用ID} "表单名" --fields @fields.json
13
+ # 默认不加菜单;要入口传 --menu(台账菜单 VIEWPORT,指向数据列表页)。漏加可用 `e10-cli menu add-table <appId> <objId>` 补
14
+ ```
15
+
16
+ 不传 `--fields` 时使用默认字段:名称(Text)、数量(Number)、日期(Date)、状态(Select)。
17
+
18
+ ### 布局类型(流式/表格式)
19
+
20
+ ```bash
21
+ e10-cli form create {应用ID} "表单名" --fields @fields.json --layout FLOW # 流式
22
+ e10-cli form create {应用ID} "表单名" --fields @fields.json --layout EXCEL # 表格(缺省)
23
+ ```
24
+
25
+ | 要点 | 说明 |
26
+ |------|------|
27
+ | **布局类型建表时定死** | 平台建表后不可切换(流式↔表格式),只能创建时选。`--layout` 写在建表请求里(`layoutType` + `isAdvance:false`) |
28
+ | **流式模板** | FLOW 用特殊模板 `820000000000000001`(非通用版本 id,跨环境一致);CLI 自动配 |
29
+ | 缺省 | 不传 `--layout` 时缺省 `EXCEL`(表格,行为不变) |
30
+
31
+ > **⚠ 建表前必须和用户确认布局类型**:表单要**流式(FLOW)** 还是**表格式(EXCEL)**——平台建表后不可切换,只能创建时定死。需求文档/截图没明确表态时,不要默认 EXCEL 直接建,先向用户问清。流程表单同理(`workflow create-workflow --layout FLOW|EXCEL`)。
32
+
33
+ ### 从需求文档识别完整布局样表
34
+
35
+ 识别发生在读取需求文档之后、编写 `plan.md` 之前。先完成字段定义识别,再扫描布局章节;不要等到创建表单时才回头猜布局。
36
+
37
+ 出现下列任一特征时,将表格作为“布局样表”候选,而不是普通字段清单:
38
+
39
+ - 上下文出现“表格式布局”“Excel样式”“按照如下布局构建”等说明;
40
+ - 单元格包含 `[字段名]`,或呈现“标签|字段|标签|字段”的交替结构;
41
+ - 存在独占行的表单标题、分组标题、有意义的空白单元格或同一行多个字段;
42
+ - 表格描述字段摆放位置,而不是“字段名称/字段类型/字段说明”的重复记录。
43
+
44
+ 逐行识别单元格角色:表单标题、分组标题、字段标签、字段控件、空白占位。字段控件后的必填、只读、金额大写等归字段显示属性;条件式必填/隐藏归显隐联动;字段比较归校验;公式归字段公式。空白单元格和同排关系属于布局信息,不能丢弃。
45
+
46
+ 优先读取 `e10-cli docx read` 生成的 Markdown 表格。只有 Markdown 不能确定合并单元格或跨列范围时,才查看原 DOCX 对应页面或表格结构;不能确定时在 plan 标“待确认”,不得自行猜测。
47
+
48
+ 识别结果必须双份落入 plan:
49
+
50
+ 1. “字段定义”保存字段类型和可直接创建的字段属性;
51
+ 2. 紧随其后的“表单布局蓝图”逐行保存标题、分组、字段同排关系、顺序、空白占位、跨列信息及原文说明。
52
+
53
+ `group`、`singleRow` 和字段数组顺序只是字段级布局提示,不能替代完整布局蓝图。生成 plan 后做一次轻量核对:原样表每个 `[字段]` 均同时出现在字段定义和布局蓝图中,且同排关系、分组顺序和原文属性没有遗漏。
54
+
55
+ “表单布局蓝图”只负责完整保存需求并指导后续执行,不作为单独的人工审核项,也不增加额外确认步骤。CLI 不直接消费该表格,也不需要额外生成 `.layout-plans/*.layout.json`。进入执行阶段后,根据蓝图把字段顺序、`group`、`singleRow`、`required`、`readOnly` 等可创建信息写入 `fields.json`,使用 `form create --fields @fields.json --layout EXCEL` 一次创建并初始化;公式、联动和校验仍走各自命令。创建结果与蓝图有局部位置差异时,再按实际布局使用 `form layout read/move/set-read-only/set-required` 等现有能力处理,不预设固定转换文件,也不修改已经可用的 EXCEL 初始化逻辑。
56
+
57
+ ## 自定义字段
58
+
59
+ ```bash
60
+ e10-cli form create {应用ID} "表单名" --fields @fields.json
61
+ ```
62
+
63
+ 字段 JSON 格式(保存在 `fields.json` 中):
64
+
65
+ ```json
66
+ [
67
+ {"componentKey": "Text", "fieldName": "客户名称"},
68
+ {"componentKey": "Phone", "fieldName": "联系电话"},
69
+ {"componentKey": "Mobile", "fieldName": "手机号码"},
70
+ {"componentKey": "IDCard", "fieldName": "身份证号"},
71
+ {"componentKey": "Employee", "fieldName": "负责人"},
72
+ {"componentKey": "Department", "fieldName": "所属部门"},
73
+ {"componentKey": "Date", "fieldName": "签订日期"},
74
+ {"componentKey": "Money", "fieldName": "合同金额"},
75
+ {"componentKey": "Select", "fieldName": "客户等级", "fieldOptions": [{"name":"A级"},{"name":"B级"}]}
76
+ ]
77
+ ```
78
+
79
+ > **明细表(DetailTable)放最下面**:主表字段在前、明细表放数组末尾。布局/铺列按数组顺序处理,明细在前会打乱主表字段排布。
80
+ > ```json
81
+ > [
82
+ > {"componentKey":"Text","fieldName":"合同名称"},
83
+ > {"componentKey":"Money","fieldName":"合同金额"},
84
+ > {"componentKey":"DetailTable","fieldName":"付款明细","formFields":[
85
+ > {"componentKey":"Text","fieldName":"付款条件"},
86
+ > {"componentKey":"Number","fieldName":"付款金额","precision":2}
87
+ > ]}
88
+ > ]
89
+ > ```
90
+
91
+ > **`valueKey` 可选但必须是数字**:Select/RadioBox/CheckBox 的 `fieldOptions` 只需写 `name`,`valueKey` 由 CLI 自动生成(雪花号)。也可手动指定**数字** valueKey(如 `"valueKey":"100"`,推荐用业务语义编码,数据记录与下游引用存的就是它);**非数字会被 CLI 直接报错拒绝**(平台规范+下游条件/公式按数字处理)。
92
+
93
+ **选项预设模板**(Select 专有):多个表单共用一套下拉选项时,用 `optionTemplate` 引用模板而不是内联 `fieldOptions`。模板先建(`e10-cli form option-template create <名称> --options @<json>`),fields.json 里写名称(或模板 ID):
94
+
95
+ ```json
96
+ {"componentKey":"Select","fieldName":"优先级","optionTemplate":"优先级模板"}
97
+ ```
98
+
99
+ - 选项不落字段上(`options:[]`),平台渲染时按模板拉取;**模板改选项,所有引用字段跟着变**
100
+ - 与 `fieldOptions` 互斥:同字段两个都写时 `optionTemplate` 被忽略(模板引用只在无内联选项时绑定)
101
+ - 数据记录存模板选项的 valueKey(`fieldOptionId`),与内联选项一致;`form data add` 直接填选项名或 valueKey
102
+ - 模板管理:`list`(`--system` 看内置)/ `read` / `copy` / `delete`;已有字段补绑用 `form add-field` 加不了——对已有 Select 改绑模板需在字段管理页面操作
103
+
104
+ **字段读写属性**:`required` 必填 / `readOnly` 只读 / `hidden` 隐藏(字段不展示但保留参与计算,如运算/派生字段):
105
+ ```json
106
+ {"componentKey":"Number","fieldName":"请假时长(小时)","readOnly":true,"hidden":true},
107
+ {"componentKey":"FileComponent","fieldName":"证明材料","required":true}
108
+ ```
109
+ > `hidden:true` → 布局属性"显示"取消(show:false);`readOnly` → 布局"禁止手工编辑";`required` → 布局"必填"。这些是**布局属性**(优先级:字段在布局中的设置 > 字段管理中字段设置 > 模块默认),建表时一次配好,勿依赖平台默认值。
110
+
111
+ **独占一行**:字段写 `"singleRow":true` → 该字段整行显示(对齐平台布局 singleRow 属性),其余字段仍两列:
112
+ ```json
113
+ {"componentKey":"Text","fieldName":"项目名称","singleRow":true},
114
+ {"componentKey":"TextArea","fieldName":"项目描述","singleRow":true},
115
+ {"componentKey":"Text","fieldName":"负责人"}
116
+ ```
117
+ > 不加 `singleRow` 的普通字段两列排布。明细表 / 落单字段(奇数最后一个)本来就独占一行。add-field 加字段可用 `--single-row`。
118
+ >
119
+ > **规划阶段就该判断,勿默认全两列**:长文本/备注/项目描述/地址/富文本/长说明 → 默认 `singleRow:true`(两列挤一起难看);标题类(项目名称、合同名称)也常独占。AI 常漏标 singleRow,建表前过一遍字段语义。
120
+
121
+ **字段分组**(按表单结构判断,**勿默认全平铺**):6+ 字段、或字段有明显逻辑分段(基本信息/合同信息/系统设置/付款信息…)→ 按 `group` 名分组,建表时自动生成折叠容器,字段收进对应分组。用户没明确要求时,按字段语义自然分组(别每张表都加,也别 3 字段小表加)。建表时 fields.json 一并写 `group`,勿留到建后用 `form group` 补(那是对齐补救手段)。
122
+ ```json
123
+ [
124
+ {"componentKey":"Text","fieldName":"客户名称","group":"基本信息"},
125
+ {"componentKey":"Phone","fieldName":"联系电话","group":"基本信息"},
126
+ {"componentKey":"Select","fieldName":"客户状态","group":"基本信息","fieldOptions":[{"name":"潜在"},{"name":"正式"}]},
127
+ {"componentKey":"Date","fieldName":"签订日期"},
128
+ {"componentKey":"TextArea","fieldName":"备注"}
129
+ ]
130
+ ```
131
+ > 不写 `group` 的字段归「未分组」平铺在分组之后。分组内字段**默认两列**(一行两个),要独占一行写 `"singleRow":true`。明细表不参与分组(独立区块)。EXCEL/FLOW 布局都按 singleRow 控制两列/整行(对齐浏览器 initLayout payload)。
132
+
133
+
134
+ **Number/Money 精度**:用 `precision` 指定小数位数(缺省 Number=0 整数、Money=2):
135
+ ```json
136
+ {"componentKey":"Number","fieldName":"单价","precision":2},
137
+ {"componentKey":"Money","fieldName":"金额"}
138
+ ```
139
+ > 不设 precision 时 Number 建出来是整数(pointSize=0)、Money 是 2 位小数。主表/明细子字段都支持。
140
+ > **Number 与 Money 是两种类型**:Number=纯数字(默认无千分位/大写),Money=金额(千分位默认开)。字段名叫"金额"不代表必须用 Money 类型——类型由方案数据语义定,名称只是展示文本。
141
+
142
+ **Number/Money 千分位与大写**(按需开启,**由字段类型决定默认,与字段名无关**):
143
+ `"delimiter":true` 开千分位(**Number 默认关、Money 默认开**,`"delimiter":false` 关 Money 的);`"capital":true` 开大写金额显示(`isCapital` + `capitalFormat onlyUpperCase`):
144
+ ```json
145
+ {"componentKey":"Number","fieldName":"费用金额","precision":2},
146
+ {"componentKey":"Money","fieldName":"费用金额"}
147
+ ```
148
+ > - **类型决定默认,不是字段名**:上面两个字段**同名**"费用金额",但前者是 Number(千分位/大写关)、后者是 Money(千分位默认开)。判断看 `componentKey`,不看字段名。
149
+ > - **千分位/大写是 opt-in**:只在方案文档**明确要求**"显示千分位/金额大写"时才加 `delimiter`/`capital`,不要因字段名含"金额/费用/收款"就自动套用。
150
+ > - **Number 类型的金额语义字段缺省就是裸数字**:`{"componentKey":"Number","fieldName":"项目费用","precision":2}` —— 不带 delimiter/capital,这是正确写法。
151
+ > - add-field 用 `--delimiter` / `--no-delimiter` / `--capital`。
152
+
153
+ **Number 百分比显示**:`"percent":true` → `numberType=percentage`(缺省 pointSize=1,可再配 `precision`):
154
+ ```json
155
+ {"componentKey":"Number","fieldName":"付款比例","percent":true,"precision":1}
156
+ ```
157
+ > ⚠️ **百分比字段的公式要 ×100**:平台百分比字段是「数值直接拼 %」(不自动 ×100)。如 付款比例=付款金额/项目金额,10000/20000=0.5,会显示「**0.5%**」而非 50%。公式必须 ×100:
158
+ > ```json
159
+ > {"componentKey":"Number","fieldName":"付款比例","percent":true,"precision":1,"formula":"{付款信息.付款金额}/{主表.项目金额}*100"}
160
+ > ```
161
+ > 这样 0.5×100=50 → 显示「50%」。累加校验「比例累加=100%」也基于百分比数(50+50=100),不是比值。
162
+
163
+ **Number/Money 默认值**:`"defaultValue":1000` → 存 `content` + `isDefault:true`(如 工时单价默认 1000 元):
164
+ ```json
165
+ {"componentKey":"Number","fieldName":"工时单价","defaultValue":1000}
166
+ ```
167
+ > 平台机制:设默认值必须连 `isDelimiter/stepMode/step/isCapital` 一起发,否则默认值不落库(CLI 已处理)。
168
+ > 单位没有独立字段属性 —— 显示单位直接写在字段名里,如 `"fieldName":"工时数量(天)"`。
169
+ > **台账列单位显示**(绕法):平台字段无单位属性,但台账列可配显示后缀,用 `form list-unit <objId> <appId> <listId> <fieldId> "(元)"` 设置(走列表列配置 `showTrans.ruleConfig.suffix`,极简结构平台即接受)。
170
+
171
+ ## 支持的字段类型
172
+
173
+ | componentKey | 说明 |
174
+ |---|---|
175
+ | Text | 文本 |
176
+ | TextArea | 多行文本 |
177
+ | Email | 邮箱 |
178
+ | Phone | 电话 |
179
+ | Mobile | 手机 |
180
+ | IDCard | 身份证号 |
181
+ | Number | 数字(千分位/大写默认关,按需开;precision 缺省 0 整数) |
182
+ | Money | 金额(千分位默认开,大写按需开;precision 缺省 2) |
183
+ | Date | 日期(默认精度**年月日**,format `yyyy-MM-dd`;要带时间用 `"format"` 覆盖) |
184
+ | DateTime | 日期-时间(`Date` 的别名,默认带 时:分,format `yyyy-MM-dd HH:mm` 不含秒) |
185
+ | Employee | 人员选择 |
186
+ | Department | 部门选择 |
187
+ | FileComponent | 附件上传(**注意是 FileComponent 不是 File**) |
188
+ | Select | 下拉选择 |
189
+ | RadioBox | 单选按钮 |
190
+ | CheckBox | 多选按钮 |
191
+ | EInvoice | 电子发票(创建后无需额外配置,平台自动处理) |
192
+ | AudioRecord | 语音(极简字段,无特殊配置。注意不是 FileComponent 附件) |
193
+ | VideoRecord | 视频(极简字段,无特殊配置) |
194
+ | DetailTable | 明细表 |
195
+ | DateRange | 日期区间 |
196
+ | Time | 时间 |
197
+ | EBuilder | 关联 EB 表单(见下节) |
198
+ | Flow | **浏览-流程**(关联流程,如"数据来源"来自项目立项流程;`--sform-id` 为目标流程绑定的表单 objId,点击自动跳流程)。**form create 的 fields.json 直接写 `"sformId":"<流程表单objId>"` 即可**(建表后 CLI 自动绑 sformId/relateExt,与 EBuilder 同机制);add-field 用 `--sform-id`。⚠ sformId 必须是**流程绑定的表单 objId**(不是 workflowId),即"仅允许关联某流程"=Flow 字段 + sformId 指向该流程的表单 |
199
+
200
+ 正常情况下,人相关的 都是用Employee
201
+ Time 的格式固定为 HH:mm:ss 如 17:00:00
202
+ > **人员/部门默认值**:默认**不配默认值**(没写就没有)。要默认当前用户/部门写 `"defaultValue": true`(建表时自动配 `defaultExtend`)。
203
+ > **Date/DateTime 精度与默认值**:默认**不填默认值**。要带时间用 `"format"` 覆盖精度(如 `"format":"yyyy-MM-dd HH:mm"`、`yyyy-MM-dd HH:mm:ss`);要配动态当天默认值写 `"defaultValue": true`(建表时自动配 `defaultExtend`)。add-field 加字段用 `--format` 覆盖精度。
204
+ > ```json
205
+ > {"componentKey":"Date","fieldName":"签订日期"},
206
+ > {"componentKey":"Date","fieldName":"精确到秒","format":"yyyy-MM-dd HH:mm:ss"},
207
+ > {"componentKey":"Date","fieldName":"默认今天","defaultValue":true}
208
+ > ```
209
+ >
210
+ > **日期限制**:A 字段**最早不得早于** B 字段写 `"minField":"B字段名"`,**最晚不得晚于**写 `"maxField":"B字段名"`(对齐平台 `min/max.dateField`,自动解析 B 的 fieldId)。**子表字段同样支持**,可指向主表字段或同子表字段。add-field 用 `--min-field` / `--max-field`。
211
+ > ```json
212
+ > {"componentKey":"Date","fieldName":"计划开始日期"},
213
+ > {"componentKey":"Date","fieldName":"计划结束日期","minField":"计划开始日期"},
214
+ > {"componentKey":"Date","fieldName":"完成日期","maxField":"计划结束日期"},
215
+ > {"componentKey":"DetailTable","fieldName":"行程明细","formFields":[
216
+ > {"componentKey":"Date","fieldName":"明细开始日期","minField":"计划开始日期"},
217
+ > {"componentKey":"Date","fieldName":"明细结束日期","minField":"明细开始日期"}
218
+ > ]}
219
+ > ```
220
+
221
+ **多选**:人员(Employee)/部门(Department)/关联ebuilder(EBuilder)/浏览(Browser)/下拉(Select) 默认单选,要选多个加 `"multiple": true`:
222
+ ```json
223
+ {"componentKey":"Employee","fieldName":"参与人员","multiple":true},
224
+ {"componentKey":"Department","fieldName":"会签部门","multiple":true},
225
+ {"componentKey":"EBuilder","fieldName":"关联客户","sformId":"<目标表单objId>","dataTitle":"name","multiple":true},
226
+ {"componentKey":"Select","fieldName":"标签","multiple":true,"fieldOptions":[{"name":"A"},{"name":"B"}]}
227
+ ```
228
+ > 不写 `multiple` 即单选。多选 EBuilder 选中多条记录,字段存数组值。**下拉 Select 多选 = 独立类型 `SelectMultiple`**(CLI 自动转,非 Select+开关)。
229
+
230
+ **文本最大长度**:Text 缺省 100、TextArea 缺省 4000,用 `"maxLen"` 覆盖(主表 + 明细子字段都支持):
231
+ ```json
232
+ {"componentKey":"Text","fieldName":"备注","maxLen":500},
233
+ {"componentKey":"TextArea","fieldName":"详情","maxLen":8000}
234
+ ```
235
+ > add-field 用 `--max-len <n>`。
236
+
237
+ ## EBuilder 关联字段
238
+
239
+ 关联其他表单记录(下拉选择/搜索),选中后展示目标表单的某个字段值。
240
+
241
+ ```json
242
+ {
243
+ "componentKey": "EBuilder",
244
+ "fieldName": "关联客户",
245
+ "sformId": "1296220571782152199",
246
+ "dataTitle": "客户名称"
247
+ }
248
+ ```
249
+
250
+ | 字段 | 必填 | 说明 |
251
+ |------|------|------|
252
+ | `sformId` | 是 | **目标表单的 objId**(不是 appId/formId) |
253
+ | `dataTitle` | 是 | 目标表单中用于显示的字段名,选中记录后展示该字段值。传 `"name"`(或不写)默认取目标表**字段名含"名称"**的字段(如 客户名称/类型名称),无则取第一个业务字段 |
254
+ | `displayColumns` | 否 | **关联浏览弹窗显示列**(字段名列表)。缺省自动用目标表业务字段**最多 5 个**(去系统字段),建好即生效;要指定用这个 |
255
+
256
+ > **关联浏览弹窗显示列默认自动配好**:`form create` 建表和 `form add-field` 加 EBuilder 字段时都自动写入 `ffDisplayColumns` = 目标表**业务字段前 5 个**(排除创建者/创建时间/数据ID等系统字段),浏览弹窗直接生效。`fields.json` 里显式写 `displayColumns` 指定列不受 5 个限制。事后想改可用 `e10-cli form ebuilder-columns <objId> <appId> <fieldId> <列...>` 或 `--clear` 清空。
257
+
258
+ ### EBuilder + 值带出(relateFrom)
259
+
260
+ 选关联记录后自动带出其他字段值(如选客户→带出联系人/地址):
261
+
262
+ ```json
263
+ {
264
+ "componentKey": "Text",
265
+ "fieldName": "联系人",
266
+ "relateFrom": { "ebuilderField": "关联客户", "sourceFieldId": "1296220571782152194" }
267
+ }
268
+ ```
269
+
270
+ - `ebuilderField`:本表单中的 EBuilder 字段名
271
+ - `sourceFieldId`:目标表单中要复制值的字段 **fieldId(数字 ID)**。⚠️ **不能传字段名**,用 `form read --app-id` 获取
272
+
273
+ 创建后补配值带出:`e10-cli form edit-field ... --relate-from <EBuilder字段名> --relate-from-source <源字段fieldId>`
274
+ > ⚠️ `--relate-from-source` 必须传字段的**数字 fieldId**,不能传字段名。
275
+
276
+ ## Select/RadioBox/CheckBox 带选项
277
+
278
+ ```json
279
+ {
280
+ "componentKey": "Select",
281
+ "fieldName": "客户等级",
282
+ "fieldOptions": [
283
+ {"name": "A级"},
284
+ {"name": "B级"},
285
+ {"name": "C级"}
286
+ ]
287
+ }
288
+ ```
289
+
290
+ ## 明细表 DetailTable
291
+
292
+ 明细表包含嵌套子字段,子字段写在其 `formFields` 数组内:
293
+
294
+ ```json
295
+ {
296
+ "componentKey": "DetailTable",
297
+ "fieldName": "订单明细",
298
+ "formFields": [
299
+ {"componentKey": "Text", "fieldName": "商品名称"},
300
+ {"componentKey": "Number", "fieldName": "数量"},
301
+ {"componentKey": "Number", "fieldName": "单价"},
302
+ {"componentKey": "Date", "fieldName": "交付日期"}
303
+ ]
304
+ }
305
+ ```
306
+
307
+ ### 二级明细表
308
+
309
+ 二级明细不是在明细表内再创建一张表,而是让当前明细表关联同一主表下的另一张明细表。`subForm` 和 `subField` 均可写名称;CLI 会解析为 ID、校验不能关联自身,并在保存后回读确认。
310
+
311
+ ```json
312
+ [
313
+ {"componentKey":"DetailTable","fieldName":"明细表2","formFields":[
314
+ {"componentKey":"Text","fieldName":"名称"}
315
+ ]},
316
+ {"componentKey":"DetailTable","fieldName":"明细表3","enableSubDetail":true,"defaultExpandRow":true,
317
+ "subDetailConfig":[{"subForm":"明细表2","subField":"名称"}],"formFields":[
318
+ {"componentKey":"Text","fieldName":"说明"}
319
+ ]}
320
+ ]
321
+ ```
322
+
323
+ 平台实测默认配置为 `parentMark=rowId`、`displayMode=inside`、`filterType=single`;通常不必显式填写。已有表单可用 `form detail-table sub-detail set` 配置,用 `disable` 暂停但保留关系,用 `clear` 清除关系。
324
+
325
+ 子字段也支持带选项的类型。
326
+
327
+ ## 复杂编号(年份编号):serial-mark
328
+
329
+ 编号(如 `XM-2026-001`、`YF-2026-0001`)走**复杂编号**机制:在任意文本字段上配编码段,`form serial-mark set --segments` 用 JSON 数组组合任意规则,**数组顺序即编号拼接顺序**,一条命令配完(含代字),重跑全量替换不累积。
330
+
331
+ ### 配置:`set --segments`
332
+
333
+ ```bash
334
+ e10-cli form serial-mark set <objId> <appId> <字段ID> --segments @segments.json
335
+ # 也支持内联 JSON:--segments '[{"type":"fixed","value":"XM-"},{"type":"serial","digits":4}]'
336
+ ```
337
+
338
+ segments.json 示例(生成如 `YF-2026-0001`,按年单独流水):
339
+ ```json
340
+ [
341
+ {"type":"field","fieldId":"<选择框字段ID>","shortName":{"研发":"YF","实施":"SS","运维":"YW","咨询":"ZX"}},
342
+ {"type":"fixed","value":"-"},
343
+ {"type":"year","format":"four","alone":true},
344
+ {"type":"serial","digits":4,"zero":true}
345
+ ]
346
+ ```
347
+
348
+ ### 段类型参考(任意组合,数组顺序决定拼接顺序)
349
+
350
+ | type | 含义 | 属性 | 平台 markFieldType |
351
+ |------|------|------|-------------------|
352
+ | `fixed` | 固定内容 | `value`(文本,如 `"XM-"`/`"-"`) | FIX_CONTEXT |
353
+ | `year` | 年份 | `format`:`four`(四位 2026,缺省)/`two`(两位 26);`alone`:true 按年单独流水(缺省 true) | DATE_YEAR |
354
+ | `serial` | 流水号 | `digits`(位数,如 4→0001);`zero`:true 补零(缺省)/false 不补零;`alone`:true 机构单独流水 | SERIAL_NUMBER |
355
+ | `field` | 表单字段值 | `fieldId`(取值字段);`alone`:true 机构单独流水;`shortName`:inline 代字映射(选项名→简称,见下) | FORM_FIELD |
356
+ | `system` | 系统字段 | `systemField`:`creator`(创建人)/`creator-dept`(创建人所属部门,自动部门代字);`alone` | SYSTEM_FIELD |
357
+ | `date` | 日期 | `format`:`yyyy`/`yyyyMM`/`yyyyMMdd`;`source`:`current`(当前)/`<字段ID>`;`alone` | DATE |
358
+
359
+ > - **任意规则直接组合**:把规则拆成段,按拼接顺序写入数组即可。如 `项目类型-年份-4位流水` = field + fixed("-") + year + serial
360
+ > - **代字自动**:field 段 markExtend=103(选项值取简称)、system creator-dept markExtend=101(部门取代字),无需手填
361
+ > - **inline 代字**:field 段带 `shortName` 自动配置代字映射,无需再跑 short-name
362
+ > - **按年单独流水**:year 段 `alone:true`(DATE_YEAR seqAlone,流水号每年重新计数)
363
+ > - **全量替换**:重跑时旧段进 delDefIds 清除,markDefId 复用,绑定/代字不丢失
364
+ > - 段对象来自 `getMarkFieldAddData` 预生成;markDefId 来自 `saveSingleMarkDef`;已有绑定时复用持久化 markDef(getMarkContext 优先用绑定记录的 targetId)
365
+
366
+ ### 增量调整(可选)
367
+
368
+ `set` 是全量重建;需在已有编号上追加/微调单段用 `add-segment`,单独查/改代字用 `short-name`:
369
+
370
+ ```bash
371
+ e10-cli form serial-mark add-segment <objId> <appId> <绑定字段ID> --type field --field-id <取值字段ID> [--position 0]
372
+ e10-cli form serial-mark add-segment <objId> <appId> <绑定字段ID> --type system --system-field creator-dept
373
+ e10-cli form serial-mark short-name list <objId> <appId> <选择框字段ID>
374
+ e10-cli form serial-mark short-name set <objId> <appId> <选择框字段ID> --map '{"研发":"YF","实施":"SS"}'
375
+ ```
376
+ add-segment 段类型与 set 一致(fixed/year/serial/field/system/date),`--position` 插入位置(缺省追加末尾)。
377
+
378
+ ### 查询与解除
379
+
380
+ ```bash
381
+ e10-cli form serial-mark read <objId> <appId> # 查看编号配置(绑定字段+组成段+代字)
382
+ e10-cli form serial-mark fields <objId> <appId> # 查可作为编号目标的字段
383
+ e10-cli form serial-mark clear <objId> <appId> <字段ID> # 解除编号绑定
384
+ ```
385
+
386
+ **注意**:
387
+ - 被编码字段平台自动设为只读(编号自动生成,不可手工改)
388
+ - 流水号按 `前缀+年份+流水` 组合查重累进
389
+ - 机制:markField 复杂编号(getEbMarkTargetId → getMarkSetForm → saveSingleMarkDef → saveOrUpdate → saveMarkField);段对象必须来自 getMarkFieldAddData 预生成;已有绑定时复用持久化 markDef,段/代字不丢失
390
+
391
+ ## 日期区间 DateRange
392
+
393
+ 日期区间字段**必须**指定精度格式,通过 `format` 配置:
394
+
395
+ ```json
396
+ {
397
+ "componentKey": "DateRange",
398
+ "fieldName": "出差时间",
399
+ "format": "yyyy-MM-dd HH:mm"
400
+ }
401
+ ```
402
+
403
+ | 字段 | 必填 | 说明 |
404
+ |------|------|------|
405
+ | `format` | 否 | 区间精度。缺省 `yyyy-MM-dd`(年-月-日);到分钟写 `yyyy-MM-dd HH:mm`;到秒 `yyyy-MM-dd HH:mm:ss` |
406
+ | `startPlaceholder` / `endPlaceholder` | 否 | 开始/结束控件占位符。缺省按 format 自动生成中文(如 `年-月-日 时:分`) |
407
+
408
+ > **CLI 自动展开**:创建时无需手写 `start`/`end`/`rangeInterval`——CLI 会把该字段展开为平台要求的 3 字段结构(主字段 + 「(开始时间)」「(结束时间)」两个 DateComponent,各带独立 fieldId),这是之前报 `DateIntervalFieldDto.getEnd()==null` 的根因(缺了 end 组件)。
409
+ >
410
+ > **事后补加**:`e10-cli form add-field <objId> <appId> "回程时间" DateRange --format "yyyy-MM-dd HH:mm"`
411
+
412
+ ## 字段公式(fields.json 的 formula 属性)
413
+
414
+ 创建表单时直接给字段绑定计算公式,CLI 自动完成「创建公式 + 绑定字段」两步(字段配置会带上 `ffExpress`):
415
+
416
+ ```json
417
+ {
418
+ "componentKey": "Number",
419
+ "fieldName": "出差天数",
420
+ "formula": "DAYS({主表.出差时间(开始时间)},{主表.出差时间(结束时间)})"
421
+ }
422
+ ```
423
+
424
+ 或对象形式指定返回类型:
425
+
426
+ ```json
427
+ "formula": { "expression": "DAYS({主表.出差时间(开始时间)},{主表.出差时间(结束时间)})", "returnType": "Number" }
428
+ ```
429
+
430
+ | 要点 | 说明 |
431
+ |------|------|
432
+ | 表达式语法 | 与 `form formula set --expression` 一致,用 `{主表.字段名}` 引用主表字段、`{明细表名.字段名}` 引用**明细表**字段(如 `DAYS({行程明细.行程开始时间},{行程明细.行程结束时间})`)。**fields.json create 与 formula set 两条路径都支持明细引用** |
433
+ | **明细列求和** | **`SUM({明细表名.字段})`** 可对明细表某列跨行求和(如 `SUM({付款信息.付款金额})`),生效。可配合 `workflow node validate` 做"明细累加=主表字段"校验 |
434
+ | **日期差** | 两个日期相减**不直接支持**,要用平台函数 **`DAYS({主表.开始},{主表.结束})`** |
435
+ | 返回类型 | 缺省 `Number`;文本/日期类用对象形式指定 |
436
+ | 事后补加 | `e10-cli form formula set <objId> <appId> --expression "..." --target <fieldId>` |
437
+
438
+ > **明细表子字段选项**:`DetailTable` 的 `formFields` 里的 `Select/RadioBox/CheckBox` 也支持 `fieldOptions`,CLI 会自动给子字段配置选项(创建时无需额外操作)。
439
+
440
+ ## 完整示例
441
+
442
+ ```bash
443
+ e10-cli form create 1283840156707348480 "采购合同" --fields @fields.json
444
+ ```
445
+
446
+ `fields.json` 内容:
447
+
448
+ ```json
449
+ [
450
+ {"componentKey":"Text","fieldName":"合同编号"},
451
+ {"componentKey":"Text","fieldName":"供应商名称"},
452
+ {"componentKey":"Employee","fieldName":"采购负责人"},
453
+ {"componentKey":"Date","fieldName":"签订日期"},
454
+ {"componentKey":"Money","fieldName":"总金额"},
455
+ {"componentKey":"Select","fieldName":"合同状态","fieldOptions":[{"name":"待审批"},{"name":"已审批"},{"name":"已完成"}]},
456
+ {"componentKey":"DetailTable","fieldName":"采购明细","formFields":[{"componentKey":"Text","fieldName":"物品名称"},{"componentKey":"Number","fieldName":"数量"},{"componentKey":"Number","fieldName":"单价"}]}
457
+ ]
458
+ ```
459
+
460
+ ## 创建成功后
461
+
462
+ - 返回表单 ID
463
+ - 用 `e10-cli form read <objId> --app-id <appId> --out fields.json` 导出字段信息(机器可读 JSON)
464
+ - 在代码中通过 `formApi.js` 读写该表单数据