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
|
@@ -1,17 +1,54 @@
|
|
|
1
1
|
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
2
|
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
EHR_PAGES,
|
|
5
|
+
EhrCliError,
|
|
6
|
+
READ,
|
|
7
|
+
SCHEMA_DATE,
|
|
8
|
+
SCHEMA_ID,
|
|
9
|
+
SCHEMA_ID_LIST,
|
|
10
|
+
SCHEMA_MONTH,
|
|
11
|
+
SCHEMA_STRING_LIST,
|
|
12
|
+
WRITE,
|
|
13
|
+
addDays,
|
|
14
|
+
asObject,
|
|
15
|
+
assertDateRange,
|
|
16
|
+
assertEnum,
|
|
17
|
+
assertMonth,
|
|
18
|
+
assertNoForbiddenKeys,
|
|
19
|
+
buildListBody,
|
|
20
|
+
compact,
|
|
21
|
+
createRecruitContextLoader,
|
|
22
|
+
ehrAuthError,
|
|
23
|
+
ehrConfirmationError,
|
|
24
|
+
ehrNetworkError,
|
|
25
|
+
ehrPageUrl,
|
|
26
|
+
ehrPartialError,
|
|
27
|
+
ehrSuccess,
|
|
28
|
+
ehrValidationError,
|
|
29
|
+
fetchListRows,
|
|
30
|
+
normalizePaged,
|
|
31
|
+
pickDefined,
|
|
32
|
+
recruitOperations,
|
|
33
|
+
requireDateRange,
|
|
34
|
+
resolveSecondAuthToken,
|
|
35
|
+
schemaOf,
|
|
36
|
+
toIdList,
|
|
37
|
+
toNumber,
|
|
38
|
+
toPageQuery,
|
|
39
|
+
toPositiveInt
|
|
40
|
+
} from "./chunk-LDZQPUIA.js";
|
|
3
41
|
import {
|
|
4
42
|
E10ApiError,
|
|
5
43
|
createE10RequestRuntime,
|
|
6
44
|
isE10SessionExpiredResponse,
|
|
7
45
|
requireE10Session
|
|
8
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-SA6VBIHY.js";
|
|
9
47
|
import {
|
|
10
48
|
E10_SESSION_EXPIRED_MESSAGE,
|
|
11
49
|
getActiveProfile
|
|
12
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-FOAA27U5.js";
|
|
13
51
|
import {
|
|
14
|
-
CliError,
|
|
15
52
|
isCliError,
|
|
16
53
|
toErrorEnvelope
|
|
17
54
|
} from "./chunk-LUSPKZKY.js";
|
|
@@ -26,62 +63,6 @@ import { existsSync } from "node:fs";
|
|
|
26
63
|
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
27
64
|
import { homedir } from "node:os";
|
|
28
65
|
import { resolve } from "node:path";
|
|
29
|
-
|
|
30
|
-
// src/shortcuts/ehr/errors.ts
|
|
31
|
-
var EhrCliError = class extends CliError {
|
|
32
|
-
type;
|
|
33
|
-
subtype;
|
|
34
|
-
code;
|
|
35
|
-
retryable;
|
|
36
|
-
stage;
|
|
37
|
-
details;
|
|
38
|
-
partialData;
|
|
39
|
-
constructor(type, subtype, message, options = {}) {
|
|
40
|
-
super(message, options.exitCode ?? 5 /* InternalError */);
|
|
41
|
-
this.name = "EhrCliError";
|
|
42
|
-
this.type = type;
|
|
43
|
-
this.subtype = subtype;
|
|
44
|
-
this.code = options.code;
|
|
45
|
-
this.retryable = options.retryable ?? false;
|
|
46
|
-
this.stage = options.stage;
|
|
47
|
-
this.details = options.details;
|
|
48
|
-
this.partialData = options.partialData;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
function ehrValidationError(subtype, message, details) {
|
|
52
|
-
return new EhrCliError("validation", subtype, message, {
|
|
53
|
-
details,
|
|
54
|
-
exitCode: 2 /* UsageError */
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function ehrAuthError(subtype, message, details) {
|
|
58
|
-
return new EhrCliError("authentication", subtype, message, {
|
|
59
|
-
details,
|
|
60
|
-
exitCode: 3 /* AuthError */
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
function ehrNetworkError(subtype, message, options = {}) {
|
|
64
|
-
return new EhrCliError("network", subtype, message, {
|
|
65
|
-
...options,
|
|
66
|
-
retryable: options.retryable ?? true,
|
|
67
|
-
exitCode: 4 /* NetworkError */
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
function ehrConfirmationError(action, details) {
|
|
71
|
-
return new EhrCliError("confirmation", "required", "\u8BE5\u64CD\u4F5C\u9700\u8981\u660E\u786E\u786E\u8BA4", {
|
|
72
|
-
details: { action, ...details },
|
|
73
|
-
exitCode: 10 /* ConfirmationRequired */
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
function ehrPartialError(message, partialData, details) {
|
|
77
|
-
return new EhrCliError("partial", "write_uncertain", message, {
|
|
78
|
-
details,
|
|
79
|
-
partialData,
|
|
80
|
-
exitCode: 11 /* Partial */
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// src/shortcuts/ehr/continuation.ts
|
|
85
66
|
function stateRoot(ctx) {
|
|
86
67
|
const configured = ctx?.config?.path();
|
|
87
68
|
if (configured) return resolve(configured, "..");
|
|
@@ -325,184 +306,6 @@ function createEhrHost(ctx, dependencies = {}) {
|
|
|
325
306
|
return { request, getSession, buildCardSign };
|
|
326
307
|
}
|
|
327
308
|
|
|
328
|
-
// src/shortcuts/ehr/operations/types.ts
|
|
329
|
-
var READ = "read";
|
|
330
|
-
var WRITE = "write";
|
|
331
|
-
function ehrSuccess(action, data, meta) {
|
|
332
|
-
const payload = { ok: true, action, data };
|
|
333
|
-
if (meta && Object.keys(meta).length > 0) payload.meta = meta;
|
|
334
|
-
return payload;
|
|
335
|
-
}
|
|
336
|
-
function schemaOf(properties, options = {}) {
|
|
337
|
-
return {
|
|
338
|
-
type: "object",
|
|
339
|
-
additionalProperties: false,
|
|
340
|
-
properties,
|
|
341
|
-
...options.required?.length ? { required: options.required } : {},
|
|
342
|
-
...options.description ? { description: options.description } : {}
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
var SCHEMA_DATE = { type: "string", pattern: "^\\d{4}-\\d{2}-\\d{2}$" };
|
|
346
|
-
var SCHEMA_MONTH = { type: "string", pattern: "^\\d{4}-\\d{2}$" };
|
|
347
|
-
var SCHEMA_ID = { oneOf: [{ type: "integer" }, { type: "string", pattern: "^\\d+$" }] };
|
|
348
|
-
var SCHEMA_ID_LIST = { type: "array", items: SCHEMA_ID };
|
|
349
|
-
var SCHEMA_STRING_LIST = { type: "array", items: { type: "string" } };
|
|
350
|
-
|
|
351
|
-
// src/shortcuts/ehr/operations/shared.ts
|
|
352
|
-
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
353
|
-
function asObject(value) {
|
|
354
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
355
|
-
throw ehrValidationError("input_not_object", "\u8F93\u5165\u5FC5\u987B\u662F JSON \u5BF9\u8C61");
|
|
356
|
-
}
|
|
357
|
-
return value;
|
|
358
|
-
}
|
|
359
|
-
function assertNoForbiddenKeys(input) {
|
|
360
|
-
for (const key of Object.keys(input)) {
|
|
361
|
-
if (FORBIDDEN_KEYS.has(key)) {
|
|
362
|
-
throw ehrValidationError("forbidden_key", `\u8F93\u5165\u5305\u542B\u975E\u6CD5\u5B57\u6BB5\uFF1A${key}`);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
var DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
367
|
-
var MONTH_PATTERN = /^\d{4}-\d{2}$/;
|
|
368
|
-
function isDate(value) {
|
|
369
|
-
return typeof value === "string" && DATE_PATTERN.test(value);
|
|
370
|
-
}
|
|
371
|
-
function isMonth(value) {
|
|
372
|
-
return typeof value === "string" && MONTH_PATTERN.test(value);
|
|
373
|
-
}
|
|
374
|
-
function isRealDate(value) {
|
|
375
|
-
const [year, month, day] = value.split("-").map(Number);
|
|
376
|
-
if (month < 1 || month > 12) return false;
|
|
377
|
-
const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate();
|
|
378
|
-
return day >= 1 && day <= daysInMonth;
|
|
379
|
-
}
|
|
380
|
-
function assertDate(value, field) {
|
|
381
|
-
if (!isDate(value)) throw ehrValidationError("date_invalid", `${field} \u5FC5\u987B\u662F YYYY-MM-DD \u683C\u5F0F`);
|
|
382
|
-
const text = value;
|
|
383
|
-
if (!isRealDate(text)) {
|
|
384
|
-
throw ehrValidationError("date_invalid", `${field} \u4E0D\u662F\u5408\u6CD5\u65E5\u671F\uFF08\u6708\u4EFD\u9700 01-12\uFF0C\u65E5\u671F\u9700\u5728\u8BE5\u6708\u6709\u6548\u8303\u56F4\u5185\uFF09\uFF1A${text}`);
|
|
385
|
-
}
|
|
386
|
-
return text;
|
|
387
|
-
}
|
|
388
|
-
function assertMonth(value, field) {
|
|
389
|
-
if (!isMonth(value)) throw ehrValidationError("month_invalid", `${field} \u5FC5\u987B\u662F YYYY-MM \u683C\u5F0F`);
|
|
390
|
-
const text = value;
|
|
391
|
-
const month = Number(text.slice(5));
|
|
392
|
-
if (month < 1 || month > 12) {
|
|
393
|
-
throw ehrValidationError("month_invalid", `${field} \u7684\u6708\u4EFD\u5FC5\u987B\u5728 01-12\uFF1A${text}`);
|
|
394
|
-
}
|
|
395
|
-
return text;
|
|
396
|
-
}
|
|
397
|
-
function toNumber(value, field) {
|
|
398
|
-
if (value === void 0 || value === null || value === "") return void 0;
|
|
399
|
-
const numeric = Number(value);
|
|
400
|
-
if (!Number.isFinite(numeric)) {
|
|
401
|
-
throw ehrValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57`);
|
|
402
|
-
}
|
|
403
|
-
return numeric;
|
|
404
|
-
}
|
|
405
|
-
function toPositiveInt(value, field) {
|
|
406
|
-
if (value === void 0 || value === null || value === "") return void 0;
|
|
407
|
-
const numeric = Number(value);
|
|
408
|
-
if (!Number.isFinite(numeric)) {
|
|
409
|
-
throw ehrValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57`);
|
|
410
|
-
}
|
|
411
|
-
const truncated = Math.trunc(numeric);
|
|
412
|
-
if (truncated !== numeric || truncated <= 0) {
|
|
413
|
-
throw ehrValidationError("number_invalid", `${field} \u5FC5\u987B\u662F\u6B63\u6574\u6570`);
|
|
414
|
-
}
|
|
415
|
-
return truncated;
|
|
416
|
-
}
|
|
417
|
-
function toIdList(value, field) {
|
|
418
|
-
if (value === void 0 || value === null) return void 0;
|
|
419
|
-
if (!Array.isArray(value)) throw ehrValidationError("id_list_invalid", `${field} \u5FC5\u987B\u662F ID \u6570\u7EC4`);
|
|
420
|
-
return value.map((item, index) => {
|
|
421
|
-
if (item === void 0 || item === null || item === "") {
|
|
422
|
-
throw ehrValidationError("id_list_invalid", `${field}[${index}] \u4E0D\u80FD\u4E3A\u7A7A`);
|
|
423
|
-
}
|
|
424
|
-
const numeric = Number(item);
|
|
425
|
-
if (!Number.isFinite(numeric)) {
|
|
426
|
-
throw ehrValidationError("id_list_invalid", `${field}[${index}] \u5FC5\u987B\u662F\u6570\u5B57 ID`);
|
|
427
|
-
}
|
|
428
|
-
return numeric;
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
function pickDefined(value, keys) {
|
|
432
|
-
const result = {};
|
|
433
|
-
for (const key of keys) {
|
|
434
|
-
if (value[key] !== void 0) result[key] = value[key];
|
|
435
|
-
}
|
|
436
|
-
return result;
|
|
437
|
-
}
|
|
438
|
-
function compact(body) {
|
|
439
|
-
for (const key of Object.keys(body)) {
|
|
440
|
-
if (body[key] === void 0) delete body[key];
|
|
441
|
-
}
|
|
442
|
-
return body;
|
|
443
|
-
}
|
|
444
|
-
function assertDateRange(args, startField, endField) {
|
|
445
|
-
const start = args[startField];
|
|
446
|
-
const end = args[endField];
|
|
447
|
-
if ((start === void 0 || start === null) !== (end === void 0 || end === null)) {
|
|
448
|
-
throw ehrValidationError("date_range_incomplete", `${startField} \u4E0E ${endField} \u5FC5\u987B\u6210\u5BF9\u63D0\u4F9B`);
|
|
449
|
-
}
|
|
450
|
-
if (start === void 0 || start === null) return {};
|
|
451
|
-
const startDate = assertDate(start, startField);
|
|
452
|
-
const endDate = assertDate(end, endField);
|
|
453
|
-
if (startDate > endDate) {
|
|
454
|
-
throw ehrValidationError("date_range_invalid", `${startField} \u4E0D\u5F97\u665A\u4E8E ${endField}`);
|
|
455
|
-
}
|
|
456
|
-
return { start: startDate, end: endDate };
|
|
457
|
-
}
|
|
458
|
-
function requireDateRange(args, startField = "beginDate", endField = "endDate") {
|
|
459
|
-
const start = args[startField];
|
|
460
|
-
const end = args[endField];
|
|
461
|
-
if (start === void 0 || start === null || start === "" || end === void 0 || end === null || end === "") {
|
|
462
|
-
throw ehrValidationError("date_range_required", `${startField} \u4E0E ${endField} \u5FC5\u586B\uFF0C\u683C\u5F0F YYYY-MM-DD`);
|
|
463
|
-
}
|
|
464
|
-
const range = assertDateRange(args, startField, endField);
|
|
465
|
-
return { beginDate: range.start, endDate: range.end };
|
|
466
|
-
}
|
|
467
|
-
function unwrapData(response) {
|
|
468
|
-
if (!response || typeof response !== "object") return response;
|
|
469
|
-
return response.data;
|
|
470
|
-
}
|
|
471
|
-
function normalizePaged(response) {
|
|
472
|
-
const data = unwrapData(response);
|
|
473
|
-
const page = {};
|
|
474
|
-
const candidates = [data?.page, response?.page, data, response];
|
|
475
|
-
for (const source of candidates) {
|
|
476
|
-
if (!source || typeof source !== "object") continue;
|
|
477
|
-
for (const key of ["pageNo", "current", "pageSize", "total", "totalCount", "totalPage", "tableId"]) {
|
|
478
|
-
if (source[key] !== void 0 && page[key] === void 0) page[key] = source[key];
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return { data, page };
|
|
482
|
-
}
|
|
483
|
-
function toPageQuery(args) {
|
|
484
|
-
const page = {};
|
|
485
|
-
const current = toPositiveInt(args?.current, "current");
|
|
486
|
-
const pageSize = toNumber(args?.pageSize, "pageSize");
|
|
487
|
-
const pageNo = toNumber(args?.pageNo, "pageNo");
|
|
488
|
-
if (current !== void 0) page.current = current;
|
|
489
|
-
if (pageSize !== void 0) page.pageSize = pageSize;
|
|
490
|
-
if (pageNo !== void 0) page.pageNo = pageNo;
|
|
491
|
-
return page;
|
|
492
|
-
}
|
|
493
|
-
var SECOND_AUTH_TOKEN_DEFAULT = "DONT_NEED";
|
|
494
|
-
function resolveSecondAuthToken(value) {
|
|
495
|
-
if (typeof value === "string" && value.trim()) return value.trim();
|
|
496
|
-
return SECOND_AUTH_TOKEN_DEFAULT;
|
|
497
|
-
}
|
|
498
|
-
function assertEnum(value, allowed, field) {
|
|
499
|
-
const text = typeof value === "string" ? value : String(value);
|
|
500
|
-
if (!allowed.includes(text)) {
|
|
501
|
-
throw ehrValidationError("enum_invalid", `${field} \u53D6\u503C\u5FC5\u987B\u662F ${allowed.join(" / ")} \u4E4B\u4E00`);
|
|
502
|
-
}
|
|
503
|
-
return text;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
309
|
// src/shortcuts/ehr/operations/attend-read.ts
|
|
507
310
|
var ATTEND_STATUS = [
|
|
508
311
|
"SIGN_IN_LATE",
|
|
@@ -1229,9 +1032,39 @@ var ehrAttendAppealSaveApply = {
|
|
|
1229
1032
|
}
|
|
1230
1033
|
throw error;
|
|
1231
1034
|
}
|
|
1035
|
+
const session = await env.host.getSession();
|
|
1036
|
+
const appealListUrl = ehrPageUrl(session.baseUrl, EHR_PAGES.attendAbnormal);
|
|
1037
|
+
let appeal = null;
|
|
1038
|
+
let locateWarning;
|
|
1039
|
+
try {
|
|
1040
|
+
const listResp = await env.host.request({
|
|
1041
|
+
method: "POST",
|
|
1042
|
+
path: "/api/attend/web/appeal/getAppealList",
|
|
1043
|
+
body: {
|
|
1044
|
+
beginDate: addDays(String(args.attendDay), -1),
|
|
1045
|
+
endDate: addDays(String(args.attendDay), 1),
|
|
1046
|
+
current: 1,
|
|
1047
|
+
pageSize: 50
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
const payload2 = listResp?.data;
|
|
1051
|
+
const rows = Array.isArray(payload2?.data) ? payload2.data : Array.isArray(payload2?.rows) ? payload2.rows : Array.isArray(payload2) ? payload2 : [];
|
|
1052
|
+
const day = String(args.attendDay);
|
|
1053
|
+
const desc = String(args.appealDesc ?? "");
|
|
1054
|
+
const pick = rows.find((r) => String(r?.attendDay ?? r?.attend_date ?? r?.attendDate ?? "").startsWith(day)) || (desc ? rows.find((r) => String(r?.appealDesc ?? r?.appeal_desc ?? "").includes(desc)) : null) || null;
|
|
1055
|
+
if (pick) appeal = pick;
|
|
1056
|
+
else locateWarning = "\u672A\u5728\u7533\u8BC9\u5217\u8868\u4E2D\u5B9A\u4F4D\u5230\u672C\u6B21\u8BB0\u5F55\uFF08\u53EF\u80FD\u521A\u63D0\u4EA4\u5C1A\u5728\u540C\u6B65\uFF09\uFF0C\u8BF7\u7A0D\u540E\u7528 ehr.attend.appeal.list \u590D\u6838";
|
|
1057
|
+
} catch (e) {
|
|
1058
|
+
locateWarning = "\u7533\u8BC9\u5217\u8868\u56DE\u67E5\u5931\u8D25\uFF1A" + (e?.message || "\u672A\u77E5\u539F\u56E0") + "\uFF1B\u8BF7\u7A0D\u540E\u7528 ehr.attend.appeal.list \u590D\u6838";
|
|
1059
|
+
}
|
|
1232
1060
|
return ehrSuccess("ehr.attend.appeal.save.apply", {
|
|
1233
1061
|
status: "COMPLETE",
|
|
1234
1062
|
result: response?.data,
|
|
1063
|
+
/** 定位到的新建申诉记录(含申诉 ID 等,处理申诉时用其 id) */
|
|
1064
|
+
appeal,
|
|
1065
|
+
/** 考勤异常/申诉页面地址(已取证路由,禁止改拼) */
|
|
1066
|
+
appealListUrl,
|
|
1067
|
+
...locateWarning ? { locateWarning } : {},
|
|
1235
1068
|
verifyHint: "\u53EF\u901A\u8FC7 ehr.attend.appeal.list \u56DE\u67E5\u7533\u8BC9\u662F\u5426\u5DF2\u751F\u6210"
|
|
1236
1069
|
});
|
|
1237
1070
|
}
|
|
@@ -1560,7 +1393,8 @@ var contactSearch = {
|
|
|
1560
1393
|
body: compact(body)
|
|
1561
1394
|
});
|
|
1562
1395
|
const { data, page } = normalizePaged(response);
|
|
1563
|
-
|
|
1396
|
+
const hrSession = await host.getSession();
|
|
1397
|
+
return ehrSuccess("ehr.hr.contact.search", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrEmployeeManager), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
1564
1398
|
}
|
|
1565
1399
|
};
|
|
1566
1400
|
var contactCount = {
|
|
@@ -1684,7 +1518,8 @@ var birthdayList = {
|
|
|
1684
1518
|
body
|
|
1685
1519
|
});
|
|
1686
1520
|
const { data, page } = normalizePaged(response);
|
|
1687
|
-
|
|
1521
|
+
const hrSession = await host.getSession();
|
|
1522
|
+
return ehrSuccess("ehr.hr.birthday.list", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrBirthdayList), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
1688
1523
|
}
|
|
1689
1524
|
};
|
|
1690
1525
|
var empchangeConditions = {
|
|
@@ -1758,7 +1593,8 @@ var empchangeList = {
|
|
|
1758
1593
|
body: compact(body)
|
|
1759
1594
|
});
|
|
1760
1595
|
const { data, page } = normalizePaged(response);
|
|
1761
|
-
|
|
1596
|
+
const hrSession = await host.getSession();
|
|
1597
|
+
return ehrSuccess("ehr.hr.empchange.list", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrPersonalStateChange), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
1762
1598
|
}
|
|
1763
1599
|
};
|
|
1764
1600
|
var hrContactOperations = [
|
|
@@ -2104,7 +1940,8 @@ var reportDeptTable = {
|
|
|
2104
1940
|
body: buildPersonReport(args, "departmentName")
|
|
2105
1941
|
});
|
|
2106
1942
|
const { data, page } = normalizePaged(response);
|
|
2107
|
-
|
|
1943
|
+
const hrSession = await host.getSession();
|
|
1944
|
+
return ehrSuccess("ehr.hr.report.dept.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrReportDeptPerson), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2108
1945
|
}
|
|
2109
1946
|
};
|
|
2110
1947
|
var reportPosiTable = {
|
|
@@ -2123,7 +1960,8 @@ var reportPosiTable = {
|
|
|
2123
1960
|
body: buildPersonReport(args, "positionName")
|
|
2124
1961
|
});
|
|
2125
1962
|
const { data, page } = normalizePaged(response);
|
|
2126
|
-
|
|
1963
|
+
const hrSession = await host.getSession();
|
|
1964
|
+
return ehrSuccess("ehr.hr.report.posi.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrReportPosiPerson), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2127
1965
|
}
|
|
2128
1966
|
};
|
|
2129
1967
|
var reportJobTable = {
|
|
@@ -2142,7 +1980,8 @@ var reportJobTable = {
|
|
|
2142
1980
|
body: buildPersonReport(args, "jobName")
|
|
2143
1981
|
});
|
|
2144
1982
|
const { data, page } = normalizePaged(response);
|
|
2145
|
-
|
|
1983
|
+
const hrSession = await host.getSession();
|
|
1984
|
+
return ehrSuccess("ehr.hr.report.job.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrReportJobPerson), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2146
1985
|
}
|
|
2147
1986
|
};
|
|
2148
1987
|
var reportJobTypeTable = {
|
|
@@ -2249,7 +2088,8 @@ var estEmpTable = {
|
|
|
2249
2088
|
}
|
|
2250
2089
|
});
|
|
2251
2090
|
const { data, page } = normalizePaged(response);
|
|
2252
|
-
|
|
2091
|
+
const hrSession = await host.getSession();
|
|
2092
|
+
return ehrSuccess("ehr.hr.est.emp.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrTpReportTp), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2253
2093
|
}
|
|
2254
2094
|
};
|
|
2255
2095
|
var estDcEmpTable = {
|
|
@@ -2295,7 +2135,8 @@ var estDcEmpTable = {
|
|
|
2295
2135
|
}
|
|
2296
2136
|
});
|
|
2297
2137
|
const { data, page } = normalizePaged(response);
|
|
2298
|
-
|
|
2138
|
+
const hrSession = await host.getSession();
|
|
2139
|
+
return ehrSuccess("ehr.hr.est.dc.emp.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrTpReportHw), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2299
2140
|
}
|
|
2300
2141
|
};
|
|
2301
2142
|
var turnEmpTable = {
|
|
@@ -2342,7 +2183,8 @@ var turnEmpTable = {
|
|
|
2342
2183
|
body
|
|
2343
2184
|
});
|
|
2344
2185
|
const { data, page } = normalizePaged(response);
|
|
2345
|
-
|
|
2186
|
+
const hrSession = await host.getSession();
|
|
2187
|
+
return ehrSuccess("ehr.hr.turn.emp.table", data, { page, viewUrl: ehrPageUrl(hrSession.baseUrl, EHR_PAGES.hrTpReportTurn), profileUrlTemplate: ehrPageUrl(hrSession.baseUrl, "/sp/hrm/profileInfo/{\u4EBA\u5458id}") });
|
|
2346
2188
|
}
|
|
2347
2189
|
};
|
|
2348
2190
|
var propsSa = {
|
|
@@ -2419,925 +2261,6 @@ var hrReportOperations = [
|
|
|
2419
2261
|
propsTable
|
|
2420
2262
|
];
|
|
2421
2263
|
|
|
2422
|
-
// src/shortcuts/ehr/operations/recruit.ts
|
|
2423
|
-
import { randomBytes as randomBytes2, randomUUID } from "node:crypto";
|
|
2424
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2425
|
-
import { homedir as homedir2 } from "node:os";
|
|
2426
|
-
import { join, resolve as resolve2 } from "node:path";
|
|
2427
|
-
var RECRUIT_APP_TAG = "weaver-recruit-service";
|
|
2428
|
-
var RECRUIT_TAGS = {
|
|
2429
|
-
talent_pool: "uf_rcrt_talent_pool",
|
|
2430
|
-
interview_plan: "uf_rcrt_interview_plan",
|
|
2431
|
-
interview_detail: "uf_rcrt_interview_detail",
|
|
2432
|
-
demand_manage: "uf_rcrt_demand_manage",
|
|
2433
|
-
position_manage: "uf_rcrt_position_manage",
|
|
2434
|
-
entry_manage: "uf_rcrt_entry_manage",
|
|
2435
|
-
offer: "uf_rcrt_offer",
|
|
2436
|
-
offer_sending: "uf_rcrt_offer_sending",
|
|
2437
|
-
candidate_manage: "uf_rcrt_candidate_manage",
|
|
2438
|
-
entry_transact: "uf_rcrt_entry_transact",
|
|
2439
|
-
entry_cancel: "uf_rcrt_entry_cancel",
|
|
2440
|
-
entry_change: "uf_rcrt_entry_change",
|
|
2441
|
-
dictionary: "uf_rcrt_dictionary",
|
|
2442
|
-
biz_config: "uf_rcrt_biz_config_mapper"
|
|
2443
|
-
};
|
|
2444
|
-
var LIST_KEYWORDS = {
|
|
2445
|
-
talent: ["\u4EBA\u624D\u5E93", "\u4EBA\u624D\u7BA1\u7406"],
|
|
2446
|
-
demand: ["\u62DB\u8058\u9700\u6C42", "\u9700\u6C42"],
|
|
2447
|
-
position: ["\u62DB\u8058\u804C\u4F4D", "\u804C\u4F4D\u5217\u8868", "\u804C\u4F4D\u7BA1\u7406"],
|
|
2448
|
-
entry: ["\u5165\u804C\u7BA1\u7406"],
|
|
2449
|
-
offer: ["\u5F55\u7528\u7BA1\u7406", "offer\u7BA1\u7406", "offer"],
|
|
2450
|
-
interview: ["\u9762\u8BD5\u7BA1\u7406"],
|
|
2451
|
-
biz_config: ["\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868"]
|
|
2452
|
-
};
|
|
2453
|
-
var LIST_TYPES = {
|
|
2454
|
-
demand: { listKey: "demand", formType: "demand_manage", title: "\u62DB\u8058\u9700\u6C42" },
|
|
2455
|
-
position: { listKey: "position", formType: "position_manage", title: "\u62DB\u8058\u804C\u4F4D" },
|
|
2456
|
-
entry: { listKey: "entry", formType: "entry_manage", title: "\u5165\u804C\u7BA1\u7406" },
|
|
2457
|
-
offer: { listKey: "offer", formType: "offer", title: "\u5F55\u7528\u7BA1\u7406" }
|
|
2458
|
-
};
|
|
2459
|
-
var INTERNAL_KEYS = /* @__PURE__ */ new Set([
|
|
2460
|
-
"id",
|
|
2461
|
-
"form_data_id",
|
|
2462
|
-
"form_table_id",
|
|
2463
|
-
"rowKey",
|
|
2464
|
-
"ebrecord_rowkey",
|
|
2465
|
-
"isFollow",
|
|
2466
|
-
"is_flow",
|
|
2467
|
-
"data_status",
|
|
2468
|
-
"data_status_value",
|
|
2469
|
-
"update_time",
|
|
2470
|
-
"formDataId",
|
|
2471
|
-
"isFollowSearch",
|
|
2472
|
-
"isShareToMe"
|
|
2473
|
-
]);
|
|
2474
|
-
var DISPLAY_UI_KEYS = /* @__PURE__ */ new Set([
|
|
2475
|
-
...INTERNAL_KEYS,
|
|
2476
|
-
"operate",
|
|
2477
|
-
"isToDo",
|
|
2478
|
-
"todoPropSpan",
|
|
2479
|
-
"flow_status"
|
|
2480
|
-
]);
|
|
2481
|
-
function randHex32() {
|
|
2482
|
-
return randomUUID().replace(/-/g, "");
|
|
2483
|
-
}
|
|
2484
|
-
function randHex6() {
|
|
2485
|
-
return randomBytes2(3).toString("hex");
|
|
2486
|
-
}
|
|
2487
|
-
function cacheDirFor(baseUrl) {
|
|
2488
|
-
const url = new URL(baseUrl);
|
|
2489
|
-
const host = url.hostname + (url.port ? `_${url.port}` : "");
|
|
2490
|
-
const envRoot = process.env.E10_SKILL_CACHE_DIR;
|
|
2491
|
-
if (envRoot) return join(envRoot, host);
|
|
2492
|
-
const home = process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve2(homedir2(), ".weaver-work-cli");
|
|
2493
|
-
return join(home, "env-cache", "recruit-ops", host);
|
|
2494
|
-
}
|
|
2495
|
-
function namesOf(field) {
|
|
2496
|
-
if (!field) return null;
|
|
2497
|
-
let arr;
|
|
2498
|
-
if (Array.isArray(field)) arr = field;
|
|
2499
|
-
else if (typeof field === "object") arr = [field];
|
|
2500
|
-
else if (typeof field === "string") {
|
|
2501
|
-
const text = field.trim();
|
|
2502
|
-
if (!text.startsWith("[") && !text.startsWith("{")) return text || null;
|
|
2503
|
-
try {
|
|
2504
|
-
arr = JSON.parse(text);
|
|
2505
|
-
} catch {
|
|
2506
|
-
return text || null;
|
|
2507
|
-
}
|
|
2508
|
-
if (!Array.isArray(arr)) arr = [arr];
|
|
2509
|
-
} else return null;
|
|
2510
|
-
const names = arr.map((item) => item && typeof item === "object" ? item.name || item.username || item.text || item.title : null).filter(Boolean);
|
|
2511
|
-
return names.length ? names.join("\u3001") : null;
|
|
2512
|
-
}
|
|
2513
|
-
function isPlainId(value) {
|
|
2514
|
-
return value != null && /^\d+$/.test(String(value).trim());
|
|
2515
|
-
}
|
|
2516
|
-
var RecruitContextError = class extends Error {
|
|
2517
|
-
subtype;
|
|
2518
|
-
constructor(subtype, message) {
|
|
2519
|
-
super(message);
|
|
2520
|
-
this.subtype = subtype;
|
|
2521
|
-
}
|
|
2522
|
-
};
|
|
2523
|
-
async function fetchFormFields(host, appId, objId) {
|
|
2524
|
-
const form = new FormData();
|
|
2525
|
-
form.set("groupId", appId);
|
|
2526
|
-
form.set("sourceId", objId);
|
|
2527
|
-
form.set("sourceType", "FORM");
|
|
2528
|
-
form.set("detailFieldsGroup", "true");
|
|
2529
|
-
form.set("enableMerge", "true");
|
|
2530
|
-
form.set("customParam", '{"terminal":""}');
|
|
2531
|
-
form.set("params", "[]");
|
|
2532
|
-
const response = await host.request({
|
|
2533
|
-
method: "POST",
|
|
2534
|
-
path: "/api/ebuilder/common/ds/fields",
|
|
2535
|
-
multipart: form
|
|
2536
|
-
});
|
|
2537
|
-
const fmap = {};
|
|
2538
|
-
const omap = {};
|
|
2539
|
-
for (const group of response?.data || []) {
|
|
2540
|
-
for (const field of group?.fields || []) {
|
|
2541
|
-
const config = field?.config || {};
|
|
2542
|
-
const dataKey = config.dataKey || "";
|
|
2543
|
-
const fieldId = String(field?.id || "");
|
|
2544
|
-
if (dataKey && fieldId) fmap[dataKey] = fieldId;
|
|
2545
|
-
if (fieldId && Array.isArray(config.options) && config.options.length) {
|
|
2546
|
-
const map = {};
|
|
2547
|
-
for (const option of config.options) {
|
|
2548
|
-
if (!option || typeof option !== "object") continue;
|
|
2549
|
-
const name = option.name;
|
|
2550
|
-
let selectionId = option.selectionId;
|
|
2551
|
-
if (!selectionId && typeof option.extra === "string") {
|
|
2552
|
-
try {
|
|
2553
|
-
const extra = JSON.parse(option.extra);
|
|
2554
|
-
selectionId = extra.selectionId || extra.id;
|
|
2555
|
-
} catch {
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
if (!selectionId) selectionId = option.value || option.valueKey || option.id;
|
|
2559
|
-
if (selectionId && name) map[String(selectionId)] = name;
|
|
2560
|
-
}
|
|
2561
|
-
if (Object.keys(map).length) omap[fieldId] = map;
|
|
2562
|
-
}
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
return { fmap, omap };
|
|
2566
|
-
}
|
|
2567
|
-
async function resolveRecruitEnv(host, appId) {
|
|
2568
|
-
const forms = {};
|
|
2569
|
-
let tenantKey = "";
|
|
2570
|
-
for (const [logic, tag] of Object.entries(RECRUIT_TAGS)) {
|
|
2571
|
-
const response = await host.request({
|
|
2572
|
-
path: "/api/ebuilder/form/obj/getObjsByTag",
|
|
2573
|
-
query: { appId, tag }
|
|
2574
|
-
});
|
|
2575
|
-
const entry = Array.isArray(response?.data) && response.data.length ? response.data[0] : null;
|
|
2576
|
-
forms[logic] = {
|
|
2577
|
-
objId: String(entry?.id || ""),
|
|
2578
|
-
formId: String(entry?.formId || ""),
|
|
2579
|
-
objName: entry?.objName || ""
|
|
2580
|
-
};
|
|
2581
|
-
if (!tenantKey && entry?.tenantKey) tenantKey = String(entry.tenantKey);
|
|
2582
|
-
}
|
|
2583
|
-
const menuResponse = await host.request({
|
|
2584
|
-
path: "/api/cusapp/app/allMenus",
|
|
2585
|
-
query: { isFront: 1, appId, terminalType: "PC" }
|
|
2586
|
-
});
|
|
2587
|
-
const flat = [];
|
|
2588
|
-
const walk = (nodes) => {
|
|
2589
|
-
for (const node of nodes || []) {
|
|
2590
|
-
if (node && typeof node === "object") {
|
|
2591
|
-
flat.push(node);
|
|
2592
|
-
walk(node.children || node.childs);
|
|
2593
|
-
}
|
|
2594
|
-
}
|
|
2595
|
-
};
|
|
2596
|
-
const menuData = menuResponse?.data;
|
|
2597
|
-
walk(typeof menuData === "object" && menuData ? menuData.cusAppMenus || menuData : menuData);
|
|
2598
|
-
const searchMenus = [];
|
|
2599
|
-
const pages = [];
|
|
2600
|
-
for (const node of flat) {
|
|
2601
|
-
if (node.pageType === "SEARCH") {
|
|
2602
|
-
searchMenus.push({ menuName: node.menuName, listId: String(node.pageId || ""), cusMenuId: String(node.id || "") });
|
|
2603
|
-
} else if (node.pageType === "PAGE") {
|
|
2604
|
-
pages.push({ menuName: node.menuName, pageId: String(node.pageId || "") });
|
|
2605
|
-
}
|
|
2606
|
-
}
|
|
2607
|
-
const fields = {};
|
|
2608
|
-
const fieldOptions = {};
|
|
2609
|
-
const resolvedForms = Object.entries(forms).filter(([, v]) => v.objId);
|
|
2610
|
-
await Promise.all(resolvedForms.map(async ([logic, entry]) => {
|
|
2611
|
-
const { fmap, omap } = await fetchFormFields(host, appId, entry.objId);
|
|
2612
|
-
if (Object.keys(fmap).length) fields[entry.objId] = fmap;
|
|
2613
|
-
if (Object.keys(omap).length) fieldOptions[entry.objId] = omap;
|
|
2614
|
-
void logic;
|
|
2615
|
-
}));
|
|
2616
|
-
const dictByName = {};
|
|
2617
|
-
const dictRaw = [];
|
|
2618
|
-
const dictMenu = searchMenus.find((m) => (m.menuName || "").trim() === "\u6570\u636E\u5B57\u5178") || null;
|
|
2619
|
-
const dictObjId = forms.dictionary?.objId || "";
|
|
2620
|
-
if (dictObjId && dictMenu) {
|
|
2621
|
-
const size = 500;
|
|
2622
|
-
let current = 1;
|
|
2623
|
-
for (; ; ) {
|
|
2624
|
-
const response = await host.request({
|
|
2625
|
-
path: `/api/ebuilder/form/list/getListDatas?passid=${dictObjId}&cid=${dictObjId}`,
|
|
2626
|
-
body: {
|
|
2627
|
-
current,
|
|
2628
|
-
pageSize: size,
|
|
2629
|
-
tableuid: randHex32(),
|
|
2630
|
-
listId: dictMenu.listId,
|
|
2631
|
-
searchParamData: { searchType: "3", type: "and" },
|
|
2632
|
-
terminal: "PC",
|
|
2633
|
-
browser: "Chrome",
|
|
2634
|
-
requiredMatch: 1,
|
|
2635
|
-
mapResult: 1,
|
|
2636
|
-
recheckQuery: 1,
|
|
2637
|
-
isFollow: 0,
|
|
2638
|
-
isShareToMe: 0,
|
|
2639
|
-
filterCondition: {},
|
|
2640
|
-
cusMenuId: dictMenu.cusMenuId,
|
|
2641
|
-
urlPageTitle: "\u6570\u636E\u5B57\u5178",
|
|
2642
|
-
menuName: "\u6570\u636E\u5B57\u5178"
|
|
2643
|
-
},
|
|
2644
|
-
headers: { ebBusinessId: dictMenu.listId }
|
|
2645
|
-
});
|
|
2646
|
-
const rows = response?.data?.data || [];
|
|
2647
|
-
for (const row of rows) {
|
|
2648
|
-
const name = row.selection_name;
|
|
2649
|
-
const optionId = row.form_data_id;
|
|
2650
|
-
if (name && optionId) {
|
|
2651
|
-
(dictByName[String(name)] ||= []).push(String(optionId));
|
|
2652
|
-
dictRaw.push({ selection_name: String(name), option_id: String(optionId), dict_type: row.dict_type, browser_key: row.browser_key });
|
|
2653
|
-
}
|
|
2654
|
-
}
|
|
2655
|
-
if (rows.length < size) break;
|
|
2656
|
-
current += 1;
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
let ebdDetailPageId = "";
|
|
2660
|
-
let selfUse = "0";
|
|
2661
|
-
const bizConfig = forms.biz_config || { objId: "", formId: "", objName: "" };
|
|
2662
|
-
const bizConfigMenu = searchMenus.find((m) => (m.menuName || "").trim() === "\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868") || null;
|
|
2663
|
-
if (bizConfig.objId && bizConfigMenu) {
|
|
2664
|
-
try {
|
|
2665
|
-
const { fmap } = await fetchFormFields(host, appId, bizConfig.objId);
|
|
2666
|
-
const keyField = fmap.config_key || "";
|
|
2667
|
-
const valueField = fmap.config || "";
|
|
2668
|
-
if (keyField && valueField) {
|
|
2669
|
-
let current = 1;
|
|
2670
|
-
for (; ; ) {
|
|
2671
|
-
const response = await host.request({
|
|
2672
|
-
path: `/api/ebuilder/form/list/getListDatas?passid=${bizConfig.objId}&cid=${bizConfig.objId}`,
|
|
2673
|
-
body: {
|
|
2674
|
-
current,
|
|
2675
|
-
pageSize: 100,
|
|
2676
|
-
tableuid: randHex32(),
|
|
2677
|
-
listId: bizConfigMenu.listId,
|
|
2678
|
-
searchParamData: { searchType: "3", type: "and" },
|
|
2679
|
-
terminal: "PC",
|
|
2680
|
-
browser: "Chrome",
|
|
2681
|
-
requiredMatch: 1,
|
|
2682
|
-
mapResult: 1,
|
|
2683
|
-
recheckQuery: 1,
|
|
2684
|
-
isFollow: 0,
|
|
2685
|
-
isShareToMe: 0,
|
|
2686
|
-
filterCondition: {},
|
|
2687
|
-
cusMenuId: bizConfigMenu.cusMenuId,
|
|
2688
|
-
urlPageTitle: "\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868",
|
|
2689
|
-
menuName: "\u4E1A\u52A1\u914D\u7F6E\u6620\u5C04\u8868"
|
|
2690
|
-
},
|
|
2691
|
-
headers: { ebBusinessId: bizConfigMenu.listId }
|
|
2692
|
-
});
|
|
2693
|
-
const rows = response?.data?.data || [];
|
|
2694
|
-
if (!rows.length) break;
|
|
2695
|
-
for (const row of rows) {
|
|
2696
|
-
if (String(row.config_key || "") === "28" && row.config) {
|
|
2697
|
-
const match = String(row.config).match(/\/sp\/ebdpage\/view\/(\d+)/);
|
|
2698
|
-
if (match) ebdDetailPageId = match[1];
|
|
2699
|
-
}
|
|
2700
|
-
if (String(row.config_key || "") === "-9999" && String(row.config) === "1") selfUse = "1";
|
|
2701
|
-
}
|
|
2702
|
-
if (rows.length < 100) break;
|
|
2703
|
-
current += 1;
|
|
2704
|
-
}
|
|
2705
|
-
}
|
|
2706
|
-
} catch {
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
if (!ebdDetailPageId) {
|
|
2710
|
-
try {
|
|
2711
|
-
const response = await host.request({
|
|
2712
|
-
path: "/api/bs/ebuilder/page/list",
|
|
2713
|
-
query: { appid: appId }
|
|
2714
|
-
});
|
|
2715
|
-
for (const page of Array.isArray(response?.data) ? response.data : []) {
|
|
2716
|
-
if ((page?.name || "") === "\u4EBA\u624D\u5361\u7247" && page?.type === "PAGE" && page?.id) {
|
|
2717
|
-
ebdDetailPageId = String(page.id);
|
|
2718
|
-
break;
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
} catch {
|
|
2722
|
-
}
|
|
2723
|
-
}
|
|
2724
|
-
const options = {};
|
|
2725
|
-
for (const [dataKey, logic] of [["recruit_status", "talent_pool"], ["channel", "talent_pool"]]) {
|
|
2726
|
-
const entry = forms[logic] || { objId: "", formId: "", objName: "" };
|
|
2727
|
-
const fieldId = (fields[entry.objId] || {})[dataKey] || "";
|
|
2728
|
-
if (fieldId && entry.objId) {
|
|
2729
|
-
const response = await host.request({
|
|
2730
|
-
path: "/api/ebuilder/common/ds/options",
|
|
2731
|
-
query: { fieldName: fieldId, objId: entry.objId, sourceType: "FORM", groupId: appId }
|
|
2732
|
-
});
|
|
2733
|
-
if (Array.isArray(response?.data)) {
|
|
2734
|
-
options[dataKey] = {};
|
|
2735
|
-
for (const option of response.data) {
|
|
2736
|
-
if (option?.id) options[dataKey][String(option.id)] = option.name;
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
}
|
|
2740
|
-
}
|
|
2741
|
-
const lists = {
|
|
2742
|
-
talent: null,
|
|
2743
|
-
demand: null,
|
|
2744
|
-
position: null,
|
|
2745
|
-
entry: null,
|
|
2746
|
-
offer: null,
|
|
2747
|
-
interview: null,
|
|
2748
|
-
dict: dictMenu,
|
|
2749
|
-
biz_config: bizConfigMenu,
|
|
2750
|
-
all_search: searchMenus,
|
|
2751
|
-
pages
|
|
2752
|
-
};
|
|
2753
|
-
for (const [biz, keywords] of Object.entries(LIST_KEYWORDS)) {
|
|
2754
|
-
for (const menu of searchMenus) {
|
|
2755
|
-
if (keywords.some((keyword) => (menu.menuName || "").includes(keyword))) {
|
|
2756
|
-
lists[biz] = menu;
|
|
2757
|
-
break;
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
return {
|
|
2762
|
-
appId,
|
|
2763
|
-
tenantKey,
|
|
2764
|
-
forms,
|
|
2765
|
-
lists,
|
|
2766
|
-
fields,
|
|
2767
|
-
field_options: fieldOptions,
|
|
2768
|
-
options,
|
|
2769
|
-
dict: { by_name: dictByName, raw: dictRaw },
|
|
2770
|
-
ebdDetailPageId,
|
|
2771
|
-
selfUse
|
|
2772
|
-
};
|
|
2773
|
-
}
|
|
2774
|
-
function createRecruitContextLoader() {
|
|
2775
|
-
const memo = /* @__PURE__ */ new Map();
|
|
2776
|
-
async function load(host) {
|
|
2777
|
-
const session = await host.getSession();
|
|
2778
|
-
const baseUrl = session.baseUrl.replace(/\/+$/, "");
|
|
2779
|
-
const memoKey = baseUrl;
|
|
2780
|
-
let cached = memo.get(memoKey);
|
|
2781
|
-
if (cached) return cached;
|
|
2782
|
-
let appId = "";
|
|
2783
|
-
let diskCache = null;
|
|
2784
|
-
try {
|
|
2785
|
-
const dir = cacheDirFor(baseUrl);
|
|
2786
|
-
if (existsSync2(dir)) {
|
|
2787
|
-
const files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
2788
|
-
if (files.length === 1) {
|
|
2789
|
-
appId = files[0].replace(/\.json$/, "");
|
|
2790
|
-
diskCache = JSON.parse(readFileSync(join(dir, files[0]), "utf8"));
|
|
2791
|
-
}
|
|
2792
|
-
}
|
|
2793
|
-
} catch {
|
|
2794
|
-
}
|
|
2795
|
-
if (diskCache) {
|
|
2796
|
-
memo.set(memoKey, diskCache);
|
|
2797
|
-
return diskCache;
|
|
2798
|
-
}
|
|
2799
|
-
const gate = await host.request({
|
|
2800
|
-
path: "/api/bs/ebuilder/app/tags/getAppIds",
|
|
2801
|
-
query: { tag: RECRUIT_APP_TAG }
|
|
2802
|
-
});
|
|
2803
|
-
const appIds = gate?.data;
|
|
2804
|
-
if (!Array.isArray(appIds) || !appIds.length) {
|
|
2805
|
-
throw new RecruitContextError(
|
|
2806
|
-
"recruit_service_not_installed",
|
|
2807
|
-
"\u5F53\u524D\u79DF\u6237\u672A\u5B89\u88C5\u62DB\u8058\u670D\u52A1\uFF08weaver-recruit-service\uFF09\uFF0C\u65E0\u6CD5\u4F7F\u7528\u62DB\u8058\u80FD\u529B\u3002\u8BF7\u5148\u5728 E10 \u5E94\u7528\u5E02\u573A\u5B89\u88C5\u300C\u62DB\u8058\u300D\u5E94\u7528\u3002"
|
|
2808
|
-
);
|
|
2809
|
-
}
|
|
2810
|
-
appId = String(appIds[0]);
|
|
2811
|
-
const resolved = await resolveRecruitEnv(host, appId);
|
|
2812
|
-
try {
|
|
2813
|
-
const dir = cacheDirFor(baseUrl);
|
|
2814
|
-
mkdirSync(dir, { recursive: true });
|
|
2815
|
-
writeFileSync(
|
|
2816
|
-
join(dir, `${appId}.json`),
|
|
2817
|
-
JSON.stringify({
|
|
2818
|
-
__meta__: {
|
|
2819
|
-
capturedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").substring(0, 19),
|
|
2820
|
-
note: "recruit-ops \u73AF\u5883\u53C2\u6570\u7F13\u5B58\uFF08weaver-work-cli \u8FD0\u884C\u65F6\u89E3\u6790\u4EA7\u7269\uFF0C\u4E0D\u542B\u8BA4\u8BC1\u5B57\u6BB5\uFF09"
|
|
2821
|
-
},
|
|
2822
|
-
envKey: `${dir.split(/[\\/]/).pop()}|${appId}`,
|
|
2823
|
-
...resolved
|
|
2824
|
-
}, null, 2),
|
|
2825
|
-
"utf8"
|
|
2826
|
-
);
|
|
2827
|
-
} catch {
|
|
2828
|
-
}
|
|
2829
|
-
memo.set(memoKey, resolved);
|
|
2830
|
-
return resolved;
|
|
2831
|
-
}
|
|
2832
|
-
return { load };
|
|
2833
|
-
}
|
|
2834
|
-
function buildListBody(params) {
|
|
2835
|
-
return {
|
|
2836
|
-
current: params.current ?? 1,
|
|
2837
|
-
pageSize: params.pageSize ?? 10,
|
|
2838
|
-
tableuid: randHex32(),
|
|
2839
|
-
listId: params.listId,
|
|
2840
|
-
searchParamData: {
|
|
2841
|
-
searchType: "3",
|
|
2842
|
-
type: "and",
|
|
2843
|
-
...params.conditions && Object.keys(params.conditions).length ? { commonSearchFields: params.conditions } : {}
|
|
2844
|
-
},
|
|
2845
|
-
terminal: "PC",
|
|
2846
|
-
browser: "Chrome",
|
|
2847
|
-
requiredMatch: 1,
|
|
2848
|
-
mapResult: 1,
|
|
2849
|
-
recheckQuery: 1,
|
|
2850
|
-
isFollow: 0,
|
|
2851
|
-
isShareToMe: 0,
|
|
2852
|
-
filterCondition: {},
|
|
2853
|
-
cusMenuId: params.cusMenuId,
|
|
2854
|
-
urlPageTitle: params.title,
|
|
2855
|
-
menuName: params.menuName
|
|
2856
|
-
};
|
|
2857
|
-
}
|
|
2858
|
-
async function fetchListRows(host, objId, listId, body) {
|
|
2859
|
-
const countBody = { ...body };
|
|
2860
|
-
delete countBody.current;
|
|
2861
|
-
delete countBody.pageSize;
|
|
2862
|
-
const [listResponse, countResponse] = await Promise.all([
|
|
2863
|
-
host.request({
|
|
2864
|
-
path: `/api/ebuilder/form/list/getListDatas?passid=${objId}&cid=${objId}`,
|
|
2865
|
-
body,
|
|
2866
|
-
headers: { ebBusinessId: listId }
|
|
2867
|
-
}),
|
|
2868
|
-
host.request({
|
|
2869
|
-
path: `/api/ebuilder/form/list/getListDataCount?passid=${objId}&cid=${objId}`,
|
|
2870
|
-
body: countBody,
|
|
2871
|
-
headers: { ebBusinessId: listId }
|
|
2872
|
-
}).catch(() => null)
|
|
2873
|
-
]);
|
|
2874
|
-
const data = normalizePaged(listResponse).data;
|
|
2875
|
-
const rawRows = data?.data || [];
|
|
2876
|
-
const displayRows = data?.displayData;
|
|
2877
|
-
const hasDisplay = Array.isArray(displayRows) && displayRows.length > 0;
|
|
2878
|
-
const rows = hasDisplay ? displayRows : rawRows;
|
|
2879
|
-
const countData = countResponse ? normalizePaged(countResponse).data : null;
|
|
2880
|
-
const pageSize = typeof body.pageSize === "number" ? body.pageSize : typeof body.pageSize === "string" ? Number(body.pageSize) || rows.length : rows.length;
|
|
2881
|
-
const countUsable = countData !== null && typeof countData.total === "number";
|
|
2882
|
-
let total;
|
|
2883
|
-
let totalExact;
|
|
2884
|
-
let totalNote;
|
|
2885
|
-
if (countUsable) {
|
|
2886
|
-
total = countData.total;
|
|
2887
|
-
totalExact = true;
|
|
2888
|
-
} else if (rows.length < pageSize) {
|
|
2889
|
-
total = rows.length;
|
|
2890
|
-
totalExact = true;
|
|
2891
|
-
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";
|
|
2892
|
-
} else {
|
|
2893
|
-
total = null;
|
|
2894
|
-
totalExact = false;
|
|
2895
|
-
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";
|
|
2896
|
-
}
|
|
2897
|
-
return { rows, displayRows: hasDisplay ? displayRows : null, total, totalExact, totalNote };
|
|
2898
|
-
}
|
|
2899
|
-
var contextResolve = {
|
|
2900
|
-
name: "ehr.recruit.context.resolve",
|
|
2901
|
-
resource: "recruit",
|
|
2902
|
-
method: "context.resolve",
|
|
2903
|
-
action: "ehr.recruit.context.resolve",
|
|
2904
|
-
summary: "\u89E3\u6790\u62DB\u8058\u6A21\u5757\u8FD0\u884C\u65F6\u53C2\u6570\uFF08appId/\u8868\u5355 objId/\u5217\u8868 listId+cusMenuId/\u5B57\u6BB5\u6620\u5C04\uFF09\uFF0C\u4E3B\u8981\u4F9B\u8C03\u8BD5\u4E0E\u515C\u5E95\uFF1B\u4E1A\u52A1 operation \u4F1A\u9690\u5F0F\u81EA\u52A8\u89E3\u6790",
|
|
2905
|
-
capability: "recruit",
|
|
2906
|
-
risk: READ,
|
|
2907
|
-
inputSchema: schemaOf({}),
|
|
2908
|
-
handler: async (_args, env) => {
|
|
2909
|
-
if (!env.recruitContext) {
|
|
2910
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
2911
|
-
}
|
|
2912
|
-
const cache = await env.recruitContext.load(env.host);
|
|
2913
|
-
return ehrSuccess("ehr.recruit.context.resolve", {
|
|
2914
|
-
appId: cache.appId,
|
|
2915
|
-
tenantKey: cache.tenantKey || null,
|
|
2916
|
-
forms: cache.forms,
|
|
2917
|
-
lists: cache.lists,
|
|
2918
|
-
ebdDetailPageId: cache.ebdDetailPageId || null,
|
|
2919
|
-
selfUse: cache.selfUse
|
|
2920
|
-
});
|
|
2921
|
-
}
|
|
2922
|
-
};
|
|
2923
|
-
var candidateSearch = {
|
|
2924
|
-
name: "ehr.recruit.candidate.search",
|
|
2925
|
-
resource: "recruit",
|
|
2926
|
-
method: "candidate.search",
|
|
2927
|
-
action: "ehr.recruit.candidate.search",
|
|
2928
|
-
summary: "\u6309\u59D3\u540D/\u624B\u673A\u53F7\u6A21\u7CCA\u641C\u7D22\u4EBA\u624D\u5E93\u4EBA\u624D\uFF1B\u65E0\u7B5B\u9009\u6761\u4EF6\u65F6\u5217\u51FA\u5168\u90E8\u4EBA\u624D\u7528\u4E8E\u6D4F\u89C8\u3002\u8FD4\u56DE\u767D\u540D\u5355\u5C55\u793A\u5B57\u6BB5",
|
|
2929
|
-
capability: "recruit",
|
|
2930
|
-
risk: READ,
|
|
2931
|
-
inputSchema: schemaOf({
|
|
2932
|
-
name: { type: "string", description: "\u59D3\u540D\u6A21\u7CCA\u5339\u914D" },
|
|
2933
|
-
mobile: { type: "string", description: "\u624B\u673A\u53F7\u6A21\u7CCA\u5339\u914D" },
|
|
2934
|
-
current: SCHEMA_ID,
|
|
2935
|
-
pageSize: SCHEMA_ID
|
|
2936
|
-
}),
|
|
2937
|
-
handler: async (args, env) => {
|
|
2938
|
-
if (!env.recruitContext) {
|
|
2939
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
2940
|
-
}
|
|
2941
|
-
const cache = await env.recruitContext.load(env.host);
|
|
2942
|
-
const talentList = cache.lists.talent;
|
|
2943
|
-
const talentObjId = cache.forms.talent_pool?.objId;
|
|
2944
|
-
if (!talentList?.listId || !talentObjId) {
|
|
2945
|
-
throw new RecruitContextError("recruit_context_missing", "\u5F53\u524D\u73AF\u5883\u672A\u89E3\u6790\u5230\u300C\u4EBA\u624D\u5E93\u300D\u83DC\u5355\u6216\u4EBA\u624D\u5E93\u8868\u5355\uFF0C\u65E0\u6CD5\u641C\u7D22\u4EBA\u624D\u3002\u8BF7\u5148\u8FD0\u884C ehr.recruit.context.resolve \u68C0\u67E5\u73AF\u5883\u3002");
|
|
2946
|
-
}
|
|
2947
|
-
const fields = cache.fields[talentObjId] || {};
|
|
2948
|
-
const nameField = "field_" + (fields.candidate_name || fields.name);
|
|
2949
|
-
const mobileField = "field_" + fields.telephone;
|
|
2950
|
-
const conditions = {};
|
|
2951
|
-
if (args.name) conditions[nameField] = [{ [nameField]: args.name, [`${nameField}_condition_type`]: "like" }];
|
|
2952
|
-
if (args.mobile) conditions[mobileField] = [{ [mobileField]: args.mobile, [`${mobileField}_condition_type`]: "like" }];
|
|
2953
|
-
const body = buildListBody({
|
|
2954
|
-
listId: talentList.listId,
|
|
2955
|
-
cusMenuId: talentList.cusMenuId,
|
|
2956
|
-
menuName: talentList.menuName || "\u4EBA\u624D\u7BA1\u7406",
|
|
2957
|
-
title: "\u4EBA\u624D\u5E93",
|
|
2958
|
-
current: toPositiveInt(args.current, "current") ?? 1,
|
|
2959
|
-
pageSize: toNumber(args.pageSize, "pageSize") ?? 10,
|
|
2960
|
-
conditions
|
|
2961
|
-
});
|
|
2962
|
-
const { rows, displayRows, total, totalExact, totalNote } = await fetchListRows(env.host, talentObjId, talentList.listId, body);
|
|
2963
|
-
let creatorNameMap = {};
|
|
2964
|
-
if (!displayRows) {
|
|
2965
|
-
const pureIds = [...new Set(rows.map((row) => row?.creator).filter(isPlainId).map((value) => String(value).trim()))];
|
|
2966
|
-
if (pureIds.length) {
|
|
2967
|
-
creatorNameMap = {};
|
|
2968
|
-
for (let index = 0; index < pureIds.length; index += 100) {
|
|
2969
|
-
const batch = pureIds.slice(index, index + 100);
|
|
2970
|
-
try {
|
|
2971
|
-
const response = await env.host.request({
|
|
2972
|
-
path: "/api/hrm/common/getEmployeeByIds",
|
|
2973
|
-
body: { userIdList: batch, externalIdList: [] },
|
|
2974
|
-
headers: { devtype: "5" }
|
|
2975
|
-
});
|
|
2976
|
-
for (const user of response?.data?.userList || []) {
|
|
2977
|
-
if (user?.id != null) creatorNameMap[String(user.id)] = user.name || null;
|
|
2978
|
-
}
|
|
2979
|
-
} catch {
|
|
2980
|
-
}
|
|
2981
|
-
}
|
|
2982
|
-
}
|
|
2983
|
-
}
|
|
2984
|
-
const statusMap = cache.options?.recruit_status || {};
|
|
2985
|
-
const dictNameMap = {};
|
|
2986
|
-
for (const item of cache.dict?.raw || []) {
|
|
2987
|
-
if (item.option_id && item.selection_name) dictNameMap[item.option_id] = item.selection_name;
|
|
2988
|
-
}
|
|
2989
|
-
const dataRows = rows.map((row) => {
|
|
2990
|
-
let creator = null;
|
|
2991
|
-
if (displayRows) {
|
|
2992
|
-
creator = namesOf(row?.creator);
|
|
2993
|
-
} else if (row?.creator != null) {
|
|
2994
|
-
const raw = String(row.creator).trim();
|
|
2995
|
-
creator = isPlainId(raw) ? creatorNameMap[raw] || raw : namesOf(raw) || raw;
|
|
2996
|
-
}
|
|
2997
|
-
return {
|
|
2998
|
-
talentId: row?.form_data_id || row?.id || null,
|
|
2999
|
-
name: row?.candidate_name || row?.name || null,
|
|
3000
|
-
mobile: row?.telephone || null,
|
|
3001
|
-
channel: dictNameMap[row?.channel] || row?.channel || null,
|
|
3002
|
-
status: statusMap[row?.recruit_status] || row?.recruit_status || null,
|
|
3003
|
-
creator,
|
|
3004
|
-
createTime: row?.create_time || null
|
|
3005
|
-
};
|
|
3006
|
-
});
|
|
3007
|
-
return ehrSuccess("ehr.recruit.candidate.search", { total, totalExact, ...totalNote ? { totalNote } : {}, rows: dataRows });
|
|
3008
|
-
}
|
|
3009
|
-
};
|
|
3010
|
-
var candidateList = {
|
|
3011
|
-
name: "ehr.recruit.candidate.list",
|
|
3012
|
-
resource: "recruit",
|
|
3013
|
-
method: "candidate.list",
|
|
3014
|
-
action: "ehr.recruit.candidate.list",
|
|
3015
|
-
summary: "\u67E5\u8BE2\u62DB\u8058\u4E1A\u52A1\u5217\u8868\uFF08demand \u62DB\u8058\u9700\u6C42 / position \u62DB\u8058\u804C\u4F4D / entry \u5165\u804C\u7BA1\u7406 / offer \u5F55\u7528\u7BA1\u7406\uFF09\uFF0CdisplayData \u663E\u793A\u5C42\u96F6\u7FFB\u8BD1\u8F93\u51FA",
|
|
3016
|
-
capability: "recruit",
|
|
3017
|
-
risk: READ,
|
|
3018
|
-
inputSchema: schemaOf({
|
|
3019
|
-
type: { type: "string", enum: ["demand", "position", "entry", "offer"], description: "\u5217\u8868\u7C7B\u578B" },
|
|
3020
|
-
current: SCHEMA_ID,
|
|
3021
|
-
pageSize: SCHEMA_ID
|
|
3022
|
-
}, { required: ["type"] }),
|
|
3023
|
-
handler: async (args, env) => {
|
|
3024
|
-
const type = typeof args.type === "string" ? args.type : "";
|
|
3025
|
-
const listType = LIST_TYPES[type];
|
|
3026
|
-
if (!listType) {
|
|
3027
|
-
throw ehrValidationError("enum_invalid", `type \u53D6\u503C\u5FC5\u987B\u662F ${Object.keys(LIST_TYPES).join(" / ")} \u4E4B\u4E00`);
|
|
3028
|
-
}
|
|
3029
|
-
if (!env.recruitContext) {
|
|
3030
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
3031
|
-
}
|
|
3032
|
-
const cache = await env.recruitContext.load(env.host);
|
|
3033
|
-
const listParam = cache.lists[listType.listKey];
|
|
3034
|
-
if (!listParam?.listId) {
|
|
3035
|
-
throw new RecruitContextError(
|
|
3036
|
-
"recruit_list_unavailable",
|
|
3037
|
-
`\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u300C${listType.title}\u300D\u529F\u80FD\uFF08\u672A\u627E\u5230\u5BF9\u5E94\u83DC\u5355/\u5217\u8868\u53C2\u6570\uFF0C\u6309\u80FD\u529B\u63A2\u6D4B\u62E6\u622A\uFF09\u3002`
|
|
3038
|
-
);
|
|
3039
|
-
}
|
|
3040
|
-
const formObjId = cache.forms[listType.formType]?.objId;
|
|
3041
|
-
if (!formObjId) {
|
|
3042
|
-
throw new RecruitContextError("recruit_context_missing", `\u672A\u89E3\u6790\u5230\u300C${listType.title}\u300D\u5BF9\u5E94\u8868\u5355\uFF0C\u65E0\u6CD5\u67E5\u8BE2\u3002`);
|
|
3043
|
-
}
|
|
3044
|
-
const body = buildListBody({
|
|
3045
|
-
listId: listParam.listId,
|
|
3046
|
-
cusMenuId: listParam.cusMenuId,
|
|
3047
|
-
menuName: listParam.menuName || listType.title,
|
|
3048
|
-
title: listType.title,
|
|
3049
|
-
current: toPositiveInt(args.current, "current") ?? 1,
|
|
3050
|
-
pageSize: toNumber(args.pageSize, "pageSize") ?? 10
|
|
3051
|
-
});
|
|
3052
|
-
const { rows, displayRows, total, totalExact, totalNote } = await fetchListRows(env.host, formObjId, listParam.listId, body);
|
|
3053
|
-
const outRows = rows.map((row) => {
|
|
3054
|
-
const cleaned = { form_data_id: row?.form_data_id || row?.id };
|
|
3055
|
-
for (const [key, value] of Object.entries(row || {})) {
|
|
3056
|
-
if (displayRows) {
|
|
3057
|
-
if (DISPLAY_UI_KEYS.has(key) || key === "form_data_id") continue;
|
|
3058
|
-
if (key.endsWith("Span") || key.endsWith("Action")) continue;
|
|
3059
|
-
const text2 = String(value ?? "");
|
|
3060
|
-
if (!text2) continue;
|
|
3061
|
-
if (typeof value === "object" || typeof value === "string" && text2.trimStart().startsWith("[")) {
|
|
3062
|
-
const names2 = namesOf(value);
|
|
3063
|
-
cleaned[key] = names2 != null ? names2 : text2;
|
|
3064
|
-
continue;
|
|
3065
|
-
}
|
|
3066
|
-
cleaned[key] = text2;
|
|
3067
|
-
continue;
|
|
3068
|
-
}
|
|
3069
|
-
if (INTERNAL_KEYS.has(key)) continue;
|
|
3070
|
-
const text = String(value ?? "");
|
|
3071
|
-
if (!text) continue;
|
|
3072
|
-
if (/^\d{16,}$/.test(text)) continue;
|
|
3073
|
-
const names = typeof value === "object" || typeof value === "string" && text.trimStart().startsWith("[") ? namesOf(value) : null;
|
|
3074
|
-
cleaned[key] = names != null ? names : text;
|
|
3075
|
-
}
|
|
3076
|
-
return cleaned;
|
|
3077
|
-
});
|
|
3078
|
-
return ehrSuccess("ehr.recruit.candidate.list", {
|
|
3079
|
-
type,
|
|
3080
|
-
total,
|
|
3081
|
-
totalExact,
|
|
3082
|
-
...totalNote ? { totalNote } : {},
|
|
3083
|
-
current: body.current,
|
|
3084
|
-
pageSize: body.pageSize,
|
|
3085
|
-
rows: outRows
|
|
3086
|
-
});
|
|
3087
|
-
}
|
|
3088
|
-
};
|
|
3089
|
-
function personNames(value) {
|
|
3090
|
-
const text = String(value ?? "").trim();
|
|
3091
|
-
if (!text) return "";
|
|
3092
|
-
if (text.startsWith("[")) {
|
|
3093
|
-
try {
|
|
3094
|
-
const arr = JSON.parse(text);
|
|
3095
|
-
if (Array.isArray(arr)) {
|
|
3096
|
-
const names = arr.map((item) => typeof item === "string" ? item : item?.name ?? item?.username ?? "").filter(Boolean);
|
|
3097
|
-
if (names.length) return names.join("\u3001");
|
|
3098
|
-
}
|
|
3099
|
-
} catch {
|
|
3100
|
-
}
|
|
3101
|
-
}
|
|
3102
|
-
return text;
|
|
3103
|
-
}
|
|
3104
|
-
function nameLike(value) {
|
|
3105
|
-
const text = String(value ?? "").trim();
|
|
3106
|
-
if (!text || /^\d{16,}$/.test(text)) return null;
|
|
3107
|
-
return text;
|
|
3108
|
-
}
|
|
3109
|
-
async function resolveCurrentUserName(host) {
|
|
3110
|
-
try {
|
|
3111
|
-
const session = await host.getSession();
|
|
3112
|
-
const baseUrl = String(session?.baseUrl || "");
|
|
3113
|
-
if (!baseUrl) return "";
|
|
3114
|
-
const resp = await fetch(
|
|
3115
|
-
`${baseUrl}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(baseUrl)}`,
|
|
3116
|
-
{
|
|
3117
|
-
method: "POST",
|
|
3118
|
-
headers: {
|
|
3119
|
-
accept: "application/json",
|
|
3120
|
-
"content-type": "application/json",
|
|
3121
|
-
eteamsid: String(session?.eteamsId || ""),
|
|
3122
|
-
cookie: typeof session?.cookieHeader === "function" ? session.cookieHeader() : "",
|
|
3123
|
-
"user-agent": typeof session?.uaHeader === "function" ? session.uaHeader() : "weaver-work-cli",
|
|
3124
|
-
origin: baseUrl
|
|
3125
|
-
},
|
|
3126
|
-
redirect: "manual"
|
|
3127
|
-
}
|
|
3128
|
-
);
|
|
3129
|
-
const data = await resp.json().catch(() => ({}));
|
|
3130
|
-
const cu = data.currentUser ?? data.data?.currentUser ?? null;
|
|
3131
|
-
return cu ? String(cu.username ?? cu.id ?? "") : "";
|
|
3132
|
-
} catch {
|
|
3133
|
-
return "";
|
|
3134
|
-
}
|
|
3135
|
-
}
|
|
3136
|
-
var interviewFeedbackTodo = {
|
|
3137
|
-
name: "ehr.recruit.interview.feedbackTodo",
|
|
3138
|
-
resource: "recruit",
|
|
3139
|
-
method: "interview.feedbackTodo",
|
|
3140
|
-
action: "ehr.recruit.interview.feedbackTodo",
|
|
3141
|
-
summary: "\u9762\u8BD5\u5F85\u529E\uFF1A**\u53EA\u8FD4\u56DE\u6211\u4F5C\u4E3A\u9762\u8BD5\u5B98\u7684 AI \u9762\u8BD5\u5F85\u53CD\u9988\u6E05\u5355**\uFF08\u5019\u9009\u4EBA\u5DF2\u7B54\u5B8C\u3001\u5DF2\u6709\u5F55\u50CF\u3001\u6211\u8FD8\u6CA1\u586B\u610F\u89C1\uFF09\uFF1B\u6309\u9700\u7FFB\u9875 + \u5BA2\u6237\u7AEF\u7B5B\u9009\uFF0C\u4E0D\u8FD4\u56DE\u5168\u91CF\u9762\u8BD5",
|
|
3142
|
-
capability: "recruit",
|
|
3143
|
-
risk: READ,
|
|
3144
|
-
inputSchema: schemaOf({
|
|
3145
|
-
maxPages: { type: "integer", minimum: 1, maximum: 50, description: "\u6700\u591A\u7FFB\u9875\u6570\uFF08\u9ED8\u8BA4 5\uFF09" },
|
|
3146
|
-
pageSize: { type: "integer", minimum: 1, maximum: 200, description: "\u5355\u9875\u6761\u6570\uFF08\u9ED8\u8BA4 200\uFF0C\u5B9E\u6D4B\u670D\u52A1\u7AEF\u4E0A\u9650 200\uFF09" }
|
|
3147
|
-
}),
|
|
3148
|
-
handler: async (args, env) => {
|
|
3149
|
-
if (!env.recruitContext) throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
3150
|
-
const cache = await env.recruitContext.load(env.host);
|
|
3151
|
-
const listParam = cache.lists.interview;
|
|
3152
|
-
const form = cache.forms.interview_plan;
|
|
3153
|
-
if (!listParam?.listId || !form?.objId) {
|
|
3154
|
-
throw new RecruitContextError(
|
|
3155
|
-
"recruit_list_unavailable",
|
|
3156
|
-
"\u5F53\u524D\u73AF\u5883\u672A\u542F\u7528\u300C\u9762\u8BD5\u7BA1\u7406\u300D\u529F\u80FD\uFF08\u672A\u627E\u5230\u9762\u8BD5\u5217\u8868/\u8868\u5355\u53C2\u6570\uFF0C\u6309\u80FD\u529B\u63A2\u6D4B\u62E6\u622A\uFF09\u3002"
|
|
3157
|
-
);
|
|
3158
|
-
}
|
|
3159
|
-
const pageSize = toNumber(args.pageSize, "pageSize") ?? 200;
|
|
3160
|
-
const maxPages = toNumber(args.maxPages, "maxPages") ?? 5;
|
|
3161
|
-
const me = await resolveCurrentUserName(env.host);
|
|
3162
|
-
const fields = cache.fields[form.objId] || {};
|
|
3163
|
-
const fieldOpts = cache.field_options[form.objId] || {};
|
|
3164
|
-
const statusOpts = fieldOpts[fields.union_status] || {};
|
|
3165
|
-
const typeOpts = fieldOpts[fields.interview_type] || {};
|
|
3166
|
-
const toCn = (map, raw) => {
|
|
3167
|
-
const text = String(raw ?? "");
|
|
3168
|
-
return map[text] ?? text;
|
|
3169
|
-
};
|
|
3170
|
-
const statusOf = (row) => toCn(statusOpts, row?.union_status_key ?? row?.union_status);
|
|
3171
|
-
const typeOf = (row) => toCn(typeOpts, row?.interview_type_key ?? row?.interview_type);
|
|
3172
|
-
const interviewerOf = (row) => personNames(row?.interviewer);
|
|
3173
|
-
const scanned = [];
|
|
3174
|
-
let lastPageCount = 0;
|
|
3175
|
-
for (let i = 0; i < maxPages; i++) {
|
|
3176
|
-
const body = buildListBody({
|
|
3177
|
-
listId: listParam.listId,
|
|
3178
|
-
cusMenuId: listParam.cusMenuId,
|
|
3179
|
-
menuName: listParam.menuName || "\u9762\u8BD5\u7BA1\u7406",
|
|
3180
|
-
title: "\u9762\u8BD5\u7BA1\u7406",
|
|
3181
|
-
current: i + 1,
|
|
3182
|
-
pageSize
|
|
3183
|
-
});
|
|
3184
|
-
const page = await fetchListRows(env.host, form.objId, listParam.listId, body);
|
|
3185
|
-
const use = page.displayRows && page.displayRows.length ? page.displayRows : page.rows;
|
|
3186
|
-
scanned.push(...use);
|
|
3187
|
-
lastPageCount = use.length;
|
|
3188
|
-
if (use.length < pageSize) break;
|
|
3189
|
-
}
|
|
3190
|
-
const pending = scanned.filter((row) => /待反馈/.test(statusOf(row)));
|
|
3191
|
-
const mineAll = me ? pending.filter((row) => interviewerOf(row).includes(me)) : [];
|
|
3192
|
-
const mineAi = mineAll.filter((row) => /AI\s*面试/i.test(typeOf(row)));
|
|
3193
|
-
const slim = (row) => ({
|
|
3194
|
-
form_data_id: row?.form_data_id ?? row?.id ?? null,
|
|
3195
|
-
candidate_name: nameLike(row?.candidate_name) ?? nameLike(row?.talent_id) ?? nameLike(row?.name),
|
|
3196
|
-
position_name: nameLike(row?.position_name) ?? nameLike(row?.position_manage_id),
|
|
3197
|
-
start_time: row?.start_time ?? null,
|
|
3198
|
-
interview_type_key: typeOf(row) || null,
|
|
3199
|
-
interview_session: row?.interview_session ?? null,
|
|
3200
|
-
interviewer: interviewerOf(row) || null,
|
|
3201
|
-
union_status_key: statusOf(row) || null,
|
|
3202
|
-
subject: row?.subject ?? null,
|
|
3203
|
-
talent_id: row?.talent_id ?? null,
|
|
3204
|
-
position_manage_id: row?.position_manage_id ?? null
|
|
3205
|
-
});
|
|
3206
|
-
const notes = [];
|
|
3207
|
-
if (!me) notes.push("\u672A\u80FD\u89E3\u6790\u5F53\u524D\u767B\u5F55\u4EBA\u59D3\u540D\uFF08teamsCheck \u5931\u8D25\uFF09\uFF0C\u65E0\u6CD5\u6309\u9762\u8BD5\u5B98\u8FC7\u6EE4");
|
|
3208
|
-
if (lastPageCount >= pageSize && scanned.length >= pageSize * maxPages) {
|
|
3209
|
-
notes.push(`\u5DF2\u626B\u63CF ${scanned.length} \u6761\uFF08\u8FBE maxPages=${maxPages} \u4E0A\u9650\uFF09\uFF0C\u5982\u6000\u7591\u9057\u6F0F\u53EF\u52A0\u5927 maxPages`);
|
|
3210
|
-
}
|
|
3211
|
-
return ehrSuccess("ehr.recruit.interview.feedbackTodo", {
|
|
3212
|
-
currentUser: me || null,
|
|
3213
|
-
scanned: scanned.length,
|
|
3214
|
-
myAiPendingFeedback: { count: mineAi.length, rows: mineAi.map(slim) },
|
|
3215
|
-
myOtherPendingFeedback: {
|
|
3216
|
-
count: mineAll.length - mineAi.length,
|
|
3217
|
-
rows: mineAll.filter((row) => !/AI\s*面试/i.test(typeOf(row))).map(slim)
|
|
3218
|
-
},
|
|
3219
|
-
...notes.length ? { note: notes.join("\uFF1B") } : {}
|
|
3220
|
-
});
|
|
3221
|
-
}
|
|
3222
|
-
};
|
|
3223
|
-
var candidateCard = {
|
|
3224
|
-
name: "ehr.recruit.candidate.card",
|
|
3225
|
-
resource: "recruit",
|
|
3226
|
-
method: "candidate.card",
|
|
3227
|
-
action: "ehr.recruit.candidate.card",
|
|
3228
|
-
summary: "\u67E5\u770B\u4EBA\u624D\u8BE6\u60C5\u5361\u7247\uFF1A\u6743\u9650\u6821\u9A8C + \u56DB\u5F20\u5361\u7247\uFF08\u57FA\u672C\u4FE1\u606F/\u5E94\u8058\u8FDB\u5C55/\u9762\u8BD5\u5B89\u6392/\u6C9F\u901A\u5907\u6CE8\uFF09\u5E76\u884C\u62C9\u53D6\uFF0C\u59D3\u540D\u4E0E\u5B57\u5178\u5168\u90E8\u5185\u8054\u89E3\u6790",
|
|
3229
|
-
capability: "recruit",
|
|
3230
|
-
risk: READ,
|
|
3231
|
-
inputSchema: schemaOf(
|
|
3232
|
-
{ talentId: { oneOf: [{ type: "integer" }, { type: "string", pattern: "^\\d+$" }], description: "\u4EBA\u624D ID\uFF0C\u6765\u81EA candidate.search \u7684 talentId" } },
|
|
3233
|
-
{ required: ["talentId"] }
|
|
3234
|
-
),
|
|
3235
|
-
handler: async (args, env) => {
|
|
3236
|
-
const talentId = args.talentId;
|
|
3237
|
-
if (talentId === void 0 || talentId === null || talentId === "") {
|
|
3238
|
-
throw ehrValidationError("talent_id_required", "talentId \u5FC5\u586B");
|
|
3239
|
-
}
|
|
3240
|
-
if (!/^\d+$/.test(String(talentId).trim())) {
|
|
3241
|
-
throw ehrValidationError("talent_id_invalid", "talentId \u5FC5\u987B\u662F\u6570\u5B57 ID");
|
|
3242
|
-
}
|
|
3243
|
-
const id = String(talentId).trim();
|
|
3244
|
-
if (!env.recruitContext) {
|
|
3245
|
-
throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
3246
|
-
}
|
|
3247
|
-
const cache = await env.recruitContext.load(env.host);
|
|
3248
|
-
const talentListId = cache.lists.talent?.listId || "";
|
|
3249
|
-
const extra = talentListId ? { ebBusinessId: talentListId } : {};
|
|
3250
|
-
const rk1 = randHex6();
|
|
3251
|
-
const [rightsResponse, prepareResponse] = await Promise.all([
|
|
3252
|
-
env.host.request({
|
|
3253
|
-
path: `/api/recruit/talent/hasRights?formDataId=${id}`,
|
|
3254
|
-
method: "POST",
|
|
3255
|
-
headers: extra
|
|
3256
|
-
}),
|
|
3257
|
-
env.host.request({
|
|
3258
|
-
path: `/api/recruit/candidate/getCandidateCardPrepareQuery?talentId=${id}&randomkey_${rk1}=${rk1}`,
|
|
3259
|
-
headers: extra
|
|
3260
|
-
})
|
|
3261
|
-
]);
|
|
3262
|
-
const rights = rightsResponse?.data || [];
|
|
3263
|
-
if (!rights.includes("READ")) {
|
|
3264
|
-
throw ehrValidationError("recruit_rights_denied", "\u5F53\u524D\u8D26\u53F7\u65E0\u8BE5\u4EBA\u624D\u8BE6\u60C5\u7684 READ \u6743\u9650\uFF0C\u65E0\u6CD5\u67E5\u770B\u3002");
|
|
3265
|
-
}
|
|
3266
|
-
const batchId = prepareResponse?.data?.batchId;
|
|
3267
|
-
if (!batchId) {
|
|
3268
|
-
throw new RecruitContextError("recruit_batch_id_missing", "\u672A\u53D6\u5230 batchId\uFF08prepareQuery \u8FD4\u56DE\u5F02\u5E38\uFF09\uFF0C\u65E0\u6CD5\u67E5\u770B\u8BE6\u60C5\u5361\u7247\u3002");
|
|
3269
|
-
}
|
|
3270
|
-
const rk2 = randHex6();
|
|
3271
|
-
const v = randHex6();
|
|
3272
|
-
const query = `talentId=${id}&batchId=${batchId}&v=${v}&randomkey_${rk2}=${rk2}`;
|
|
3273
|
-
const cardBody = { talentId: id, batchId, current: 1, pageSize: 100 };
|
|
3274
|
-
const [base, other, interview, remark] = await Promise.all([
|
|
3275
|
-
env.host.request({ path: `/api/recruit/candidate/getCandidateCardBaseInfo?${query}`, headers: extra }),
|
|
3276
|
-
env.host.request({ path: `/api/recruit/candidate/getCandidateCardOtherInfo?${query}`, headers: extra }),
|
|
3277
|
-
env.host.request({ path: "/api/recruit/candidate/getCandidateCardInterviewInfo", body: cardBody, headers: extra }),
|
|
3278
|
-
env.host.request({ path: "/api/recruit/candidate/getCandidateCardRemark", body: cardBody, headers: extra })
|
|
3279
|
-
]);
|
|
3280
|
-
const statusMap = cache.options?.recruit_status || {};
|
|
3281
|
-
const talent = base?.data?.talent || {};
|
|
3282
|
-
const currentBatch = other?.data?.currentCandidateBatch || {};
|
|
3283
|
-
const interviewList = interview?.data?.list || [];
|
|
3284
|
-
const remarkList = remark?.data?.list || [];
|
|
3285
|
-
const baseUrl = (await env.host.getSession()).baseUrl.replace(/\/+$/, "");
|
|
3286
|
-
return ehrSuccess("ehr.recruit.candidate.card", {
|
|
3287
|
-
talentId: id,
|
|
3288
|
-
cardLink: cache.ebdDetailPageId ? `${baseUrl}/sp/ebdpage/view/${cache.ebdDetailPageId}?talentId=${id}${String(cache.selfUse ?? "") === "1" ? "&recruitType=useSelf" : ""}` : null,
|
|
3289
|
-
baseInfo: {
|
|
3290
|
-
name: talent?.hrm?.name,
|
|
3291
|
-
mobile: talent?.telephone,
|
|
3292
|
-
channel: talent?.channel,
|
|
3293
|
-
status: statusMap[base?.data?.recruitStatus] || base?.data?.recruitStatus || null,
|
|
3294
|
-
createTime: talent?.createTime
|
|
3295
|
-
},
|
|
3296
|
-
position: {
|
|
3297
|
-
position: currentBatch?.position?.name,
|
|
3298
|
-
stage: currentBatch?.currentStageName,
|
|
3299
|
-
stages: (currentBatch?.allStage || []).map((stage) => stage?.stageName).filter(Boolean),
|
|
3300
|
-
archiveStatus: currentBatch?.archiveStatus?.name,
|
|
3301
|
-
employManager: namesOf(currentBatch?.employManager),
|
|
3302
|
-
channel: currentBatch?.channel,
|
|
3303
|
-
candidateManageId: currentBatch?.id || currentBatch?.candidateManageId || null,
|
|
3304
|
-
batchId: currentBatch?.batchId || batchId,
|
|
3305
|
-
positionId: currentBatch?.position?.id || null
|
|
3306
|
-
},
|
|
3307
|
-
interviews: interviewList.map((item) => ({
|
|
3308
|
-
subject: item?.subject,
|
|
3309
|
-
startTime: item?.startTime || null,
|
|
3310
|
-
endTime: item?.endTime || null,
|
|
3311
|
-
status: namesOf(item?.unionStatus),
|
|
3312
|
-
type: namesOf(item?.interviewType),
|
|
3313
|
-
round: namesOf(item?.interviewSession),
|
|
3314
|
-
interviewer: namesOf(item?.interviewer),
|
|
3315
|
-
arranger: namesOf(item?.creator),
|
|
3316
|
-
updater: namesOf(item?.updater),
|
|
3317
|
-
position: namesOf(item?.positionManageId),
|
|
3318
|
-
feedbacks: (item?.interviewFeedBack || []).map((feedback) => ({
|
|
3319
|
-
result: feedback?.result?.[0]?.name || null,
|
|
3320
|
-
comment: feedback?.judgement ? feedback.judgement.replace(/<[^>]+>/g, "").trim() : null,
|
|
3321
|
-
feedbacker: namesOf(feedback?.updater),
|
|
3322
|
-
createTime: feedback?.createTime
|
|
3323
|
-
}))
|
|
3324
|
-
})),
|
|
3325
|
-
remarks: remarkList.map((item) => ({
|
|
3326
|
-
time: item?.contactTime || item?.createTime,
|
|
3327
|
-
creator: item?.creator?.username || item?.creator?.name || null,
|
|
3328
|
-
content: item?.remark
|
|
3329
|
-
}))
|
|
3330
|
-
});
|
|
3331
|
-
}
|
|
3332
|
-
};
|
|
3333
|
-
var recruitOperations = [
|
|
3334
|
-
contextResolve,
|
|
3335
|
-
candidateSearch,
|
|
3336
|
-
candidateList,
|
|
3337
|
-
candidateCard,
|
|
3338
|
-
interviewFeedbackTodo
|
|
3339
|
-
];
|
|
3340
|
-
|
|
3341
2264
|
// src/shortcuts/ehr/operations/recruit-write.ts
|
|
3342
2265
|
import { createHash as createHash3 } from "node:crypto";
|
|
3343
2266
|
var CONTINUATION_TTL_SECONDS2 = 600;
|
|
@@ -3631,21 +2554,25 @@ async function resolveCandidateForWrite(host, cache, talentId) {
|
|
|
3631
2554
|
throw ehrValidationError("recruit_batch_id_missing", "\u672A\u53D6\u5230 batchId\uFF08prepareQuery \u8FD4\u56DE\u5F02\u5E38\uFF09\uFF0C\u65E0\u6CD5\u5B9A\u4F4D\u5019\u9009\u4EBA\u5E94\u8058\u6279\u6B21");
|
|
3632
2555
|
}
|
|
3633
2556
|
const v = randomHex6();
|
|
3634
|
-
const otherResponse = await
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
if (!name) {
|
|
3641
|
-
const baseResponse = await host.request({
|
|
2557
|
+
const [otherResponse, baseResponse] = await Promise.all([
|
|
2558
|
+
host.request({
|
|
2559
|
+
path: `/api/recruit/candidate/getCandidateCardOtherInfo?talentId=${talentId}&batchId=${batchId}&v=${v}&randomkey_ab=ab`,
|
|
2560
|
+
headers: extra
|
|
2561
|
+
}),
|
|
2562
|
+
host.request({
|
|
3642
2563
|
path: `/api/recruit/candidate/getCandidateCardBaseInfo?talentId=${talentId}&batchId=${batchId}&v=${v}&randomkey_cd=cd`,
|
|
3643
2564
|
headers: extra
|
|
3644
|
-
})
|
|
3645
|
-
|
|
3646
|
-
}
|
|
2565
|
+
}).catch(() => null)
|
|
2566
|
+
]);
|
|
2567
|
+
const batch = otherResponse?.data?.currentCandidateBatch || {};
|
|
2568
|
+
const talentBase = baseResponse?.data?.talent || {};
|
|
2569
|
+
const name = batch?.talent?.name || talentBase?.hrm?.name || talentBase?.name || "";
|
|
2570
|
+
const email = String(talentBase.email || talentBase.hrm?.email || "").trim();
|
|
2571
|
+
const mobile = String(talentBase.telephone || talentBase.mobile || "").trim();
|
|
3647
2572
|
return {
|
|
3648
2573
|
name,
|
|
2574
|
+
email,
|
|
2575
|
+
mobile,
|
|
3649
2576
|
candidateManageId: batch?.id || batch?.candidateManageId || null,
|
|
3650
2577
|
positionId: batch?.position?.id || null,
|
|
3651
2578
|
positionName: batch?.position?.name || null,
|
|
@@ -3855,6 +2782,7 @@ var candidateCreateApply = {
|
|
|
3855
2782
|
}
|
|
3856
2783
|
};
|
|
3857
2784
|
var INTERVIEW_TYPES = ["\u73B0\u573A\u9762\u8BD5", "\u89C6\u9891\u9762\u8BD5", "\u7535\u8BDD\u9762\u8BD5", "AI\u9762\u8BD5"];
|
|
2785
|
+
var AI_DEFAULT_PLAN_NAME = "\u5927\u6A21\u578B\u9762\u8BD5";
|
|
3858
2786
|
var INTERVIEW_DATAKEYS = [
|
|
3859
2787
|
"subject",
|
|
3860
2788
|
"start_time",
|
|
@@ -3877,15 +2805,150 @@ function defaultInterviewWindow() {
|
|
|
3877
2805
|
const end = new Date(now.getTime() + 60 * 60 * 1e3);
|
|
3878
2806
|
return { start: fmt(now), end: fmt(end) };
|
|
3879
2807
|
}
|
|
2808
|
+
async function resolveCurrentUserForWrite(host) {
|
|
2809
|
+
try {
|
|
2810
|
+
const session = await host.getSession();
|
|
2811
|
+
const baseUrl = String(session?.baseUrl || "");
|
|
2812
|
+
if (!baseUrl) return null;
|
|
2813
|
+
const resp = await fetch(
|
|
2814
|
+
`${baseUrl}/api/baseserver/layout/teamsCheck?clientType=not_xinchuang&client=WEB&domainName=${encodeURIComponent(baseUrl)}`,
|
|
2815
|
+
{
|
|
2816
|
+
method: "POST",
|
|
2817
|
+
headers: {
|
|
2818
|
+
accept: "application/json",
|
|
2819
|
+
"content-type": "application/json",
|
|
2820
|
+
eteamsid: String(session?.eteamsId || ""),
|
|
2821
|
+
cookie: typeof session?.cookieHeader === "function" ? session.cookieHeader() : "",
|
|
2822
|
+
"user-agent": typeof session?.uaHeader === "function" ? session.uaHeader() : "weaver-work-cli",
|
|
2823
|
+
origin: baseUrl
|
|
2824
|
+
},
|
|
2825
|
+
redirect: "manual"
|
|
2826
|
+
}
|
|
2827
|
+
);
|
|
2828
|
+
const data = await resp.json().catch(() => ({}));
|
|
2829
|
+
const cu = data?.currentUser ?? data?.data?.currentUser ?? null;
|
|
2830
|
+
if (!cu?.id) return null;
|
|
2831
|
+
return { id: String(cu.id), name: String(cu.username || cu.id) };
|
|
2832
|
+
} catch {
|
|
2833
|
+
return null;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
async function fetchLayoutIdForForm(host, formId) {
|
|
2837
|
+
try {
|
|
2838
|
+
const r = await host.request({
|
|
2839
|
+
path: `/api/ebuilder/form/form/core/getFormLayout?formId=${encodeURIComponent(formId)}`,
|
|
2840
|
+
method: "GET"
|
|
2841
|
+
});
|
|
2842
|
+
const id = r?.data?.formLayout?.id;
|
|
2843
|
+
if (id) return String(id);
|
|
2844
|
+
} catch {
|
|
2845
|
+
}
|
|
2846
|
+
try {
|
|
2847
|
+
const r = await host.request({
|
|
2848
|
+
path: "/api/ebuilder/form/form/core/getFormLayout",
|
|
2849
|
+
method: "POST",
|
|
2850
|
+
body: { module: "ebuilderform", formId, terminalType: "PC" }
|
|
2851
|
+
});
|
|
2852
|
+
const id = r?.data?.formLayout?.id;
|
|
2853
|
+
if (id) return String(id);
|
|
2854
|
+
} catch {
|
|
2855
|
+
}
|
|
2856
|
+
return formId;
|
|
2857
|
+
}
|
|
2858
|
+
var DIGITAL_PLAN_NAME_KEYS = ["msfa_name", "digital_name", "plan_name", "scheme_name"];
|
|
2859
|
+
async function listDigitalPlansForWrite(host, cache, formId, layoutId, fieldId) {
|
|
2860
|
+
try {
|
|
2861
|
+
const r = await host.request({
|
|
2862
|
+
path: "/api/ebuilder/form/common/browser/complete/ebuilder",
|
|
2863
|
+
body: {
|
|
2864
|
+
browserMultiple: false,
|
|
2865
|
+
newly: 1,
|
|
2866
|
+
searchValue: "",
|
|
2867
|
+
formParam: JSON.stringify({ formId, layoutId, fieldId, filterItems: [], module: "ebuilderform", dataDetails: [] }),
|
|
2868
|
+
openScroll: true,
|
|
2869
|
+
controlId: fieldId,
|
|
2870
|
+
businessId: formId,
|
|
2871
|
+
variableMap: {}
|
|
2872
|
+
}
|
|
2873
|
+
});
|
|
2874
|
+
if (r?.status !== false && r?.data) {
|
|
2875
|
+
const list = r.data.data || [];
|
|
2876
|
+
const items2 = list.filter((x) => x && x.id).map((x) => ({ id: String(x.id), name: String(x.name || "").trim() }));
|
|
2877
|
+
if (items2.length) return { available: true, items: items2 };
|
|
2878
|
+
}
|
|
2879
|
+
} catch {
|
|
2880
|
+
}
|
|
2881
|
+
const menus = cache.lists?.all_search || [];
|
|
2882
|
+
const menu = menus.find((m) => (m.menuName || "").includes("\u9762\u8BD5\u6570\u5B57\u4EBA")) || menus.find((m) => (m.menuName || "").includes("\u6570\u5B57\u4EBA\u914D\u7F6E"));
|
|
2883
|
+
if (!menu?.listId) {
|
|
2884
|
+
return { available: false, items: [], reason: "\u5173\u8054\u5B57\u6BB5\u5019\u9009\u63A5\u53E3\u4E0D\u53EF\u7528\uFF0C\u4E14\u5F53\u524D\u73AF\u5883\u672A\u914D\u7F6E\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D\u5217\u8868\u83DC\u5355" };
|
|
2885
|
+
}
|
|
2886
|
+
let objId = "";
|
|
2887
|
+
try {
|
|
2888
|
+
const r = await host.request({
|
|
2889
|
+
path: `/api/ebuilder/form/obj/getObjsByTag?appId=${encodeURIComponent(String(cache.appId || ""))}&tag=uf_rcrt_digital_human`,
|
|
2890
|
+
method: "GET"
|
|
2891
|
+
});
|
|
2892
|
+
const d = r?.data;
|
|
2893
|
+
if (Array.isArray(d) && d.length) objId = String(d[0]?.id || "");
|
|
2894
|
+
} catch {
|
|
2895
|
+
}
|
|
2896
|
+
if (!objId) return { available: false, items: [], reason: "\u672A\u80FD\u89E3\u6790\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D\u5BF9\u8C61 id" };
|
|
2897
|
+
const rows = [];
|
|
2898
|
+
for (let cur = 1; cur <= 20; cur++) {
|
|
2899
|
+
const r = await host.request({
|
|
2900
|
+
path: `/api/ebuilder/form/list/getListDatas?passid=${objId}&cid=${objId}`,
|
|
2901
|
+
body: {
|
|
2902
|
+
current: cur,
|
|
2903
|
+
pageSize: 100,
|
|
2904
|
+
tableuid: randomHex32(),
|
|
2905
|
+
listId: menu.listId,
|
|
2906
|
+
searchParamData: { searchType: "3", type: "and" },
|
|
2907
|
+
terminal: "PC",
|
|
2908
|
+
browser: "Chrome",
|
|
2909
|
+
requiredMatch: 1,
|
|
2910
|
+
mapResult: 1,
|
|
2911
|
+
recheckQuery: 1,
|
|
2912
|
+
isFollow: 0,
|
|
2913
|
+
isShareToMe: 0,
|
|
2914
|
+
filterCondition: {},
|
|
2915
|
+
cusMenuId: menu.cusMenuId,
|
|
2916
|
+
urlPageTitle: menu.menuName,
|
|
2917
|
+
menuName: menu.menuName
|
|
2918
|
+
},
|
|
2919
|
+
headers: { ebBusinessId: String(menu.listId) }
|
|
2920
|
+
});
|
|
2921
|
+
const page = r?.data?.data || [];
|
|
2922
|
+
rows.push(...page);
|
|
2923
|
+
if (page.length < 100) break;
|
|
2924
|
+
}
|
|
2925
|
+
const items = rows.map((x) => {
|
|
2926
|
+
const nk = DIGITAL_PLAN_NAME_KEYS.find((k) => String(x[k] || "").trim());
|
|
2927
|
+
return { id: String(x.form_data_id || x.id || ""), name: String(nk ? x[nk] : "").trim() };
|
|
2928
|
+
}).filter((x) => x.id);
|
|
2929
|
+
if (!items.length) return { available: false, items: [], reason: "\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D\u6682\u65E0\u53EF\u9009\u65B9\u6848" };
|
|
2930
|
+
return { available: true, items };
|
|
2931
|
+
}
|
|
2932
|
+
function pickDigitalPlanForWrite(items, key) {
|
|
2933
|
+
const k = String(key || "").trim();
|
|
2934
|
+
if (!k) return { plan: null, ambiguous: [] };
|
|
2935
|
+
const byId = items.filter((x) => x.id === k);
|
|
2936
|
+
if (byId.length === 1) return { plan: byId[0], ambiguous: [] };
|
|
2937
|
+
const byExact = items.filter((x) => x.name === k);
|
|
2938
|
+
if (byExact.length === 1) return { plan: byExact[0], ambiguous: [] };
|
|
2939
|
+
const byLike = items.filter((x) => x.name.includes(k));
|
|
2940
|
+
if (byLike.length === 1) return { plan: byLike[0], ambiguous: [] };
|
|
2941
|
+
return { plan: null, ambiguous: byLike };
|
|
2942
|
+
}
|
|
3880
2943
|
async function buildInterviewPlan(env, cache, args) {
|
|
3881
2944
|
const host = env.host;
|
|
3882
2945
|
const talentId = requiredString(args, "talentId", "talent_id_required", "\u4EBA\u624D ID");
|
|
3883
2946
|
if (!/^\d+$/.test(talentId)) throw ehrValidationError("talent_id_invalid", "talentId \u5FC5\u987B\u662F\u6570\u5B57 ID");
|
|
3884
|
-
const interviewer = requiredString(args, "interviewer", "interviewer_required", "\u9762\u8BD5\u5B98\u59D3\u540D");
|
|
3885
2947
|
const type = typeof args.type === "string" && args.type.trim() ? args.type.trim() : "\u73B0\u573A\u9762\u8BD5";
|
|
3886
2948
|
if (!INTERVIEW_TYPES.includes(type)) {
|
|
3887
2949
|
throw ehrValidationError("enum_invalid", `type\uFF08\u9762\u8BD5\u65B9\u5F0F\uFF09\u53D6\u503C\u5FC5\u987B\u662F ${INTERVIEW_TYPES.join(" / ")} \u4E4B\u4E00`);
|
|
3888
2950
|
}
|
|
2951
|
+
const isAI = type === "AI\u9762\u8BD5";
|
|
3889
2952
|
const session = typeof args.session === "string" && args.session.trim() ? args.session.trim() : "\u521D\u8BD5";
|
|
3890
2953
|
const candidate = await resolveCandidateForWrite(host, cache, talentId);
|
|
3891
2954
|
const positionId = args.positionId ? String(args.positionId) : candidate.positionId;
|
|
@@ -3914,9 +2977,69 @@ async function buildInterviewPlan(env, cache, args) {
|
|
|
3914
2977
|
if (!sessionOptionId) {
|
|
3915
2978
|
throw ehrValidationError("enum_invalid", `\u9762\u8BD5\u8F6E\u6B21\u300C${session}\u300D\u4E0D\u5728\u679A\u4E3E\u4E2D\uFF08${Object.keys(sessionMap).join(" / ")}\uFF09`);
|
|
3916
2979
|
}
|
|
3917
|
-
const
|
|
3918
|
-
|
|
3919
|
-
|
|
2980
|
+
const interviewerInput = typeof args.interviewer === "string" ? args.interviewer.trim() : "";
|
|
2981
|
+
let interviewerId = null;
|
|
2982
|
+
let interviewer = interviewerInput;
|
|
2983
|
+
if (interviewerInput) {
|
|
2984
|
+
interviewerId = await resolvePersonId(host, fieldIdOf("interviewer"), interviewerInput);
|
|
2985
|
+
if (!interviewerId) {
|
|
2986
|
+
throw ehrValidationError("interviewer_not_found", `\u9762\u8BD5\u5B98\u300C${interviewerInput}\u300D\u89E3\u6790\u4E0D\u5230 userId\uFF08browser/complete/resource \u65E0\u5339\u914D\uFF09`);
|
|
2987
|
+
}
|
|
2988
|
+
} else {
|
|
2989
|
+
const me = await resolveCurrentUserForWrite(host);
|
|
2990
|
+
if (!me) {
|
|
2991
|
+
throw ehrValidationError("interviewer_unresolved", "\u672A\u6307\u5B9A\u9762\u8BD5\u5B98\uFF0C\u4E14\u65E0\u6CD5\u89E3\u6790\u5F53\u524D\u767B\u5F55\u4EBA\uFF08teamsCheck \u5931\u8D25\uFF09\uFF1B\u8BF7\u7528 interviewer \u53C2\u6570\u6307\u5B9A");
|
|
2992
|
+
}
|
|
2993
|
+
interviewerId = await resolvePersonId(host, fieldIdOf("interviewer"), me.name);
|
|
2994
|
+
if (!interviewerId) {
|
|
2995
|
+
throw ehrValidationError(
|
|
2996
|
+
"interviewer_unresolved",
|
|
2997
|
+
`\u672A\u6307\u5B9A\u9762\u8BD5\u5B98\uFF0C\u5F53\u524D\u767B\u5F55\u4EBA\u300C${me.name}\u300D\u5728\u4EBA\u5458\u5B57\u6BB5\u4E2D\u89E3\u6790\u4E0D\u5230\uFF1B\u8BF7\u7528 interviewer \u53C2\u6570\u6307\u5B9A`
|
|
2998
|
+
);
|
|
2999
|
+
}
|
|
3000
|
+
interviewer = me.name;
|
|
3001
|
+
}
|
|
3002
|
+
let aiPlan = null;
|
|
3003
|
+
let aiPlans = [];
|
|
3004
|
+
let email = String(args.email || "").trim() || candidate.email;
|
|
3005
|
+
const mobile = candidate.mobile;
|
|
3006
|
+
if (isAI) {
|
|
3007
|
+
const digitalFid = fieldIdOf("digital_id");
|
|
3008
|
+
if (!digitalFid) {
|
|
3009
|
+
throw ehrValidationError("recruit_field_missing", "\u9762\u8BD5\u8BA1\u5212\u8868\u5355\u7F3A\u5C11\u300CAI\u9762\u8BD5\u65B9\u6848\u300D\u5B57\u6BB5\uFF08digital_id\uFF09\uFF0C\u65E0\u6CD5\u5B89\u6392 AI \u9762\u8BD5");
|
|
3010
|
+
}
|
|
3011
|
+
const layoutId = await fetchLayoutIdForForm(host, formId);
|
|
3012
|
+
const plans = await listDigitalPlansForWrite(host, cache, formId, layoutId, digitalFid);
|
|
3013
|
+
aiPlans = plans.items;
|
|
3014
|
+
if (!plans.available) {
|
|
3015
|
+
throw ehrValidationError(
|
|
3016
|
+
"ai_plan_unavailable",
|
|
3017
|
+
`AI \u9762\u8BD5\u5FC5\u987B\u9009\u62E9\u300CAI\u9762\u8BD5\u65B9\u6848\u300D\uFF0C\u4F46${plans.reason || "\u6682\u65E0\u53EF\u9009\u65B9\u6848"}\uFF1B\u8BF7\u5148\u5728\u8BE5\u73AF\u5883\u7EF4\u62A4\u300C\u9762\u8BD5\u6570\u5B57\u4EBA\u914D\u7F6E\u300D`
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
const wanted = typeof args.aiPlan === "string" && args.aiPlan.trim() ? args.aiPlan.trim() : AI_DEFAULT_PLAN_NAME;
|
|
3021
|
+
const picked = pickDigitalPlanForWrite(aiPlans, wanted);
|
|
3022
|
+
if (picked.plan) {
|
|
3023
|
+
aiPlan = picked.plan;
|
|
3024
|
+
} else if (picked.ambiguous.length > 1) {
|
|
3025
|
+
throw ehrValidationError(
|
|
3026
|
+
"ai_plan_ambiguous",
|
|
3027
|
+
`AI\u9762\u8BD5\u65B9\u6848\u300C${wanted}\u300D\u547D\u4E2D\u591A\u4E2A\uFF1A${picked.ambiguous.map((x) => x.name).join("\u3001")}\uFF0C\u8BF7\u7528 aiPlan \u6307\u660E\u5177\u4F53\u65B9\u6848`,
|
|
3028
|
+
{ candidates: picked.ambiguous }
|
|
3029
|
+
);
|
|
3030
|
+
} else {
|
|
3031
|
+
throw ehrValidationError(
|
|
3032
|
+
"ai_plan_not_found",
|
|
3033
|
+
`\u672A\u627E\u5230 AI\u9762\u8BD5\u65B9\u6848\u300C${wanted}\u300D\uFF0C\u8BF7\u7528 aiPlan \u4ECE\u5019\u9009\u4E2D\u6307\u5B9A\uFF08\u5019\u9009\uFF1A${aiPlans.map((x) => x.name).join("\u3001")}\uFF09`,
|
|
3034
|
+
{ candidates: aiPlans }
|
|
3035
|
+
);
|
|
3036
|
+
}
|
|
3037
|
+
if (!email) {
|
|
3038
|
+
throw ehrValidationError("email_required", "AI \u9762\u8BD5\u8981\u6C42\u586B\u5199\u5019\u9009\u4EBA\u90AE\u7BB1\uFF1A\u4EBA\u624D\u8D44\u6599\u91CC\u6CA1\u6709\u90AE\u7BB1\uFF0C\u8BF7\u7528 email \u53C2\u6570\u63D0\u4F9B");
|
|
3039
|
+
}
|
|
3040
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
|
3041
|
+
throw ehrValidationError("email_invalid", `\u5019\u9009\u4EBA\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E\uFF1A${email}`);
|
|
3042
|
+
}
|
|
3920
3043
|
}
|
|
3921
3044
|
const window = defaultInterviewWindow();
|
|
3922
3045
|
const start = typeof args.startTime === "string" && args.startTime.trim() ? args.startTime.trim() : window.start;
|
|
@@ -3934,7 +3057,10 @@ async function buildInterviewPlan(env, cache, args) {
|
|
|
3934
3057
|
{ formField: { id: fieldIdOf("interviewer") }, dataOptions: [{ optionId: interviewerId, content: interviewer }] },
|
|
3935
3058
|
{ formField: { id: fieldIdOf("position_manage_id") }, dataOptions: [{ optionId: positionId, content: candidate.positionName }] },
|
|
3936
3059
|
{ formField: { id: fieldIdOf("talent_id") }, dataOptions: [{ optionId: talentId, content: candidate.name }] },
|
|
3937
|
-
{ formField: { id: fieldIdOf("candidate_manage_id") }, dataOptions: [{ optionId: candidate.candidateManageId, content: candidate.candidateManageId }] }
|
|
3060
|
+
{ formField: { id: fieldIdOf("candidate_manage_id") }, dataOptions: [{ optionId: candidate.candidateManageId, content: candidate.candidateManageId }] },
|
|
3061
|
+
...mobile ? [{ formField: { id: fieldIdOf("mobile") }, content: mobile }] : [],
|
|
3062
|
+
...email ? [{ formField: { id: fieldIdOf("email") }, content: email }] : [],
|
|
3063
|
+
...aiPlan ? [{ formField: { id: fieldIdOf("digital_id") }, dataOptions: [{ optionId: aiPlan.id, content: aiPlan.name }] }] : []
|
|
3938
3064
|
];
|
|
3939
3065
|
return {
|
|
3940
3066
|
formId,
|
|
@@ -3943,13 +3069,20 @@ async function buildInterviewPlan(env, cache, args) {
|
|
|
3943
3069
|
candidateName: candidate.name,
|
|
3944
3070
|
positionName: candidate.positionName,
|
|
3945
3071
|
interviewTime: `${start} ~ ${end}`,
|
|
3946
|
-
interviewer
|
|
3072
|
+
interviewer,
|
|
3073
|
+
email: email || void 0,
|
|
3074
|
+
mobile: mobile || void 0,
|
|
3075
|
+
isAIInterview: isAI,
|
|
3076
|
+
aiPlan,
|
|
3077
|
+
aiPlans: isAI ? aiPlans : void 0
|
|
3947
3078
|
};
|
|
3948
3079
|
}
|
|
3949
3080
|
var interviewArrangeSchema = {
|
|
3950
3081
|
talentId: { type: "string", pattern: "^\\d+$", description: "\u4EBA\u624D ID\uFF08candidate.search \u8FD4\u56DE\u7684 talentId\uFF09" },
|
|
3951
|
-
interviewer: { type: "string", description: "\u9762\u8BD5\u5B98\u59D3\u540D\uFF08\
|
|
3082
|
+
interviewer: { type: "string", description: "\u9762\u8BD5\u5B98\u59D3\u540D\uFF08\u53EF\u9009\uFF1B\u4E0D\u586B\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u4EBA\uFF09" },
|
|
3952
3083
|
type: { type: "string", enum: [...INTERVIEW_TYPES], description: "\u9762\u8BD5\u65B9\u5F0F\uFF0C\u9ED8\u8BA4\u73B0\u573A\u9762\u8BD5" },
|
|
3084
|
+
aiPlan: { type: "string", description: "AI \u9762\u8BD5\u65B9\u6848\uFF08\u65B9\u6848\u540D\u6216 id\uFF1Btype=AI\u9762\u8BD5 \u65F6\u751F\u6548\uFF0C\u9ED8\u8BA4\u300C\u5927\u6A21\u578B\u9762\u8BD5\u300D\uFF09" },
|
|
3085
|
+
email: { type: "string", description: "\u5019\u9009\u4EBA\u90AE\u7BB1\uFF08AI \u9762\u8BD5\u5FC5\u586B\uFF1B\u4E0D\u586B\u5219\u53D6\u4EBA\u624D\u8D44\u6599\u91CC\u7684\u90AE\u7BB1\uFF09" },
|
|
3953
3086
|
session: { type: "string", description: "\u9762\u8BD5\u8F6E\u6B21\uFF08\u5982 \u521D\u8BD5/\u590D\u8BD5\uFF09\uFF0C\u9ED8\u8BA4\u521D\u8BD5\uFF1B\u987B\u5728\u679A\u4E3E\u5185" },
|
|
3954
3087
|
positionId: { type: "string", description: "\u5E94\u8058\u804C\u4F4D ID\uFF1B\u4E0D\u586B\u65F6\u4ECE\u4EBA\u624D\u5F53\u524D\u5E94\u8058\u6279\u6B21\u7EE7\u627F" },
|
|
3955
3088
|
startTime: { type: "string", pattern: "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$", description: "\u5F00\u59CB\u65F6\u95F4 YYYY-MM-DD HH:mm\uFF0C\u9ED8\u8BA4\u5F53\u524D\u65F6\u95F4" },
|
|
@@ -3965,7 +3098,7 @@ var interviewArrangePrepare = {
|
|
|
3965
3098
|
capability: "recruit",
|
|
3966
3099
|
risk: WRITE,
|
|
3967
3100
|
requiresConfirmation: true,
|
|
3968
|
-
inputSchema: schemaOf({ ...interviewArrangeSchema }, { required: ["talentId"
|
|
3101
|
+
inputSchema: schemaOf({ ...interviewArrangeSchema }, { required: ["talentId"] }),
|
|
3969
3102
|
handler: async (args, env) => {
|
|
3970
3103
|
const cache = await requireRecruitCache(env);
|
|
3971
3104
|
const plan = await buildInterviewPlan(env, cache, args);
|
|
@@ -3993,6 +3126,11 @@ var interviewArrangePrepare = {
|
|
|
3993
3126
|
session: args.session || "\u521D\u8BD5",
|
|
3994
3127
|
time: plan.interviewTime,
|
|
3995
3128
|
interviewer: plan.interviewer,
|
|
3129
|
+
...plan.isAIInterview ? {
|
|
3130
|
+
aiPlan: plan.aiPlan ? `${plan.aiPlan.name}\uFF08id=${plan.aiPlan.id}\uFF09` : "(\u672A\u6307\u5B9A)",
|
|
3131
|
+
email: plan.email || "(\u7F3A\u5931)",
|
|
3132
|
+
mobile: plan.mobile || "(\u4EBA\u624D\u8D44\u6599\u65E0\u624B\u673A\u53F7)"
|
|
3133
|
+
} : {},
|
|
3996
3134
|
notify: notify ? "\u5C06\u89E6\u53D1\u300C\u65B0\u5EFA\u65E5\u7A0B\u300D\u9762\u8BD5\u901A\u77E5\u52A8\u4F5C\u6D41\uFF08\u5916\u90E8\u901A\u77E5\uFF09" : "\u9762\u8BD5\u901A\u77E5\u9ED8\u8BA4\u4E0D\u89E6\u53D1"
|
|
3997
3135
|
},
|
|
3998
3136
|
willSubmit: { formId: plan.formId, objId: plan.objId, dataDetails: plan.dataDetails },
|
|
@@ -5747,42 +4885,106 @@ async function uploadResumeFile(env, filePath, fieldId, formId) {
|
|
|
5747
4885
|
}
|
|
5748
4886
|
return { fileid: String(fileid), name, size };
|
|
5749
4887
|
}
|
|
5750
|
-
async function
|
|
5751
|
-
|
|
5752
|
-
const
|
|
4888
|
+
async function queryTagByName(env, name) {
|
|
4889
|
+
const pageSize = 100;
|
|
4890
|
+
const bodyOf = (type) => ({ type, name, order: 8, pageSize, pageNo: 1, search: 1, tagGroup: 0, tagModules: ["ebuilderform"] });
|
|
4891
|
+
const rs = await Promise.all(
|
|
4892
|
+
[0, 1].map(
|
|
4893
|
+
(type) => env.host.request({
|
|
4894
|
+
path: "/api/my/tag/query",
|
|
4895
|
+
method: "POST",
|
|
4896
|
+
body: bodyOf(type),
|
|
4897
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
4898
|
+
}).catch(() => null)
|
|
4899
|
+
)
|
|
4900
|
+
);
|
|
4901
|
+
const items = [];
|
|
4902
|
+
let filtered = true;
|
|
4903
|
+
for (const r of rs) {
|
|
4904
|
+
const d = r?.data || {};
|
|
4905
|
+
const list = Array.isArray(d.data) ? d.data : [];
|
|
4906
|
+
const total = Number(d.total || 0);
|
|
4907
|
+
if (list.length >= pageSize && total >= pageSize) filtered = false;
|
|
4908
|
+
items.push(...list);
|
|
4909
|
+
}
|
|
4910
|
+
return { items, filtered };
|
|
4911
|
+
}
|
|
4912
|
+
async function fetchTagsOfType(env, type) {
|
|
4913
|
+
const pageSize = 100;
|
|
4914
|
+
const bodyOf = (pageNo) => ({ type, name: "", order: 8, pageSize, pageNo, search: 1, tagGroup: 0, tagModules: ["ebuilderform"] });
|
|
4915
|
+
const requestPage = (pageNo) => env.host.request({
|
|
5753
4916
|
path: "/api/my/tag/query",
|
|
5754
4917
|
method: "POST",
|
|
5755
|
-
body:
|
|
4918
|
+
body: bodyOf(pageNo),
|
|
5756
4919
|
operation: "ehr.recruit.candidate.import.apply"
|
|
5757
|
-
});
|
|
5758
|
-
const
|
|
4920
|
+
}).catch(() => null);
|
|
4921
|
+
const first = await requestPage(1);
|
|
4922
|
+
const d = first?.data || {};
|
|
4923
|
+
const rows = Array.isArray(d.data) ? [...d.data] : [];
|
|
4924
|
+
const total = Number(d.total || 0);
|
|
4925
|
+
const pages = Math.min(40, Math.max(1, Math.ceil(total / pageSize)));
|
|
4926
|
+
if (pages > 1 && rows.length) {
|
|
4927
|
+
const rest = Array.from({ length: pages - 1 }, (_, i) => i + 2);
|
|
4928
|
+
for (let i = 0; i < rest.length; i += 5) {
|
|
4929
|
+
const batch = rest.slice(i, i + 5);
|
|
4930
|
+
const rs = await Promise.all(batch.map((p) => requestPage(p)));
|
|
4931
|
+
for (const r of rs) {
|
|
4932
|
+
const list = r?.data?.data;
|
|
4933
|
+
if (Array.isArray(list)) rows.push(...list);
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
}
|
|
4937
|
+
return rows;
|
|
4938
|
+
}
|
|
4939
|
+
async function resolveTagIds(env, tagNames) {
|
|
4940
|
+
const norm = (s) => String(s == null ? "" : s).trim().toLowerCase();
|
|
4941
|
+
const uniqNames = [...new Set(tagNames.map((n) => String(n)).filter(Boolean))];
|
|
5759
4942
|
const byName = /* @__PURE__ */ new Map();
|
|
5760
|
-
|
|
5761
|
-
const name = String(row
|
|
5762
|
-
const id = row
|
|
5763
|
-
if (name
|
|
4943
|
+
const absorb = (row) => {
|
|
4944
|
+
const name = String(row?.name ?? row?.tagName ?? "").trim();
|
|
4945
|
+
const id = row?.tagId ?? row?.id;
|
|
4946
|
+
if (!name || id === void 0) return;
|
|
4947
|
+
const key = norm(name);
|
|
4948
|
+
const prev = byName.get(key);
|
|
4949
|
+
if (!prev) byName.set(key, { id: String(id), name });
|
|
4950
|
+
else if ((row?.type ?? 0) === 0) byName.set(key, { id: String(id), name });
|
|
4951
|
+
};
|
|
4952
|
+
const probes = await Promise.all(uniqNames.map((n) => queryTagByName(env, n)));
|
|
4953
|
+
const nameQueryUsable = probes.every((p) => p.filtered);
|
|
4954
|
+
if (nameQueryUsable) {
|
|
4955
|
+
for (const p of probes) for (const item of p.items) absorb(item);
|
|
4956
|
+
} else {
|
|
4957
|
+
for (const type of [0, 1]) {
|
|
4958
|
+
const rows = await fetchTagsOfType(env, type).catch(() => []);
|
|
4959
|
+
for (const item of rows) absorb(item);
|
|
4960
|
+
}
|
|
5764
4961
|
}
|
|
5765
|
-
const
|
|
5766
|
-
const
|
|
4962
|
+
const resolved = [];
|
|
4963
|
+
const found = [];
|
|
5767
4964
|
const skipped = [];
|
|
5768
4965
|
for (const name of tagNames) {
|
|
5769
|
-
const hit = byName.get(name);
|
|
4966
|
+
const hit = byName.get(norm(name));
|
|
5770
4967
|
if (!hit) {
|
|
5771
4968
|
skipped.push(name);
|
|
5772
4969
|
continue;
|
|
5773
4970
|
}
|
|
5774
|
-
|
|
5775
|
-
|
|
4971
|
+
resolved.push({ id: hit.id, name: hit.name, type: 0 });
|
|
4972
|
+
found.push(name);
|
|
5776
4973
|
}
|
|
5777
|
-
|
|
4974
|
+
return { resolved, found, skipped };
|
|
4975
|
+
}
|
|
4976
|
+
async function applyPlatformTags(env, talentId, tagNames) {
|
|
4977
|
+
if (!tagNames.length) return { applied: [], skipped: [] };
|
|
4978
|
+
const r = await resolveTagIds(env, tagNames);
|
|
4979
|
+
if (r.resolved.length) {
|
|
5778
4980
|
await env.host.request({
|
|
5779
4981
|
path: "/api/my/tag/common/batchAddEntityTag",
|
|
5780
4982
|
method: "POST",
|
|
5781
|
-
body: { tags, batchDatas: [{ entityId: talentId, module: "ebuilderform" }] },
|
|
4983
|
+
body: { tags: r.resolved, batchDatas: [{ entityId: talentId, module: "ebuilderform" }] },
|
|
5782
4984
|
operation: "ehr.recruit.candidate.import.apply"
|
|
5783
4985
|
});
|
|
5784
4986
|
}
|
|
5785
|
-
return { applied, skipped };
|
|
4987
|
+
return { applied: r.found, skipped: r.skipped };
|
|
5786
4988
|
}
|
|
5787
4989
|
async function requireCache2(env) {
|
|
5788
4990
|
if (!env.recruitContext) throw ehrValidationError("recruit_context_unavailable", "\u62DB\u8058\u4E0A\u4E0B\u6587\u52A0\u8F7D\u5668\u672A\u521D\u59CB\u5316");
|
|
@@ -5972,7 +5174,11 @@ var candidateImportPrepare = {
|
|
|
5972
5174
|
handler: async (args, env) => {
|
|
5973
5175
|
const cache = await requireCache2(env);
|
|
5974
5176
|
const plan = await buildImportPlan(env, cache, args);
|
|
5975
|
-
const
|
|
5177
|
+
const tagNames = Array.isArray(args.tags) ? args.tags.map(String).filter(Boolean) : [];
|
|
5178
|
+
const [dup, tagCheck] = await Promise.all([
|
|
5179
|
+
checkDuplicateByMobile(env, cache, plan.mobile),
|
|
5180
|
+
tagNames.length ? resolveTagIds(env, tagNames).then((rt) => ({ requested: tagNames, found: rt.found, missing: rt.skipped })).catch((error) => ({ requested: tagNames, missing: [], error: error?.message || "\u6807\u7B7E\u9884\u68C0\u5931\u8D25" })) : Promise.resolve(null)
|
|
5181
|
+
]);
|
|
5976
5182
|
if (dup.length > 1) {
|
|
5977
5183
|
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`);
|
|
5978
5184
|
}
|
|
@@ -6012,6 +5218,7 @@ var candidateImportPrepare = {
|
|
|
6012
5218
|
details: plan.details,
|
|
6013
5219
|
tags: Array.isArray(args.tags) ? args.tags : []
|
|
6014
5220
|
},
|
|
5221
|
+
...tagCheck ? { tagCheck } : {},
|
|
6015
5222
|
continuation,
|
|
6016
5223
|
expiresInSeconds: 600
|
|
6017
5224
|
});
|
|
@@ -6077,37 +5284,28 @@ var candidateImportApply = {
|
|
|
6077
5284
|
{ candidateName: payload.candidateName, telephone: payload.telephone }
|
|
6078
5285
|
);
|
|
6079
5286
|
}
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
} catch {
|
|
6103
|
-
labelMatch = "FAILED\uFF08\u4E0D\u5F71\u54CD\u5EFA\u6863\uFF0C\u53EF\u7A0D\u540E\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u89E6\u53D1\uFF09";
|
|
6104
|
-
}
|
|
6105
|
-
let tagResult = { applied: [], skipped: [] };
|
|
6106
|
-
try {
|
|
6107
|
-
tagResult = await applyPlatformTags(env, talentId, Array.isArray(payload.tags) ? payload.tags.map(String) : []);
|
|
6108
|
-
} catch (error) {
|
|
6109
|
-
tagResult = { applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] };
|
|
6110
|
-
}
|
|
5287
|
+
const batchTask = env.host.request({
|
|
5288
|
+
path: `/api/recruit/candidate/initTalentBatch?formDataId=${encodeURIComponent(talentId)}`,
|
|
5289
|
+
method: "POST",
|
|
5290
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
5291
|
+
}).then(() => ({ ok: true, note: void 0 })).catch((error) => ({
|
|
5292
|
+
ok: false,
|
|
5293
|
+
note: `\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`
|
|
5294
|
+
}));
|
|
5295
|
+
const labelTask = env.host.request({
|
|
5296
|
+
path: `/api/recruit/label/matchTalentLabel?talentId=${encodeURIComponent(talentId)}`,
|
|
5297
|
+
method: "POST",
|
|
5298
|
+
body: {},
|
|
5299
|
+
operation: "ehr.recruit.candidate.import.apply"
|
|
5300
|
+
}).then((r) => r?.data === void 0 ? "TRIGGERED" : String(r.data)).catch(() => "FAILED\uFF08\u4E0D\u5F71\u54CD\u5EFA\u6863\uFF0C\u53EF\u7A0D\u540E\u5728\u4EBA\u624D\u5361\u7247\u624B\u52A8\u89E6\u53D1\uFF09");
|
|
5301
|
+
const tagTask = applyPlatformTags(
|
|
5302
|
+
env,
|
|
5303
|
+
talentId,
|
|
5304
|
+
Array.isArray(payload.tags) ? payload.tags.map(String) : []
|
|
5305
|
+
).catch(() => ({ applied: [], skipped: Array.isArray(payload.tags) ? payload.tags.map(String) : [] }));
|
|
5306
|
+
const [batchOutcome, labelMatch, tagResult] = await Promise.all([batchTask, labelTask, tagTask]);
|
|
5307
|
+
const batchOk = batchOutcome.ok;
|
|
5308
|
+
const batchNote = batchOutcome.note;
|
|
6111
5309
|
const baseUrl = session.baseUrl.replace(/\/+$/, "");
|
|
6112
5310
|
const extra = String(cache.selfUse) === "1" ? "&recruitType=useSelf" : "";
|
|
6113
5311
|
const talentCardUrl = cache.ebdDetailPageId ? `${baseUrl}/sp/ebdpage/view/${cache.ebdDetailPageId}?talentId=${talentId}${extra}` : null;
|