weaver-work-cli 0.1.31 → 0.1.33

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 (186) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/{archive-U766FTFH.js → archive-FVFY6GZN.js} +2 -2
  3. package/dist/chunks/{archive-oa-DMWEKX3L.js → archive-oa-NW3OD4UV.js} +2 -2
  4. package/dist/chunks/{asset-TCR7VDEV.js → asset-7QJKMIDV.js} +2 -2
  5. package/dist/chunks/{attachment-content-AQNX5N3S.js → attachment-content-OSAVA6K3.js} +3 -2
  6. package/dist/chunks/{blog-EVZWGDVM.js → blog-I7SDPNW4.js} +2 -2
  7. package/dist/chunks/{caizhilian-JOWS6SL5.js → caizhilian-O37ZIQNY.js} +2 -2
  8. package/dist/chunks/{calendar-5WNCV66Q.js → calendar-7KXE4ED3.js} +2 -2
  9. package/dist/chunks/{chunk-VZTXRG6X.js → chunk-2FLWXFVS.js} +4 -4
  10. package/dist/chunks/{chunk-QWY6PGL6.js → chunk-2LV74IWP.js} +361 -56
  11. package/dist/chunks/chunk-3SO6QL6U.js +73 -0
  12. package/dist/chunks/{chunk-H3WDBYJW.js → chunk-6ATGWRZM.js} +6 -4
  13. package/dist/chunks/chunk-BYATLLEF.js +68 -0
  14. package/dist/chunks/chunk-BYBSCN4X.js +932 -0
  15. package/dist/chunks/{chunk-324YPTC2.js → chunk-D223PTXU.js} +11 -2
  16. package/dist/chunks/{chunk-R2IJAK7T.js → chunk-EEWPQE3O.js} +2 -2
  17. package/dist/chunks/{chunk-J7RJTZSV.js → chunk-GFPXQIY2.js} +2 -2
  18. package/dist/chunks/{chunk-AC7KJWC5.js → chunk-HEL5XTYI.js} +12 -6
  19. package/dist/chunks/{chunk-CVZ2JOSW.js → chunk-IHUYP6LO.js} +1 -1
  20. package/dist/chunks/{chunk-R7O5PUWO.js → chunk-ILMBNVSG.js} +2 -2
  21. package/dist/chunks/{chunk-6V7ZLF34.js → chunk-KAS45KNR.js} +1 -1
  22. package/dist/chunks/{chunk-H6XSTSLM.js → chunk-MEEFGWTM.js} +54 -196
  23. package/dist/chunks/{chunk-GCG2NMWR.js → chunk-MQ2I5AA3.js} +4 -2
  24. package/dist/chunks/chunk-NHA62QD7.js +774 -0
  25. package/dist/chunks/{chunk-2DUV44UX.js → chunk-OCU4RLHC.js} +641 -309
  26. package/dist/chunks/{chunk-65QMVWHS.js → chunk-PRHJGPMA.js} +2 -2
  27. package/dist/chunks/{chunk-WHD4XMRP.js → chunk-Q6LWB5HX.js} +2 -2
  28. package/dist/chunks/{chunk-D4LTJSJD.js → chunk-RBGOMK4Y.js} +50 -33
  29. package/dist/chunks/chunk-VBCFFFGT.js +226 -0
  30. package/dist/chunks/{ebuilder-form-NJ4YK6CC.js → chunk-WRRJ4GG2.js} +22 -1148
  31. package/dist/chunks/{chunk-RCGYCOMG.js → chunk-WY74UBJ6.js} +264 -750
  32. package/dist/chunks/conflict-SFNEVJY5.js +21 -0
  33. package/dist/chunks/continuation-RN6PZN2M.js +11 -0
  34. package/dist/chunks/cowork-CKWYHXYB.js +2508 -0
  35. package/dist/chunks/ebuilder-form-KOLJRVZD.js +121 -0
  36. package/dist/chunks/{ehr-MMYN36VA.js → ehr-WFOC3B4D.js} +1174 -20
  37. package/dist/chunks/{esb-HIWHOU7Q.js → esb-LJZTN663.js} +4 -4
  38. package/dist/chunks/{fna-KBACQTA5.js → fna-F7QRIIZC.js} +2 -2
  39. package/dist/chunks/{host-3OHS5QUX.js → host-BCGUVEWX.js} +3 -3
  40. package/dist/chunks/host-BQBRHVR3.js +23 -0
  41. package/dist/chunks/{host-KQL5N4HO.js → host-DGE2TZD4.js} +3 -3
  42. package/dist/chunks/{host-LLSZQCWR.js → host-KXPTEWFS.js} +3 -3
  43. package/dist/chunks/{host-IG6KEH5Q.js → host-VQ6JJXGQ.js} +3 -3
  44. package/dist/chunks/{hrm-LYEC67ZQ.js → hrm-NI6XAKW5.js} +3 -3
  45. package/dist/chunks/{im-RN2UKAEU.js → im-7TRTF3KT.js} +88 -12
  46. package/dist/chunks/{invoice-EEPHLAF6.js → invoice-AOXWJKYT.js} +3 -3
  47. package/dist/chunks/{jiuchuanhui-WVVZYSJE.js → jiuchuanhui-7NQWEZAW.js} +2 -2
  48. package/dist/chunks/{lazy-dispatch-MDOFFL2S.js → lazy-dispatch-RNS4EE4S.js} +4 -4
  49. package/dist/chunks/{mail-LNQLTF6L.js → mail-VDHJAB4O.js} +3 -3
  50. package/dist/chunks/{meeting-XSD3BDVQ.js → meeting-GA7XCNNP.js} +214 -43
  51. package/dist/chunks/{okr-TMWTIU2K.js → okr-TQIRERPQ.js} +2 -2
  52. package/dist/chunks/operations-5QL3AECO.js +11 -0
  53. package/dist/chunks/{plan-A2FSFA7T.js → plan-4RY4LN2P.js} +2 -2
  54. package/dist/chunks/{project-T26QLBQF.js → project-D6XT2OC5.js} +2 -2
  55. package/dist/chunks/{registry-JCFEYXOE.js → registry-JHRIDQ3A.js} +4 -4
  56. package/dist/chunks/{registry-2VLUAESA.js → registry-OZSMDVPP.js} +2 -2
  57. package/dist/chunks/{registry-ZJMJVWFA.js → registry-QKMI43Q6.js} +8 -6
  58. package/dist/chunks/{registry-Q7OQJ3SU.js → registry-VOGKFFTR.js} +2 -2
  59. package/dist/chunks/{room-recommend-UR4ZDZS6.js → room-recommend-D4EUOOWY.js} +4 -3
  60. package/dist/chunks/{schedule-5L2PM4M6.js → schedule-XPFBHPCV.js} +4 -3
  61. package/dist/chunks/{workflow-TR6PG2SL.js → workflow-HLBZRWIY.js} +172 -6
  62. package/dist/core/package-paths.js +16 -2
  63. package/dist/index.js +30 -25
  64. package/dist/internal/e10/auth-recovery.js +14 -4
  65. package/dist/shortcuts/contract/host.js +34 -59
  66. package/dist/shortcuts/cowork/continuation.js +70 -0
  67. package/dist/shortcuts/cowork/errors.js +59 -0
  68. package/dist/shortcuts/cowork/host.js +172 -0
  69. package/dist/shortcuts/cowork/index.js +166 -0
  70. package/dist/shortcuts/cowork/manifest.js +65 -0
  71. package/dist/shortcuts/cowork/operations/discuss-write.js +277 -0
  72. package/dist/shortcuts/cowork/operations/item-write.js +380 -0
  73. package/dist/shortcuts/cowork/operations/member-write.js +283 -0
  74. package/dist/shortcuts/cowork/operations/permission-write.js +286 -0
  75. package/dist/shortcuts/cowork/operations/read.js +423 -0
  76. package/dist/shortcuts/cowork/operations/registry.js +39 -0
  77. package/dist/shortcuts/cowork/operations/review-write.js +157 -0
  78. package/dist/shortcuts/cowork/operations/shared.js +215 -0
  79. package/dist/shortcuts/cowork/operations/types.js +24 -0
  80. package/dist/shortcuts/cowork/operations.js +19 -0
  81. package/dist/shortcuts/ehr/host.js +4 -1
  82. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +757 -0
  83. package/dist/shortcuts/ehr/operations/recruit-position.js +367 -0
  84. package/dist/shortcuts/ehr/operations/recruit-stats.js +133 -0
  85. package/dist/shortcuts/ehr/operations/recruit-write.js +8 -16
  86. package/dist/shortcuts/ehr/operations/recruit.js +35 -10
  87. package/dist/shortcuts/ehr/operations/registry.js +6 -0
  88. package/dist/shortcuts/im/diagnostics.js +97 -0
  89. package/dist/shortcuts/im/host.js +58 -31
  90. package/dist/shortcuts/im/index.js +7 -2
  91. package/dist/shortcuts/im/operations/at-mention.js +127 -0
  92. package/dist/shortcuts/im/operations/file-user.js +10 -2
  93. package/dist/shortcuts/im/operations/group-read.js +26 -5
  94. package/dist/shortcuts/im/operations/group-write.js +35 -28
  95. package/dist/shortcuts/im/operations/msg-sync.js +7 -2
  96. package/dist/shortcuts/im/operations/msg-write.js +76 -10
  97. package/dist/shortcuts/im/operations/quote-mention.js +119 -0
  98. package/dist/shortcuts/im/operations/session.js +1 -1
  99. package/dist/shortcuts/im/operations/shared.js +10 -0
  100. package/dist/shortcuts/im/operations/types.js +13 -0
  101. package/dist/shortcuts/index.js +5 -0
  102. package/dist/shortcuts/mail/host.js +4 -1
  103. package/dist/shortcuts/meeting/host.js +27 -34
  104. package/dist/shortcuts/meeting/operations/create.js +4 -1
  105. package/dist/shortcuts/meeting/operations/eb/catalog.js +5 -0
  106. package/dist/shortcuts/meeting/operations/eb/conflict.js +78 -7
  107. package/dist/shortcuts/meeting/operations/eb/create-flow.js +168 -26
  108. package/dist/shortcuts/meeting/operations/eb/factory.js +69 -1
  109. package/dist/shortcuts/meeting/operations/eb/index.js +16 -3
  110. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +14 -3
  111. package/dist/shortcuts/meeting/operations/eb-fallback.js +159 -0
  112. package/dist/shortcuts/meeting/operations/env.js +93 -46
  113. package/dist/shortcuts/meeting/operations/form-fields.js +110 -0
  114. package/dist/shortcuts/meeting/operations/registry.js +2 -0
  115. package/dist/shortcuts/meeting/operations/standard-guard.js +71 -0
  116. package/dist/shortcuts/meeting/operations.js +16 -0
  117. package/dist/shortcuts/workflow/index.js +110 -1
  118. package/dist/shortcuts/workflow/operations/form.js +24 -3
  119. package/dist/shortcuts/workflow/operations/read.js +104 -23
  120. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupRules.js +448 -0
  121. package/dist/shortcuts/workflow/operations/todoSmartConvert/aigroupStore.js +106 -0
  122. package/dist/shortcuts/workflow/operations/todoSmartConvert/businessRules.js +47 -0
  123. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +30 -23
  124. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +1 -0
  125. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +1 -0
  126. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +2 -1
  127. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +2 -4
  128. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +138 -181
  129. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +12 -7
  130. package/docs/e10-auth.md +1 -1
  131. package/docs/im.md +8 -1
  132. package/docs/todo-smart-convert/README.md +1 -1
  133. package/docs/todo-smart-convert/data-contract.md +2 -2
  134. package/docs/todo-smart-convert/subgroup-rules.md +6 -0
  135. package/package.json +1 -1
  136. package/skill-template/domains/yimiaoban.md +3 -3
  137. package/skill-template/skill-template.md +1 -1
  138. package/skills/weaver-e10-blog/SKILL.md +5 -5
  139. package/skills/weaver-e10-caizhilian/SKILL.md +5 -5
  140. package/skills/weaver-e10-calendar/SKILL.md +5 -5
  141. package/skills/weaver-e10-esb/SKILL.md +5 -5
  142. package/skills/weaver-e10-hrm/SKILL.md +5 -5
  143. package/skills/weaver-e10-jinchengda/SKILL.md +2 -2
  144. package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -5
  145. package/skills/weaver-e10-jucailin/SKILL.md +18 -12
  146. package/skills/weaver-e10-jucailin/references/recruit-create.md +104 -0
  147. package/skills/weaver-e10-mail/SKILL.md +5 -5
  148. package/skills/weaver-e10-meeting/SKILL.md +171 -25
  149. package/skills/weaver-e10-meeting/references/meeting-eb.md +4 -3
  150. package/skills/weaver-e10-meeting/references/meeting-queries.md +9 -6
  151. package/skills/weaver-e10-meeting/references/meeting-verification.md +8 -6
  152. package/skills/weaver-e10-meeting.zip +0 -0
  153. package/skills/weaver-e10-okr/SKILL.md +5 -5
  154. package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
  155. package/skills/weaver-e10-plan/SKILL.md +5 -5
  156. package/skills/weaver-e10-shared/SKILL.md +12 -12
  157. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -4
  158. package/skills/weaver-e10-wenshuding/SKILL.md +5 -5
  159. package/skills/weaver-e10-workflow/SKILL.md +29 -5
  160. package/skills/weaver-e10-workflow/aigroup/default.json +88 -0
  161. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +66 -14
  162. package/skills/weaver-e10-workflow/references/workflow-agent-entry.md +1 -1
  163. package/skills/weaver-e10-workflow/references/workflow-memory.md +1 -1
  164. package/skills/weaver-e10-workflow/references/workflow-query.md +12 -10
  165. package/skills/weaver-e10-workflow/references/workflow-view.md +2 -2
  166. package/skills/weaver-e10-workflow/tools/todo-serve.cjs +239 -0
  167. package/skills/weaver-e10-workflow/{scripts → tools}/todo-summary.cjs +218 -28
  168. package/skills/weaver-e10-yepiaotong/SKILL.md +10 -8
  169. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +7 -7
  170. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +10 -10
  171. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +40 -37
  172. package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +4 -4
  173. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +27 -38
  174. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +4 -4
  175. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +37 -29
  176. package/skills/weaver-e10-yimiaoban/SKILL.md +156 -33
  177. package/skills/weaver-e10-yimiaoban/references/ding-write.md +1 -1
  178. package/skills/weaver-e10-yimiaoban/references/error-codes.md +5 -1
  179. package/skills/weaver-e10-yimiaoban/references/group-read.md +5 -1
  180. package/skills/weaver-e10-yimiaoban/references/group-write.md +6 -4
  181. package/skills/weaver-e10-yimiaoban/references/msg-read.md +1 -0
  182. package/skills/weaver-e10-yimiaoban/references/msg-write.md +34 -2
  183. package/skills/weaver-e10-yimiaoban/references/safety-boundaries.md +5 -2
  184. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +79 -58
  185. package/skills/weaver-e10-yimiaoban/references/user-remind.md +2 -2
  186. package/skills/weaver-e10-ziguanjia/SKILL.md +5 -5
@@ -4,11 +4,11 @@ import {
4
4
  E10ApiError,
5
5
  createE10RequestRuntime,
6
6
  requireE10Session
7
- } from "./chunk-H3WDBYJW.js";
7
+ } from "./chunk-6ATGWRZM.js";
8
8
  import {
9
9
  E10_SESSION_EXPIRED_MESSAGE,
10
10
  getActiveProfile
11
- } from "./chunk-324YPTC2.js";
11
+ } from "./chunk-D223PTXU.js";
12
12
  import {
13
13
  CliError,
14
14
  isCliError,
@@ -17,7 +17,7 @@ import {
17
17
  import "./chunk-BUSC6UAE.js";
18
18
 
19
19
  // src/shortcuts/ehr/index.ts
20
- import { readFile as readFile2 } from "node:fs/promises";
20
+ import { readFile as readFile3 } from "node:fs/promises";
21
21
 
22
22
  // src/shortcuts/ehr/continuation.ts
23
23
  import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
@@ -221,7 +221,7 @@ function mapRuntimeNetworkError(error) {
221
221
  function createEhrHost(ctx, dependencies = {}) {
222
222
  let e10Session = null;
223
223
  let sessionContext = null;
224
- const requireSession = dependencies.requireSession || requireE10Session;
224
+ const requireSession = dependencies.requireSession || ((innerCtx) => requireE10Session(innerCtx, { skipProfileEnrichment: true }));
225
225
  async function ensureSession() {
226
226
  if (!e10Session) {
227
227
  e10Session = await requireSession(ctx);
@@ -2876,8 +2876,24 @@ async function fetchListRows(host, objId, listId, body) {
2876
2876
  const hasDisplay = Array.isArray(displayRows) && displayRows.length > 0;
2877
2877
  const rows = hasDisplay ? displayRows : rawRows;
2878
2878
  const countData = countResponse ? normalizePaged(countResponse).data : null;
2879
- const total = countData?.total !== void 0 ? countData.total : rows.length;
2880
- return { rows, displayRows: hasDisplay ? displayRows : null, total };
2879
+ const pageSize = typeof body.pageSize === "number" ? body.pageSize : typeof body.pageSize === "string" ? Number(body.pageSize) || rows.length : rows.length;
2880
+ const countUsable = countData !== null && typeof countData.total === "number";
2881
+ let total;
2882
+ let totalExact;
2883
+ let totalNote;
2884
+ if (countUsable) {
2885
+ total = countData.total;
2886
+ totalExact = true;
2887
+ } else if (rows.length < pageSize) {
2888
+ total = rows.length;
2889
+ totalExact = true;
2890
+ totalNote = "\u8BA1\u6570\u63A5\u53E3\u4E0D\u53EF\u7528\uFF0C\u672C\u9875\u672A\u6EE1\uFF08\u5DF2\u5230\u672B\u9875\uFF09\uFF0C\u603B\u6570\u6309\u5DF2\u53D6\u56DE\u884C\u6570\u5F97\u51FA";
2891
+ } else {
2892
+ total = null;
2893
+ totalExact = false;
2894
+ totalNote = "\u8BA1\u6570\u63A5\u53E3\u4E0D\u53EF\u7528\u4E14\u672C\u9875\u5DF2\u6EE1\uFF0C\u603B\u6570\u4E0D\u53EF\u77E5\uFF08\u53EF\u8C03\u5927 pageSize \u53D6\u56DE\u5168\u90E8\u884C\u6570\uFF09";
2895
+ }
2896
+ return { rows, displayRows: hasDisplay ? displayRows : null, total, totalExact, totalNote };
2881
2897
  }
2882
2898
  var contextResolve = {
2883
2899
  name: "ehr.recruit.context.resolve",
@@ -2942,7 +2958,7 @@ var candidateSearch = {
2942
2958
  pageSize: toNumber(args.pageSize, "pageSize") ?? 10,
2943
2959
  conditions
2944
2960
  });
2945
- const { rows, displayRows, total } = await fetchListRows(env.host, talentObjId, talentList.listId, body);
2961
+ const { rows, displayRows, total, totalExact, totalNote } = await fetchListRows(env.host, talentObjId, talentList.listId, body);
2946
2962
  let creatorNameMap = {};
2947
2963
  if (!displayRows) {
2948
2964
  const pureIds = [...new Set(rows.map((row) => row?.creator).filter(isPlainId).map((value) => String(value).trim()))];
@@ -2987,7 +3003,7 @@ var candidateSearch = {
2987
3003
  createTime: row?.create_time || null
2988
3004
  };
2989
3005
  });
2990
- return ehrSuccess("ehr.recruit.candidate.search", { total, rows: dataRows });
3006
+ return ehrSuccess("ehr.recruit.candidate.search", { total, totalExact, ...totalNote ? { totalNote } : {}, rows: dataRows });
2991
3007
  }
2992
3008
  };
2993
3009
  var candidateList = {
@@ -3032,7 +3048,7 @@ var candidateList = {
3032
3048
  current: toPositiveInt(args.current, "current") ?? 1,
3033
3049
  pageSize: toNumber(args.pageSize, "pageSize") ?? 10
3034
3050
  });
3035
- const { rows, displayRows, total } = await fetchListRows(env.host, formObjId, listParam.listId, body);
3051
+ const { rows, displayRows, total, totalExact, totalNote } = await fetchListRows(env.host, formObjId, listParam.listId, body);
3036
3052
  const outRows = rows.map((row) => {
3037
3053
  const cleaned = { form_data_id: row?.form_data_id || row?.id };
3038
3054
  for (const [key, value] of Object.entries(row || {})) {
@@ -3061,6 +3077,8 @@ var candidateList = {
3061
3077
  return ehrSuccess("ehr.recruit.candidate.list", {
3062
3078
  type,
3063
3079
  total,
3080
+ totalExact,
3081
+ ...totalNote ? { totalNote } : {},
3064
3082
  current: body.current,
3065
3083
  pageSize: body.pageSize,
3066
3084
  rows: outRows
@@ -3364,12 +3382,6 @@ async function resolvePersonId(host, fieldId, keyword) {
3364
3382
  const first = list[0];
3365
3383
  return first ? String(first.id || first.value || "") || null : null;
3366
3384
  }
3367
- async function getInterviewPortalFieldIds(host) {
3368
- const response = await host.request({
3369
- path: "/api/recruit/candidate/getFieldIdsForInterview"
3370
- });
3371
- return response?.data || {};
3372
- }
3373
3385
  async function saveFormData(host, params) {
3374
3386
  const layoutId = params.layoutId || params.formId;
3375
3387
  const customParam = {
@@ -3730,11 +3742,10 @@ async function buildInterviewPlan(env, cache, args) {
3730
3742
  const objId = cacheObjId(cache, "interview_plan", "\u9762\u8BD5\u8BA1\u5212\u8868\u5355");
3731
3743
  const formId = cacheFormId(cache, "interview_plan");
3732
3744
  const fields = cache.fields[objId] || {};
3733
- const portalFields = await getInterviewPortalFieldIds(host);
3734
- const fieldIdOf = (key) => fields[key] || portalFields[key] || "";
3745
+ const fieldIdOf = (key) => fields[key] || "";
3735
3746
  for (const key of INTERVIEW_DATAKEYS) {
3736
3747
  if (!fieldIdOf(key)) {
3737
- throw ehrValidationError("recruit_field_missing", `\u9762\u8BD5\u8BA1\u5212\u8868\u5355\u7F3A\u5C11\u5B57\u6BB5 ${key}\uFF08ds/fields \u4E0E\u95E8\u6237\u5B57\u6BB5\u5747\u89E3\u6790\u4E0D\u5230\uFF09`);
3748
+ throw ehrValidationError("recruit_field_missing", `\u9762\u8BD5\u8BA1\u5212\u8868\u5355\u7F3A\u5C11\u5B57\u6BB5 ${key}\uFF08\u73AF\u5883\u7F13\u5B58 ds/fields \u672A\u89E3\u6790\u5230\uFF0C\u8BF7\u91CD\u5EFA\u73AF\u5883\u7F13\u5B58\u540E\u91CD\u8BD5\uFF09`);
3738
3749
  }
3739
3750
  }
3740
3751
  const typeMap = await getDsOptions(host, objId, fieldIdOf("interview_type"), cache.appId);
@@ -4822,6 +4833,1146 @@ var recruitWriteOperations = [
4822
4833
  feedbackUrgeApply
4823
4834
  ];
4824
4835
 
4836
+ // src/shortcuts/ehr/operations/recruit-stats.ts
4837
+ var STATS_MODULES = {
4838
+ talent: { listKey: "talent", formType: "talent_pool", title: "\u4EBA\u624D\u5E93" },
4839
+ demand: { listKey: "demand", formType: "demand_manage", title: "\u62DB\u8058\u9700\u6C42" },
4840
+ position: { listKey: "position", formType: "position_manage", title: "\u62DB\u8058\u804C\u4F4D" },
4841
+ entry: { listKey: "entry", formType: "entry_manage", title: "\u5165\u804C\u7BA1\u7406" },
4842
+ offer: { listKey: "offer", formType: "offer", title: "\u5F55\u7528\u7BA1\u7406" },
4843
+ interview: {
4844
+ listKey: "interview",
4845
+ formType: "interview_plan",
4846
+ title: "\u9762\u8BD5\u5B89\u6392",
4847
+ note: "\u9762\u8BD5\u7BA1\u7406\u5217\u8868\u53EF\u80FD\u6309\u9875\u9762\u914D\u7F6E\u53EA\u663E\u793A\u8FD1\u671F\u8BB0\u5F55\uFF0C\u8BA1\u6570\u4EC5\u4F9B\u91CF\u7EA7\u53C2\u8003"
4848
+ }
4849
+ };
4850
+ var DEFAULT_MODULES = ["talent", "demand", "position", "entry", "offer"];
4851
+ async function countModule(env, cache, key, pageSize, maxPages) {
4852
+ const cfg = STATS_MODULES[key];
4853
+ const list = cache.lists[cfg.listKey];
4854
+ const objId = cache.forms[cfg.formType]?.objId;
4855
+ if (!list?.listId || !objId) {
4856
+ return {
4857
+ key,
4858
+ module: cfg.title,
4859
+ available: false,
4860
+ total: null,
4861
+ totalExact: false,
4862
+ scannedRows: 0,
4863
+ note: "\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u8BE5\u529F\u80FD\u83DC\u5355\uFF08\u672A\u627E\u5230\u5217\u8868\u6216\u8868\u5355\uFF09\uFF0C\u5DF2\u8DF3\u8FC7"
4864
+ };
4865
+ }
4866
+ const baseBody = buildListBody({
4867
+ listId: list.listId,
4868
+ cusMenuId: list.cusMenuId,
4869
+ menuName: list.menuName || cfg.title,
4870
+ title: cfg.title,
4871
+ pageSize
4872
+ });
4873
+ let scanned = 0;
4874
+ let total = null;
4875
+ let totalExact = false;
4876
+ let note = cfg.note;
4877
+ for (let current = 1; current <= maxPages; current++) {
4878
+ const page = await fetchListRows(env.host, objId, list.listId, { ...baseBody, current, pageSize });
4879
+ if (current === 1 && page.total !== null && page.totalExact) {
4880
+ total = page.total;
4881
+ totalExact = true;
4882
+ break;
4883
+ }
4884
+ scanned += page.rows.length;
4885
+ if (page.rows.length < pageSize) {
4886
+ total = scanned;
4887
+ totalExact = true;
4888
+ break;
4889
+ }
4890
+ }
4891
+ if (total === null) {
4892
+ totalExact = false;
4893
+ note = `\u8BA1\u6570\u63A5\u53E3\u4E0D\u53EF\u7528\u4E14\u8FBE\u626B\u63CF\u4E0A\u9650\uFF08${maxPages} \u9875 \xD7 ${pageSize} \u884C\uFF09\u4ECD\u672A\u53D6\u5B8C\uFF0C\u603B\u6570\u4E0D\u53EF\u77E5\uFF1B\u53EF\u8C03\u5927 pageSize/maxPages \u91CD\u8BD5`;
4894
+ }
4895
+ return { key, module: cfg.title, available: true, total, totalExact, scannedRows: scanned, ...note ? { note } : {} };
4896
+ }
4897
+ var recruitStats = {
4898
+ name: "ehr.recruit.stats",
4899
+ resource: "recruit",
4900
+ method: "stats",
4901
+ action: "ehr.recruit.stats",
4902
+ summary: '\u62DB\u8058\u5DE5\u4F5C\u7EDF\u8BA1\uFF1A\u6309\u6A21\u5757\u7EDF\u8BA1\u8BB0\u5F55\u6570\uFF08\u4EBA\u624D\u5E93/\u62DB\u8058\u9700\u6C42/\u62DB\u8058\u804C\u4F4D/\u5165\u804C\u7BA1\u7406/\u5F55\u7528\u7BA1\u7406/\u9762\u8BD5\u5B89\u6392\uFF09\uFF0C\u8BA1\u6570\u4E0D\u53EF\u7528\u65F6\u5982\u5B9E\u6807"\u603B\u6570\u4E0D\u53EF\u77E5"',
4903
+ capability: "recruit",
4904
+ risk: READ,
4905
+ inputSchema: schemaOf({
4906
+ modules: {
4907
+ type: "array",
4908
+ items: { type: "string", enum: Object.keys(STATS_MODULES) },
4909
+ uniqueItems: true,
4910
+ description: `\u8981\u7EDF\u8BA1\u7684\u6A21\u5757\uFF0C\u9ED8\u8BA4 ${DEFAULT_MODULES.join(",")}`
4911
+ },
4912
+ pageSize: { type: "integer", minimum: 1, maximum: 200, description: "\u5355\u9875\u884C\u6570\uFF0C\u9ED8\u8BA4 100\uFF08\u8BA1\u6570\u63A5\u53E3\u4E0D\u53EF\u7528\u65F6\u7528\u4E8E\u5206\u9875\u5B9E\u63A2\uFF09" },
4913
+ maxPages: { type: "integer", minimum: 1, maximum: 20, description: "\u6700\u591A\u7FFB\u9875\u6570\uFF0C\u9ED8\u8BA4 5" }
4914
+ }),
4915
+ handler: async (args, env) => {
4916
+ if (!env.recruitContext) {
4917
+ throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
4918
+ }
4919
+ const requested = args.modules === void 0 ? DEFAULT_MODULES : Array.isArray(args.modules) ? args.modules.map(String) : [];
4920
+ if (!requested.length) {
4921
+ throw ehrValidationError("modules_required", `modules \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF0C\u53EF\u9009\u503C\uFF1A${Object.keys(STATS_MODULES).join(" / ")}`);
4922
+ }
4923
+ for (const key of requested) {
4924
+ if (!STATS_MODULES[key]) {
4925
+ throw ehrValidationError("enum_invalid", `modules \u542B\u4E0D\u652F\u6301\u7684\u503C\uFF1A${key}\uFF08\u53EF\u9009 ${Object.keys(STATS_MODULES).join(" / ")}\uFF09`);
4926
+ }
4927
+ }
4928
+ const pageSize = Number.isInteger(args.pageSize) ? Number(args.pageSize) : 100;
4929
+ const maxPages = Number.isInteger(args.maxPages) ? Number(args.maxPages) : 5;
4930
+ const cache = await env.recruitContext.load(env.host);
4931
+ const modules = await Promise.all(
4932
+ requested.map((key) => countModule(env, cache, key, pageSize, maxPages))
4933
+ );
4934
+ const known = modules.filter((m) => m.available && m.total !== null);
4935
+ const unknown = modules.filter((m) => m.available && m.total === null);
4936
+ const unavailable = modules.filter((m) => !m.available);
4937
+ return ehrSuccess("ehr.recruit.stats", {
4938
+ modules,
4939
+ summary: {
4940
+ knownTotal: known.reduce((sum, m) => sum + m.total, 0),
4941
+ knownModules: known.map((m) => m.key),
4942
+ unknownModules: unknown.map((m) => m.key),
4943
+ unavailableModules: unavailable.map((m) => m.key),
4944
+ note: unknown.length ? "\u5B58\u5728\u603B\u6570\u4E0D\u53EF\u77E5\u7684\u6A21\u5757\uFF08\u89C1\u5BF9\u5E94 note\uFF09\uFF0C\u672A\u8BA1\u5165 knownTotal" : void 0
4945
+ }
4946
+ }, { pageSize, maxPages });
4947
+ }
4948
+ };
4949
+ var recruitStatsOperations = [recruitStats];
4950
+
4951
+ // src/shortcuts/ehr/operations/recruit-position.ts
4952
+ import { createHash as createHash4 } from "node:crypto";
4953
+ var TEXT_KEYS = ["position_name"];
4954
+ var MTEXT_KEYS = ["position_duty", "work_request"];
4955
+ var PERSON_DEFAULT_KEYS = ["recr_principal", "employ_manager"];
4956
+ var REF_COPY_KEYS = [
4957
+ "position_nature",
4958
+ "job_category",
4959
+ "education",
4960
+ "work_years",
4961
+ "work_location",
4962
+ "salary_min",
4963
+ "salary_max",
4964
+ "recruit_flow"
4965
+ ];
4966
+ var TEXT_DEFAULTS = { recruit_count: "1", number_of_pay_months: "12" };
4967
+ var OPTION_DEFAULTS = { salary_type: "\u6708\u85AA", recruit_type: "\u793E\u4F1A\u62DB\u8058", status: "\u62DB\u8058\u4E2D" };
4968
+ var SET_FIELDS = [
4969
+ { arg: "education", key: "education", kind: "dict", label: "\u5B66\u5386\u8981\u6C42\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
4970
+ { arg: "workYears", key: "work_years", kind: "dict", label: "\u5DE5\u4F5C\u5E74\u9650\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
4971
+ { arg: "jobCategory", key: "job_category", kind: "dict", label: "\u804C\u4F4D\u7C7B\u522B\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
4972
+ { arg: "positionNature", key: "position_nature", kind: "dict", label: "\u804C\u4F4D\u5C5E\u6027\uFF08\u6309\u6570\u636E\u5B57\u5178\u540D\u79F0\uFF09" },
4973
+ { arg: "salaryType", key: "salary_type", kind: "option", label: "\u85AA\u916C\u7C7B\u578B\uFF08\u6708\u85AA/\u5E74\u85AA\u7B49\uFF09" },
4974
+ { arg: "recruitType", key: "recruit_type", kind: "option", label: "\u62DB\u8058\u65B9\u5F0F\uFF08\u793E\u4F1A\u62DB\u8058/\u6821\u56ED\u62DB\u8058\u7B49\uFF09" },
4975
+ { arg: "recruitCount", key: "recruit_count", kind: "number", label: "\u62DB\u8058\u4EBA\u6570" },
4976
+ { arg: "salaryMin", key: "salary_min", kind: "number", label: "\u85AA\u916C\u4E0B\u9650" },
4977
+ { arg: "salaryMax", key: "salary_max", kind: "number", label: "\u85AA\u916C\u4E0A\u9650" },
4978
+ { arg: "numberOfPayMonths", key: "number_of_pay_months", kind: "number", label: "\u85AA\u916C\u6708\u6570" },
4979
+ { arg: "recruitPrincipal", key: "recr_principal", kind: "person", label: "\u62DB\u8058\u8D1F\u8D23\u4EBA\uFF08\u6309\u59D3\u540D\uFF09" },
4980
+ { arg: "employManager", key: "employ_manager", kind: "person", label: "\u7528\u4EBA\u7ECF\u7406\uFF08\u6309\u59D3\u540D\uFF09" },
4981
+ { arg: "interviewer", key: "interviewer", kind: "person", label: "\u9762\u8BD5\u5B98\uFF08\u6309\u59D3\u540D\uFF09" },
4982
+ { arg: "recruitHelper", key: "recr_helper", kind: "person", label: "\u62DB\u8058\u534F\u52A9\u4EBA\uFF08\u6309\u59D3\u540D\uFF09" }
4983
+ ];
4984
+ var SET_SCHEMA = Object.fromEntries(
4985
+ SET_FIELDS.map((f) => [f.arg, f.kind === "number" ? { type: "string", description: `${f.label}\uFF08\u6570\u5B57\uFF0C\u6309\u5B57\u7B26\u4E32\u4F20\uFF09` } : { type: "string", description: f.label }])
4986
+ );
4987
+ function fingerprint3(value) {
4988
+ return createHash4("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
4989
+ }
4990
+ function requireConfirm3(args, action) {
4991
+ if (args.confirm !== true) {
4992
+ throw ehrConfirmationError(action, { hint: "\u91CD\u65B0\u8C03\u7528\u65F6\u4F20\u5165 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation" });
4993
+ }
4994
+ }
4995
+ async function requireCache(env) {
4996
+ if (!env.recruitContext) throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
4997
+ return env.recruitContext.load(env.host);
4998
+ }
4999
+ async function fetchReferenceDetails(env, cache, objId, formId) {
5000
+ const list = cache.lists.position;
5001
+ if (!list?.listId) return [];
5002
+ try {
5003
+ const body = buildListBody({
5004
+ listId: list.listId,
5005
+ cusMenuId: list.cusMenuId,
5006
+ menuName: list.menuName || "\u62DB\u8058\u804C\u4F4D",
5007
+ title: "\u62DB\u8058\u804C\u4F4D",
5008
+ pageSize: 1
5009
+ });
5010
+ const page = await fetchListRows(env.host, objId, list.listId, body);
5011
+ const row = page.rows[0];
5012
+ const recordId = row?.form_data_id || row?.id;
5013
+ if (!recordId) return [];
5014
+ const record = await getFormDataRecord(env.host, formId, String(recordId), objId);
5015
+ return toSubmitDetails(record.dataDetails);
5016
+ } catch {
5017
+ return [];
5018
+ }
5019
+ }
5020
+ async function buildPositionPlan(env, cache, args) {
5021
+ const form = cache.forms.position_manage;
5022
+ const objId = form?.objId;
5023
+ const formId = form?.formId || objId;
5024
+ if (!objId || !formId) {
5025
+ throw ehrValidationError(
5026
+ "position_form_unavailable",
5027
+ "\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u300C\u62DB\u8058\u804C\u4F4D\u300D\u529F\u80FD\uFF08\u672A\u89E3\u6790\u5230 position_manage \u8868\u5355\uFF09\uFF0C\u65E0\u6CD5\u5EFA\u804C\u4F4D"
5028
+ );
5029
+ }
5030
+ const fields = cache.fields[objId] || {};
5031
+ const fid = (key) => fields[key];
5032
+ for (const key of [...TEXT_KEYS, ...MTEXT_KEYS]) {
5033
+ if (!fid(key)) {
5034
+ throw ehrValidationError("recruit_field_missing", `\u804C\u4F4D\u7BA1\u7406\u7F3A\u5C11\u5B57\u6BB5 ${key}\uFF08ds/fields \u89E3\u6790\u4E0D\u5230\uFF09\uFF0C\u65E0\u6CD5\u5EFA\u804C\u4F4D`);
5035
+ }
5036
+ }
5037
+ const positionName = String(args.positionName ?? "").trim();
5038
+ if (!positionName) throw ehrValidationError("position_name_required", "positionName \u5FC5\u586B");
5039
+ const data = /* @__PURE__ */ new Map();
5040
+ const put = (entry) => {
5041
+ if (entry && entry.formField?.id) data.set(String(entry.formField.id), entry);
5042
+ };
5043
+ const has = (key) => {
5044
+ const id = fid(key);
5045
+ return !!(id && data.has(String(id)));
5046
+ };
5047
+ put({ formField: { id: fid("position_name") }, content: positionName });
5048
+ const duty = typeof args.duty === "string" ? args.duty : "";
5049
+ const requirement = typeof args.requirement === "string" ? args.requirement : "";
5050
+ if (duty && fid("position_duty")) put({ formField: { id: fid("position_duty") }, dataText: { content: duty } });
5051
+ if (requirement && fid("work_request")) put({ formField: { id: fid("work_request") }, dataText: { content: requirement } });
5052
+ const applied = [];
5053
+ const skipped = [];
5054
+ if (args.demandId !== void 0 && args.demandId !== null && args.demandId !== "") {
5055
+ if (!fid("demand")) throw ehrValidationError("recruit_field_missing", "\u804C\u4F4D\u7BA1\u7406\u7F3A\u5C11\u5B57\u6BB5 demand\uFF0C\u65E0\u6CD5\u5173\u8054\u62DB\u8058\u9700\u6C42");
5056
+ const demandId = String(args.demandId).replace(/[^\d]/g, "");
5057
+ if (!demandId) throw ehrValidationError("demand_id_invalid", "demandId \u5FC5\u987B\u662F\u6570\u5B57 ID");
5058
+ put({
5059
+ formField: { id: fid("demand") },
5060
+ dataOptions: [{ optionId: demandId, content: typeof args.demandName === "string" && args.demandName ? args.demandName : demandId }]
5061
+ });
5062
+ applied.push(`demand=${demandId}`);
5063
+ }
5064
+ for (const field of SET_FIELDS) {
5065
+ const raw = args[field.arg];
5066
+ if (raw === void 0 || raw === null || String(raw).trim() === "") continue;
5067
+ const value = String(raw).trim();
5068
+ const fieldId = fid(field.key);
5069
+ if (!fieldId) {
5070
+ skipped.push(`${field.key}\uFF08\u804C\u4F4D\u8868\u5355\u65E0\u8BE5\u5B57\u6BB5\uFF09`);
5071
+ continue;
5072
+ }
5073
+ if (field.kind === "text" || field.kind === "number") {
5074
+ put({ formField: { id: fieldId }, content: value });
5075
+ applied.push(`${field.key}=${value}`);
5076
+ } else if (field.kind === "option") {
5077
+ const options = await getDsOptions(env.host, objId, fieldId, cache.appId);
5078
+ const optionId = options[value];
5079
+ if (!optionId) {
5080
+ skipped.push(`${field.key}=${value}\uFF08\u9009\u9879\u672A\u5339\u914D\uFF1A${Object.keys(options).slice(0, 8).join("/")}\u2026\uFF09`);
5081
+ continue;
5082
+ }
5083
+ put({ formField: { id: fieldId }, dataOptions: [{ optionId: String(optionId), content: value }] });
5084
+ applied.push(`${field.key}=${value}`);
5085
+ } else if (field.kind === "dict") {
5086
+ const ids = cache.dict.by_name[value] || [];
5087
+ const unique = [...new Set(ids.map(String))];
5088
+ if (unique.length !== 1) {
5089
+ skipped.push(`${field.key}=${value}\uFF08\u5B57\u5178${unique.length === 0 ? "\u65E0\u6B64\u9879" : "\u540C\u540D\u591A\u9879\uFF0C\u6B67\u4E49"}\uFF0C\u672A\u5199\u5165\uFF09`);
5090
+ continue;
5091
+ }
5092
+ put({ formField: { id: fieldId }, dataOptions: [{ optionId: unique[0], content: value }] });
5093
+ applied.push(`${field.key}=${value}`);
5094
+ } else {
5095
+ const personId = await resolvePersonId(env.host, fieldId, value);
5096
+ if (!personId) {
5097
+ skipped.push(`${field.key}=${value}\uFF08\u4EBA\u5458\u672A\u5339\u914D\uFF09`);
5098
+ continue;
5099
+ }
5100
+ put({ formField: { id: fieldId }, dataOptions: [{ optionId: String(personId), content: value }] });
5101
+ applied.push(`${field.key}=${value}`);
5102
+ }
5103
+ }
5104
+ for (const [key, name] of Object.entries(OPTION_DEFAULTS)) {
5105
+ const fieldId = fid(key);
5106
+ if (!fieldId || has(key)) continue;
5107
+ const options = await getDsOptions(env.host, objId, fieldId, cache.appId);
5108
+ const optionId = options[name];
5109
+ if (optionId) put({ formField: { id: fieldId }, dataOptions: [{ optionId: String(optionId), content: name }] });
5110
+ }
5111
+ for (const [key, value] of Object.entries(TEXT_DEFAULTS)) {
5112
+ const fieldId = fid(key);
5113
+ if (fieldId && !has(key)) put({ formField: { id: fieldId }, content: value });
5114
+ }
5115
+ const session = await env.host.getSession();
5116
+ for (const key of PERSON_DEFAULT_KEYS) {
5117
+ const fieldId = fid(key);
5118
+ if (fieldId && !has(key) && session.userId) {
5119
+ put({ formField: { id: fieldId }, dataOptions: [{ optionId: session.userId, content: "\u5F53\u524D\u7528\u6237" }] });
5120
+ }
5121
+ }
5122
+ const refDetails = await fetchReferenceDetails(env, cache, objId, formId);
5123
+ const refMap = /* @__PURE__ */ new Map();
5124
+ for (const detail of refDetails) {
5125
+ const id = detail?.formField?.id;
5126
+ if (id) refMap.set(String(id), detail);
5127
+ }
5128
+ const inherited = [];
5129
+ const missingRef = [];
5130
+ for (const key of REF_COPY_KEYS) {
5131
+ const fieldId = fid(key);
5132
+ if (!fieldId || has(key)) continue;
5133
+ const ref = refMap.get(String(fieldId));
5134
+ if (ref) {
5135
+ put(ref);
5136
+ inherited.push(key);
5137
+ } else {
5138
+ missingRef.push(key);
5139
+ }
5140
+ }
5141
+ const inverse = {};
5142
+ for (const [dataKey, fieldId] of Object.entries(fields)) inverse[String(fieldId)] = dataKey;
5143
+ return {
5144
+ objId,
5145
+ formId,
5146
+ dataDetails: [...data.values()],
5147
+ summary: {
5148
+ positionName,
5149
+ dutyLength: duty.length,
5150
+ requirementLength: requirement.length,
5151
+ fieldCount: data.size,
5152
+ filledFields: [...data.keys()].map((id) => inverse[id] || id).sort(),
5153
+ explicitApplied: applied,
5154
+ explicitSkipped: skipped,
5155
+ inheritedFromExistingPosition: inherited,
5156
+ noReferenceValue: missingRef,
5157
+ principalDefault: session.userId ? "\u5F53\u524D\u767B\u5F55\u7528\u6237" : "\u672A\u89E3\u6790\u5230\u5F53\u524D\u7528\u6237"
5158
+ }
5159
+ };
5160
+ }
5161
+ var positionCreatePrepare = {
5162
+ name: "ehr.recruit.position.create.prepare",
5163
+ resource: "recruit",
5164
+ method: "position.create.prepare",
5165
+ action: "ehr.recruit.position.create.prepare",
5166
+ summary: "\u751F\u6210\u804C\u4F4D\u5E76\u5EFA\u5230\u62DB\u8058\u804C\u4F4D\u5217\u8868\u524D\u7684\u786E\u8BA4\u6458\u8981\uFF1A\u89E3\u6790\u804C\u4F4D\u8868\u5355\u5B57\u6BB5\u3001\u5957\u7528\u9ED8\u8BA4\u503C\uFF08\u72B6\u6001/\u6D41\u7A0B/\u8D1F\u8D23\u4EBA/\u5173\u8054\u5B57\u6BB5\uFF09\uFF0C\u4E0D\u5199\u5165\u4EFB\u4F55\u6570\u636E",
5167
+ capability: "recruit",
5168
+ risk: WRITE,
5169
+ requiresConfirmation: true,
5170
+ inputSchema: schemaOf(
5171
+ {
5172
+ positionName: { type: "string", maxLength: 120, description: "\u804C\u4F4D\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
5173
+ duty: { type: "string", maxLength: 2e4, description: "\u5C97\u4F4D\u804C\u8D23 / JD \u6B63\u6587\uFF08\u5199\u5165\u804C\u4F4D\u804C\u8D23\u591A\u884C\u6587\u672C\uFF09" },
5174
+ requirement: { type: "string", maxLength: 2e4, description: "\u4EFB\u804C\u8981\u6C42\uFF08\u5199\u5165\u5DE5\u4F5C\u4EFB\u804C\u8981\u6C42\u591A\u884C\u6587\u672C\uFF09" },
5175
+ demandId: { ...SCHEMA_ID, description: "\u5173\u8054\u62DB\u8058\u9700\u6C42 id\uFF08\u53EF\u9009\uFF09" },
5176
+ demandName: { type: "string", maxLength: 200, description: "\u5173\u8054\u9700\u6C42\u540D\u79F0\uFF08\u4EC5\u7528\u4E8E\u6458\u8981\u5C55\u793A\uFF09" },
5177
+ ...SET_SCHEMA
5178
+ },
5179
+ { required: ["positionName"] }
5180
+ ),
5181
+ handler: async (args, env) => {
5182
+ const cache = await requireCache(env);
5183
+ const plan = await buildPositionPlan(env, cache, args);
5184
+ const session = await env.host.getSession();
5185
+ const continuation = await env.continuation.issue(
5186
+ {
5187
+ operation: "ehr.recruit.position.create.apply",
5188
+ baseUrl: session.baseUrl,
5189
+ profile: session.profile,
5190
+ userId: session.userId,
5191
+ payload: { objId: plan.objId, formId: plan.formId, positionName: String(args.positionName).trim(), dataDetails: plan.dataDetails },
5192
+ fingerprint: fingerprint3({ objId: plan.objId, dataDetails: plan.dataDetails })
5193
+ },
5194
+ 10 * 60 * 1e3
5195
+ );
5196
+ return ehrSuccess("ehr.recruit.position.create.prepare", {
5197
+ status: "AWAITING_CONFIRMATION",
5198
+ preview: { action: "\u751F\u6210\u804C\u4F4DJD\u5E76\u5EFA\u804C\u4F4D\uFF08saveFormData \u2192 addPosition\uFF09", ...plan.summary },
5199
+ willSubmit: { objId: plan.objId, formId: plan.formId, dataDetails: plan.dataDetails },
5200
+ continuation,
5201
+ expiresInSeconds: 600
5202
+ });
5203
+ }
5204
+ };
5205
+ var positionCreateApply = {
5206
+ name: "ehr.recruit.position.create.apply",
5207
+ resource: "recruit",
5208
+ method: "position.create.apply",
5209
+ action: "ehr.recruit.position.create.apply",
5210
+ summary: "\u6267\u884C\u5EFA\u804C\u4F4D\uFF08saveFormData \u2192 addPosition\uFF09\uFF1B\u5FC5\u987B\u5148 prepare \u5E76\u7ECF\u7528\u6237\u660E\u786E\u786E\u8BA4",
5211
+ capability: "recruit",
5212
+ risk: WRITE,
5213
+ requiresConfirmation: true,
5214
+ inputSchema: schemaOf(
5215
+ {
5216
+ positionName: { type: "string", maxLength: 120 },
5217
+ confirm: { const: true },
5218
+ continuation: { type: "string", minLength: 1 }
5219
+ },
5220
+ { required: ["positionName", "confirm", "continuation"] }
5221
+ ),
5222
+ handler: async (args, env) => {
5223
+ requireConfirm3(args, "ehr.recruit.position.create.apply");
5224
+ const lease = await env.continuation.verify(args.continuation, "ehr.recruit.position.create.apply");
5225
+ const session = await env.host.getSession();
5226
+ if (lease.baseUrl !== session.baseUrl || lease.profile !== session.profile || lease.userId !== session.userId) {
5227
+ throw ehrValidationError("context_mismatch", "\u786E\u8BA4\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF08\u79DF\u6237\u6216\u767B\u5F55\u8D26\u53F7\u4E0D\u540C\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
5228
+ }
5229
+ const positionName = String(args.positionName ?? "").trim();
5230
+ const payload = lease.payload || {};
5231
+ if (payload.positionName !== positionName) {
5232
+ throw ehrValidationError("target_changed", "\u804C\u4F4D\u540D\u79F0\u4E0E prepare \u65F6\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
5233
+ }
5234
+ const cache = await requireCache(env);
5235
+ const formDataId = await saveFormData(env.host, {
5236
+ appId: cache.appId,
5237
+ formId: String(payload.formId),
5238
+ objId: String(payload.objId),
5239
+ name: `\u804C\u4F4D\u7BA1\u7406-${positionName}`,
5240
+ dataDetails: payload.dataDetails || []
5241
+ });
5242
+ if (!formDataId) {
5243
+ throw ehrValidationError("save_failed", "saveFormData \u672A\u8FD4\u56DE formDataId\uFF0C\u804C\u4F4D\u672A\u521B\u5EFA");
5244
+ }
5245
+ const response = await env.host.request({
5246
+ path: `/api/recruit/position/v2/addPosition?formDataId=${encodeURIComponent(formDataId)}`,
5247
+ method: "POST",
5248
+ operation: "ehr.recruit.position.create.apply"
5249
+ });
5250
+ const data = response?.data || {};
5251
+ const positionPostId = data.positionPostId ? String(data.positionPostId) : "";
5252
+ const created = response?.status !== false && !!positionPostId;
5253
+ const list = cache.lists.position;
5254
+ const baseUrl = session.baseUrl.replace(/\/+$/, "");
5255
+ const cardUrl = `${baseUrl}/sp/ebdfpage/card/0/${payload.objId}/${formDataId}`;
5256
+ const listLocateUrl = list?.listId ? `${baseUrl}/sp/ebdfpage/list/${list.listId}/card/0/${payload.objId}/${formDataId}/${list.listId}?id=${formDataId}&openSource=field&openSourceId=${formDataId}` : null;
5257
+ if (!created) {
5258
+ throw ehrValidationError(
5259
+ "position_create_failed",
5260
+ `\u804C\u4F4D\u8868\u5355\u5DF2\u4FDD\u5B58\uFF08formDataId=${formDataId}\uFF09\uFF0C\u4F46 addPosition \u672A\u8FD4\u56DE\u804C\u4F4D id\uFF1A${response?.msg || "\u672A\u77E5\u539F\u56E0"}\uFF1B\u8BF7\u5230\u804C\u4F4D\u7BA1\u7406\u6838\u5BF9\u540E\u518D\u51B3\u5B9A\u662F\u5426\u91CD\u8BD5`
5261
+ );
5262
+ }
5263
+ return ehrSuccess("ehr.recruit.position.create.apply", {
5264
+ result: "success",
5265
+ formDataId,
5266
+ positionPostId,
5267
+ rpaChecked: data.checkRpa === void 0 ? null : !!data.checkRpa,
5268
+ rpaValidMsg: data.rpaValidMsg || null,
5269
+ positionName,
5270
+ cardUrl,
5271
+ listLocateUrl
5272
+ });
5273
+ }
5274
+ };
5275
+ var recruitPositionOperations = [
5276
+ positionCreatePrepare,
5277
+ positionCreateApply
5278
+ ];
5279
+
5280
+ // src/shortcuts/ehr/operations/recruit-candidate-import.ts
5281
+ import { createHash as createHash5 } from "node:crypto";
5282
+ import { readFile as readFile2, stat } from "node:fs/promises";
5283
+ import { basename } from "node:path";
5284
+ var SUB_TABLES = [
5285
+ {
5286
+ table: "rcrt_education_exp",
5287
+ input: "academicInformations",
5288
+ cols: {
5289
+ school: (r) => r.school,
5290
+ edu_major: (r) => r.edu_major ?? r.major,
5291
+ edu_education: (r) => r.edu_education ?? r.education,
5292
+ degree: (r) => r.degree,
5293
+ study_date: (r) => r.study_date ?? joinRange(r.start_date, r.end_date),
5294
+ faculty: (r) => r.faculty,
5295
+ research_direction: (r) => r.research_direction,
5296
+ major_courses: (r) => r.major_courses
5297
+ }
5298
+ },
5299
+ {
5300
+ table: "rcrt_work_exp",
5301
+ input: "jobInformations",
5302
+ cols: {
5303
+ co_name: (r) => r.co_name ?? r.company,
5304
+ work_position: (r) => r.work_position ?? r.position,
5305
+ work_dept: (r) => r.work_dept ?? r.department,
5306
+ work_desc: (r) => r.work_desc ?? r.job_description,
5307
+ resign_cause: (r) => r.resign_cause,
5308
+ start_end_date: (r) => r.start_end_date ?? joinRange(r.start_date, r.end_date) ?? r.work_date,
5309
+ work_type: (r) => r.work_type
5310
+ }
5311
+ },
5312
+ {
5313
+ table: "rcrt_sxjl",
5314
+ input: "internshipExperiences",
5315
+ cols: {
5316
+ sx_co_name: (r) => r.sx_co_name ?? r.company,
5317
+ position_job: (r) => r.position_job ?? r.position,
5318
+ job_description: (r) => r.job_description,
5319
+ entry_time: (r) => r.entry_time,
5320
+ sx_work_type: (r) => r.sx_work_type
5321
+ }
5322
+ },
5323
+ {
5324
+ table: "rcrt_project_exp",
5325
+ input: "projectExperiences",
5326
+ cols: {
5327
+ pj_name: (r) => r.pj_name ?? r.project_name,
5328
+ pj_role: (r) => r.pj_role,
5329
+ pj_duty: (r) => r.pj_duty,
5330
+ pj_introduction: (r) => r.pj_introduction ?? r.project_description,
5331
+ pj_date: (r) => r.pj_date ?? joinRange(r.start_date, r.end_date)
5332
+ }
5333
+ },
5334
+ {
5335
+ table: "rcrt_award_exp",
5336
+ input: "awardExperiences",
5337
+ cols: {
5338
+ award_name: (r) => r.award_name,
5339
+ awarded: (r) => r.awarded,
5340
+ credentials: (r) => r.credentials,
5341
+ award_date: (r) => r.award_date
5342
+ }
5343
+ },
5344
+ {
5345
+ table: "rcrt_language_skill",
5346
+ input: "languageAbilities",
5347
+ cols: {
5348
+ language_type: (r) => r.language_type,
5349
+ mastery: (r) => r.mastery,
5350
+ ls_ability: (r) => r.ls_ability,
5351
+ literacy: (r) => r.literacy
5352
+ }
5353
+ }
5354
+ ];
5355
+ var DICT_COLS = /* @__PURE__ */ new Set([
5356
+ "edu_education",
5357
+ "degree",
5358
+ "work_type",
5359
+ "sx_work_type",
5360
+ "mastery",
5361
+ "ls_ability",
5362
+ "literacy"
5363
+ ]);
5364
+ function joinRange(start, end) {
5365
+ const s = start === void 0 || start === null ? "" : String(start).trim();
5366
+ const e = end === void 0 || end === null ? "" : String(end).trim();
5367
+ if (!s && !e) return void 0;
5368
+ return `${s},${e}`;
5369
+ }
5370
+ async function resolveSubTableMeta(env, formId) {
5371
+ let data = null;
5372
+ try {
5373
+ const r = await env.host.request({
5374
+ path: `/api/ebuilder/form/form/core/getFormLayout?formId=${encodeURIComponent(formId)}`,
5375
+ method: "GET",
5376
+ operation: "ehr.recruit.candidate.import.prepare"
5377
+ });
5378
+ data = r?.data;
5379
+ } catch {
5380
+ }
5381
+ if (!data) {
5382
+ const r = await env.host.request({
5383
+ path: "/api/ebuilder/form/form/core/getFormLayout",
5384
+ method: "POST",
5385
+ body: { module: "ebuilderform", formId, terminalType: "PC" },
5386
+ operation: "ehr.recruit.candidate.import.prepare"
5387
+ });
5388
+ data = r?.data;
5389
+ }
5390
+ const comps = data?.formLayout?.pageLayouts?.[0]?.comps || [];
5391
+ const out = {};
5392
+ for (const comp of comps) {
5393
+ const cfg = comp?.config || {};
5394
+ if (comp?.type !== "DetailTable" || !cfg.dataKey || !cfg.subFormId) continue;
5395
+ out[String(cfg.dataKey)] = {
5396
+ dataKey: String(cfg.dataKey),
5397
+ subFormId: String(cfg.subFormId),
5398
+ title: String(cfg.title || ""),
5399
+ columns: {}
5400
+ };
5401
+ }
5402
+ for (const comp of comps) {
5403
+ const cfg = comp?.config || {};
5404
+ const subFormId = String(cfg.subFormId || "");
5405
+ if (!subFormId || !cfg.dataKey || !cfg.fieldId) continue;
5406
+ const target = Object.values(out).find((t) => t.subFormId === subFormId);
5407
+ if (!target) continue;
5408
+ const column = {
5409
+ id: String(cfg.fieldId),
5410
+ type: String(comp?.type || ""),
5411
+ title: String(cfg.title || "")
5412
+ };
5413
+ if (cfg.start?.dataKey && cfg.end?.dataKey) {
5414
+ column.startKey = String(cfg.start.dataKey);
5415
+ column.endKey = String(cfg.end.dataKey);
5416
+ }
5417
+ target.columns[String(cfg.dataKey)] = column;
5418
+ }
5419
+ return out;
5420
+ }
5421
+ function makeDictResolver(cache, warnings) {
5422
+ const byId = /* @__PURE__ */ new Map();
5423
+ for (const row of cache.dict?.raw || []) {
5424
+ if (row.option_id && row.selection_name) byId.set(String(row.option_id), String(row.selection_name));
5425
+ }
5426
+ return (value, label) => {
5427
+ const raw = value === void 0 || value === null ? "" : String(value).trim();
5428
+ if (!raw) return "";
5429
+ if (/^\d{6,}$/.test(raw)) {
5430
+ if (byId.has(raw)) return raw;
5431
+ warnings.push(`${label}\uFF1A\u5B57\u5178 id ${raw} \u672A\u5728\u672C\u73AF\u5883\u5B57\u5178\u4E2D\uFF0C\u5DF2\u8DF3\u8FC7`);
5432
+ return "";
5433
+ }
5434
+ const ids = [...new Set((cache.dict?.by_name?.[raw] || []).map(String))];
5435
+ if (ids.length === 1) return ids[0];
5436
+ warnings.push(`${label}\u300C${raw}\u300D${ids.length === 0 ? "\u5728\u5B57\u5178\u4E2D\u4E0D\u5B58\u5728" : "\u547D\u4E2D\u591A\u4E2A\u540C\u540D\u9009\u9879\uFF08\u6B67\u4E49\uFF09"}\uFF0C\u5DF2\u8DF3\u8FC7`);
5437
+ return "";
5438
+ };
5439
+ }
5440
+ function buildSubDetails(structured, meta, nodeOfTable, resolveDict) {
5441
+ const details = {};
5442
+ const stats = {};
5443
+ const nodes = {};
5444
+ const warnings = [];
5445
+ for (const spec of SUB_TABLES) {
5446
+ const sub = meta[spec.table];
5447
+ if (!sub) {
5448
+ stats[spec.table] = 0;
5449
+ continue;
5450
+ }
5451
+ const rows = Array.isArray(structured[spec.input]) ? structured[spec.input] : [];
5452
+ const built = [];
5453
+ for (const row of rows) {
5454
+ if (!row || typeof row !== "object") continue;
5455
+ const out = {};
5456
+ for (const [colKey, pick] of Object.entries(spec.cols)) {
5457
+ const column = sub.columns[colKey];
5458
+ if (!column) continue;
5459
+ let value = pick(row);
5460
+ if (value === void 0 || value === null || String(value).trim() === "") continue;
5461
+ if (DICT_COLS.has(colKey)) {
5462
+ value = resolveDict(value, `${sub.title}.${column.title || colKey}`);
5463
+ if (!value) continue;
5464
+ }
5465
+ if (column.startKey && column.endKey) {
5466
+ const parts = Array.isArray(value) ? value : String(value).split(/[,~]/);
5467
+ const start = String(parts[0] ?? "").trim();
5468
+ const end = String(parts[1] ?? "").trim();
5469
+ if (!start || !end) continue;
5470
+ out[column.startKey] = start;
5471
+ out[column.endKey] = end;
5472
+ continue;
5473
+ }
5474
+ out[colKey] = String(value);
5475
+ }
5476
+ if (Object.keys(out).length > 0) built.push(out);
5477
+ }
5478
+ if (built.length === 0) {
5479
+ stats[spec.table] = 0;
5480
+ continue;
5481
+ }
5482
+ const node = nodeOfTable[sub.subFormId];
5483
+ if (!node) {
5484
+ warnings.push(`\u5B50\u8868\u300C${sub.title || spec.table}\u300D\u5728 getTableMapping \u4E2D\u65E0\u5BF9\u5E94\u8282\u70B9\uFF0C\u672C\u6B21\u4E0D\u5199\u5165\uFF08${built.length} \u884C\uFF09`);
5485
+ stats[spec.table] = 0;
5486
+ continue;
5487
+ }
5488
+ details[node] = built;
5489
+ nodes[spec.table] = node;
5490
+ stats[spec.table] = built.length;
5491
+ }
5492
+ return { details, stats, nodes, warnings };
5493
+ }
5494
+ async function datasetSaveFormData(env, objId, mainTable, details) {
5495
+ const record = { mainTable };
5496
+ for (const [node, rows] of Object.entries(details)) {
5497
+ if (rows.length) record[node] = rows;
5498
+ }
5499
+ const response = await env.host.request({
5500
+ path: "/api/ebuilder/form/dataset/v2/saveFormData",
5501
+ method: "POST",
5502
+ body: {
5503
+ datajson: {
5504
+ datas: [record],
5505
+ header: { objId },
5506
+ operationinfo: { fieldNoFindIgnore: "true", doAction: "false" }
5507
+ }
5508
+ },
5509
+ operation: "ehr.recruit.candidate.import.apply"
5510
+ });
5511
+ const datajson = response?.data?.datajson || {};
5512
+ const code = response?.message?.code;
5513
+ const ok = (code === void 0 || String(code) === "0") && datajson.status !== false;
5514
+ if (!ok) {
5515
+ throw ehrValidationError(
5516
+ "save_failed",
5517
+ `dataset saveFormData \u5931\u8D25\uFF1A${datajson.message || response?.message?.msg || JSON.stringify(response).slice(0, 200)}`
5518
+ );
5519
+ }
5520
+ const ids = Array.isArray(datajson.dataIds) ? datajson.dataIds : [];
5521
+ if (!ids.length) {
5522
+ throw ehrValidationError("save_failed", `dataset saveFormData \u672A\u8FD4\u56DE dataIds\uFF1A${JSON.stringify(response).slice(0, 200)}`);
5523
+ }
5524
+ return String(ids[0]);
5525
+ }
5526
+ async function uploadResumeFile(env, filePath, fieldId, formId) {
5527
+ let buffer;
5528
+ let mtimeMs = Date.now();
5529
+ try {
5530
+ buffer = await readFile2(filePath);
5531
+ mtimeMs = (await stat(filePath)).mtimeMs || Date.now();
5532
+ } catch {
5533
+ throw ehrValidationError("resume_file_unreadable", `\u65E0\u6CD5\u8BFB\u53D6\u7B80\u5386\u6587\u4EF6\uFF1A${filePath}`);
5534
+ }
5535
+ const name = basename(filePath);
5536
+ const size = buffer.length;
5537
+ const baseForm = (withFile) => {
5538
+ const fd2 = new FormData();
5539
+ fd2.append("compressImg", "false");
5540
+ fd2.append("source", "form");
5541
+ fd2.append("fieldId", fieldId);
5542
+ fd2.append("sourceRefId", formId);
5543
+ fd2.append("module", "ebuilderform");
5544
+ fd2.append("authModule", "ebuilderform");
5545
+ fd2.append("formId", formId);
5546
+ fd2.append("refId", formId);
5547
+ fd2.append("size", String(size));
5548
+ fd2.append("commonText", JSON.stringify({ fieldId, formId }));
5549
+ if (withFile) fd2.append("file", new Blob([new Uint8Array(buffer)]), name);
5550
+ return fd2;
5551
+ };
5552
+ const pre = await env.host.request({
5553
+ path: "/api/file/preUploadCheck",
5554
+ method: "POST",
5555
+ multipart: baseForm(true),
5556
+ // 预上传检查必须带文件,否则服务端 500
5557
+ headers: { ebBusinessId: formId, langType: "zh_CN", timeZoneOffset: "-480" },
5558
+ operation: "ehr.recruit.candidate.import.apply"
5559
+ });
5560
+ const preUploadId = pre?.data?.preUploadId;
5561
+ const uploadType = pre?.data?.uploadType || "common";
5562
+ if (!preUploadId) {
5563
+ throw ehrValidationError("resume_preupload_failed", `\u7B80\u5386\u9884\u4E0A\u4F20\u68C0\u67E5\u5931\u8D25\uFF1A${JSON.stringify(pre || {}).slice(0, 200)}`);
5564
+ }
5565
+ const fd = baseForm(false);
5566
+ fd.append("name", name);
5567
+ fd.append("MD5", createHash5("md5").update(buffer).digest("hex"));
5568
+ fd.append("lastModified", String(Math.round(mtimeMs)));
5569
+ fd.append("lastModifiedDate", String(Math.round(mtimeMs)));
5570
+ fd.append("preUploadId", String(preUploadId));
5571
+ fd.append("uploadType", String(uploadType));
5572
+ fd.append("file", new Blob([new Uint8Array(buffer)]), name);
5573
+ const res = await env.host.request({
5574
+ path: "/api/file/module/upload",
5575
+ method: "POST",
5576
+ multipart: fd,
5577
+ headers: { ebBusinessId: formId, langType: "zh_CN", timeZoneOffset: "-480" },
5578
+ operation: "ehr.recruit.candidate.import.apply"
5579
+ });
5580
+ const fileid = res?.data?.fileid || res?.data?.uploadModuleDto?.fileObj?.fileId || res?.data?.fileObj?.fileId;
5581
+ if (!fileid) {
5582
+ throw ehrValidationError("resume_upload_failed", `\u7B80\u5386\u4E0A\u4F20\u672A\u8FD4\u56DE fileid\uFF1A${JSON.stringify(res || {}).slice(0, 200)}`);
5583
+ }
5584
+ return { fileid: String(fileid), name, size };
5585
+ }
5586
+ async function applyPlatformTags(env, talentId, tagNames) {
5587
+ if (!tagNames.length) return { applied: [], skipped: [] };
5588
+ const list = await env.host.request({
5589
+ path: "/api/my/tag/query",
5590
+ method: "POST",
5591
+ body: { tagModules: ["ebuilderform"], current: 1, pageSize: 500 },
5592
+ operation: "ehr.recruit.candidate.import.apply"
5593
+ });
5594
+ const rows = list?.data?.data || list?.data?.list || [];
5595
+ const byName = /* @__PURE__ */ new Map();
5596
+ for (const row of rows) {
5597
+ const name = String(row.name ?? row.tagName ?? "").trim();
5598
+ const id = row.tagId ?? row.id;
5599
+ if (name && id !== void 0 && !byName.has(name)) byName.set(name, { id: String(id), name });
5600
+ }
5601
+ const tags = [];
5602
+ const applied = [];
5603
+ const skipped = [];
5604
+ for (const name of tagNames) {
5605
+ const hit = byName.get(name);
5606
+ if (!hit) {
5607
+ skipped.push(name);
5608
+ continue;
5609
+ }
5610
+ tags.push({ id: hit.id, name: hit.name, type: 0 });
5611
+ applied.push(name);
5612
+ }
5613
+ if (tags.length) {
5614
+ await env.host.request({
5615
+ path: "/api/my/tag/common/batchAddEntityTag",
5616
+ method: "POST",
5617
+ body: { tags, batchDatas: [{ entityId: talentId, module: "ebuilderform" }] },
5618
+ operation: "ehr.recruit.candidate.import.apply"
5619
+ });
5620
+ }
5621
+ return { applied, skipped };
5622
+ }
5623
+ async function requireCache2(env) {
5624
+ if (!env.recruitContext) throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
5625
+ return env.recruitContext.load(env.host);
5626
+ }
5627
+ function str(value) {
5628
+ if (value === void 0 || value === null) return "";
5629
+ return String(value).trim();
5630
+ }
5631
+ async function buildImportPlan(env, cache, args) {
5632
+ const warnings = [];
5633
+ const talent = cache.forms.talent_pool;
5634
+ const objId = talent?.objId;
5635
+ const formId = talent?.formId || objId;
5636
+ if (!objId || !formId) {
5637
+ throw ehrValidationError("talent_form_unavailable", "\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u300C\u4EBA\u624D\u5E93\u300D\u529F\u80FD\uFF08\u672A\u89E3\u6790\u5230 talent_pool \u8868\u5355\uFF09");
5638
+ }
5639
+ const fields = cache.fields[objId] || {};
5640
+ const name = str(args.candidateName);
5641
+ const mobile = str(args.telephone);
5642
+ if (!name) throw ehrValidationError("candidate_name_required", "candidateName \u5FC5\u586B");
5643
+ if (!/^\d{6,}$/.test(mobile)) throw ehrValidationError("telephone_invalid", "telephone \u5FC5\u987B\u662F 6 \u4F4D\u4EE5\u4E0A\u6570\u5B57\uFF08\u624B\u673A\u53F7\uFF09");
5644
+ if (!fields.candidate_name || !fields.telephone) {
5645
+ throw ehrValidationError("recruit_field_missing", "\u73AF\u5883\u7F13\u5B58\u7F3A\u4EBA\u624D\u59D3\u540D\u5B57\u6BB5(candidate_name)\u6216\u624B\u673A\u5B57\u6BB5(telephone)");
5646
+ }
5647
+ const resolveDict = makeDictResolver(cache, warnings);
5648
+ const main = {};
5649
+ const putText = (key, value, longText = false) => {
5650
+ if (!fields[key]) return;
5651
+ const text = str(value);
5652
+ if (!text) return;
5653
+ main[key] = text;
5654
+ void longText;
5655
+ };
5656
+ putText("candidate_name", name);
5657
+ putText("telephone", mobile);
5658
+ putText("email", args.email);
5659
+ putText("birthday", args.birthday);
5660
+ putText("age", args.age);
5661
+ putText("college", args.college);
5662
+ putText("graduate_date", args.graduateDate);
5663
+ putText("joinworkdate", args.joinworkdate);
5664
+ putText("intend_position", args.intendPosition);
5665
+ putText("intended_workplace", args.intendedWorkplace);
5666
+ putText("self_desc", args.selfDesc, true);
5667
+ putText("work_ability", args.workAbility, true);
5668
+ for (const [key, inputKey, label] of [
5669
+ ["gender", "genderName", "\u6027\u522B"],
5670
+ ["highest_degree", "highestDegreeName", "\u6700\u9AD8\u5B66\u5386"]
5671
+ ]) {
5672
+ if (!fields[key]) continue;
5673
+ const raw = str(args[inputKey]);
5674
+ if (!raw) continue;
5675
+ const id = resolveDict(raw, label);
5676
+ if (id) main[key] = id;
5677
+ }
5678
+ const channel = str(args.channel);
5679
+ if (channel) {
5680
+ if (!fields.channel) warnings.push("\u4EBA\u624D\u8868\u5355\u65E0\u6E20\u9053\u5B57\u6BB5\uFF0Cchannel \u5DF2\u5FFD\u7565");
5681
+ else {
5682
+ const id = resolveDict(channel, "\u6E20\u9053");
5683
+ if (id) main.channel = id;
5684
+ }
5685
+ }
5686
+ if (fields.is_blacklist) {
5687
+ const noId = resolveDict("\u5426", "\u9ED1\u540D\u5355");
5688
+ if (noId) main.is_blacklist = noId;
5689
+ }
5690
+ let subStats = {};
5691
+ let detailNodes = {};
5692
+ let details = {};
5693
+ try {
5694
+ const mappingResponse = await env.host.request({
5695
+ path: `/api/ebuilder/form/dataset/v1/getTableMapping?objId=${encodeURIComponent(objId)}`,
5696
+ method: "GET",
5697
+ operation: "ehr.recruit.candidate.import.prepare"
5698
+ });
5699
+ const mapping = mappingResponse?.data;
5700
+ if (!mapping?.mainTable) throw new Error("getTableMapping \u672A\u8FD4\u56DE mainTable");
5701
+ const nodeOfTable = {};
5702
+ for (const [node, tableId] of Object.entries(mapping)) {
5703
+ if (node === "mainTable") continue;
5704
+ nodeOfTable[String(tableId)] = node;
5705
+ }
5706
+ const meta = await resolveSubTableMeta(env, formId);
5707
+ const built = buildSubDetails(args, meta, nodeOfTable, resolveDict);
5708
+ details = built.details;
5709
+ subStats = built.stats;
5710
+ detailNodes = built.nodes;
5711
+ warnings.push(...built.warnings);
5712
+ } catch (error) {
5713
+ warnings.push(`\u660E\u7EC6\u8868\u672A\u5199\u5165\uFF1A${error?.message || "\u672A\u77E5\u9519\u8BEF"}\uFF08\u4E3B\u8868\u7167\u5E38\u5EFA\u6863\uFF09`);
5714
+ }
5715
+ const subRowTotal = Object.values(subStats).reduce((sum, n) => sum + n, 0);
5716
+ const summary = {
5717
+ candidateName: name,
5718
+ telephone: mobile,
5719
+ email: str(args.email) || "(\u672A\u586B)",
5720
+ channel: channel || "(\u672A\u6307\u5B9A)",
5721
+ mainFieldCount: Object.keys(main).length,
5722
+ mainFields: Object.keys(main).sort(),
5723
+ subTableRows: subStats,
5724
+ subRowTotal,
5725
+ detailNodes,
5726
+ platformTags: Array.isArray(args.tags) ? args.tags : [],
5727
+ resumeFile: str(args.resumeFile) || "(\u672A\u63D0\u4F9B\u539F\u4EF6)",
5728
+ warnings
5729
+ };
5730
+ return {
5731
+ objId,
5732
+ formId,
5733
+ talentObjId: objId,
5734
+ mainTable: main,
5735
+ details,
5736
+ subStats,
5737
+ detailNodes,
5738
+ warnings,
5739
+ talentName: name,
5740
+ mobile,
5741
+ summary
5742
+ };
5743
+ }
5744
+ var candidateImportPrepare = {
5745
+ name: "ehr.recruit.candidate.import.prepare",
5746
+ resource: "recruit",
5747
+ method: "candidate.import.prepare",
5748
+ action: "ehr.recruit.candidate.import.prepare",
5749
+ summary: "\u7B80\u5386\u5BFC\u5165\u5EFA\u4EBA\u624D\u7684\u786E\u8BA4\u6458\u8981\uFF1A\u624B\u673A\u53F7\u67E5\u91CD + \u4E3B\u8868\u5B57\u6BB5\u6620\u5C04 + 6 \u5F20\u660E\u7EC6\u8868\u884C\u6570 + \u6807\u7B7E\u6838\u9A8C\uFF0C\u4E0D\u5199\u5165\u4EFB\u4F55\u6570\u636E",
5750
+ capability: "recruit",
5751
+ risk: WRITE,
5752
+ requiresConfirmation: true,
5753
+ inputSchema: schemaOf({
5754
+ candidateName: { type: "string", maxLength: 60, description: "\u59D3\u540D\uFF08\u5FC5\u586B\uFF09" },
5755
+ telephone: { type: "string", pattern: "^\\d{6,20}$", description: "\u624B\u673A\u53F7\uFF08\u5FC5\u586B\uFF0C\u67E5\u91CD\u4E3B\u952E\uFF09" },
5756
+ email: { type: "string", maxLength: 120 },
5757
+ genderName: { type: "string", description: "\u6027\u522B\u540D\u79F0\uFF08\u5982 \u7537/\u5973\uFF0C\u6309\u672C\u73AF\u5883\u5B57\u5178\u53CD\u67E5\uFF09" },
5758
+ birthday: { type: "string", description: "\u51FA\u751F\u65E5\u671F YYYY-MM-DD" },
5759
+ age: { type: "string", description: "\u5E74\u9F84" },
5760
+ highestDegreeName: { type: "string", description: "\u6700\u9AD8\u5B66\u5386\u540D\u79F0\uFF08\u5982 \u672C\u79D1/\u7855\u58EB\uFF09" },
5761
+ college: { type: "string", maxLength: 120, description: "\u6BD5\u4E1A\u9662\u6821" },
5762
+ graduateDate: { type: "string", description: "\u6BD5\u4E1A\u65F6\u95F4" },
5763
+ joinworkdate: { type: "string", description: "\u53C2\u52A0\u5DE5\u4F5C\u65E5\u671F" },
5764
+ intendPosition: { type: "string", maxLength: 120, description: "\u610F\u5411\u5C97\u4F4D" },
5765
+ intendedWorkplace: { type: "string", maxLength: 120, description: "\u671F\u671B\u5DE5\u4F5C\u5730\u70B9" },
5766
+ selfDesc: { type: "string", maxLength: 2e4, description: "\u81EA\u6211\u8BC4\u4EF7\uFF08\u957F\u6587\u672C\uFF09" },
5767
+ workAbility: { type: "string", maxLength: 2e4, description: "\u804C\u4E1A\u6280\u80FD/\u6280\u672F\u6808\uFF08\u957F\u6587\u672C\uFF09" },
5768
+ channel: { type: "string", maxLength: 60, description: "\u4EBA\u624D\u6765\u6E90\u6E20\u9053\u540D\u79F0\uFF08\u5982 \u667A\u8054\u62DB\u8058/\u5185\u63A8\uFF09" },
5769
+ tags: { type: "array", items: { type: "string" }, maxItems: 20, description: "\u5E73\u53F0\u6807\u7B7E\u540D\u79F0\uFF08\u987B\u4E3A\u672C\u73AF\u5883\u5DF2\u6709\u6807\u7B7E\uFF0C\u540C\u540D\u4F18\u5148\u516C\u5171\uFF1B\u4E0D\u81EA\u52A8\u521B\u5EFA\uFF09" },
5770
+ resumeFile: { type: "string", description: "\u7B80\u5386\u539F\u4EF6\u672C\u5730\u8DEF\u5F84\uFF08\u53EF\u9009\uFF1B\u63D0\u4F9B\u5219\u4E0A\u4F20\u5230\u539F\u59CB\u7B80\u5386\u9644\u4EF6\u5B57\u6BB5\uFF09" },
5771
+ academicInformations: {
5772
+ type: "array",
5773
+ maxItems: 20,
5774
+ description: "\u6559\u80B2\u7ECF\u5386\uFF08school/edu_major/edu_education/degree/study_date/faculty/research_direction/major_courses\uFF09",
5775
+ items: { type: "object" }
5776
+ },
5777
+ jobInformations: {
5778
+ type: "array",
5779
+ maxItems: 30,
5780
+ description: "\u5DE5\u4F5C\u7ECF\u5386\uFF08co_name/work_position/work_dept/work_desc/resign_cause/start_date/end_date/work_type\uFF09",
5781
+ items: { type: "object" }
5782
+ },
5783
+ internshipExperiences: {
5784
+ type: "array",
5785
+ maxItems: 20,
5786
+ description: "\u5B9E\u4E60\u7ECF\u5386\uFF08sx_co_name/position_job/job_description/entry_time/sx_work_type\uFF09",
5787
+ items: { type: "object" }
5788
+ },
5789
+ projectExperiences: {
5790
+ type: "array",
5791
+ maxItems: 30,
5792
+ description: "\u9879\u76EE\u7ECF\u5386\uFF08pj_name/pj_role/pj_duty/pj_introduction/start_date/end_date\uFF09",
5793
+ items: { type: "object" }
5794
+ },
5795
+ awardExperiences: {
5796
+ type: "array",
5797
+ maxItems: 20,
5798
+ description: "\u83B7\u5956\u7ECF\u5386\uFF08award_name/awarded/credentials/award_date\uFF09",
5799
+ items: { type: "object" }
5800
+ },
5801
+ languageAbilities: {
5802
+ type: "array",
5803
+ maxItems: 10,
5804
+ description: "\u8BED\u8A00\u80FD\u529B\uFF08language_type/mastery/ls_ability/literacy\uFF09",
5805
+ items: { type: "object" }
5806
+ }
5807
+ }, { required: ["candidateName", "telephone"] }),
5808
+ handler: async (args, env) => {
5809
+ const cache = await requireCache2(env);
5810
+ const plan = await buildImportPlan(env, cache, args);
5811
+ const dup = await checkDuplicateByMobile(env, cache, plan.mobile);
5812
+ if (dup.length > 1) {
5813
+ throw ehrValidationError("duplicate_ambiguous", `\u624B\u673A\u53F7 ${plan.mobile} \u5B58\u5728\u591A\u6761\u5019\u9009\uFF08\u6570\u636E\u5F02\u5E38\uFF09\uFF0C\u8BF7\u4EBA\u5DE5\u6838\u5BF9\u540E\u518D\u51B3\u5B9A\uFF0C\u4E0D\u81EA\u52A8\u65B0\u5EFA`);
5814
+ }
5815
+ const dupRow = dup[0];
5816
+ const session = await env.host.getSession();
5817
+ const continuation = await env.continuation.issue(
5818
+ {
5819
+ operation: "ehr.recruit.candidate.import.apply",
5820
+ baseUrl: session.baseUrl,
5821
+ profile: session.profile,
5822
+ userId: session.userId,
5823
+ payload: {
5824
+ objId: plan.objId,
5825
+ formId: plan.formId,
5826
+ mainTable: plan.mainTable,
5827
+ details: plan.details,
5828
+ tags: Array.isArray(args.tags) ? args.tags.map(String) : [],
5829
+ resumeFile: str(args.resumeFile),
5830
+ subStats: plan.subStats,
5831
+ warnings: plan.warnings,
5832
+ candidateName: plan.talentName,
5833
+ telephone: plan.mobile
5834
+ }
5835
+ },
5836
+ 10 * 60 * 1e3
5837
+ );
5838
+ return ehrSuccess("ehr.recruit.candidate.import.prepare", {
5839
+ status: "AWAITING_CONFIRMATION",
5840
+ preview: {
5841
+ action: "\u7B80\u5386\u5BFC\u5165\u5EFA\u4EBA\u624D\uFF08dataset/v2/saveFormData \u4E3B\u8868+\u660E\u7EC6 \u2192 \u6279\u6B21 \u2192 \u667A\u80FD\u6807\u7B7E \u2192 \u5E73\u53F0\u6807\u7B7E\uFF09",
5842
+ ...plan.summary,
5843
+ duplicate: dupRow ? `\u5DF2\u5B58\u5728\u540C\u624B\u673A\u53F7\u4EBA\u624D\u300C${dupRow.candidate_name || dupRow.name || ""}\u300D\uFF08id=${dupRow.form_data_id || dupRow.id}\uFF09\u2192 apply \u5C06\u963B\u65AD` : "\u65E0\u91CD\u590D"
5844
+ },
5845
+ willSubmit: {
5846
+ objId: plan.objId,
5847
+ mainTable: plan.mainTable,
5848
+ details: plan.details,
5849
+ tags: Array.isArray(args.tags) ? args.tags : []
5850
+ },
5851
+ continuation,
5852
+ expiresInSeconds: 600
5853
+ });
5854
+ }
5855
+ };
5856
+ var candidateImportApply = {
5857
+ name: "ehr.recruit.candidate.import.apply",
5858
+ resource: "recruit",
5859
+ method: "candidate.import.apply",
5860
+ action: "ehr.recruit.candidate.import.apply",
5861
+ summary: "\u6267\u884C\u7B80\u5386\u5BFC\u5165\u5EFA\u4EBA\u624D\uFF08\u4E3B\u8868+\u660E\u7EC6 \u2192 \u6279\u6B21 \u2192 \u667A\u80FD\u6807\u7B7E \u2192 \u5E73\u53F0\u6807\u7B7E \u2192 \u53CC\u94FE\u63A5\uFF09\uFF1B\u5FC5\u987B\u5148 prepare \u5E76\u7ECF\u7528\u6237\u660E\u786E\u786E\u8BA4",
5862
+ capability: "recruit",
5863
+ risk: WRITE,
5864
+ requiresConfirmation: true,
5865
+ inputSchema: schemaOf(
5866
+ {
5867
+ candidateName: { type: "string", maxLength: 60 },
5868
+ telephone: { type: "string", pattern: "^\\d{6,20}$" },
5869
+ resumeFile: { type: "string" },
5870
+ tags: { type: "array", items: { type: "string" }, maxItems: 20 },
5871
+ confirm: { const: true },
5872
+ continuation: { type: "string", minLength: 1 }
5873
+ },
5874
+ { required: ["candidateName", "telephone", "confirm", "continuation"] }
5875
+ ),
5876
+ handler: async (args, env) => {
5877
+ if (args.confirm !== true) {
5878
+ throw ehrConfirmationError("ehr.recruit.candidate.import.apply", {
5879
+ hint: "\u91CD\u65B0\u8C03\u7528\u65F6\u4F20\u5165 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation"
5880
+ });
5881
+ }
5882
+ const lease = await env.continuation.verify(args.continuation, "ehr.recruit.candidate.import.apply");
5883
+ const session = await env.host.getSession();
5884
+ if (lease.baseUrl !== session.baseUrl || lease.profile !== session.profile || lease.userId !== session.userId) {
5885
+ throw ehrValidationError("context_mismatch", "\u786E\u8BA4\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF08\u79DF\u6237\u6216\u767B\u5F55\u8D26\u53F7\u4E0D\u540C\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
5886
+ }
5887
+ const payload = lease.payload || {};
5888
+ if (payload.candidateName !== str(args.candidateName) || payload.telephone !== str(args.telephone)) {
5889
+ throw ehrValidationError("target_changed", "\u59D3\u540D\u6216\u624B\u673A\u53F7\u4E0E prepare \u65F6\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
5890
+ }
5891
+ const cache = await requireCache2(env);
5892
+ const objId = String(payload.objId);
5893
+ const formId = String(payload.formId);
5894
+ const fields = cache.fields[objId] || {};
5895
+ const mainTable = { ...payload.mainTable || {} };
5896
+ const resumeFieldKey = "original_resume";
5897
+ const resumeFile = str(payload.resumeFile);
5898
+ let uploaded = null;
5899
+ if (resumeFile) {
5900
+ if (!fields[resumeFieldKey]) {
5901
+ throw ehrValidationError("resume_field_missing", "\u4EBA\u624D\u8868\u5355\u65E0\u300C\u539F\u59CB\u7B80\u5386\u300D\u9644\u4EF6\u5B57\u6BB5\uFF08original_resume\uFF09\uFF0C\u65E0\u6CD5\u4E0A\u4F20\u539F\u4EF6");
5902
+ }
5903
+ uploaded = await uploadResumeFile(env, resumeFile, fields[resumeFieldKey], formId);
5904
+ mainTable[resumeFieldKey] = uploaded.fileid;
5905
+ }
5906
+ let talentId;
5907
+ try {
5908
+ talentId = await datasetSaveFormData(env, objId, mainTable, payload.details || {});
5909
+ } catch (error) {
5910
+ if (error?.subtype === "save_failed") throw error;
5911
+ throw ehrPartialError(
5912
+ `\u7B80\u5386\u5EFA\u6863\u5199\u5165\u7ED3\u679C\u4E0D\u786E\u5B9A\uFF08${error?.message || "\u672A\u77E5\u9519\u8BEF"}\uFF09\uFF1A\u8BF7\u5148\u7528\u4EBA\u624D\u5E93\u641C\u7D22\u624B\u673A\u53F7 ${payload.telephone} \u6838\u5BF9\u662F\u5426\u5DF2\u5EFA\u6863\uFF0C\u7981\u6B62\u76F4\u63A5\u91CD\u8BD5`,
5913
+ { candidateName: payload.candidateName, telephone: payload.telephone }
5914
+ );
5915
+ }
5916
+ let batchOk = null;
5917
+ let batchNote;
5918
+ try {
5919
+ await env.host.request({
5920
+ path: `/api/recruit/candidate/initTalentBatch?formDataId=${encodeURIComponent(talentId)}`,
5921
+ method: "POST",
5922
+ operation: "ehr.recruit.candidate.import.apply"
5923
+ });
5924
+ batchOk = true;
5925
+ } catch (error) {
5926
+ batchOk = false;
5927
+ batchNote = `\u4EBA\u624D\u5DF2\u5EFA\u6863\uFF0C\u4F46\u521D\u59CB\u5316\u4EBA\u624D\u6279\u6B21\u5931\u8D25\uFF1A${error?.message || "\u672A\u77E5\u9519\u8BEF"}\uFF08\u53EF\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u5904\u7406\uFF09`;
5928
+ }
5929
+ let labelMatch = null;
5930
+ try {
5931
+ const r = await env.host.request({
5932
+ path: `/api/recruit/label/matchTalentLabel?talentId=${encodeURIComponent(talentId)}`,
5933
+ method: "POST",
5934
+ body: {},
5935
+ operation: "ehr.recruit.candidate.import.apply"
5936
+ });
5937
+ labelMatch = r?.data === void 0 ? "TRIGGERED" : String(r.data);
5938
+ } catch {
5939
+ labelMatch = "FAILED\uFF08\u4E0D\u5F71\u54CD\u5EFA\u6863\uFF0C\u53EF\u7A0D\u540E\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u89E6\u53D1\uFF09";
5940
+ }
5941
+ let tagResult = { applied: [], skipped: [] };
5942
+ try {
5943
+ tagResult = await applyPlatformTags(env, talentId, Array.isArray(payload.tags) ? payload.tags.map(String) : []);
5944
+ } catch (error) {
5945
+ tagResult = { applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] };
5946
+ }
5947
+ const baseUrl = session.baseUrl.replace(/\/+$/, "");
5948
+ const extra = String(cache.selfUse) === "1" ? "&recruitType=useSelf" : "";
5949
+ const talentCardUrl = cache.ebdDetailPageId ? `${baseUrl}/sp/ebdpage/view/${cache.ebdDetailPageId}?talentId=${talentId}${extra}` : null;
5950
+ const talentListId = cache.lists.talent?.listId;
5951
+ const talentListLocateUrl = talentListId ? `${baseUrl}/sp/ebdfpage/list/${talentListId}?talentId=${talentId}${extra}` : null;
5952
+ const warnings = [...payload.warnings || []];
5953
+ if (batchNote) warnings.push(batchNote);
5954
+ return ehrSuccess("ehr.recruit.candidate.import.apply", {
5955
+ result: "success",
5956
+ talentId,
5957
+ candidateName: payload.candidateName,
5958
+ telephone: payload.telephone,
5959
+ mainTableFields: Object.keys(mainTable).length,
5960
+ detailRows: payload.subStats || void 0,
5961
+ attachment: uploaded ? { name: uploaded.name, size: uploaded.size } : null,
5962
+ batch: { ok: batchOk, note: batchNote },
5963
+ labelMatch,
5964
+ tagsApplied: tagResult.applied,
5965
+ tagsSkipped: tagResult.skipped,
5966
+ talentCardUrl,
5967
+ talentListLocateUrl
5968
+ }, warnings.length ? { warnings } : void 0);
5969
+ }
5970
+ };
5971
+ var recruitCandidateImportOperations = [
5972
+ candidateImportPrepare,
5973
+ candidateImportApply
5974
+ ];
5975
+
4825
5976
  // src/shortcuts/ehr/operations/salary.ts
4826
5977
  function requireMonthRange(value, field) {
4827
5978
  if (!Array.isArray(value) || value.length === 0) {
@@ -5003,7 +6154,10 @@ function buildRegistry() {
5003
6154
  ...hrDataSourceOperations,
5004
6155
  ...hrReportOperations,
5005
6156
  ...recruitOperations,
5006
- ...recruitWriteOperations
6157
+ ...recruitWriteOperations,
6158
+ ...recruitStatsOperations,
6159
+ ...recruitPositionOperations,
6160
+ ...recruitCandidateImportOperations
5007
6161
  ];
5008
6162
  for (const definition of definitions) {
5009
6163
  if (registry.has(definition.name)) {
@@ -5114,7 +6268,7 @@ async function inputFrom(options, extra = {}) {
5114
6268
  if (opts.input) {
5115
6269
  let raw;
5116
6270
  try {
5117
- raw = stripBom(opts.input === "-" ? await readStdin() : await readFile2(String(opts.input), "utf8"));
6271
+ raw = stripBom(opts.input === "-" ? await readStdin() : await readFile3(String(opts.input), "utf8"));
5118
6272
  } catch {
5119
6273
  throw ehrValidationError("input_unreadable", `\u65E0\u6CD5\u8BFB\u53D6 --input\uFF1A${String(opts.input)}`);
5120
6274
  }