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.
- package/dist/chunks/{archive-JHTONRST.js → archive-J4I6MCKF.js} +2 -2
- package/dist/chunks/{archive-oa-FCHLCPHC.js → archive-oa-BRZKKTO4.js} +2 -2
- package/dist/chunks/{asset-RLIHC7DB.js → asset-L7D4FAOZ.js} +2 -2
- package/dist/chunks/{asset-idle-KVOFTLCP.js → asset-idle-DADLLV75.js} +2 -2
- package/dist/chunks/{attachment-content-RZYDB3MB.js → attachment-content-K4C7VLWQ.js} +3 -3
- package/dist/chunks/{blog-42OZTJNP.js → blog-BVGQ7NZL.js} +2 -2
- package/dist/chunks/{caizhilian-KRK547K5.js → caizhilian-SAADNFD6.js} +2 -2
- package/dist/chunks/{calendar-RTWAMKHD.js → calendar-Q7NQY5Z2.js} +61 -23
- package/dist/chunks/{chunk-LFMSDBZN.js → chunk-3KTFS4IA.js} +308 -153
- package/dist/chunks/{chunk-G2JSIUWF.js → chunk-4PD5NWAX.js} +89 -0
- package/dist/chunks/{chunk-T6EGVBKU.js → chunk-4RAE6JXP.js} +1 -1
- package/dist/chunks/{chunk-7BRU4EFH.js → chunk-72CKAUAG.js} +29 -2
- package/dist/chunks/{chunk-NETCCARD.js → chunk-APVFJUQH.js} +2 -2
- package/dist/chunks/{chunk-CAQNBBQA.js → chunk-BBKDXQEC.js} +2 -2
- package/dist/chunks/{chunk-57IECMWX.js → chunk-BIPYLLVS.js} +26 -12
- package/dist/chunks/{chunk-LN447PY2.js → chunk-EKWAQSLU.js} +3 -2
- package/dist/chunks/{chunk-4TEDNCON.js → chunk-FOAA27U5.js} +338 -52
- package/dist/chunks/{chunk-7U577Q7U.js → chunk-G4UR6NXN.js} +2 -2
- package/dist/chunks/{chunk-NJKREDA3.js → chunk-GEWYMQME.js} +1 -1
- package/dist/chunks/{chunk-I566ZYNF.js → chunk-GHXCDPTM.js} +1 -1
- package/dist/chunks/{chunk-4CTESSKI.js → chunk-IZ7S7QUS.js} +4 -4
- package/dist/chunks/{chunk-VNBU55SL.js → chunk-JPRO6ER2.js} +57 -2432
- package/dist/chunks/{chunk-IZSSVYAG.js → chunk-LADPYOWC.js} +2 -2
- package/dist/chunks/chunk-LDZQPUIA.js +1238 -0
- package/dist/chunks/chunk-NKZRQXST.js +2546 -0
- package/dist/chunks/{chunk-JWRZM2H2.js → chunk-QKNKR4RH.js} +3 -3
- package/dist/chunks/{chunk-FLS4DPGP.js → chunk-R4CHUSKC.js} +28 -15
- package/dist/chunks/{chunk-WFFNM65B.js → chunk-SA6VBIHY.js} +73 -19
- package/dist/chunks/{chunk-SPRHHSVC.js → chunk-TTPJJJC4.js} +2 -2
- package/dist/chunks/{chunk-7E6MUOEK.js → chunk-W7BEHOSR.js} +2 -2
- package/dist/chunks/{chunk-CXRQWOZ5.js → chunk-YRSZQUD2.js} +2 -2
- package/dist/chunks/{conflict-VR55AOOO.js → conflict-F2OMZRTO.js} +2 -2
- package/dist/chunks/{contract-HI4FNPYE.js → contract-5BETHRSG.js} +2 -2
- package/dist/chunks/{cowork-HJLI353D.js → cowork-3MN6EQQO.js} +22 -12
- package/dist/chunks/create-flow-5FQNNMVO.js +55 -0
- package/dist/chunks/{ebuilder-form-HTGI63UU.js → ebuilder-form-SBHOYBUD.js} +3 -3
- package/dist/chunks/{ehr-GYXIYH3A.js → ehr-KMOJULKG.js} +432 -1234
- package/dist/chunks/{env-DW3G4HUO.js → env-LB7NBL2O.js} +2 -2
- package/dist/chunks/{esb-I5INCEFE.js → esb-W2PJCFCX.js} +4 -4
- package/dist/chunks/{factory-TKXGXS6L.js → factory-6ZFQXQ46.js} +1 -1
- package/dist/chunks/{fna-K2MHTQ24.js → fna-ZQPCUV4R.js} +2 -2
- package/dist/chunks/{group-chat-VYBNMJLG.js → group-chat-2HHAJN46.js} +5 -3
- package/dist/chunks/{host-ZUQTJYYK.js → host-4CBHGOHT.js} +3 -3
- package/dist/chunks/{host-D5SERMAJ.js → host-ATKVNZAT.js} +3 -3
- package/dist/chunks/{host-JM4YVHFM.js → host-BQH22NTQ.js} +3 -3
- package/dist/chunks/{host-L3VLITMT.js → host-X2CSLFM6.js} +3 -3
- package/dist/chunks/{host-256GVCAH.js → host-YTODKMSL.js} +3 -3
- package/dist/chunks/{hrm-VLRBKTZB.js → hrm-FFM4UJFS.js} +4 -4
- package/dist/chunks/{im-QK3VTLXK.js → im-VEHKDQPB.js} +7 -7
- package/dist/chunks/{invoice-T5JTA32H.js → invoice-LVIKSIIF.js} +3 -3
- package/dist/chunks/{jiuchuanhui-P2FNEQVZ.js → jiuchuanhui-X6DINO5P.js} +2 -2
- package/dist/chunks/{lazy-dispatch-XRRI46M6.js → lazy-dispatch-KSWTN5L6.js} +4 -4
- package/dist/chunks/{mail-3Y7MJ6PS.js → mail-VDKRGUD3.js} +2 -2
- package/dist/chunks/{meeting-M7LTXGJE.js → meeting-CLC6HP3Z.js} +12 -11
- package/dist/chunks/{okr-OBC6S67L.js → okr-CHG4OO3U.js} +2 -2
- package/dist/chunks/{plan-5H6I53SK.js → plan-XWR75667.js} +2 -2
- package/dist/chunks/{project-L75QZV4S.js → project-5BXOOKMG.js} +40 -23
- package/dist/chunks/recruit-stage-DGMFNNDE.js +4507 -0
- package/dist/chunks/{registry-RXPN6BBT.js → registry-7FFOXIAW.js} +4 -4
- package/dist/chunks/{registry-KMHCPAAD.js → registry-BKBZPBAJ.js} +10 -9
- package/dist/chunks/{registry-QGHFNUWS.js → registry-OZSMDVPP.js} +2 -2
- package/dist/chunks/{registry-UGRBCBHO.js → registry-RHMW6ANW.js} +2 -2
- package/dist/chunks/{registry-NYPYMZXG.js → registry-Z43434VG.js} +1 -1
- package/dist/chunks/{room-recommend-A3UDC3CA.js → room-recommend-62H7ZQQ6.js} +4 -4
- package/dist/chunks/{schedule-5GCACCK7.js → schedule-FNXKH3DQ.js} +4 -4
- package/dist/chunks/{workflow-M5ZJ7DWF.js → workflow-ADHKCAJK.js} +6 -6
- package/dist/index.js +33 -28
- package/dist/internal/e10/auth/commands.js +1 -0
- package/dist/internal/e10/auth/messages.js +6 -0
- package/dist/internal/e10/auth/session.js +17 -0
- package/dist/internal/e10/auth/xiaoe.js +286 -44
- package/dist/internal/e10/auth-recovery.js +36 -5
- package/dist/internal/e10/context.js +56 -12
- package/dist/internal/e10/index.js +1 -1
- package/dist/internal/e10/network-error.js +93 -0
- package/dist/internal/e10/request-runtime.js +6 -0
- package/dist/shortcuts/calendar/operations/read.js +31 -22
- package/dist/shortcuts/calendar/operations/write.js +45 -1
- package/dist/shortcuts/cowork/operations/discuss-write.js +5 -1
- package/dist/shortcuts/cowork/operations/item-write.js +1 -7
- package/dist/shortcuts/cowork/operations/member-write.js +3 -1
- package/dist/shortcuts/cowork/operations/permission-write.js +5 -1
- package/dist/shortcuts/cowork/operations/shared.js +7 -0
- package/dist/shortcuts/ehr/operations/attend-write.js +43 -1
- package/dist/shortcuts/ehr/operations/hr-contact.js +7 -4
- package/dist/shortcuts/ehr/operations/hr-report.js +13 -7
- package/dist/shortcuts/ehr/operations/recruit-candidate-import.js +134 -59
- package/dist/shortcuts/ehr/operations/recruit-write.js +262 -17
- package/dist/shortcuts/ehr/operations/recruit.js +10 -4
- package/dist/shortcuts/ehr/operations/shared.js +47 -0
- package/dist/shortcuts/hrm/operations/org.js +118 -0
- package/dist/shortcuts/index.js +5 -0
- package/dist/shortcuts/meeting/operations/eb/catalog.js +4 -1
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +85 -28
- package/dist/shortcuts/meeting/operations/eb/factory.js +33 -0
- package/dist/shortcuts/meeting/operations/eb/group-chat.js +25 -3
- package/dist/shortcuts/meeting/operations/eb/person-cache.js +96 -0
- package/dist/shortcuts/meeting/operations/eb/room-recommend.js +33 -11
- package/dist/shortcuts/project/operations/read.js +6 -25
- package/dist/shortcuts/project/operations/shared.js +22 -0
- package/dist/shortcuts/project/operations/write.js +28 -2
- package/dist/shortcuts/recruit-stage/context.js +119 -0
- package/dist/shortcuts/recruit-stage/continuation.js +73 -0
- package/dist/shortcuts/recruit-stage/errors.js +65 -0
- package/dist/shortcuts/recruit-stage/host.js +109 -0
- package/dist/shortcuts/recruit-stage/index.js +115 -0
- package/dist/shortcuts/recruit-stage/manifest.js +29 -0
- package/dist/shortcuts/recruit-stage/operations/interview-arrange.js +722 -0
- package/dist/shortcuts/recruit-stage/operations/interview-feedback.js +269 -0
- package/dist/shortcuts/recruit-stage/operations/jd-create.js +630 -0
- package/dist/shortcuts/recruit-stage/operations/list.js +431 -0
- package/dist/shortcuts/recruit-stage/operations/registry.js +38 -0
- package/dist/shortcuts/recruit-stage/operations/resume-import.js +1198 -0
- package/dist/shortcuts/recruit-stage/operations/search.js +158 -0
- package/dist/shortcuts/recruit-stage/operations/types.js +25 -0
- package/dist/shortcuts/recruit-stage/school-tiers.json +318 -0
- package/dist/shortcuts/recruit-stage/shared.js +608 -0
- package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +4 -2
- package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +13 -6
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +17 -24
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +14 -9
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +50 -8
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +2 -1
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +17 -11
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +7 -39
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +3 -2
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +51 -15
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +16 -1
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +151 -63
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.subGroup.js +56 -0
- package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +39 -14
- package/docs/e10-auth.md +7 -1
- package/docs/operation-manual.md +8 -0
- package/package.json +1 -1
- package/scripts/install-skill-to-xiaoe.mjs +105 -0
- package/scripts/package-skill.mjs +4 -2
- package/skill-template/business-info.json +24 -0
- package/skill-template/domains/recruit-stage.md +29 -0
- package/skills/weaver-e10-calendar/SKILL.md +2 -1
- package/skills/weaver-e10-calendar/references/calendar-write.md +54 -0
- package/skills/weaver-e10-cowork/SKILL.md +1 -1
- package/skills/weaver-e10-cowork/references/cowork-write.md +3 -1
- package/skills/weaver-e10-jucailin/SKILL.md +1 -1
- package/skills/weaver-e10-jucailin/references/attend-write.md +8 -0
- package/skills/weaver-e10-jucailin/references/hr-contact.md +8 -0
- package/skills/weaver-e10-jucailin/references/hr-report.md +8 -0
- package/skills/weaver-e10-jucailin/references/recruit-create.md +2 -2
- package/skills/weaver-e10-jucailin/references/recruit-read.md +1 -1
- package/skills/weaver-e10-jucailin/references/recruit-write.md +4 -3
- package/skills/weaver-e10-mail/SKILL.md +1 -1
- package/skills/weaver-e10-meeting/SKILL.md +32 -2
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-recruit-stage/SKILL.md +226 -0
- package/skills/weaver-e10-recruit-stage/agents/openai.yaml +119 -0
- package/skills/weaver-e10-recruit-stage/lib/recruit-xiaoe-file.mjs +188 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-arrange-interview.md +322 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-capability-check.md +127 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-check-install.md +65 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-detail-process.md +63 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-edit-interview-feedback.md +142 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-jd-create.md +73 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-jd-template.md +56 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-list-candidate.md +101 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-list-interview.md +148 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-match-candidates.md +77 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-output-links.md +59 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resolve-creator.md +69 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resolve-metadata.md +241 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resume-import.md +438 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-resume-parse.md +128 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-search-candidate.md +146 -0
- package/skills/weaver-e10-recruit-stage/references/recruit-urge-feedback.md +69 -0
- package/skills/weaver-e10-shared/SKILL.md +1 -1
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +4 -2
- package/skills/weaver-e10-shijingran/SKILL.md +3 -2
- package/skills/weaver-e10-shijingran/references/operations.md +3 -1
- package/skills/weaver-e10-shijingran/references/source-manifest.json +41 -40
- package/skills/weaver-e10-shijingran/references/write-operations.md +2 -0
- package/skills/weaver-e10-workflow/SKILL.md +4 -2
- package/skills/weaver-e10-workflow/aigroup/default.json +11 -9
- package/skills/weaver-e10-workflow/references/todo-smart-convert.md +23 -13
- package/skills/weaver-e10-workflow/tools/todo-summary.cjs +62 -20
- package/skills/weaver-e10-yepiaotong/SKILL.md +9 -10
- package/skills/weaver-e10-yepiaotong/references/invoice-agent-entry.md +6 -3
- package/dist/chunks/{chunk-E7OK5WD5.js → chunk-2LV74IWP.js} +5 -5
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recruit-arrange-interview
|
|
3
|
+
description: 创建面试安排,支持现场、电话、视频、AI 面试方式(saveFormData + assignedInterview)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 安排面试
|
|
7
|
+
|
|
8
|
+
> **平台兼容**:本文命令示例在 macOS/Linux 与 Windows PowerShell 下均可执行——JSON 用单引号包裹、内部双引号不转义;PowerShell 下不使用反斜杠续行。
|
|
9
|
+
> 本文档中的 `${...}` 形参(表单 objId / 布局 formId / 列表 listId / EB 页面 viewId·pageId / 应用 appId / 动作流 id / 菜单 id cusMenuId)为**租户相关值**:表单 objId 与布局 formId 同由 `getObjsByTag` 一次返回;列表/页面/菜单 id 由部署参数提供(**可经 `allMenus` 菜单树自动发现**,见 `recruit-resolve-metadata.md` §3.1);**字段 id(`formField.id`)经 `ds/fields` 运行时解析,不写死**(见 `recruit-resolve-metadata.md` §5)。
|
|
10
|
+
|
|
11
|
+
## 1. 基础信息
|
|
12
|
+
- 接口名称:安排面试(与页面「保存」按钮**等价的动作链**:系统保存 → 各 esb 动作流 → 分配面试 → AI 面试提醒)
|
|
13
|
+
- 请求方式:`POST`
|
|
14
|
+
- 去域名路径:
|
|
15
|
+
- ① `/api/ebuilder/form/form/core/saveFormData`(保存面试计划表单,formId 见 recruit-resolve-metadata.md)
|
|
16
|
+
- ② 表单「保存」按钮 actions[] 中的 `actionType=esb` 动作 → `/api/ebuilder/form/esb/runEsb`(按 `showOrder` 顺序逐条执行;**id 运行时解析,不写死**,见 §4.4)
|
|
17
|
+
- ③ 表单「保存」按钮 actions[] 中的 `actionType=jsCode` 动作(典型实现即调 `/api/recruit/candidate/assignedInterview`)→ 技能侧等价调用该接口(见 §4.5)
|
|
18
|
+
- 辅助(可选):`GET /api/ebuilder/form/obj/getObjsByTag?appId={appId}&tag=uf_rcrt_interview_plan`(一次取得面试计划 `objId` 与布局 `formId`;字段 id 经 `ds/fields` 解析)
|
|
19
|
+
- 辅助(动作链解析):`POST /api/ebuilder/form/data/getFormButtons`(body 带 `objId` + `layoutId`,取「保存」按钮的 `actions[]`)
|
|
20
|
+
- 所属模块:招聘管理(recruit)
|
|
21
|
+
- 所属分组:面试 / 写操作
|
|
22
|
+
|
|
23
|
+
## 2. 业务用途
|
|
24
|
+
用户说"给 X 安排一场面试""约个现场/电话/视频/AI 面试""安排面试官 Y 面试 Z"时调用。先保存面试计划(含主题、时间、方式、面试官、职位/应聘者),再按页面「保存」按钮配置的动作链逐条执行(新建日程、分配面试、AI 面试提醒等),使其与人工点保存的结果一致。属写操作,**必须先展示摘要并获明确确认后再提交**。
|
|
25
|
+
|
|
26
|
+
> **定位候选人**:`--prepare/--commit/--prefill` 均可不带 `--talent-id`,直接 `--mobile <手机号>` 或 `--name <姓名>`(人才库检索;唯一命中自动采用,多条输出 candidates 交用户选择,exit 3)。
|
|
27
|
+
|
|
28
|
+
## 3. 前置条件
|
|
29
|
+
- 已安装招聘服务(第 0 步闸门通过)。
|
|
30
|
+
- **定位前置(必做)**:写操作前必须先按手机号(叠加姓名/渠道缩小范围)搜索定位候选人(`recruit-search-candidate`)拿到 `talentId` 与应聘批次;命中 0 条→提示未找到、不臆测;命中多条→列出候选清单(姓名/手机/渠道/状态/创建时间/`talentId`)请用户确认,**绝不自动取第一条**(写操作选错对象后果不可逆)。消歧规则见 SKILL.md「自然语言 → 参数映射」。
|
|
31
|
+
- 需目标应聘者 `talentId`(来自搜索/详情)与职位 `positionManageId`(来自职位列表/详情);面试官为人员门户字段,传其 `userId`(名称→ID 用 `browser/complete/resource` 解析)。
|
|
32
|
+
- 应聘管理记录 id(`candidate_manage_id`)通常与 `talentId` 的应聘批次对应(新建应聘者后即生成;见 §4.3 字段表)。
|
|
33
|
+
- 第①步保存面试计划后拿到 `formDataId`(= 面试计划记录 id),第②③步均依赖它。
|
|
34
|
+
|
|
35
|
+
## 3.1 字段联动与显示属性联动(EB 能力,运行时获取,不写死)
|
|
36
|
+
面试计划表单用 EB 搭建,字段联动/显示属性联动由表单设计声明,Agent **不写死、不臆造**,统一走运行时获取:
|
|
37
|
+
- `GET /api/ebuilder/form/form/core/getFormLayout?formId=<面试计划表单id>` 返回 `linkageActions`(字段联动)与 `viewLinkages`(显示属性联动:某字段值决定另一字段是否显示/必填/只读)。**部分环境上 GET 返回 405**,需用 POST 同路径(body 带 `module`);`write-op.mjs::getFormLayout/getFormLayoutMeta` 已做 GET→POST 回退,调用方直接用即可。
|
|
38
|
+
- 运行时联动计算:`POST /api/ebuilder/form/form/linkage/executeFdLinkage`(接口存在),传入联动 id 与上下文返回推导结果。
|
|
39
|
+
- **处理原则**:提交前若不确定某字段是否联动/必填依赖(如"选了某面试方式才要求填地点"),先调 `getFormLayout` 读取声明;选项类联动值用 `executeFdLinkage` 计算后填入;遇到"选 A 才显 B"时先向用户收集 A 再展示 B,不一次性把所有字段甩给用户、也不瞎编联动结果。
|
|
40
|
+
|
|
41
|
+
## 4. 请求参数
|
|
42
|
+
|
|
43
|
+
### 4.1 第①步 saveFormData(Query)
|
|
44
|
+
| 字段 | 位置 | 类型 | 必填 | 业务说明 |
|
|
45
|
+
|---|---|---|---|---|
|
|
46
|
+
| `formId` | query | string | 是 | 面试计划表单 id(运行时解析,见 recruit-resolve-metadata.md) |
|
|
47
|
+
|
|
48
|
+
### 4.2 第①步 saveFormData(Body 结构,同新建应聘者)
|
|
49
|
+
| 字段 | 位置 | 类型 | 必填 | 说明 |
|
|
50
|
+
|---|---|---|---|---|
|
|
51
|
+
| `module` | body | string | 是 | `ebuilderform` |
|
|
52
|
+
| `appId` | body | string | 是 | 安装闸门 `data[0]` |
|
|
53
|
+
| `customParam.objId` | body | string | 是 | 面试计划对象 id(运行时解析,见 recruit-resolve-metadata.md) |
|
|
54
|
+
| `formData.module` | body | string | 是 | `ebuilderform` |
|
|
55
|
+
| `formData.client` | body | string | 是 | `pc` |
|
|
56
|
+
| `formData.dataStatus` | body | string | 是 | `submit` |
|
|
57
|
+
| `formData.form.id` | body | string | 是 | 面试计划表单 id(同 query `formId`) |
|
|
58
|
+
| `formData.formLayout.id` | body | string | 是 | 面试计划表单布局 id(运行时解析,见 recruit-resolve-metadata.md) |
|
|
59
|
+
| `formData.dataDetails` | body | array | 是 | 各业务字段(见 4.3) |
|
|
60
|
+
|
|
61
|
+
### 4.3 面试计划表单字段(dataDetails,全字段)
|
|
62
|
+
| 字段 id(运行时解析) | 含义 | 必填 | 值形态(示例) |
|
|
63
|
+
|---|---|---|---|
|
|
64
|
+
| `<面试主题字段id>` | 面试主题 | 是 | `content`(如 `AI工程师-高刚的面试`);**无职位回退(script 版)**:候选人未挂应聘职位(`positionManageId` 解析不到)时,主题取 `姓名+的面试`,**不得拼出 `undefined-…`/`null-…` 前缀**(新建未挂职位的候选人生成主题时该情况常见) |
|
|
65
|
+
| `<开始时间字段id>` | 开始时间 | 是 | `content`(`2026-08-06 10:30`) |
|
|
66
|
+
| `<结束时间字段id>` | 结束时间 | 是 | `content`(`2026-08-06 11:30`) |
|
|
67
|
+
| `<面试方式字段id>` | 面试方式 | 是 | `dataOptions`(现场面试/视频面试/电话面试/AI面试) |
|
|
68
|
+
| `<面试类型字段id>` | 面试类型 | 是 | `dataOptions`(初试/复试…) |
|
|
69
|
+
| `<面试轮次字段id>` | 面试轮次 | 否 | `dataOptions`(第一轮…) |
|
|
70
|
+
| `<面试官字段id>` | 面试官 | 是 | `dataOptions[].optionObj{userId,name}` |
|
|
71
|
+
| `<应聘职位字段id>` | 应聘职位 | 是 | `dataOptions[].optionId` = `positionManageId` |
|
|
72
|
+
| `<面试地点字段id>` | 面试地点 | 否 | `dataText` |
|
|
73
|
+
| `<手机字段id>` | 手机 | **是(脚本强制)** | `content`:从人才基本信息 `telephone` 取值**显式写入**(页面按 talent_id 联动带出,直接 saveFormData 不会自动带) |
|
|
74
|
+
| `<邮箱字段id>` | 邮箱 | **AI面试必填** | `content`:从人才基本信息 `email` 取值**显式写入**;AI面试服务端按邮箱发通知/录屏链接,缺失则**阻断**(支持 `--email` 当场补录) |
|
|
75
|
+
| `<AI面试方案字段id>` | AI面试方案(`digital_id`) | **AI面试必填** | `dataOptions`:`optionId` = 面试数字人配置表记录的 `form_data_id`;来源见 §4.7(未指定时列出候选让用户选,**不自动取第一条**) |
|
|
76
|
+
| `<人才字段id>` | 人才(talent_id) | 是 | `dataOptions[].optionId` = `talentId` |
|
|
77
|
+
| `<应聘管理字段id>` | 应聘管理(candidate_manage_id) | 是 | `dataOptions[].optionId` = 应聘批次记录 id |
|
|
78
|
+
| `<邮件模板字段id>` | 邮件模板 | 否 | `dataOptions`(默认模板) |
|
|
79
|
+
| `<通知内容字段id>` | 通知内容 | 否 | `dataText`(支持 `{面试方式}` `{开始时间}` `{应聘岗位}` 等占位符) |
|
|
80
|
+
| `<状态字段id>` | 状态 | 否 | `dataOptions`(未开始) |
|
|
81
|
+
| `<反馈状态字段id>` | 反馈状态 | 否 | `dataOptions`(未反馈) |
|
|
82
|
+
| `<系统/开关字段id>`(多个) | 系统/开关字段 | 否 | 照抄表单默认值(默认/关闭/是/0/3 等) |
|
|
83
|
+
|
|
84
|
+
> 字段 id 不写死:经 `recruit-resolve-metadata.md` §5 的 `ds/fields` 按 `config.dataKey` 解析(结果已并入环境缓存 `fields[objId]` 的 `{dataKey: fieldId}`)。解析不到时停止,不得臆造 fieldId。
|
|
85
|
+
|
|
86
|
+
> 面试方式枚举:**一律经 `ds/options` 运行时解析,不写死**(实测示例:现场面试=`841052191228968963`、电话面试=`841052191228968961`、视频面试=`841052191228968962`、**AI面试=`841052191228968964`**;各环境/版本可能不同,以实际返回为准)。面试环节/轮次同理,不写死。
|
|
87
|
+
|
|
88
|
+
### 4.4 动作链中的 esb 动作(runEsb)
|
|
89
|
+
| 字段 | 位置 | 类型 | 必填 | 说明 |
|
|
90
|
+
|---|---|---|---|---|
|
|
91
|
+
| `objId` | query | string | 是 | 面试计划对象 id(运行时解析,见 recruit-resolve-metadata.md) |
|
|
92
|
+
| `dataIds` | body | string | 是 | 第①步返回 `formDataId` |
|
|
93
|
+
| `esbActionIds` | body | string | 是 | **「保存」按钮 actions[] 里 `actionType=esb` 的动作 id**(按 `showOrder` 顺序逐条触发) |
|
|
94
|
+
| `objId` | body | string | 是 | 同 query |
|
|
95
|
+
|
|
96
|
+
> 注:**不写死**任何 `esbActionIds`。运行时 `getFormButtons(objId, layoutId)` 取 `buttonKey=save` 的按钮,读其 `actions[]`(见 §4.6)——动作数量与名称因环境/版本而异(如「面试管理-新建日程」「AI面试时发送提醒」),有多少条执行多少条。
|
|
97
|
+
|
|
98
|
+
### 4.5 动作链中的 jsCode 动作 → assignedInterview(分配面试)
|
|
99
|
+
| 字段 | 位置 | 类型 | 必填 | 说明 |
|
|
100
|
+
|---|---|---|---|---|
|
|
101
|
+
| `formDataId` | query | string | 是 | 第①步返回 `data.id`(面试计划记录 id) |
|
|
102
|
+
|
|
103
|
+
> **无请求体**(POST 仅 Query 传 `formDataId`)。
|
|
104
|
+
> 页面「保存」按钮用一段 jsCode 动作(名称如「安排面试后续动作API」)调本接口;脚本**不执行页面脚本**,而是识别 `ecode` 中的 `/api/recruit/candidate/assignedInterview` 并**等价调用**,位置严格按该动作的 `showOrder`。
|
|
105
|
+
|
|
106
|
+
### 4.6 「保存」按钮动作链(与页面点保存等价,核心契约)
|
|
107
|
+
页面点「保存」不是只调一次 `saveFormData`,而是**依次执行按钮配置里的整串动作**。抓包实证(2026-08-17):
|
|
108
|
+
| showOrder | 动作名 | actionType | 实际请求 |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| 0 | 保存 | system | `saveFormData` |
|
|
111
|
+
| 1 | 面试管理-新建日程 | esb | `runEsb`(esbActionIds=动作 id) |
|
|
112
|
+
| 2 | 安排面试后续动作API | jsCode | `assignedInterview?formDataId=…`(脚本内 ecode 显式调用) |
|
|
113
|
+
| 3 | AI面试时发送提醒 | esb | `runEsb`(esbActionIds=动作 id) |
|
|
114
|
+
|
|
115
|
+
> 某环境实测(2026-10-21)动作链是 4 条,且多一条「**创建视频会议**」:新建日程 → 创建视频会议 → 面试安排后续动作API → AI面试时发送提醒。
|
|
116
|
+
> **另一环境实测(2026-10-21)也是 4 条,但第 4 条是「面试管理-新建EB日程」**(8 月抓包时只有 3 条,说明期间配置有更新)。
|
|
117
|
+
> 结论:**条数与名称随环境、随配置变更而变化**,一律以 `getFormButtons` 返回为准,不得按名称写死执行清单。
|
|
118
|
+
|
|
119
|
+
**技能执行规则**
|
|
120
|
+
1. `getFormButtons` 取 `buttonKey=save` 的按钮 → `actions[]` 按 `showOrder` 升序(跨环境自适应,不写死 id / 名称 / 条数);
|
|
121
|
+
2. **`enable=0` 的动作一律跳过**(页面上被禁用的动作不会执行,脚本也不能执行;实测人才表单 7 条动作里 3 条为禁用态);
|
|
122
|
+
3. 跳过 `actionType=system`(已由第①步 `saveFormData` 完成);
|
|
123
|
+
4. `actionType=esb` → `runEsb`,**逐条按序**;任一失败即中断并报错(与页面一致,后续动作不再执行);
|
|
124
|
+
5. `actionType=jsCode` 且 `ecode` 含 `assignedInterview` → 等价调用;**其它自定义 jsCode 无法等价执行 → 跳过并写入 `warnings`**(不静默);
|
|
125
|
+
6. 若整串动作里**没有** `assignedInterview`(部分环境未把它配成保存动作)→ 在动作链之后**兜底调用一次**并写入 `warnings`;
|
|
126
|
+
7. `--skip-save-actions` 仅用于排查:只保存表单、不执行任何后续动作(记录不进入面试流程)。
|
|
127
|
+
|
|
128
|
+
> 说明:面试通知由**服务端动作流**发出(不是技能自己拼消息)。技能只要把 `esb` 动作按页面顺序触发,通知/日程/AI 面试提醒就与人工点保存完全一致。
|
|
129
|
+
|
|
130
|
+
### 4.7 AI面试方案(面试数字人配置表):运行时定位 + 必填选择
|
|
131
|
+
|
|
132
|
+
**为什么必须动态**:`digital_id` 的候选来自「面试数字人配置」列表,该表在不同环境 **objId / listId / 记录 id 全不同**(某环境实测 listId=`1274931191811432873`、objId=`1274931183271831435`,不同环境完全不同)。
|
|
133
|
+
|
|
134
|
+
**定位链路(全部运行时解析,不写死)**
|
|
135
|
+
1. **首选:关联字段候选接口**(不依赖菜单/列表,标准包未配菜单也能用)
|
|
136
|
+
`POST /api/ebuilder/form/common/browser/complete/ebuilder`
|
|
137
|
+
```json
|
|
138
|
+
{ "browserMultiple": false, "newly": 1, "searchValue": "",
|
|
139
|
+
"formParam": "{\"formId\":\"<面试计划formId>\",\"layoutId\":\"<layoutId>\",\"fieldId\":\"<digital_id字段id>\",\"filterItems\":[],\"module\":\"ebuilderform\",\"dataDetails\":[]}",
|
|
140
|
+
"openScroll": true, "controlId": "<digital_id字段id>", "businessId": "<formId>", "variableMap": {} }
|
|
141
|
+
```
|
|
142
|
+
响应 `data.data[] = { id, name, ebObjId }`,`id` 即提交用的 `optionId`,`name` 即方案名。
|
|
143
|
+
2. **兜底:菜单列表**(`cache.lists.digital_human` → `listInit` 取 `objid` → `getListDatas?passid={objid}&cid={objid}`)。
|
|
144
|
+
|
|
145
|
+
> 跨环境实测:**部分环境**有「面试数字人配置表」菜单(listId `1274931191811432873`,2 个方案,默认「大模型面试」);**部分环境没有该菜单**(36 个 SEARCH 菜单里都没有),只能走接口 ①——实测返回唯一方案「大模型岗位」(`1324570620131057673`),且 部分环境 **没有** `digital_id` 默认值(`defaultDetails` 无此项)。所以不能把「默认方案」当成通用前提。
|
|
146
|
+
|
|
147
|
+
**选择规则**
|
|
148
|
+
- 传了 `--ai-plan <方案名或id>`:id 精确 → 名称全等 → 名称包含;**命中多条视为歧义**并列出,绝不自动取第一条。
|
|
149
|
+
- 没传:`--prepare` 输出 `aiPlans` 候选清单 + `needAiPlan=true`;`--commit` 直接**阻断**(不落库、不执行动作链),提示用户选定后重试。
|
|
150
|
+
- 候选里 `isDefault=true` 的那条是**页面默认方案**(来自 `defaultDetails.digital_id`,实测为「大模型面试」),同时单独输出 `defaultAiPlan`;用户说"用默认"时按该值传 `--ai-plan` 即可。
|
|
151
|
+
|
|
152
|
+
### 4.8 联动必填核对(`getFormLayout` 元数据,只读)
|
|
153
|
+
|
|
154
|
+
`GET /api/ebuilder/form/form/core/getFormLayout?formId=<面试计划formId>` 返回:
|
|
155
|
+
- `viewRelateConfig[]`:字段级 `required/readOnly/display`(**静态必填**);
|
|
156
|
+
- `viewLinkages[]`:条件必填/显隐(`linkageProp` 含 `show`/`edit`/`required`/`readonly`/`hide`),条件形如 `interview_type EQUAL <枚举名>`;
|
|
157
|
+
- `defaultDetails[]`:页面默认值(有默认值的字段不写也会被带上)。
|
|
158
|
+
|
|
159
|
+
`--prepare` 会据此输出 `requiredHint`:当前面试方式下**必填、但本次未提供且无默认值**的字段(dataKey + 中文名)。
|
|
160
|
+
|
|
161
|
+
> 某环境实测(2026-08-17 抓包,`getFormLayout?formId=840751242946035714`):
|
|
162
|
+
> - 静态必填 10 个:应聘管理、应聘职位、人才、面试主题、面试方式、面试轮次、面试官、开始时间、关联日程、状态(后两个有默认值);
|
|
163
|
+
> - **`AI面试`(= 数字人面试)→ `digital_id`(AI面试方案)+ `email` 必填**,同时**隐藏**关联日程、发送渠道与两个开关字段;
|
|
164
|
+
> - `AI面试(小程序)` → `interview_paper_id`(面试试卷)+ `send_channel`(发送渠道)必填(与数字人版是两种形态,不要混);
|
|
165
|
+
> - `send_channel = 邮件` → `notice_mould`(通知模板)必填(有默认模板)。
|
|
166
|
+
>
|
|
167
|
+
> **枚举改名/换 id 的坑(已处理)**:联动条件绑的是 optionId。数字人面试原来的枚举项 `AI面试(数字人)`(optionId `841052191228968964`)已被删除,新增的 `AI面试`(optionId `1274947951008702504`)就是它。若按名称直接比对会判成"条件不命中"、得出"页面不要求方案"的错误结论。
|
|
168
|
+
> 判定规则见 `computeRequiredHint`:条件 optionId **仍在枚举** → 严格按当前名比较;**已不在枚举** → 仅当用户所选是「裸名」时按去括号比较(`AI面试(数字人)` ≈ `AI面试`,而 `AI面试(小程序)` 这类带括号取值不参与),从而既兼容改名又不会串到小程序版。
|
|
169
|
+
>
|
|
170
|
+
> 页面默认方案:`digital_id` 的 `defaultDetails` = **「大模型面试」**(记录 id `1274944914469281862`,在面试数字人配置表内)。`--prepare` 会把该默认方案标成 `isDefault=true` 并输出 `defaultAiPlan`。
|
|
171
|
+
>
|
|
172
|
+
> **某环境实测(2026-10-21,POST 取布局)**:
|
|
173
|
+
> - 静态必填 10 个:人才、应聘职位、面试主题、面试方式、面试轮次、**面试表格(`interview_table`,部分环境特有)**、面试官、开始时间、关联日程、状态;
|
|
174
|
+
> - `AI面试` → 联动 `required digital_id` + `required email`(与另一环境实测结论一致),并隐藏 `adjutant_interviewer`;
|
|
175
|
+
> - `AI面试(小程序)` → 面试试卷 + 发送渠道(同另一环境);
|
|
176
|
+
> - `defaultDetails` **没有** `digital_id` → 部分环境无页面默认方案,必须由用户选。
|
|
177
|
+
> - 部分环境的联动条件里 optionId 是旧值(`841052191228968964` / `841052191228968960`),枚举已换成 `937153879646070190…` / `1320966047218835460`,同样靠上述「optionId 在不在枚举 + 裸名去括号」规则识别。
|
|
178
|
+
|
|
179
|
+
## 5. 响应数据结构
|
|
180
|
+
- 第①步:`data.id` = 面试计划记录 id(后续步骤入参)。
|
|
181
|
+
- 动作链中的 esb 动作:`data.successNum` / `data.failNum` / `data.successMsg` = 动作流触发结果(`status=false` 即失败)。
|
|
182
|
+
- 动作链中的分配面试:`data.msg`(操作成功)、`data.finalBatchId`(新应聘批次 id)、`data.needRefresh` / `data.refreshCard`(页面刷新标记)。
|
|
183
|
+
|
|
184
|
+
## 6. 请求示例
|
|
185
|
+
```json
|
|
186
|
+
// ① 保存面试计划
|
|
187
|
+
POST /api/ebuilder/form/form/core/saveFormData?formId=<面试计划 formId,getObjsByTag 同响应返回>
|
|
188
|
+
{ "module": "ebuilderform",
|
|
189
|
+
"customParam": { "objId": "${INTERVIEW_PLAN_FORM_OBJID}", "name": "面试管理-<主题> <时间>", "firstDataName": "面试管理-<主题> <时间>",
|
|
190
|
+
"isFlowEnd": false, "otherOperator": "", "dataStatus": "submit", "rightType": "0", "appId": "<data[0]>" },
|
|
191
|
+
"appId": "<data[0]>",
|
|
192
|
+
"formData": { "module": "ebuilderform", "client": "pc", "dataStatus": "submit",
|
|
193
|
+
"form": { "id": "<面试计划 formId,getObjsByTag 同响应返回>" },
|
|
194
|
+
"formLayout": { "id": "<面试计划 formLayout.id,getFormLayout 响应>" },
|
|
195
|
+
"dataDetails": [
|
|
196
|
+
{ "formField": { "id": "<面试主题字段id>" }, "content": "AI工程师-高刚的面试" },
|
|
197
|
+
{ "formField": { "id": "<开始时间字段id>" }, "content": "2026-08-06 10:30" },
|
|
198
|
+
{ "formField": { "id": "<结束时间字段id>" }, "content": "2026-08-06 11:30" },
|
|
199
|
+
{ "formField": { "id": "<面试方式字段id>" }, "dataOptions": [{ "optionId": "841052191228968963", "content": "现场面试" }] },
|
|
200
|
+
{ "formField": { "id": "<面试类型字段id>" }, "dataOptions": [{ "optionId": "841052191228968964", "content": "初试" }] },
|
|
201
|
+
{ "formField": { "id": "<面试官字段id>" }, "dataOptions": [{ "optionId": "<面试官userId>", "content": "<面试官姓名>" }] },
|
|
202
|
+
{ "formField": { "id": "<应聘职位字段id>" }, "dataOptions": [{ "optionId": "<positionManageId>", "content": "<职位名>" }] },
|
|
203
|
+
{ "formField": { "id": "<人才字段id>" }, "dataOptions": [{ "optionId": "<talentId>", "content": "<姓名>" }] },
|
|
204
|
+
{ "formField": { "id": "<应聘管理字段id>" }, "dataOptions": [{ "optionId": "<candidate_manage_id>", "content": "<id>" }] },
|
|
205
|
+
{ "formField": { "id": "<状态字段id>" }, "dataOptions": [{ "optionId": "841052191228968972", "content": "未开始" }] },
|
|
206
|
+
{ "formField": { "id": "<反馈状态字段id>" }, "dataOptions": [{ "optionId": "0", "content": "未反馈" }] }
|
|
207
|
+
] } }
|
|
208
|
+
|
|
209
|
+
// ②③④ 动作链:从「保存」按钮 actions[] 按 showOrder 逐条执行(下方为 某环境实例,id 均为运行时解析结果)
|
|
210
|
+
POST /api/ebuilder/form/esb/runEsb?objId=${INTERVIEW_PLAN_FORM_OBJID}
|
|
211
|
+
{ "dataIds": "<formDataId>", "esbActionIds": "<showOrder=1 的 esb 动作 id>", "objId": "${INTERVIEW_PLAN_FORM_OBJID}" }
|
|
212
|
+
|
|
213
|
+
// 分配面试(无 body)——对应 showOrder=2 的 jsCode 动作
|
|
214
|
+
POST /api/recruit/candidate/assignedInterview?formDataId=<formDataId>
|
|
215
|
+
|
|
216
|
+
POST /api/ebuilder/form/esb/runEsb?objId=${INTERVIEW_PLAN_FORM_OBJID}
|
|
217
|
+
{ "dataIds": "<formDataId>", "esbActionIds": "<showOrder=3 的 esb 动作 id>", "objId": "${INTERVIEW_PLAN_FORM_OBJID}" }
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## 7. 响应示例
|
|
221
|
+
```json
|
|
222
|
+
// ①
|
|
223
|
+
{ "code": 200, "status": true, "data": { "id": "1300448559071436804" } }
|
|
224
|
+
// ②
|
|
225
|
+
{ "code": 200, "status": true, "data": { "successNum": 2, "failNum": 0, "successMsg": "1条数据执行esb接口完成", "needRefresh": true } }
|
|
226
|
+
// ③
|
|
227
|
+
{ "code": 200, "status": true, "data": { "msg": "操作成功", "needRefresh": true, "finalBatchId": "1300447863211237411", "refreshCard": true, "fromPoolBatch": false } }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
脚本 `--commit` 输出示例(含动作链执行结果与卡片单页链接):
|
|
231
|
+
```json
|
|
232
|
+
{ "mode": "commit", "result": "success",
|
|
233
|
+
"interviewFormId": "1328644967777771668",
|
|
234
|
+
"interviewCardUrl": "{baseUrl}/sp/ebdfpage/card/0/<面试计划 objId>/1328644967777771668",
|
|
235
|
+
"saveActions": [
|
|
236
|
+
{ "order": 1, "name": "面试管理-新建日程", "type": "esb", "ok": true, "msg": "【面试管理-新建日程】执行成功!" },
|
|
237
|
+
{ "order": 2, "name": "安排面试后续动作API", "type": "jsCode", "ok": true, "msg": "等价调用 assignedInterview(分配面试)" },
|
|
238
|
+
{ "order": 3, "name": "AI面试时发送提醒", "type": "esb", "ok": true, "msg": "【招聘recruit-新建AI面试后按钮事件发送提醒】执行成功!" }
|
|
239
|
+
],
|
|
240
|
+
"warnings": [],
|
|
241
|
+
"assigned": { "msg": "操作成功", "finalBatchId": "1318436783908855811" } }
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## 8. 错误码
|
|
245
|
+
| 错误码 | 含义 | AI 处理建议 |
|
|
246
|
+
|---|---|---|
|
|
247
|
+
| 非 200 | 认证/参数错误 | 提示检查认证(`weaver-work-cli auth status`) / 参数;参数缺失先反问 |
|
|
248
|
+
| 分配面试 400 | `formDataId` 缺失或无效 | 确认第①步返回的 `data.id` 已正确透传 |
|
|
249
|
+
| 动作链 esb `status=false` | 日程/提醒等动作流执行失败 | 按动作名报错并**中断**(后续动作不执行,与页面一致);检查该动作流配置 |
|
|
250
|
+
| 本地阻断:AI面试缺邮箱 | `--email` 未提供且人才资料无邮箱 | **不创建**;提示用户提供邮箱(`--email`)或在人才资料补全后重试 |
|
|
251
|
+
| 本地阻断:邮箱格式错 / 缺手机 | 取值不合法 | 提示用户提供有效值后重试,不静默写空 |
|
|
252
|
+
|
|
253
|
+
## 9. 调用参考
|
|
254
|
+
- 用户场景:"给 X 安排面试"。
|
|
255
|
+
- **流程**:收集(应聘者/职位/面试官/时间/方式)→ 展示摘要(含将执行的动作链清单)→ 用户确认 → ① 保存 → ②③④ 按「保存」按钮 actions[] 顺序执行 → 输出结果(动作链明细 + 新应聘批次 `finalBatchId`)。
|
|
256
|
+
- 面试官名称→ID:走 `browser/complete/resource`(fieldId 按门户字段规则);命中多个列出选项让用户确认。
|
|
257
|
+
- **确认摘要模板(提交前必展示,必须带出定位键)**:
|
|
258
|
+
> 即将为 **姓名(手机:XXX | `talentId=XXX`)** 安排面试:
|
|
259
|
+
> - 职位:XXX | 方式:现场/视频/电话/AI | 时间:XXX
|
|
260
|
+
> - 面试官:XXX
|
|
261
|
+
> 请确认对象与参数无误(确认后才会保存并分配)。
|
|
262
|
+
|
|
263
|
+
## 10. 注意事项
|
|
264
|
+
- **写操作确认**:必须展示摘要并获用户明确确认后再提交。**提交时默认执行「保存」按钮的完整动作链**(含服务端发出的面试通知/日程/提醒),与人工点保存一致;`--prepare` 会先把动作清单列出来供确认。
|
|
265
|
+
- **不得"只保存表单"**:只调 `saveFormData` 会留下「有表单、无日程、无分配、无通知」的半成品(页面看不到、流程不生效)。必须走完动作链;`--skip-save-actions` 仅限排查。
|
|
266
|
+
- **定位前置**:提交前必须先按手机号/姓名搜索定位到唯一候选人(见 §3),命中多条先消歧,绝不自动取第一条。
|
|
267
|
+
- 面试官/职位/人才/应聘管理均为**门户字段**,`dataOptions[].optionObj` 内含 `userId`/`name`,展示取 `name`,提交传 `optionId`(= userId / positionManageId / talentId / candidate_manage_id)。
|
|
268
|
+
- 面试字段 id 经 `ds/fields` 按 `dataKey` 解析(`interviewer`/`position_manage_id`/`mobile`/`talent_id`/`candidate_manage_id`/`email`,已并入环境缓存 `fields[objId]`),如需动态确认字段 id 可查 `recruit-resolve-metadata.md` §5。
|
|
269
|
+
- **面试官默认 = 当前登录用户**:`--interviewer` 可省略;省略时经 `POST /api/baseserver/layout/teamsCheck` 取 `currentUser` 作为面试官(与页面「选 AI面试 后联动带出当前人」一致)。**不得**用"人员候选列表第一条"当默认(可能是任意人;2026-10-21 已修)。
|
|
270
|
+
- **手机号 / 邮箱必须显式写入**(2026-10-21 修):页面操作时表单按 `talent_id` **联动带出**手机/邮箱,但**直接调 `saveFormData` 不触发表单联动** → 不写就落空。脚本从 `getCandidateCardBaseInfo` 的 `talent.telephone` / `talent.email` 取值写入;也支持 `--mobile` / `--email` 当场补录(补录优先)。
|
|
271
|
+
- **AI 面试邮箱为必填**:`type` 含 `AI`(兼容「AI面试 / AI 面试」命名差异)时,若人才资料与 `--email` 都没有邮箱,**直接阻断创建**,提示用户提供邮箱后重试;邮箱格式不合法同样阻断。**不得静默写空、不得降级创建**。
|
|
272
|
+
- **AI面试方案(`digital_id`)为必填**:未传 `--ai-plan` 时 `--prepare` 输出 `aiPlans` 候选、`--commit` 直接阻断;候选来自「面试数字人配置」列表,**objId/listId/记录 id 全部运行时解析,不写死**。用户选定后带 `--ai-plan` 重试;多条命中先消歧,**绝不自动取第一条**。
|
|
273
|
+
- **联动必填以表单配置为准**:`--prepare` 的 `requiredHint` 会列出「当前面试方式下必填但未提供且无默认值」的字段。若出现 `interview_paper_id`(面试试卷)/`send_channel`(发送渠道),说明该环境页面还要求这两项,需先与用户确认后再补写(见文档末尾「未闭环」)。
|
|
274
|
+
- **记录卡片单页链接**:`--commit` 输出 `interviewCardUrl = {baseUrl}/sp/ebdfpage/card/0/{objId}/{formDataId}`(objId 运行时从环境缓存取,dataId 为 saveFormData 返回值);供 Agent 在回答里给出可点击链接。
|
|
275
|
+
- 时间格式:`YYYY-MM-DD HH:mm`(含空格)。
|
|
276
|
+
- **AI面试(数字人)**:当 面试方式 = `AI面试` 时,服务端按数字人配置(`uf_rcrt_zego_config` 即构云端录制 / `uf_rcrt_digital_human` 面试方案,管理员一次性配置,详见 `recruit-business-map/references/ai-interview-manual.md`)自动驱动数字人面试与通知(`uf_rcrt_dhi_notify_log`);技能侧只需正确选择「AI面试」方式并走 ①②③ 三步编排,**无需额外操作**。数字人自动约面(机器人自动约面)的 HR 操作与 admin 配置要点见 `recruit-business-map/references/ai-interview-manual.md` 操作手册备份;手动模式已验证 OK,视为功能支持。
|
|
277
|
+
|
|
278
|
+
## 11. 预填模式(打开人才卡片 → 面试安排表单 → 选面试方式;人工保存,不落库)
|
|
279
|
+
|
|
280
|
+
**用途**:对齐"人工安排面试"的操作路径,支撑「AI面试邀约」演示链路(原始需求:**打开人才卡片 → 安排AI面试 → 打开面试管理页面**)。与 §1–§10 的 `--prepare/--commit`(**直接落库**)并列——本模式**不落库**,只"打开页面 + 在表单里选面试方式",由 HR 核对后保存。
|
|
281
|
+
|
|
282
|
+
**用法**
|
|
283
|
+
```bash
|
|
284
|
+
node scripts/recruit-arrange-interview.mjs --prefill --talent-id <id> [--type AI面试]
|
|
285
|
+
```
|
|
286
|
+
输出:`talentCardUrl`(人才卡片)、`interviewListUrl`(面试管理列表)、`jsExpr`(在表单上选「面试方式=<type>」)、`steps`。
|
|
287
|
+
|
|
288
|
+
**执行步骤(Agent 编排,依赖浏览器自动化 browser-skill/bsk)**
|
|
289
|
+
1. 打开 `talentCardUrl` → 进入该候选人卡片;
|
|
290
|
+
2. 点卡片上的「**安排面试**」→ 打开面试安排表单(**主题 / 候选人 / 职位由表单默认值自动带入**,无需预填);
|
|
291
|
+
3. 在页面执行 `jsExpr`(例:`bsk evaluate "<jsExpr>"`)→ 选中「面试方式=`<type>`」,**触发表单联动**;
|
|
292
|
+
4. 由 HR 核对(可按需调整)后点「**保存**」完成面试安排;
|
|
293
|
+
5. (可选)打开 `interviewListUrl` 查看面试管理列表。
|
|
294
|
+
|
|
295
|
+
**AI面试联动(2026-10-21 核对)**
|
|
296
|
+
- **「AI面试」= 数字人面试**:联动条件里的 `AI面试(数字人)`(旧 optionId `841052191228968964`)就是它,只是后来枚举项换了 id 与显示名(新 `1274947951008702504`「AI面试」)。
|
|
297
|
+
- 选中「面试方式=AI面试」后,页面联动带出:**AI面试方案(默认「大模型面试」)**、面试官=当前登录人、开始/结束时间;并**隐藏**关联日程、发送渠道。
|
|
298
|
+
- `--commit` 路径**不依赖联动**:方案由 `--ai-plan` 显式指定(未指定时 `--prepare` 给候选、`--commit` 阻断),避免"默认值静默生效"而用户不知情。
|
|
299
|
+
|
|
300
|
+
**字段与枚举(运行时解析,不写死)**
|
|
301
|
+
- 字段 id:环境缓存 `cache.fields[面试计划 objId]`(如 `interview_type`);
|
|
302
|
+
- 「面试方式」optionId:`getDsOptions(objId, interview_type, appId)` 按名称取(实测示例:现场=`841052191228968963`、视频=`…962`、电话=`…961`、**AI面试=`…964`**)。
|
|
303
|
+
|
|
304
|
+
**通知与后续动作(两条路径结果一致)**
|
|
305
|
+
- **页面点「保存」= 依次执行按钮配置的动作链**:系统保存 → esb(新建日程)→ jsCode(分配面试)→ esb(AI面试提醒)。`--commit` 已按**同一动作链**执行(见 §4.6),所以脚本落库与人工保存效果一致。
|
|
306
|
+
- 本 `--prefill` 模式把"填表 + 点保存"交给页面/人工,技能不落库;通知仍由服务端动作流发出,技能不自己拼消息。
|
|
307
|
+
|
|
308
|
+
**边界**
|
|
309
|
+
- 本模式依赖浏览器自动化(WorkBuddy 桌面端 `bsk`,或具备表单注入能力的客户端);小E 端若只能打开页面,可只打开 `talentCardUrl` / `interviewListUrl`,第③步由 HR 手点。
|
|
310
|
+
- **AI面试闭环不可全链自动化**:技能止于"面试安排",通知/候选人录制/视频归集均由服务端与候选人侧完成;HR 后续在面试管理里查台账、`recruit-detail-interview` 看面试与反馈、`recruit-edit-interview-feedback` 填反馈。
|
|
311
|
+
|
|
312
|
+
## 12. 未闭环(2026-10-21 核对联动必填得出)
|
|
313
|
+
|
|
314
|
+
| # | 事项 | 现状 | 影响 |
|
|
315
|
+
|---|---|---|---|
|
|
316
|
+
| 1 | 面试试卷 `interview_paper_id` / 发送渠道 `send_channel` | 仅 **`AI面试(小程序)`** 形态必填(数字人版会隐藏这两项);脚本未写、也未提供候选查询 | 若在对话里选「AI面试(小程序)」,页面会要求这两项;当前建议统一走「AI面试」(数字人) |
|
|
317
|
+
|
|
318
|
+
> 结论:**「AI面试」= 数字人面试**,必填项是 **AI面试方案 + 邮箱**,不需要面试试卷/发送渠道(那两项属于「AI面试(小程序)」)。
|
|
319
|
+
>
|
|
320
|
+
> **部分环境已实测(2026-10-21)**:动作链解析出 4 个动作(各环境动作集不同,以运行时解析为准);AI 面试方案候选可用(「大模型岗位」);缺方案时 `--commit` 正确阻断;视频面试路径不受影响。
|
|
321
|
+
|
|
322
|
+
> **--commit 成功产物(2026-10-22 定稿)**:两个 Markdown 链接——① `viewLink`(面试安排详情页)② `listLocateLink`(面试管理列表并滑出本次安排,listId 取环境缓存动态组合)。
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# 环境能力探测(运行时自适应,不写死版本)
|
|
2
|
+
|
|
3
|
+
>
|
|
4
|
+
> **核心原则:不判断"是哪个版本",而是运行时探测"这个环境有哪些能力"**。探测结果驱动路由——能力可用才执行,未启用/未部署 → 友好提示并终止,**绝不猜测、不硬凑、不假装成功**。
|
|
5
|
+
|
|
6
|
+
## 1. 为什么需要(背景)
|
|
7
|
+
|
|
8
|
+
不同应用版本的功能差异是**离散且未知的**(全功能版本有 需求/职位/人才库/面试/Offer/入职/统计 全套;部分版本有 需求/职位/人才库/面试,但**无 Offer、无入职管理、无统计看板**,且菜单命名不同)。技能不得硬编码"某版本全 / 某版本简",因为:
|
|
9
|
+
- 未来可能有第三个版本(功能组合又不同);
|
|
10
|
+
- 同一版本不同租户可能因授权/配置不同而有差异;
|
|
11
|
+
- 菜单名会变(人才管理→人才库、招聘职位→职位列表、入职管理→应聘管理是不同业务、Offer管理→offer设置是配置页)。
|
|
12
|
+
|
|
13
|
+
## 2. 能力探测流程(每次会话开始时执行一次,结果缓存于本次会话)
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
第 0 步 安装闸门:GET /api/bs/ebuilder/app/tags/getAppIds?tag=weaver-recruit-service
|
|
17
|
+
├─ 失败/空 → ⚠️ 未安装招聘服务,终止(不进入任何招聘接口)
|
|
18
|
+
└─ 成功 → appId
|
|
19
|
+
|
|
20
|
+
第 1 步 表单存在性:对每个业务 tag 调 GET /api/ebuilder/form/obj/getObjsByTag?appId={appId}&tag={tag}
|
|
21
|
+
tag 清单:uf_rcrt_talent_pool(人才库) / uf_rcrt_demand_manage(需求) / uf_rcrt_position_manage(职位)
|
|
22
|
+
/ uf_rcrt_interview_plan(面试) / uf_rcrt_entry_manage(入职) / uf_rcrt_offer(Offer)
|
|
23
|
+
→ 每个 tag:objId 解析到 = 表单存在;解析不到 = 表单未部署
|
|
24
|
+
|
|
25
|
+
第 2 步 菜单入口:GET /api/cusapp/app/allMenus(递归 children[])
|
|
26
|
+
→ 对每个业务用「候选关键词组 + pageType=SEARCH」语义匹配(见 recruit-resolve-metadata.md §3.1)
|
|
27
|
+
→ 命中 = 有列表入口;不命中 = 无入口(可能是未启用,也可能是换名/配置页混淆)
|
|
28
|
+
|
|
29
|
+
第 3 步 汇总能力清单:
|
|
30
|
+
功能 表单(objId) 菜单(listId) 判定
|
|
31
|
+
─────────────────────────────────────────
|
|
32
|
+
人才搜索/详情 有 有(或无也可) 可用(详情不依赖列表菜单)
|
|
33
|
+
需求列表 有 有 可用
|
|
34
|
+
职位列表 有 有 可用
|
|
35
|
+
面试(安排/查) 有 — 可用(写操作/卡片接口不依赖菜单;安排面试需 `getObjsByTag` + `ds/fields` 再确认)
|
|
36
|
+
入职(名单/办/取消)有 有 可用
|
|
37
|
+
有 无 ⚠️ 未启用(表单在但无入口)→ 拦截
|
|
38
|
+
无 — ⚠️ 未部署 → 拦截
|
|
39
|
+
Offer(发/查) 有 有 可用
|
|
40
|
+
有 无 ⚠️ 未启用 → 拦截(部分版本:表单在、仅 offer设置 配置页)
|
|
41
|
+
招聘统计 有看板 PAGE 菜单 可用(nchart)
|
|
42
|
+
无看板 PAGE 菜单 ⚠️ 未启用 → 拦截(部分版本:仅 EDC 报表,不在本技能范围)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 3. 判定矩阵(每类功能统一规则)
|
|
46
|
+
|
|
47
|
+
| 场景 | 判定 | 输出 |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| 表单 objId 解析不到 | **未部署** | `⚠️ 当前环境未部署「X」功能,无法执行。` + 说明 + 停止 |
|
|
50
|
+
| 表单在、但菜单匹配不到(且该功能依赖列表入口) | **未启用** | `⚠️ 当前环境未启用「X」功能(未找到对应菜单)。` + 说明「不顶替」+ 停止 |
|
|
51
|
+
| 菜单匹配到**配置页/近似业务**(设置/配置/复制/开发排查等) | **不算命中** | 继续匹配;全不中按上一条处理 |
|
|
52
|
+
| 表单+菜单都在,但接口调用失败/业务码失败 | **调用失败** | 按接口文档错误码解释,如实提示,停止;不假装成功 |
|
|
53
|
+
| 表单+菜单都在,接口正常 | **可用** | 正常执行 |
|
|
54
|
+
|
|
55
|
+
**红线(严禁)**:
|
|
56
|
+
- 菜单匹配不到 → **不得用近似业务菜单硬凑**(如 部分版本用「应聘管理」顶入职、用「offer设置」顶 Offer);
|
|
57
|
+
- 字段/枚举拿不到 → 不得臆造 id(按 data-dictionary 原样回退,或反问用户);
|
|
58
|
+
- 接口 HTTP 200 但业务码失败 → 不得仅凭状态码判成功;
|
|
59
|
+
- 写操作某步失败 → 如实上报「已完成 X / 失败 Y」,不谎称整体成功;
|
|
60
|
+
- 网络超时写操作不自动重试(防重复写入)。
|
|
61
|
+
|
|
62
|
+
## 4. 各功能能力探测细则
|
|
63
|
+
|
|
64
|
+
### 4.1 人才搜索 / 详情
|
|
65
|
+
- 依赖:`uf_rcrt_talent_pool` objId(tag 解析)。
|
|
66
|
+
- 详情编排不依赖列表菜单(卡片接口直接收 talentId+batchId);但「搜索」需要列表 `getListDatas`(listId 经 allMenus 发现,或 L2 dataset/v2 降级)。
|
|
67
|
+
- 人才库菜单候选词:`人才管理`/`人才库`。
|
|
68
|
+
|
|
69
|
+
### 4.2 需求 / 职位列表
|
|
70
|
+
- 依赖:`uf_rcrt_demand_manage`/`uf_rcrt_position_manage` objId + 对应 SEARCH 菜单。
|
|
71
|
+
- 菜单候选词:需求=`招聘需求`/`需求`;职位=`招聘职位`/`职位列表`。
|
|
72
|
+
- 菜单匹配不到 → 未启用拦截。
|
|
73
|
+
|
|
74
|
+
### 4.3 面试(安排 / 查询 / 催评)
|
|
75
|
+
- 依赖:`uf_rcrt_interview_plan` objId + 布局 formId(同由 `getObjsByTag` 一次返回)+ 字段 id(经 `ds/fields` 按 `dataKey` 解析)。
|
|
76
|
+
- 查询/反馈卡片不依赖菜单;安排面试走 saveFormData→runEsb→assignedInterview(不依赖列表菜单)。
|
|
77
|
+
- **判定要点**:objId 解析到 = 表单在 = 可用;解析不到 = 未部署拦截。
|
|
78
|
+
- 面试通知/催评动作流:`esbActionIds` 跨环境不同,须运行时按按钮配置解析(面试计划表单 `getFormButtons` / 面试反馈列表 `getListButtons`,见 recruit-resolve-metadata.md §4)——**解析不到时反问用户提供,不臆造 id**。
|
|
79
|
+
|
|
80
|
+
### 4.4 入职(名单 / 办入职 / 取消改期)
|
|
81
|
+
- 依赖:`uf_rcrt_entry_manage` objId + SEARCH 菜单(候选词:`入职管理`)。
|
|
82
|
+
- **部分版本**:表单在(objId 可解析)但**无「入职管理」菜单**(「应聘管理」是应聘者管理、非入职)→ 判定**未启用**,拦截提示,不顶替。
|
|
83
|
+
- 办入职/取消入职虽走表单接口,但定位名单/入口依赖菜单 → 同样拦截。
|
|
84
|
+
- **取消/改期入职另依赖中间表 tag(`uf_rcrt_entry_cancel` / `uf_rcrt_entry_change`)**:**tag 解析不到(`data:[]`)= 该环境未启用取消/改期入职** → 阻断该动作并友好提示「当前环境未启用取消入职/改期入职功能」,不执行、不兜底、不臆造(用户决策:不清晰的动作,宁可不执行,也不能乱执行)。
|
|
85
|
+
|
|
86
|
+
### 4.5 Offer(发 Offer / 查询记录)
|
|
87
|
+
- 依赖:`uf_rcrt_offer` objId + SEARCH 菜单(候选词:`录用管理`——实名;`offer有效期设置`/`offer设置` 是配置页不算)。
|
|
88
|
+
- **部分版本**:表单在但无「录用管理」菜单(仅 offer设置 配置页)→ 判定**未启用**,拦截,不顶替。
|
|
89
|
+
|
|
90
|
+
### 4.6 招聘统计(nchart 看板)
|
|
91
|
+
- 依赖:`招聘数据看板`/`招聘工作统计` 等 **PAGE 型看板菜单**(allMenus pageType=PAGE 且菜单名含 统计/看板)。
|
|
92
|
+
- **部分版本**:无任何统计 PAGE 看板(仅 EDC REPORT 报表:面试出席/创建/沟通统计)→ 判定**未启用**,拦截(EDC 报表不在本技能范围)。
|
|
93
|
+
- 全功能版本:存在 `招聘数据看板` PAGE(pageId 经 allMenus 自动发现),nchart 可用。
|
|
94
|
+
|
|
95
|
+
### 4.7 简历解析(OCR)
|
|
96
|
+
- 依赖:`/api/recruit/ocr/checkRpaValid` 等接口路由(POST 空参返回业务响应即路由存在)。
|
|
97
|
+
- 路由不存在(404)→ 未部署拦截;存在 → 可用(仅解析不写库)。
|
|
98
|
+
|
|
99
|
+
## 5. 执行时容错(每步都要)
|
|
100
|
+
|
|
101
|
+
1. **接口调用前**:确认该功能在能力清单中「可用」,否则直接输出拦截提示,不发起调用。
|
|
102
|
+
2. **接口调用失败**(非 200 / 业务码失败):按文档错误码解释,如实提示,停止。
|
|
103
|
+
3. **解析不到**(字段 id / 枚举 / 动作流 id / 菜单):不臆造 → 反问用户或按 data-dictionary 回退。
|
|
104
|
+
4. **写操作**:先定位(locate-first)→ 消歧 → 确认摘要 → 用户确认才提交;失败如实上报部分失败。
|
|
105
|
+
5. **严禁猜测执行**:任何"可能是/大概是/应该可以"的路径,先停下来问用户,或按文档明确规则处理。
|
|
106
|
+
|
|
107
|
+
## 6. 基线判定(版本探测,)
|
|
108
|
+
|
|
109
|
+
**背景**:部分接口是最近基线新增、或不同基线出入参有破坏性改造,调用前需确认当前环境基线符合。能力特征探测(§2)已能判定"接口存在/功能启用",是基线符合性的兜底;平台版本接口可补充**显式版本号**,用于精确对照文档基线标注。
|
|
110
|
+
|
|
111
|
+
**版本获取**(可选增强,容错):
|
|
112
|
+
- 接口:`GET /api/security/license/getVersion`(平台通用,去域名路径;随机 key 参数如 `randomkey_probe=1`)
|
|
113
|
+
- 响应:`data` 为 JSON 字符串,含 `version`(如 `10.0.2605.01`)
|
|
114
|
+
- **容错**:部分环境有安全网关(如需完整会话 cookie)或权限限制,直接调用可能失败——**探测失败不阻塞初始化**,`version` 记为未知,基线判定回退 §2 能力特征探测。
|
|
115
|
+
- 初始化工具 `scripts/_init_env_cache.mjs`(随包 Node 版)已含此探测,版本号落环境缓存 `version` 字段(「刷新环境参数」后生效)。
|
|
116
|
+
|
|
117
|
+
**基线判定双通道**:
|
|
118
|
+
1. **版本号通道**:缓存 `version` 非空 → 对照接口文档「适用基线」标注(见 SKILL.md「接口基线标注」),低于基线 → 拦截提示,不调用;
|
|
119
|
+
2. **特征通道**(兜底,始终有效):版本取不到时,用 §2 能力特征(tag 可解析 / 菜单存在 / 按钮配置)判定接口可用性——特征缺失即按「未启用/未部署」拦截提示。
|
|
120
|
+
|
|
121
|
+
**基线标注不臆测**:接口文档中「适用基线」的具体版本号需以官方基线说明为准;无明确基线号时标注机制性描述("以环境版本接口返回为准 + 能力特征探测"),不得猜测版本值。
|
|
122
|
+
|
|
123
|
+
## 7. 与现有文档的关系
|
|
124
|
+
|
|
125
|
+
- 本文档是**第 0 步前置检查的扩展**(原只查安装闸门,现扩展为能力探测)。
|
|
126
|
+
- 菜单语义匹配细节见 `recruit-resolve-metadata.md` §3.1/§3.2(含多候选关键词、排除配置页、L1/L2/L3 降级)。
|
|
127
|
+
- 各功能接口文档(recruit-search-candidate.md / recruit-list-*.md / recruit-arrange-interview.md / recruit-entry-*.md / recruit-send-offer.md / recruit-stats.md)在「前置依赖」中引用本文档。
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recruit-check-install
|
|
3
|
+
description: 招聘服务安装检测闸门(第 0 步必做,取 appId)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 前置:招聘服务安装检测(Agent 辅助)
|
|
7
|
+
> 本文档中的 `${...}` 形参(表单 objId / 列表 listId / EB 页面 viewId·pageId / 应用 appId / 动作流 id)为**租户相关值**:表单 objId 经 `recruit-resolve-metadata.md` 的 tag 链运行时解析;其余由部署参数提供(**可经 `allMenus` 菜单树自动发现**,见 `recruit-resolve-metadata.md` §3.1);字段 ID(field_937…)依当前租户表单而定,详见 `data-dictionary.md`。
|
|
8
|
+
|
|
9
|
+
## 1. 基础信息
|
|
10
|
+
- 接口名称:按应用标签获取应用 id 列表 `getAppIds`(ebuilder-app 对外 REST)
|
|
11
|
+
- 请求方式:`GET`
|
|
12
|
+
- 去域名路径:`/api/bs/ebuilder/app/tags/getAppIds`
|
|
13
|
+
- 所属模块:低代码平台 e-Builder(ebuilder-app)
|
|
14
|
+
- 所属分组:前置 / Agent 辅助
|
|
15
|
+
|
|
16
|
+
## 2. 业务用途
|
|
17
|
+
**任何招聘操作前的第 0 步闸门**:用招聘应用固定标签 `weaver-recruit-service` 反查当前租户下是否已安装招聘服务。返回非空列表 = 已安装(且拿到 `appId`);返回空 = 未安装,应直接提示用户"您未安装招聘服务"并终止后续流程,不再调用任何招聘接口。
|
|
18
|
+
|
|
19
|
+
## 3. 前置条件
|
|
20
|
+
- 有效的认证(由 `weaver-work-cli auth` 托管的 E10 登录态提供)(租户上下文由会话决定,无需额外传 `tenantKey`)。
|
|
21
|
+
- 应在搜索 / 详情等所有招聘接口之前最先调用。
|
|
22
|
+
|
|
23
|
+
## 4. 请求参数
|
|
24
|
+
| 字段 | 位置 | 类型 | 必填 | 约束 | 业务说明 |
|
|
25
|
+
|---|---|---|---|---|---|
|
|
26
|
+
| `tag` | query | string | 是 | 固定值 `weaver-recruit-service` | 招聘应用的固定标签(由应用方打在 EB 应用上) |
|
|
27
|
+
|
|
28
|
+
## 5. 响应数据结构
|
|
29
|
+
| 字段 | 类型 | 说明 |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `code` | int | 200 表示成功 |
|
|
32
|
+
| `status` | boolean | `true` 表示正常返回 |
|
|
33
|
+
| `data` | array\<long\> | 该标签在当前租户下的应用 id 列表;**非空 = 已安装**,取 `data[0]` 为 `appId`;**空数组 = 未安装** |
|
|
34
|
+
|
|
35
|
+
## 6. 请求示例
|
|
36
|
+
```json
|
|
37
|
+
// GET /api/bs/ebuilder/app/tags/getAppIds?tag=weaver-recruit-service
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 7. 响应示例
|
|
41
|
+
```json
|
|
42
|
+
// 已安装
|
|
43
|
+
{ "code": 200, "msg": "接口返回成功", "status": true, "data": ["${RECRUIT_APP_ID}"], "fail": false }
|
|
44
|
+
// 未安装(标签无对应应用)
|
|
45
|
+
{ "code": 200, "msg": "接口返回成功", "status": true, "data": [], "fail": false }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 8. 错误码与失败形态(分情形处理,**不得把所有失败都当"未安装"**)
|
|
49
|
+
| 错误码 / 响应形态 | 含义 | AI 处理建议 |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| 200 + `status=true` + `data`=[] | 标签无对应应用(**未安装**) | 提示「您当前租户未安装招聘服务,请先安装后重试」,终止流程 |
|
|
52
|
+
| 200 + `status=false` + `msg` | 业务失败(常见:账号未授权该模块) | 按 `msg` 解释;`msg` 含「未授权/无权限」→ 提示「当前账号无招聘模块访问权限,请联系管理员开通」;其余按业务失败提示,**不得误报"未安装"** |
|
|
53
|
+
| HTTP 401 | 认证缺失或过期 | 提示重新登录(认证由 `weaver-work-cli auth` 托管)后重试 |
|
|
54
|
+
| HTTP 403 | 已认证但无模块访问权限(**模块未启用/未授权给本账号的典型形态**) | 提示「当前账号无招聘模块访问权限,请联系管理员开通或启用模块」 |
|
|
55
|
+
| HTTP 404 | 接口路由不存在(非 E10 环境 / 服务版本未部署该模块) | 提示「接口不存在:确认目标为 E10 环境且服务版本已部署该模块」,**不得误报"未安装"** |
|
|
56
|
+
| 网络异常 / 超时 | 连接失败 | 提示网络/连接异常,读取类可有限重试,仍失败再终止 |
|
|
57
|
+
|
|
58
|
+
## 9. 调用参考
|
|
59
|
+
- Agent 辅助:作为所有招聘能力的统一前置闸门。命中 `data` 非空后,方可继续搜索 / 详情流程;命中空则直接输出未安装提示并停止。
|
|
60
|
+
- `appId`(`data[0]`)可用于后续 EB 详情链接拼装,或作为其他需 appId 的接口入参。
|
|
61
|
+
|
|
62
|
+
## 10. 注意事项
|
|
63
|
+
- 同租户若多次导入同一标签应用,`data` 可能含多个 appId(tag 策略限制,无法自动去重)。取首个 `data[0]` 作为主 appId;必要时向用户说明"检测到多个安装实例"。
|
|
64
|
+
- 仅用 `tag` 入参,租户隔离由服务端会话保证,切勿在请求里臆测 `tenantKey`。
|
|
65
|
+
- 本接口为只读查询,不触发任何写操作。
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: recruit-detail-process
|
|
3
|
+
description: 应聘过程卡片(Agent 辅助,默认不展示)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 详情卡片:应聘过程(Agent 辅助,默认不展示)
|
|
7
|
+
|
|
8
|
+
## 1. 基础信息
|
|
9
|
+
- 接口名称:人才应聘过程日志 `getCandidateCardProcess`
|
|
10
|
+
- 请求方式:`POST`
|
|
11
|
+
- 去域名路径:`/api/recruit/processLog/getCandidateCardProcess`
|
|
12
|
+
- 所属模块:招聘管理(recruit)
|
|
13
|
+
- 所属分组:详情 / Agent 辅助
|
|
14
|
+
|
|
15
|
+
## 2. 业务用途
|
|
16
|
+
获取该人才在招聘流程中的操作过程日志:操作描述、操作人、业务类型、时间。默认详情流程**不展示**;仅当用户明确要求"应聘过程"时才调用。
|
|
17
|
+
|
|
18
|
+
## 3. 前置条件
|
|
19
|
+
- `talentId`、`batchId`(来自 prepareQuery)。
|
|
20
|
+
|
|
21
|
+
## 4. 请求参数
|
|
22
|
+
| 字段 | 位置 | 类型 | 必填 | 约束 | 业务说明 |
|
|
23
|
+
|---|---|---|---|---|---|
|
|
24
|
+
| `talentId` | body | string | 是 | 人才 id | |
|
|
25
|
+
| `batchId` | body | string | 否 | 批次 id | 部分部署需要 |
|
|
26
|
+
| `current` | body | int | 否 | 默认 1 | 页码 |
|
|
27
|
+
| `pageSize` | body | int | 否 | 默认 10 | 每页条数 |
|
|
28
|
+
|
|
29
|
+
## 5. 响应数据结构
|
|
30
|
+
| 字段 | 类型 | 说明 |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `data.list[].optContext` | string | 操作描述 |
|
|
33
|
+
| `data.list[].operatorId` | object | 操作人 `{name}` |
|
|
34
|
+
| `data.list[].optBusiness` | string | 业务类型 |
|
|
35
|
+
| `data.list[].createTime` | string | 操作时间 |
|
|
36
|
+
|
|
37
|
+
## 6. 请求示例
|
|
38
|
+
```json
|
|
39
|
+
{ "talentId": "1276382457065553922", "batchId": "937153853968540001", "current": 1, "pageSize": 10 }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 7. 响应示例
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"code": 200, "status": true,
|
|
46
|
+
"data": { "list": [
|
|
47
|
+
{ "optContext": "进入面试环节", "operatorId": { "name": "钱七" },
|
|
48
|
+
"optBusiness": "stage_change", "createTime": "2026-08-03 09:00" }
|
|
49
|
+
] }
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 8. 错误码
|
|
54
|
+
| 错误码 | 含义 | AI 处理建议 |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| 来源文档未提供接口特有错误码 | — | 非 200 / 重定向 → 提示 认证可能过期(`weaver-work-cli auth status`) |
|
|
57
|
+
|
|
58
|
+
## 9. 调用参考
|
|
59
|
+
- Agent 辅助:默认不调用;用户明确要求"应聘过程/流转记录"时才调用并加 `## 应聘过程(N)` 段。
|
|
60
|
+
|
|
61
|
+
## 10. 注意事项
|
|
62
|
+
- 默认详情流程不展示本卡片,避免信息过载。
|
|
63
|
+
- `operatorId` 取 `name` 回填。
|