weaver-work-cli 0.1.6 → 0.1.7

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 (225) hide show
  1. package/README.md +14 -9
  2. package/dist/cmd/skills/index.js +60 -0
  3. package/dist/internal/e10/auth/commands.js +44 -31
  4. package/dist/internal/e10/auth/session.js +44 -3
  5. package/dist/internal/e10/auth/xiaoe.js +363 -11
  6. package/dist/internal/e10/context.js +4 -2
  7. package/dist/internal/skills/detector.js +42 -0
  8. package/dist/internal/skills/install.js +50 -3
  9. package/dist/shortcuts/archive/render/search-format.js +12 -3
  10. package/dist/shortcuts/ebuilder-form/continuation.js +70 -0
  11. package/dist/shortcuts/ebuilder-form/errors.js +54 -0
  12. package/dist/shortcuts/ebuilder-form/host.js +1238 -0
  13. package/dist/shortcuts/ebuilder-form/index.js +108 -0
  14. package/dist/shortcuts/ebuilder-form/manifest.js +347 -0
  15. package/dist/shortcuts/ebuilder-form/operations/read.js +157 -0
  16. package/dist/shortcuts/ebuilder-form/operations/registry.js +56 -0
  17. package/dist/shortcuts/ebuilder-form/operations/shared.js +132 -0
  18. package/dist/shortcuts/ebuilder-form/operations/types.js +19 -0
  19. package/dist/shortcuts/ebuilder-form/operations/write.js +277 -0
  20. package/dist/shortcuts/ebuilder-form/operations.js +8 -0
  21. package/dist/shortcuts/ehr/operations/salary.js +2 -140
  22. package/dist/shortcuts/im/continuation.js +70 -0
  23. package/dist/shortcuts/{yimiaoban → im}/errors.js +14 -14
  24. package/dist/shortcuts/{yimiaoban → im}/host.js +26 -26
  25. package/dist/shortcuts/{yimiaoban → im}/index.js +42 -42
  26. package/dist/shortcuts/{yimiaoban → im}/manifest.js +7 -6
  27. package/dist/shortcuts/{yimiaoban → im}/operations/file-user.js +54 -41
  28. package/dist/shortcuts/{yimiaoban → im}/operations/group-read.js +46 -44
  29. package/dist/shortcuts/{yimiaoban → im}/operations/group-write.js +113 -66
  30. package/dist/shortcuts/{yimiaoban → im}/operations/msg-sync.js +164 -141
  31. package/dist/shortcuts/{yimiaoban → im}/operations/msg-write.js +47 -47
  32. package/dist/shortcuts/{yimiaoban → im}/operations/person.js +10 -10
  33. package/dist/shortcuts/{yimiaoban → im}/operations/registry.js +10 -8
  34. package/dist/shortcuts/{yimiaoban → im}/operations/session.js +82 -83
  35. package/dist/shortcuts/im/operations/shared.js +442 -0
  36. package/dist/shortcuts/{yimiaoban → im}/operations/types.js +1 -1
  37. package/dist/shortcuts/im/operations/user-remind.js +201 -0
  38. package/dist/shortcuts/{yimiaoban → im}/operations/write-util.js +7 -7
  39. package/dist/shortcuts/{yimiaoban → im}/operations.js +3 -3
  40. package/dist/shortcuts/index.js +10 -2
  41. package/dist/shortcuts/invoice/manifest.js +113 -10
  42. package/dist/shortcuts/invoice/operations/import.js +39 -14
  43. package/dist/shortcuts/invoice/operations/reim.js +38 -18
  44. package/dist/shortcuts/invoice/operations/shared.js +35 -6
  45. package/dist/shortcuts/jiuchuanhui/manifest.js +3 -3
  46. package/dist/shortcuts/jiuchuanhui/operations/registry.js +2 -2
  47. package/dist/shortcuts/{yimiaoban → okr}/continuation.js +10 -10
  48. package/dist/shortcuts/okr/errors.js +70 -0
  49. package/dist/shortcuts/okr/host.js +169 -0
  50. package/dist/shortcuts/okr/index.js +155 -0
  51. package/dist/shortcuts/okr/manifest.js +70 -0
  52. package/dist/shortcuts/okr/operations/link.js +305 -0
  53. package/dist/shortcuts/okr/operations/read.js +481 -0
  54. package/dist/shortcuts/okr/operations/registry.js +31 -0
  55. package/dist/shortcuts/okr/operations/shared.js +381 -0
  56. package/dist/shortcuts/okr/operations/types.js +88 -0
  57. package/dist/shortcuts/okr/operations/write.js +838 -0
  58. package/dist/shortcuts/okr/operations.js +8 -0
  59. package/dist/shortcuts/project/continuation.js +70 -0
  60. package/dist/shortcuts/project/errors.js +53 -0
  61. package/dist/shortcuts/project/host.js +160 -0
  62. package/dist/shortcuts/project/index.js +106 -0
  63. package/dist/shortcuts/project/manifest.js +36 -0
  64. package/dist/shortcuts/project/operations/read.js +551 -0
  65. package/dist/shortcuts/project/operations/registry.js +31 -0
  66. package/dist/shortcuts/project/operations/shared.js +68 -0
  67. package/dist/shortcuts/project/operations/types.js +39 -0
  68. package/dist/shortcuts/project/operations/write.js +266 -0
  69. package/dist/shortcuts/project/operations.js +8 -0
  70. package/dist/shortcuts/workflow/continuation.js +508 -0
  71. package/dist/shortcuts/workflow/endpoints.js +149 -0
  72. package/dist/shortcuts/workflow/errors.js +112 -0
  73. package/dist/shortcuts/workflow/host.js +224 -0
  74. package/dist/shortcuts/workflow/index.js +116 -0
  75. package/dist/shortcuts/workflow/manifest.js +30 -0
  76. package/dist/shortcuts/workflow/operations/form.js +4159 -0
  77. package/dist/shortcuts/workflow/operations/read.js +3778 -0
  78. package/dist/shortcuts/workflow/operations/registry.js +33 -0
  79. package/dist/shortcuts/workflow/operations/shared.js +167 -0
  80. package/dist/shortcuts/workflow/operations/types.js +44 -0
  81. package/dist/shortcuts/workflow/operations/write.js +1991 -0
  82. package/dist/shortcuts/workflow/operations.js +119 -0
  83. package/dist/shortcuts/workflow/state.js +182 -0
  84. package/docs/SKILL.md +5 -3
  85. package/docs/_catalog.md +10 -1
  86. package/docs/agent-invoice.md +2 -2
  87. package/docs/agent-skill-install.md +2 -2
  88. package/docs/e10-auth.md +3 -1
  89. package/docs/ebuilder-form.md +38 -0
  90. package/docs/im.md +104 -0
  91. package/docs/invoice.md +5 -5
  92. package/docs/okr.md +122 -0
  93. package/docs/operation-manual.md +10 -7
  94. package/docs/project.md +69 -0
  95. package/docs/skill-review-2026-09-19.md +68 -0
  96. package/package.json +3 -2
  97. package/scripts/package-skill.mjs +38 -11
  98. package/scripts/sync-connector-skills.mjs +172 -0
  99. package/skill-template/business-info.json +357 -16
  100. package/skill-template/domains/ebuilder-form.md +5 -0
  101. package/skill-template/domains/okr.md +18 -0
  102. package/skill-template/domains/shijingran.md +3 -0
  103. package/skill-template/domains/skill-maker.md +4 -4
  104. package/skill-template/domains/workflow.md +22 -0
  105. package/skill-template/domains/yepiaotong.md +4 -2
  106. package/skill-template/domains/yimiaoban.md +13 -10
  107. package/skill-template/product.json +5 -0
  108. package/skill-template/skill-template.md +1 -0
  109. package/skills/weaver-e10-calendar/SKILL.md +5 -1
  110. package/skills/weaver-e10-calendar/references/calendar-query.md +7 -0
  111. package/skills/weaver-e10-calendar/references/source-manifest.json +314 -32
  112. package/skills/weaver-e10-ebuilder-form/SKILL.md +123 -0
  113. package/skills/weaver-e10-ebuilder-form/references/context-routing.md +90 -0
  114. package/skills/weaver-e10-ebuilder-form/references/custom-api.md +86 -0
  115. package/skills/weaver-e10-ebuilder-form/references/disabled-capabilities.md +50 -0
  116. package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +100 -0
  117. package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +91 -0
  118. package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +74 -0
  119. package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +86 -0
  120. package/skills/weaver-e10-ebuilder-form/references/source-manifest.json +107 -0
  121. package/skills/weaver-e10-esb/SKILL.md +1 -1
  122. package/skills/weaver-e10-esb/references/source-manifest.json +15 -14
  123. package/skills/weaver-e10-hrm/SKILL.md +1 -1
  124. package/skills/weaver-e10-hrm/references/source-manifest.json +357 -38
  125. package/skills/weaver-e10-jiuchuanhui/SKILL.md +22 -4
  126. package/skills/weaver-e10-jiuchuanhui/references/clue.md +4 -2
  127. package/skills/weaver-e10-jiuchuanhui/references/contact.md +1 -1
  128. package/skills/weaver-e10-jiuchuanhui/references/customer.md +3 -3
  129. package/skills/weaver-e10-jiuchuanhui/references/disabled-capabilities.md +1 -1
  130. package/skills/weaver-e10-jiuchuanhui/references/discovery-config.md +10 -10
  131. package/skills/weaver-e10-jiuchuanhui/references/general-helpers.md +3 -3
  132. package/skills/weaver-e10-jiuchuanhui/references/sale.md +7 -7
  133. package/skills/weaver-e10-jiuchuanhui/references/source-manifest.json +3 -3
  134. package/skills/weaver-e10-jucailin/SKILL.md +2 -2
  135. package/skills/weaver-e10-mail/SKILL.md +22 -6
  136. package/skills/weaver-e10-meeting/SKILL.md +22 -1
  137. package/skills/weaver-e10-okr/SKILL.md +139 -0
  138. package/skills/weaver-e10-okr/references/okr-align.md +59 -0
  139. package/skills/weaver-e10-okr/references/okr-keyresult.md +68 -0
  140. package/skills/weaver-e10-okr/references/okr-link-routing.md +67 -0
  141. package/skills/weaver-e10-okr/references/okr-query.md +105 -0
  142. package/skills/weaver-e10-okr/references/okr-write.md +94 -0
  143. package/skills/weaver-e10-okr/references/source-manifest.json +672 -0
  144. package/skills/weaver-e10-plan/SKILL.md +3 -3
  145. package/skills/weaver-e10-plan/references/plan-report-write.md +1 -1
  146. package/skills/weaver-e10-plan/references/source-manifest.json +20 -20
  147. package/skills/weaver-e10-qiyecheng/SKILL.md +21 -1
  148. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +17 -17
  149. package/skills/weaver-e10-shared/SKILL.md +79 -11
  150. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +41 -8
  151. package/skills/weaver-e10-shared/references/non-interactive-environment.md +78 -0
  152. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +39 -0
  153. package/skills/weaver-e10-shijingran/SKILL.md +83 -0
  154. package/skills/weaver-e10-shijingran/references/field-resolution.md +105 -0
  155. package/skills/weaver-e10-shijingran/references/operations.md +154 -0
  156. package/skills/weaver-e10-shijingran/references/source-manifest.json +1380 -0
  157. package/skills/weaver-e10-shijingran/references/write-operations.md +90 -0
  158. package/skills/weaver-e10-skill-maker/SKILL.md +26 -9
  159. package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +39 -8
  160. package/skills/weaver-e10-skill-maker/references/detector-validation.md +25 -8
  161. package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +66 -5
  162. package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +86 -0
  163. package/skills/weaver-e10-skill-maker/references/source-update-detection.md +59 -5
  164. package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +16 -8
  165. package/skills/weaver-e10-wenshuding/SKILL.md +28 -4
  166. package/skills/weaver-e10-wenshuding/references/archive-search.md +14 -0
  167. package/skills/weaver-e10-wenshuding/references/source-manifest.json +27 -26
  168. package/skills/weaver-e10-workflow/SKILL.md +250 -0
  169. package/skills/weaver-e10-workflow/references/source-manifest.json +1062 -0
  170. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +96 -0
  171. package/skills/weaver-e10-workflow/references/workflow-batch.md +275 -0
  172. package/skills/weaver-e10-workflow/references/workflow-create.md +182 -0
  173. package/skills/weaver-e10-workflow/references/workflow-edit.md +106 -0
  174. package/skills/weaver-e10-workflow/references/workflow-memory.md +165 -0
  175. package/skills/weaver-e10-workflow/references/workflow-operate.md +153 -0
  176. package/skills/weaver-e10-workflow/references/workflow-query.md +821 -0
  177. package/skills/weaver-e10-workflow/references/workflow-share.md +117 -0
  178. package/skills/weaver-e10-workflow/references/workflow-view.md +189 -0
  179. package/skills/weaver-e10-yepiaotong/SKILL.md +28 -28
  180. package/skills/weaver-e10-yepiaotong/references/invoice-disabled-capabilities.md +11 -5
  181. package/skills/weaver-e10-yepiaotong/references/invoice-import.md +14 -8
  182. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +9 -43
  183. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +8 -0
  184. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +13 -17
  185. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +6 -7
  186. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +2 -2
  187. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +1155 -553
  188. package/skills/weaver-e10-yimiaoban/SKILL.md +56 -38
  189. package/skills/weaver-e10-yimiaoban/references/ding-write.md +8 -8
  190. package/skills/weaver-e10-yimiaoban/references/error-codes.md +16 -0
  191. package/skills/weaver-e10-yimiaoban/references/field-resolution.md +10 -10
  192. package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +12 -12
  193. package/skills/weaver-e10-yimiaoban/references/group-read.md +16 -16
  194. package/skills/weaver-e10-yimiaoban/references/group-write.md +17 -15
  195. package/skills/weaver-e10-yimiaoban/references/msg-read.md +21 -17
  196. package/skills/weaver-e10-yimiaoban/references/msg-write.md +10 -10
  197. package/skills/weaver-e10-yimiaoban/references/person.md +6 -6
  198. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +15 -11
  199. package/skills/weaver-e10-yimiaoban/references/session-sysmsg.md +11 -10
  200. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +2164 -154
  201. package/skills/weaver-e10-yimiaoban/references/user-remind.md +75 -0
  202. package/skills/weaver-e10-ziguanjia/SKILL.md +4 -2
  203. package/skills/weaver-e10-ziguanjia/references/source-manifest.json +99 -29
  204. package/tools/weaver-skill-detector-1.0.13/SKILL.md +253 -0
  205. package/tools/weaver-skill-detector-1.0.13/_meta.json +6 -0
  206. package/tools/weaver-skill-detector-1.0.13/references/checklist.md +298 -0
  207. package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +4190 -0
  208. package/dist/shortcuts/yimiaoban/operations/shared.js +0 -236
  209. package/docs/yimiaoban.md +0 -86
  210. package/skills/weaver-e10-calendar/product.json +0 -8
  211. package/skills/weaver-e10-esb/product.json +0 -8
  212. package/skills/weaver-e10-hrm/product.json +0 -8
  213. package/skills/weaver-e10-jiuchuanhui/product.json +0 -8
  214. package/skills/weaver-e10-jucailin/product.json +0 -8
  215. package/skills/weaver-e10-mail/product.json +0 -8
  216. package/skills/weaver-e10-meeting/product.json +0 -8
  217. package/skills/weaver-e10-plan/product.json +0 -8
  218. package/skills/weaver-e10-qiyecheng/product.json +0 -8
  219. package/skills/weaver-e10-skill-maker/product.json +0 -8
  220. package/skills/weaver-e10-wenshuding/product.json +0 -8
  221. package/skills/weaver-e10-yepiaotong/product.json +0 -8
  222. package/skills/weaver-e10-yepiaotong/references/invoice-red.md +0 -261
  223. package/skills/weaver-e10-yimiaoban/product.json +0 -8
  224. package/skills/weaver-e10-ziguanjia/product.json +0 -8
  225. /package/dist/shortcuts/{yimiaoban → im}/operations/msg-parse.js +0 -0
@@ -0,0 +1,305 @@
1
+ import { isOkrErrorType, okrApiError } from '../errors.js';
2
+ import { businessMessage, isDatajsonSuccess } from '../host.js';
3
+ import { compact, ebMainTables, optionValue } from './shared.js';
4
+ /** ebuilder「OKR 目标」应用标签(源资料固定值)。 */
5
+ const OKR_APP_TAG = 'weaver-wr-goal-eb';
6
+ /** ebuilder「OKR 目标详情」表单标签(源资料固定值)。 */
7
+ export const OKR_EB_FORM_TAG = 'uf_wrgm_baseinfo';
8
+ const VERSION_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
9
+ /**
10
+ * 源资料固定映射:租户 tqasclatif 的 okr 目标详情 eb 表单 id 无需动态获取。
11
+ * 该租户命中时跳过 getAppIds / getObjsByTag 两步解析。
12
+ */
13
+ const EB_FORM_ID_FIXED = {
14
+ tqasclatif: '1027322801024458753',
15
+ };
16
+ export function okrVersionCacheKey(tenantKey) {
17
+ return `okr:version:${tenantKey}`;
18
+ }
19
+ export function okrEbFormCacheKey(tenantKey) {
20
+ return `okr:ebform:${tenantKey}`;
21
+ }
22
+ /**
23
+ * 源资料路由规则:`ver_name >= V2` → e10-ebuilder 链路,其它情况 → e10 标准版链路。
24
+ * 兼容 `V2` / `v2` / `V14` / `2` 等写法,只比较主版本号。
25
+ */
26
+ export function isEbVersion(verName) {
27
+ if (typeof verName !== 'string')
28
+ return false;
29
+ const match = /^[vV]?(\d+)/.exec(verName.trim());
30
+ if (!match)
31
+ return false;
32
+ return Number(match[1]) >= 2;
33
+ }
34
+ /**
35
+ * 链路判定:优先读租户隔离、有效期 1 天的版本判定缓存;未命中或已过期才调用 okr_searchAppver 取
36
+ * `ver_name`,并把结果写回租户缓存。
37
+ *
38
+ * 只有真正拿到版本答案时才写缓存:接口不可用(标准版租户通常没有该 ebuilder 接口)时降级为标准版
39
+ * 链路并如实说明,不写缓存、不硬编码链路。
40
+ */
41
+ export async function resolveLink(host, options = {}) {
42
+ const session = await host.getSession();
43
+ const key = okrVersionCacheKey(session.tenantKey);
44
+ if (!options.refresh) {
45
+ const cached = await host.getCache(key);
46
+ const value = cached && typeof cached === 'object' ? cached : null;
47
+ if (value && (value.link === 'standard' || value.link === 'eb')) {
48
+ return {
49
+ link: value.link,
50
+ verName: value.verName ?? null,
51
+ tenantKey: session.tenantKey,
52
+ cached: true,
53
+ degraded: false,
54
+ reason: null,
55
+ checkedAt: typeof value.checkedAt === 'string' ? value.checkedAt : new Date().toISOString(),
56
+ };
57
+ }
58
+ }
59
+ let verName = null;
60
+ let degraded = false;
61
+ let reason = null;
62
+ try {
63
+ const response = await host.request({
64
+ method: 'POST',
65
+ path: '/api/ebuilder/form/formdata/v2/getFormDataList/okr_searchAppver',
66
+ operation: 'okr.version.check',
67
+ body: {
68
+ datajson: {
69
+ mainTable: {},
70
+ pageInfo: { pageNo: '1', pageSize: '10' },
71
+ header: { operator: session.userId },
72
+ },
73
+ },
74
+ });
75
+ const mainTable = ebMainTables(response)[0];
76
+ verName = optionValue(mainTable?.ver_name) ?? null;
77
+ }
78
+ catch (error) {
79
+ if (isOkrErrorType(error, 'api') || isOkrErrorType(error, 'network')) {
80
+ degraded = true;
81
+ reason = error.message;
82
+ }
83
+ else {
84
+ throw error;
85
+ }
86
+ }
87
+ const link = isEbVersion(verName) ? 'eb' : 'standard';
88
+ const info = {
89
+ link,
90
+ verName,
91
+ tenantKey: session.tenantKey,
92
+ cached: false,
93
+ degraded,
94
+ reason,
95
+ checkedAt: new Date().toISOString(),
96
+ };
97
+ if (!degraded)
98
+ await host.setCache(key, info, VERSION_CACHE_TTL_MS);
99
+ return info;
100
+ }
101
+ function firstId(value) {
102
+ if (Array.isArray(value) && value.length > 0) {
103
+ const first = value[0];
104
+ if (typeof first === 'string' || typeof first === 'number')
105
+ return String(first);
106
+ if (first && typeof first === 'object') {
107
+ const record = first;
108
+ const candidate = record.id ?? record.objId ?? record.idobjId ?? record.value;
109
+ if (candidate !== undefined && candidate !== null && candidate !== '')
110
+ return String(candidate);
111
+ }
112
+ }
113
+ if (typeof value === 'string' || typeof value === 'number')
114
+ return String(value);
115
+ return undefined;
116
+ }
117
+ /** getObjsByTag 返回的 data 数组中按 tag 命中的那条记录的 objId(源资料:eb 表单 id 指 id/objId)。 */
118
+ export function pickObjIdByTag(value, formTag) {
119
+ const root = value && typeof value === 'object' && 'datajson' in value
120
+ ? value.datajson
121
+ : value;
122
+ const data = root?.data;
123
+ if (!Array.isArray(data))
124
+ return firstId(root);
125
+ const objects = data.filter((item) => item && typeof item === 'object');
126
+ if (objects.length > 0) {
127
+ const tagged = objects.filter((item) => item.tag !== undefined && item.tag !== null);
128
+ const matched = tagged.find((item) => String(item.tag) === formTag);
129
+ if (matched)
130
+ return firstId([matched]);
131
+ // 响应带 tag 但没有一个是目标表单:说明表单不存在,返回 undefined 而不是猜一个表单 id。
132
+ if (tagged.length > 0)
133
+ return undefined;
134
+ // 响应结构里没有 tag:接口只返回一条时回落到首个元素。
135
+ return firstId(objects);
136
+ }
137
+ return firstId(data);
138
+ }
139
+ /** 获取 eb 目标详情页所需的表单 id(源资料:eb 表单 id 指 id/objId,不是 formId)。 */
140
+ export async function resolveEbFormId(host) {
141
+ const session = await host.getSession();
142
+ const templateOf = (formId) => `/sp/ebdfpage/card/0/${formId}/{goalId}`;
143
+ const fixed = EB_FORM_ID_FIXED[session.tenantKey];
144
+ if (fixed) {
145
+ return {
146
+ appTag: OKR_APP_TAG,
147
+ appId: null,
148
+ formTag: OKR_EB_FORM_TAG,
149
+ formId: fixed,
150
+ source: 'fixed',
151
+ detailUrlTemplate: templateOf(fixed),
152
+ };
153
+ }
154
+ // 源资料:取得当前租户的 okr 目标详情 eb 表单 id 后长期缓存,后续不再动态获取。
155
+ const key = okrEbFormCacheKey(session.tenantKey);
156
+ const cached = await host.getCache(key);
157
+ const cachedValue = cached && typeof cached === 'object' ? cached : null;
158
+ if (cachedValue && typeof cachedValue.formId === 'string' && cachedValue.formId) {
159
+ return {
160
+ appTag: OKR_APP_TAG,
161
+ appId: typeof cachedValue.appId === 'string' ? cachedValue.appId : null,
162
+ formTag: OKR_EB_FORM_TAG,
163
+ formId: cachedValue.formId,
164
+ source: 'cache',
165
+ detailUrlTemplate: templateOf(cachedValue.formId),
166
+ };
167
+ }
168
+ const appIdsResponse = await host.request({
169
+ method: 'GET',
170
+ path: '/api/bs/ebuilder/app/tags/getAppIds',
171
+ query: { tag: OKR_APP_TAG },
172
+ operation: 'okr.eb.form.resolve',
173
+ }).catch(() => undefined);
174
+ const appId = firstId(appIdsResponse?.data);
175
+ if (!appId) {
176
+ throw okrApiError('eb_app_not_found', `未检测到「OKR 目标」ebuilder 应用(appTag: ${OKR_APP_TAG}),无法生成目标详情页链接`);
177
+ }
178
+ const formResponse = await host.request({
179
+ method: 'GET',
180
+ path: '/api/ebuilder/form/obj/getObjsByTag',
181
+ query: { tag: OKR_EB_FORM_TAG, appId },
182
+ operation: 'okr.eb.form.resolve',
183
+ }).catch(() => undefined);
184
+ const formId = pickObjIdByTag(formResponse, OKR_EB_FORM_TAG);
185
+ if (!formId) {
186
+ throw okrApiError('eb_form_not_found', `未找到目标详情 ebuilder 表单(tag: ${OKR_EB_FORM_TAG}),无法生成目标详情页链接`);
187
+ }
188
+ const info = {
189
+ appTag: OKR_APP_TAG,
190
+ appId,
191
+ formTag: OKR_EB_FORM_TAG,
192
+ formId,
193
+ source: 'dynamic',
194
+ detailUrlTemplate: templateOf(formId),
195
+ };
196
+ await host.setCache(key, { appId, formId });
197
+ return info;
198
+ }
199
+ /** 标准版目标详情页地址(源资料固定格式)。 */
200
+ export function buildStandardDetailPath(goalId) {
201
+ return `/sp/goal/openDetail?id=${goalId}`;
202
+ }
203
+ /**
204
+ * 把站内相对路径拼成可直接点击的绝对地址(列表表格、详情返回与写入回执统一使用绝对地址)。
205
+ * 已经是绝对地址时原样返回,链接缺失时返回 null 而不是伪造地址。
206
+ */
207
+ export function okrAbsoluteUrl(baseUrl, path) {
208
+ if (!path)
209
+ return null;
210
+ if (/^https?:\/\//iu.test(path))
211
+ return path;
212
+ const origin = String(baseUrl ?? '').replace(/\/+$/u, '');
213
+ const suffix = path.startsWith('/') ? path : `/${path}`;
214
+ return `${origin}${suffix}`;
215
+ }
216
+ /**
217
+ * 创建详情页链接解析器。eb 链路需要先解析表单 id,属于附加信息:
218
+ * 解析失败时只记警告并返回 null,绝不让主查询/主写入失败或被重试(源资料强制「链接暂不可用」语义)。
219
+ */
220
+ export async function createDetailUrlResolver(host, link) {
221
+ const warnings = [];
222
+ if (link === 'standard') {
223
+ return {
224
+ warnings,
225
+ async resolve(goalId) {
226
+ return goalId ? buildStandardDetailPath(goalId) : null;
227
+ },
228
+ };
229
+ }
230
+ let formId = null;
231
+ let resolved = false;
232
+ return {
233
+ warnings,
234
+ async resolve(goalId) {
235
+ if (!goalId)
236
+ return null;
237
+ if (!resolved) {
238
+ resolved = true;
239
+ try {
240
+ formId = (await resolveEbFormId(host)).formId;
241
+ }
242
+ catch (error) {
243
+ warnings.push(`目标详情页链接暂不可用:${error.message}`);
244
+ formId = null;
245
+ }
246
+ }
247
+ return formId ? `/sp/ebdfpage/card/0/${formId}/${goalId}` : null;
248
+ },
249
+ };
250
+ }
251
+ /** 只读取目标详情的 ebuilder / 标准版原始响应,供写入前合并使用。 */
252
+ export async function fetchGoalRaw(host, link, goalId) {
253
+ const session = await host.getSession();
254
+ if (link === 'standard') {
255
+ const response = await host.request({
256
+ method: 'GET',
257
+ path: `/api/workrelate/goal/getObjectDetail/${goalId}`,
258
+ operation: 'okr.get',
259
+ });
260
+ return response?.data?.obj ?? null;
261
+ }
262
+ const response = await host.request({
263
+ method: 'POST',
264
+ path: '/api/ebuilder/form/formdata/v2/getFormDataByPk/okr_queryGoal',
265
+ operation: 'okr.get',
266
+ body: {
267
+ datajson: {
268
+ mainTable: { id: goalId },
269
+ header: { operator: session.userId },
270
+ },
271
+ },
272
+ });
273
+ if (!isDatajsonSuccess(response)) {
274
+ throw okrApiError('business_error', businessMessage(response), { response: businessMessage(response) });
275
+ }
276
+ return ebMainTables(response)[0] ?? null;
277
+ }
278
+ /** 从目标详情中取出负责人人员 id(对齐目标新增时用于补全双方负责人)。 */
279
+ export function goalPrincipalId(raw, link) {
280
+ if (!raw || typeof raw !== 'object')
281
+ return null;
282
+ if (link === 'standard') {
283
+ const value = raw.principalid;
284
+ return value === undefined || value === null || value === '' ? null : String(value);
285
+ }
286
+ return optionValue(raw.principalid) ?? null;
287
+ }
288
+ /** 标准版新建/编辑请求体构造(源资料 workrelate/goal/create|update 入参)。 */
289
+ export function buildStandardSaveBody(input) {
290
+ return compact({
291
+ ...(input.goalId ? { id: input.goalId } : {}),
292
+ name: input.name,
293
+ scopeId: input.scopeId,
294
+ ...(input.scopeId === '2' && input.scopeDataId ? { scopeDataId: input.scopeDataId } : {}),
295
+ periodType: input.periodType,
296
+ periodRange: input.periodRange,
297
+ ...(input.periodType === '2' && input.periodQuarter ? { periodQuarter: input.periodQuarter } : {}),
298
+ principalid: input.principalid,
299
+ ...(input.partners ? { partners: input.partners } : {}),
300
+ ...(input.remark === undefined ? {} : { remark: input.remark }),
301
+ ...(input.keyresultList ? { keyresultList: input.keyresultList } : {}),
302
+ status: input.status,
303
+ parentId: input.parentId ?? '0',
304
+ });
305
+ }