weaver-work-cli 0.1.7 → 0.1.20

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 (264) hide show
  1. package/README.md +11 -11
  2. package/dist/cmd/action.js +76 -0
  3. package/dist/cmd/index.js +2 -0
  4. package/dist/cmd/refs/index.js +103 -0
  5. package/dist/cmd/register.js +31 -0
  6. package/dist/cmd/root.js +1 -0
  7. package/dist/cmd/setup/index.js +25 -5
  8. package/dist/cmd/skills/index.js +37 -5
  9. package/dist/core/connector.js +54 -0
  10. package/dist/core/context.js +2 -1
  11. package/dist/core/input.js +48 -0
  12. package/dist/core/output.js +298 -3
  13. package/dist/core/refs.js +432 -0
  14. package/dist/core/state.js +26 -0
  15. package/dist/internal/e10/auth/commands.js +2 -2
  16. package/dist/internal/e10/auth/session.js +14 -0
  17. package/dist/internal/e10/auth/xiaoe.js +116 -51
  18. package/dist/internal/e10/request-runtime.js +5 -0
  19. package/dist/internal/skills/install.js +148 -28
  20. package/dist/internal/skills/reader.js +12 -9
  21. package/dist/shortcuts/blog/continuation.js +74 -0
  22. package/dist/shortcuts/blog/errors.js +60 -0
  23. package/dist/shortcuts/blog/host.js +175 -0
  24. package/dist/shortcuts/blog/index.js +324 -0
  25. package/dist/shortcuts/blog/manifest.js +415 -0
  26. package/dist/shortcuts/blog/operations/comment.js +125 -0
  27. package/dist/shortcuts/blog/operations/comments.js +31 -0
  28. package/dist/shortcuts/blog/operations/edit.js +131 -0
  29. package/dist/shortcuts/blog/operations/export.js +46 -0
  30. package/dist/shortcuts/blog/operations/like.js +80 -0
  31. package/dist/shortcuts/blog/operations/publish.js +157 -0
  32. package/dist/shortcuts/blog/operations/query-user.js +58 -0
  33. package/dist/shortcuts/blog/operations/query.js +96 -0
  34. package/dist/shortcuts/blog/operations/registry.js +54 -0
  35. package/dist/shortcuts/blog/operations/remind.js +176 -0
  36. package/dist/shortcuts/blog/operations/shared.js +330 -0
  37. package/dist/shortcuts/blog/operations/types.js +16 -0
  38. package/dist/shortcuts/blog/operations.js +9 -0
  39. package/dist/shortcuts/caizhilian/continuation.js +70 -0
  40. package/dist/shortcuts/caizhilian/errors.js +53 -0
  41. package/dist/shortcuts/caizhilian/host.js +190 -0
  42. package/dist/shortcuts/caizhilian/index.js +186 -0
  43. package/dist/shortcuts/caizhilian/manifest.js +42 -0
  44. package/dist/shortcuts/caizhilian/operations/api.js +801 -0
  45. package/dist/shortcuts/caizhilian/operations/confirm.js +75 -0
  46. package/dist/shortcuts/caizhilian/operations/files.js +306 -0
  47. package/dist/shortcuts/caizhilian/operations/form.js +170 -0
  48. package/dist/shortcuts/caizhilian/operations/handlers/collab.js +611 -0
  49. package/dist/shortcuts/caizhilian/operations/handlers/document.js +890 -0
  50. package/dist/shortcuts/caizhilian/operations/handlers/file-collection.js +346 -0
  51. package/dist/shortcuts/caizhilian/operations/handlers/file-upload.js +192 -0
  52. package/dist/shortcuts/caizhilian/operations/handlers/fileops.js +570 -0
  53. package/dist/shortcuts/caizhilian/operations/handlers/folder.js +969 -0
  54. package/dist/shortcuts/caizhilian/operations/handlers/search.js +318 -0
  55. package/dist/shortcuts/caizhilian/operations/handlers/setting-attach.js +294 -0
  56. package/dist/shortcuts/caizhilian/operations/handlers/setting-backup.js +423 -0
  57. package/dist/shortcuts/caizhilian/operations/handlers/setting-encrypt.js +238 -0
  58. package/dist/shortcuts/caizhilian/operations/handlers/setting-storage.js +364 -0
  59. package/dist/shortcuts/caizhilian/operations/handlers/system.js +106 -0
  60. package/dist/shortcuts/caizhilian/operations/registry.js +151 -0
  61. package/dist/shortcuts/caizhilian/operations/shared.js +408 -0
  62. package/dist/shortcuts/caizhilian/operations/specs.js +623 -0
  63. package/dist/shortcuts/caizhilian/operations/types.js +57 -0
  64. package/dist/shortcuts/caizhilian/operations.js +21 -0
  65. package/dist/shortcuts/contract/continuation.js +70 -0
  66. package/dist/shortcuts/contract/errors.js +62 -0
  67. package/dist/shortcuts/contract/host.js +205 -0
  68. package/dist/shortcuts/contract/index.js +318 -0
  69. package/dist/shortcuts/contract/manifest.js +596 -0
  70. package/dist/shortcuts/contract/operations/clause-reference.js +78 -0
  71. package/dist/shortcuts/contract/operations/form-info.js +371 -0
  72. package/dist/shortcuts/contract/operations/read.js +118 -0
  73. package/dist/shortcuts/contract/operations/registry.js +43 -0
  74. package/dist/shortcuts/contract/operations/request.js +300 -0
  75. package/dist/shortcuts/contract/operations/shared.js +133 -0
  76. package/dist/shortcuts/contract/operations/subject.js +157 -0
  77. package/dist/shortcuts/contract/operations/template.js +81 -0
  78. package/dist/shortcuts/contract/operations/types.js +7 -0
  79. package/dist/shortcuts/contract/operations/workflow.js +52 -0
  80. package/dist/shortcuts/contract/operations/write.js +131 -0
  81. package/dist/shortcuts/contract/operations.js +8 -0
  82. package/dist/shortcuts/hrm/index.js +83 -2
  83. package/dist/shortcuts/hrm/operations/employee.js +160 -30
  84. package/dist/shortcuts/hrm/operations/org.js +17 -3
  85. package/dist/shortcuts/hrm/operations/position.js +18 -2
  86. package/dist/shortcuts/index.js +5 -1
  87. package/dist/shortcuts/invoice/index.js +74 -36
  88. package/dist/shortcuts/invoice/manifest.js +674 -4
  89. package/dist/shortcuts/invoice/markdown.js +172 -0
  90. package/dist/shortcuts/invoice/operations/add.js +3 -3
  91. package/dist/shortcuts/invoice/operations/delete.js +2 -2
  92. package/dist/shortcuts/invoice/operations/get.js +10 -2
  93. package/dist/shortcuts/invoice/operations/import.js +2 -2
  94. package/dist/shortcuts/invoice/operations/registry.js +8 -1
  95. package/dist/shortcuts/invoice/operations/reim-auto.js +719 -0
  96. package/dist/shortcuts/invoice/operations/reim.js +85 -2
  97. package/dist/shortcuts/invoice/operations/shared.js +75 -8
  98. package/dist/shortcuts/invoice/operations/update.js +2 -2
  99. package/dist/shortcuts/invoice/operations/upload-and-validate.js +93 -0
  100. package/dist/shortcuts/invoice/operations/validate-preview.js +2 -1
  101. package/dist/shortcuts/invoice/projection.js +328 -0
  102. package/dist/shortcuts/meeting/host.js +18 -1
  103. package/dist/shortcuts/meeting/manifest.js +30 -18
  104. package/dist/shortcuts/meeting/operations/eb/catalog.js +390 -0
  105. package/dist/shortcuts/meeting/operations/eb/conflict.js +389 -0
  106. package/dist/shortcuts/meeting/operations/eb/factory.js +389 -0
  107. package/dist/shortcuts/meeting/operations/eb/index.js +22 -0
  108. package/dist/shortcuts/meeting/operations/env.js +8 -1
  109. package/dist/shortcuts/meeting/operations/registry.js +2 -0
  110. package/dist/shortcuts/meeting/operations/signs.js +216 -2
  111. package/dist/shortcuts/workflow/endpoints.js +2 -1
  112. package/dist/shortcuts/workflow/errors.js +8 -2
  113. package/dist/shortcuts/workflow/host.js +6 -3
  114. package/dist/shortcuts/workflow/operations/form.js +931 -533
  115. package/dist/shortcuts/workflow/operations/read.js +462 -81
  116. package/dist/shortcuts/workflow/operations/shared.js +44 -0
  117. package/dist/shortcuts/workflow/operations/write.js +760 -56
  118. package/dist/shortcuts/workflow/operations.js +36 -10
  119. package/docs/_catalog.md +6 -0
  120. package/docs/agent-invoice.md +5 -1
  121. package/docs/agent-io-channel-design.md +468 -0
  122. package/docs/agent-skill-install.md +9 -4
  123. package/docs/blog.md +123 -0
  124. package/docs/caizhilian.md +304 -0
  125. package/docs/contract.md +91 -0
  126. package/docs/e10-auth.md +2 -2
  127. package/docs/hrm.md +19 -9
  128. package/docs/invoice.md +5 -1
  129. package/docs/meeting.md +1 -1
  130. package/docs/operation-manual.md +15 -3
  131. package/docs/skill-review-2026-09-19.md +2 -2
  132. package/package.json +2 -2
  133. package/scripts/package-skill.mjs +33 -20
  134. package/skill-template/business-info.json +113 -14
  135. package/skill-template/domains/blog.md +24 -0
  136. package/skill-template/domains/caizhilian.md +22 -0
  137. package/skill-template/domains/jinchengda.md +23 -0
  138. package/skill-template/domains/meeting.md +1 -1
  139. package/skill-template/domains/workflow.md +1 -1
  140. package/skill-template/skill-template.md +1 -1
  141. package/skills/weaver-e10-blog/SKILL.md +111 -0
  142. package/skills/weaver-e10-blog/references/blog-comment.md +51 -0
  143. package/skills/weaver-e10-blog/references/blog-comments.md +39 -0
  144. package/skills/weaver-e10-blog/references/blog-default-permission.md +38 -0
  145. package/skills/weaver-e10-blog/references/blog-disabled-capabilities.md +11 -0
  146. package/skills/weaver-e10-blog/references/blog-edit.md +51 -0
  147. package/skills/weaver-e10-blog/references/blog-export.md +42 -0
  148. package/skills/weaver-e10-blog/references/blog-like.md +50 -0
  149. package/skills/weaver-e10-blog/references/blog-publish.md +52 -0
  150. package/skills/weaver-e10-blog/references/blog-query-user.md +45 -0
  151. package/skills/weaver-e10-blog/references/blog-query.md +49 -0
  152. package/skills/weaver-e10-blog/references/blog-remind.md +51 -0
  153. package/skills/weaver-e10-blog/references/blog-resolve-users.md +38 -0
  154. package/skills/weaver-e10-blog/references/source-manifest.json +1540 -0
  155. package/skills/weaver-e10-caizhilian/SKILL.md +216 -0
  156. package/skills/weaver-e10-caizhilian/references/agent-entry.md +106 -0
  157. package/skills/weaver-e10-caizhilian/references/collaboration.md +112 -0
  158. package/skills/weaver-e10-caizhilian/references/document.md +111 -0
  159. package/skills/weaver-e10-caizhilian/references/file-collection.md +136 -0
  160. package/skills/weaver-e10-caizhilian/references/file-upload.md +309 -0
  161. package/skills/weaver-e10-caizhilian/references/files.md +120 -0
  162. package/skills/weaver-e10-caizhilian/references/folder.md +118 -0
  163. package/skills/weaver-e10-caizhilian/references/org-browser.md +104 -0
  164. package/skills/weaver-e10-caizhilian/references/setting-attach.md +410 -0
  165. package/skills/weaver-e10-caizhilian/references/setting-backup.md +372 -0
  166. package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +399 -0
  167. package/skills/weaver-e10-caizhilian/references/setting-storage.md +603 -0
  168. package/skills/weaver-e10-caizhilian/references/source-manifest.json +5079 -0
  169. package/skills/weaver-e10-caizhilian/references/withheld.md +93 -0
  170. package/skills/weaver-e10-caizhilian/references/write-protocol.md +120 -0
  171. package/skills/weaver-e10-calendar/SKILL.md +4 -3
  172. package/skills/weaver-e10-ebuilder-form/SKILL.md +4 -9
  173. package/skills/weaver-e10-ebuilder-form/references/context-routing.md +0 -9
  174. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -5
  175. package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +1 -5
  176. package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +1 -5
  177. package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +1 -5
  178. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -5
  179. package/skills/weaver-e10-esb/SKILL.md +2 -2
  180. package/skills/weaver-e10-esb/references/source-manifest.json +9 -9
  181. package/skills/weaver-e10-hrm/SKILL.md +54 -6
  182. package/skills/weaver-e10-hrm/references/employee.md +89 -15
  183. package/skills/weaver-e10-hrm/references/org.md +7 -4
  184. package/skills/weaver-e10-hrm/references/position.md +14 -7
  185. package/skills/weaver-e10-hrm/references/source-manifest.json +1 -1
  186. package/skills/weaver-e10-jinchengda/SKILL.md +166 -0
  187. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +82 -0
  188. package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +69 -0
  189. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +78 -0
  190. package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +27 -0
  191. package/skills/weaver-e10-jinchengda/references/contract-request-status.md +71 -0
  192. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +94 -0
  193. package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +89 -0
  194. package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +77 -0
  195. package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +66 -0
  196. package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +94 -0
  197. package/skills/weaver-e10-jinchengda/references/source-manifest.json +259 -0
  198. package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -11
  199. package/skills/weaver-e10-jucailin/SKILL.md +4 -3
  200. package/skills/weaver-e10-mail/SKILL.md +4 -11
  201. package/skills/weaver-e10-meeting/SKILL.md +66 -32
  202. package/skills/weaver-e10-meeting/references/meeting-change.md +5 -2
  203. package/skills/weaver-e10-meeting/references/meeting-create.md +2 -1
  204. package/skills/weaver-e10-meeting/references/meeting-eb.md +114 -0
  205. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +9 -8
  206. package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +35 -7
  207. package/skills/weaver-e10-meeting/references/meeting-update.md +1 -1
  208. package/skills/weaver-e10-okr/SKILL.md +6 -11
  209. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  210. package/skills/weaver-e10-plan/SKILL.md +3 -3
  211. package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +1 -1
  212. package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +1 -1
  213. package/skills/weaver-e10-plan/references/source-manifest.json +13 -13
  214. package/skills/weaver-e10-qiyecheng/SKILL.md +4 -10
  215. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +9 -9
  216. package/skills/weaver-e10-shared/SKILL.md +36 -25
  217. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -31
  218. package/skills/weaver-e10-shared/references/json-output-contract.md +20 -11
  219. package/skills/weaver-e10-shijingran/SKILL.md +2 -1
  220. package/skills/weaver-e10-shijingran/references/source-manifest.json +9 -9
  221. package/skills/weaver-e10-skill-maker/SKILL.md +4 -10
  222. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +5 -3
  223. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +12 -27
  224. package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +17 -5
  225. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +4 -27
  226. package/skills/weaver-e10-wenshuding/SKILL.md +5 -16
  227. package/skills/weaver-e10-wenshuding/references/source-manifest.json +7 -7
  228. package/skills/weaver-e10-workflow/SKILL.md +32 -37
  229. package/skills/weaver-e10-workflow/references/source-manifest.json +40 -77
  230. package/skills/weaver-e10-workflow/references/workflow-batch.md +90 -29
  231. package/skills/weaver-e10-workflow/references/workflow-create.md +79 -109
  232. package/skills/weaver-e10-workflow/references/workflow-memory.md +19 -9
  233. package/skills/weaver-e10-workflow/references/workflow-operate.md +2 -2
  234. package/skills/weaver-e10-workflow/references/workflow-query.md +37 -20
  235. package/skills/weaver-e10-workflow/references/workflow-share.md +18 -2
  236. package/skills/weaver-e10-workflow/references/workflow-view.md +4 -4
  237. package/skills/weaver-e10-yepiaotong/SKILL.md +75 -39
  238. package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +22 -1
  239. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +3 -1
  240. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +5 -5
  241. package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +135 -0
  242. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +15 -3
  243. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +1 -1
  244. package/skills/weaver-e10-yepiaotong/references/invoice-summarize.py +217 -0
  245. package/skills/weaver-e10-yepiaotong/references/invoice-upload-and-validate.md +88 -0
  246. package/skills/weaver-e10-yepiaotong/references/invoice-validation-preview.md +7 -2
  247. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +90 -10
  248. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +1 -0
  249. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +70 -49
  250. package/skills/weaver-e10-yepiaotong/references/reim-fast-path.md +119 -0
  251. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +55 -36
  252. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +4 -0
  253. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +149 -0
  254. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +125 -5
  255. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +430 -63
  256. package/skills/weaver-e10-yimiaoban/SKILL.md +4 -12
  257. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
  258. package/skills/weaver-e10-ziguanjia/SKILL.md +2 -1
  259. package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +3 -3
  260. package/tools/weaver-skill-detector-1.0.13/SKILL.md +9 -9
  261. package/tools/weaver-skill-detector-1.0.13/references/checklist.md +3 -3
  262. package/tools/weaver-skill-detector-1.0.13/scripts/__pycache__/validate_skill.cpython-313.pyc +0 -0
  263. package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +98 -91
  264. package/scripts/sync-connector-skills.mjs +0 -172
@@ -0,0 +1,371 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { contractValidationError } from '../errors.js';
3
+ import { requireId } from './shared.js';
4
+ /**
5
+ * 流程表单读取(三段式)。
6
+ *
7
+ * 原实现走 `/api/workflow/pathdef/openapi/getFormInfo`,实测在 E10 10.0.9807.01 合同租户上
8
+ * 返回 errcode 0 但**表单为空**,读不到任何字段。与 `weaver-e10-workflow`(`src/shortcuts/workflow`)
9
+ * 同源的正确做法是三次调用:
10
+ *
11
+ * 1. `loadBaseParam` 取表单会话(requestId / nodeId / authStr / authSignature)
12
+ * 2. `loadFrameParam` 取表单身份(formId / relateType / nodeId / 权限开关)
13
+ * 3. `getFormLayout` 取字段布局(`form` + `formLayout` + `viewRelateConfig` 静态必填)
14
+ *
15
+ * 前两步的结果只服务于第三步,不落 continuation 状态、不写本地文件,因此保持为只读 operation。
16
+ */
17
+ const FORM_INFO_ENDPOINTS = {
18
+ loadBase: '/api/workflow/core/flowPage/loadBaseParam',
19
+ loadFrame: '/api/workflow/core/flowPage/loadFrameParam',
20
+ formLayout: '/api/workflow/core/form/core/getFormLayout',
21
+ };
22
+ /** 表单接口公共 query 参数,与 workflow 模块的 AJAX_QUERY 一致。 */
23
+ const AJAX_QUERY = { sf_request_type: 'ajax' };
24
+ const SELECT_COMPONENTS = new Set(['select', 'selectmultiple', 'radiobox', 'checkbox', 'radio', 'multiselect']);
25
+ const BROWSER_COMPONENTS = new Set([
26
+ 'employee', 'department', 'subcompany', 'jobtitle', 'job', 'relatebrowser',
27
+ 'browser', 'workflow', 'ebuilder', 'customer', 'project',
28
+ ]);
29
+ const NON_INPUT_COMPONENTS = new Set([
30
+ 'paragraph', 'label', 'divider', 'option', 'detailtable', 'group', 'layout', 'internaltitle', 'multilingualtag',
31
+ ]);
32
+ const READONLY_COMPONENTS = new Set([
33
+ 'dividingline', 'paragraph', 'slidercomponent', 'button', 'subtablecontrol', 'mobileinteraction',
34
+ ]);
35
+ /**
36
+ * 建模表单(relateType = WEA_EBUILDER)的布局接口在另一个 module 下,需替换路径前缀。
37
+ * 传短 key 会原样返回导致路径非法,因此只接受完整路径。
38
+ */
39
+ function formApiUrl(path, relateType) {
40
+ if (String(relateType || '').trim() === 'WEA_EBUILDER') {
41
+ return path.replace('/api/workflow/core/', '/api/ebuilder/flow/');
42
+ }
43
+ return path;
44
+ }
45
+ /**
46
+ * 这三条接口的响应统一形如 `{ code, msg, status, data: { ... } }`——业务载荷在 `data` 里,
47
+ * 顶层只有状态。缺 `data`(或 `data` 不是对象)时按裸载荷兜底,避免单点判空。
48
+ */
49
+ function unwrapPayload(value) {
50
+ const data = (value ?? {}).data;
51
+ return (data && typeof data === 'object') ? data : (value ?? {});
52
+ }
53
+ /** loadBaseParam → 表单会话(对应 workflow 模块的 parseRuntime)。 */
54
+ function parseRuntime(data, workflowId) {
55
+ if (!data || typeof data !== 'object')
56
+ throw contractValidationError('format_error', 'loadBaseParam 未返回 data');
57
+ const common = data.commonParam;
58
+ if (!common || typeof common !== 'object')
59
+ throw contractValidationError('format_error', 'loadBaseParam 未返回 commonParam');
60
+ const currentUser = (common.currentUser && typeof common.currentUser === 'object') ? common.currentUser : {};
61
+ const employeeId = String(currentUser.userId ?? '');
62
+ if (!employeeId)
63
+ throw contractValidationError('format_error', '缺少 commonParam.currentUser.userId');
64
+ const requestInfo = (data.requestInfo && typeof data.requestInfo === 'object') ? data.requestInfo : {};
65
+ return {
66
+ request_id: String(common.requestId ?? ''),
67
+ node_id: String(common.userCurrentNodeId ?? common.fixedNodeId ?? ''),
68
+ employee_id: employeeId,
69
+ identity_id: String(common.identityId ?? employeeId),
70
+ identity_type: Number(common.identityType ?? 0),
71
+ auth_str: String(common.authStr ?? ''),
72
+ auth_signature: String(common.authSignatureStr ?? ''),
73
+ workflow_name: String(requestInfo.workflowName ?? ''),
74
+ default_request_name: String(requestInfo.requestName ?? '').trim(),
75
+ };
76
+ }
77
+ /** loadFrameParam → 表单身份(对应 workflow 模块的 parseFrame)。 */
78
+ function parseFrame(data, nodeId) {
79
+ if (!data || typeof data !== 'object')
80
+ throw contractValidationError('format_error', 'loadFrameParam 未返回 data');
81
+ const configs = data.formConfig;
82
+ if (!Array.isArray(configs) || configs.length !== 1 || !configs[0] || typeof configs[0] !== 'object') {
83
+ throw contractValidationError('format_error', 'loadFrameParam 返回的表单配置不是唯一项');
84
+ }
85
+ const config = configs[0];
86
+ const formInfo = (config.formInfo && typeof config.formInfo === 'object') ? config.formInfo : {};
87
+ const formId = String(formInfo.relateKey ?? '');
88
+ if (!formId)
89
+ throw contractValidationError('format_error', '缺少 formConfig.formInfo.relateKey');
90
+ const relateType = String(formInfo.relateType ?? '').trim() || 'WEA_FORM';
91
+ const viewNodeId = String(config.viewFormNodeId ?? nodeId);
92
+ if (!viewNodeId)
93
+ throw contractValidationError('format_error', '缺少 formConfig.viewFormNodeId');
94
+ if (viewNodeId !== nodeId)
95
+ throw contractValidationError('format_error', 'loadBaseParam 与 loadFrameParam 返回了不同节点');
96
+ const ts = String(config.timestamp ?? '').match(/^\d+$/) ? Number(config.timestamp) : Date.now();
97
+ return {
98
+ form_id: formId,
99
+ relate_type: relateType,
100
+ permission_id: String(config.permissionId ?? '').trim(),
101
+ permission_type: Number(config.permissionType ?? 1),
102
+ layout_multi_id: String(config.layoutMultiId ?? config.defaultLayoutId ?? ''),
103
+ new_layout: config.newLayout !== false,
104
+ sys_field_new_mode: config.sysFieldNewMode !== false,
105
+ view_form_node_id: viewNodeId,
106
+ timestamp: ts,
107
+ // enableNodePermission=false ⇒ 未启用节点权限,顶层不带 permissionId 才能拿到 viewRelateConfig。
108
+ enable_node_permission: config.enableNodePermission !== false,
109
+ };
110
+ }
111
+ /** getFormLayout 请求体(对应 workflow 模块的 buildLayoutRequest)。 */
112
+ function buildLayoutRequest(workflowId, runtime, frame) {
113
+ const permissionId = String(frame.permission_id ?? '').trim();
114
+ const nodePermissionEnabled = frame.enable_node_permission !== false;
115
+ return {
116
+ terminalType: 'PC',
117
+ formId: frame.form_id,
118
+ ...(nodePermissionEnabled && permissionId ? { permissionId } : {}),
119
+ module: 'workflow',
120
+ customParam: {
121
+ permissionType: frame.permission_type,
122
+ requestId: runtime.request_id,
123
+ workflowId,
124
+ nodeId: runtime.node_id,
125
+ authSignatureStr: runtime.auth_signature,
126
+ authStr: runtime.auth_str,
127
+ readOnly: false,
128
+ identityId: runtime.identity_id,
129
+ identityType: runtime.identity_type,
130
+ isTest: false,
131
+ create: true,
132
+ mobile: false,
133
+ formId: frame.form_id,
134
+ source: 'view',
135
+ isAgent: false,
136
+ beAgentId: '0',
137
+ hideSysFieldArea: true,
138
+ viewFormNodeId: frame.view_form_node_id,
139
+ timestamp: frame.timestamp,
140
+ turnTodoUser: [],
141
+ sysFieldNewMode: frame.sys_field_new_mode,
142
+ },
143
+ cacheUid: randomUUID(),
144
+ newLayout: frame.new_layout,
145
+ layoutMultiId: frame.layout_multi_id,
146
+ dataCrossLayout: false,
147
+ employeeId: runtime.employee_id,
148
+ refId: workflowId,
149
+ initialDatas: [
150
+ { keyType: null, key: 'isCreate', value: 1 },
151
+ { keyType: null, key: 'isMobile', value: 0 },
152
+ ],
153
+ cost: false,
154
+ effectValues: [workflowId, runtime.node_id],
155
+ orgAsyncPageQuery: true,
156
+ };
157
+ }
158
+ /** 静态必填/只读/显示:优先取 getFormLayout 下发的 viewRelateConfig,缺省回落字段自带标记。 */
159
+ function viewRelateMaps(layoutData) {
160
+ const required = {};
161
+ const disableEdit = {};
162
+ const viewRelateConfig = Array.isArray(layoutData.viewRelateConfig) ? layoutData.viewRelateConfig : [];
163
+ for (const item of viewRelateConfig) {
164
+ if (!item || typeof item !== 'object')
165
+ continue;
166
+ const fieldId = String(item.fieldId ?? '').trim();
167
+ if (!fieldId)
168
+ continue;
169
+ required[fieldId] = Boolean(item.required);
170
+ disableEdit[fieldId] = Boolean(item.disableEdit);
171
+ }
172
+ return { required, disableEdit };
173
+ }
174
+ /**
175
+ * 读布局页签结构,与 workflow 模块的 parseLayoutMeta 同源:
176
+ * - `hidePositions`:Excel 布局里 `attrs.hide` 的格子坐标,落在这些位置的字段视为不可见
177
+ * - `compsFieldIds`:第一页 `comps[].config.fieldId`,主表字段必须在此白名单内
178
+ * 明细表字段不受此约束(它们挂在 detailtable 组件下,不出现在页面 comps 里)
179
+ */
180
+ function parseLayoutMeta(layoutData) {
181
+ const hiddenCellIds = new Set();
182
+ const compsFieldIds = new Set();
183
+ let page0 = null;
184
+ const pageLayouts = layoutData && layoutData.formLayout ? layoutData.formLayout.pageLayouts : undefined;
185
+ if (Array.isArray(pageLayouts) && pageLayouts.length)
186
+ page0 = pageLayouts[0];
187
+ if (page0 && typeof page0 === 'object') {
188
+ const workbook = (page0.config && page0.config.workbook) ? page0.config.workbook : {};
189
+ const cells = workbook.Sheet1 ? workbook.Sheet1.cells : null;
190
+ const hidePositions = new Set();
191
+ if (Array.isArray(cells)) {
192
+ for (const cell of cells) {
193
+ if (!cell || typeof cell !== 'object')
194
+ continue;
195
+ const attrs = (cell.tag && cell.tag.attrs) ? cell.tag.attrs : {};
196
+ if (attrs.hide)
197
+ hidePositions.add(`${cell.col}:${cell.row}`);
198
+ }
199
+ }
200
+ for (const comp of page0.comps || []) {
201
+ if (!comp || typeof comp !== 'object')
202
+ continue;
203
+ const cfg = comp.config || {};
204
+ const fieldId = String(cfg.fieldId ?? '').trim();
205
+ if (!fieldId)
206
+ continue;
207
+ const excel = cfg.excel || {};
208
+ if (hidePositions.has(`${excel.col}:${excel.row}`))
209
+ hiddenCellIds.add(fieldId);
210
+ compsFieldIds.add(fieldId);
211
+ }
212
+ }
213
+ return { hiddenCellIds, compsFieldIds };
214
+ }
215
+ /** 从布局树里收集字段(同一 fieldId 取信息量最大的那个节点)。 */
216
+ function extractFields(layoutData) {
217
+ const candidates = {};
218
+ const walk = (value) => {
219
+ if (Array.isArray(value)) {
220
+ for (const child of value)
221
+ walk(child);
222
+ return;
223
+ }
224
+ if (!value || typeof value !== 'object')
225
+ return;
226
+ const fieldId = String(value.fieldId ?? '').trim();
227
+ const component = String(value.componentKey ?? value.type ?? '').trim();
228
+ if (fieldId && component) {
229
+ const previous = candidates[fieldId];
230
+ if (previous === undefined || Object.keys(value).length > Object.keys(previous).length) {
231
+ candidates[fieldId] = value;
232
+ }
233
+ }
234
+ for (const child of Object.values(value))
235
+ walk(child);
236
+ };
237
+ walk(layoutData.formLayout);
238
+ const meta = parseLayoutMeta(layoutData);
239
+ const { required: requiredMap, disableEdit } = viewRelateMaps(layoutData);
240
+ const result = [];
241
+ for (const fieldId of Object.keys(candidates)) {
242
+ const raw = candidates[fieldId];
243
+ const component = String(raw.componentKey ?? raw.type ?? '');
244
+ const normalized = component.toLowerCase();
245
+ if (NON_INPUT_COMPONENTS.has(normalized) || normalized.startsWith('flowpagesysfield'))
246
+ continue;
247
+ const subFormId = String(raw.subFormId ?? '');
248
+ if (meta.hiddenCellIds.has(fieldId))
249
+ continue;
250
+ // 主表字段必须真的挂在页面上;明细字段不在页面 comps 里,不受白名单约束
251
+ if (meta.compsFieldIds.size && !subFormId && !meta.compsFieldIds.has(fieldId))
252
+ continue;
253
+ const browserType = (raw.browserType && typeof raw.browserType === 'object') ? raw.browserType : {};
254
+ const options = [];
255
+ for (const option of raw.options || []) {
256
+ if (!option || typeof option !== 'object')
257
+ continue;
258
+ const optionId = String(option.valueKey ?? option.selectionId ?? option.id ?? '').trim();
259
+ const name = String(option.name ?? option.content ?? '').trim();
260
+ if (optionId && name)
261
+ options.push({ id: optionId, name });
262
+ }
263
+ // browserType 已归一化为对象:JS 的 Boolean({}) 恒为 true,必须判"非空对象",
264
+ // 否则每个字段都会被当成浏览按钮字段(workflow 模块 2026-09-16 的同类修复)。
265
+ const isBrowser = Object.keys(browserType).length > 0 || BROWSER_COMPONENTS.has(normalized);
266
+ result.push({
267
+ id: fieldId,
268
+ name: String(raw.title ?? raw.name ?? raw.dataKey ?? fieldId),
269
+ componentKey: component,
270
+ required: requiredMap[fieldId] !== undefined ? requiredMap[fieldId] : Boolean(raw.required || raw.mustInput),
271
+ readOnly: Boolean(READONLY_COMPONENTS.has(normalized) || raw.readOnly || disableEdit[fieldId]),
272
+ subFormId,
273
+ isBrowser,
274
+ isSelect: SELECT_COMPONENTS.has(normalized) || options.length > 0,
275
+ isMultiple: (SELECT_COMPONENTS.has(normalized) && (normalized === 'selectmultiple' || normalized === 'checkbox' || normalized === 'multiselect'))
276
+ || (isBrowser && raw.isSingle === false),
277
+ browserType: String(browserType.type ?? browserType.id ?? raw.browserTypeCode ?? ''),
278
+ browserModule: String(browserType.module ?? raw.browserModule ?? ''),
279
+ options,
280
+ format: String(raw.format ?? raw.formatPattern ?? ''),
281
+ typeLen: raw.typeLen !== undefined ? raw.typeLen : raw.typeLength,
282
+ showOrder: raw.showOrder !== undefined ? raw.showOrder : 0,
283
+ });
284
+ }
285
+ result.sort((a, b) => {
286
+ if (Boolean(a.subFormId) !== Boolean(b.subFormId))
287
+ return a.subFormId ? 1 : -1;
288
+ if (a.subFormId !== b.subFormId)
289
+ return a.subFormId < b.subFormId ? -1 : 1;
290
+ const sa = Number(a.showOrder || 0);
291
+ const sb = Number(b.showOrder || 0);
292
+ if (sa !== sb)
293
+ return sa - sb;
294
+ return a.id < b.id ? -1 : 1;
295
+ });
296
+ return result;
297
+ }
298
+ /**
299
+ * `contract.workflow.form.info`:读流程发起表单的字段定义。
300
+ * 输入只需 `workflowId`;三段式内部的中间值(formId / requestId / nodeId)由实现自行串联。
301
+ */
302
+ export const contractWorkflowFormInfoOperation = {
303
+ name: 'contract.workflow.form.info',
304
+ async execute(input, context) {
305
+ const { host } = context;
306
+ const workflowId = requireId(input.workflowId, 'workflowId');
307
+ const query = { workflowId, isCreate: 1, ...AJAX_QUERY };
308
+ const base = { workflowId, isCreate: 1, isMobile: 0 };
309
+ const baseValue = await host.contractRequest({
310
+ method: 'POST',
311
+ path: FORM_INFO_ENDPOINTS.loadBase,
312
+ query,
313
+ body: base,
314
+ });
315
+ const frameValue = await host.contractRequest({
316
+ method: 'POST',
317
+ path: FORM_INFO_ENDPOINTS.loadFrame,
318
+ query,
319
+ body: base,
320
+ });
321
+ const runtime = parseRuntime(unwrapPayload(baseValue), workflowId);
322
+ const frame = parseFrame(unwrapPayload(frameValue), runtime.node_id);
323
+ const layoutPath = formApiUrl(FORM_INFO_ENDPOINTS.formLayout, frame.relate_type);
324
+ const layoutValue = await host.contractRequest({
325
+ method: 'POST',
326
+ path: layoutPath,
327
+ query: { formId: frame.form_id, ...AJAX_QUERY },
328
+ body: buildLayoutRequest(workflowId, runtime, frame),
329
+ });
330
+ const layout = unwrapPayload(layoutValue);
331
+ if (!layout || typeof layout !== 'object') {
332
+ throw contractValidationError('format_error', 'getFormLayout 未返回有效 data');
333
+ }
334
+ const returnedFormId = String((layout.form ?? {}).id ?? '');
335
+ if (returnedFormId && returnedFormId !== frame.form_id) {
336
+ throw contractValidationError('format_error', 'getFormLayout 返回了不同的 formId');
337
+ }
338
+ const fields = extractFields(layout);
339
+ const requiredFields = fields.filter((field) => field.required).map((field) => field.id);
340
+ const subFormRequired = {};
341
+ for (const field of fields) {
342
+ if (!field.subFormId || !field.required)
343
+ continue;
344
+ (subFormRequired[field.subFormId] ??= []).push(field.id);
345
+ }
346
+ // 必填口径:viewRelateConfig 非空时它才是权威来源(字段自带 required 只是表单设计默认值),
347
+ // 另有 lowercase 的差异来自条件必填——服务端按场景动态判定,静态读取拿不到,交给发起侧实时校验。
348
+ const requiredSource = Array.isArray(layout.viewRelateConfig) && layout.viewRelateConfig.length
349
+ ? 'viewRelateConfig'
350
+ : 'field-metadata';
351
+ return {
352
+ status: 'COMPLETE',
353
+ data: {
354
+ path: layoutPath,
355
+ steps: [FORM_INFO_ENDPOINTS.loadBase, FORM_INFO_ENDPOINTS.loadFrame, layoutPath],
356
+ formId: frame.form_id,
357
+ layoutId: String((layout.formLayout ?? {}).id ?? ''),
358
+ relateType: frame.relate_type,
359
+ requestId: runtime.request_id,
360
+ nodeId: runtime.node_id,
361
+ workflowName: runtime.workflow_name,
362
+ defaultRequestName: runtime.default_request_name,
363
+ fieldCount: fields.length,
364
+ requiredFields,
365
+ requiredSource,
366
+ subFormRequired,
367
+ fields,
368
+ },
369
+ };
370
+ },
371
+ };
@@ -0,0 +1,118 @@
1
+ import { maskText } from './shared.js';
2
+ const PASSTHROUGH_KEYS = [
3
+ 'code',
4
+ 'msg',
5
+ 'message',
6
+ 'status',
7
+ 'fail',
8
+ 'data',
9
+ 'baseInfoList',
10
+ 'activeWfId',
11
+ 'total',
12
+ 'maxPage',
13
+ ];
14
+ function defaultShape(value) {
15
+ const result = {};
16
+ for (const key of PASSTHROUGH_KEYS) {
17
+ if (value[key] !== undefined)
18
+ result[key] = value[key];
19
+ }
20
+ return result;
21
+ }
22
+ export class ContractReadOperation {
23
+ name;
24
+ spec;
25
+ constructor(name, spec) {
26
+ this.name = name;
27
+ this.spec = spec;
28
+ }
29
+ async execute(input, { host }) {
30
+ const query = {
31
+ ...(this.spec.method === 'GET' ? this.spec.defaults ?? {} : {}),
32
+ ...(this.spec.query?.(input) ?? {}),
33
+ };
34
+ const body = {
35
+ ...(this.spec.method === 'POST' ? this.spec.defaults ?? {} : {}),
36
+ ...(this.spec.body?.(input) ?? {}),
37
+ };
38
+ const form = this.spec.form?.(input);
39
+ const value = await host.contractRequest({
40
+ method: this.spec.method,
41
+ path: this.spec.path,
42
+ query,
43
+ ...(form ? { form } : this.spec.method === 'POST' ? { body } : {}),
44
+ ...(this.spec.userIdField ? { userIdField: this.spec.userIdField } : {}),
45
+ });
46
+ return {
47
+ status: 'COMPLETE',
48
+ data: { path: this.spec.path, ...(this.spec.shape ?? defaultShape)(value) },
49
+ };
50
+ }
51
+ }
52
+ function asArray(value) {
53
+ return Array.isArray(value) ? value.filter((item) => item && typeof item === 'object') : [];
54
+ }
55
+ /** 只保留环境无关的展示字段,去掉 tenantKey / 人员 ID / 完整 appId。 */
56
+ export function projectSubjects(value) {
57
+ return {
58
+ code: value.code,
59
+ msg: value.msg,
60
+ objs: asArray(value.data).map((item) => ({
61
+ id: item.id,
62
+ objName: item.objName,
63
+ showName: item.showName,
64
+ tag: item.tag,
65
+ })),
66
+ };
67
+ }
68
+ export function projectWorkflowBase(value) {
69
+ return {
70
+ message: value.message,
71
+ workflows: asArray(value.baseInfoList).map((item) => ({
72
+ id: item.id,
73
+ workflowName: item.workflowName,
74
+ workflowType: item.workflowType,
75
+ status: item.status,
76
+ versionId: item.versionId,
77
+ activeWfId: item.activeWfId,
78
+ })),
79
+ };
80
+ }
81
+ export function projectWorkflowList(value) {
82
+ return {
83
+ message: value.message,
84
+ workflows: asArray(value.data).map((item) => ({
85
+ id: item.id,
86
+ workflowName: item.workflowName,
87
+ workflowType: item.workflowType,
88
+ })),
89
+ };
90
+ }
91
+ export function projectRequestStatus(value) {
92
+ const base = (value.data ?? {});
93
+ const info = (base.workflowBaseInfo ?? {});
94
+ return {
95
+ message: value.message,
96
+ request: {
97
+ requestId: info.requestId,
98
+ workflowId: info.workflowId,
99
+ requestName: info.requestName,
100
+ status: info.status ?? base.status,
101
+ flowStatus: info.flowStatus,
102
+ currentNodeType: base.currentNodeType,
103
+ lastOperator: info.lastOperator === undefined ? undefined : maskText(info.lastOperator),
104
+ },
105
+ };
106
+ }
107
+ export function projectRequestLog(value) {
108
+ return {
109
+ message: value.message,
110
+ logs: asArray(value.data).map((item) => ({
111
+ operatorName: (item.commentor ?? {}).name,
112
+ content: item.content,
113
+ commentType: item.commentType,
114
+ stepName: item.stepName,
115
+ addTime: item.addTime,
116
+ })),
117
+ };
118
+ }
@@ -0,0 +1,43 @@
1
+ import { contractValidationError } from '../errors.js';
2
+ import { contractOperations } from '../manifest.js';
3
+ import { contractClauseReferenceOperations } from './clause-reference.js';
4
+ import { contractRequestOperations } from './request.js';
5
+ import { contractSubjectOperations } from './subject.js';
6
+ import { contractTemplateOperations } from './template.js';
7
+ import { contractWorkflowOperations } from './workflow.js';
8
+ function buildRegistry() {
9
+ const registry = new Map();
10
+ const handlers = [
11
+ ...contractTemplateOperations,
12
+ ...contractClauseReferenceOperations,
13
+ ...contractSubjectOperations,
14
+ ...contractWorkflowOperations,
15
+ ...contractRequestOperations,
16
+ ];
17
+ for (const handler of handlers) {
18
+ if (registry.has(handler.name))
19
+ throw new Error(`duplicate contract operation handler: ${handler.name}`);
20
+ registry.set(handler.name, handler);
21
+ }
22
+ for (const contract of contractOperations) {
23
+ if (!registry.has(contract.name))
24
+ throw new Error(`missing contract operation handler: ${contract.name}`);
25
+ }
26
+ for (const name of registry.keys()) {
27
+ if (!contractOperations.some((contract) => contract.name === name)) {
28
+ throw new Error(`contract operation handler without manifest contract: ${name}`);
29
+ }
30
+ }
31
+ return registry;
32
+ }
33
+ const contractOperationRegistry = buildRegistry();
34
+ export function getContractOperation(operation) {
35
+ const handler = contractOperationRegistry.get(operation);
36
+ if (!handler) {
37
+ throw contractValidationError('operation_unknown', `今承达合同管理不支持操作:${operation}`);
38
+ }
39
+ return handler;
40
+ }
41
+ export function listContractOperations() {
42
+ return [...contractOperationRegistry.keys()];
43
+ }