weaver-work-cli 0.1.40 → 0.1.42

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 (185) hide show
  1. package/dist/chunks/{archive-JHTONRST.js → archive-J4I6MCKF.js} +2 -2
  2. package/dist/chunks/{archive-oa-FCHLCPHC.js → archive-oa-BRZKKTO4.js} +2 -2
  3. package/dist/chunks/{asset-RLIHC7DB.js → asset-L7D4FAOZ.js} +2 -2
  4. package/dist/chunks/{asset-idle-KVOFTLCP.js → asset-idle-DADLLV75.js} +2 -2
  5. package/dist/chunks/{attachment-content-RZYDB3MB.js → attachment-content-K4C7VLWQ.js} +3 -3
  6. package/dist/chunks/{blog-42OZTJNP.js → blog-BVGQ7NZL.js} +2 -2
  7. package/dist/chunks/{caizhilian-KRK547K5.js → caizhilian-SAADNFD6.js} +2 -2
  8. package/dist/chunks/{calendar-RTWAMKHD.js → calendar-Q7NQY5Z2.js} +61 -23
  9. package/dist/chunks/{chunk-LFMSDBZN.js → chunk-3KTFS4IA.js} +308 -153
  10. package/dist/chunks/{chunk-G2JSIUWF.js → chunk-4PD5NWAX.js} +89 -0
  11. package/dist/chunks/{chunk-T6EGVBKU.js → chunk-4RAE6JXP.js} +1 -1
  12. package/dist/chunks/{chunk-7BRU4EFH.js → chunk-72CKAUAG.js} +29 -2
  13. package/dist/chunks/{chunk-NETCCARD.js → chunk-APVFJUQH.js} +2 -2
  14. package/dist/chunks/{chunk-CAQNBBQA.js → chunk-BBKDXQEC.js} +2 -2
  15. package/dist/chunks/{chunk-57IECMWX.js → chunk-BIPYLLVS.js} +26 -12
  16. package/dist/chunks/{chunk-LN447PY2.js → chunk-EKWAQSLU.js} +3 -2
  17. package/dist/chunks/{chunk-4TEDNCON.js → chunk-FOAA27U5.js} +338 -52
  18. package/dist/chunks/{chunk-7U577Q7U.js → chunk-G4UR6NXN.js} +2 -2
  19. package/dist/chunks/{chunk-NJKREDA3.js → chunk-GEWYMQME.js} +1 -1
  20. package/dist/chunks/{chunk-I566ZYNF.js → chunk-GHXCDPTM.js} +1 -1
  21. package/dist/chunks/{chunk-4CTESSKI.js → chunk-IZ7S7QUS.js} +4 -4
  22. package/dist/chunks/{chunk-VNBU55SL.js → chunk-JPRO6ER2.js} +57 -2432
  23. package/dist/chunks/{chunk-IZSSVYAG.js → chunk-LADPYOWC.js} +2 -2
  24. package/dist/chunks/chunk-LDZQPUIA.js +1238 -0
  25. package/dist/chunks/chunk-NKZRQXST.js +2546 -0
  26. package/dist/chunks/{chunk-JWRZM2H2.js → chunk-QKNKR4RH.js} +3 -3
  27. package/dist/chunks/{chunk-FLS4DPGP.js → chunk-R4CHUSKC.js} +28 -15
  28. package/dist/chunks/{chunk-WFFNM65B.js → chunk-SA6VBIHY.js} +73 -19
  29. package/dist/chunks/{chunk-SPRHHSVC.js → chunk-TTPJJJC4.js} +2 -2
  30. package/dist/chunks/{chunk-7E6MUOEK.js → chunk-W7BEHOSR.js} +2 -2
  31. package/dist/chunks/{chunk-CXRQWOZ5.js → chunk-YRSZQUD2.js} +2 -2
  32. package/dist/chunks/{conflict-VR55AOOO.js → conflict-F2OMZRTO.js} +2 -2
  33. package/dist/chunks/{contract-HI4FNPYE.js → contract-5BETHRSG.js} +2 -2
  34. package/dist/chunks/{cowork-HJLI353D.js → cowork-3MN6EQQO.js} +22 -12
  35. package/dist/chunks/create-flow-5FQNNMVO.js +55 -0
  36. package/dist/chunks/{ebuilder-form-HTGI63UU.js → ebuilder-form-SBHOYBUD.js} +3 -3
  37. package/dist/chunks/{ehr-GYXIYH3A.js → ehr-KMOJULKG.js} +432 -1234
  38. package/dist/chunks/{env-DW3G4HUO.js → env-LB7NBL2O.js} +2 -2
  39. package/dist/chunks/{esb-I5INCEFE.js → esb-W2PJCFCX.js} +4 -4
  40. package/dist/chunks/{factory-TKXGXS6L.js → factory-6ZFQXQ46.js} +1 -1
  41. package/dist/chunks/{fna-K2MHTQ24.js → fna-ZQPCUV4R.js} +2 -2
  42. package/dist/chunks/{group-chat-VYBNMJLG.js → group-chat-2HHAJN46.js} +5 -3
  43. package/dist/chunks/{host-ZUQTJYYK.js → host-4CBHGOHT.js} +3 -3
  44. package/dist/chunks/{host-D5SERMAJ.js → host-ATKVNZAT.js} +3 -3
  45. package/dist/chunks/{host-JM4YVHFM.js → host-BQH22NTQ.js} +3 -3
  46. package/dist/chunks/{host-L3VLITMT.js → host-X2CSLFM6.js} +3 -3
  47. package/dist/chunks/{host-256GVCAH.js → host-YTODKMSL.js} +3 -3
  48. package/dist/chunks/{hrm-VLRBKTZB.js → hrm-FFM4UJFS.js} +4 -4
  49. package/dist/chunks/{im-QK3VTLXK.js → im-VEHKDQPB.js} +7 -7
  50. package/dist/chunks/{invoice-T5JTA32H.js → invoice-LVIKSIIF.js} +3 -3
  51. package/dist/chunks/{jiuchuanhui-P2FNEQVZ.js → jiuchuanhui-X6DINO5P.js} +2 -2
  52. package/dist/chunks/{lazy-dispatch-XRRI46M6.js → lazy-dispatch-KSWTN5L6.js} +4 -4
  53. package/dist/chunks/{mail-3Y7MJ6PS.js → mail-VDKRGUD3.js} +2 -2
  54. package/dist/chunks/{meeting-M7LTXGJE.js → meeting-CLC6HP3Z.js} +12 -11
  55. package/dist/chunks/{okr-OBC6S67L.js → okr-CHG4OO3U.js} +2 -2
  56. package/dist/chunks/{plan-5H6I53SK.js → plan-XWR75667.js} +2 -2
  57. package/dist/chunks/{project-L75QZV4S.js → project-5BXOOKMG.js} +40 -23
  58. package/dist/chunks/recruit-stage-DGMFNNDE.js +4507 -0
  59. package/dist/chunks/{registry-RXPN6BBT.js → registry-7FFOXIAW.js} +4 -4
  60. package/dist/chunks/{registry-KMHCPAAD.js → registry-BKBZPBAJ.js} +10 -9
  61. package/dist/chunks/{registry-QGHFNUWS.js → registry-OZSMDVPP.js} +2 -2
  62. package/dist/chunks/{registry-UGRBCBHO.js → registry-RHMW6ANW.js} +2 -2
  63. package/dist/chunks/{registry-NYPYMZXG.js → registry-Z43434VG.js} +1 -1
  64. package/dist/chunks/{room-recommend-A3UDC3CA.js → room-recommend-62H7ZQQ6.js} +4 -4
  65. package/dist/chunks/{schedule-5GCACCK7.js → schedule-FNXKH3DQ.js} +4 -4
  66. package/dist/chunks/{workflow-M5ZJ7DWF.js → workflow-ADHKCAJK.js} +6 -6
  67. package/dist/index.js +33 -28
  68. package/dist/internal/e10/auth/commands.js +1 -0
  69. package/dist/internal/e10/auth/messages.js +6 -0
  70. package/dist/internal/e10/auth/session.js +17 -0
  71. package/dist/internal/e10/auth/xiaoe.js +286 -44
  72. package/dist/internal/e10/auth-recovery.js +36 -5
  73. package/dist/internal/e10/context.js +56 -12
  74. package/dist/internal/e10/index.js +1 -1
  75. package/dist/internal/e10/network-error.js +93 -0
  76. package/dist/internal/e10/request-runtime.js +6 -0
  77. package/dist/shortcuts/calendar/operations/read.js +31 -22
  78. package/dist/shortcuts/calendar/operations/write.js +45 -1
  79. package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
  80. package/dist/shortcuts/cowork/operations/item-write.js +1 -7
  81. package/dist/shortcuts/cowork/operations/member-write.js +3 -1
  82. package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
  83. package/dist/shortcuts/cowork/operations/shared.js +7 -0
  84. package/dist/shortcuts/ehr/operations/attend-write.js +43 -1
  85. package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
  86. package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
  87. package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +134 -59
  88. package/dist/shortcuts/ehr/operations/recruit-write.js +262 -17
  89. package/dist/shortcuts/ehr/operations/recruit.js +10 -4
  90. package/dist/shortcuts/ehr/operations/shared.js +47 -0
  91. package/dist/shortcuts/hrm/operations/org.js +118 -0
  92. package/dist/shortcuts/index.js +5 -0
  93. package/dist/shortcuts/meeting/operations/eb/catalog.js +4 -1
  94. package/dist/shortcuts/meeting/operations/eb/create-flow.js +85 -28
  95. package/dist/shortcuts/meeting/operations/eb/factory.js +33 -0
  96. package/dist/shortcuts/meeting/operations/eb/group-chat.js +25 -3
  97. package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
  98. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +33 -11
  99. package/dist/shortcuts/project/operations/read.js +6 -25
  100. package/dist/shortcuts/project/operations/shared.js +22 -0
  101. package/dist/shortcuts/project/operations/write.js +28 -2
  102. package/dist/shortcuts/recruit-stage/context.js +119 -0
  103. package/dist/shortcuts/recruit-stage/continuation.js +73 -0
  104. package/dist/shortcuts/recruit-stage/errors.js +65 -0
  105. package/dist/shortcuts/recruit-stage/host.js +109 -0
  106. package/dist/shortcuts/recruit-stage/index.js +115 -0
  107. package/dist/shortcuts/recruit-stage/manifest.js +29 -0
  108. package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
  109. package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
  110. package/dist/shortcuts/recruit-stage/operations/jd-create.js +630 -0
  111. package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
  112. package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
  113. package/dist/shortcuts/recruit-stage/operations/resume-import.js +1198 -0
  114. package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
  115. package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
  116. package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
  117. package/dist/shortcuts/recruit-stage/shared.js +608 -0
  118. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
  119. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +13 -6
  120. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
  121. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
  122. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +50 -8
  123. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +2 -1
  124. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
  125. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +7 -39
  126. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
  127. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +51 -15
  128. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
  129. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
  130. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
  131. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +39 -14
  132. package/docs/e10-auth.md +7 -1
  133. package/docs/operation-manual.md +8 -0
  134. package/package.json +1 -1
  135. package/scripts/install-skill-to-xiaoe.mjs +105 -0
  136. package/scripts/package-skill.mjs +4 -2
  137. package/skill-template/business-info.json +24 -0
  138. package/skill-template/domains/recruit-stage.md +29 -0
  139. package/skills/weaver-e10-calendar/SKILL.md +2 -1
  140. package/skills/weaver-e10-calendar/references/calendar-write.md +54 -0
  141. package/skills/weaver-e10-cowork/SKILL.md +1 -1
  142. package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
  143. package/skills/weaver-e10-jucailin/SKILL.md +1 -1
  144. package/skills/weaver-e10-jucailin/references/attend-write.md +8 -0
  145. package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
  146. package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
  147. package/skills/weaver-e10-jucailin/references/recruit-create.md +2 -2
  148. package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
  149. package/skills/weaver-e10-jucailin/references/recruit-write.md +4 -3
  150. package/skills/weaver-e10-mail/SKILL.md +1 -1
  151. package/skills/weaver-e10-meeting/SKILL.md +32 -2
  152. package/skills/weaver-e10-meeting.zip +0 -0
  153. package/skills/weaver-e10-recruit-stage/SKILL.md +226 -0
  154. package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
  155. package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
  156. package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
  157. package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
  158. package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
  159. package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
  160. package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
  161. package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +73 -0
  162. package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
  163. package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
  164. package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
  165. package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
  166. package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
  167. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
  168. package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
  169. package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +438 -0
  170. package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
  171. package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
  172. package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
  173. package/skills/weaver-e10-shared/SKILL.md +1 -1
  174. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -2
  175. package/skills/weaver-e10-shijingran/SKILL.md +3 -2
  176. package/skills/weaver-e10-shijingran/references/operations.md +3 -1
  177. package/skills/weaver-e10-shijingran/references/source-manifest.json +41 -40
  178. package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
  179. package/skills/weaver-e10-workflow/SKILL.md +4 -2
  180. package/skills/weaver-e10-workflow/aigroup/default.json +11 -9
  181. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +23 -13
  182. package/skills/weaver-e10-workflow/tools/todo-summary.cjs +62 -20
  183. package/skills/weaver-e10-yepiaotong/SKILL.md +9 -10
  184. package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
  185. package/dist/chunks/{chunk-E7OK5WD5.js → chunk-2LV74IWP.js} +5 -5
@@ -0,0 +1,142 @@
1
+ # 提交/修改面试反馈(组合写操作)
2
+
3
+ > **平台兼容**:本文命令示例在 macOS/Linux 与 Windows PowerShell 下均可执行——JSON 用单引号包裹、内部双引号不转义;PowerShell 下不使用反斜杠续行。
4
+
5
+ ## 1. 接口概述
6
+
7
+ 把「提交面试评价」按钮的完整动作链固化为可调用的组合写操作:保存面试反馈表单(更新结果/评价)+ 触发按钮绑定的 esb 动作流 + 写招聘过程日志(`addProcessLog`)。通过**按钮动作智能解析**(粗定位 → 精核验 → 拆解执行 → 回查校验)在任意环境自适应,不依赖按钮名/ID。
8
+
9
+ ## 2. 业务用途
10
+
11
+ 用户在面试详情里填写/修改某场面试的反馈结果(通过/不通过/待定)与评价文字并提交。系统侧点击「提交评价」按钮实际触发三段动作:
12
+ 1. **保存反馈表单**(EB `saveFormData`,更新 `interview_detail` 表单对应反馈记录);
13
+ 2. **触发动作流**(EB `runEsb`,按钮配置的 esb 动作流:面试安排-填写反馈 / 全部面试反馈完成-更新日程状态 / 招聘recruit-面试反馈提醒 等);
14
+ 3. **写招聘过程日志**(招聘专属接口 `POST /api/recruit/processLog/addProcessLog`,把结果/评价落到招聘业务过程流,`processEnum=20` 标识"提交面试评价")。
15
+
16
+ > **适用基线**:`addProcessLog` 为招聘标准接口(路径/入参由招聘应用代码固定,客户搭建不影响);表单/按钮为 EB 配置物,运行时解析。调用前经能力探测确认。
17
+
18
+ ## 3. 前置条件
19
+
20
+ - 已登录(`weaver-work-cli auth status` 通过),环境参数缓存含 `interview_detail` 表单(tag 自动解析)。
21
+ - 候选人有可编辑的面试反馈记录(`getCandidateCardInterviewInfo` 返回 `interviewFeedBack`,含 `optCanEdit:true`)。
22
+ - 能力探测:反馈表单、按钮配置、`addProcessLog` 可用;缺失即拦截提示。
23
+
24
+ ## 4. 请求参数
25
+
26
+ ### 4.1 定位参数(脚本入口)
27
+
28
+ | 参数 | 必填 | 说明 |
29
+ |---|---|---|
30
+ | `--talent-id` / `--mobile` | 二选一 | 候选人定位(talentId 优先) |
31
+ | `--feedback-id` | 选填 | 直接指定反馈记录 id(=`interviewFeedBack[0].id`=`formDataId`=`businessId`),最稳;缺省取第一场含反馈的面试(可 `--plan-index` 指定) |
32
+ | `--result` | 选填 | 新面试结果中文(通过/不通过/待定),经 `ds/options` 解析 optionId |
33
+ | `--comment` | 选填 | 新评价文字 |
34
+ | `--prepare` / `--commit` | 写操作模式 | prepare=只定位+校验+确认摘要不写;commit=真实执行 |
35
+
36
+ ### 4.2 关键接口入参
37
+
38
+ | 步骤 | 接口 | 方法/入参 |
39
+ |---|---|---|
40
+ | 反馈记录定位 | `getCandidateCardInterviewInfo` | `POST` body `{talentId, batchId, current:1, pageSize:20}` → `data.list[i].interviewFeedBack[0]`:`id`(=formDataId)、`result[]`、`judgement`、`interviewPlanId[]`、`interviewer[]` |
41
+ | 反馈记录数据 | `getFormDataAndLayout` | `POST /api/ebuilder/form/form/core/getFormDataAndLayout?formId=<反馈表单formId>&dataId=<反馈记录id>`,body 见 §5 → `data.formData.{id, updateTimeStamp, dataDetails}` + `data.formLayout.id` |
42
+ | 按钮粗定位 | `getFormButtons` | `POST /api/ebuilder/form/data/getFormButtons`,body `{layoutType:"formLayout", objId, dataId, formDataId:dataId, type:"2", ...}` → 找 `actionType=system` 或 `buttonKey=editSave` 的按钮 |
43
+ | 保存反馈 | `saveFormData` | `POST /api/ebuilder/form/form/core/saveFormData?formId=<formId>`,`formData.id`=反馈记录id、`updateTimeStamp`=最新、`dataDetails`=全字段集(防清空)、`formLayout.id`=`getFormDataAndLayout` 的 formLayout.id(⚠️ 更新场景勿用 `getFormLayout`:部分版本 GET 405,虽然 `write-op.mjs::getFormLayout` 已加 POST 回退,但记录级布局以 `getFormDataAndLayout` 为准) |
44
+ | 动作流 | `runEsb` | `POST /api/ebuilder/form/esb/runEsb?objId=<objId>`,body `{dataIds:<反馈记录id>, esbActionIds:<按钮 esb actions id 逗号拼接>}` |
45
+ | 写过程日志 | `addProcessLog` | `POST /api/recruit/processLog/addProcessLog`,body `{talentId, batchId, result:<结果optionId>, judgement:"<p>评价</p>", businessId:<反馈记录id>, processEnum:"20"}` |
46
+
47
+ ## 5. 请求示例
48
+
49
+ ```bash
50
+ # ① 反馈记录定位(拿 batchId 后)
51
+ curl -s -X POST "${BASE_URL}/api/recruit/candidate/getCandidateCardInterviewInfo" \
52
+ -H "Content-Type: application/json" -H "Cookie: ${COOKIE}" -H "eteamsid: ${ETEAMSID}" \
53
+ -H "langType: zh_CN" -H "timeZoneOffset: -480" -H "Accept: application/json" \
54
+ -d '{"talentId":"<talentId>","batchId":"<batchId>","current":1,"pageSize":20}'
55
+ # → data.list[i].interviewFeedBack[0] = {id:"<反馈记录id>", result:[{id,name}], judgement:"<p>…</p>", ...}
56
+
57
+ # ② 保存反馈(全字段集 + updateTimeStamp 乐观锁)
58
+ curl -s -X POST "${BASE_URL}/api/ebuilder/form/form/core/saveFormData?formId=<formId>" \
59
+ -H "Content-Type: application/json" -H "Cookie: ${COOKIE}" -H "eteamsid: ${ETEAMSID}" \
60
+ -H "langType: zh_CN" -H "timeZoneOffset: -480" -H "Accept: application/json" \
61
+ -d '{
62
+ "module":"ebuilderform","appId":"<appId>",
63
+ "customParam":{"objId":"<objId>","name":"面试反馈-<面试主题>","firstDataName":"面试反馈-<面试主题>","isFlowEnd":false,"otherOperator":"","dataStatus":"submit","rightType":"2","appId":"<appId>"},
64
+ "formData":{
65
+ "id":"<反馈记录id>","updateTimeStamp":"<最新>","module":"ebuilderform","client":"pc","dataStatus":"submit",
66
+ "form":{"id":"<formId>"},"formLayout":{"id":"<getFormDataAndLayout的formLayout.id>"},
67
+ "dataDetails":[
68
+ {"formField":{"id":"<result字段id>"},"dataOptions":[{"optionId":"<结果optionId>","content":"不通过"}]},
69
+ {"formField":{"id":"<judgement字段id>"},"dataText":{"content":"<p>太随意了,不合适</p>"}},
70
+ {"formField":{"id":"<面试主题字段id>"},"dataOptions":[{"optionId":"<面试计划id>","content":"<面试主题>"}]},
71
+ {"formField":{"id":"<batchId字段id>"},"dataOptions":[{"optionId":"<batchId>","content":"<batchId>"}]},
72
+ {"formField":{"id":"<人才字段id>"},"dataOptions":[{"optionId":"<talentId>","content":"<姓名>"}]},
73
+ {"formField":{"id":"<反馈人字段id>"},"dataOptions":[{"optionId":"<反馈人id>","content":"<反馈人>"}]}
74
+ ]
75
+ }
76
+ }'
77
+
78
+ # ③ 动作流
79
+ curl -s -X POST "${BASE_URL}/api/ebuilder/form/esb/runEsb?objId=<objId>" \
80
+ -H "Content-Type: application/json" -H "Cookie: ${COOKIE}" -H "eteamsid: ${ETEAMSID}" \
81
+ -H "langType: zh_CN" -H "timeZoneOffset: -480" -H "Accept: application/json" \
82
+ -d '{"dataIds":"<反馈记录id>","esbActionIds":"<按钮esb动作id1>,<id2>,<id3>","objId":"<objId>"}'
83
+
84
+ # ④ 写招聘过程日志
85
+ curl -s -X POST "${BASE_URL}/api/recruit/processLog/addProcessLog" \
86
+ -H "Content-Type: application/json" -H "Cookie: ${COOKIE}" -H "eteamsid: ${ETEAMSID}" \
87
+ -H "langType: zh_CN" -H "timeZoneOffset: -480" -H "Accept: application/json" \
88
+ -d '{"talentId":"<talentId>","batchId":"<batchId>","result":"<结果optionId>","judgement":"<p>太随意了,不合适</p>","businessId":"<反馈记录id>","processEnum":"20"}'
89
+ ```
90
+
91
+ ## 6. 响应参数
92
+
93
+ | 接口 | 成功标志 | 说明 |
94
+ |---|---|---|
95
+ | `saveFormData` | `status:true` / `code:200` | 返回 `data.id`(=反馈记录id) |
96
+ | `runEsb` | `data.successNum` ≥1 | 触发动作流数 |
97
+ | `addProcessLog` | `data:"SUCCESS"` | 过程日志写入成功 |
98
+ | 回查 | `getCandidateCardInterviewInfo` 该反馈 `result`/`judgement` 已变 | 闭环校验 |
99
+
100
+ ## 7. 错误码 / 失败边界
101
+
102
+ - **按钮匹配不到**(`getFormButtons` 无 system/editSave 按钮):拦截提示「当前环境未找到提交评价按钮,可能已被客户调整」,不硬猜。
103
+ - **saveFormData 后端 `layoutVersion null`**:`formLayout.id` 必须用 `getFormDataAndLayout` 的 `formLayout.id`,**不要用 `getFormLayout`**(部分版本该接口 GET 直接 405;`write-op.mjs::getFormLayout` 虽已加 POST 回退,但更新既有记录仍以 `getFormDataAndLayout` 为准)。
104
+ - **乐观锁冲突**:`updateTimeStamp` 必须提交前实时取(每次保存会更新),提交失败提示重试。
105
+ - **结果枚举解析不到**(`ds/options` 无该名称):列可选项请用户确认,不臆造 optionId。
106
+ - **反馈记录无权限/不存在**:`getFormDataAndLayout` 的 `formData` 为空 → 提示无权限或记录不存在。
107
+ - **部分失败**:saveFormData 成功但 runEsb/addProcessLog 失败 → 如实上报「已完成 X / 失败 Y」,不回滚不重试。
108
+
109
+ ## 8. 注意事项
110
+
111
+ - **全字段集防清空**:`dataDetails` 必须带反馈记录全部字段(面试主题/batchId/人才/反馈人/结果/评价等),只改 result/judgement 两个字段的值,缺失字段会导致保存时清空(技能红线:不得整条用空字段集覆盖)。
112
+ - **updateTimeStamp 是乐观锁**:提交用最新值;prepare 与 commit 间被他人修改会失效,commit 前需重新获取。
113
+ - **jsCode 动作不解析执行**:按钮的 `jsCode`(如"记录应聘过程")内联 JS 里的招聘 API(`addProcessLog`)按标准契约**直接调用**,不模拟执行前端 JS;刷新/关闭等前端行为技能不执行。
114
+ - **按钮动作分类**:`system`→保存;`esb`→runEsb;`jsCode`→提取其中后端 API 按契约直调(条件型说明、无法解析拦截)。
115
+ - **跨环境自适应**:不依赖按钮名/ID——以 `actionType`/`buttonKey=editSave`/URL 特征(`/api/recruit/processLog/addProcessLog`)定位;esb 动作流 id 运行时按钮解析,不写死。
116
+
117
+ ## 9. 调用编排(组合写操作)
118
+
119
+ ```
120
+ 定位候选人(talentId) → getCandidateCardPrepareQuery 取 batchId
121
+ → getCandidateCardInterviewInfo 取反馈记录(interviewFeedBack[0].id/result/judgement)
122
+ → getFormDataAndLayout 取 updateTimeStamp + 全字段 + formLayout.id
123
+ → getFormButtons(type=2+dataId) 粗定位提交按钮(system/editSave)
124
+ → analyzeButtonActions 精核验(esbIds + jsCode 招聘 API)
125
+ → [prepare] 确认摘要(候选人/面试/当前反馈/新反馈/将执行动作)
126
+ → [commit] saveFormData(全字段+最新updateTimeStamp) → runEsb(esbIds) → addProcessLog
127
+ → 回查 getCandidateCardInterviewInfo 校验已生效
128
+ ```
129
+
130
+ ## 10. 关联接口
131
+
132
+ - 前置:`getCandidateCardPrepareQuery`(取 batchId)、`getCandidateCardInterviewInfo`(面试+反馈卡片)、`getFormDataAndLayout`(反馈记录数据/updateTimeStamp/formLayout)。
133
+ - 平行:`saveFormData`(EB 通用保存)、`runEsb`(EB 通用动作流)、`addProcessLog`(招聘过程日志)。
134
+ - 关联:`recruit-urge-feedback.md`(催评,另一反馈动作流入口);`recruit-detail-process.md`(应聘过程卡片,展示 addProcessLog 写入的过程日志)。
135
+
136
+ ## 11. 产物链接(recruit-stage CLI)
137
+
138
+ `interview.feedback.edit.apply` 成功后返回两个可直接展示的字段:
139
+ - `talentCardUrl`:该人才卡片(点进去可看此候选人的面试与全部反馈);
140
+ - `interviewListUrl`:面试管理列表页。
141
+
142
+ 展示时作为可点击链接给用户(Markdown 链接),缺字段表示当前环境未配置对应页面,不补造。
@@ -0,0 +1,73 @@
1
+ # 招聘启事智能生成 —— 任务主文档(对话生成 JD → 确认 → 自动落库 → 打开列表)
2
+
3
+ > **平台兼容**:本文命令示例在 macOS/Linux 与 Windows PowerShell 下均可执行——JSON 用单引号包裹、内部双引号不转义;PowerShell 下不使用反斜杠续行。
4
+
5
+ ## 基础信息
6
+
7
+ | 项目 | 内容 |
8
+ |---|---|
9
+ | 对应需求 | 【人事招聘阶段】2. 招聘启事智能生成(小e 对话触发) |
10
+ | 脚本 | `scripts/recruit-generate-jd.mjs` |
11
+ | 写接口 | `POST /api/ebuilder/form/form/core/saveFormData`(职位管理)→ `POST /api/recruit/candidate/addPosition`(生成职位,body 只带 formDataId,两步流) |
12
+ | 输出结果 | 岗位 JD 初稿(对话展示)+ **两个 Markdown 链接**(职位详情查看页 / 招聘岗位列表·已定位新建职位) |
13
+ | 用途类型 | 用户场景 / **写操作** |
14
+
15
+ ## 交互流程(与需求逐条对应)
16
+
17
+ | 需求原文 | 实现 |
18
+ |---|---|
19
+ | 1)招聘人员在小e中输入岗位需求描述,并「帮我生成这个岗位的JD」 | 对话抽取岗位要素(名称/职责/要求/人数…),缺项先问 |
20
+ | 2)按照企业招聘标准及岗位要求生成招聘启事和岗位JD初稿 | Agent 按 `recruit-jd-template.md`(企业标准模板)生成**招聘启事 + JD 初稿**,全文展示在对话里 |
21
+ | 3)确认后自动生成到招聘岗位列表中 | 用户确认后跑脚本 `--commit` 自动落库;成功后输出两个 Markdown 链接:职位详情查看页 + **招聘岗位列表(已定位新建职位)** |
22
+ | 交互方式:小e对话框 + 右侧窗口打开招聘岗位列表 | 卡片由前端渲染(标题 + 「在 E10 中打开」按钮)→ 新 tab 打开列表(右栏 iframe 因 SameSite 不可行,见 `recruit-output-links.md`) |
23
+ | 输出结果:岗位JD初稿 | JD 初稿全文在对话里给出;落库的职位记录含职责/要求字段 |
24
+
25
+ ## 使用流程(Agent 执行约定)
26
+
27
+ 1. **抽取岗位要素**:职位名称(必缺先问)、职责、任职要求、招聘人数、用人部门等。信息不足先问,不猜。
28
+ 2. **生成 JD 初稿**:按 `recruit-jd-template.md` 的企业标准模板生成招聘启事 + 岗位 JD(职责 4~6 条、要求 4~6 条,贴合用户给的岗位描述)。**全文展示给用户**——这就是需求的"输出结果"。
29
+ 3. **字段推导**:从需求 + JD 推导职位管理字段值;不确定的列出来问用户。
30
+ 4. **`--prepare`(只读,不写库)**:脚本自动补全必填默认值(状态=招聘中、招聘流程=环境默认流程、招聘负责人/用人经理=当前登录人等),输出确认摘要。把摘要**用中文复述**给用户(不展示字段 key 与内部 id)。
31
+ 5. **用户明确确认后**才 `--commit`(写真实数据)。
32
+ 6. **输出产物**:把脚本输出的**两个 Markdown 链接**按顺序放在回答正文里:先 `viewLink`(新建职位详情查看页),再 `listLocateLink`(招聘岗位列表 + 自动滑出本次新建职位详情的组合页);JD 初稿全文在正文里。**不要用 browsertool 卡片**(fill_form 在非表单页卡死,实测;见 `recruit-output-links.md`)。
33
+ 7. **告知**:「职位已建好,点卡片上的『在 E10 中打开』可查看招聘岗位列表;JD 初稿如需调整,告诉我改哪里,我更新后再建」。
34
+
35
+ ## 脚本用法
36
+
37
+ ```bash
38
+ # ① 只出确认摘要(不写库)
39
+ node scripts/recruit-generate-jd.mjs --prepare \
40
+ --position-name "Java开发工程师" \
41
+ --position-duty "<职责正文,可多段>" \
42
+ --work-request "<任职要求正文,可多段>" \
43
+ [--set <字段dataKey>=<值> ...] # AI 依 JD 指定字段值(可多次),如 --set recruit-count=2
44
+
45
+ # ② 用户确认后写库
46
+ node scripts/recruit-generate-jd.mjs --commit ...同参数...
47
+ ```
48
+
49
+ ### 关键输出字段(--commit)
50
+
51
+ | 字段 | 含义 |
52
+ |---|---|
53
+ | `result: success` | 落库成功 |
54
+ | `formDataId` | 职位管理记录 id(内部值,不给用户看) |
55
+ | `positionListUrl` | 招聘岗位列表 URL(菜单入口形态) |
56
+ | `positionListLocateUrl` | **列表 + 滑出新建职位详情**的组合页 URL(`/sp/ebdfpage/list/{listId}/card/0/{objId}/{dataId}/{listId}?id=…`,2026-10-21 实测简化版可用) |
57
+ | `positionCardUrl` | 本次新建职位的卡片单页 URL(作为普通链接给用户) |
58
+ | `viewLink` | **Markdown 链接①**:新建职位详情查看页(原样放回答正文) |
59
+ | `listLocateLink` | **Markdown 链接②**:招聘岗位列表(已定位新建职位,原样放回答正文) |
60
+ | `rpaChecked` | RPA 发布校验结果(false 时提示用户关注 `rpaValidMsg`) |
61
+
62
+ ### 必填默认值(脚本自动补,无需用户逐项给)
63
+
64
+ 状态=招聘中、招聘流程=当前环境默认启用流程、招聘负责人/用人经理=当前登录人、招聘人数等数值/枚举类按 JD 推导或环境默认。字段 id、枚举 id、菜单 id、appId **全部运行时解析**,跨环境不写死。
65
+
66
+ ## 执行纪律(强制)
67
+
68
+ 1. **写操作必须先确认**:`--prepare` 摘要经用户明确确认后才可 `--commit`;**禁止跳过确认直接写库**。
69
+ 2. **不臆造参数**:字段值只能来自用户输入、JD 推导或脚本默认值;`--set` 的键必须是脚本认识的 dataKey。
70
+ 3. **不暴露内部标识**:对用户只写中文(「招聘中」「2 人」),不展示字段 key、optionId、formDataId。
71
+ 4. **不输出凭证**:不展示 Cookie / ETEAMSID / token。
72
+ 5. **产物纪律**:`viewLink` / `listLocateLink` 两个 Markdown 链接按顺序原样搬运;不要包 browsertool 标签(fill_form 在非表单页卡死,实测);url 缺失时只给另一个,不输出半截。
73
+ 6. **环境自适应**:baseUrl / appId / 字段 id 一律来自会话与环境解析,**任何文件不得写死 IP / 域名 / 端口**;目标环境未部署招聘应用时脚本会给出友好提示,如实转告。
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: recruit-jd-template
3
+ description: 招聘启事 / 岗位JD 的企业标准模板与撰写规范——生成JD 与招聘启事时以本文件为准;企业有内部模板时直接替换本文件内容即可
4
+ ---
5
+
6
+ # 招聘启事 / 岗位JD 文案模板(企业标准)
7
+
8
+ > **用途**:`recruit-jd-create.md` §2.2「招聘启事 / 岗位JD 文案生成规范」的**标准来源**。
9
+ > **可替换**:企业有内部 JD 模板 / 话术 / 品牌口径时,**直接替换本文件正文**(保留章节骨架),生成即按企业标准执行;未替换则用下方**通用兜底**。
10
+
11
+ ## 1. 生成两件产物
12
+ | 产物 | 去向 | 形态 |
13
+ |---|---|---|
14
+ | **招聘启事**(对外文案) | 对话展示,**不落库**(职位管理表单无"启事"字段,已核 583 字段) | markdown 文案 |
15
+ | **岗位JD初稿**(结构化) | 落库 `position_duty`(职位职责)+ `work_request`(任职要求) | 多条、换行分隔、行首**不加** `-` |
16
+
17
+ ## 2. 招聘启事模板(通用兜底,可替换)
18
+ ```markdown
19
+ # <岗位名称>(<工作地点>|<招聘人数>人)
20
+
21
+ ## 岗位职责
22
+ 1. <职责 1:动词开头,含对象与结果>
23
+ 2. <职责 2>
24
+ …(5–8 条)
25
+
26
+ ## 任职要求
27
+ 1. <要求 1:学历/年限/技能,可衡量>
28
+ 2. <要求 2>
29
+ …(4–6 条)
30
+
31
+ ## 我们提供 # 可选,仅在有依据时写
32
+ - <薪酬范围 / 福利 / 成长空间;无依据则不写>
33
+
34
+ ## 应聘方式 # 可选
35
+ - <投递渠道 / 联系方式;无依据则不写>
36
+ ```
37
+
38
+ ## 3. 撰写规范(硬性)
39
+ - **可衡量、可核对**:职责用"动词 + 对象 + 结果";要求给学历/年限/技能等可判定条件,避免"优秀""较强"等空话。
40
+ - **条数**:职责 5–8 条、要求 4–6 条,每条一行。
41
+ - **字段联动**:启事里的地点/薪资/学历/年限应与传给脚本的 `--set`(`work_location` / `education` / `work_years` / `salary_min|max`)**保持一致**。
42
+ - **两份产物同源**:JD 初稿的职责/要求必须与启事正文**逐条一致**(不得一份删改)。
43
+ - **可参考系统已有职位**:生成前可 `recruit-list.mjs --type position` 拉同类职位,对齐措辞与字段取值。
44
+
45
+ ## 4. 红线
46
+ - **不得编造**:用户未提供的薪资/地点/学历/人数,一律写"面议 / 待定 / 不限"或**直接不写**;不得虚构福利、上市信息、团队规模。
47
+ - **不得歧视**:不出现性别、年龄、婚育、户籍/地域、民族、宗教、残障等歧视性表述。
48
+ - **不得承诺**:不写"保证录用""包住宿(未确认)"等无依据承诺。
49
+ - 合规要求沿用手册:**招聘启事内容须符合当地劳动与广告法规**。
50
+
51
+ ## 5. 企业标准替换指引
52
+ 替换时请保持以下**结构契约**不变(技能按此读取):
53
+ 1. 第 1 节两张产物表的**字段落点**(`position_duty` / `work_request`)不变;
54
+ 2. 第 3 节的**条数与同源**规则可调,但需保留"职责/要求分列";
55
+ 3. 第 4 节**红线不得删除**(可加严,不可放宽)。
56
+ > 如需新增企业专有章节(如"企业文化""团队介绍"),追加在 `## 我们提供` 之后即可。
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: recruit-list-candidate
3
+ description: 查询应聘者列表(候选人台账),支持按职位/人才/批次精确筛选与翻页取全,返回候选人、职位、阶段、渠道、手机/邮箱等,用于「看某职位的候选人」与「按岗位找/筛候选人」
4
+ ---
5
+
6
+ # 查询应聘者列表
7
+
8
+ > **平台兼容**:本文命令示例在 macOS/Linux 与 Windows PowerShell 下均可执行——JSON 用单引号包裹、内部双引号不转义;PowerShell 下不使用反斜杠续行。
9
+
10
+ > 本文档示例中的 `env` / `form_data_id` / `talent_id` 等均为**实测环境的参考值**(不同环境全部不同);运行时按菜单别名 / `ds/fields` 解析,**不得写死**(见 `recruit-resolve-metadata.md`)。
11
+
12
+ ## 1. 基础信息
13
+ - 接口名称:查询应聘者列表(候选人台账)
14
+ - 请求方式:`POST`
15
+ - 去域名路径:`/api/ebuilder/form/list/getListDatas`(与搜索人才/需求/职位同族列表接口)
16
+ - 脚本:`node scripts/recruit-list.mjs --type candidate [--position-id <id>] [--talent-id <id>] [--all]`
17
+ - 所属模块:招聘管理(recruit)
18
+ - 所属分组:应聘者 / 查询
19
+
20
+ ## 2. 业务用途
21
+ 用户说"**这个职位有哪些候选人**""看下 X 职位的应聘者""**帮我找到适合这个岗位的候选人**""筛优质候选人"时调用。返回「应聘者」列表(候选人台账),每行含候选人、应聘职位、当前阶段、渠道、手机/邮箱、人才 id。属只读查询,**无需确认门**。
22
+
23
+ > 需求对应:【人事招聘阶段 3】④「帮我找到适合这个岗位的候选人,筛选优质候选人」——本接口提供**候选人数据**,匹配度打分/排序由 AI 完成(见 `recruit-match-candidates.md`)。
24
+
25
+ ## 3. 前置条件
26
+ - 已安装招聘服务(第 0 步闸门通过)。
27
+ - **列表参数解析(跨环境、不写死)**:优先环境缓存 `lists.candidate`;缺失时**按菜单名「应聘者」从菜单树解析** `listId`/`cusMenuId`(脚本已内置该回退)。表单 `objId` 经 tag 或缓存 `forms.candidate_manage` 解析。
28
+ - 上下文参数按 `recruit-resolve-metadata.md` §7 全带(缺则假空)。
29
+
30
+ ## 4. 请求参数
31
+
32
+ ### 4.1 Query
33
+ | 字段 | 位置 | 类型 | 必填 | 业务说明 |
34
+ |---|---|---|---|---|
35
+ | `passid` / `cid` | query | string | 是 | 应聘者表单 `objId` |
36
+
37
+ ### 4.2 Body(getListDatas 同族)
38
+ | 字段 | 位置 | 类型 | 必填 | 业务说明 |
39
+ |---|---|---|---|---|
40
+ | `listId` | body | string | 是 | 应聘者列表视图 id(`lists.candidate` 或「应聘者」菜单) |
41
+ | `cusMenuId` | body | string | 是 | 同上菜单 id |
42
+ | `searchParamData` | body | object | 是 | `{ "searchType":"3", "type":"and" }` + 可选 `commonSearchFields`(服务端条件,**实测对 `position_id` 不生效**,见 §4.3) |
43
+ | 上下文参数 | body | — | 是 | `terminal`/`browser`/`requiredMatch`/`mapResult`/`recheckQuery`/`isFollow`/`isShareToMe`/`filterCondition`/`urlPageTitle`/`menuName` |
44
+
45
+ ### 4.3 脚本筛选参数(**客户端本地等值筛选,跨环境稳定**)
46
+ | 参数 | 对应 dataKey | 说明 |
47
+ |---|---|---|
48
+ | `--position-id <职位id>` | `position_id` | 只保留该职位的候选人 |
49
+ | `--talent-id <人才id>` | `talent_id` | 只保留该人才的批次 |
50
+ | `--candidate-manage-id <批次id>` | `candidate_manage_id` | 只保留该批次 |
51
+ | `--all` | — | **翻页取全后再筛**(`--max-pages` 上限默认 20)——按职位筛「务必加 `--all`**,否则只筛第一页 |
52
+
53
+ > 实测:服务端 `commonSearchFields` 传 `position_id like` 返回**未过滤**的结果(0 效果),故筛选**一律在客户端按 dataKey 等值做**;`--all` 保证扫的是全量而不是首页 20 条。
54
+
55
+ ## 5. 响应数据结构(行字段)
56
+ | 字段 | 说明 |
57
+ |---|---|
58
+ | `candidate_name` | 候选人姓名 |
59
+ | `position_name` / `position_id` | 应聘职位名 / 职位 id |
60
+ | `stage_name` / `stage_type_key` | 当前阶段(初筛 / 面试 / 待入职 …) |
61
+ | `resume_channel` | 渠道(手动录入 / 内部推荐 / BOSS直聘 / 培训机构 …) |
62
+ | `telephone` / `email` / `gender_name` | 手机 / 邮箱 / 性别 |
63
+ | `talent_id` | 人才 id(人才卡片 URL 输出契约见 `recruit-output-links.md`) |
64
+ | `create_time` | 投递/创建时间 |
65
+ | `form_data_id` | 应聘记录 id |
66
+
67
+ ## 6. 请求示例
68
+ ```bash
69
+ # 某职位的全部候选人(先翻页取全再本地筛)
70
+ node scripts/recruit-list.mjs --type candidate --position-id <职位id> --all --page-size 20
71
+ # 只看首页 20 条内符合条件的
72
+ node scripts/recruit-list.mjs --type candidate --position-id <职位id> --page-size 20
73
+ ```
74
+
75
+ ## 7. 响应示例(脚本)
76
+ ```json
77
+ { "env": "<测试环境地址>", "type": "candidate", "total": 75, "returned": 14, "filters": ["职位"],
78
+ "rows": [
79
+ { "candidate_name": "陈宇", "position_name": "AI工程师", "stage_name": "初筛", "resume_channel": "手动录入",
80
+ "telephone": "13800000003", "talent_id": "1325294055798906885" }
81
+ ] }
82
+ ```
83
+
84
+ ## 8. 错误码
85
+ | 错误码 | 含义 | AI 处理建议 |
86
+ |---|---|---|
87
+ | 非 200 | 认证/参数错误 | 检查认证 / `listId`/`cusMenuId` |
88
+ | 菜单未匹配 | 环境未启用「应聘者」菜单 | 按 `recruit-capability-check.md` 拦截,不硬凑近似菜单 |
89
+ | 筛选后 0 行 | 该职位确无候选人,或未加 `--all` 只扫了首页 | 加 `--all` 复跑一次再下结论 |
90
+
91
+ ## 9. 调用参考
92
+ - 用户场景:"这个职位有哪些候选人""帮我找到适合这个岗位的候选人"。
93
+ - **流程**:能力探测 → 解析 `objId`/`listId`/`cusMenuId` → `--position-id` + `--all` 取候选人 → 展示或交给 `recruit-match-candidates.md` 打分排序。
94
+ - 与 `recruit-search-candidate.md` 的区别:那个是**按手机/姓名/渠道在人才库搜**;本接口是**按职位查应聘者台账**(候选人维度)。
95
+
96
+ ## 10. 注意事项
97
+ - **只读查询,无确认门**。
98
+ - **菜单名跨基线不同**:「应聘者」(环境A) / **「应聘管理」**(环境B)——脚本按别名数组匹配,不写死。
99
+ - **阶段字段跨基线不同**:`stage_name`(环境A) / **`stage_type_key`**(环境B)→ 已归一到 `stage_name`。
100
+ - **按职位筛必须加 `--all`**:服务端不做该筛选,本地筛只作用于已取回的行。
101
+ - 展示行内不输出无意义裸 id;`talent_id` 保留(供查看详情/打开人才卡片)。
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: recruit-list-interview
3
+ description: 查询面试管理列表(面试安排),支持按「近 N 天」过滤与按开始时间排序,返回候选人/职位/面试方式/环节/轮次/面试官/时间/反馈状态,用于「查看近期的面试安排」
4
+ ---
5
+
6
+ # 查询面试安排列表
7
+
8
+ > **平台兼容**:本文命令示例在 macOS/Linux 与 Windows PowerShell 下均可执行——JSON 用单引号包裹、内部双引号不转义;PowerShell 下不使用反斜杠续行。
9
+
10
+ > 本文档示例中的 `env` / `form_data_id` / `talent_id` 等均为**实测环境的参考值**(不同环境全部不同);运行时按菜单别名 / `ds/fields` 解析,**不得写死**(见 `recruit-resolve-metadata.md`)。
11
+
12
+ ## 1. 基础信息
13
+ - 接口名称:查询面试管理列表(面试安排)
14
+ - 请求方式:`POST`
15
+ - 去域名路径:`/api/ebuilder/form/list/getListDatas`(与搜索人才/需求/职位同族列表接口)
16
+ - 脚本:`node scripts/recruit-list.mjs --type interview [--recent <N>] [--sort start_time] [--page-size 20]`
17
+ - 所属模块:招聘管理(recruit)
18
+ - 所属分组:面试 / 查询
19
+
20
+ ## 2. 业务用途
21
+ 用户说"**查看近期的面试安排**""这周有哪些面试""X 的面试安排在什么时候""谁还没反馈面试"时调用。返回「面试管理」列表,每行含候选人、职位、面试时间、面试方式、环节/轮次、面试官、反馈状态。属只读查询,**无需确认门**。
22
+
23
+ > 需求对应:【人事招聘阶段 4】① 招聘人员在小e 中询问「查看近期的面试安排」——本接口即该问句的数据底座;右侧窗口用 artifact 打开「面试管理」列表(见 §9)。
24
+
25
+ ## 3. 前置条件
26
+ - 已安装招聘服务(第 0 步闸门通过)。
27
+ - **能力探测**:面试计划表单 `objId` 经 tag `uf_rcrt_interview_plan` 解析;列表 `listId`/`cusMenuId` 取环境缓存的 `lists.interview`(运行时解析,跨环境不写死)。缺失 → 按 `recruit-capability-check.md` 判定"未启用",提示「当前环境未提供面试管理功能」,不硬凑。
28
+ - 上下文参数按 `recruit-resolve-metadata.md` §7 全带(缺则假空)。
29
+
30
+ ## 4. 请求参数
31
+
32
+ ### 4.1 Query
33
+ | 字段 | 位置 | 类型 | 必填 | 业务说明 |
34
+ |---|---|---|---|---|
35
+ | `passid` / `cid` | query | string | 是 | 面试计划表单 `objId` |
36
+
37
+ ### 4.2 Body(getListDatas 同族)
38
+ | 字段 | 位置 | 类型 | 必填 | 业务说明 |
39
+ |---|---|---|---|---|
40
+ | `listId` | body | string | 是 | 面试列表视图 id(`lists.interview.listId`) |
41
+ | `cusMenuId` | body | string | 是 | 同上菜单 id |
42
+ | `searchParamData` | body | object | 是 | `{ "searchType":"3", "type":"and" }`(条件见 §4.4) |
43
+ | 上下文参数 | body | — | 是 | `terminal`/`browser`/`requiredMatch`/`mapResult`/`recheckQuery`/`isFollow`/`isShareToMe`/`filterCondition`/`urlPageTitle`/`menuName` |
44
+ | `current` / `pageSize` | body | int | 否 | 分页(脚本 `--page` / `--page-size`) |
45
+
46
+ ### 4.3 脚本本地过滤/排序(**不依赖服务端,跨环境稳定**)
47
+ | 参数 | 说明 |
48
+ |---|---|
49
+ | `--recent <N>` | 仅保留 `start_time` 在**近 N 天**内的行(本地按数据里的时间字符串判定;需求"近期"由它落地) |
50
+ | `--sort <dataKey>` | 按该字段**倒序**排序(时间类取最新在前,如 `--sort start_time`) |
51
+ | `--all` | 翻页取全量后再过滤/排序(`--max-pages` 控制上限,默认 20) |
52
+
53
+ > 实测:服务端 `commonSearchFields` 对**时间字段**筛选不稳定,故"近期"一律在本地做(`--recent`)。
54
+
55
+ ## 5. 响应数据结构(行字段)
56
+ | 字段 | 说明 |
57
+ |---|---|
58
+ | `candidate_name` | 候选人姓名 |
59
+ | `position_name` | 应聘职位 |
60
+ | `start_time` / `end_time` | 面试开始 / 结束时间(`yyyy-MM-dd HH:mm`) |
61
+ | `interview_session` | 环节(初试/复试…) |
62
+ | `interview_type_key` | **面试方式**(现场面试 / 视频面试 / 电话面试 / **AI面试**) |
63
+ | `interview_rounds` | 轮次(第一轮/第四轮…) |
64
+ | `interviewer` | 面试官 |
65
+ | `union_status_key` | 反馈状态(待反馈 / 已反馈…) |
66
+ | `subject` | 面试主题(如「AI工程师-李沐的面试」) |
67
+ | `talent_id` / `position_manage_id` / `candidate_manage_id` | 人才 / 职位 / 应聘批次 id(下游编排用) |
68
+ | `form_data_id` | 面试记录 id(详情/反馈用) |
69
+
70
+ > ⚠️ `interview_type_key`、`interview_rounds` 在 displayData 里**偶尔回退成 optionId**;脚本已做 `ds/options` 运行时映射回中文(映射不到才保留原值)。
71
+
72
+ ## 6. 请求示例
73
+ ```bash
74
+ # 查看近期(30 天内)面试安排,按开始时间倒序,取全量
75
+ node scripts/recruit-list.mjs --type interview --recent 30 --sort start_time --all --page-size 20
76
+ # 不加 --recent 则返回列表默认顺序的全部页;--page-size 控制单页
77
+ node scripts/recruit-list.mjs --type interview --page-size 10
78
+ ```
79
+
80
+ ## 7. 响应示例(脚本)
81
+ ```json
82
+ { "env": "<测试环境地址>", "type": "interview", "total": 16, "totalExact": true,
83
+ "recentDays": 30, "returned": 3,
84
+ "rows": [
85
+ { "candidate_name": "李沐", "position_name": "AI工程师", "start_time": "2026-10-10 13:19", "end_time": "2026-10-17 13:19",
86
+ "interview_session": "初试", "interview_type_key": "AI面试", "interview_rounds": "第四轮",
87
+ "interviewer": "招聘专员", "union_status_key": "待反馈", "subject": "AI工程师-李沐的面试",
88
+ "talent_id": "1276382457065553922", "position_manage_id": "1276382220792020998" }
89
+ ] }
90
+ ```
91
+
92
+ ## 8. 错误码
93
+ | 错误码 | 含义 | AI 处理建议 |
94
+ |---|---|---|
95
+ | 非 200 | 认证/参数错误 | 检查认证(`weaver-work-cli auth status`)/ `listId`/`cusMenuId` |
96
+ | `rows` 空 | 无面试记录 / 或 `--recent` 过滤后无命中 | 去掉 `--recent` 复跑一次再判"无记录" |
97
+ | 菜单未匹配 | 环境未启用面试管理 | 拦截提示,不硬凑 |
98
+
99
+ ## 9. 调用参考
100
+ - 用户场景:"查看近期的面试安排""这周的面试""谁还没反馈"。
101
+ - **流程**:能力探测(面试菜单存在)→ 解析 `objId`/`listId`/`cusMenuId` → `--recent N` 过滤 + `--sort start_time` → 展示(按"时间 → 候选人(职位)· 方式 · 环节/轮次 · 面试官 · 反馈状态"排版)。
102
+ - **右侧窗口**:小E 场景可在回答末尾附 `<artifact>[{"file_name":"面试管理","file_type":"url","url":"<面试管理列表URL>"}]</artifact>` 让右侧打开面试管理列表(URL 拼装见 `recruit-arrange-interview.md` §11 `interviewListUrl`)。
103
+
104
+ ## 10. 注意事项
105
+ - **只读查询,无确认门**。
106
+ - **跨基线列名不同**(环境B用 `name`/`interview_type`/`union_status`,且 `talent_id`/`position_manage_id` 直接给文本)→ 脚本已用 `DISPLAY_ALIASES` 归一为 `candidate_name`/`interview_type_key`/`union_status_key`;**调用方按归一后的字段读,别按环境分支判断**(详见 `recruit-resolve-metadata.md`)。
107
+ - "近期"由 `--recent N` 落地(本地判定),**不要臆造服务端时间筛选参数**。
108
+ - `total` 在部分列表不可信(某环境实测计数返回 167994,明显虚高):以 `scanned`(实际取回)与 `returned`(过滤后)为准;`--all` 触达 `--max-pages` 上限时 `totalNote` 会提示。
109
+ - 展示时间统一 `yyyy-MM-dd HH:mm`;行内不输出无意义的 16 位裸 id(`talent_id` 等业务 id 保留,供下游编排)。
110
+
111
+ ## 10. 面试待办:`--feedback-todo`(只返回我要填反馈的)
112
+
113
+ ```bash
114
+ node scripts/recruit-list.mjs --type interview --feedback-todo
115
+ ```
116
+
117
+ 固定输出两个分组(**只含我作为面试官的记录**,不返回全量面试列表):
118
+
119
+ | 分组 | 含义 | 判据 |
120
+ |---|---|---|
121
+ | `myAiPendingFeedback` | **AI 面试已答完、已有录像、我还没填意见** ← 主清单 | 待反馈 + AI面试 + 面试官含我 |
122
+ | `myOtherPendingFeedback` | 我作为面试官的其他方式面试待反馈(现场/视频/电话) | 待反馈 + 面试官含我 |
123
+
124
+ **为什么不用看视频字段**:后端 `InterviewStatusEnum.TO_FEEDBACK`(待反馈)的置位条件是
125
+ `InterviewPlanStatusPerPlanThread` 判定的「AI 面试结束时间已过 且(有录像附件 或 已开始录制)且 反馈结果为空」
126
+ ——**「待反馈」本身就等于「已完成 + 有视频 + 未填意见」**,技能侧无需再读视频字段(`video_url_info` 是「视频面试地址」,HR 手填的会议链接,与录像无关)。
127
+
128
+ 取数策略(面试列表服务端筛选不生效,只能客户端筛):
129
+ - 自动隐含 `--all`,默认 `--page-size 200`、`--max-pages 5`(约 1000 条,实测 4–5 秒)
130
+ - 输出 `scanned` 与实际总数对比,并在 `note` 提示是否需要加大 `--max-pages`
131
+ - 当前用户由 `teamsCheck` 解析(`currentUser.username`),失败时 `mine` 为空并给出 note
132
+
133
+ 输出示例:
134
+
135
+ ```json
136
+ {
137
+ "feedbackTodo": {
138
+ "currentUser": "李伟(上海)",
139
+ "scanned": 1000,
140
+ "myAiPendingFeedback": { "count": 1, "rows": [{ "candidate_name": "2606基线测试", "position_name": "大模型算法工程师", "start_time": "2026-10-27 11:47", "interview_session": "初试", "union_status_key": "待反馈", "form_data_id": "..." }] },
141
+ "myOtherPendingFeedback": { "count": 0, "rows": [] },
142
+ "note": "已扫描 1000/168386 条(面试列表默认顺序),未覆盖全部;如怀疑遗漏可加 --max-pages N 扩大"
143
+ }
144
+ }
145
+ ```
146
+
147
+ > 时效性:待反馈状态由 E10 调度任务 `RecruitSyncInterviewPlanStatusTask` 定时同步(非实时),
148
+ > 刚结束的 AI 面试可能有几分钟延迟;提示语里应说明「以系统状态为准」。
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: recruit-match-candidates
3
+ description: 按岗位找/筛优质候选人——用应聘者列表 + 职位 JD 做 AI 人岗匹配打分与排序,输出候选人评分卡与建议清单(不落库、不改状态)
4
+ ---
5
+
6
+ # 按岗位找 / 筛优质候选人(人岗匹配)
7
+
8
+ ## 1. 业务用途
9
+ 用户说"**帮我找到适合这个岗位的候选人**""筛一下优质候选人""这个职位谁最合适""按 JD 帮我排个优先级"时走本编排。输出**候选人评分卡 + 建议清单**,并在小E 场景可在右侧打开人才卡片。
10
+
11
+ > 需求对应:【人事招聘阶段 3】④「招聘人员在小e 中询问『帮我找到适合这个岗位的候选人』,筛选优质候选人」。
12
+
13
+ ## 2. 能力边界(重要,先对齐)
14
+ - **没有"人岗匹配度"后端接口**:`api-index` 全量端点中**无** match/score/degree 类接口;招聘侧 `label` 只有"标签匹配"(`matchTalentLabel`),**不是匹配度**。
15
+ - 因此**匹配度 = AI 评估能力**(与《AI人岗智能匹配_功能表述参考》讲稿一致):解析 JD → 建"岗位能力模型" → 逐维比对候选人 → 输出匹配率与优劣势。
16
+ - **不落库**:`uf_rcrt_talent_pool` / 候选人记录**没有匹配度字段**(已核 95 个字段);本能力只**输出评分与建议**,不回写、不改候选人阶段/状态。
17
+
18
+ ## 3. 数据底座(全部只读)
19
+ | 数据 | 来源 |
20
+ |---|---|
21
+ | 目标职位(含 JD 职责/要求) | `recruit-list.mjs --type position` 定位 → 详情取 `position_duty` / `work_request` / `education` / `work_years` / `work_location` / `recruit_count` |
22
+ | 该职位的候选人 | `recruit-list.mjs --type candidate --position-id <职位id> --all --page-size 20`(见 `recruit-list-candidate.md`) |
23
+ | 候选人细节(可选,用于逐维比对) | `recruit-detail.mjs --talent-id <talent_id>`(基础信息/教育/工作经历,见 `recruit-detail-*.md`) |
24
+ | 简历原文(可选) | 人才卡片「原始简历」(见 `recruit-resume-import.md` §11 / `recruit-resume-parse.md`) |
25
+
26
+ ## 4. 打分模型(AI 侧执行,维度可依企业标准调整)
27
+ | 维度 | 权重 | 判据(来自 JD 与候选人数据) |
28
+ |---|---|---|
29
+ | 硬性条件 | 高 | 学历、工作年限、工作地点、必要证书 |
30
+ | 硬技能 | 高 | JD 职责/要求中的技术栈/工具/行业经验 vs 候选人技能与工作经历 |
31
+ | 经验相关性 | 中 | 行业/岗位相关性、项目复杂度、管理与协作经验 |
32
+ | 加分项 | 低 | 名企背景、外语能力、可立即到岗等 |
33
+ | 风险点 | — | 频繁跳槽、经验断层、地点不符等(单列提示,不直接降分) |
34
+
35
+ **产出**:每位候选人 `匹配度(0–100 或 高/中/低)` + `命中点` + `缺口` + `一句话建议`。
36
+
37
+ ## 5. 执行流程(Agent 编排)
38
+ 1. **定位职位**:`node scripts/recruit-list.mjs --type position` 找目标职位 → 拿职位 `form_data_id` 与 JD 文本(缺失则读职位详情)。
39
+ 2. **取候选人**:`node scripts/recruit-list.mjs --type candidate --position-id <职位id> --all --page-size 20`。
40
+ 3. **(可选)补细节**:对前若干名调 `recruit-detail.mjs --talent-id <id>` 取教育/工作经历,做逐维比对。
41
+ 4. **AI 打分排序**:按 §4 维度逐人评分,输出**评分卡表格**(默认 Top 5–10)。
42
+ 5. **展示与跳转**:给出建议清单;小E 场景附 `<artifact>` 打开人才卡片或人才管理列表(见 §6)。
43
+
44
+ ## 6. 输出样式
45
+ ```markdown
46
+ **<职位名> · 候选人匹配度(共 N 人,按匹配度排序)**
47
+
48
+ | # | 候选人 | 匹配度 | 命中 | 缺口 | 建议 |
49
+ |---|---|---|---|---|---|
50
+ | 1 | 李沐 | 高(88) | 5年Java、AI项目经验;地点匹配 | 学历未达"本科" | 优先安排面试 |
51
+ | 2 | 何子元 | 中(65) | 技能匹配 | 年限偏少(1年) | 可作备选 |
52
+ ```
53
+ - 匹配度**必须给依据**(命中/缺口逐条),不空喊分数;
54
+ - **缺失数据不编造**:学历/年限缺就写"信息缺失",标注需人工核对。
55
+
56
+ ## 7. 右侧打开(小E 场景)
57
+ - 打开**人才卡片**:`{baseUrl}/sp/ebdpage/view/{ebdDetailPageId}?talentId={talent_id}`(见 `recruit-resume-import.md` §11)
58
+ - 打开**人才管理/应聘者列表**:用菜单拼装(同 `recruit-list-interview.md` §9 范式)
59
+ - 用法:把 `<artifact>[{"file_name":"…","file_type":"url","url":"…"}]</artifact>` 附在回答正文末尾(**仅小E**;WorkBuddy 桌面端不解析)。
60
+
61
+ ## 8. 错误码 / 异常处理
62
+ | 情况 | 处理 |
63
+ |---|---|
64
+ | 职位下无候选人 | 提示"该职位暂无候选人",并给出「人才库按关键词搜」的替代路径(`recruit-search-candidate.md`) |
65
+ | 筛选后 0 行 | 检查是否漏了 `--all`(只扫了首页) |
66
+ | 候选人教育/经历缺失 | 标注"信息缺失",不臆测;必要时先 `recruit-detail.mjs` 补取 |
67
+ | 环境未启用「应聘者」菜单 | 按 `recruit-capability-check.md` 拦截,不硬凑 |
68
+
69
+ ## 9. 调用参考(一句话触发示例)
70
+ - "帮我找 AI工程师 这个岗位合适的候选人" → 取候选人 + AI 打分 Top N。
71
+ - "这个职位的候选人帮我排个优先级" → 同上,输出排序表。
72
+ - "李沐适合这个岗位吗" → 单人对单岗评分卡。
73
+
74
+ ## 10. 注意事项
75
+ - **只读、不落库、不改状态**:不写匹配度、不改候选人阶段、不发通知。
76
+ - **不替代业务决策**:评分是辅助建议,最终以 HR 判断为准;展示时明确"AI 评估,仅供参考"。
77
+ - **维度可配置**:若企业有"岗位能力模型/招聘标准",以其为准(见 `recruit-jd-template.md`),本文件 §4 为通用兜底。