weaver-work-cli 0.1.33 → 0.1.38
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-FVFY6GZN.js → archive-PDV724YK.js} +5 -4
- package/dist/chunks/{archive-oa-NW3OD4UV.js → archive-oa-4XE4MNXQ.js} +4 -3
- package/dist/chunks/{asset-7QJKMIDV.js → asset-PDL2QE2N.js} +8 -7
- package/dist/chunks/{attachment-content-OSAVA6K3.js → attachment-content-MDDGOE5E.js} +3 -3
- package/dist/chunks/{blog-I7SDPNW4.js → blog-UYR3EUXW.js} +5 -4
- package/dist/chunks/{caizhilian-O37ZIQNY.js → caizhilian-LG2X5NMF.js} +5 -4
- package/dist/chunks/{calendar-7KXE4ED3.js → calendar-FG4BAZHE.js} +4 -3
- package/dist/chunks/{chunk-Q6LWB5HX.js → chunk-6FTTSA45.js} +4 -3
- package/dist/chunks/{chunk-MQ2I5AA3.js → chunk-6LTFIFLM.js} +3 -2
- package/dist/chunks/{chunk-WRRJ4GG2.js → chunk-CORFRD7Q.js} +4 -3
- package/dist/chunks/{chunk-WY74UBJ6.js → chunk-DMV2TOMH.js} +2194 -240
- package/dist/chunks/{chunk-MEEFGWTM.js → chunk-ELYDWBZJ.js} +135 -10
- package/dist/chunks/{chunk-EEWPQE3O.js → chunk-FUWVHMVV.js} +7 -6
- package/dist/chunks/{chunk-HEL5XTYI.js → chunk-GGJFMNJM.js} +26 -4
- package/dist/chunks/{chunk-KAS45KNR.js → chunk-IZUDA353.js} +1 -1
- package/dist/chunks/{chunk-2FLWXFVS.js → chunk-J7USS3ED.js} +4 -4
- package/dist/chunks/{chunk-IHUYP6LO.js → chunk-JSMFPO43.js} +1 -1
- package/dist/chunks/{chunk-RBGOMK4Y.js → chunk-KKRL3REV.js} +5 -4
- package/dist/chunks/{chunk-OCU4RLHC.js → chunk-NI6GIPIM.js} +195 -36
- package/dist/chunks/{chunk-PRHJGPMA.js → chunk-NR6RKXPA.js} +2 -2
- package/dist/chunks/{chunk-D223PTXU.js → chunk-OJQUJZQF.js} +33 -7
- package/dist/chunks/{chunk-ILMBNVSG.js → chunk-UJJD4QWF.js} +4 -3
- package/dist/chunks/{chunk-6ATGWRZM.js → chunk-UZZBA6PV.js} +177 -14
- package/dist/chunks/{chunk-GFPXQIY2.js → chunk-VRYHGG6O.js} +2 -2
- package/dist/chunks/{chunk-NHA62QD7.js → chunk-XJY7G4DD.js} +3 -3
- package/dist/chunks/{chunk-VBCFFFGT.js → chunk-Z32KWY6G.js} +4 -1
- package/dist/chunks/{conflict-SFNEVJY5.js → conflict-BQZEQ4SP.js} +2 -2
- package/dist/chunks/contract-XIRAFTEV.js +9111 -0
- package/dist/chunks/{cowork-CKWYHXYB.js → cowork-BLG62BL2.js} +46 -26
- package/dist/chunks/{ebuilder-form-KOLJRVZD.js → ebuilder-form-NUKG5QW4.js} +3 -3
- package/dist/chunks/{ehr-WFOC3B4D.js → ehr-2STW5ILH.js} +174 -10
- package/dist/chunks/{esb-LJZTN663.js → esb-UUDQUNKY.js} +4 -4
- package/dist/chunks/{fna-F7QRIIZC.js → fna-6RCY4NU5.js} +15 -9
- package/dist/chunks/{host-VQ6JJXGQ.js → host-7RXEDMAH.js} +3 -3
- package/dist/chunks/{host-KXPTEWFS.js → host-EJZFROU3.js} +3 -3
- package/dist/chunks/{host-BCGUVEWX.js → host-FWDOSRH5.js} +3 -3
- package/dist/chunks/{host-DGE2TZD4.js → host-RHM3NPXV.js} +3 -3
- package/dist/chunks/{host-BQBRHVR3.js → host-UFF33TWJ.js} +3 -3
- package/dist/chunks/{hrm-NI6XAKW5.js → hrm-PKJ6ELSH.js} +3 -3
- package/dist/chunks/{im-7TRTF3KT.js → im-YJAXS7CO.js} +3 -3
- package/dist/chunks/{invoice-AOXWJKYT.js → invoice-HWVSXGX6.js} +3 -3
- package/dist/chunks/{jiuchuanhui-7NQWEZAW.js → jiuchuanhui-L7VKILZB.js} +4 -3
- package/dist/chunks/{lazy-dispatch-RNS4EE4S.js → lazy-dispatch-NMYEIHRH.js} +4 -4
- package/dist/chunks/{mail-VDHJAB4O.js → mail-B42RRU7G.js} +46 -24
- package/dist/chunks/{meeting-GA7XCNNP.js → meeting-CFYVBJSS.js} +77 -12
- package/dist/chunks/{okr-TQIRERPQ.js → okr-GCLF6V7W.js} +4 -3
- package/dist/chunks/{plan-4RY4LN2P.js → plan-ZVL7GBRI.js} +4 -3
- package/dist/chunks/{project-D6XT2OC5.js → project-4YWAAE2K.js} +4 -3
- package/dist/chunks/{registry-QKMI43Q6.js → registry-EP4VTHZS.js} +8 -8
- package/dist/chunks/{registry-JHRIDQ3A.js → registry-FRJ6H7BT.js} +4 -4
- package/dist/chunks/{registry-VOGKFFTR.js → registry-SG2PGVCF.js} +2 -2
- package/dist/chunks/{room-recommend-D4EUOOWY.js → room-recommend-R3JVUUAC.js} +4 -4
- package/dist/chunks/{schedule-XPFBHPCV.js → schedule-NIJBTYDO.js} +4 -4
- package/dist/chunks/{workflow-HLBZRWIY.js → workflow-BB24DFBY.js} +11 -4
- package/dist/index.js +31 -26
- package/dist/internal/e10/auth-recovery.js +114 -1
- package/dist/internal/e10/client.js +16 -2
- package/dist/internal/e10/fetch-timing.js +31 -0
- package/dist/internal/e10/request-runtime.js +108 -7
- package/dist/shortcuts/archive/host.js +3 -2
- package/dist/shortcuts/archive-oa/host.js +2 -1
- package/dist/shortcuts/asset/host.js +6 -5
- package/dist/shortcuts/blog/host.js +3 -2
- package/dist/shortcuts/caizhilian/host.js +3 -2
- package/dist/shortcuts/calendar/host.js +2 -1
- package/dist/shortcuts/contract/host.js +2 -1
- package/dist/shortcuts/cowork/host.js +10 -1
- package/dist/shortcuts/cowork/operations/types.js +17 -2
- package/dist/shortcuts/ebuilder-form/host.js +3 -1
- package/dist/shortcuts/ehr/host.js +2 -1
- package/dist/shortcuts/ehr/operations/recruit-write.js +35 -0
- package/dist/shortcuts/ehr/operations/recruit.js +147 -0
- package/dist/shortcuts/esb/host.js +2 -1
- package/dist/shortcuts/fna/host.js +2 -1
- package/dist/shortcuts/fna/operations/expense-chart.js +19 -7
- package/dist/shortcuts/hrm/host.js +2 -1
- package/dist/shortcuts/im/host.js +3 -2
- package/dist/shortcuts/index.js +5 -0
- package/dist/shortcuts/invoice/host.js +5 -4
- package/dist/shortcuts/jiuchuanhui/host.js +2 -1
- package/dist/shortcuts/mail/host.js +10 -1
- package/dist/shortcuts/mail/operations/types.js +17 -2
- package/dist/shortcuts/meeting/host.js +3 -2
- package/dist/shortcuts/meeting/index.js +79 -1
- package/dist/shortcuts/meeting/invitation/text.js +71 -0
- package/dist/shortcuts/meeting/manifest.js +10 -0
- package/dist/shortcuts/meeting/operations/eb/catalog.js +5 -0
- package/dist/shortcuts/meeting/operations/eb/conflict.js +6 -1
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +2105 -169
- package/dist/shortcuts/meeting/operations/eb/crm-search.js +478 -0
- package/dist/shortcuts/meeting/operations/eb/factory.js +161 -8
- package/dist/shortcuts/meeting/operations/eb/index.js +2 -0
- package/dist/shortcuts/meeting/operations/eb/room-recommend.js +36 -2
- package/dist/shortcuts/meeting/operations/eb-fallback.js +4 -0
- package/dist/shortcuts/meeting/operations/env.js +6 -0
- package/dist/shortcuts/meeting/operations/invitation.js +200 -28
- package/dist/shortcuts/okr/host.js +2 -1
- package/dist/shortcuts/plan/host.js +2 -1
- package/dist/shortcuts/project/host.js +2 -1
- package/dist/shortcuts/workflow/endpoints.js +8 -3
- package/dist/shortcuts/workflow/operations/form.js +341 -36
- package/dist/shortcuts/workflow/operations.js +23 -1
- package/docs/ehr.md +1 -1
- package/docs/fna.md +2 -1
- package/package.json +1 -1
- package/skill-template/business-info.json +18 -0
- package/skill-template/domains/cowork.md +14 -0
- package/skills/weaver-e10-cowork/SKILL.md +101 -0
- package/skills/weaver-e10-cowork/references/cowork-read.md +90 -0
- package/skills/weaver-e10-cowork/references/cowork-write.md +131 -0
- package/skills/weaver-e10-cowork/references/safety-boundaries.md +45 -0
- package/skills/weaver-e10-jucailin/SKILL.md +21 -3
- package/skills/weaver-e10-jucailin/references/recruit-read.md +25 -0
- package/skills/weaver-e10-jucailin/references/recruit-write.md +13 -0
- package/skills/weaver-e10-jucailin/references/salary.md +15 -11
- package/skills/weaver-e10-mail/SKILL.md +12 -9
- package/skills/weaver-e10-meeting/SKILL.md +499 -300
- package/skills/weaver-e10-meeting/references/meeting-eb.md +334 -0
- package/skills/weaver-e10-meeting/references/meeting-invitation.md +64 -6
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
- package/skills/weaver-e10-qiyecheng/SKILL.md +5 -2
- package/skills/weaver-e10-qiyecheng/references/catalog.md +2 -2
- package/skills/weaver-e10-qiyecheng/references/expense-chart.md +15 -1
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +22 -21
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
|
@@ -2,28 +2,30 @@ import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
|
2
2
|
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
ebRoomRecommendOperation,
|
|
5
|
+
loadRooms,
|
|
5
6
|
recommendRooms,
|
|
6
7
|
rememberFrequentRoom
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GGJFMNJM.js";
|
|
8
9
|
import {
|
|
9
10
|
meetingEbScheduleOperations
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-J7USS3ED.js";
|
|
11
12
|
import {
|
|
12
13
|
ebMeetingWritePreflight,
|
|
13
14
|
fetchEbAppSettings,
|
|
14
15
|
findCommonFreeSlots,
|
|
15
16
|
meetingEbConflictOperations
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-XJY7G4DD.js";
|
|
17
18
|
import {
|
|
19
|
+
PENDING_MARK,
|
|
18
20
|
listMeetingAttachments,
|
|
19
21
|
meetingAttachmentContentOperations,
|
|
20
22
|
renderDocx
|
|
21
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-6LTFIFLM.js";
|
|
22
24
|
import {
|
|
23
25
|
meetingEnvOperations,
|
|
24
26
|
meetingStateDir,
|
|
25
27
|
resolveMeetingEnvMode
|
|
26
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-Z32KWY6G.js";
|
|
27
29
|
import {
|
|
28
30
|
EB_BASE,
|
|
29
31
|
EB_ENDPOINTS,
|
|
@@ -55,7 +57,7 @@ import {
|
|
|
55
57
|
toIdString,
|
|
56
58
|
verifyLease,
|
|
57
59
|
writeBody
|
|
58
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-ELYDWBZJ.js";
|
|
59
61
|
|
|
60
62
|
// src/shortcuts/meeting/operations/meetings.ts
|
|
61
63
|
function overlapsDate(beginDatetime, endDatetime, date) {
|
|
@@ -2221,7 +2223,7 @@ var meetingAttachmentAttach = {
|
|
|
2221
2223
|
if (mode === "append" && existingIds.length === 0) {
|
|
2222
2224
|
existingIds.push(...beforeIds);
|
|
2223
2225
|
}
|
|
2224
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
2226
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
2225
2227
|
const list = getMeetingOperation2("meeting.eb.meeting.list");
|
|
2226
2228
|
let fileId = incomingFileId;
|
|
2227
2229
|
let name = String(args.name ?? "").trim();
|
|
@@ -2309,7 +2311,7 @@ function textOf(value) {
|
|
|
2309
2311
|
return value === void 0 || value === null ? "" : String(value);
|
|
2310
2312
|
}
|
|
2311
2313
|
async function readMinute(env, id) {
|
|
2312
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
2314
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
2313
2315
|
const detail = getMeetingOperation2("meeting.eb.minute.detail");
|
|
2314
2316
|
const result = await detail.handler({ id }, env);
|
|
2315
2317
|
const row = result?.data?.data;
|
|
@@ -2388,7 +2390,7 @@ var meetingMinuteWriteContent = {
|
|
|
2388
2390
|
} else {
|
|
2389
2391
|
statusReason = "\u4EC5\u6E05\u7A7A\u5185\u5BB9\uFF0C\u672A\u6539\u72B6\u6001";
|
|
2390
2392
|
}
|
|
2391
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
2393
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
2392
2394
|
const prepare = getMeetingOperation2("meeting.eb.minute.update.prepare");
|
|
2393
2395
|
const apply = getMeetingOperation2("meeting.eb.minute.update.apply");
|
|
2394
2396
|
const prepared = await prepare.handler({ id, mt_id: mtId, ...patch }, env);
|
|
@@ -2518,8 +2520,8 @@ function parseLocalTime(value) {
|
|
|
2518
2520
|
return Number.isNaN(parsed.getTime()) ? null : parsed;
|
|
2519
2521
|
}
|
|
2520
2522
|
function formatStamp(d) {
|
|
2521
|
-
const
|
|
2522
|
-
return `${d.getFullYear()}-${
|
|
2523
|
+
const pad3 = (n) => String(n).padStart(2, "0");
|
|
2524
|
+
return `${d.getFullYear()}-${pad3(d.getMonth() + 1)}-${pad3(d.getDate())} ${pad3(d.getHours())}:${pad3(d.getMinutes())}:${pad3(d.getSeconds())}`;
|
|
2523
2525
|
}
|
|
2524
2526
|
function computeChatWindow(meeting, now = /* @__PURE__ */ new Date()) {
|
|
2525
2527
|
const begin = parseLocalTime(meeting.begin_datetime);
|
|
@@ -2647,16 +2649,16 @@ function buildDigest(messages, nameByUid, keepSystem, maxChars) {
|
|
|
2647
2649
|
return { transcript, kept: lines.length, dropped, truncated };
|
|
2648
2650
|
}
|
|
2649
2651
|
async function saveTranscript(ctx, mtId, transcript) {
|
|
2650
|
-
const { mkdir:
|
|
2652
|
+
const { mkdir: mkdir5, writeFile: writeFile5 } = await import("node:fs/promises");
|
|
2651
2653
|
const { join: join3 } = await import("node:path");
|
|
2652
2654
|
const { stateDir } = await import("./state-Y2XBP6YE.js");
|
|
2653
2655
|
const dir = join3(stateDir(ctx), "transcripts");
|
|
2654
|
-
await
|
|
2655
|
-
const
|
|
2656
|
+
await mkdir5(dir, { recursive: true });
|
|
2657
|
+
const pad3 = (n) => String(n).padStart(2, "0");
|
|
2656
2658
|
const now = /* @__PURE__ */ new Date();
|
|
2657
|
-
const stamp2 = `${now.getFullYear()}${
|
|
2659
|
+
const stamp2 = `${now.getFullYear()}${pad3(now.getMonth() + 1)}${pad3(now.getDate())}-${pad3(now.getHours())}${pad3(now.getMinutes())}${pad3(now.getSeconds())}`;
|
|
2658
2660
|
const filePath = join3(dir, `${mtId}-${stamp2}.txt`);
|
|
2659
|
-
await
|
|
2661
|
+
await writeFile5(filePath, transcript, "utf8");
|
|
2660
2662
|
return filePath;
|
|
2661
2663
|
}
|
|
2662
2664
|
var meetingMinuteFromGroupChat = {
|
|
@@ -2746,7 +2748,7 @@ var meetingMinuteFromGroupChat = {
|
|
|
2746
2748
|
const mtId = textOf2(args.mt_id).trim();
|
|
2747
2749
|
if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
|
|
2748
2750
|
const pipeline = ["text", "minutes", "document"].includes(args.pipeline) ? args.pipeline : "text";
|
|
2749
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
2751
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
2750
2752
|
const ctx = env.ctx;
|
|
2751
2753
|
let stepStart = Date.now();
|
|
2752
2754
|
const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
|
|
@@ -2770,7 +2772,7 @@ var meetingMinuteFromGroupChat = {
|
|
|
2770
2772
|
}
|
|
2771
2773
|
mark("readMeeting", stepStart);
|
|
2772
2774
|
const pullStart = Date.now();
|
|
2773
|
-
const { createImHost } = await import("./host-
|
|
2775
|
+
const { createImHost } = await import("./host-RHM3NPXV.js");
|
|
2774
2776
|
const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
|
|
2775
2777
|
const { getImOperation } = await import("./registry-OZSMDVPP.js");
|
|
2776
2778
|
const imEnv = { ctx, host: createImHost(ctx), continuation: createImContinuationSigner(ctx) };
|
|
@@ -2838,9 +2840,9 @@ var meetingMinuteFromGroupChat = {
|
|
|
2838
2840
|
const extraSections = [];
|
|
2839
2841
|
for (const file of extraFiles) {
|
|
2840
2842
|
try {
|
|
2841
|
-
const { readFile:
|
|
2842
|
-
const buffer = await
|
|
2843
|
-
const { extractText } = await import("./attachment-content-
|
|
2843
|
+
const { readFile: readFile5 } = await import("node:fs/promises");
|
|
2844
|
+
const buffer = await readFile5(file);
|
|
2845
|
+
const { extractText } = await import("./attachment-content-MDDGOE5E.js");
|
|
2844
2846
|
const extracted = extractText(buffer, file, "");
|
|
2845
2847
|
if (extracted.text.trim()) {
|
|
2846
2848
|
extraSections.push(`\u3010\u6750\u6599\uFF1A${file.split(/[\\/]/).pop() ?? file}\u3011
|
|
@@ -2967,9 +2969,9 @@ ${groupTranscript}` : ""
|
|
|
2967
2969
|
if (!employeeId) {
|
|
2968
2970
|
warnings.push("\u672A\u53D6\u5230 ESB \u89E6\u53D1\u4EBA id\uFF08employeeId\uFF09\uFF0C\u5DF2\u8DF3\u8FC7\u540E\u7EED ESB \u8C03\u7528");
|
|
2969
2971
|
} else {
|
|
2970
|
-
const { createEsbHost } = await import("./host-
|
|
2972
|
+
const { createEsbHost } = await import("./host-FWDOSRH5.js");
|
|
2971
2973
|
const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
|
|
2972
|
-
const { getEsbOperation } = await import("./registry-
|
|
2974
|
+
const { getEsbOperation } = await import("./registry-FRJ6H7BT.js");
|
|
2973
2975
|
const esbEnv = { ctx, host: createEsbHost(ctx), continuation: createEsbContinuationSigner(ctx) };
|
|
2974
2976
|
const prepareOp = getEsbOperation("esb.trigger.prepare");
|
|
2975
2977
|
const applyOp = getEsbOperation("esb.trigger.apply");
|
|
@@ -3153,7 +3155,7 @@ var meetingDecisionNotifyGroup = {
|
|
|
3153
3155
|
const warnings = [];
|
|
3154
3156
|
const mtId = textOf3(args.mt_id).trim();
|
|
3155
3157
|
if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
|
|
3156
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
3158
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
3157
3159
|
const ctx = env.ctx;
|
|
3158
3160
|
const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
|
|
3159
3161
|
{ mt_id: mtId, pageNo: 1, pageSize: 1 },
|
|
@@ -3217,7 +3219,7 @@ var meetingDecisionNotifyGroup = {
|
|
|
3217
3219
|
charCount: formatted.text.length,
|
|
3218
3220
|
text: formatted.text
|
|
3219
3221
|
};
|
|
3220
|
-
const { createImHost } = await import("./host-
|
|
3222
|
+
const { createImHost } = await import("./host-RHM3NPXV.js");
|
|
3221
3223
|
const imHost = createImHost(ctx);
|
|
3222
3224
|
let displayText = formatted.text;
|
|
3223
3225
|
let wireText = formatted.text;
|
|
@@ -3359,14 +3361,14 @@ function defaultDueDate(begin, days) {
|
|
|
3359
3361
|
const base = new Date(normalized.replace(/-/g, "/"));
|
|
3360
3362
|
const start = Number.isNaN(base.getTime()) ? /* @__PURE__ */ new Date() : base;
|
|
3361
3363
|
const due = new Date(start.getTime() + Math.max(days, 1) * 24 * 36e5);
|
|
3362
|
-
const
|
|
3363
|
-
return `${due.getFullYear()}-${
|
|
3364
|
+
const pad3 = (n) => String(n).padStart(2, "0");
|
|
3365
|
+
return `${due.getFullYear()}-${pad3(due.getMonth() + 1)}-${pad3(due.getDate())} 18:00`;
|
|
3364
3366
|
}
|
|
3365
3367
|
async function waitForTaskIncrease(fetchTotal, baseline, timeoutMs = 15e3, intervalMs = 2e3) {
|
|
3366
3368
|
const start = Date.now();
|
|
3367
3369
|
let total = baseline;
|
|
3368
3370
|
while (Date.now() - start < timeoutMs) {
|
|
3369
|
-
await new Promise((
|
|
3371
|
+
await new Promise((resolve6) => setTimeout(resolve6, intervalMs));
|
|
3370
3372
|
total = await fetchTotal();
|
|
3371
3373
|
if (total > baseline) return { total, waitedMs: Date.now() - start, increased: true };
|
|
3372
3374
|
}
|
|
@@ -3455,7 +3457,7 @@ var meetingPipelineRun = {
|
|
|
3455
3457
|
const needsConfirm = level === "tasks" || level === "notify";
|
|
3456
3458
|
const confirmed = args.confirm === true;
|
|
3457
3459
|
const executedLevel = needsConfirm && !confirmed ? "document" : level;
|
|
3458
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
3460
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
3459
3461
|
const ctx = env.ctx;
|
|
3460
3462
|
let stepStart = Date.now();
|
|
3461
3463
|
const reuseMinuteId = textOf4(args.minuteId).trim();
|
|
@@ -3524,7 +3526,7 @@ var meetingPipelineRun = {
|
|
|
3524
3526
|
]);
|
|
3525
3527
|
}
|
|
3526
3528
|
stepStart = Date.now();
|
|
3527
|
-
const { createHrmHost } = await import("./host-
|
|
3529
|
+
const { createHrmHost } = await import("./host-EJZFROU3.js");
|
|
3528
3530
|
const { getHrmOperation } = await import("./registry-NYPYMZXG.js");
|
|
3529
3531
|
const hrmEnv = { ctx, host: createHrmHost(ctx) };
|
|
3530
3532
|
const queryOp = getHrmOperation("hrm.employee.query");
|
|
@@ -3562,8 +3564,8 @@ var meetingPipelineRun = {
|
|
|
3562
3564
|
})();
|
|
3563
3565
|
const beginAt = textOf4(meetingInfo.end_datetime).trim() || textOf4(meetingInfo.begin_datetime).trim() || (() => {
|
|
3564
3566
|
const now = /* @__PURE__ */ new Date();
|
|
3565
|
-
const
|
|
3566
|
-
return `${now.getFullYear()}-${
|
|
3567
|
+
const pad3 = (n) => String(n).padStart(2, "0");
|
|
3568
|
+
return `${now.getFullYear()}-${pad3(now.getMonth() + 1)}-${pad3(now.getDate())} ${pad3(now.getHours())}:${pad3(now.getMinutes())}`;
|
|
3567
3569
|
})();
|
|
3568
3570
|
const dueDays = typeof args.taskDueDays === "number" && args.taskDueDays > 0 ? args.taskDueDays : 7;
|
|
3569
3571
|
const dueAt = defaultDueDate(beginAt, dueDays);
|
|
@@ -3721,13 +3723,75 @@ var meetingPipelineRun = {
|
|
|
3721
3723
|
var meetingPipelineOperations = [meetingPipelineRun];
|
|
3722
3724
|
|
|
3723
3725
|
// src/shortcuts/meeting/operations/invitation.ts
|
|
3726
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
3724
3727
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
3725
3728
|
import { dirname, join, resolve as resolve3 } from "node:path";
|
|
3726
3729
|
import { fileURLToPath } from "node:url";
|
|
3730
|
+
|
|
3731
|
+
// src/shortcuts/meeting/invitation/text.ts
|
|
3732
|
+
function cell(value) {
|
|
3733
|
+
return String(value ?? "").replace(/\|/g, "/").replace(/\s*\r?\n\s*/g, " ").trim();
|
|
3734
|
+
}
|
|
3735
|
+
function renderInvitationMarkdown(resolver, agendaRows, options = {}) {
|
|
3736
|
+
const pending = /* @__PURE__ */ new Set();
|
|
3737
|
+
const val = (key) => {
|
|
3738
|
+
const rendered = resolver(key);
|
|
3739
|
+
if (rendered.pending) {
|
|
3740
|
+
pending.add(key);
|
|
3741
|
+
return PENDING_MARK;
|
|
3742
|
+
}
|
|
3743
|
+
return String(rendered.text ?? "").trim();
|
|
3744
|
+
};
|
|
3745
|
+
const lines = [];
|
|
3746
|
+
lines.push("# \u9080\u8BF7\u51FD");
|
|
3747
|
+
lines.push("");
|
|
3748
|
+
lines.push(`**\u5C0A\u656C\u7684 ${val("guest_org")}\uFF1A**`);
|
|
3749
|
+
lines.push("");
|
|
3750
|
+
lines.push(`${val("caller")} \u8BDA\u9080\u60A8\u53C2\u52A0\u300C${val("mt_name")}\u300D\uFF0C\u73B0\u5C06\u4F1A\u8BAE\u5B89\u6392\u901A\u77E5\u5982\u4E0B\uFF1A`);
|
|
3751
|
+
lines.push("");
|
|
3752
|
+
lines.push(`- **\u4F1A\u8BAE\u540D\u79F0**\uFF1A${val("mt_name")}`);
|
|
3753
|
+
lines.push(`- **\u4F1A\u8BAE\u65F6\u95F4**\uFF1A${val("begin_datetime")}~${val("end_datetime")}`);
|
|
3754
|
+
lines.push(`- **\u4F1A\u8BAE\u5730\u70B9**\uFF1A${val("address")}`);
|
|
3755
|
+
lines.push(`- **\u53C2\u4F1A\u4EBA\u5458**\uFF1A${val("hrm_members")}`);
|
|
3756
|
+
lines.push(`- **\u4F1A\u8BAE\u5185\u5BB9**\uFF1A${val("mt_desc")}`);
|
|
3757
|
+
lines.push("");
|
|
3758
|
+
lines.push(`**${val("begin_date")}\u4F1A\u8BAE\u8BAE\u7A0B\u5B89\u6392\uFF1A**`);
|
|
3759
|
+
lines.push("");
|
|
3760
|
+
lines.push("| \u8BAE\u7A0B\u5B89\u6392 | \u8BAE\u7A0B\u5185\u5BB9 | \u8BAE\u7A0B\u65F6\u95F4 |");
|
|
3761
|
+
lines.push("| --- | --- | --- |");
|
|
3762
|
+
if (agendaRows.length === 0) {
|
|
3763
|
+
lines.push("| \u2014 | \u6682\u65E0\u8BAE\u7A0B | \u2014 |");
|
|
3764
|
+
} else {
|
|
3765
|
+
for (const [name, content, timeRange] of agendaRows) {
|
|
3766
|
+
lines.push(`| ${cell(name) || "\u2014"} | ${cell(content) || "\u2014"} | ${cell(timeRange) || "\u2014"} |`);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
lines.push("");
|
|
3770
|
+
lines.push(val("company_name"));
|
|
3771
|
+
lines.push("");
|
|
3772
|
+
lines.push(val("issue_date"));
|
|
3773
|
+
lines.push("");
|
|
3774
|
+
lines.push("> \u6CE8\uFF1A\u4EE5\u4E0A\u4E3A\u62DF\u5B9A\u4F1A\u8BAE\u5B89\u6392\uFF0C\u5177\u4F53\u4F1A\u8BAE\u65F6\u95F4\u4E0E\u8BAE\u7A0B\u9700\u6839\u636E\u5B9E\u9645\u60C5\u51B5\u786E\u8BA4\u3002");
|
|
3775
|
+
if (options.pendingHint !== false && pending.size > 0) {
|
|
3776
|
+
lines.push("");
|
|
3777
|
+
lines.push(`> \u26A0\uFE0F \u6807 ${PENDING_MARK} \u7684\u5B57\u6BB5\u4F1A\u8BAE\u91CC\u6CA1\u6709\u503C\uFF0C\u9700\u8981\u4EBA\u5DE5\u8865\uFF1B\u8865\u5B8C\u53EF\u7528 mtId \u91CD\u65B0\u751F\u6210\u3002`);
|
|
3778
|
+
}
|
|
3779
|
+
return { markdown: lines.join("\n"), pendingFields: [...pending] };
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
// src/shortcuts/meeting/operations/invitation.ts
|
|
3727
3783
|
function templatePath() {
|
|
3728
3784
|
const override = process.env.WEAVER_MEETING_INVITATION_TEMPLATE;
|
|
3729
3785
|
if (override) return resolve3(override);
|
|
3730
3786
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
3787
|
+
let dir = here;
|
|
3788
|
+
for (let depth = 0; depth < 6; depth += 1) {
|
|
3789
|
+
const candidate = join(dir, "templates", "meeting", "invitation.docx");
|
|
3790
|
+
if (existsSync2(candidate)) return candidate;
|
|
3791
|
+
const parent = dirname(dir);
|
|
3792
|
+
if (parent === dir) break;
|
|
3793
|
+
dir = parent;
|
|
3794
|
+
}
|
|
3731
3795
|
return resolve3(here, "../../../../templates/meeting/invitation.docx");
|
|
3732
3796
|
}
|
|
3733
3797
|
var WEEKDAYS = ["\u661F\u671F\u65E5", "\u661F\u671F\u4E00", "\u661F\u671F\u4E8C", "\u661F\u671F\u4E09", "\u661F\u671F\u56DB", "\u661F\u671F\u4E94", "\u661F\u671F\u516D"];
|
|
@@ -3765,7 +3829,7 @@ function formatTimeRange(start, end) {
|
|
|
3765
3829
|
}
|
|
3766
3830
|
async function loadAgendaFromTopics(env, mtId) {
|
|
3767
3831
|
try {
|
|
3768
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
3832
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
3769
3833
|
const operation = getMeetingOperation2("meeting.eb.topic.list");
|
|
3770
3834
|
const result = await operation.handler({ mt_id: mtId, pageNo: 1, pageSize: 200 }, env);
|
|
3771
3835
|
const rows = result.data?.rows ?? [];
|
|
@@ -3862,6 +3926,65 @@ async function resolveIssuerOrganization(env, creatorId) {
|
|
|
3862
3926
|
return null;
|
|
3863
3927
|
}
|
|
3864
3928
|
}
|
|
3929
|
+
async function resolveSessionUserName(env) {
|
|
3930
|
+
try {
|
|
3931
|
+
const session = await env.host.getSession();
|
|
3932
|
+
const userId = String(session?.userId ?? "").trim();
|
|
3933
|
+
if (!userId) return "";
|
|
3934
|
+
const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
|
|
3935
|
+
const batch = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.batch");
|
|
3936
|
+
if (!batch) return "";
|
|
3937
|
+
const result = await batch.handler({ ids: [userId] }, env);
|
|
3938
|
+
const row = (result?.data?.rows ?? [])[0];
|
|
3939
|
+
return String(row?.name ?? "").trim();
|
|
3940
|
+
} catch {
|
|
3941
|
+
return "";
|
|
3942
|
+
}
|
|
3943
|
+
}
|
|
3944
|
+
var DETAIL_FALLBACK_KEYS = [
|
|
3945
|
+
"hrm_members",
|
|
3946
|
+
"mt_desc",
|
|
3947
|
+
"total_member",
|
|
3948
|
+
"caller",
|
|
3949
|
+
"contacter",
|
|
3950
|
+
"begin_datetime",
|
|
3951
|
+
"end_datetime",
|
|
3952
|
+
"other_members",
|
|
3953
|
+
"mt_creator",
|
|
3954
|
+
"topic_presenter",
|
|
3955
|
+
"mt_format",
|
|
3956
|
+
"mt_type",
|
|
3957
|
+
"video_url",
|
|
3958
|
+
"org_members",
|
|
3959
|
+
"with_secauth"
|
|
3960
|
+
];
|
|
3961
|
+
async function supplementRowFromDetail(row, mtId, env) {
|
|
3962
|
+
const isBlank = (value) => {
|
|
3963
|
+
if (value === void 0 || value === null) return true;
|
|
3964
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
3965
|
+
return String(value).trim() === "";
|
|
3966
|
+
};
|
|
3967
|
+
const missing = DETAIL_FALLBACK_KEYS.filter((key) => isBlank(row[key]));
|
|
3968
|
+
if (missing.length === 0) return { row, filled: [] };
|
|
3969
|
+
try {
|
|
3970
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
3971
|
+
const detailOperation = getMeetingOperation2("meeting.eb.meeting.detail");
|
|
3972
|
+
const result = await detailOperation.handler({ id: mtId }, env);
|
|
3973
|
+
const flat = result?.data?.data ?? result?.data ?? {};
|
|
3974
|
+
const merged = { ...row };
|
|
3975
|
+
const filled = [];
|
|
3976
|
+
for (const key of missing) {
|
|
3977
|
+
const value = flat[key];
|
|
3978
|
+
if (!isBlank(value)) {
|
|
3979
|
+
merged[key] = value;
|
|
3980
|
+
filled.push(key);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
return { row: merged, filled };
|
|
3984
|
+
} catch {
|
|
3985
|
+
return { row, filled: [] };
|
|
3986
|
+
}
|
|
3987
|
+
}
|
|
3865
3988
|
function buildResolver(row, extra, issuerOrg) {
|
|
3866
3989
|
const begin = parseDateTime(row.begin_datetime);
|
|
3867
3990
|
const end = parseDateTime(row.end_datetime);
|
|
@@ -3899,6 +4022,9 @@ function buildResolver(row, extra, issuerOrg) {
|
|
|
3899
4022
|
org_members: orgMembers,
|
|
3900
4023
|
// 落款公司全称:`extra.company_name` 可覆盖(对外开放时客户传自己的公司名)
|
|
3901
4024
|
company_name: String(extra.company_name ?? "").trim() || DEFAULT_COMPANY_NAME,
|
|
4025
|
+
// 客户单位(「尊敬的 XXX」):先看 extra(建会时由 create.flow 把参会客户名带进来),
|
|
4026
|
+
// 再看会议主表的 crm_members(部分租户会存),都没有才留【待补充】
|
|
4027
|
+
guest_org: String(extra.guest_org ?? "").trim() || flattenFieldValue(row.crm_members) || "",
|
|
3902
4028
|
// 单独暴露上级公司,模板需要「公司级落款」时可直接用
|
|
3903
4029
|
issuer_company: issuerCompany,
|
|
3904
4030
|
other_members: humanizeMembers(row.other_members),
|
|
@@ -3921,7 +4047,10 @@ function buildResolver(row, extra, issuerOrg) {
|
|
|
3921
4047
|
};
|
|
3922
4048
|
const lookup = (key) => {
|
|
3923
4049
|
if (key in derived) return derived[key];
|
|
3924
|
-
if (key in standard)
|
|
4050
|
+
if (key in standard) {
|
|
4051
|
+
const standardValue = standard[key];
|
|
4052
|
+
if (String(standardValue ?? "").trim() !== "") return standardValue;
|
|
4053
|
+
}
|
|
3925
4054
|
if (key.startsWith("extra.") && key.slice(6) in extra) return extra[key.slice(6)];
|
|
3926
4055
|
if (key in extra) return extra[key];
|
|
3927
4056
|
const raw = row[key];
|
|
@@ -3945,14 +4074,24 @@ var meetingInvitationRender = {
|
|
|
3945
4074
|
resource: "invitation",
|
|
3946
4075
|
method: "render",
|
|
3947
4076
|
action: "meeting.invitation.render",
|
|
3948
|
-
summary: "\u6309\u4F1A\u8BAE\u771F\u5B9E\u6570\u636E\u751F\u6210\u9080\u8BF7\u51FD
|
|
4077
|
+
summary: "\u6309\u4F1A\u8BAE\u771F\u5B9E\u6570\u636E\u751F\u6210\u9080\u8BF7\u51FD\uFF08\u53EA\u8BFB\uFF0C\u4E0D\u53D1\u9001\uFF09\uFF1A**\u540C\u65F6\u8FD4\u56DE docx \u4E0E\u5BF9\u8BDD\u5185\u53EF\u5C55\u793A\u7684 Markdown \u5168\u6587**\uFF08`text` \u5B57\u6BB5\uFF09\uFF0C\u4F1A\u8BDD\u91CC\u5E94\u76F4\u63A5\u628A `text` \u8D34\u51FA\u6765\uFF0C\u4E0D\u8981\u53EA\u7ED9\u6587\u4EF6\u540D\u8BA9\u4EBA\u81EA\u5DF1\u4E0B\u8F7D\uFF1B\u6570\u636E\u53D6 meeting.eb.meeting.list \u5355\u67E5\uFF1B\u8BAE\u7A0B\u6709\u8BAE\u9898\u5C31\u6309\u8BAE\u9898\u81EA\u52A8\u586B\u3001\u6CA1\u6709\u5219\u4FDD\u7559\u6A21\u677F\u793A\u4F8B\u884C\uFF1B\u53D6\u4E0D\u5230\u7684\u5B57\u6BB5\u6E32\u67D3\u6210\u3010\u5F85\u8865\u5145\u3011\uFF08docx \u91CC\u662F\u9EC4\u8272\u9AD8\u4EAE\uFF09\uFF1B\u79DF\u6237\u81EA\u5B9A\u4E49\u5B57\u6BB5\u7528 extra \u4F20\u5165",
|
|
3949
4078
|
capability: "invitation",
|
|
3950
4079
|
risk: "read",
|
|
3951
4080
|
inputSchema: {
|
|
3952
4081
|
type: "object",
|
|
3953
4082
|
additionalProperties: false,
|
|
3954
4083
|
properties: {
|
|
3955
|
-
mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF08EB \u7248 mt_detail \u4E3B\u952E\uFF09" },
|
|
4084
|
+
mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF08EB \u7248 mt_detail \u4E3B\u952E\uFF09\u3002**\u4E0E\u4E0B\u9762\u7684\u5B57\u6BB5\u4E8C\u9009\u4E00**\uFF1A\u6709 mtId \u8D70\u771F\u5B9E\u4F1A\u8BAE\u6570\u636E\uFF1B\u6CA1\u6709\u5219\u7528\u4F20\u5165\u5B57\u6BB5\u76F4\u63A5\u751F\u6210\uFF08\u6D41\u7A0B\u5EFA\u4F1A\u5BA1\u6279\u4E2D\u4E5F\u80FD\u51FA\u9080\u8BF7\u51FD\uFF09" },
|
|
4085
|
+
mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u65E0 mtId \u65F6\u5FC5\u586B\uFF09" },
|
|
4086
|
+
begin_datetime: { type: "string", description: "\u5F00\u59CB\u65F6\u95F4 `yyyy-MM-dd HH:mm`\uFF08\u65E0 mtId \u65F6\u5FC5\u586B\uFF09" },
|
|
4087
|
+
end_datetime: { type: "string", description: "\u7ED3\u675F\u65F6\u95F4 `yyyy-MM-dd HH:mm`\uFF08\u65E0 mtId \u65F6\u5EFA\u8BAE\u586B\uFF0C\u7F3A\u4E86\u7ED3\u675F\u65F6\u95F4\u4F1A\u662F\u3010\u5F85\u8865\u5145\u3011\uFF09" },
|
|
4088
|
+
address: { type: "string", description: "\u4F1A\u8BAE\u5730\u70B9/\u4F1A\u8BAE\u5BA4**\u540D\u79F0**\uFF08\u65E0 mtId \u65F6\u7528\uFF1B\u8FD9\u91CC\u8981\u4F20\u540D\u79F0\uFF0C\u4E0D\u662F id\uFF09" },
|
|
4089
|
+
hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u59D3\u540D\uFF08\u9017\u53F7/\u987F\u53F7\u5206\u9694\uFF0C\u65E0 mtId \u65F6\u7528\uFF09" },
|
|
4090
|
+
mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BAE\u9898\u6982\u8981" },
|
|
4091
|
+
org_members: { type: "string", description: "\u843D\u6B3E\u5355\u4F4D\uFF08\u4E0D\u4F20\u5219\u5C1D\u8BD5\u7528\u53D1\u8D77\u4EBA\u90E8\u95E8 / \u7559\u3010\u5F85\u8865\u5145\u3011\uFF09" },
|
|
4092
|
+
caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
|
|
4093
|
+
contacter: { type: "string", description: "\u8054\u7CFB\u4EBA" },
|
|
4094
|
+
total_member: { type: "string", description: "\u53C2\u4F1A\u4EBA\u6570" },
|
|
3956
4095
|
extra: {
|
|
3957
4096
|
type: "object",
|
|
3958
4097
|
additionalProperties: { type: "string" },
|
|
@@ -3963,41 +4102,78 @@ var meetingInvitationRender = {
|
|
|
3963
4102
|
description: "\u8F93\u51FA\u6587\u4EF6\u5B8C\u6574\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09\u3002\u7F3A\u7701\u5199\u5230 ~/.weaver-work-cli/meeting/invitations/\u9080\u8BF7\u51FD-{\u4F1A\u8BAE\u540D}-{\u65E5\u671F}.docx"
|
|
3964
4103
|
}
|
|
3965
4104
|
},
|
|
3966
|
-
required: [
|
|
4105
|
+
required: []
|
|
3967
4106
|
},
|
|
3968
4107
|
handler: async (args, env) => {
|
|
3969
4108
|
const mtId = String(args.mtId ?? "").trim();
|
|
3970
|
-
if (!mtId) {
|
|
3971
|
-
throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mtId\uFF09");
|
|
3972
|
-
}
|
|
3973
4109
|
const extra = {};
|
|
3974
4110
|
if (args.extra && typeof args.extra === "object") {
|
|
3975
4111
|
for (const [key, value] of Object.entries(args.extra)) {
|
|
3976
4112
|
if (value !== void 0 && value !== null) extra[key] = String(value);
|
|
3977
4113
|
}
|
|
3978
4114
|
}
|
|
3979
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-QKMI43Q6.js");
|
|
3980
|
-
const listOperation = getMeetingOperation2("meeting.eb.meeting.list");
|
|
3981
4115
|
let row;
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
4116
|
+
let dataSource = "meeting";
|
|
4117
|
+
let detailSupplementary = [];
|
|
4118
|
+
if (!mtId) {
|
|
4119
|
+
const mtName = String(args.mt_name ?? "").trim();
|
|
4120
|
+
const beginText = String(args.begin_datetime ?? "").trim();
|
|
4121
|
+
if (!mtName || !beginText) {
|
|
4122
|
+
throw meetingValidationError(
|
|
4123
|
+
"invitation_source_required",
|
|
4124
|
+
"\u8981\u4E48\u4F20 mtId\uFF08\u6309\u771F\u5B9E\u4F1A\u8BAE\u751F\u6210\uFF09\uFF0C\u8981\u4E48\u4F20 mt_name + begin_datetime\uFF08\u6309\u7533\u8BF7\u5355\u4FE1\u606F\u9884\u586B\u751F\u6210\uFF09"
|
|
4125
|
+
);
|
|
4126
|
+
}
|
|
4127
|
+
const session = await env.host.getSession().catch(() => null);
|
|
4128
|
+
const sessionUserId = String(session?.userId ?? "");
|
|
4129
|
+
row = {
|
|
4130
|
+
mt_name: mtName,
|
|
4131
|
+
begin_datetime: beginText,
|
|
4132
|
+
end_datetime: String(args.end_datetime ?? "").trim(),
|
|
4133
|
+
address: String(args.address ?? "").trim(),
|
|
4134
|
+
hrm_members: String(args.hrm_members ?? "").trim(),
|
|
4135
|
+
mt_desc: String(args.mt_desc ?? "").trim(),
|
|
4136
|
+
org_members: String(args.org_members ?? "").trim(),
|
|
4137
|
+
caller: String(args.caller ?? "").trim(),
|
|
4138
|
+
contacter: String(args.contacter ?? "").trim(),
|
|
4139
|
+
total_member: String(args.total_member ?? "").trim(),
|
|
4140
|
+
creator: sessionUserId
|
|
4141
|
+
};
|
|
4142
|
+
dataSource = "payload";
|
|
4143
|
+
} else {
|
|
4144
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
4145
|
+
const listOperation = getMeetingOperation2("meeting.eb.meeting.list");
|
|
4146
|
+
try {
|
|
4147
|
+
const listed = await listOperation.handler({ mt_id: mtId, pageNo: 1, pageSize: 1 }, env);
|
|
4148
|
+
const rows = listed.data?.rows ?? [];
|
|
4149
|
+
row = rows[0]?.mainTable ?? rows[0];
|
|
4150
|
+
} catch (error) {
|
|
4151
|
+
throw meetingValidationError(
|
|
4152
|
+
"invitation_source_unavailable",
|
|
4153
|
+
`\u8BFB\u53D6\u4F1A\u8BAE\u6570\u636E\u5931\u8D25\uFF08\u9080\u8BF7\u51FD\u5F53\u524D\u4F9D\u8D56 EB \u7248\u4F1A\u8BAE\u5217\u8868\uFF09\uFF1A${error instanceof Error ? error.message : String(error)}`,
|
|
4154
|
+
{ mtId }
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4157
|
+
if (!row) {
|
|
4158
|
+
throw meetingValidationError("not_found", `\u672A\u627E\u5230\u4F1A\u8BAE id=${mtId}\uFF0C\u6216\u5F53\u524D\u8D26\u53F7\u65E0\u6743\u9650\u67E5\u770B`, { mtId });
|
|
4159
|
+
}
|
|
4160
|
+
const supplement = await supplementRowFromDetail(row, mtId, env);
|
|
4161
|
+
row = supplement.row;
|
|
4162
|
+
detailSupplementary = supplement.filled;
|
|
4163
|
+
}
|
|
4164
|
+
let callerFromSession = false;
|
|
4165
|
+
if (!String(row.caller ?? "").trim() && !String(row.mt_creator ?? "").trim()) {
|
|
4166
|
+
const sessionName = await resolveSessionUserName(env);
|
|
4167
|
+
if (sessionName) {
|
|
4168
|
+
row = { ...row, caller: sessionName };
|
|
4169
|
+
callerFromSession = true;
|
|
4170
|
+
}
|
|
3995
4171
|
}
|
|
3996
4172
|
const creatorId = String(row.creator ?? "").trim();
|
|
3997
4173
|
const needsIssuerOrg = !String(row.org_members ?? "").trim() && creatorId !== "";
|
|
3998
4174
|
const issuerOrg = needsIssuerOrg ? await resolveIssuerOrganization(env, creatorId) : null;
|
|
3999
4175
|
const { resolver, orgSource } = buildResolver(row, extra, issuerOrg);
|
|
4000
|
-
let agendaRows = await loadAgendaFromTopics(env, mtId);
|
|
4176
|
+
let agendaRows = dataSource === "meeting" && mtId ? await loadAgendaFromTopics(env, mtId) : [];
|
|
4001
4177
|
let agendaSource = agendaRows.length > 0 ? "meeting.topic" : "template";
|
|
4002
4178
|
if (agendaRows.length === 0) {
|
|
4003
4179
|
const fromExtra = parseAgendaFromExtra(extra.agenda);
|
|
@@ -4019,6 +4195,7 @@ var meetingInvitationRender = {
|
|
|
4019
4195
|
const rendered = renderDocx(template, resolver, {
|
|
4020
4196
|
agenda: { headerKeyword: AGENDA_HEADER_KEYWORD, rows: agendaRows }
|
|
4021
4197
|
});
|
|
4198
|
+
const textVersion = renderInvitationMarkdown(resolver, agendaRows);
|
|
4022
4199
|
const begin = parseDateTime(row.begin_datetime);
|
|
4023
4200
|
const dateTag = begin ? `${begin.getFullYear()}${pad(begin.getMonth() + 1)}${pad(begin.getDate())}` : "\u672A\u77E5\u65E5\u671F";
|
|
4024
4201
|
const fileName = `\u9080\u8BF7\u51FD-${safeFileName(String(row.mt_name ?? ""))}-${dateTag}.docx`;
|
|
@@ -4026,6 +4203,11 @@ var meetingInvitationRender = {
|
|
|
4026
4203
|
await mkdir2(dirname(target), { recursive: true });
|
|
4027
4204
|
await writeFile2(target, rendered.buffer);
|
|
4028
4205
|
const warnings = [];
|
|
4206
|
+
if (dataSource === "payload") {
|
|
4207
|
+
warnings.push(
|
|
4208
|
+
"\u672C\u9080\u8BF7\u51FD\u6309**\u7533\u8BF7\u5355\u5DF2\u77E5\u4FE1\u606F**\u9884\u751F\u6210\uFF08\u4F1A\u8BAE\u53EF\u80FD\u8FD8\u5728\u5BA1\u6279\u4E2D\u3001\u5C1A\u672A\u751F\u6210\uFF09\uFF0C\u5C5E\u4E8E**\u9884\u7F6E\u51FD**\uFF1A\u8BF7\u4E0B\u8F7D\u540E\u4EBA\u5DE5\u6838\u5BF9/\u4FEE\u6539\u518D\u81EA\u884C\u53D1\u9001\u3002\u4F1A\u8BAE\u6B63\u5F0F\u751F\u6210\u540E\u53EF\u7528 mtId \u91CD\u65B0\u751F\u6210\u4E00\u7248\u62FF\u5230\u5B8C\u6574\u5B57\u6BB5\u3002"
|
|
4209
|
+
);
|
|
4210
|
+
}
|
|
4029
4211
|
if (rendered.pending.length > 0) {
|
|
4030
4212
|
warnings.push(
|
|
4031
4213
|
`\u4EE5\u4E0B\u5B57\u6BB5\u53D6\u4E0D\u5230\u503C\uFF0C\u5DF2\u6E32\u67D3\u6210\u9EC4\u8272\u9AD8\u4EAE\u3010\u5F85\u8865\u5145\u3011\uFF0C\u8BF7\u4EBA\u5DE5\u8865\u5145\uFF1A${rendered.pending.join("\u3001")}`
|
|
@@ -4050,14 +4232,21 @@ var meetingInvitationRender = {
|
|
|
4050
4232
|
filePath: target,
|
|
4051
4233
|
fileName,
|
|
4052
4234
|
bytes: rendered.buffer.length,
|
|
4053
|
-
meetingId: mtId,
|
|
4235
|
+
meetingId: mtId || null,
|
|
4054
4236
|
meetingName: String(row.mt_name ?? ""),
|
|
4237
|
+
// meeting=按真实会议数据;payload=按申请单字段预生成(会议可能还没生成,属预置函)
|
|
4238
|
+
dataSource,
|
|
4239
|
+
// 列表单查丢字段时,用 detail 补回来的字段名(有值 = 邀请函用的是合并后的数据)
|
|
4240
|
+
detailSupplemented: detailSupplementary,
|
|
4241
|
+
// 对话内展示用的 Markdown 全文(与 docx 同源)。上层应直接把这段贴进回复正文,
|
|
4242
|
+
// ⛔ 不要只丢一个 filePath 让用户自己去本地打开看内容。
|
|
4243
|
+
text: textVersion.markdown,
|
|
4055
4244
|
filledFields: rendered.filled,
|
|
4056
4245
|
pendingFields: rendered.pending,
|
|
4057
4246
|
// 落款单位的实际来源,便于调用方判断是否需要人工改写
|
|
4058
4247
|
orgSource,
|
|
4059
|
-
// 召集人来源:meeting.caller=会议自己填的 / meeting.mt_creator=回落到创建人 / none=都没有
|
|
4060
|
-
callerSource: String(row.caller ?? "").trim() ? "meeting.caller" : String(row.mt_creator ?? "").trim() ? "meeting.mt_creator" : "none",
|
|
4248
|
+
// 召集人来源:meeting.caller=会议自己填的 / meeting.mt_creator=回落到创建人 / session.user=回落到发起人本人 / none=都没有
|
|
4249
|
+
callerSource: callerFromSession ? "session.user" : String(row.caller ?? "").trim() ? "meeting.caller" : String(row.mt_creator ?? "").trim() ? "meeting.mt_creator" : "none",
|
|
4061
4250
|
// 议程来源:meeting.topic=按议题自动填 / extra=调用方传入 / template=保留模板示例行
|
|
4062
4251
|
agendaSource,
|
|
4063
4252
|
agendaRows: agendaRows.length,
|
|
@@ -4354,7 +4543,7 @@ function buildCodewords(bytes, version, ecc) {
|
|
|
4354
4543
|
for (const byte of bytes) appendBits(byte, 8);
|
|
4355
4544
|
appendBits(0, Math.min(4, capacityBits - bits.length));
|
|
4356
4545
|
appendBits(0, (8 - bits.length % 8) % 8);
|
|
4357
|
-
for (let
|
|
4546
|
+
for (let pad3 = 236; bits.length < capacityBits; pad3 ^= 236 ^ 17) appendBits(pad3, 8);
|
|
4358
4547
|
const dataCodewords = new Array(bits.length / 8).fill(0);
|
|
4359
4548
|
bits.forEach((bit, i) => {
|
|
4360
4549
|
dataCodewords[i >>> 3] |= bit << 7 - (i & 7);
|
|
@@ -4540,8 +4729,8 @@ function renderQrSvg(matrix, options = {}) {
|
|
|
4540
4729
|
var ECC_LEVELS = ["L", "M", "Q", "H"];
|
|
4541
4730
|
function stamp() {
|
|
4542
4731
|
const now = /* @__PURE__ */ new Date();
|
|
4543
|
-
const
|
|
4544
|
-
return `${now.getFullYear()}${
|
|
4732
|
+
const pad3 = (n) => String(n).padStart(2, "0");
|
|
4733
|
+
return `${now.getFullYear()}${pad3(now.getMonth() + 1)}${pad3(now.getDate())}-${pad3(now.getHours())}${pad3(now.getMinutes())}${pad3(now.getSeconds())}`;
|
|
4545
4734
|
}
|
|
4546
4735
|
function safeName(input) {
|
|
4547
4736
|
return input.replace(/[\\/:*?"<>|\s]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
|
|
@@ -4706,7 +4895,7 @@ var meetingSummaryGet = {
|
|
|
4706
4895
|
const mtId = textOf5(args.mt_id).trim();
|
|
4707
4896
|
if (!mtId) throw meetingValidationError("mt_id_required", "\u5FC5\u987B\u63D0\u4F9B\u4F1A\u8BAE id\uFF08mt_id\uFF09");
|
|
4708
4897
|
const ctx = env.ctx;
|
|
4709
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
4898
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
4710
4899
|
const warnings = [];
|
|
4711
4900
|
const timings = {};
|
|
4712
4901
|
const include = Array.isArray(args.include) && args.include.length > 0 ? args.include.filter((item) => ALL_SECTIONS.includes(item)) : ALL_SECTIONS;
|
|
@@ -4842,7 +5031,7 @@ var meetingSummaryGet = {
|
|
|
4842
5031
|
warnings.push("\u8BE5\u4F1A\u8BAE\u6CA1\u6709\u5173\u8054\u7FA4\u804A\uFF08imchat_groupid \u4E3A\u7A7A\uFF09\uFF0Cchat \u6BB5\u4E3A null");
|
|
4843
5032
|
} else {
|
|
4844
5033
|
try {
|
|
4845
|
-
const { createImHost } = await import("./host-
|
|
5034
|
+
const { createImHost } = await import("./host-RHM3NPXV.js");
|
|
4846
5035
|
const { createImContinuationSigner } = await import("./continuation-2CKSBLA6.js");
|
|
4847
5036
|
const { getImOperation } = await import("./registry-OZSMDVPP.js");
|
|
4848
5037
|
const imEnv = {
|
|
@@ -4968,7 +5157,7 @@ var meetingFormFields = {
|
|
|
4968
5157
|
hint: "\u6CA1\u89E3\u6790\u5230\u8BE5\u8868\u7684 objId\uFF08\u53EF\u80FD\u5F53\u524D\u73AF\u5883\u6CA1\u6709\u8FD9\u5F20\u8868\uFF0C\u6216\u8D26\u53F7\u65E0\u6743\u9650\uFF09"
|
|
4969
5158
|
}, { warnings: resolved.warnings });
|
|
4970
5159
|
}
|
|
4971
|
-
const { createEbuilderFormHost } = await import("./host-
|
|
5160
|
+
const { createEbuilderFormHost } = await import("./host-UFF33TWJ.js");
|
|
4972
5161
|
const { createEbuilderFormContinuationSigner } = await import("./continuation-RN6PZN2M.js");
|
|
4973
5162
|
const { executeEbuilderFormOperation } = await import("./operations-5QL3AECO.js");
|
|
4974
5163
|
const formEnv = {
|
|
@@ -5020,15 +5209,15 @@ var CONTINUATION_TTL_SECONDS6 = 600;
|
|
|
5020
5209
|
var DATE_PATTERN = "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}$";
|
|
5021
5210
|
function formatSecondNow() {
|
|
5022
5211
|
const now = /* @__PURE__ */ new Date();
|
|
5023
|
-
const
|
|
5024
|
-
return `${now.getFullYear()}-${
|
|
5212
|
+
const pad3 = (value) => String(value).padStart(2, "0");
|
|
5213
|
+
return `${now.getFullYear()}-${pad3(now.getMonth() + 1)}-${pad3(now.getDate())} ${pad3(now.getHours())}:${pad3(now.getMinutes())}:${pad3(now.getSeconds())}`;
|
|
5025
5214
|
}
|
|
5026
5215
|
var DECISION_DONE = "2";
|
|
5027
5216
|
var MT_STATUS_OVER = "8";
|
|
5028
5217
|
var CANCELLED_MARK_DELAY_MS = 800;
|
|
5029
5218
|
async function isCancelledMeeting(env, mtId) {
|
|
5030
5219
|
try {
|
|
5031
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
5220
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
5032
5221
|
const listed = await getMeetingOperation2("meeting.eb.meeting.list").handler(
|
|
5033
5222
|
// withCount:false —— 这里只要一行状态,不必额外请求 count(少一次往返,也便于测试替身)
|
|
5034
5223
|
{ mt_id: mtId, pageNo: 1, pageSize: 1, withCount: false },
|
|
@@ -5247,8 +5436,8 @@ var decisionPublishApply = {
|
|
|
5247
5436
|
);
|
|
5248
5437
|
}
|
|
5249
5438
|
if (cancelled) {
|
|
5250
|
-
await new Promise((
|
|
5251
|
-
setTimeout(
|
|
5439
|
+
await new Promise((resolve6) => {
|
|
5440
|
+
setTimeout(resolve6, CANCELLED_MARK_DELAY_MS);
|
|
5252
5441
|
});
|
|
5253
5442
|
warnings.push(
|
|
5254
5443
|
`\u8BE5\u4F1A\u8BAE\u6B64\u524D\u88AB\u53D6\u6D88\u8FC7\uFF1A\u5DF2\u5728\u300C\u5199\u51B3\u8BAE\u300D\u4E0E\u300C\u6807\u8BB0\u5DF2\u51B3\u8BAE\u300D\u4E4B\u95F4\u7559 ${CANCELLED_MARK_DELAY_MS}ms \u95F4\u9694\uFF0C\u907F\u514D ESB \u628A\u540C\u4E00\u6279\u660E\u7EC6\u751F\u6210\u4E24\u8F6E\u4EFB\u52A1\uFF08\u771F\u673A\u9A8C\u8BC1\u8FC7\u7684\u5751\uFF09`
|
|
@@ -5549,7 +5738,383 @@ var ebMeetingAssociation = async (ctx) => {
|
|
|
5549
5738
|
};
|
|
5550
5739
|
};
|
|
5551
5740
|
|
|
5741
|
+
// src/shortcuts/meeting/operations/eb/crm-search.ts
|
|
5742
|
+
var DEFAULT_CRM_FLOW_ID = "904205116264026112";
|
|
5743
|
+
var DEFAULT_KEYWORD_FIELD = "custom_name";
|
|
5744
|
+
var KEYWORD_FIELD_HINTS = [
|
|
5745
|
+
"custom_name",
|
|
5746
|
+
"mc",
|
|
5747
|
+
"sjmc",
|
|
5748
|
+
"khmc",
|
|
5749
|
+
"customerName",
|
|
5750
|
+
"customer_name",
|
|
5751
|
+
"clientName",
|
|
5752
|
+
"name",
|
|
5753
|
+
"keyword",
|
|
5754
|
+
"keywordName",
|
|
5755
|
+
"searchKey"
|
|
5756
|
+
];
|
|
5757
|
+
var ID_KEYS = ["sjID", "sjid", "sj_id", "sjjId", "customerId", "custId", "clientId", "id"];
|
|
5758
|
+
var NAME_KEYS = ["mc", "sjmc", "sj_name", "customerName", "custName", "clientName", "name"];
|
|
5759
|
+
var LIST_KEYS = [
|
|
5760
|
+
"detail1",
|
|
5761
|
+
"detail2",
|
|
5762
|
+
"detail3",
|
|
5763
|
+
"detail",
|
|
5764
|
+
"details",
|
|
5765
|
+
"detailList",
|
|
5766
|
+
"list",
|
|
5767
|
+
"rows",
|
|
5768
|
+
"items",
|
|
5769
|
+
"data",
|
|
5770
|
+
"records",
|
|
5771
|
+
"result",
|
|
5772
|
+
"customers",
|
|
5773
|
+
"sjList"
|
|
5774
|
+
];
|
|
5775
|
+
function asRecord(value) {
|
|
5776
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
5777
|
+
}
|
|
5778
|
+
function pickFirst(row, keys) {
|
|
5779
|
+
for (const key of keys) {
|
|
5780
|
+
const value = row[key];
|
|
5781
|
+
if (value === void 0 || value === null) continue;
|
|
5782
|
+
if (typeof value === "object") {
|
|
5783
|
+
const nested = asRecord(value);
|
|
5784
|
+
if (nested) {
|
|
5785
|
+
const inner = pickFirst(nested, keys) || pickFirst(nested, ["id", "name"]);
|
|
5786
|
+
if (inner) return inner;
|
|
5787
|
+
}
|
|
5788
|
+
continue;
|
|
5789
|
+
}
|
|
5790
|
+
const text = String(value).trim();
|
|
5791
|
+
if (text !== "") return text;
|
|
5792
|
+
}
|
|
5793
|
+
return "";
|
|
5794
|
+
}
|
|
5795
|
+
function unwrapRow(value) {
|
|
5796
|
+
const record = asRecord(value);
|
|
5797
|
+
if (!record) return null;
|
|
5798
|
+
const main = asRecord(record.mainTable);
|
|
5799
|
+
return main ?? record;
|
|
5800
|
+
}
|
|
5801
|
+
function collectCandidateLists(customData) {
|
|
5802
|
+
const found = [];
|
|
5803
|
+
const main = asRecord(customData.mainTable);
|
|
5804
|
+
if (main) {
|
|
5805
|
+
found.push({ source: "customData.mainTable", rows: [main] });
|
|
5806
|
+
for (const key of LIST_KEYS) {
|
|
5807
|
+
const value = main[key];
|
|
5808
|
+
if (Array.isArray(value)) found.push({ source: `customData.mainTable.${key}`, rows: value });
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
for (const key of LIST_KEYS) {
|
|
5812
|
+
const value = customData[key];
|
|
5813
|
+
if (Array.isArray(value)) found.push({ source: `customData.${key}`, rows: value });
|
|
5814
|
+
}
|
|
5815
|
+
return found;
|
|
5816
|
+
}
|
|
5817
|
+
var CONTACT_LIST_KEYS = ["lxr", "contacts", "contactList", "lxrList"];
|
|
5818
|
+
var ADDRESS_LIST_KEYS = ["khdz", "addresses", "addressList", "dz"];
|
|
5819
|
+
var CONTACT_NAME_KEYS = ["field_1173221220888062706", "xm", "lxrxm", "contactName", "name"];
|
|
5820
|
+
var CONTACT_MOBILE_KEYS = ["field_1173221220888062708", "sjhm", "mobile", "phone", "tel", "lxrdh"];
|
|
5821
|
+
var CONTACT_DEPT_KEYS = ["field_1173221220888062707", "bm", "dept", "department", "bmmc"];
|
|
5822
|
+
var MOBILE_RE = /^[+\d][\d\s-]{6,}$/;
|
|
5823
|
+
var DEPT_RE = /(部|科|处|室|中心|事业部|分公司|集团|公司)$/;
|
|
5824
|
+
function pickRawList(row, keys) {
|
|
5825
|
+
for (const key of keys) {
|
|
5826
|
+
if (Array.isArray(row[key])) return row[key];
|
|
5827
|
+
}
|
|
5828
|
+
return void 0;
|
|
5829
|
+
}
|
|
5830
|
+
function parseCrmContacts(raw) {
|
|
5831
|
+
if (!Array.isArray(raw)) return [];
|
|
5832
|
+
const out = [];
|
|
5833
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5834
|
+
for (const item of raw) {
|
|
5835
|
+
const row = asRecord(item);
|
|
5836
|
+
if (!row) continue;
|
|
5837
|
+
const entries = Object.entries(row).filter(([key, value]) => !key.startsWith("subForm") && value !== null && value !== void 0 && String(value).trim() !== "");
|
|
5838
|
+
if (entries.length === 0) continue;
|
|
5839
|
+
const pick = (keys) => {
|
|
5840
|
+
for (const key of keys) {
|
|
5841
|
+
const hit = entries.find(([k]) => k === key);
|
|
5842
|
+
if (hit) return String(hit[1]).trim();
|
|
5843
|
+
}
|
|
5844
|
+
return "";
|
|
5845
|
+
};
|
|
5846
|
+
let name = pick(CONTACT_NAME_KEYS);
|
|
5847
|
+
let mobile = pick(CONTACT_MOBILE_KEYS);
|
|
5848
|
+
let dept = pick(CONTACT_DEPT_KEYS);
|
|
5849
|
+
for (const [, value] of entries) {
|
|
5850
|
+
const text = String(value).trim();
|
|
5851
|
+
if (text === "") continue;
|
|
5852
|
+
if (!mobile && MOBILE_RE.test(text)) {
|
|
5853
|
+
mobile = text;
|
|
5854
|
+
continue;
|
|
5855
|
+
}
|
|
5856
|
+
if (!name && !DEPT_RE.test(text) && !/^\d+$/.test(text)) {
|
|
5857
|
+
name = text;
|
|
5858
|
+
continue;
|
|
5859
|
+
}
|
|
5860
|
+
if (!dept && DEPT_RE.test(text)) dept = text;
|
|
5861
|
+
}
|
|
5862
|
+
if (name === "" && mobile === "") continue;
|
|
5863
|
+
const dedupeKey = `${name}|${mobile}`;
|
|
5864
|
+
if (seen.has(dedupeKey)) continue;
|
|
5865
|
+
seen.add(dedupeKey);
|
|
5866
|
+
out.push({ name, mobile, ...dept === "" ? {} : { dept } });
|
|
5867
|
+
}
|
|
5868
|
+
return out;
|
|
5869
|
+
}
|
|
5870
|
+
function parseCrmAddresses(raw) {
|
|
5871
|
+
if (!Array.isArray(raw)) return [];
|
|
5872
|
+
const out = [];
|
|
5873
|
+
for (const item of raw) {
|
|
5874
|
+
const row = asRecord(item);
|
|
5875
|
+
if (!row) continue;
|
|
5876
|
+
const parts = Object.entries(row).filter(([key, value]) => !key.startsWith("subForm") && value !== null && value !== void 0 && String(value).trim() !== "").map(([, value]) => String(value).trim());
|
|
5877
|
+
if (parts.length > 0) out.push(parts.join(" "));
|
|
5878
|
+
}
|
|
5879
|
+
return out;
|
|
5880
|
+
}
|
|
5881
|
+
function normalizeCustomers(rows, limit) {
|
|
5882
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5883
|
+
for (const raw of rows) {
|
|
5884
|
+
const row = unwrapRow(raw);
|
|
5885
|
+
if (!row) continue;
|
|
5886
|
+
const customerId = pickFirst(row, ID_KEYS);
|
|
5887
|
+
const name = pickFirst(row, NAME_KEYS);
|
|
5888
|
+
if (customerId === "" && name === "") continue;
|
|
5889
|
+
const key = customerId !== "" ? customerId : `name:${name}`;
|
|
5890
|
+
if (seen.has(key)) continue;
|
|
5891
|
+
const contacts = parseCrmContacts(pickRawList(row, CONTACT_LIST_KEYS));
|
|
5892
|
+
const addresses = parseCrmAddresses(pickRawList(row, ADDRESS_LIST_KEYS));
|
|
5893
|
+
seen.set(key, {
|
|
5894
|
+
customerId,
|
|
5895
|
+
name,
|
|
5896
|
+
...contacts.length > 0 ? { contacts } : {},
|
|
5897
|
+
...addresses.length > 0 ? { addresses } : {}
|
|
5898
|
+
});
|
|
5899
|
+
}
|
|
5900
|
+
const all = [...seen.values()];
|
|
5901
|
+
const total = all.length;
|
|
5902
|
+
return { items: limit > 0 ? all.slice(0, limit) : all, total };
|
|
5903
|
+
}
|
|
5904
|
+
function parseCrmSearchPayload(actionData, options) {
|
|
5905
|
+
const action = asRecord(actionData) ?? {};
|
|
5906
|
+
const responseData = asRecord(action.responseData) ?? {};
|
|
5907
|
+
const customData = asRecord(responseData.customData) ?? {};
|
|
5908
|
+
const rawHasData = action.hasData;
|
|
5909
|
+
const hasData = rawHasData === void 0 || rawHasData === null ? null : Number(rawHasData) > 0;
|
|
5910
|
+
const templateFields = options.templateFields ?? [];
|
|
5911
|
+
const base = {
|
|
5912
|
+
keyword: options.keyword,
|
|
5913
|
+
limit: options.limit,
|
|
5914
|
+
total: 0,
|
|
5915
|
+
items: [],
|
|
5916
|
+
truncated: false,
|
|
5917
|
+
source: "customData",
|
|
5918
|
+
hasData,
|
|
5919
|
+
exact: false,
|
|
5920
|
+
singleBestMatch: false,
|
|
5921
|
+
message: "",
|
|
5922
|
+
templateFields,
|
|
5923
|
+
keywordField: options.keywordField ?? null
|
|
5924
|
+
};
|
|
5925
|
+
if (options.templateBlocked === true) {
|
|
5926
|
+
return {
|
|
5927
|
+
...base,
|
|
5928
|
+
blocked: "esb_template_empty",
|
|
5929
|
+
message: "\u52A8\u4F5C\u6D41\u914D\u4E86\u300C\u81EA\u5B9A\u4E49\u5165\u53C2\u6A21\u677F\u300D\u4F46\u4E3B\u8868\u5B57\u6BB5\u4E3A\u7A7A\uFF08customParams.mainTable = {}\uFF09\uFF0C\u89E6\u53D1\u65F6\u4F20\u5165\u7684\u67E5\u8BE2\u6761\u4EF6\u4F1A\u88AB\u4E22\u5F03\uFF0C\u56E0\u6B64\u67E5\u4E0D\u5230\u5BA2\u6237\u3002\u9700\u8981\u5148\u5728 ESB \u8BBE\u8BA1\u5668\u91CC\u7ED9\u8BE5\u52A8\u4F5C\u6D41\u8865\u5165\u53C2\uFF08`custom_name` \u5BA2\u6237\u540D\u79F0\uFF09\u540E\u518D\u67E5\u3002"
|
|
5930
|
+
};
|
|
5931
|
+
}
|
|
5932
|
+
const lists = collectCandidateLists(customData);
|
|
5933
|
+
const best = lists.map((item) => ({ ...item, normalized: normalizeCustomers(item.rows, options.limit) })).sort((a, b) => b.normalized.total - a.normalized.total)[0];
|
|
5934
|
+
if (!best) {
|
|
5935
|
+
return {
|
|
5936
|
+
...base,
|
|
5937
|
+
message: "\u52A8\u4F5C\u6D41\u8FD4\u56DE\u91CC\u6CA1\u6709\u53EF\u8BC6\u522B\u7684\u5BA2\u6237\u7ED3\u6784\uFF08\u65E2\u6CA1\u6709 mainTable \u884C\uFF0C\u4E5F\u6CA1\u6709 detail/list \u4E4B\u7C7B\u7684\u5217\u8868\uFF09\uFF0C\u8BF7\u68C0\u67E5\u52A8\u4F5C\u6D41\u7684\u8F93\u51FA\u6A21\u677F\u662F\u5426\u4ECD\u8F93\u51FA sjID/mc"
|
|
5938
|
+
};
|
|
5939
|
+
}
|
|
5940
|
+
if (best.normalized.total === 0) {
|
|
5941
|
+
return {
|
|
5942
|
+
...base,
|
|
5943
|
+
source: best.source,
|
|
5944
|
+
message: `\u6309\u300C${options.keyword}\u300D\u6CA1\u6709\u5339\u914D\u5230\u5BA2\u6237\uFF08\u52A8\u4F5C\u6D41\u8FD4\u56DE\u7A7A\u884C\uFF09`
|
|
5945
|
+
};
|
|
5946
|
+
}
|
|
5947
|
+
const items = best.normalized.items;
|
|
5948
|
+
const singleBestMatch = best.normalized.total === 1;
|
|
5949
|
+
const exact = singleBestMatch && items[0].name === options.keyword;
|
|
5950
|
+
const rawAddress = pickRawList(best.rows[0], ADDRESS_LIST_KEYS);
|
|
5951
|
+
const addressHint = Array.isArray(rawAddress) && rawAddress.length > 0 && (items[0].addresses?.length ?? 0) === 0 ? `\u52A8\u4F5C\u6D41\u7684\u300C\u5BA2\u6237\u5730\u5740\u300D\uFF08khdz\uFF09\u53EA\u56DE\u4E86 ${rawAddress.length} \u6761\u660E\u7EC6\u884C id\uFF0C\u6CA1\u6709\u5730\u5740\u6587\u672C \u2014\u2014 \u9700\u8981\u5728 ESB \u8F93\u51FA\u6A21\u677F\u91CC\u8865\u4E0A\u5730\u5740\u5B57\u6BB5\uFF08\u5982 \u8BE6\u7EC6\u5730\u5740/\u7701\u5E02\u533A\uFF09\uFF0C\u5426\u5219\u9080\u8BF7\u51FD\u548C\u660E\u7EC6\u8868\u91CC\u62FF\u4E0D\u5230\u5730\u5740\u3002` : void 0;
|
|
5952
|
+
return {
|
|
5953
|
+
...base,
|
|
5954
|
+
items,
|
|
5955
|
+
total: best.normalized.total,
|
|
5956
|
+
truncated: best.normalized.total > options.limit,
|
|
5957
|
+
source: best.source,
|
|
5958
|
+
exact,
|
|
5959
|
+
singleBestMatch,
|
|
5960
|
+
...addressHint ? { addressHint } : {},
|
|
5961
|
+
message: exact ? `\u7CBE\u786E\u547D\u4E2D\u5BA2\u6237\u300C${items[0].name}\u300D\uFF08${items[0].customerId}\uFF09` : `\u6309\u300C${options.keyword}\u300D\u6A21\u7CCA\u547D\u4E2D ${best.normalized.total} \u4E2A\u5BA2\u6237` + (singleBestMatch ? "\uFF08\u52A8\u4F5C\u6D41\u53EA\u56DE\u9996\u4E2A\u5339\u914D\uFF09" : "") + (best.normalized.total > options.limit ? `\uFF0C\u5DF2\u6309 limit=${options.limit} \u622A\u65AD` : "")
|
|
5962
|
+
};
|
|
5963
|
+
}
|
|
5964
|
+
function pickKeywordField(templateMainTable) {
|
|
5965
|
+
const keys = Object.keys(templateMainTable ?? {});
|
|
5966
|
+
if (keys.length === 0) return null;
|
|
5967
|
+
for (const hint of KEYWORD_FIELD_HINTS) {
|
|
5968
|
+
const hit = keys.find((key) => key.toLowerCase() === hint.toLowerCase());
|
|
5969
|
+
if (hit) return hit;
|
|
5970
|
+
}
|
|
5971
|
+
return keys.length === 1 ? keys[0] : null;
|
|
5972
|
+
}
|
|
5973
|
+
function pickLimitField(templateMainTable) {
|
|
5974
|
+
const keys = Object.keys(templateMainTable ?? {});
|
|
5975
|
+
const hints = ["pageSize", "pagesize", "limit", "rows", "size", "num"];
|
|
5976
|
+
for (const hint of hints) {
|
|
5977
|
+
const hit = keys.find((key) => key.toLowerCase() === hint.toLowerCase());
|
|
5978
|
+
if (hit) return hit;
|
|
5979
|
+
}
|
|
5980
|
+
return null;
|
|
5981
|
+
}
|
|
5982
|
+
async function runCrmSearchFlow(env, input) {
|
|
5983
|
+
const session = await env.host.getSession();
|
|
5984
|
+
const employeeId = String(input.employeeId ?? session?.userId ?? "").trim();
|
|
5985
|
+
if (!employeeId) {
|
|
5986
|
+
throw meetingValidationError("crm_employee_required", "\u53D6\u4E0D\u5230\u5F53\u524D\u767B\u5F55\u7528\u6237 id\uFF0C\u65E0\u6CD5\u89E6\u53D1 ESB \u5BA2\u6237\u67E5\u8BE2");
|
|
5987
|
+
}
|
|
5988
|
+
const { createEsbHost } = await import("./host-FWDOSRH5.js");
|
|
5989
|
+
const { createEsbContinuationSigner } = await import("./continuation-NLECEJPX.js");
|
|
5990
|
+
const { getEsbOperation } = await import("./registry-FRJ6H7BT.js");
|
|
5991
|
+
const esbEnv = {
|
|
5992
|
+
ctx: env.ctx,
|
|
5993
|
+
host: createEsbHost(env.ctx),
|
|
5994
|
+
continuation: createEsbContinuationSigner(env.ctx)
|
|
5995
|
+
};
|
|
5996
|
+
const templateOp = getEsbOperation("esb.input-format");
|
|
5997
|
+
const prepareOp = getEsbOperation("esb.trigger.prepare");
|
|
5998
|
+
const applyOp = getEsbOperation("esb.trigger.apply");
|
|
5999
|
+
let templateMainTable = null;
|
|
6000
|
+
let customParamsTemplate = null;
|
|
6001
|
+
let templateReadOk = false;
|
|
6002
|
+
try {
|
|
6003
|
+
const template = await templateOp.handler({ applicationId: input.flowId }, esbEnv);
|
|
6004
|
+
customParamsTemplate = asRecord(template?.data?.customParams);
|
|
6005
|
+
templateMainTable = asRecord(customParamsTemplate?.mainTable);
|
|
6006
|
+
templateReadOk = true;
|
|
6007
|
+
} catch {
|
|
6008
|
+
}
|
|
6009
|
+
const templateFields = Object.keys(templateMainTable ?? {});
|
|
6010
|
+
const templateBlocked = templateReadOk && customParamsTemplate !== null && templateFields.length === 0;
|
|
6011
|
+
const keywordField = pickKeywordField(templateMainTable) ?? DEFAULT_KEYWORD_FIELD;
|
|
6012
|
+
const limitField = pickLimitField(templateMainTable);
|
|
6013
|
+
const mainTable = {};
|
|
6014
|
+
mainTable[keywordField] = input.keyword;
|
|
6015
|
+
if (limitField) mainTable[limitField] = input.limit;
|
|
6016
|
+
const pre = await prepareOp.handler(
|
|
6017
|
+
{
|
|
6018
|
+
esbFlowId: input.flowId,
|
|
6019
|
+
employeeId,
|
|
6020
|
+
customParams: { mainTable }
|
|
6021
|
+
},
|
|
6022
|
+
esbEnv
|
|
6023
|
+
);
|
|
6024
|
+
const applied = await applyOp.handler(
|
|
6025
|
+
{ continuation: pre?.data?.continuation, confirm: true },
|
|
6026
|
+
esbEnv
|
|
6027
|
+
);
|
|
6028
|
+
const actionData = applied?.data?.actionData;
|
|
6029
|
+
const parsed = parseCrmSearchPayload(actionData, {
|
|
6030
|
+
keyword: input.keyword,
|
|
6031
|
+
limit: input.limit,
|
|
6032
|
+
templateFields,
|
|
6033
|
+
keywordField,
|
|
6034
|
+
templateBlocked
|
|
6035
|
+
});
|
|
6036
|
+
if (actionData && typeof actionData === "object") {
|
|
6037
|
+
const reminder = actionData.reminder;
|
|
6038
|
+
const reminderText = reminder === void 0 || reminder === null ? "" : String(reminder);
|
|
6039
|
+
if (reminderText !== "" && reminderText !== "0") parsed.actionMessage = reminderText;
|
|
6040
|
+
}
|
|
6041
|
+
return { result: parsed, raw: applied?.data };
|
|
6042
|
+
}
|
|
6043
|
+
var ebCrmSearch = {
|
|
6044
|
+
name: "meeting.eb.crm.search",
|
|
6045
|
+
resource: "eb",
|
|
6046
|
+
method: "meeting.eb.crm.search",
|
|
6047
|
+
action: "meeting.eb.crm.search",
|
|
6048
|
+
summary: "\u6309\u5BA2\u6237\u540D\u79F0\u67E5\u8BE2 CRM \u5BA2\u6237\uFF08ESB \u52A8\u4F5C\u6D41 904205116264026112\uFF0C\u5165\u53C2 custom_name\uFF0C\u51FA\u53C2 sjID/mc\uFF09\uFF1B\u52A8\u4F5C\u6D41\u4E00\u6B21\u53EA\u56DE\u9996\u4E2A\u5339\u914D\uFF0C\u540D\u79F0\u4E0D\u5B8C\u5168\u4E00\u81F4\u65F6\u987B\u56DE\u95EE\u7528\u6237\u786E\u8BA4",
|
|
6049
|
+
capability: "eb.crm",
|
|
6050
|
+
risk: "read",
|
|
6051
|
+
inputSchema: schemaOf(
|
|
6052
|
+
{
|
|
6053
|
+
keyword: {
|
|
6054
|
+
type: "string",
|
|
6055
|
+
minLength: 1,
|
|
6056
|
+
description: "\u5BA2\u6237\u540D\u79F0\uFF0C\u8D70\u52A8\u4F5C\u6D41\u5165\u53C2 custom_name\uFF08\u5305\u542B\u5339\u914D\uFF09\uFF1A\u7ED9\u5168\u79F0\u6700\u7A33\uFF0C\u7247\u6BB5\u53EA\u56DE\u9996\u4E2A\u5339\u914D"
|
|
6057
|
+
},
|
|
6058
|
+
limit: { type: "number", description: "\u8FD4\u56DE\u6761\u6570\u4E0A\u9650\uFF0C\u9ED8\u8BA4 10\uFF08\u5F53\u524D\u52A8\u4F5C\u6D41\u4E00\u6B21\u53EA\u56DE 1 \u6761\uFF0C\u4EC5\u4F5C\u517C\u5BB9\uFF09" },
|
|
6059
|
+
flowId: { type: "string", description: "\u8986\u76D6 ESB \u52A8\u4F5C\u6D41 id\uFF08\u9ED8\u8BA4 904205116264026112\uFF09" },
|
|
6060
|
+
employeeId: { type: "string", description: "\u8986\u76D6\u89E6\u53D1\u4EBA\u5458 id\uFF08\u9ED8\u8BA4\u5F53\u524D\u767B\u5F55\u7528\u6237\uFF09" },
|
|
6061
|
+
includeRaw: { type: "boolean", description: "true=\u9644\u5E26 ESB \u539F\u59CB\u8FD4\u56DE\uFF0C\u4FBF\u4E8E\u6392\u67E5\u8F93\u51FA\u7ED3\u6784" }
|
|
6062
|
+
},
|
|
6063
|
+
{ required: ["keyword"] }
|
|
6064
|
+
),
|
|
6065
|
+
handler: async (args, env) => {
|
|
6066
|
+
const keyword = String(args.keyword ?? "").trim();
|
|
6067
|
+
if (!keyword) {
|
|
6068
|
+
throw meetingValidationError("crm_keyword_required", "keyword \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u5BA2\u6237\u540D\u79F0\u5173\u952E\u5B57\uFF09");
|
|
6069
|
+
}
|
|
6070
|
+
const limitRaw = Number(args.limit ?? 10);
|
|
6071
|
+
const limit = Number.isFinite(limitRaw) && limitRaw > 0 ? Math.min(Math.floor(limitRaw), 100) : 10;
|
|
6072
|
+
const { result, raw } = await runCrmSearchFlow(env, {
|
|
6073
|
+
keyword,
|
|
6074
|
+
limit,
|
|
6075
|
+
flowId: String(args.flowId ?? "").trim() || DEFAULT_CRM_FLOW_ID,
|
|
6076
|
+
...args.employeeId ? { employeeId: String(args.employeeId) } : {}
|
|
6077
|
+
});
|
|
6078
|
+
const warnings = [];
|
|
6079
|
+
if (result.blocked === "esb_template_empty") {
|
|
6080
|
+
warnings.push(result.message);
|
|
6081
|
+
warnings.push("\u26D4 \u4E0D\u8981\u56DE\u590D\u300C\u6CA1\u6709\u8FD9\u4E2A\u5BA2\u6237\u300D\uFF1A\u8FD9\u662F\u52A8\u4F5C\u6D41\u5165\u53C2\u6A21\u677F\u672A\u914D\u7F6E\uFF0C\u5C5E\u4E8E\u914D\u7F6E\u95EE\u9898\u3002");
|
|
6082
|
+
} else if (result.items.length === 0) {
|
|
6083
|
+
warnings.push(`\u6309\u300C${keyword}\u300D\u6CA1\u6709\u5339\u914D\u5230\u5BA2\u6237\uFF1B\u53EF\u6362\u66F4\u77ED\u7684\u5173\u952E\u5B57\uFF08\u53BB\u6389\u5730\u57DF/\u540E\u7F00\uFF09\uFF0C\u6216\u786E\u8BA4\u8BE5\u5BA2\u6237\u662F\u5426\u5DF2\u5728 CRM \u5EFA\u6863\uFF08\u8FD9\u662F\u300C\u67E5\u65E0\u300D\uFF0C\u53EF\u4EE5\u5982\u5B9E\u56DE\u590D\u7528\u6237\uFF09\u3002`);
|
|
6084
|
+
} else if (!result.exact) {
|
|
6085
|
+
warnings.push(`\u52A8\u4F5C\u6D41\u4E00\u6B21\u53EA\u56DE\u9996\u4E2A\u5339\u914D\uFF1A\u300C${result.items[0].name}\u300D\uFF08${result.items[0].customerId}\uFF09\uFF0C\u4E0E\u300C${keyword}\u300D\u4E0D\u5B8C\u5168\u4E00\u81F4\u3002\u8BF7\u628A**\u547D\u4E2D\u5168\u540D\u539F\u6837\u5FF5\u51FA\u6765\u95EE"\u662F\u8FD9\u5BB6\u5417"**\uFF0C\u7528\u6237\u8BA4\u4E86\u518D\u628A\u8BE5 id \u5199\u8FDB create.flow.prepare \u7684 crm_members\uFF0C\u4E0D\u8981\u731C\u3002\u26D4 \u4E0D\u8981\u95EE\u6210"\u586B\u8FDB\u53C2\u4F1A\u5BA2\u6237\u5B57\u6BB5\u8FD8\u662F\u53EA\u5199\u8FDB\u4F1A\u8BAE\u5185\u5BB9\u5907\u6CE8"\u8FD9\u79CD\u9009\u62E9\u9898 \u2014\u2014 \u5BA2\u6237\u4E00\u5F8B\u8981\u5173\u8054\u5BA2\u6237\u6863\u6848\uFF0C"\u53EA\u5199\u5907\u6CE8"\u662F\u660E\u4EE4\u7981\u6B62\u7684\u505A\u6CD5\u3002`);
|
|
6086
|
+
}
|
|
6087
|
+
if (result.items.some((item) => item.name === "")) {
|
|
6088
|
+
warnings.push("\u6709\u5BA2\u6237\u53EA\u8FD4\u56DE\u4E86 sjID \u6CA1\u8FD4\u56DE mc\uFF08\u540D\u79F0\uFF09\uFF0C\u8BF7\u8BA9\u52A8\u4F5C\u6D41\u8F93\u51FA mc \u5B57\u6BB5\u3002");
|
|
6089
|
+
}
|
|
6090
|
+
const firstCustomer = result.items[0];
|
|
6091
|
+
if (firstCustomer) {
|
|
6092
|
+
const contacts = firstCustomer.contacts ?? [];
|
|
6093
|
+
if (contacts.length > 0) {
|
|
6094
|
+
warnings.push(
|
|
6095
|
+
`\u8BE5\u5BA2\u6237\u6709 ${contacts.length} \u4F4D\u8054\u7CFB\u4EBA\uFF1A` + contacts.map((c) => `${c.name}${c.dept ? `\uFF08${c.dept}\uFF09` : ""} ${c.mobile || "\u65E0\u624B\u673A\u53F7"}`).join("\u3001") + '\u3002\u5EFA\u4F1A\u65F6\u4F20 `crm_members` \u5C31\u4F1A\u628A\u8FD9**\u5168\u90E8\u8054\u7CFB\u4EBA\u81EA\u52A8\u5199\u6210\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\u884C**\uFF08\u4E00\u4EBA\u4E00\u884C\uFF09\uFF0C\u26D4 \u4E0D\u8981\u95EE\u7528\u6237"\u9009\u54EA\u4F4D"\u3001\u4E5F\u4E0D\u8981\u53EA\u5E26\u5176\u4E2D\u4E00\u4F4D\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8BF4"\u53EA\u5199\u67D0\u67D0"\u65F6\u624D\u7528 crm_member_details:[{"xm":"<\u59D3\u540D>","sjhm":"<\u624B\u673A\u53F7>","zw":"<\u90E8\u95E8\u6216\u804C\u4F4D>"}] \u8986\u76D6\u3002'
|
|
6096
|
+
);
|
|
6097
|
+
} else {
|
|
6098
|
+
warnings.push(
|
|
6099
|
+
'\u8BE5\u5BA2\u6237**\u6CA1\u6709\u8054\u7CFB\u4EBA**\uFF08\u52A8\u4F5C\u6D41\u672A\u8F93\u51FA lxr\uFF0C\u6216\u8BE5\u5BA2\u6237\u6CA1\u5EFA\u6863\u8054\u7CFB\u4EBA\uFF09\u2014\u2014 \u8FD9\u662F\u552F\u4E00\u9700\u8981\u95EE\u8054\u7CFB\u4EBA\u7684\u573A\u666F\u3002\u53EF\u4EE5\u95EE\u7528\u6237\u300C\u8981\u4E0D\u8981\u8865\u4E00\u4E0B\u8054\u7CFB\u4EBA\u59D3\u540D\u548C\u624B\u673A\u53F7\uFF08\u65B9\u4FBF\u7684\u8BDD\u518D\u7ED9\u804C\u4F4D\uFF09\u300D\uFF0C\u518D\u4EE5 crm_member_details:[{"xm":"\u5F20\u4E09","sjhm":"13800000000"}] \u4F20\u7ED9 create.flow.prepare/quick\uFF1B\u7528\u6237\u8BF4"\u6CA1\u6709"\u5C31\u7559\u7A7A\uFF0C\u4E0D\u8981\u786C\u7F16\u3002'
|
|
6100
|
+
);
|
|
6101
|
+
}
|
|
6102
|
+
if (result.addressHint) warnings.push(result.addressHint);
|
|
6103
|
+
}
|
|
6104
|
+
return meetingSuccess(
|
|
6105
|
+
"meeting.eb.crm.search",
|
|
6106
|
+
{ ...result, ...args.includeRaw === true ? { raw } : {} },
|
|
6107
|
+
warnings.length > 0 ? { warnings } : {}
|
|
6108
|
+
);
|
|
6109
|
+
}
|
|
6110
|
+
};
|
|
6111
|
+
var meetingEbCrmOperations = [ebCrmSearch];
|
|
6112
|
+
|
|
5552
6113
|
// src/shortcuts/meeting/operations/eb/create-flow.ts
|
|
6114
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
6115
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
|
|
6116
|
+
import { homedir } from "node:os";
|
|
6117
|
+
import { resolve as resolve5 } from "node:path";
|
|
5553
6118
|
var FIELD_ALIASES = {
|
|
5554
6119
|
mt_name: ["\u4F1A\u8BAE\u540D\u79F0", "\u4F1A\u8BAE\u4E3B\u9898", "\u4E3B\u9898"],
|
|
5555
6120
|
begin_datetime: ["\u5F00\u59CB\u65F6\u95F4", "\u4F1A\u8BAE\u5F00\u59CB\u65F6\u95F4"],
|
|
@@ -5559,18 +6124,22 @@ var FIELD_ALIASES = {
|
|
|
5559
6124
|
customize_address: ["\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9", "\u81EA\u5B9A\u4E49\u5730\u70B9"],
|
|
5560
6125
|
hrm_members: ["\u53C2\u4F1A\u4EBA\u5458", "\u53C2\u4F1A\u4EBA"],
|
|
5561
6126
|
total_member: ["\u53C2\u4F1A\u4EBA\u6570", "\u4EBA\u6570"],
|
|
6127
|
+
/** 参会客户(CustomerComponent 客户浏览按钮):值是客户 id 列表,不是客户名称文本。 */
|
|
6128
|
+
crm_members: ["\u53C2\u4F1A\u5BA2\u6237", "\u5BA2\u6237"],
|
|
6129
|
+
crm_member_count: ["\u5E94\u5230\u5BA2\u6237\u6570", "\u5BA2\u6237\u6570"],
|
|
5562
6130
|
caller: ["\u53EC\u96C6\u4EBA", "\u53D1\u8D77\u4EBA"],
|
|
5563
6131
|
contacter: ["\u8054\u7CFB\u4EBA"],
|
|
5564
6132
|
mt_type: ["\u4F1A\u8BAE\u7C7B\u578B"],
|
|
5565
6133
|
other_remark: ["\u5907\u6CE8", "\u5176\u4ED6\u8BF4\u660E"]
|
|
5566
6134
|
};
|
|
6135
|
+
var PERSON_FIELD_LABELS = { caller: "\u53EC\u96C6\u4EBA", contacter: "\u8054\u7CFB\u4EBA" };
|
|
5567
6136
|
function workflowEnv(env) {
|
|
5568
6137
|
return env;
|
|
5569
6138
|
}
|
|
5570
6139
|
async function loadCreateForm(env, workflowId) {
|
|
5571
|
-
const { createWorkflowHost } = await import("./host-
|
|
6140
|
+
const { createWorkflowHost } = await import("./host-7RXEDMAH.js");
|
|
5572
6141
|
const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
|
|
5573
|
-
const { getWorkflowOperation } = await import("./registry-
|
|
6142
|
+
const { getWorkflowOperation } = await import("./registry-SG2PGVCF.js");
|
|
5574
6143
|
const wfEnv = {
|
|
5575
6144
|
...workflowEnv(env),
|
|
5576
6145
|
host: createWorkflowHost(env.ctx),
|
|
@@ -5614,39 +6183,126 @@ async function resolveEmployeeNames(env, ids) {
|
|
|
5614
6183
|
}
|
|
5615
6184
|
return map;
|
|
5616
6185
|
}
|
|
5617
|
-
async function
|
|
6186
|
+
async function resolvePersonTokens(env, tokens) {
|
|
6187
|
+
const map = /* @__PURE__ */ new Map();
|
|
6188
|
+
const unique = [...new Set(tokens.map((token) => String(token).trim()).filter((token) => token !== ""))];
|
|
6189
|
+
if (unique.length === 0) return map;
|
|
6190
|
+
const idLike = unique.filter((token) => /^\d{8,}$/.test(token));
|
|
6191
|
+
const nameLike = unique.filter((token) => !/^\d{8,}$/.test(token));
|
|
6192
|
+
if (idLike.length > 0) {
|
|
6193
|
+
const names = await resolveEmployeeNames(env, idLike);
|
|
6194
|
+
for (const id of idLike) map.set(id, { id, name: names.get(id) ?? id });
|
|
6195
|
+
}
|
|
6196
|
+
if (nameLike.length > 0) {
|
|
6197
|
+
try {
|
|
6198
|
+
const { hrmEmployeeOperations } = await import("./employee-SAK2QYXX.js");
|
|
6199
|
+
const query = hrmEmployeeOperations.find((operation) => operation.name === "hrm.employee.query");
|
|
6200
|
+
for (const name of nameLike) {
|
|
6201
|
+
if (!query) break;
|
|
6202
|
+
const found = await query.handler({ keyword: name, pageSize: 10 }, env).catch(() => null);
|
|
6203
|
+
const rows = found?.data?.rows ?? [];
|
|
6204
|
+
const exact = rows.find((row) => String(row.name ?? "").trim() === name);
|
|
6205
|
+
const hit = exact ?? (rows.length === 1 ? rows[0] : void 0);
|
|
6206
|
+
const id = String(hit?.id ?? "").trim();
|
|
6207
|
+
if (id === "") continue;
|
|
6208
|
+
map.set(name, { id, name: String(hit?.name ?? name) });
|
|
6209
|
+
}
|
|
6210
|
+
} catch {
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
return map;
|
|
6214
|
+
}
|
|
6215
|
+
async function resolveSelfPerson(env) {
|
|
6216
|
+
let session = null;
|
|
6217
|
+
try {
|
|
6218
|
+
session = await env.host?.getSession?.();
|
|
6219
|
+
} catch {
|
|
6220
|
+
return null;
|
|
6221
|
+
}
|
|
6222
|
+
const id = String(session?.userId ?? "").trim();
|
|
6223
|
+
if (id === "" || id === "unknown") return null;
|
|
6224
|
+
const names = await resolveEmployeeNames(env, [id]);
|
|
6225
|
+
const name = String(names.get(id) ?? "").trim();
|
|
6226
|
+
if (name === "") return null;
|
|
6227
|
+
return { id, name };
|
|
6228
|
+
}
|
|
6229
|
+
function applySelfPersonDefaults(args, self) {
|
|
6230
|
+
const filled = [];
|
|
6231
|
+
const missing = ["caller", "contacter"].filter((field) => String(args[field] ?? "").trim() === "");
|
|
6232
|
+
if (missing.length === 0) return { filled, warning: "" };
|
|
6233
|
+
if (!self) {
|
|
6234
|
+
return {
|
|
6235
|
+
filled,
|
|
6236
|
+
warning: missing.length === 2 ? "\u26A0\uFE0F \u6CA1\u80FD\u786E\u8BA4\u5F53\u524D\u767B\u5F55\u7528\u6237\u5BF9\u5E94\u7684\u5458\u5DE5 \u2014\u2014\u300C\u53EC\u96C6\u4EBA\u300D\u300C\u8054\u7CFB\u4EBA\u300D\u4F1A\u7559\u7A7A\uFF0C\u8BF7\u663E\u5F0F\u4F20 caller / contacter\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002" : ""
|
|
6237
|
+
};
|
|
6238
|
+
}
|
|
6239
|
+
for (const field of missing) {
|
|
6240
|
+
args[field] = self.id;
|
|
6241
|
+
filled.push({ field, id: self.id, name: self.name });
|
|
6242
|
+
}
|
|
6243
|
+
return { filled, warning: "" };
|
|
6244
|
+
}
|
|
6245
|
+
function parseRoomRef(input) {
|
|
6246
|
+
const text = String(input ?? "").trim();
|
|
6247
|
+
if (!text) return {};
|
|
6248
|
+
const withId = /^(.*?)[((]\s*(\d{4,})\s*[))]$/.exec(text);
|
|
6249
|
+
if (withId) {
|
|
6250
|
+
const name = withId[1].trim();
|
|
6251
|
+
const id = withId[2];
|
|
6252
|
+
return name ? { id, name } : { id };
|
|
6253
|
+
}
|
|
6254
|
+
if (/^\d+$/.test(text)) return { id: text };
|
|
6255
|
+
return { name: text };
|
|
6256
|
+
}
|
|
6257
|
+
async function resolveAddressRoom(env, input) {
|
|
5618
6258
|
const text = String(input ?? "").trim();
|
|
5619
6259
|
if (!text) return null;
|
|
5620
|
-
const
|
|
6260
|
+
const ref = parseRoomRef(text);
|
|
6261
|
+
const { loadRooms: loadRooms2 } = await import("./room-recommend-R3JVUUAC.js");
|
|
6262
|
+
let rooms = [];
|
|
5621
6263
|
try {
|
|
5622
|
-
|
|
5623
|
-
const byId = rooms.find((room) => room.id === text);
|
|
5624
|
-
if (byId) return { id: byId.id, name: byId.name };
|
|
5625
|
-
const byName = rooms.find((room) => room.name === text);
|
|
5626
|
-
if (byName) return { id: byName.id, name: byName.name };
|
|
6264
|
+
rooms = (await loadRooms2(env, {})).rooms;
|
|
5627
6265
|
} catch {
|
|
6266
|
+
return { id: ref.id ?? "", name: ref.name ?? text, status: "unknown", lookupFailed: true };
|
|
6267
|
+
}
|
|
6268
|
+
const hit = (ref.id ? rooms.find((room) => room.id === ref.id) : void 0) ?? (ref.name ? rooms.find((room) => room.name === ref.name) : void 0);
|
|
6269
|
+
if (hit) return { id: hit.id, name: hit.name, status: hit.status, statusText: hit.statusText };
|
|
6270
|
+
if (ref.id) return { id: ref.id, name: ref.name ?? "", status: "unknown" };
|
|
6271
|
+
return null;
|
|
6272
|
+
}
|
|
6273
|
+
async function resolveRoomValue(env, input) {
|
|
6274
|
+
const text = String(input ?? "").trim();
|
|
6275
|
+
if (!text) return null;
|
|
6276
|
+
const resolved = await resolveAddressRoom(env, text).catch(() => null);
|
|
6277
|
+
if (resolved?.id && !resolved.lookupFailed) {
|
|
6278
|
+
return { id: resolved.id, name: resolved.name || resolved.id };
|
|
5628
6279
|
}
|
|
5629
|
-
|
|
6280
|
+
const ref = parseRoomRef(text);
|
|
6281
|
+
if (ref.id) {
|
|
5630
6282
|
try {
|
|
5631
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
5632
|
-
const detail = await getMeetingOperation2("meeting.eb.room.detail").handler({ id:
|
|
6283
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6284
|
+
const detail = await getMeetingOperation2("meeting.eb.room.detail").handler({ id: ref.id }, env);
|
|
5633
6285
|
const main = detail?.data?.mainTable ?? detail?.data?.data?.mainTable ?? {};
|
|
5634
|
-
const name = String(main.room_name ?? "").trim();
|
|
5635
|
-
if (name) return { id:
|
|
6286
|
+
const name = String(main.room_name ?? "").trim() || ref.name || "";
|
|
6287
|
+
if (name) return { id: ref.id, name };
|
|
5636
6288
|
} catch {
|
|
5637
6289
|
}
|
|
5638
|
-
return { id:
|
|
6290
|
+
return { id: ref.id, name: ref.name || ref.id };
|
|
5639
6291
|
}
|
|
5640
6292
|
return null;
|
|
5641
6293
|
}
|
|
5642
6294
|
async function shapeBrowserValues(env, values) {
|
|
5643
6295
|
const notes = [];
|
|
5644
6296
|
const shaped = { ...values };
|
|
6297
|
+
const readable = {};
|
|
5645
6298
|
if (shaped.address !== void 0 && shaped.address !== "") {
|
|
5646
6299
|
const room = await resolveRoomValue(env, String(shaped.address));
|
|
5647
6300
|
if (room) {
|
|
5648
6301
|
shaped.address = room;
|
|
6302
|
+
readable.address = room.name;
|
|
5649
6303
|
notes.push(`\u4F1A\u8BAE\u5730\u70B9\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${room.name}(${room.id})`);
|
|
6304
|
+
} else {
|
|
6305
|
+
readable.address = String(shaped.address);
|
|
5650
6306
|
}
|
|
5651
6307
|
}
|
|
5652
6308
|
const personFields = ["hrm_members", "caller", "contacter"];
|
|
@@ -5658,42 +6314,476 @@ async function shapeBrowserValues(env, values) {
|
|
|
5658
6314
|
idPool.push(...ids);
|
|
5659
6315
|
}
|
|
5660
6316
|
if (idPool.length > 0) {
|
|
5661
|
-
const
|
|
5662
|
-
const toObject = (
|
|
6317
|
+
const people = await resolvePersonTokens(env, idPool);
|
|
6318
|
+
const toObject = (token) => people.get(token) ?? { id: token, name: token };
|
|
6319
|
+
const toName = (token) => people.get(token)?.name ?? token;
|
|
5663
6320
|
if (shaped.hrm_members !== void 0 && shaped.hrm_members !== "") {
|
|
5664
6321
|
const ids = String(shaped.hrm_members).split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
|
|
5665
6322
|
shaped.hrm_members = ids.map(toObject);
|
|
6323
|
+
readable.hrm_members = ids.map(toName).join("\u3001");
|
|
5666
6324
|
notes.push(`\u53C2\u4F1A\u4EBA\u5458\u6309\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${ids.length} \u4EBA`);
|
|
5667
6325
|
}
|
|
5668
6326
|
if (shaped.caller !== void 0 && shaped.caller !== "") {
|
|
5669
6327
|
const id = String(shaped.caller).trim();
|
|
5670
6328
|
shaped.caller = toObject(id);
|
|
6329
|
+
readable.caller = toName(id);
|
|
5671
6330
|
}
|
|
5672
6331
|
if (shaped.contacter !== void 0 && shaped.contacter !== "") {
|
|
5673
6332
|
const id = String(shaped.contacter).trim();
|
|
5674
6333
|
shaped.contacter = toObject(id);
|
|
6334
|
+
readable.contacter = toName(id);
|
|
6335
|
+
}
|
|
6336
|
+
const unresolved = [...new Set(idPool)].filter((token) => !people.has(token));
|
|
6337
|
+
if (unresolved.length > 0) {
|
|
6338
|
+
notes.push(
|
|
6339
|
+
`\u26A0\uFE0F \u6709 ${unresolved.length} \u4E2A\u4EBA\u5458\u6CA1\u89E3\u6790\u5230\u5458\u5DE5\uFF1A${unresolved.join("\u3001")} \u2014\u2014 \u8868\u5355\u91CC\u7684\u300C\u53C2\u4F1A\u4EBA\u5458/\u53EC\u96C6\u4EBA/\u8054\u7CFB\u4EBA\u300D\u53EF\u80FD\u663E\u793A\u4E0D\u51FA\u6765\u3002\u8BF7\u6539\u4F20\u5458\u5DE5 id\uFF0C\u6216\u786E\u8BA4\u59D3\u540D\u4E0E\u82B1\u540D\u518C\u5B8C\u5168\u4E00\u81F4\u3002`
|
|
6340
|
+
);
|
|
6341
|
+
}
|
|
6342
|
+
}
|
|
6343
|
+
if (shaped.crm_members !== void 0 && shaped.crm_members !== "") {
|
|
6344
|
+
const rows = [];
|
|
6345
|
+
const push = (idRaw, nameRaw) => {
|
|
6346
|
+
const id = String(idRaw ?? "").trim();
|
|
6347
|
+
const name = String(nameRaw ?? "").trim();
|
|
6348
|
+
if (id === "" && name === "") return;
|
|
6349
|
+
rows.push({ id, name });
|
|
6350
|
+
};
|
|
6351
|
+
const pushToken = (tokenRaw) => {
|
|
6352
|
+
const token = String(tokenRaw ?? "").trim();
|
|
6353
|
+
if (token === "") return;
|
|
6354
|
+
const matched = token.match(/^(.*?)[((]\s*([0-9A-Za-z_-]+)\s*[))]$/);
|
|
6355
|
+
if (matched) {
|
|
6356
|
+
push(matched[2], matched[1]);
|
|
6357
|
+
return;
|
|
6358
|
+
}
|
|
6359
|
+
if (/^\d{8,}$/.test(token)) {
|
|
6360
|
+
push(token, "");
|
|
6361
|
+
return;
|
|
6362
|
+
}
|
|
6363
|
+
push("", token);
|
|
6364
|
+
};
|
|
6365
|
+
const raw = shaped.crm_members;
|
|
6366
|
+
if (Array.isArray(raw)) {
|
|
6367
|
+
for (const item of raw) {
|
|
6368
|
+
if (item && typeof item === "object") {
|
|
6369
|
+
const obj = item;
|
|
6370
|
+
push(obj.id ?? obj.sjID ?? obj.customerId, obj.name ?? obj.mc);
|
|
6371
|
+
} else {
|
|
6372
|
+
for (const token of String(item).split(/[,;,;]+/).map((one) => one.trim()).filter((one) => one !== "")) {
|
|
6373
|
+
pushToken(token);
|
|
6374
|
+
}
|
|
6375
|
+
}
|
|
6376
|
+
}
|
|
6377
|
+
} else if (typeof raw === "object") {
|
|
6378
|
+
const obj = raw;
|
|
6379
|
+
push(obj.id ?? obj.sjID ?? obj.customerId, obj.name ?? obj.mc);
|
|
6380
|
+
} else {
|
|
6381
|
+
for (const token of String(raw).split(/[,;,;]+/).map((item) => item.trim()).filter((item) => item !== "")) {
|
|
6382
|
+
pushToken(token);
|
|
6383
|
+
}
|
|
6384
|
+
}
|
|
6385
|
+
if (rows.length > 0) {
|
|
6386
|
+
const nameOnly = rows.filter((row) => row.id === "" && row.name !== "");
|
|
6387
|
+
if (nameOnly.length > 0) {
|
|
6388
|
+
try {
|
|
6389
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6390
|
+
const search = getMeetingOperation2("meeting.eb.crm.search");
|
|
6391
|
+
for (const row of nameOnly) {
|
|
6392
|
+
const found = await search.handler({ keyword: row.name, limit: 5 }, env).catch(() => null);
|
|
6393
|
+
const items = found?.data?.items ?? [];
|
|
6394
|
+
const hit = items.find((item) => String(item?.name ?? "").trim() === row.name) ?? items[0];
|
|
6395
|
+
const id = String(hit?.customerId ?? "").trim();
|
|
6396
|
+
if (id === "") continue;
|
|
6397
|
+
row.id = id;
|
|
6398
|
+
const fullName = String(hit?.name ?? "").trim();
|
|
6399
|
+
if (fullName !== "") row.name = fullName;
|
|
6400
|
+
}
|
|
6401
|
+
} catch {
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6404
|
+
const unresolved = rows.filter((row) => row.id === "");
|
|
6405
|
+
if (unresolved.length > 0) {
|
|
6406
|
+
throw meetingValidationError(
|
|
6407
|
+
"crm_not_found",
|
|
6408
|
+
`\u53C2\u4F1A\u5BA2\u6237\u6709 ${unresolved.length} \u4E2A\u5728 CRM \u91CC\u67E5\u4E0D\u5230\uFF1A${unresolved.map((row) => row.name).join("\u3001")}\u3002\u8BF7\u786E\u8BA4\u5BA2\u6237\u540D\u79F0\uFF0C\u6216\u5148\u5230\u5BA2\u6237\u8868\u5EFA\u6863\uFF1B\u4E5F\u53EF\u4EE5\u6539\u7528\u300C\u5BA2\u6237\u540D(\u5BA2\u6237id)\u300D\u6216 \`[{id,name}]\` \u4F20 crm_members\u3002`
|
|
6409
|
+
);
|
|
6410
|
+
}
|
|
6411
|
+
shaped.crm_members = rows;
|
|
6412
|
+
readable.crm_members = rows.map((row) => row.name || row.id).join("\u3001");
|
|
6413
|
+
notes.push(`\u53C2\u4F1A\u5BA2\u6237\u6309\u5BA2\u6237\u6D4F\u89C8\u6309\u94AE\u683C\u5F0F\u63D0\u4EA4\uFF1A${rows.length} \u4E2A\u5BA2\u6237`);
|
|
6414
|
+
const missingNames = rows.filter((row) => row.name === "");
|
|
6415
|
+
if (missingNames.length > 0) {
|
|
6416
|
+
throw meetingValidationError(
|
|
6417
|
+
"crm_name_required",
|
|
6418
|
+
`\u53C2\u4F1A\u5BA2\u6237\u6709 ${missingNames.length} \u4E2A\u53EA\u7ED9\u4E86 id\u3001\u6CA1\u6709\u5BA2\u6237\u540D\u79F0\uFF1A${missingNames.map((row) => row.id).join("\u3001")}\u3002\u5BA2\u6237\u6D4F\u89C8\u6309\u94AE\u5FC5\u987B\u5E26\u540D\u79F0\u624D\u80FD\u5199\u5165\uFF08\u53EA\u7ED9 id \u4F1A\u88AB\u670D\u52A1\u7AEF\u9759\u9ED8\u5B58\u6210\u7A7A\u503C\uFF09\u3002\u8BF7\u5148\u7528 \`meeting.eb.crm.search\` \u6309\u5BA2\u6237\u540D\u67E5\u5230 \`{ customerId, name }\`\uFF0C\u518D\u4EE5 \`[{id,name}]\` \u6216\u300C\u5BA2\u6237\u540D(\u5BA2\u6237id)\u300D\u7684\u5F62\u5F0F\u4F20 \`crm_members\`\u3002`
|
|
6419
|
+
);
|
|
6420
|
+
}
|
|
6421
|
+
} else {
|
|
6422
|
+
delete shaped.crm_members;
|
|
6423
|
+
}
|
|
6424
|
+
}
|
|
6425
|
+
for (const [key, raw] of Object.entries(values)) {
|
|
6426
|
+
if (readable[key] !== void 0) continue;
|
|
6427
|
+
if (raw === void 0 || raw === null || raw === "") continue;
|
|
6428
|
+
if (typeof raw === "object") continue;
|
|
6429
|
+
readable[key] = String(raw);
|
|
6430
|
+
}
|
|
6431
|
+
return { values: shaped, notes, readable };
|
|
6432
|
+
}
|
|
6433
|
+
function normalizeFieldName(name) {
|
|
6434
|
+
return String(name ?? "").replace(/[((][^(())]*[))]/g, "").replace(/[\s\u3000]+/g, "").trim();
|
|
6435
|
+
}
|
|
6436
|
+
var CRM_DETAIL_COLUMNS = {
|
|
6437
|
+
xm: ["\u59D3\u540D", "\u5BA2\u6237\u59D3\u540D", "\u53C2\u4F1A\u4EBA", "\u53C2\u4F1A\u4EBA\u59D3\u540D"],
|
|
6438
|
+
xb: ["\u6027\u522B"],
|
|
6439
|
+
zw: ["\u804C\u4F4D", "\u804C\u52A1"],
|
|
6440
|
+
sjhm: ["\u624B\u673A\u53F7\u7801", "\u624B\u673A\u53F7", "\u624B\u673A", "\u7535\u8BDD", "\u8054\u7CFB\u7535\u8BDD"],
|
|
6441
|
+
bz: ["\u5907\u6CE8", "\u8BF4\u660E"]
|
|
6442
|
+
};
|
|
6443
|
+
function resolveCrmDetailTarget(fields) {
|
|
6444
|
+
const groups = /* @__PURE__ */ new Map();
|
|
6445
|
+
for (const field of fields) {
|
|
6446
|
+
const sid = String(field.subFormId ?? "").trim();
|
|
6447
|
+
if (!sid) continue;
|
|
6448
|
+
const list = groups.get(sid);
|
|
6449
|
+
if (list) list.push(field);
|
|
6450
|
+
else groups.set(sid, [field]);
|
|
6451
|
+
}
|
|
6452
|
+
let best = null;
|
|
6453
|
+
for (const [subFormId, list] of groups) {
|
|
6454
|
+
const columns = {};
|
|
6455
|
+
const labels = {};
|
|
6456
|
+
for (const [semantic, aliases] of Object.entries(CRM_DETAIL_COLUMNS)) {
|
|
6457
|
+
const hit = list.find((field) => aliases.includes(normalizeFieldName(field.name)));
|
|
6458
|
+
if (!hit) continue;
|
|
6459
|
+
columns[semantic] = hit.id;
|
|
6460
|
+
labels[semantic] = hit.name;
|
|
6461
|
+
}
|
|
6462
|
+
if (!columns.xm) continue;
|
|
6463
|
+
const score = Object.keys(columns).length + (columns.sjhm ? 1 : 0) + (columns.zw ? 1 : 0);
|
|
6464
|
+
if (!best || score > best.score) best = { subFormId, columns, labels, score };
|
|
6465
|
+
}
|
|
6466
|
+
return best ? { subFormId: best.subFormId, columns: best.columns, labels: best.labels } : null;
|
|
6467
|
+
}
|
|
6468
|
+
function detectCrmMentionInText(...texts) {
|
|
6469
|
+
for (const text of texts) {
|
|
6470
|
+
if (typeof text !== "string") continue;
|
|
6471
|
+
const value = text.trim();
|
|
6472
|
+
if (value === "") continue;
|
|
6473
|
+
const hit = /(?:参会|拜访|来访)?客户\s*(?:名称)?\s*(?:是|为|[::])\s*([^\s,,。;;、))]{2,40})/.exec(value);
|
|
6474
|
+
if (hit?.[1]) return hit[1].trim();
|
|
6475
|
+
}
|
|
6476
|
+
return null;
|
|
6477
|
+
}
|
|
6478
|
+
function normalizeCrmDetailRows(raw) {
|
|
6479
|
+
if (raw === void 0 || raw === null || raw === "") return [];
|
|
6480
|
+
const list = Array.isArray(raw) ? raw : [raw];
|
|
6481
|
+
const keyAlias = {
|
|
6482
|
+
xm: "xm",
|
|
6483
|
+
name: "xm",
|
|
6484
|
+
customername: "xm",
|
|
6485
|
+
\u59D3\u540D: "xm",
|
|
6486
|
+
\u5BA2\u6237\u59D3\u540D: "xm",
|
|
6487
|
+
xb: "xb",
|
|
6488
|
+
gender: "xb",
|
|
6489
|
+
sex: "xb",
|
|
6490
|
+
\u6027\u522B: "xb",
|
|
6491
|
+
zw: "zw",
|
|
6492
|
+
title: "zw",
|
|
6493
|
+
position: "zw",
|
|
6494
|
+
job: "zw",
|
|
6495
|
+
\u804C\u4F4D: "zw",
|
|
6496
|
+
\u804C\u52A1: "zw",
|
|
6497
|
+
sjhm: "sjhm",
|
|
6498
|
+
mobile: "sjhm",
|
|
6499
|
+
phone: "sjhm",
|
|
6500
|
+
tel: "sjhm",
|
|
6501
|
+
\u624B\u673A\u53F7\u7801: "sjhm",
|
|
6502
|
+
\u624B\u673A\u53F7: "sjhm",
|
|
6503
|
+
\u7535\u8BDD: "sjhm",
|
|
6504
|
+
\u8054\u7CFB\u7535\u8BDD: "sjhm",
|
|
6505
|
+
bz: "bz",
|
|
6506
|
+
remark: "bz",
|
|
6507
|
+
note: "bz",
|
|
6508
|
+
\u5907\u6CE8: "bz",
|
|
6509
|
+
\u8BF4\u660E: "bz"
|
|
6510
|
+
};
|
|
6511
|
+
const rows = [];
|
|
6512
|
+
for (const item of list) {
|
|
6513
|
+
if (item === void 0 || item === null || typeof item !== "object") continue;
|
|
6514
|
+
const row = {};
|
|
6515
|
+
for (const [key, value] of Object.entries(item)) {
|
|
6516
|
+
const semantic = keyAlias[String(key).trim().toLowerCase()] ?? keyAlias[String(key).trim()];
|
|
6517
|
+
if (!semantic) continue;
|
|
6518
|
+
if (value === void 0 || value === null) continue;
|
|
6519
|
+
const text = String(value).trim();
|
|
6520
|
+
if (text === "") continue;
|
|
6521
|
+
row[semantic] = text;
|
|
6522
|
+
}
|
|
6523
|
+
if (!row.xm && !row.sjhm) continue;
|
|
6524
|
+
rows.push(row);
|
|
6525
|
+
}
|
|
6526
|
+
return rows;
|
|
6527
|
+
}
|
|
6528
|
+
function crmMemberEntriesFromArgs(raw) {
|
|
6529
|
+
const list = Array.isArray(raw) ? raw : raw === void 0 || raw === null || raw === "" ? [] : [raw];
|
|
6530
|
+
const out = [];
|
|
6531
|
+
const push = (idRaw, nameRaw, contactsRaw) => {
|
|
6532
|
+
const id = String(idRaw ?? "").trim();
|
|
6533
|
+
const name = String(nameRaw ?? "").trim();
|
|
6534
|
+
if (id === "" && name === "") return;
|
|
6535
|
+
const contacts = (Array.isArray(contactsRaw) ? contactsRaw : []).map((item) => {
|
|
6536
|
+
const row = item ?? {};
|
|
6537
|
+
return {
|
|
6538
|
+
name: String(row.name ?? row.xm ?? "").trim(),
|
|
6539
|
+
mobile: String(row.mobile ?? row.sjhm ?? row.phone ?? "").trim(),
|
|
6540
|
+
...String(row.dept ?? row.bm ?? "").trim() === "" ? {} : { dept: String(row.dept ?? row.bm).trim() }
|
|
6541
|
+
};
|
|
6542
|
+
}).filter((one) => one.name !== "" || one.mobile !== "");
|
|
6543
|
+
out.push({ id: id === "" ? name : id, name, contacts });
|
|
6544
|
+
};
|
|
6545
|
+
for (const item of list) {
|
|
6546
|
+
if (item && typeof item === "object") {
|
|
6547
|
+
const obj = item;
|
|
6548
|
+
push(obj.customerId ?? obj.sjID ?? obj.id, obj.name ?? obj.mc, obj.contacts ?? obj.lxr);
|
|
6549
|
+
} else {
|
|
6550
|
+
const token = String(item).trim();
|
|
6551
|
+
if (token === "") continue;
|
|
6552
|
+
const matched = token.match(/^(.*?)[((]\s*([0-9A-Za-z_-]+)\s*[))]$/);
|
|
6553
|
+
if (matched) push(matched[2], matched[1], void 0);
|
|
6554
|
+
else push(token, "", void 0);
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
return out;
|
|
6558
|
+
}
|
|
6559
|
+
function crmContactsToDetailRows(entries) {
|
|
6560
|
+
const rows = [];
|
|
6561
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6562
|
+
for (const entry of entries) {
|
|
6563
|
+
for (const contact of entry.contacts) {
|
|
6564
|
+
const xm = contact.name.trim();
|
|
6565
|
+
const sjhm = contact.mobile.trim();
|
|
6566
|
+
if (xm === "" && sjhm === "") continue;
|
|
6567
|
+
const key = `${xm}|${sjhm}`;
|
|
6568
|
+
if (seen.has(key)) continue;
|
|
6569
|
+
seen.add(key);
|
|
6570
|
+
const row = { xm: xm === "" ? sjhm : xm };
|
|
6571
|
+
if (sjhm !== "") row.sjhm = sjhm;
|
|
6572
|
+
if (contact.dept && contact.dept.trim() !== "") row.bz = `\u90E8\u95E8\uFF1A${contact.dept.trim()}`;
|
|
6573
|
+
rows.push(row);
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
return rows;
|
|
6577
|
+
}
|
|
6578
|
+
async function resolveAutoCrmDetailRows(env, raw) {
|
|
6579
|
+
const entries = crmMemberEntriesFromArgs(raw);
|
|
6580
|
+
const missing = [];
|
|
6581
|
+
if (entries.length > 0) {
|
|
6582
|
+
try {
|
|
6583
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6584
|
+
const search = getMeetingOperation2("meeting.eb.crm.search");
|
|
6585
|
+
for (const entry of entries) {
|
|
6586
|
+
const keyword = (entry.name || entry.id).trim();
|
|
6587
|
+
if (keyword === "") {
|
|
6588
|
+
missing.push(entry.id);
|
|
6589
|
+
continue;
|
|
6590
|
+
}
|
|
6591
|
+
const searchOnce = async (kw) => {
|
|
6592
|
+
const found = await search.handler({ keyword: kw, limit: 5 }, env).catch(() => null);
|
|
6593
|
+
const items = found?.data?.items ?? [];
|
|
6594
|
+
const hit = items.find((item) => String(item?.customerId ?? "") === entry.id) ?? items[0];
|
|
6595
|
+
return hit?.contacts ?? [];
|
|
6596
|
+
};
|
|
6597
|
+
let live = await searchOnce(keyword);
|
|
6598
|
+
if (live.length === 0 && keyword.includes("--")) {
|
|
6599
|
+
const short = keyword.split("--")[0].trim();
|
|
6600
|
+
if (short !== "") live = await searchOnce(short);
|
|
6601
|
+
}
|
|
6602
|
+
if (live.length === 0) {
|
|
6603
|
+
if (entry.contacts.length === 0) missing.push(entry.name || entry.id);
|
|
6604
|
+
continue;
|
|
6605
|
+
}
|
|
6606
|
+
const keyOf = (one) => `${String(one.name ?? "").trim()}|${String(one.mobile ?? "").trim()}`;
|
|
6607
|
+
const merged = /* @__PURE__ */ new Map();
|
|
6608
|
+
for (const one of live) merged.set(keyOf(one), one);
|
|
6609
|
+
for (const one of entry.contacts) {
|
|
6610
|
+
const key = keyOf(one);
|
|
6611
|
+
const base = merged.get(key);
|
|
6612
|
+
merged.set(key, base ? { ...base, ...one } : one);
|
|
6613
|
+
}
|
|
6614
|
+
entry.contacts = [...merged.values()];
|
|
6615
|
+
}
|
|
6616
|
+
} catch {
|
|
5675
6617
|
}
|
|
5676
6618
|
}
|
|
5677
|
-
return {
|
|
6619
|
+
return {
|
|
6620
|
+
rows: crmContactsToDetailRows(entries),
|
|
6621
|
+
customers: entries.map((entry) => entry.name || entry.id).filter((one) => one !== ""),
|
|
6622
|
+
missing
|
|
6623
|
+
};
|
|
5678
6624
|
}
|
|
5679
|
-
function mapFields(fields, values) {
|
|
6625
|
+
function mapFields(fields, values, preferred = {}) {
|
|
5680
6626
|
const byName = new Map(fields.map((field) => [field.name.trim(), field]));
|
|
6627
|
+
const byId = new Map(fields.map((field) => [field.id, field]));
|
|
6628
|
+
const byNormalized = /* @__PURE__ */ new Map();
|
|
6629
|
+
for (const field of fields) {
|
|
6630
|
+
const key = normalizeFieldName(field.name);
|
|
6631
|
+
if (key && !byNormalized.has(key)) byNormalized.set(key, field);
|
|
6632
|
+
}
|
|
5681
6633
|
const main = {};
|
|
5682
6634
|
const mapped = {};
|
|
5683
6635
|
const unmapped = [];
|
|
6636
|
+
const resolved = {};
|
|
6637
|
+
const findField = (aliases) => {
|
|
6638
|
+
for (const name of aliases) {
|
|
6639
|
+
const field = byName.get(name);
|
|
6640
|
+
if (field) return field;
|
|
6641
|
+
}
|
|
6642
|
+
for (const name of aliases) {
|
|
6643
|
+
const field = byNormalized.get(normalizeFieldName(name));
|
|
6644
|
+
if (field) return field;
|
|
6645
|
+
}
|
|
6646
|
+
for (const name of aliases) {
|
|
6647
|
+
const needle = normalizeFieldName(name);
|
|
6648
|
+
if (needle.length < 2) continue;
|
|
6649
|
+
for (const [key, field] of byNormalized) {
|
|
6650
|
+
if (key.includes(needle)) return field;
|
|
6651
|
+
}
|
|
6652
|
+
}
|
|
6653
|
+
return void 0;
|
|
6654
|
+
};
|
|
5684
6655
|
for (const [key, raw] of Object.entries(values)) {
|
|
5685
6656
|
if (raw === void 0 || raw === null || raw === "") continue;
|
|
5686
6657
|
const aliases = FIELD_ALIASES[key] ?? [key];
|
|
5687
|
-
const
|
|
6658
|
+
const prefId = preferred[key];
|
|
6659
|
+
const hit = (prefId ? byId.get(prefId) : void 0) ?? findField(aliases);
|
|
5688
6660
|
if (!hit) {
|
|
5689
6661
|
unmapped.push(key);
|
|
5690
6662
|
continue;
|
|
5691
6663
|
}
|
|
5692
6664
|
main[hit.id] = raw;
|
|
5693
6665
|
mapped[key] = `${hit.name}(${hit.id})`;
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
}
|
|
6666
|
+
resolved[key] = hit.id;
|
|
6667
|
+
}
|
|
6668
|
+
return { main, mapped, unmapped, resolved };
|
|
6669
|
+
}
|
|
6670
|
+
var PREVIEW_PERSON_FIELD_RE = /^(召集人|联系人|参会人员|会议创建人|主讲人|负责人|费用承担人)$/;
|
|
6671
|
+
async function decoratePreviewPersonNames(env, main, fields, known = /* @__PURE__ */ new Map()) {
|
|
6672
|
+
const targets = fields.filter((field) => PREVIEW_PERSON_FIELD_RE.test(String(field?.name ?? "").trim()));
|
|
6673
|
+
if (targets.length === 0) return main;
|
|
6674
|
+
const ID_ONLY_RE = /^\d{8,}$/;
|
|
6675
|
+
const missingNameId = (value) => {
|
|
6676
|
+
if (typeof value === "string") return ID_ONLY_RE.test(value.trim()) ? value.trim() : null;
|
|
6677
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
6678
|
+
const obj = value;
|
|
6679
|
+
const id = String(obj.id ?? "").trim();
|
|
6680
|
+
const name = String(obj.name ?? "").trim();
|
|
6681
|
+
if (id !== "" && (name === "" || name === id)) return id;
|
|
6682
|
+
}
|
|
6683
|
+
return null;
|
|
6684
|
+
};
|
|
6685
|
+
const ids = /* @__PURE__ */ new Set();
|
|
6686
|
+
for (const field of targets) {
|
|
6687
|
+
const value = main[field.id];
|
|
6688
|
+
const one = missingNameId(value);
|
|
6689
|
+
if (one) ids.add(one);
|
|
6690
|
+
else if (Array.isArray(value)) for (const item of value) {
|
|
6691
|
+
const hit = missingNameId(item);
|
|
6692
|
+
if (hit) ids.add(hit);
|
|
6693
|
+
}
|
|
6694
|
+
}
|
|
6695
|
+
if (ids.size === 0) return main;
|
|
6696
|
+
let names = new Map(known);
|
|
6697
|
+
const unknown = [...ids].filter((id) => !names.has(id));
|
|
6698
|
+
if (unknown.length > 0) {
|
|
6699
|
+
try {
|
|
6700
|
+
const resolved = await resolveEmployeeNames(env, unknown);
|
|
6701
|
+
for (const [id, name] of resolved) names.set(id, name);
|
|
6702
|
+
} catch {
|
|
6703
|
+
}
|
|
6704
|
+
}
|
|
6705
|
+
if (names.size === 0) return main;
|
|
6706
|
+
const rename = (value) => {
|
|
6707
|
+
const one = missingNameId(value);
|
|
6708
|
+
if (one) return names.get(one) ?? value;
|
|
6709
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
6710
|
+
const obj = value;
|
|
6711
|
+
const id = String(obj.id ?? "").trim();
|
|
6712
|
+
const name = names.get(id);
|
|
6713
|
+
if (name) return { ...obj, name };
|
|
6714
|
+
}
|
|
6715
|
+
return value;
|
|
6716
|
+
};
|
|
6717
|
+
const decorated = { ...main };
|
|
6718
|
+
for (const field of targets) {
|
|
6719
|
+
const value = decorated[field.id];
|
|
6720
|
+
decorated[field.id] = Array.isArray(value) ? value.map(rename) : rename(value);
|
|
6721
|
+
}
|
|
6722
|
+
return decorated;
|
|
6723
|
+
}
|
|
6724
|
+
function renderFormPreview(fields, main) {
|
|
6725
|
+
const fmt = (value) => {
|
|
6726
|
+
if (value === void 0 || value === null) return "\u2014";
|
|
6727
|
+
if (Array.isArray(value)) {
|
|
6728
|
+
const parts = value.map((one) => fmt(one)).filter((one) => one !== "\u2014");
|
|
6729
|
+
return parts.length > 0 ? parts.join("\u3001") : "\u2014";
|
|
6730
|
+
}
|
|
6731
|
+
if (typeof value === "object") {
|
|
6732
|
+
const obj = value;
|
|
6733
|
+
const name = String(obj.name ?? obj.mc ?? "").trim();
|
|
6734
|
+
if (name !== "") return name.replace(/\|/gu, "/");
|
|
6735
|
+
const id = String(obj.id ?? obj.customerId ?? obj.sjID ?? "").trim();
|
|
6736
|
+
return id === "" ? "\u2014" : id;
|
|
6737
|
+
}
|
|
6738
|
+
const text = String(value).trim();
|
|
6739
|
+
return text === "" ? "\u2014" : text.replace(/\|/gu, "/").replace(/\r?\n/gu, " ");
|
|
6740
|
+
};
|
|
6741
|
+
const lines = ["| \u5B57\u6BB5 | \u503C |", "| --- | --- |"];
|
|
6742
|
+
const known = /* @__PURE__ */ new Set();
|
|
6743
|
+
for (const field of fields) {
|
|
6744
|
+
known.add(field.id);
|
|
6745
|
+
if (!(field.id in main)) continue;
|
|
6746
|
+
lines.push(`| ${String(field.name).replace(/\|/gu, "/")} | ${fmt(main[field.id])} |`);
|
|
6747
|
+
}
|
|
6748
|
+
for (const [id, value] of Object.entries(main)) {
|
|
6749
|
+
if (known.has(id)) continue;
|
|
6750
|
+
lines.push(`| ${id} | ${fmt(value)} |`);
|
|
6751
|
+
}
|
|
6752
|
+
return lines.join("\n");
|
|
6753
|
+
}
|
|
6754
|
+
function flowFieldCacheDir(env) {
|
|
6755
|
+
const configured = env?.ctx?.config?.path?.();
|
|
6756
|
+
const root = configured ? resolve5(String(configured), "..") : process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve5(homedir(), ".weaver-work-cli");
|
|
6757
|
+
return resolve5(root, "meeting", "cache");
|
|
6758
|
+
}
|
|
6759
|
+
function flowFieldCacheFile(env, workflowId) {
|
|
6760
|
+
return resolve5(flowFieldCacheDir(env), `flow-fields-${workflowId}.json`);
|
|
6761
|
+
}
|
|
6762
|
+
async function readFlowFieldMap(env, workflowId) {
|
|
6763
|
+
try {
|
|
6764
|
+
const file = flowFieldCacheFile(env, workflowId);
|
|
6765
|
+
if (!existsSync3(file)) return {};
|
|
6766
|
+
const parsed = JSON.parse(await readFile4(file, "utf8"));
|
|
6767
|
+
return parsed && typeof parsed.mapping === "object" && parsed.mapping ? parsed.mapping : {};
|
|
6768
|
+
} catch {
|
|
6769
|
+
return {};
|
|
6770
|
+
}
|
|
6771
|
+
}
|
|
6772
|
+
async function writeFlowFieldMap(env, workflowId, workflowName, mapping) {
|
|
6773
|
+
if (Object.keys(mapping).length === 0) return;
|
|
6774
|
+
try {
|
|
6775
|
+
const file = flowFieldCacheFile(env, workflowId);
|
|
6776
|
+
await mkdir4(resolve5(file, ".."), { recursive: true });
|
|
6777
|
+
const cache = {
|
|
6778
|
+
workflowId,
|
|
6779
|
+
...workflowName ? { workflowName } : {},
|
|
6780
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6781
|
+
mapping
|
|
6782
|
+
};
|
|
6783
|
+
await writeFile4(file, JSON.stringify(cache, null, 2), "utf8");
|
|
6784
|
+
} catch {
|
|
6785
|
+
}
|
|
6786
|
+
}
|
|
5697
6787
|
function normalizeWorkflowIds(raw) {
|
|
5698
6788
|
if (raw === void 0 || raw === null) return [];
|
|
5699
6789
|
const list = Array.isArray(raw) ? raw : [raw];
|
|
@@ -5709,6 +6799,45 @@ function normalizeWorkflowIds(raw) {
|
|
|
5709
6799
|
}
|
|
5710
6800
|
return ids;
|
|
5711
6801
|
}
|
|
6802
|
+
var FIXED_FLOW_IDS = ["1325677244111462606", "1326190634427154474"];
|
|
6803
|
+
var FIXED_FLOW_PROFILES = [
|
|
6804
|
+
{
|
|
6805
|
+
host: "www.e-cology.com.cn",
|
|
6806
|
+
tenantKey: "t7akvdnf84",
|
|
6807
|
+
label: "\u6CDB\u5FAE\u751F\u4EA7\uFF08\u6CDB\u5FAE\u7F51\u7EDC\uFF09",
|
|
6808
|
+
ids: [...FIXED_FLOW_IDS]
|
|
6809
|
+
}
|
|
6810
|
+
];
|
|
6811
|
+
function fixedFlowFlagOn() {
|
|
6812
|
+
const flag = String(process.env.WEAVER_MEETING_FIXED_FLOW ?? "1").trim().toLowerCase();
|
|
6813
|
+
return !(flag === "0" || flag === "false" || flag === "off");
|
|
6814
|
+
}
|
|
6815
|
+
function fixedFlowOverride() {
|
|
6816
|
+
const override = String(process.env.WEAVER_MEETING_FIXED_FLOW_IDS ?? "").trim();
|
|
6817
|
+
if (!override) return [];
|
|
6818
|
+
return override.split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
|
|
6819
|
+
}
|
|
6820
|
+
async function fixedFlowIdsForEnv(env) {
|
|
6821
|
+
if (!fixedFlowFlagOn()) return { ids: [] };
|
|
6822
|
+
const override = fixedFlowOverride();
|
|
6823
|
+
if (override.length > 0) return { ids: override, label: "\u73AF\u5883\u53D8\u91CF\u6307\u5B9A" };
|
|
6824
|
+
let baseUrl = "";
|
|
6825
|
+
let tenantKey = "";
|
|
6826
|
+
try {
|
|
6827
|
+
const session = await env?.host?.getSession?.();
|
|
6828
|
+
baseUrl = String(session?.baseUrl ?? "");
|
|
6829
|
+
tenantKey = String(session?.tenantKey ?? session?.tenantId ?? "");
|
|
6830
|
+
} catch {
|
|
6831
|
+
}
|
|
6832
|
+
if (!baseUrl) return { ids: [...FIXED_FLOW_IDS], label: "\u9ED8\u8BA4\u56FA\u5316\u914D\u7F6E\uFF08\u672A\u53D6\u5230\u767B\u5F55\u73AF\u5883\uFF09" };
|
|
6833
|
+
const host = baseUrl.replace(/^https?:\/\//i, "").replace(/\/.*$/, "").toLowerCase();
|
|
6834
|
+
const hit = FIXED_FLOW_PROFILES.find((profile) => profile.host === host && (!profile.tenantKey || !tenantKey || profile.tenantKey === tenantKey));
|
|
6835
|
+
return hit ? { ids: [...hit.ids], label: hit.label } : { ids: [] };
|
|
6836
|
+
}
|
|
6837
|
+
function shouldAutoPickFlow(args) {
|
|
6838
|
+
if (args.flowChoice === "auto") return true;
|
|
6839
|
+
return String(process.env.WEAVER_MEETING_FLOW_CHOICE ?? "").trim().toLowerCase() === "auto";
|
|
6840
|
+
}
|
|
5712
6841
|
async function resolveWorkflowId(env, args) {
|
|
5713
6842
|
const explicitList = normalizeWorkflowIds(args.workflowId);
|
|
5714
6843
|
if (explicitList.length > 0) {
|
|
@@ -5718,37 +6847,113 @@ async function resolveWorkflowId(env, args) {
|
|
|
5718
6847
|
source: "argument"
|
|
5719
6848
|
};
|
|
5720
6849
|
}
|
|
6850
|
+
const fixed = await fixedFlowIdsForEnv(env);
|
|
6851
|
+
if (fixed.ids.length > 0) {
|
|
6852
|
+
return {
|
|
6853
|
+
workflowId: fixed.ids.length === 1 ? fixed.ids[0] : "",
|
|
6854
|
+
candidates: fixed.ids,
|
|
6855
|
+
source: "fixed",
|
|
6856
|
+
...fixed.label ? { label: fixed.label } : {}
|
|
6857
|
+
};
|
|
6858
|
+
}
|
|
5721
6859
|
const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
|
|
5722
6860
|
const candidates = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
|
|
5723
6861
|
if (candidates.length === 0) {
|
|
5724
6862
|
throw meetingValidationError(
|
|
5725
6863
|
"flow_not_configured",
|
|
5726
|
-
"\u5E94\u7528\u8BBE\u7F6E\u91CC\u6CA1\u6709\u914D\u7F6E\u300C\u65B0\u5EFA\u4F1A\u8BAE\u5DE5\u4F5C\u6D41\u300D\uFF08mt_new_wf \u4E3A\u7A7A\uFF09\uFF0C\u65E0\u6CD5\u8D70\u6D41\u7A0B\u5EFA\u4F1A\uFF1B\u8BF7\u7BA1\u7406\u5458\u5728\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u91CC\u914D\u7F6E\uFF0C\u6216\
|
|
6864
|
+
"\u5E94\u7528\u8BBE\u7F6E\u91CC\u6CA1\u6709\u914D\u7F6E\u300C\u65B0\u5EFA\u4F1A\u8BAE\u5DE5\u4F5C\u6D41\u300D\uFF08mt_new_wf \u4E3A\u7A7A\uFF09\uFF0C\u4E5F\u6CA1\u6709\u542F\u7528\u56FA\u5316\u6D41\u7A0B\uFF0C\u65E0\u6CD5\u8D70\u6D41\u7A0B\u5EFA\u4F1A\uFF1B\u8BF7\u7BA1\u7406\u5458\u5728\u4F1A\u8BAE\u5E94\u7528\u8BBE\u7F6E\u91CC\u914D\u7F6E\uFF0C\u6216\u7528 WEAVER_MEETING_FIXED_FLOW_IDS \u6307\u5B9A\u9ED8\u8BA4\u6D41\u7A0B"
|
|
5727
6865
|
);
|
|
5728
6866
|
}
|
|
5729
6867
|
return { workflowId: candidates.length === 1 ? candidates[0] : "", candidates, source: "settings" };
|
|
5730
6868
|
}
|
|
6869
|
+
function pad2(value) {
|
|
6870
|
+
return String(value).padStart(2, "0");
|
|
6871
|
+
}
|
|
6872
|
+
function tomorrowIso() {
|
|
6873
|
+
const date = new Date(Date.now() + 24 * 60 * 60 * 1e3);
|
|
6874
|
+
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
|
|
6875
|
+
}
|
|
6876
|
+
function formatMinute(date) {
|
|
6877
|
+
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
|
|
6878
|
+
}
|
|
6879
|
+
async function probeWorkflowCandidates(env, ids) {
|
|
6880
|
+
const probed = await Promise.all(ids.map(async (id) => {
|
|
6881
|
+
try {
|
|
6882
|
+
const probeForm = await loadCreateForm(env, id);
|
|
6883
|
+
return {
|
|
6884
|
+
id,
|
|
6885
|
+
probeForm,
|
|
6886
|
+
probe: {
|
|
6887
|
+
workflowId: id,
|
|
6888
|
+
...probeForm.workflowName ? { name: probeForm.workflowName } : {},
|
|
6889
|
+
launchable: true
|
|
6890
|
+
}
|
|
6891
|
+
};
|
|
6892
|
+
} catch (error) {
|
|
6893
|
+
return {
|
|
6894
|
+
id,
|
|
6895
|
+
probeForm: null,
|
|
6896
|
+
probe: {
|
|
6897
|
+
workflowId: id,
|
|
6898
|
+
launchable: false,
|
|
6899
|
+
reason: String(error?.message ?? error).slice(0, 160)
|
|
6900
|
+
}
|
|
6901
|
+
};
|
|
6902
|
+
}
|
|
6903
|
+
}));
|
|
6904
|
+
const probes = [];
|
|
6905
|
+
const loadedForms = /* @__PURE__ */ new Map();
|
|
6906
|
+
for (const item of probed) {
|
|
6907
|
+
if (item.probeForm) loadedForms.set(item.id, item.probeForm);
|
|
6908
|
+
probes.push(item.probe);
|
|
6909
|
+
}
|
|
6910
|
+
return { probes, loadedForms };
|
|
6911
|
+
}
|
|
5731
6912
|
var ebMeetingCreateFlowPrepare = {
|
|
5732
6913
|
name: "meeting.eb.meeting.create.flow.prepare",
|
|
5733
6914
|
resource: "eb",
|
|
5734
6915
|
method: "meeting.eb.meeting.create.flow.prepare",
|
|
5735
6916
|
action: "meeting.eb.meeting.create.flow.prepare",
|
|
5736
|
-
summary:
|
|
6917
|
+
summary: '\u6D41\u7A0B\u5EFA\u4F1A\uFF08\u51C6\u5907\uFF09\uFF1A\u7528\u56FA\u5316\u6D41\u7A0B\u5019\u9009\u9010\u4E2A\u63A2\u6D4B\u53D1\u8D77\u6743\u9650 \u2014\u2014 \u4EC5 1 \u4E2A\u53EF\u53D1\u8D77\u5C31\u81EA\u52A8\u7528\u5B83\u3001\u591A\u4E2A\u90FD\u53EF\u53D1\u8D77\u5219\u8FD4\u56DE\u9009\u9879\u8BA9\u7528\u6237\u9009\u3001\u90FD\u4E0D\u53EF\u53D1\u8D77\u62A5\u300C\u6CA1\u6709\u53D1\u8D77\u6743\u9650\u300D\uFF1B\u4E0D\u4F20 begin_datetime \u65F6\u81EA\u52A8\u63A8\u8350\u300C\u4EBA+\u4F1A\u8BAE\u5BA4\u90FD\u7A7A\u95F2\u300D\u7684\u65F6\u6BB5\u3002\u53EA\u51FA\u9884\u89C8\u4E0E\u786E\u8BA4\u7968\u636E\uFF0C\u4E0D\u63D0\u4EA4\u3002\u26A0\uFE0F \u7528\u6237\u63D0\u5230\u5BA2\u6237\u540D\uFF08\u300C\u5BA2\u6237\u662F X\u300D\uFF09\u65F6**\u5FC5\u987B\u5148** meeting.eb.crm.search {"keyword":"X"} \u62FF customerId\uFF0C\u518D\u4F20 crm_members:[{id,name}]\uFF1B\u53EA\u628A\u5BA2\u6237\u540D\u5199\u8FDB\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\uFF0C\u8868\u5355\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5C31\u662F\u7A7A\u7684',
|
|
5737
6918
|
capability: "eb.meeting",
|
|
5738
6919
|
risk: "read-before-write",
|
|
5739
6920
|
requiresConfirmation: true,
|
|
5740
6921
|
inputSchema: schemaOf(
|
|
5741
6922
|
{
|
|
5742
6923
|
mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
|
|
5743
|
-
begin_datetime: {
|
|
5744
|
-
|
|
6924
|
+
begin_datetime: {
|
|
6925
|
+
...SCHEMA_DATETIME_MINUTE,
|
|
6926
|
+
description: "\u5F00\u59CB\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\u3002**\u53EF\u4EE5\u4E0D\u4F20**\uFF1A\u4E0D\u4F20\u4F1A\u6309\u53C2\u4F1A\u4EBA\u4E0E\u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u60C5\u51B5\u63A8\u8350 3 \u4E2A\u65F6\u6BB5\u8BA9\u4F60\u9009\uFF1B\u53EA\u4F20\u5F00\u59CB\u65F6\u95F4\u3001\u4E0D\u4F20\u7ED3\u675F\u65F6\u95F4\u65F6\uFF0C\u6309 durationMinutes\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09\u81EA\u52A8\u7B97\u7ED3\u675F\u65F6\u95F4"
|
|
6927
|
+
},
|
|
6928
|
+
end_datetime: {
|
|
6929
|
+
...SCHEMA_DATETIME_MINUTE,
|
|
6930
|
+
description: "\u7ED3\u675F\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\uFF1B\u4E0D\u4F20\u5219\u6309 durationMinutes \u4ECE\u5F00\u59CB\u65F6\u95F4\u63A8\u7B97\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09"
|
|
6931
|
+
},
|
|
5745
6932
|
mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
|
|
5746
6933
|
address: { type: "string", description: "\u4F1A\u8BAE\u5BA4\uFF08\u540D\u79F0\u6216 id\uFF0C\u6309\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u8981\u6C42\uFF09" },
|
|
5747
6934
|
customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
|
|
5748
6935
|
hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458\uFF08\u9017\u53F7\u5206\u9694\u5458\u5DE5 id \u6216\u59D3\u540D\uFF0C\u6309\u6D41\u7A0B\u8868\u5355\u8981\u6C42\uFF09" },
|
|
5749
6936
|
total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
|
|
5750
|
-
|
|
5751
|
-
|
|
6937
|
+
crm_members: {
|
|
6938
|
+
oneOf: [{ type: "string" }, { type: "array", items: { oneOf: [{ type: "string" }, { type: "object" }] } }],
|
|
6939
|
+
description: "\u53C2\u4F1A\u5BA2\u6237\uFF1A**\u5FC5\u987B\u5E26\u5BA2\u6237\u540D\u79F0**\uFF0C\u5199\u6CD5 `[{id,name}]` \u6216\u300C\u5BA2\u6237\u540D(\u5BA2\u6237id)\u300D\u6216\u9017\u53F7\u5206\u9694\u7684\u8FD9\u4E24\u79CD\u3002\u5BA2\u6237\u5148\u4ECE `meeting.eb.crm.search` \u6309\u5BA2\u6237\u540D\u67E5\u51FA\uFF08\u5165\u53C2 custom_name\uFF0C\u51FA\u53C2 items[].customerId / name\uFF09\uFF0C\u8BE5\u67E5\u8BE2**\u4E00\u6B21\u53EA\u56DE\u9996\u4E2A\u5339\u914D** \u21D2 exact=false \u65F6\u5FC5\u987B\u5148\u8BA9\u7528\u6237\u786E\u8BA4\u5BA2\u6237\u540D\u518D\u5199\u8FD9\u4E2A\u5B57\u6BB5\u3002\u26D4 \u53EA\u7ED9 id \u4E0D\u7ED9\u540D\u79F0\u4F1A\u88AB\u62D2\u7EDD\uFF08\u5BA2\u6237\u6D4F\u89C8\u6309\u94AE\u6309\u540D\u79F0\u843D\u503C\uFF0C\u53EA\u7ED9 id \u4F1A\u9759\u9ED8\u5B58\u6210\u7A7A\uFF09"
|
|
6940
|
+
},
|
|
6941
|
+
crm_member_count: { type: "number", description: "\u5E94\u5230\u5BA2\u6237\u6570\uFF1B\u4E0D\u4F20\u5219\u6309 crm_members \u6761\u6570\u81EA\u52A8\u7B97" },
|
|
6942
|
+
crm_member_details: {
|
|
6943
|
+
type: "array",
|
|
6944
|
+
description: '\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\uFF08\u5BBF\u4E3B\u8868\u5355\u91CC\u7684\u660E\u7EC6\u8868\uFF0C\u5217 \u59D3\u540D/\u6027\u522B/\u804C\u4F4D/\u624B\u673A\u53F7\u7801/\u5907\u6CE8\uFF09\uFF1A\u6BCF\u884C `{"xm":"\u5F20\u4E09","xb":"\u7537","zw":"\u7ECF\u7406","sjhm":"138...","bz":""}`\uFF0C\u4E5F\u63A5\u53D7\u4E2D\u6587\u952E\uFF08\u59D3\u540D/\u6027\u522B/\u804C\u4F4D/\u624B\u673A\u53F7\u7801/\u5907\u6CE8\uFF09\u3002\u5217\u5B57\u6BB5 id \u7531 CLI \u4ECE\u8868\u5355\u91CC\u6309\u5217\u540D\u53CD\u67E5\uFF0C\u4E0D\u7528\u4F20\u3002\u26A0\uFE0F \u8BE5\u660E\u7EC6\u8868\u5FC5\u987B\u5728\u53D1\u8D77\u8282\u70B9\u5E03\u5C40\u91CC\uFF08\u5426\u5219 CLI \u4F1A\u63D0\u793A"\u8868\u5355\u91CC\u6CA1\u6709\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6"\u5E76\u5FFD\u7565\u8FD9\u4E9B\u884C\uFF09\u26D4 \u9ED8\u8BA4\u4E0D\u751F\u6548\uFF1A\u5BA2\u6237\u8054\u7CFB\u4EBA\u7531 CLI \u6309 CRM \u5168\u91CF\u81EA\u52A8\u5E26\u5165\uFF0C\u8FD9\u91CC\u53EA\u5728 crm_detail_mode:"only" \u65F6\u624D\u7528\u6765"\u53EA\u5199\u8FD9\u51E0\u4F4D"',
|
|
6945
|
+
items: { type: "object" }
|
|
6946
|
+
},
|
|
6947
|
+
crm_detail_mode: {
|
|
6948
|
+
type: "string",
|
|
6949
|
+
description: '\u660E\u7EC6\u884C\u53E3\u5F84\uFF1A\u4E0D\u4F20\uFF08\u9ED8\u8BA4\uFF09= \u6309 CRM \u628A\u8BE5\u5BA2\u6237**\u5168\u90E8**\u8054\u7CFB\u4EBA\u81EA\u52A8\u5199\u5165\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\uFF08\u4E00\u4EBA\u4E00\u884C\uFF0C\u4E0D\u7528\u95EE\u7528\u6237\u9009\u54EA\u4F4D\uFF09\uFF1B\u4F20 "only" = \u53EA\u5199 crm_member_details \u91CC\u70B9\u540D\u7684\u8FD9\u51E0\u4F4D'
|
|
6950
|
+
},
|
|
6951
|
+
caller: { type: "string", description: "\u53EC\u96C6\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u53EC\u96C6\u4EBA\u624D\u4F20" },
|
|
6952
|
+
contacter: { type: "string", description: "\u8054\u7CFB\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u8054\u7CFB\u4EBA\u624D\u4F20" },
|
|
6953
|
+
mt_type: {
|
|
6954
|
+
type: "string",
|
|
6955
|
+
description: "\u4F1A\u8BAE\u7C7B\u578B\uFF1A\u53EF\u4F20\u7C7B\u578B\u540D\u79F0\u6216 id\uFF08\u5148\u7528 `meeting.eb.type.list` \u67E5\u6709\u54EA\u4E9B\uFF09\u3002**\u5F88\u591A\u79DF\u6237\u7684\u6D41\u7A0B\u8868\u5355\u628A\u300C\u4F1A\u8BAE\u7C7B\u578B\u300D\u8BBE\u4E3A\u5FC5\u586B**\uFF0C\u4E0D\u4F20\u4F1A\u88AB `workflow.createRequest` \u6253\u56DE\u7F3A\u5B57\u6BB5"
|
|
6956
|
+
},
|
|
5752
6957
|
other_remark: { type: "string", description: "\u5907\u6CE8" },
|
|
5753
6958
|
workflowId: {
|
|
5754
6959
|
oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
|
|
@@ -5756,117 +6961,171 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5756
6961
|
},
|
|
5757
6962
|
autoRoom: { type: "boolean", description: "\u9ED8\u8BA4 false\uFF1A\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\u65F6\u8FD4\u56DE\u5019\u9009\u8BA9\u7528\u6237\u9009\uFF1B\u4F20 true \u624D\u81EA\u52A8\u91C7\u7528\u63A8\u8350" },
|
|
5758
6963
|
allowNoRoom: { type: "boolean", description: "\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\u7B49\uFF09\u65F6\u4F20 true\uFF0C\u907F\u514D\u88AB\u201C\u8BF7\u9009\u62E9\u4F1A\u8BAE\u5BA4\u201D\u62E6\u4F4F" },
|
|
6964
|
+
timeConfirmed: {
|
|
6965
|
+
type: "boolean",
|
|
6966
|
+
description: '\u26D4 **\u65F6\u95F4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0**\u3002\u53EA\u6709\u4EE5\u4E0B\u4E24\u79CD\u60C5\u51B5\u624D\u4F20 true\uFF1A\u2460 \u7528\u6237\u539F\u8BDD\u91CC\u660E\u786E\u7ED9\u51FA\u4E86\u65F6\u95F4\uFF08\u5982"\u660E\u5929 9 \u70B9\u5230 10 \u70B9"\uFF09\uFF1B\u2461 \u7528\u6237\u5728\u65F6\u6BB5\u9009\u9879\u91CC\u70B9\u9009\u540E\uFF0C\u628A `options[].value` **\u6574\u4F53**\u539F\u6837\u56DE\u4F20\uFF08value \u81EA\u5E26\u8BE5\u6807\u8BB0\uFF09\u3002\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF1A\u5373\u4F7F\u4F60\u4F20\u4E86 begin_datetime\uFF0CCLI \u4E5F**\u4E0D\u4F1A**\u5F53\u6210\u5DF2\u5B9A\uFF0C\u800C\u662F\u8FD4\u56DE\u65F6\u6BB5\u9009\u9879\u8BA9\u7528\u6237\u70B9\u9009\u3002\u26D4 \u7528\u6237\u53EA\u8BF4"\u660E\u5929/\u4E0A\u5348/\u4E0B\u5348"\u8FD9\u7C7B\u6A21\u7CCA\u8BF4\u6CD5\u65F6\uFF0C**\u5FC5\u987B\u4E0D\u4F20**\uFF0C\u8BA9 CLI \u7ED9\u5019\u9009'
|
|
6967
|
+
},
|
|
6968
|
+
roomConfirmed: {
|
|
6969
|
+
type: "boolean",
|
|
6970
|
+
description: '\u26D4 **\u4F1A\u8BAE\u5BA4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0**\u3002\u53EA\u6709\u4EE5\u4E0B\u4E24\u79CD\u60C5\u51B5\u624D\u4F20 true\uFF1A\u2460 \u7528\u6237\u539F\u8BDD\u660E\u786E\u6307\u5B9A\u4E86\u67D0\u95F4\u4F1A\u8BAE\u5BA4\uFF1B\u2461 \u7528\u6237\u5728\u623F\u95F4\u9009\u9879\u91CC\u70B9\u9009\u540E\u628A `options[].value` \u6574\u4F53\u539F\u6837\u56DE\u4F20\u3002\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF1A\u5373\u4F7F\u4F20\u4E86 address\uFF0CCLI \u4E5F\u4F1A\u628A"\u4F60\u6307\u5B9A\u7684\u8FD9\u95F4"\u548C\u63A8\u8350\u5019\u9009\u4E00\u8D77\u5217\u51FA\u6765\u8BA9\u7528\u6237\u70B9\u9009\u3002\u26D4 \u4E0D\u8981\u81EA\u5DF1\u4ECE room.list / room.recommend \u91CC\u6311\u4E00\u95F4\u585E\u8FDB address \u2014\u2014 \u90A3\u662F\u66FF\u7528\u6237\u62CD\u677F'
|
|
6971
|
+
},
|
|
5759
6972
|
extraFields: {
|
|
5760
6973
|
type: "object",
|
|
5761
|
-
description: '\u6309**\u6D41\u7A0B\u8868\u5355\u91CC\u7684\u5B57\u6BB5\u540D**\u586B\u989D\u5916\u5B57\u6BB5\uFF0C\u5F62\u5982 {"\u53C2\u4F1A\u5BA2\u6237": "xx\u516C\u53F8", "\u8054\u7CFB\u65B9\u5F0F": "138xxxx"}\uFF1A\u7528\u4E8E\u79DF\u6237\u5728\u6D41\u7A0B\u8868\u5355\u4E0A\u81EA\u5EFA\u3001CLI \u5185\u7F6E\u522B\u540D\u91CC\u6CA1\u6709\u7684\u5B57\u6BB5\u3002\u952E\u5FC5\u987B\u4E0E\u8BE5\u6D41\u7A0B\u8868\u5355\u7684\u5B57\u6BB5\u540D\u5B8C\u5168\u4E00\u81F4\uFF08prepare \u7684 warnings \u4F1A\u5217\u51FA\u8868\u5355\u73B0\u6709\u5168\u90E8\u5B57\u6BB5\u540D\uFF09\uFF1B\u5339\u914D\u4E0D\u5230\u7684\u4F1A\u8FDB unmapped \u63D0\u793A\uFF0C\u4E0D\u4F1A\u778E\u586B'
|
|
6974
|
+
description: '\u6309**\u6D41\u7A0B\u8868\u5355\u91CC\u7684\u5B57\u6BB5\u540D**\u586B\u989D\u5916\u5B57\u6BB5\uFF0C\u5F62\u5982 {"\u53C2\u4F1A\u5BA2\u6237": "xx\u516C\u53F8", "\u8054\u7CFB\u65B9\u5F0F": "138xxxx"}\uFF1A\u7528\u4E8E\u79DF\u6237\u5728\u6D41\u7A0B\u8868\u5355\u4E0A\u81EA\u5EFA\u3001CLI \u5185\u7F6E\u522B\u540D\u91CC\u6CA1\u6709\u7684\u5B57\u6BB5\u3002\u952E\u5FC5\u987B\u4E0E\u8BE5\u6D41\u7A0B\u8868\u5355\u7684\u5B57\u6BB5\u540D\u5B8C\u5168\u4E00\u81F4\uFF08prepare \u7684 warnings \u4F1A\u5217\u51FA\u8868\u5355\u73B0\u6709\u5168\u90E8\u5B57\u6BB5\u540D\uFF09\uFF1B\u5339\u914D\u4E0D\u5230\u7684\u4F1A\u8FDB unmapped \u63D0\u793A\uFF0C\u4E0D\u4F1A\u778E\u586B\u3002\u26D4 **\u4F1A\u8BAE\u5730\u70B9 / \u53C2\u4F1A\u4EBA\u5458 / \u53EC\u96C6\u4EBA / \u8054\u7CFB\u4EBA / \u4F1A\u8BAE\u7C7B\u578B \u4E0D\u8981\u585E\u8FD9\u91CC** \u2014\u2014 \u5B83\u4EEC\u6709\u4E13\u7528\u5165\u53C2\uFF08address / hrm_members / caller / contacter / mt_type\uFF09\uFF0CCLI \u4F1A\u628A\u503C\u8865\u6210\u6D4F\u89C8\u6309\u94AE\u8981\u7684 `{id,name}` \u5BF9\u8C61\uFF1B\u585E\u8FDB extraFields \u4F1A\u6309\u7EAF\u6587\u672C\u63D0\u4EA4\uFF0C\u670D\u52A1\u7AEF\u4F1A\u6253\u56DE\u300C\u8BF7\u6309\u540D\u79F0\u9009\u62E9\u300D'
|
|
6975
|
+
},
|
|
6976
|
+
dateFrom: {
|
|
6977
|
+
type: "string",
|
|
6978
|
+
description: "\u6CA1\u7ED9\u5177\u4F53\u65F6\u95F4\u65F6\u6309\u54EA\u4E00\u5929\u63A8\u8350\u65F6\u6BB5\uFF08yyyy-MM-dd\uFF1B\u4E0D\u4F20\u9ED8\u8BA4\u660E\u5929\uFF09"
|
|
6979
|
+
},
|
|
6980
|
+
durationMinutes: {
|
|
6981
|
+
type: "number",
|
|
6982
|
+
description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09\uFF1A\u53EA\u7ED9\u4E86\u5F00\u59CB\u65F6\u95F4\u65F6\u7528\u6765\u7B97\u7ED3\u675F\u65F6\u95F4\uFF1B\u63A8\u8350\u65F6\u6BB5\u65F6\u4E5F\u6309\u8FD9\u4E2A\u65F6\u957F\u627E"
|
|
6983
|
+
},
|
|
6984
|
+
workStartHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u65E9\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
|
|
6985
|
+
workEndHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u665A\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
|
|
6986
|
+
fieldValues: {
|
|
6987
|
+
type: "object",
|
|
6988
|
+
additionalProperties: true,
|
|
6989
|
+
description: '\u6309**\u8868\u5355\u5B57\u6BB5 datakey\uFF08fieldId\uFF09**\u76F4\u63A5\u7ED9\u503C\uFF0C\u5F62\u5982 {"1325677252711735881": "\u7814\u8BA8\u4F1A"}\u3002\u4F18\u5148\u7EA7\u6700\u9AD8\uFF08\u540C\u540D\u5B57\u6BB5\u4EE5\u5B83\u4E3A\u51C6\uFF09\uFF1A\u9002\u5408\u5B57\u6BB5\u540D\u5E26\u63D0\u793A\u8BED\u3001\u6216\u79DF\u6237\u81EA\u5EFA\u5B57\u6BB5\u8FD9\u7C7B\u6309\u4E2D\u6587\u540D\u731C\u4E0D\u5230\u7684\u60C5\u51B5\u3002datakey \u4ECE prepare \u8FD4\u56DE\u7684 preview.mapped\uFF08\u5F62\u5982 "\u4F1A\u8BAE\u540D\u79F0(1325677252711735881)"\uFF09\u91CC\u53D6\uFF1B\u6BCF\u4E2A\u6D41\u7A0B\u7684 datakey \u56FA\u5B9A\u4E0D\u53D8\uFF0C\u53EF\u957F\u671F\u786C\u7F16\u7801\u3002'
|
|
6990
|
+
},
|
|
6991
|
+
flowChoice: {
|
|
6992
|
+
type: "string",
|
|
6993
|
+
enum: ["auto", "ask"],
|
|
6994
|
+
description: "\u591A\u4E2A\u5EFA\u4F1A\u6D41\u7A0B**\u90FD\u6709\u53D1\u8D77\u6743\u9650**\u65F6\u600E\u4E48\u529E\uFF1A**\u9ED8\u8BA4\uFF08\u4E0D\u4F20 / ask\uFF09= \u8FD4\u56DE\u9009\u9879\u8BA9\u7528\u6237\u6311**\uFF1Bauto = \u81EA\u52A8\u53D6\u4F18\u5148\u7EA7\u6700\u9AD8\u7684\u90A3\u4E2A\uFF08\u7701\u4E00\u8F6E\uFF0C\u4F46\u9009\u9519\u6D41\u7A0B\u4F1A\u6F0F\u5B57\u6BB5\uFF0C\u614E\u7528\uFF09\u3002\u53EA\u6709 1 \u4E2A\u6709\u6743\u9650\u65F6\u4E0D\u53D7\u6B64\u53C2\u6570\u5F71\u54CD\uFF0CCLI \u76F4\u63A5\u53D1\u8D77"
|
|
5762
6995
|
}
|
|
5763
6996
|
},
|
|
5764
|
-
{ required: ["mt_name"
|
|
6997
|
+
{ required: ["mt_name"] }
|
|
5765
6998
|
),
|
|
5766
6999
|
handler: async (args, env) => {
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
let workflowId = resolved.workflowId;
|
|
5770
|
-
const sourceLabel = resolved.source === "argument" ? "\u8C03\u7528\u65B9\u4F20\u5165" : "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
|
|
5771
|
-
const probes = [];
|
|
5772
|
-
const loadedForms = /* @__PURE__ */ new Map();
|
|
5773
|
-
if (!workflowId && candidates.length > 1) {
|
|
5774
|
-
const probed = await Promise.all(candidates.map(async (id) => {
|
|
5775
|
-
try {
|
|
5776
|
-
const probeForm = await loadCreateForm(env, id);
|
|
5777
|
-
return {
|
|
5778
|
-
id,
|
|
5779
|
-
probeForm,
|
|
5780
|
-
probe: {
|
|
5781
|
-
workflowId: id,
|
|
5782
|
-
...probeForm.workflowName ? { name: probeForm.workflowName } : {},
|
|
5783
|
-
launchable: true
|
|
5784
|
-
}
|
|
5785
|
-
};
|
|
5786
|
-
} catch (error) {
|
|
5787
|
-
return {
|
|
5788
|
-
id,
|
|
5789
|
-
probeForm: null,
|
|
5790
|
-
probe: {
|
|
5791
|
-
workflowId: id,
|
|
5792
|
-
launchable: false,
|
|
5793
|
-
reason: String(error?.message ?? error).slice(0, 160)
|
|
5794
|
-
}
|
|
5795
|
-
};
|
|
5796
|
-
}
|
|
5797
|
-
}));
|
|
5798
|
-
for (const item of probed) {
|
|
5799
|
-
if (item.probeForm) loadedForms.set(item.id, item.probeForm);
|
|
5800
|
-
probes.push(item.probe);
|
|
5801
|
-
}
|
|
5802
|
-
const launchable = probes.filter((probe) => probe.launchable);
|
|
5803
|
-
if (launchable.length === 0) {
|
|
5804
|
-
throw meetingValidationError(
|
|
5805
|
-
"flow_not_launchable",
|
|
5806
|
-
`${sourceLabel}\u4E86 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u4F46\u5F53\u524D\u8D26\u53F7\u4E00\u4E2A\u90FD\u53D1\u8D77\u4E0D\u4E86\uFF08\u65E0\u53D1\u8D77\u6743\u9650\u6216\u6D41\u7A0B\u5DF2\u505C\u7528\uFF09\uFF1A` + probes.map((probe) => `${probe.workflowId}\uFF08${probe.reason ?? "\u4E0D\u53EF\u53D1\u8D77"}\uFF09`).join("\uFF1B"),
|
|
5807
|
-
{ probes }
|
|
5808
|
-
);
|
|
5809
|
-
}
|
|
5810
|
-
if (launchable.length > 1) {
|
|
5811
|
-
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
5812
|
-
status: "NEEDS_SELECTION",
|
|
5813
|
-
message: `${sourceLabel}\u4E86 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77\u5176\u4E2D ${launchable.length} \u4E2A\uFF0C\u8BF7\u8BA9\u7528\u6237\u9009\u62E9\u8981\u89E6\u53D1\u54EA\u4E00\u4E2A \u2014\u2014 **\u4E0D\u8981\u9ED8\u8BA4\u53D6\u7B2C\u4E00\u4E2A**\uFF08\u5404\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u53EF\u80FD\u5B8C\u5168\u4E0D\u540C\uFF0C\u9009\u9519\u4F1A\u6F0F\u5B57\u6BB5\uFF1B2026-10-29 \u771F\u5B9E\u4E8B\u6545\uFF1A\u53D6\u7B2C\u4E00\u4E2A\u5BFC\u81F4\u5B57\u6BB5\u5168\u586B\u4E0D\u8FDB\u53E6\u4E00\u6761\u6D41\u7A0B\uFF0C\u7528\u6237\u4EE5\u4E3A"\u7CFB\u7EDF\u53EA\u652F\u6301\u4E00\u6761\u6D41\u7A0B"\uFF09`,
|
|
5814
|
-
options: launchable.map((probe, index) => ({
|
|
5815
|
-
key: `W${index + 1}`,
|
|
5816
|
-
label: probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId,
|
|
5817
|
-
value: { workflowId: probe.workflowId },
|
|
5818
|
-
reason: "\u5F53\u524D\u8D26\u53F7\u6709\u53D1\u8D77\u6743\u9650",
|
|
5819
|
-
// 把该流程的字段名如实带出来:不同流程字段差异很大(有的有设备需求/涉密项目,有的没有),
|
|
5820
|
-
// 用户要靠这个才能选对(2026-10-29 用户反馈:选错方式后字段全填不进去)。
|
|
5821
|
-
fields: (loadedForms.get(probe.workflowId)?.fields ?? []).map((f) => f.name).filter(Boolean)
|
|
5822
|
-
})),
|
|
5823
|
-
probes
|
|
5824
|
-
}, {
|
|
5825
|
-
warnings: [
|
|
5826
|
-
`${sourceLabel}\u4E86 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5176\u4E2D ${launchable.length} \u4E2A\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77\uFF1B**\u5FC5\u987B\u628A\u8FD9\u51E0\u4E2A\u6D41\u7A0B\u505A\u6210\u9009\u9879\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\uFF0C\u7981\u6B62\u81EA\u5DF1\u66FF\u7528\u6237\u9009**\uFF1B\u9009\u5B9A\u540E\u5E26\u5355\u4E2A workflowId \u91CD\u65B0 prepare\u3002`,
|
|
5827
|
-
...probes.filter((probe) => !probe.launchable).map((probe) => `\u6D41\u7A0B ${probe.workflowId} \u5F53\u524D\u8D26\u53F7\u65E0\u6CD5\u53D1\u8D77\uFF08${probe.reason ?? "\u65E0\u6743\u9650"}\uFF09\uFF0C\u5DF2\u6392\u9664`)
|
|
5828
|
-
]
|
|
5829
|
-
});
|
|
5830
|
-
}
|
|
5831
|
-
workflowId = launchable[0].workflowId;
|
|
5832
|
-
}
|
|
5833
|
-
const form = loadedForms.get(workflowId) ?? await loadCreateForm(env, workflowId);
|
|
5834
|
-
if (!form.continuation) {
|
|
5835
|
-
throw meetingValidationError("flow_context_missing", "\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u6CA1\u6709\u8FD4\u56DE continuation\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u63D0\u4EA4");
|
|
5836
|
-
}
|
|
7000
|
+
let workflowId = "";
|
|
7001
|
+
let flowPickNote = null;
|
|
5837
7002
|
const decisions = {};
|
|
5838
7003
|
const enrich = args.enrich !== false;
|
|
5839
7004
|
const beginText = String(args.begin_datetime ?? "").trim();
|
|
5840
|
-
|
|
5841
|
-
const
|
|
7005
|
+
let endText = String(args.end_datetime ?? "").trim();
|
|
7006
|
+
const rawMembers = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
|
|
7007
|
+
const nameLike = rawMembers.filter((item) => !/^\d+$/.test(item));
|
|
7008
|
+
const nameToId = nameLike.length > 0 ? await import("./schedule-NIJBTYDO.js").then((m) => m.resolveMemberIdsByName(env, nameLike)).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
|
|
7009
|
+
const memberIds = rawMembers.map((item) => nameToId.get(item) ?? item);
|
|
7010
|
+
const timeConfirmed = args.timeConfirmed === true;
|
|
7011
|
+
const callerWorkflowId = String(args.workflowId ?? "").trim();
|
|
7012
|
+
const earlyWorkflowNote = callerWorkflowId === "" ? "" : `\u26D4 \u4F60\u4F20\u4E86 workflowId=${callerWorkflowId}\uFF0C\u4F46**\u6D41\u7A0B\u8FD8\u6CA1\u5230\u786E\u8BA4\u6B65\u9AA4**\uFF08\u987A\u5E8F\u662F \u540D\u79F0\u2192\u65F6\u95F4\u2192\u53C2\u4F1A\u4EBA\u2192\u5730\u70B9\u2192\u6D41\u7A0B\uFF09\u3002\u672C\u6B21\u53EA\u5904\u7406\u65F6\u95F4/\u5730\u70B9\uFF1B\u26D4 \u4E0D\u8981\u5728\u56DE\u590D\u91CC\u8BF4"\u6309 X \u6D41\u7A0B\u53D1\u8D77"\u2014\u2014\u56DB\u8981\u7D20\u5B9A\u5B8C\u540E CLI \u4F1A\u8FD4\u56DE\u6D41\u7A0B\u9009\u9879\u8BA9\u7528\u6237\u70B9\u3002`;
|
|
7013
|
+
const beginHasTime = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(beginText);
|
|
7014
|
+
const endHasTime = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}/.test(endText);
|
|
7015
|
+
if (beginHasTime && !endHasTime) {
|
|
7016
|
+
const duration = Number(args.durationMinutes) > 0 ? Math.round(Number(args.durationMinutes)) : 60;
|
|
7017
|
+
const startMs = Date.parse(beginText.slice(0, 16).replace(" ", "T"));
|
|
7018
|
+
if (Number.isFinite(startMs)) endText = formatMinute(new Date(startMs + duration * 6e4));
|
|
7019
|
+
}
|
|
7020
|
+
if (!beginHasTime || !timeConfirmed) {
|
|
7021
|
+
const day2 = /^\d{4}-\d{2}-\d{2}/.test(beginText) ? beginText.slice(0, 10) : String(args.dateFrom ?? "").trim().slice(0, 10) || tomorrowIso();
|
|
7022
|
+
const duration = Number(args.durationMinutes) > 0 ? Math.round(Number(args.durationMinutes)) : 60;
|
|
7023
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
7024
|
+
const suggested = await getMeetingOperation2("meeting.eb.meeting.create.suggest").handler(
|
|
7025
|
+
{
|
|
7026
|
+
dateFrom: day2,
|
|
7027
|
+
durationMinutes: duration,
|
|
7028
|
+
hrm_members: memberIds.join(","),
|
|
7029
|
+
maxSlots: 3,
|
|
7030
|
+
topN: 3,
|
|
7031
|
+
...Number(args.total_member) > 0 ? { memberCount: Number(args.total_member) } : {},
|
|
7032
|
+
...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
|
|
7033
|
+
...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {}
|
|
7034
|
+
},
|
|
7035
|
+
env
|
|
7036
|
+
).catch((error) => ({ data: { slots: [] }, slotError: String(error?.message ?? error).slice(0, 160) }));
|
|
7037
|
+
const slotOptions2 = suggested?.data?.slots ?? [];
|
|
7038
|
+
const slotWarnings = [
|
|
7039
|
+
...suggested?.warnings ?? [],
|
|
7040
|
+
...suggested?.slotError ? [`\u65F6\u6BB5\u63A8\u8350\u672A\u8DD1\u6210\u529F\uFF1A${suggested.slotError}`] : [],
|
|
7041
|
+
...memberIds.length === 0 ? ['\u26A0\uFE0F \u6CA1\u6709\u53C2\u4F1A\u4EBA\u5458\uFF0C\u65E0\u6CD5\u6838\u9A8C"\u4EBA\u662F\u5426\u7A7A\u95F2" \u2014\u2014 \u4E0B\u9762\u53EA\u662F**\u4F1A\u8BAE\u5BA4\u6709\u7A7A**\u7684\u65F6\u6BB5\uFF0C\u8BF7\u5982\u5B9E\u8BF4\u660E\u3002'] : []
|
|
7042
|
+
];
|
|
7043
|
+
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
7044
|
+
status: "NEEDS_SELECTION",
|
|
7045
|
+
selectionType: "slot",
|
|
7046
|
+
ui: { component: "choice", multiple: false, recommendedKey: "T1" },
|
|
7047
|
+
message: slotOptions2.length > 0 ? `${beginHasTime ? `\u4F60\u4F20\u5165\u7684\u65F6\u95F4 ${beginText}~${endText} **\u672A\u7ECF\u7528\u6237\u786E\u8BA4**\uFF08\u6CA1\u5E26 timeConfirmed\uFF09` : "\u6CA1\u6709\u7ED9\u51FA\u5177\u4F53\u65F6\u95F4"}\uFF0C\u5DF2\u6309\u53C2\u4F1A\u4EBA\u4E0E\u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u60C5\u51B5\u63A8\u8350 ${slotOptions2.length} \u4E2A\u65F6\u6BB5\uFF08${day2}\uFF0C\u65F6\u957F ${duration} \u5206\u949F\uFF09\u2014\u2014 \u26D4 \u5FC5\u987B\u8BA9\u7528\u6237\u5728\u9009\u9879\u91CC\u70B9\u9009\uFF0C**\u4E0D\u8981**\u628A\u4EFB\u4F55\u4E00\u4E2A\u5019\u9009\u5199\u6210"\u5DF2\u5B9A"\u6216\u653E\u8FDB\u786E\u8BA4\u6458\u8981` : `${beginHasTime ? `\u4F60\u4F20\u5165\u7684\u65F6\u95F4 ${beginText}~${endText} \u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF08\u6CA1\u5E26 timeConfirmed\uFF09` : "\u6CA1\u6709\u7ED9\u51FA\u5177\u4F53\u65F6\u95F4"}\uFF0C\u4E14 ${day2} \u6CA1\u80FD\u627E\u5230\u300C\u53C2\u4F1A\u4EBA\u7A7A\u95F2 + \u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u300D\u7684\u65F6\u6BB5\uFF0C\u8BF7\u8BA9\u7528\u6237\u6362\u4E2A\u65E5\u671F\u6216\u6307\u5B9A\u65F6\u95F4`,
|
|
7048
|
+
options: slotOptions2.map((slot, index) => ({
|
|
7049
|
+
key: `T${index + 1}`,
|
|
7050
|
+
label: String(slot.label ?? ""),
|
|
7051
|
+
// ⛔ 时间不在 slot 顶层,而在 slot.value 里(suggest 的返回结构)—— 取错会让调用方
|
|
7052
|
+
// 拿不到 begin/end,只能再问用户一次时间(2026-10-30 冒烟实测踩到)。
|
|
7053
|
+
// `timeConfirmed: true` 在这里是**关键**:用户点选后 value 原样回传,下一轮才被认作"已确认";
|
|
7054
|
+
// agent 自己编的时间不带这个标记,就永远停在选项这一步。
|
|
7055
|
+
value: {
|
|
7056
|
+
begin_datetime: String(slot.value?.begin ?? slot.begin ?? "").trim(),
|
|
7057
|
+
end_datetime: String(slot.value?.end ?? slot.end ?? "").trim(),
|
|
7058
|
+
address: slot.value?.address ?? null,
|
|
7059
|
+
timeConfirmed: true
|
|
7060
|
+
},
|
|
7061
|
+
reason: String(slot.reason ?? ""),
|
|
7062
|
+
rooms: slot.rooms ?? []
|
|
7063
|
+
})),
|
|
7064
|
+
day: day2,
|
|
7065
|
+
durationMinutes: duration,
|
|
7066
|
+
memberIds,
|
|
7067
|
+
// ⛔ 这里**不能**出现 workflowId:流程确认在四要素之后(2026-10-30 顺序调整)。
|
|
7068
|
+
// 返回 workflowId 会让 agent 误以为"流程已定",于是在回复里先讲流程、再问时间。
|
|
7069
|
+
workflowPending: true,
|
|
7070
|
+
hint: "\u9009\u5B9A\u540E\u628A value **\u6574\u4F53**\u539F\u6837\u5E26\u56DE\u91CD\u65B0\u8C03\u7528\uFF08\u542B timeConfirmed: true\uFF09\uFF1Baddress \u5DF2\u81EA\u52A8\u5E26\u4E0A\u8BE5\u65F6\u6BB5\u53EF\u7528\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u4ECD\u9700\u8BA9\u7528\u6237\u5355\u72EC\u786E\u8BA4\u6216\u7528 roomConfirmed: true"
|
|
7071
|
+
}, {
|
|
7072
|
+
warnings: [
|
|
7073
|
+
`${beginHasTime ? `\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\uFF1A\u4F60\u4F20\u5165\u7684\u65F6\u95F4 ${beginText}~${endText} \u6CA1\u6709\u7528\u6237\u786E\u8BA4\u6807\u8BB0\uFF08timeConfirmed\uFF09\uFF0C\u5DF2\u6539\u4E3A\u7ED9\u5019\u9009\u3002` : "\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\uFF1A\u65F6\u95F4\u672A\u786E\u5B9A\uFF08\u7F3A begin_datetime\uFF09\u3002"}\u5DF2\u6309 ${day2} \u63A8\u8350\u65F6\u6BB5\uFF0C\u8BF7\u7528\u9009\u9879\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\u3002`,
|
|
7074
|
+
...slotWarnings,
|
|
7075
|
+
...earlyWorkflowNote ? [earlyWorkflowNote] : []
|
|
7076
|
+
]
|
|
7077
|
+
});
|
|
7078
|
+
}
|
|
5842
7079
|
let addressInput = args.address;
|
|
5843
7080
|
const hadAddressInput = String(args.address ?? "").trim() !== "";
|
|
5844
7081
|
const day = beginText.slice(0, 10);
|
|
5845
7082
|
const durationMinutes = beginText && endText ? Math.max(15, Math.round((Date.parse(endText.replace(" ", "T")) - Date.parse(beginText.replace(" ", "T"))) / 6e4) || 60) : 60;
|
|
5846
7083
|
const timings = {};
|
|
5847
7084
|
const startedAt = Date.now();
|
|
7085
|
+
const enrichFailures = [];
|
|
7086
|
+
const noteFailure = (label) => (error) => {
|
|
7087
|
+
enrichFailures.push(`${label}\u672A\u5B8C\u6210\uFF1A${String(error?.message ?? error).slice(0, 120)}`);
|
|
7088
|
+
return null;
|
|
7089
|
+
};
|
|
7090
|
+
const needSelfPerson = String(args.caller ?? "").trim() === "" || String(args.contacter ?? "").trim() === "";
|
|
7091
|
+
const autoPerson = applySelfPersonDefaults(
|
|
7092
|
+
args,
|
|
7093
|
+
needSelfPerson ? await resolveSelfPerson(env) : null
|
|
7094
|
+
);
|
|
7095
|
+
const autoFilledPerson = autoPerson.filled;
|
|
7096
|
+
const selfPersonWarning = autoPerson.warning;
|
|
7097
|
+
const declaredTotal = Number(args.total_member) > 0 ? Number(args.total_member) : null;
|
|
7098
|
+
const callerToken = String(args.caller ?? "").trim();
|
|
7099
|
+
const callerInMembers = callerToken !== "" && (rawMembers.includes(callerToken) || memberIds.includes(callerToken));
|
|
7100
|
+
const roomMemberCount = declaredTotal ?? (memberIds.length > 0 ? memberIds.length + (callerInMembers ? 0 : 1) : void 0);
|
|
5848
7101
|
const roomTask = enrich && beginText && endText ? recommendRooms(env, {
|
|
5849
7102
|
beginDatetime: beginText,
|
|
5850
7103
|
endDatetime: endText,
|
|
5851
|
-
...
|
|
7104
|
+
...roomMemberCount ? { memberCount: roomMemberCount } : {},
|
|
7105
|
+
// 建会是"要下单"的场景:宁可多一次请求也必须拿最新台账(24h 缓存会让刚导入的会议室看不到)。
|
|
7106
|
+
refreshRooms: true,
|
|
5852
7107
|
topN: 3
|
|
5853
|
-
}).catch(()
|
|
7108
|
+
}).catch(noteFailure("\u4F1A\u8BAE\u5BA4\u63A8\u8350")) : Promise.resolve(null);
|
|
5854
7109
|
const addressId = String(addressInput ?? "").trim();
|
|
5855
|
-
const
|
|
5856
|
-
const roomConflictTask = enrich && beginText && endText &&
|
|
5857
|
-
const
|
|
5858
|
-
|
|
5859
|
-
|
|
7110
|
+
const roomConfirmed = args.roomConfirmed === true;
|
|
7111
|
+
const roomConflictTask = enrich && beginText && endText && addressId !== "" ? (async () => {
|
|
7112
|
+
const room = await resolveAddressRoom(env, addressId);
|
|
7113
|
+
if (!room) return { unresolved: true, input: addressId };
|
|
7114
|
+
if (!room.id || room.lookupFailed || room.status !== "0") return { room };
|
|
7115
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
7116
|
+
const result = await getMeetingOperation2("meeting.eb.conflict.room").handler(
|
|
7117
|
+
{ beginDatetime: beginText, endDatetime: endText, address: room.id },
|
|
5860
7118
|
env
|
|
5861
7119
|
);
|
|
5862
|
-
|
|
7120
|
+
return { room, ...result?.data ?? {} };
|
|
7121
|
+
})().catch(noteFailure("\u4F1A\u8BAE\u5BA4**\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
|
|
5863
7122
|
const conflictTask = enrich && beginText && endText && memberIds.length > 0 ? (async () => {
|
|
5864
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
7123
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
5865
7124
|
return getMeetingOperation2("meeting.eb.conflict.member").handler(
|
|
5866
7125
|
{ beginDatetime: beginText, endDatetime: endText, hrmMembers: memberIds.join(",") },
|
|
5867
7126
|
env
|
|
5868
7127
|
);
|
|
5869
|
-
})().catch(()
|
|
7128
|
+
})().catch(noteFailure("\u53C2\u4F1A\u4EBA**\u4F1A\u8BAE\u5360\u7528**\u68C0\u6D4B")) : Promise.resolve(null);
|
|
5870
7129
|
const availabilityTask = enrich && beginText && endText && memberIds.length > 0 ? findCommonFreeSlots(env, {
|
|
5871
7130
|
rangeStart: `${day} 00:00`,
|
|
5872
7131
|
rangeEnd: `${day} 23:59`,
|
|
@@ -5875,7 +7134,7 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5875
7134
|
maxSlots: 3,
|
|
5876
7135
|
maxDays: 1,
|
|
5877
7136
|
includeSchedule: true
|
|
5878
|
-
}).catch(()
|
|
7137
|
+
}).catch(noteFailure("\u53C2\u4F1A\u4EBA**\u65E5\u7A0B\u7A7A\u95F2**\u68C0\u6D4B")) : Promise.resolve(null);
|
|
5879
7138
|
const [roomRec, memberConflict, free, roomConflict] = await Promise.all([
|
|
5880
7139
|
roomTask,
|
|
5881
7140
|
conflictTask,
|
|
@@ -5883,17 +7142,84 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5883
7142
|
roomConflictTask
|
|
5884
7143
|
]);
|
|
5885
7144
|
timings.parallelMs = Date.now() - startedAt;
|
|
7145
|
+
const memberConflicts = memberConflict?.data?.conflicts ?? [];
|
|
7146
|
+
if (memberConflicts.length > 0) decisions.memberConflicts = memberConflicts;
|
|
7147
|
+
const freeSlots = free?.slots ?? [];
|
|
7148
|
+
if (free) {
|
|
7149
|
+
decisions.scheduleItems = free.scheduleItems;
|
|
7150
|
+
decisions.availabilityCost = free.cost;
|
|
7151
|
+
if (freeSlots.length > 0) {
|
|
7152
|
+
decisions.suggestedSlots = freeSlots;
|
|
7153
|
+
decisions.slotOptions = freeSlots.map((slot, index) => ({
|
|
7154
|
+
key: `T${index + 1}`,
|
|
7155
|
+
label: `${slot.begin.slice(11)}~${slot.end.slice(11)}\uFF08${day}\uFF09 \xB7 \u5168\u90E8\u53C2\u4F1A\u4EBA\u7A7A\u95F2`,
|
|
7156
|
+
value: { begin: slot.begin, end: slot.end },
|
|
7157
|
+
reason: "\u8BE5\u65F6\u6BB5\u6240\u6709\u53C2\u4F1A\u4EBA\u90FD\u6CA1\u6709\u4F1A\u8BAE\u4E0E\u65E5\u7A0B\u5360\u7528\uFF08\u5DF2\u540C\u65F6\u6838\u5BF9\u4F1A\u8BAE\u56DE\u6267\u4E0E\u65E5\u7A0B\uFF09"
|
|
7158
|
+
}));
|
|
7159
|
+
} else if (free.blockingSummary) {
|
|
7160
|
+
decisions.dayBlocked = { day, summary: free.blockingSummary };
|
|
7161
|
+
}
|
|
7162
|
+
}
|
|
7163
|
+
const conflictBrief = {
|
|
7164
|
+
memberConflicts,
|
|
7165
|
+
suggestedSlots: freeSlots,
|
|
7166
|
+
...enrichFailures.length > 0 ? { enrichFailures } : {}
|
|
7167
|
+
};
|
|
7168
|
+
const failureWarnings = enrichFailures.map(
|
|
7169
|
+
(failure) => `\u26A0\uFE0F ${failure} \u2014\u2014 **\u8FD9\u4E0D\u4EE3\u8868\u6CA1\u6709\u51B2\u7A81**\uFF0C\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\u8BE5\u9879\u672A\u6838\u9A8C\uFF0C\u4E0D\u8981\u58F0\u79F0"\u65F6\u95F4\u5DF2\u786E\u8BA4\u7A7A\u95F2"`
|
|
7170
|
+
);
|
|
5886
7171
|
const roomOptions = (roomRec?.candidates ?? []).map((candidate, index) => ({
|
|
5887
7172
|
key: `R${index + 1}`,
|
|
5888
7173
|
label: `${candidate.name}${candidate.capacity.max > 0 ? `\uFF08\u53EF\u5BB9 ${candidate.capacity.max} \u4EBA\uFF09` : ""}${index === 0 ? " \xB7 \u63A8\u8350" : ""}`,
|
|
5889
|
-
|
|
7174
|
+
// roomConfirmed: true = 用户点选该选项即代表"确认用这间",原样回传后下一轮才被认。
|
|
7175
|
+
value: { id: candidate.id, name: candidate.name, roomConfirmed: true },
|
|
5890
7176
|
reason: candidate.reasons.join("\uFF1B")
|
|
5891
7177
|
}));
|
|
5892
|
-
const roomConflictData = roomConflict
|
|
5893
|
-
|
|
7178
|
+
const roomConflictData = roomConflict;
|
|
7179
|
+
const resolvedAddress = roomConflictData?.room ?? null;
|
|
7180
|
+
const resolvedAddressId = resolvedAddress?.id || addressId;
|
|
7181
|
+
const addressDisplay = resolvedAddress?.name || addressId;
|
|
7182
|
+
if (roomConflictData?.unresolved === true) {
|
|
7183
|
+
decisions.roomNotFound = { input: addressId, candidates: roomOptions.length };
|
|
7184
|
+
if (roomOptions.length > 0) decisions.roomOptions = roomOptions;
|
|
7185
|
+
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
7186
|
+
status: "NEEDS_SELECTION",
|
|
7187
|
+
selectionType: "room",
|
|
7188
|
+
ui: { component: "choice", multiple: false, recommendedKey: "R1" },
|
|
7189
|
+
message: `\u6CA1\u627E\u5230\u540D\u4E3A\u300C${addressId}\u300D\u7684\u4F1A\u8BAE\u5BA4\uFF08\u4F1A\u8BAE\u5BA4\u53F0\u8D26\u91CC\u6CA1\u6709\u8FD9\u4E2A\u540D\u5B57\uFF09\uFF0C\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002` + (roomOptions.length > 0 ? `\u8BF7\u4ECE\u4E0B\u9762 ${roomOptions.length} \u4E2A\u5728\u8BE5\u65F6\u6BB5\u7A7A\u95F2\u7684\u4F1A\u8BAE\u5BA4\u91CC\u9009\u4E00\u95F4\uFF0C\u6216\u6838\u5BF9\u4E00\u4E0B\u4F1A\u8BAE\u5BA4\u540D\u79F0` : "\u8BE5\u65F6\u6BB5\u4E5F\u6CA1\u6709\u53EF\u7528\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u6539\u4F1A\u8BAE\u65F6\u95F4\u6216\u6539\u7EBF\u4E0A\u4F1A\u8BAE\uFF08allowNoRoom: true\uFF09"),
|
|
7190
|
+
workflowPending: true,
|
|
7191
|
+
options: roomOptions,
|
|
7192
|
+
recommended: roomOptions[0]?.value ?? null,
|
|
7193
|
+
roomNotFound: decisions.roomNotFound,
|
|
7194
|
+
hint: "\u9009\u5B9A\u540E\u628A value **\u6574\u4F53**\u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09\uFF1B\u6838\u5BF9\u540D\u79F0\u53EF\u7528 `meeting.eb.room.list` \u770B\u5168\u91CF\u6E05\u5355"
|
|
7195
|
+
}, {
|
|
7196
|
+
warnings: [
|
|
7197
|
+
`\u4F1A\u8BAE\u5BA4\u300C${addressId}\u300D\u5728\u53F0\u8D26\u91CC\u4E0D\u5B58\u5728\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`,
|
|
7198
|
+
'\u26D4 \u4E0D\u8981\u628A\u5B83\u5F53\u6210"\u7528\u6237\u6307\u5B9A\u7684\u623F\u95F4"\u5199\u8FDB\u786E\u8BA4\u6458\u8981 \u2014\u2014 \u8FD9\u95F4\u623F\u6839\u672C\u6CA1\u6709\u88AB\u89E3\u6790\u51FA\u6765\u3002'
|
|
7199
|
+
]
|
|
7200
|
+
});
|
|
7201
|
+
}
|
|
7202
|
+
if (resolvedAddress && resolvedAddress.status === "1") {
|
|
7203
|
+
decisions.roomSealed = { id: resolvedAddress.id, name: resolvedAddress.name };
|
|
7204
|
+
if (roomOptions.length > 0) decisions.roomOptions = roomOptions;
|
|
7205
|
+
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
7206
|
+
status: "NEEDS_SELECTION",
|
|
7207
|
+
selectionType: "room",
|
|
7208
|
+
ui: { component: "choice", multiple: false, recommendedKey: "R1" },
|
|
7209
|
+
message: `\u4F1A\u8BAE\u5BA4\u300C${resolvedAddress.name}\u300D\u5F53\u524D\u662F**\u5C01\u5B58**\u72B6\u6001\uFF08\u4E0D\u53EF\u9884\u7EA6\uFF09\uFF0C\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002` + (roomOptions.length > 0 ? "\u8BF7\u6539\u7528\u4E0B\u9762\u7A7A\u95F2\u7684\u4F1A\u8BAE\u5BA4" : "\u8BE5\u65F6\u6BB5\u6CA1\u6709\u5176\u5B83\u53EF\u7528\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u6539\u4F1A\u8BAE\u65F6\u95F4"),
|
|
7210
|
+
workflowPending: true,
|
|
7211
|
+
options: roomOptions,
|
|
7212
|
+
recommended: roomOptions[0]?.value ?? null,
|
|
7213
|
+
roomSealed: decisions.roomSealed
|
|
7214
|
+
}, {
|
|
7215
|
+
warnings: [`\u4F1A\u8BAE\u5BA4\u300C${resolvedAddress.name}\u300D\uFF08${resolvedAddress.id}\uFF09\u5DF2\u5C01\u5B58\uFF0C\u4E0D\u53EF\u9884\u7EA6\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`]
|
|
7216
|
+
});
|
|
7217
|
+
}
|
|
7218
|
+
if (addressInput && roomConfirmed && roomConflictData?.hasConflict === true) {
|
|
5894
7219
|
const busy = Array.isArray(roomConflictData.conflicts) ? roomConflictData.conflicts : [];
|
|
5895
7220
|
decisions.roomConflict = {
|
|
5896
|
-
address:
|
|
7221
|
+
address: resolvedAddressId,
|
|
7222
|
+
addressName: addressDisplay,
|
|
5897
7223
|
hasConflict: true,
|
|
5898
7224
|
conflicts: busy,
|
|
5899
7225
|
verdict: roomConflictData.verdict ?? "conflict"
|
|
@@ -5902,14 +7228,17 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5902
7228
|
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
5903
7229
|
status: "NEEDS_SELECTION",
|
|
5904
7230
|
selectionType: "room_conflict",
|
|
5905
|
-
|
|
7231
|
+
ui: { component: "choice", multiple: false, recommendedKey: "R1" },
|
|
7232
|
+
message: `\u4F60\u6307\u5B9A\u7684\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D\u5728 ${beginText}~${endText} \u5DF2\u88AB\u5360\u7528\uFF08${busy.length} \u6761\u5360\u7528\u8BB0\u5F55\uFF09\uFF0C\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002\u8BF7\u6539\u7528\u4E0B\u9762\u7A7A\u95F2\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u6216\u8C03\u6574\u4F1A\u8BAE\u65F6\u95F4`,
|
|
7233
|
+
workflowPending: true,
|
|
5906
7234
|
options: roomOptions,
|
|
5907
7235
|
recommended: roomOptions[0]?.value ?? null,
|
|
5908
7236
|
conflicts: busy,
|
|
7237
|
+
roomConflict: decisions.roomConflict,
|
|
5909
7238
|
hint: "\u9009\u5B9A\u540E\u628A value.id \u4F5C\u4E3A address \u91CD\u65B0\u8C03\u7528\uFF1B\u8981\u6539\u65F6\u95F4\u5C31\u540C\u65F6\u4F20\u65B0\u7684 begin_datetime/end_datetime"
|
|
5910
7239
|
}, {
|
|
5911
7240
|
warnings: [
|
|
5912
|
-
`\u4F1A\u8BAE\u5BA4
|
|
7241
|
+
`\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D\uFF08${resolvedAddressId}\uFF09\u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${busy.length} \u6761\u5360\u7528\uFF0C\u5DF2\u62E6\u4E0B\u672A\u63D0\u4EA4\u3002`,
|
|
5913
7242
|
roomOptions.length > 0 ? `\u5DF2\u6309\u4EBA\u6570/\u5E38\u7528/\u7A7A\u95F2\u7ED9\u51FA ${roomOptions.length} \u4E2A\u66FF\u4EE3\u4F1A\u8BAE\u5BA4\uFF08R1 \u4E3A\u9996\u9009\uFF09\u3002` : "\u8BE5\u65F6\u6BB5\u6CA1\u6709\u53EF\u66FF\u4EE3\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\uFF0C\u5EFA\u8BAE\u8C03\u6574\u4F1A\u8BAE\u65F6\u95F4\u6216\u6539\u7EBF\u4E0A\u4F1A\u8BAE\uFF08allowNoRoom: true\uFF09\u3002"
|
|
5914
7243
|
]
|
|
5915
7244
|
});
|
|
@@ -5922,18 +7251,38 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5922
7251
|
meta: roomRec.meta
|
|
5923
7252
|
};
|
|
5924
7253
|
const autoRoom = args.autoRoom === true;
|
|
5925
|
-
|
|
7254
|
+
const needRoomPick = !addressInput || !roomConfirmed;
|
|
7255
|
+
let pickOptions = roomOptions;
|
|
7256
|
+
if (addressInput && !roomConfirmed) {
|
|
7257
|
+
const hit = roomOptions.find((item) => String(item.value?.id) === resolvedAddressId);
|
|
7258
|
+
const specified = hit ? { ...hit, label: `${hit.label}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`, value: { ...hit.value, roomConfirmed: true } } : {
|
|
7259
|
+
key: "R0",
|
|
7260
|
+
label: `${addressDisplay}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`,
|
|
7261
|
+
value: { ...resolvedAddressId ? { id: resolvedAddressId } : {}, name: addressDisplay, roomConfirmed: true },
|
|
7262
|
+
reason: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u672A\u63D0\u4EA4\u3001\u672A\u786E\u8BA4"
|
|
7263
|
+
};
|
|
7264
|
+
pickOptions = [specified, ...roomOptions.filter((item) => String(item.value?.id) !== resolvedAddressId)].map((item, index) => ({ ...item, key: `R${index + 1}` }));
|
|
7265
|
+
}
|
|
7266
|
+
if (needRoomPick && !autoRoom && pickOptions.length > 0 && args.allowNoRoom !== true) {
|
|
5926
7267
|
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
5927
7268
|
status: "NEEDS_SELECTION",
|
|
5928
7269
|
selectionType: "room",
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
7270
|
+
ui: { component: "choice", multiple: false, recommendedKey: "R1" },
|
|
7271
|
+
message: addressInput ? `\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D**\u672A\u7ECF\u7528\u6237\u786E\u8BA4**\uFF08\u6CA1\u5E26 roomConfirmed\uFF09\uFF0C\u5DF2\u628A\u5B83\u548C\u5176\u5B83\u5019\u9009\u4E00\u8D77\u5217\u51FA\u6765 \u2014\u2014 \u26D4 \u5FC5\u987B\u8BA9\u7528\u6237\u5728\u9009\u9879\u91CC\u70B9\u9009\uFF0C\u4E0D\u8981\u76F4\u63A5\u63D0\u4EA4` : `\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF0C\u8BF7\u4ECE ${pickOptions.length} \u4E2A\u5019\u9009\u91CC\u9009\u62E9\uFF08\u5DF2\u6309\u4EBA\u6570/\u5E38\u7528/\u65F6\u6BB5\u5360\u7528\u6392\u5E8F\uFF09`,
|
|
7272
|
+
// 固化自动选的流程要带出来:调用方下一轮带 address 重调时不用再猜用的是哪条流程。
|
|
7273
|
+
workflowPending: true,
|
|
7274
|
+
options: pickOptions,
|
|
7275
|
+
recommended: pickOptions[0]?.value ?? null,
|
|
7276
|
+
hint: "\u9009\u5B9A\u540E\u628A value **\u6574\u4F53**\u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09\uFF1B\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\u8BF7\u4F20 allowNoRoom: true",
|
|
7277
|
+
...conflictBrief
|
|
5933
7278
|
}, {
|
|
5934
7279
|
warnings: [
|
|
5935
|
-
"\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\uFF0C\u4E5F\u6CA1\u6709\u66FF\u7528\u6237\u6311\u623F\u95F4\u3002",
|
|
5936
|
-
"\u5982\u9700\u76F4\u63A5\u5EFA\u4F1A\u5E76\u6CBF\u7528\u63A8\u8350\uFF0C\u53EF\u4F20 autoRoom: true\uFF1B\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\u5219\u4F20 allowNoRoom: true\u3002"
|
|
7280
|
+
addressInput ? `\u4F1A\u8BAE\u5BA4\u300C${addressDisplay}\u300D\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\u3002` : "\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF1A\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\uFF0C\u4E5F\u6CA1\u6709\u66FF\u7528\u6237\u6311\u623F\u95F4\u3002",
|
|
7281
|
+
"\u5982\u9700\u76F4\u63A5\u5EFA\u4F1A\u5E76\u6CBF\u7528\u63A8\u8350\uFF0C\u53EF\u4F20 autoRoom: true\uFF1B\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\u5219\u4F20 allowNoRoom: true\u3002",
|
|
7282
|
+
...earlyWorkflowNote ? [earlyWorkflowNote] : [],
|
|
7283
|
+
...memberConflicts.length > 0 ? [`\u26A0\uFE0F \u6CE8\u610F\uFF1A\u53C2\u4F1A\u4EBA\u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${memberConflicts.length} \u573A\u4F1A\u8BAE\u51B2\u7A81 \u2014\u2014 \u9009\u623F\u524D\u5148\u628A\u8FD9\u6761\u544A\u8BC9\u7528\u6237\uFF0C\u522B\u8BA9\u4ED6\u9009\u5B8C\u624D\u53D1\u73B0\u3002`] : [],
|
|
7284
|
+
...freeSlots.length > 0 ? [`\u5F53\u5929\u5168\u90E8\u53C2\u4F1A\u4EBA\u90FD\u7A7A\u95F2\u7684\u65F6\u6BB5\uFF1A${freeSlots.map((s) => `${s.begin.slice(11)}~${s.end.slice(11)}`).join("\u3001")}`] : [],
|
|
7285
|
+
...failureWarnings
|
|
5937
7286
|
]
|
|
5938
7287
|
});
|
|
5939
7288
|
}
|
|
@@ -5950,38 +7299,160 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5950
7299
|
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
5951
7300
|
status: "NEEDS_SELECTION",
|
|
5952
7301
|
selectionType: "room_unavailable",
|
|
7302
|
+
ui: { component: "choice", multiple: false, recommendedKey: "C2" },
|
|
5953
7303
|
message: "\u672A\u6307\u5B9A\u4F1A\u8BAE\u5BA4\uFF0C\u4E14\u6309\u4EBA\u6570/\u65F6\u6BB5\u6CA1\u80FD\u63A8\u8350\u51FA\u53EF\u7528\u7684\u7A7A\u95F2\u4F1A\u8BAE\u5BA4\u3002\u8BF7\u8BA9\u7528\u6237\u4ECE\u4E0B\u9762\u4E09\u6761\u91CC\u9009\u4E00\u6761\uFF0C**\u4E0D\u8981**\u76F4\u63A5\u63D0\u4EA4\u4E00\u4E2A\u6CA1\u6709\u5730\u70B9\u7684\u4F1A\u8BAE",
|
|
7304
|
+
workflowPending: true,
|
|
5954
7305
|
options: [
|
|
5955
7306
|
{ key: "C1", label: "\u6211\u6307\u5B9A\u5177\u4F53\u4F1A\u8BAE\u5BA4\uFF08\u8868\u5355\u91CC\u70B9\u9009\uFF0C\u6216\u544A\u8BC9\u6211\u4F1A\u8BAE\u5BA4\u540D\u79F0/id\uFF09", value: { action: "specify" } },
|
|
5956
7307
|
{ key: "C2", label: "\u6539\u7528\u7EBF\u4E0A\u4F1A\u8BAE\uFF08\u817E\u8BAF\u4F1A\u8BAE/\u89C6\u9891\uFF09", value: { action: "no_room" } },
|
|
5957
7308
|
{ key: "C3", label: '\u5148\u6309"\u5730\u70B9\u5F85\u5B9A"\u63D0\u4EA4', value: { action: "allow_no_room" } }
|
|
5958
7309
|
],
|
|
5959
|
-
roomUnavailable: decisions.roomUnavailable
|
|
7310
|
+
roomUnavailable: decisions.roomUnavailable,
|
|
7311
|
+
...conflictBrief
|
|
5960
7312
|
}, {
|
|
5961
7313
|
warnings: [
|
|
5962
7314
|
`\u4F1A\u8BAE\u5BA4\u63A8\u8350\u65E0\u7ED3\u679C\uFF1A${String(decisions.roomUnavailable.reason)}\u3002\u672C\u6B21**\u6CA1\u6709\u63D0\u4EA4**\u3002`,
|
|
5963
|
-
"\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\uFF09\u5C31\u5E26 allowNoRoom: true \u91CD\u65B0\u8C03\u7528\uFF1B\u8981\u6307\u5B9A\u623F\u95F4\u5C31\u5E26 address\u3002"
|
|
7315
|
+
"\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\uFF09\u5C31\u5E26 allowNoRoom: true \u91CD\u65B0\u8C03\u7528\uFF1B\u8981\u6307\u5B9A\u623F\u95F4\u5C31\u5E26 address\u3002",
|
|
7316
|
+
...memberConflicts.length > 0 ? [`\u26A0\uFE0F \u53E6\u5916\uFF1A\u53C2\u4F1A\u4EBA\u5728\u8BE5\u65F6\u6BB5\u5DF2\u6709 ${memberConflicts.length} \u573A\u4F1A\u8BAE\u51B2\u7A81 \u2014\u2014 \u6362\u65F6\u95F4\u53EF\u80FD\u6BD4\u6362\u623F\u95F4\u66F4\u5212\u7B97\u3002`] : [],
|
|
7317
|
+
...freeSlots.length > 0 ? [`\u5F53\u5929\u5168\u90E8\u53C2\u4F1A\u4EBA\u90FD\u7A7A\u95F2\u7684\u65F6\u6BB5\uFF1A${freeSlots.map((s) => `${s.begin.slice(11)}~${s.end.slice(11)}`).join("\u3001")}`] : [],
|
|
7318
|
+
...failureWarnings
|
|
5964
7319
|
]
|
|
5965
7320
|
});
|
|
5966
7321
|
}
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
7322
|
+
if (enrich && addressInput && !roomConfirmed && roomOptions.length === 0 && args.allowNoRoom !== true) {
|
|
7323
|
+
const specified = {
|
|
7324
|
+
key: "R1",
|
|
7325
|
+
label: `${addressDisplay}\uFF08\u4F60\u6307\u5B9A\u7684\uFF0C\u5F85\u786E\u8BA4\uFF09`,
|
|
7326
|
+
value: { ...resolvedAddressId ? { id: resolvedAddressId } : {}, name: addressDisplay, roomConfirmed: true },
|
|
7327
|
+
reason: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\uFF0C\u672A\u63D0\u4EA4\u3001\u672A\u786E\u8BA4"
|
|
7328
|
+
};
|
|
7329
|
+
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
7330
|
+
status: "NEEDS_SELECTION",
|
|
7331
|
+
selectionType: "room",
|
|
7332
|
+
ui: { component: "choice", multiple: false, recommendedKey: "R1" },
|
|
7333
|
+
message: "\u4F60\u4F20\u5165\u7684\u4F1A\u8BAE\u5BA4\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF0C\u4E14\u672C\u6B21\u6CA1\u80FD\u63A8\u8350\u51FA\u5176\u5B83\u5019\u9009 \u2014\u2014 \u8BF7\u8BA9\u7528\u6237\u786E\u8BA4\u8FD9\u4E00\u95F4\uFF0C\u6216\u6362\u4E00\u95F4 / \u6539\u65F6\u6BB5",
|
|
7334
|
+
workflowPending: true,
|
|
7335
|
+
options: [specified],
|
|
7336
|
+
recommended: specified.value,
|
|
7337
|
+
hint: "\u7528\u6237\u786E\u8BA4\u7528\u8FD9\u95F4\u5C31\u628A value \u539F\u6837\u5E26\u56DE\uFF08\u542B roomConfirmed: true\uFF09"
|
|
7338
|
+
}, {
|
|
7339
|
+
warnings: ["\u4F1A\u8BAE\u5BA4\u672A\u7ECF\u7528\u6237\u786E\u8BA4\uFF0C\u672C\u6B21**\u6CA1\u6709**\u63D0\u4EA4\u3002", ...failureWarnings]
|
|
7340
|
+
});
|
|
7341
|
+
}
|
|
7342
|
+
const resolved = await resolveWorkflowId(env, args);
|
|
7343
|
+
const confirmedAddressId = resolvedAddressId;
|
|
7344
|
+
const confirmedAddressLabel = addressId === "" ? "" : resolvedAddress?.name || String(roomOptions.find((item) => String(item.value?.id ?? "") === confirmedAddressId)?.value?.name ?? "") || addressId;
|
|
7345
|
+
const confirmedWhen = `${beginText}~${String(endText).slice(11) || endText}`;
|
|
7346
|
+
let candidates = resolved.candidates;
|
|
7347
|
+
workflowId = resolved.workflowId;
|
|
7348
|
+
let sourceLabel = resolved.source === "argument" ? "\u8C03\u7528\u65B9\u4F20\u5165" : resolved.source === "fixed" ? `\u56FA\u5316\u914D\u7F6E\uFF08${resolved.label ?? "\u9ED8\u8BA4"}\uFF09` : "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
|
|
7349
|
+
let probes = [];
|
|
7350
|
+
let loadedForms = /* @__PURE__ */ new Map();
|
|
7351
|
+
const autoPick = shouldAutoPickFlow(args);
|
|
7352
|
+
if (!workflowId && candidates.length > 1) {
|
|
7353
|
+
let probed = await probeWorkflowCandidates(env, candidates);
|
|
7354
|
+
probes = probed.probes;
|
|
7355
|
+
loadedForms = probed.loadedForms;
|
|
7356
|
+
let launchable = probes.filter((probe) => probe.launchable);
|
|
7357
|
+
if (launchable.length === 0 && resolved.source === "fixed") {
|
|
7358
|
+
const settings = await fetchEbAppSettings(env, "meeting.eb.meeting.create.flow.prepare");
|
|
7359
|
+
const fallbackIds = String(settings.mtNewWf ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
|
|
7360
|
+
if (fallbackIds.length > 0) {
|
|
7361
|
+
probed = await probeWorkflowCandidates(env, fallbackIds);
|
|
7362
|
+
probes = probed.probes;
|
|
7363
|
+
loadedForms = probed.loadedForms;
|
|
7364
|
+
candidates = fallbackIds;
|
|
7365
|
+
sourceLabel = "\u5E94\u7528\u8BBE\u7F6E\u914D\u7F6E";
|
|
7366
|
+
launchable = probes.filter((probe) => probe.launchable);
|
|
7367
|
+
}
|
|
7368
|
+
}
|
|
7369
|
+
if (launchable.length === 0) {
|
|
7370
|
+
throw meetingValidationError(
|
|
7371
|
+
"flow_not_launchable",
|
|
7372
|
+
`\u5F53\u524D\u8D26\u53F7**\u6CA1\u6709\u53D1\u8D77\u5EFA\u4F1A\u6D41\u7A0B\u7684\u6743\u9650**\uFF1A${sourceLabel}\u7684 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\u90FD\u53D1\u8D77\u4E0D\u4E86\uFF08\u65E0\u53D1\u8D77\u6743\u9650\u6216\u6D41\u7A0B\u5DF2\u505C\u7528\uFF09\u2014\u2014${probes.map((probe) => `${probe.workflowId}\uFF08${probe.reason ?? "\u4E0D\u53EF\u53D1\u8D77"}\uFF09`).join("\uFF1B")}\u3002\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF1A\u9700\u8981\u627E\u7BA1\u7406\u5458\u5F00\u901A\u8BE5\u6D41\u7A0B\u7684\u53D1\u8D77\u6743\u9650\uFF0C\u6216\u8BF7\u6709\u6743\u9650\u7684\u540C\u4E8B\u4EE3\u4E3A\u53D1\u8D77\uFF1B**\u4E0D\u8981**\u6539\u7528\u76F4\u8FDE\u5EFA\u4F1A\u7ED5\u8FC7\u6D41\u7A0B\u7BA1\u63A7\u3002`,
|
|
7373
|
+
{ probes }
|
|
7374
|
+
);
|
|
7375
|
+
}
|
|
7376
|
+
if (launchable.length > 1 && !autoPick) {
|
|
7377
|
+
return meetingSuccess("meeting.eb.meeting.create.flow.prepare", {
|
|
7378
|
+
status: "NEEDS_SELECTION",
|
|
7379
|
+
// ⚠️ 以前漏了这个字段(agent 拿到 undefined 无法判断是哪类选择,2026-10-30 真机发现)。
|
|
7380
|
+
selectionType: "flow",
|
|
7381
|
+
// 明确告诉调用方"这是一道选择题,请用选项控件呈现",不要降级成文本列表
|
|
7382
|
+
// (2026-10-30 用户反馈:agent 把会议室候选写成文本 + "需要你指定一间",没给选项卡)。
|
|
7383
|
+
ui: { component: "choice", multiple: false, recommendedKey: "W1" },
|
|
7384
|
+
// 四要素已经确认到这一步了:摘要一起给出去,用户只需点一下流程,就能直接提交。
|
|
7385
|
+
confirmed: {
|
|
7386
|
+
mt_name: String(args.mt_name ?? ""),
|
|
7387
|
+
begin_datetime: beginText,
|
|
7388
|
+
end_datetime: endText,
|
|
7389
|
+
address: confirmedAddressId || null,
|
|
7390
|
+
addressName: confirmedAddressLabel || null,
|
|
7391
|
+
hrm_members: memberIds
|
|
7392
|
+
},
|
|
7393
|
+
message: `\u4F1A\u8BAE\u8981\u7D20\u5DF2\u786E\u8BA4\uFF08${String(args.mt_name ?? "")} \xB7 ${confirmedWhen}${confirmedAddressLabel ? ` \xB7 ${confirmedAddressLabel}` : " \xB7 \u65E0\u4F1A\u8BAE\u5BA4"}\uFF09\uFF1B\u5F53\u524D\u8D26\u53F7\u5BF9 ${sourceLabel}\u7684 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B**\u90FD\u6709\u53D1\u8D77\u6743\u9650**\uFF0C\u8BF7\u8BA9\u7528\u6237\u6700\u540E\u9009\u4E00\u4E0B\u300C\u7528\u54EA\u6761\u6D41\u7A0B\u53D1\u8D77\u300D\u2014\u2014 **\u4E0D\u8981\u9ED8\u8BA4\u53D6\u7B2C\u4E00\u4E2A**\uFF08\u5404\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u53EF\u80FD\u5B8C\u5168\u4E0D\u540C\uFF0C\u9009\u9519\u4F1A\u6F0F\u5B57\u6BB5\uFF1B2026-10-29 \u771F\u5B9E\u4E8B\u6545\uFF1A\u53D6\u7B2C\u4E00\u4E2A\u5BFC\u81F4\u5B57\u6BB5\u5168\u586B\u4E0D\u8FDB\u53E6\u4E00\u6761\u6D41\u7A0B\uFF0C\u7528\u6237\u4EE5\u4E3A"\u7CFB\u7EDF\u53EA\u652F\u6301\u4E00\u6761\u6D41\u7A0B"\uFF09\u3002\u26A0\uFE0F \u53EA\u6709\u5176\u4E2D 1 \u4E2A\u6709\u6743\u9650\u65F6 CLI \u4F1A\u76F4\u63A5\u53D1\u8D77\uFF0C\u4E0D\u4F1A\u8D70\u5230\u8FD9\u4E00\u6B65`,
|
|
7394
|
+
options: launchable.map((probe, index) => ({
|
|
7395
|
+
key: `W${index + 1}`,
|
|
7396
|
+
label: probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId,
|
|
7397
|
+
// ⛔ 把已确认的四要素一起带回去:用户点选流程后**原样回传 value** 就能直接出确认摘要,
|
|
7398
|
+
// 不用再走一遍时间/房间闸门(否则"先定四要素再选流程"会多出一轮无效往返)。
|
|
7399
|
+
value: {
|
|
7400
|
+
workflowId: probe.workflowId,
|
|
7401
|
+
begin_datetime: beginText,
|
|
7402
|
+
end_datetime: endText,
|
|
7403
|
+
timeConfirmed: true,
|
|
7404
|
+
...confirmedAddressId ? { address: confirmedAddressId, roomConfirmed: true } : {}
|
|
7405
|
+
},
|
|
7406
|
+
reason: "\u5F53\u524D\u8D26\u53F7\u6709\u53D1\u8D77\u6743\u9650",
|
|
7407
|
+
// 把该流程的字段名如实带出来:不同流程字段差异很大(有的有设备需求/涉密项目,有的没有),
|
|
7408
|
+
// 用户要靠这个才能选对(2026-10-29 用户反馈:选错方式后字段全填不进去)。
|
|
7409
|
+
fields: (loadedForms.get(probe.workflowId)?.fields ?? []).map((f) => f.name).filter(Boolean)
|
|
7410
|
+
})),
|
|
7411
|
+
probes
|
|
7412
|
+
}, {
|
|
7413
|
+
warnings: [
|
|
7414
|
+
`${sourceLabel}\uFF1A\u5171 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5176\u4E2D ${launchable.length} \u4E2A\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77\uFF1B**\u5FC5\u987B\u628A\u8FD9\u51E0\u4E2A\u6D41\u7A0B\u505A\u6210\u9009\u9879\u8BA9\u7528\u6237\u6311\u4E00\u4E2A\uFF0C\u7981\u6B62\u81EA\u5DF1\u66FF\u7528\u6237\u9009**\uFF1B\u9009\u5B9A\u540E\u5E26\u5355\u4E2A workflowId \u91CD\u65B0 prepare\u3002`,
|
|
7415
|
+
...probes.filter((probe) => !probe.launchable).map((probe) => `\u6D41\u7A0B ${probe.workflowId} \u5F53\u524D\u8D26\u53F7\u65E0\u6CD5\u53D1\u8D77\uFF08${probe.reason ?? "\u65E0\u6743\u9650"}\uFF09\uFF0C\u5DF2\u6392\u9664`)
|
|
7416
|
+
]
|
|
7417
|
+
});
|
|
7418
|
+
}
|
|
7419
|
+
workflowId = launchable[0].workflowId;
|
|
7420
|
+
if (launchable.length === 1 && candidates.length > 1) {
|
|
7421
|
+
const only = launchable[0];
|
|
7422
|
+
flowPickNote = `${sourceLabel}\uFF1A\u5171 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5F53\u524D\u8D26\u53F7\u53EA\u6709\u300C${only.name ?? only.workflowId}\u300D\uFF08${only.workflowId}\uFF09\u6709\u53D1\u8D77\u6743\u9650\uFF0C\u5DF2\u76F4\u63A5\u7528\u5B83\u53D1\u8D77`;
|
|
7423
|
+
}
|
|
7424
|
+
if (launchable.length > 1) {
|
|
7425
|
+
const picked2 = launchable[0];
|
|
7426
|
+
const others = launchable.slice(1).map((probe) => probe.name ? `${probe.name}\uFF08${probe.workflowId}\uFF09` : probe.workflowId);
|
|
7427
|
+
flowPickNote = `${sourceLabel}\uFF1A\u5171 ${candidates.length} \u4E2A\u5EFA\u4F1A\u6D41\u7A0B\uFF0C\u5F53\u524D\u8D26\u53F7\u53EF\u53D1\u8D77 ${launchable.length} \u4E2A\uFF0C\u5DF2\u6309\u4F18\u5148\u7EA7\u81EA\u52A8\u9009\u7528\u300C${picked2.name ?? picked2.workflowId}\u300D\uFF08${picked2.workflowId}\uFF09\uFF1B\u5176\u4ED6\u53EF\u7528\u6D41\u7A0B\uFF1A${others.join("\u3001")} \u2014\u2014 \u8981\u7528\u5B83\u4EEC\u8BF7\u663E\u5F0F\u4F20 workflowId\u3002`;
|
|
7428
|
+
}
|
|
7429
|
+
}
|
|
7430
|
+
let form = loadedForms.get(workflowId);
|
|
7431
|
+
if (!form) {
|
|
7432
|
+
try {
|
|
7433
|
+
form = await loadCreateForm(env, workflowId);
|
|
7434
|
+
} catch (error) {
|
|
7435
|
+
throw meetingValidationError(
|
|
7436
|
+
"flow_not_launchable",
|
|
7437
|
+
`\u5F53\u524D\u8D26\u53F7**\u6CA1\u6709\u53D1\u8D77\u5EFA\u4F1A\u6D41\u7A0B\u7684\u6743\u9650**\uFF08\u6216\u6D41\u7A0B\u5DF2\u505C\u7528\uFF09\uFF1A\u5EFA\u4F1A\u6D41\u7A0B ${workflowId} \u7684\u8868\u5355\u8F7D\u5165\u5931\u8D25 \u2014\u2014 ${String(error?.message ?? error).slice(0, 200)}\u3002\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF1A\u9700\u8981\u627E\u7BA1\u7406\u5458\u5F00\u901A\u8BE5\u6D41\u7A0B\u7684\u53D1\u8D77\u6743\u9650\uFF0C\u6216\u8BF7\u6709\u6743\u9650\u7684\u540C\u4E8B\u4EE3\u4E3A\u53D1\u8D77\uFF1B**\u4E0D\u8981**\u6539\u7528\u76F4\u8FDE\u5EFA\u4F1A\u7ED5\u8FC7\u6D41\u7A0B\u7BA1\u63A7\u3002`,
|
|
7438
|
+
{ workflowId }
|
|
7439
|
+
);
|
|
5982
7440
|
}
|
|
5983
7441
|
}
|
|
7442
|
+
if (!form.continuation) {
|
|
7443
|
+
throw meetingValidationError("flow_context_missing", "\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u6CA1\u6709\u8FD4\u56DE continuation\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u63D0\u4EA4");
|
|
7444
|
+
}
|
|
5984
7445
|
decisions.timings = timings;
|
|
7446
|
+
const crmMemberCount = (() => {
|
|
7447
|
+
if (args.crm_member_count !== void 0 && args.crm_member_count !== "") return args.crm_member_count;
|
|
7448
|
+
const raw = args.crm_members;
|
|
7449
|
+
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
7450
|
+
if (Array.isArray(raw)) return raw.length > 0 ? raw.length : void 0;
|
|
7451
|
+
const text = String(raw).trim();
|
|
7452
|
+
if (!text) return void 0;
|
|
7453
|
+
const count = text.split(/[,;,;]+/).map((item) => item.trim()).filter((item) => item !== "").length;
|
|
7454
|
+
return count > 0 ? count : void 0;
|
|
7455
|
+
})();
|
|
5985
7456
|
const shaped = await shapeBrowserValues(env, {
|
|
5986
7457
|
mt_name: args.mt_name,
|
|
5987
7458
|
begin_datetime: args.begin_datetime,
|
|
@@ -5991,15 +7462,118 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
5991
7462
|
customize_address: args.customize_address,
|
|
5992
7463
|
hrm_members: args.hrm_members,
|
|
5993
7464
|
total_member: args.total_member,
|
|
7465
|
+
crm_members: args.crm_members,
|
|
7466
|
+
...crmMemberCount === void 0 ? {} : { crm_member_count: crmMemberCount },
|
|
5994
7467
|
caller: args.caller,
|
|
5995
7468
|
contacter: args.contacter,
|
|
5996
7469
|
other_remark: args.other_remark,
|
|
5997
7470
|
mt_type: args.mt_type,
|
|
5998
7471
|
...args.extraFields && typeof args.extraFields === "object" && !Array.isArray(args.extraFields) ? args.extraFields : {}
|
|
5999
7472
|
});
|
|
6000
|
-
const
|
|
7473
|
+
const preferredFields = await readFlowFieldMap(env, workflowId);
|
|
7474
|
+
const { main, mapped, unmapped, resolved: resolvedFields } = mapFields(form.fields, shaped.values, preferredFields);
|
|
7475
|
+
await writeFlowFieldMap(env, workflowId, form.workflowName, resolvedFields);
|
|
6001
7476
|
const warnings = [];
|
|
7477
|
+
if (autoFilledPerson.length > 0) {
|
|
7478
|
+
const labels = autoFilledPerson.map((one) => `\u300C${PERSON_FIELD_LABELS[one.field]}\u300D`).join("");
|
|
7479
|
+
warnings.push(
|
|
7480
|
+
`${labels}\u6CA1\u6709\u4F20\u503C\uFF0C\u5DF2\u6309**\u5F53\u524D\u767B\u5F55\u4EBA**\u8865\u9F50\uFF1A${autoFilledPerson[0].name}\uFF08${autoFilledPerson[0].id}\uFF09\u3002\u8981\u6362\u6210\u522B\u4EBA\uFF08\u4F8B\u5982\u66FF\u4ED6\u4EBA\u5EFA\u4F1A\u3001\u6307\u5B9A\u522B\u7684\u8054\u7CFB\u4EBA\uFF09\u8BF7\u663E\u5F0F\u4F20 caller / contacter\u3002`
|
|
7481
|
+
);
|
|
7482
|
+
} else if (selfPersonWarning) {
|
|
7483
|
+
warnings.push(selfPersonWarning);
|
|
7484
|
+
}
|
|
7485
|
+
if (flowPickNote) warnings.push(flowPickNote);
|
|
6002
7486
|
for (const note of shaped.notes) warnings.push(note);
|
|
7487
|
+
const crmMentioned = detectCrmMentionInText(args.mt_name, args.mt_desc, args.other_remark);
|
|
7488
|
+
if (crmMentioned && !args.crm_members) {
|
|
7489
|
+
const hasCrmField = form.fields.some((field) => /参会客户/.test(String(field?.label ?? field?.name ?? field?.fieldName ?? "")));
|
|
7490
|
+
warnings.push(
|
|
7491
|
+
`\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u91CC\u63D0\u5230\u5BA2\u6237\u300C${crmMentioned}\u300D\uFF0C\u4F46\u672C\u6B21\u6CA1\u4F20 crm_members` + (hasCrmField ? `\uFF0C\u8BE5\u6D41\u7A0B\u8868\u5355**\u6709\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5B57\u6BB5\uFF0C\u73B0\u5728\u4F1A\u662F\u7A7A\u7684**\u3002\u8BF7\u5148 meeting.eb.crm.search {"keyword":"${crmMentioned}"} \u62FF items[].customerId\uFF0C\u518D\u7528 crm_members:[{id,name}] \u91CD\u65B0\u63D0\u4EA4\uFF08\u5FC5\u987B\u5E26\u5BA2\u6237\u540D\u79F0\uFF09\u3002` : "\uFF08\u8BE5\u6D41\u7A0B\u8868\u5355\u91CC\u6CA1\u6709\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5B57\u6BB5\uFF0C\u672C\u6761\u53EF\u5FFD\u7565\uFF09\u3002")
|
|
7492
|
+
);
|
|
7493
|
+
}
|
|
7494
|
+
const crmMembersGiven = Array.isArray(args.crm_members) ? args.crm_members.length > 0 : String(args.crm_members ?? "").trim() !== "";
|
|
7495
|
+
if (crmMembersGiven) {
|
|
7496
|
+
const crmFieldId = String(resolvedFields.crm_members ?? "").trim();
|
|
7497
|
+
const crmField = form.fields.find((field) => String(field?.id ?? "") === crmFieldId);
|
|
7498
|
+
const componentKey = String(crmField?.componentKey ?? "").toLowerCase();
|
|
7499
|
+
if (crmField && componentKey !== "" && componentKey !== "customer" && componentKey !== "customercomponent") {
|
|
7500
|
+
warnings.push(
|
|
7501
|
+
`\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5B57\u6BB5\uFF08${crmFieldId}\uFF09\u662F ${crmField.componentKey} \u7EC4\u4EF6\uFF1A\u5BA2\u6237 id \u4E0E\u540D\u79F0\u7167\u5E38\u5199\u8FDB\u6D41\u7A0B\u5355\u636E\uFF0C\u518D\u7531 ESB \u7684\u5B57\u6BB5\u6620\u5C04\u540C\u6B65\u5230\u4F1A\u8BAE\u8868 \u2014\u2014 \u6B63\u5E38\u914D\u7F6E\uFF0C\u4E0D\u9700\u8981\u6539\u8868\u5355\u3002`
|
|
7502
|
+
);
|
|
7503
|
+
}
|
|
7504
|
+
}
|
|
7505
|
+
const providedCrmDetailRows = normalizeCrmDetailRows(args.crm_member_details);
|
|
7506
|
+
const onlyDetailMode = String(args.crm_detail_mode ?? "").trim().toLowerCase() === "only";
|
|
7507
|
+
let crmDetailRows = onlyDetailMode ? providedCrmDetailRows : [];
|
|
7508
|
+
if (crmMembersGiven && !onlyDetailMode) {
|
|
7509
|
+
const detailTarget = resolveCrmDetailTarget(form.fields);
|
|
7510
|
+
if (detailTarget) {
|
|
7511
|
+
const auto = await resolveAutoCrmDetailRows(env, args.crm_members);
|
|
7512
|
+
if (auto.rows.length > 0) {
|
|
7513
|
+
crmDetailRows = auto.rows;
|
|
7514
|
+
if (providedCrmDetailRows.length > 0) {
|
|
7515
|
+
const byName = new Map(providedCrmDetailRows.map((row) => [String(row.xm ?? "").trim(), row]));
|
|
7516
|
+
crmDetailRows = crmDetailRows.map((row) => {
|
|
7517
|
+
const given = byName.get(String(row.xm ?? "").trim());
|
|
7518
|
+
if (!given) return row;
|
|
7519
|
+
const merged = { ...row };
|
|
7520
|
+
for (const [key, value] of Object.entries(given)) {
|
|
7521
|
+
if (String(value ?? "").trim() !== "") merged[key] = String(value);
|
|
7522
|
+
}
|
|
7523
|
+
return merged;
|
|
7524
|
+
});
|
|
7525
|
+
}
|
|
7526
|
+
warnings.push(
|
|
7527
|
+
`\u5DF2\u81EA\u52A8\u628A\u300C${auto.customers.join("\u3001")}\u300D\u7684 ${auto.rows.length} \u4F4D\u8054\u7CFB\u4EBA\u5199\u8FDB\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\uFF1A${auto.rows.map((row) => `${row.xm}${row.sjhm ? ` ${row.sjhm}` : ""}`).join("\u3001")}\uFF08\u660E\u7EC6\u8868\u672C\u6765\u5C31\u4E00\u4EBA\u4E00\u884C\uFF0C\u4E0D\u9700\u8981\u8BA9\u7528\u6237\u6311\uFF09\u3002\u786E\u5B9E\u53EA\u60F3\u8981\u5176\u4E2D\u51E0\u4F4D\u65F6\uFF0C\u4F20 crm_detail_mode:"only" \u518D\u914D crm_member_details \u624D\u8986\u76D6\u672C\u6B21\u81EA\u52A8\u5E26\u5165\u3002`
|
|
7528
|
+
);
|
|
7529
|
+
} else if (auto.missing.length > 0) {
|
|
7530
|
+
warnings.push(
|
|
7531
|
+
`\u5DF2\u5199\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\uFF0C\u4F46\u6CA1\u80FD\u81EA\u52A8\u5E26\u51FA\u300C${auto.missing.join("\u3001")}\u300D\u7684\u8054\u7CFB\u4EBA\uFF08CRM \u91CC\u67E5\u4E0D\u5230\uFF09\u3002\u8BF7\u628A\u5DF2\u67E5\u5230\u7684\u8054\u7CFB\u4EBA\u76F4\u63A5\u544A\u7ED9\u7528\u6237\u6838\u5BF9\uFF1B\u786E\u5B9E\u6CA1\u6709\u8054\u7CFB\u4EBA\u65F6\u95EE\u4E00\u6B21\u59D3\u540D+\u624B\u673A\u53F7\uFF0C\u518D\u4EE5 crm_member_details:[{"xm":"\u5F20\u4E09","sjhm":"13800000000"}] \u91CD\u65B0 prepare\u3002`
|
|
7532
|
+
);
|
|
7533
|
+
}
|
|
7534
|
+
}
|
|
7535
|
+
}
|
|
7536
|
+
let detailPayload;
|
|
7537
|
+
if (crmDetailRows.length > 0) {
|
|
7538
|
+
const target = resolveCrmDetailTarget(form.fields);
|
|
7539
|
+
if (!target) {
|
|
7540
|
+
warnings.push(
|
|
7541
|
+
`\u4F20\u4E86 crm_member_details\uFF08${crmDetailRows.length} \u884C\uFF09\uFF0C\u4F46\u8BE5\u5EFA\u4F1A\u6D41\u7A0B\u7684**\u53D1\u8D77\u8282\u70B9\u8868\u5355\u91CC\u6CA1\u6709\u300C\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\u300D\u660E\u7EC6\u8868**\uFF08\u6216\u5B83\u88AB\u6446\u5728\u9690\u85CF\u884C\u4E0A\uFF09\uFF0C\u660E\u7EC6\u65E0\u6CD5\u5199\u5165\uFF0C\u5DF2\u5FFD\u7565\u8FD9\u4E9B\u884C\uFF1B\u4E3B\u8868\u7684\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u7167\u5E38\u5199\u5165\u3002`
|
|
7542
|
+
);
|
|
7543
|
+
} else {
|
|
7544
|
+
detailPayload = {
|
|
7545
|
+
[target.subFormId]: crmDetailRows.map((row) => {
|
|
7546
|
+
const line = {};
|
|
7547
|
+
for (const [semantic, fieldId] of Object.entries(target.columns)) {
|
|
7548
|
+
const value = row[semantic];
|
|
7549
|
+
if (value !== void 0 && value !== "") line[fieldId] = value;
|
|
7550
|
+
}
|
|
7551
|
+
return line;
|
|
7552
|
+
})
|
|
7553
|
+
};
|
|
7554
|
+
warnings.push(
|
|
7555
|
+
`\u53C2\u4F1A\u5BA2\u6237\u660E\u7EC6\uFF1A${crmDetailRows.length} \u884C\u5199\u5165\u660E\u7EC6\u8868 ${target.subFormId}\uFF08\u5217\uFF1A${Object.values(target.labels).join("/")}\uFF09`
|
|
7556
|
+
);
|
|
7557
|
+
}
|
|
7558
|
+
}
|
|
7559
|
+
if (args.fieldValues && typeof args.fieldValues === "object" && !Array.isArray(args.fieldValues)) {
|
|
7560
|
+
const knownIds = new Set(form.fields.map((field) => field.id));
|
|
7561
|
+
for (const [fieldId, raw] of Object.entries(args.fieldValues)) {
|
|
7562
|
+
if (raw === void 0 || raw === null || raw === "") continue;
|
|
7563
|
+
if (!knownIds.has(fieldId)) {
|
|
7564
|
+
warnings.push(`fieldValues \u91CC\u7684 datakey\u300C${fieldId}\u300D\u4E0D\u5728\u8BE5\u6D41\u7A0B\u8868\u5355\u91CC\uFF0C\u5DF2\u5FFD\u7565\uFF08\u5148\u7528 prepare \u4E0D\u5E26 fieldValues \u8DD1\u4E00\u6B21\uFF0C\u770B unmapped/\u8868\u5355\u5B57\u6BB5\u6E05\u5355\uFF09`);
|
|
7565
|
+
continue;
|
|
7566
|
+
}
|
|
7567
|
+
main[fieldId] = raw;
|
|
7568
|
+
mapped[`datakey:${fieldId}`] = fieldId;
|
|
7569
|
+
}
|
|
7570
|
+
}
|
|
7571
|
+
if (enrichFailures.length > 0) {
|
|
7572
|
+
decisions.enrichFailures = enrichFailures;
|
|
7573
|
+
for (const failure of enrichFailures) {
|
|
7574
|
+
warnings.push(`\u26A0\uFE0F ${failure} \u2014\u2014 **\u8FD9\u4E0D\u4EE3\u8868\u6CA1\u6709\u51B2\u7A81**\uFF0C\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\u8BE5\u9879\u672A\u6838\u9A8C\uFF0C\u4E0D\u8981\u58F0\u79F0"\u65F6\u95F4\u5DF2\u786E\u8BA4\u7A7A\u95F2"`);
|
|
7575
|
+
}
|
|
7576
|
+
}
|
|
6003
7577
|
const picked = decisions.autoRoom?.picked;
|
|
6004
7578
|
if (picked && !hadAddressInput) {
|
|
6005
7579
|
warnings.push(
|
|
@@ -6007,21 +7581,30 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
6007
7581
|
);
|
|
6008
7582
|
}
|
|
6009
7583
|
const slotOptions = decisions.slotOptions ?? [];
|
|
6010
|
-
|
|
7584
|
+
const memberConflictCount = decisions.memberConflicts?.length ?? 0;
|
|
7585
|
+
if (memberConflictCount > 0 && slotOptions.length > 0) {
|
|
7586
|
+
warnings.push(
|
|
7587
|
+
`\u53C2\u4F1A\u4EBA\u65F6\u95F4\u6709\u51B2\u7A81\uFF08${memberConflictCount} \u6761\u5360\u7528\uFF09\uFF1B\u5F53\u5929\u6240\u6709\u4EBA\u90FD\u7A7A\u7684\u65F6\u6BB5\uFF1A` + slotOptions.map((item) => `[${item.key}] ${item.label}`).join("\uFF1B") + "\u2014\u2014\u8BF7\u7528\u9009\u9879\u65B9\u5F0F\u8BA9\u7528\u6237\u6311\uFF08\u9009\u5B9A\u540E\u91CD\u65B0 prepare \u5E76\u6539\u65F6\u95F4\uFF09\u3002"
|
|
7588
|
+
);
|
|
7589
|
+
} else if (memberConflictCount === 0 && slotOptions.length > 0) {
|
|
6011
7590
|
warnings.push(
|
|
6012
|
-
`\u53C2\u4F1A\u4EBA\
|
|
7591
|
+
`\u8BE5\u65F6\u6BB5\u53C2\u4F1A\u4EBA\u6CA1\u6709\u4F1A\u8BAE/\u65E5\u7A0B\u5360\u7528\uFF08\u5DF2\u6838\u5BF9\u4F1A\u8BAE\u56DE\u6267\u4E0E\u65E5\u7A0B\uFF09\u3002\u5F53\u5929\u5176\u4ED6\u5171\u540C\u7A7A\u95F2\u65F6\u6BB5\uFF1A${slotOptions.map((item) => `[${item.key}] ${item.label}`).join("\uFF1B")}`
|
|
6013
7592
|
);
|
|
6014
7593
|
} else if (decisions.dayBlocked?.summary) {
|
|
6015
7594
|
warnings.push(String(decisions.dayBlocked.summary));
|
|
6016
7595
|
}
|
|
6017
|
-
|
|
7596
|
+
const unmappedReal = unmapped.filter((name) => name !== "mt_name" && name !== "crm_member_count");
|
|
7597
|
+
if (unmappedReal.length > 0) {
|
|
6018
7598
|
warnings.push(
|
|
6019
|
-
`\u4EE5\u4E0B\u5B57\u6BB5\u6CA1\u6709\u5728\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u91CC\u627E\u5230\u540C\u540D\u5B57\u6BB5\uFF0C\u672A\u81EA\u52A8\u586B\u5199\uFF1A${
|
|
7599
|
+
`\u4EE5\u4E0B\u5B57\u6BB5\u6CA1\u6709\u5728\u5EFA\u4F1A\u6D41\u7A0B\u8868\u5355\u91CC\u627E\u5230\u540C\u540D\u5B57\u6BB5\uFF0C\u672A\u81EA\u52A8\u586B\u5199\uFF1A${unmappedReal.join("\u3001")}\uFF08\u8868\u5355\u73B0\u6709\u5B57\u6BB5\uFF1A${form.fields.map((field) => field.name).join("\u3001")}\uFF09`
|
|
6020
7600
|
);
|
|
6021
7601
|
}
|
|
6022
7602
|
if (!main[form.fields.find((field) => field.name === "\u4F1A\u8BAE\u540D\u79F0")?.id ?? ""] && !mapped.mt_name) {
|
|
6023
|
-
warnings.push(
|
|
7603
|
+
warnings.push(
|
|
7604
|
+
"\u8BE5\u5EFA\u4F1A\u6D41\u7A0B\u7684\u8868\u5355\u6CA1\u6709\u300C\u4F1A\u8BAE\u540D\u79F0\u300D\u5B57\u6BB5\uFF08\u90E8\u5206\u6D41\u7A0B\u7528\u6D41\u7A0B\u6807\u9898\u4EE3\u66FF\u4F1A\u8BAE\u540D\u79F0\uFF0C\u5C5E\u6B63\u5E38\u914D\u7F6E\uFF0C\u4E0D\u662F\u6D41\u7A0B\u914D\u9519\uFF09\u3002\u5982\u9700\u4F1A\u8BAE\u540D\u79F0\u72EC\u7ACB\u6210\u5B57\u6BB5\uFF0C\u8BF7\u6539\u9009\u5E26\u8BE5\u5B57\u6BB5\u7684\u6D41\u7A0B\uFF08\u5982\u300C\u4F1A\u8BAE\u7533\u8BF7\u6D41\u7A0B\uFF08NEW\uFF09\u300D\uFF09\u3002"
|
|
7605
|
+
);
|
|
6024
7606
|
}
|
|
7607
|
+
const crmPatchIds = (Array.isArray(shaped.values.crm_members) ? shaped.values.crm_members : []).map((row) => String(row?.id ?? "").trim()).filter((id) => id !== "");
|
|
6025
7608
|
const session = await env.host.getSession();
|
|
6026
7609
|
const continuation = await env.continuation.issue(
|
|
6027
7610
|
{
|
|
@@ -6033,10 +7616,18 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
6033
7616
|
workflowId,
|
|
6034
7617
|
requestName: String(args.mt_name),
|
|
6035
7618
|
mtName: String(args.mt_name),
|
|
6036
|
-
data: { main },
|
|
6037
|
-
surfaceContinuation: form.continuation
|
|
7619
|
+
data: { main, ...detailPayload ? { details: detailPayload } : {} },
|
|
7620
|
+
surfaceContinuation: form.continuation,
|
|
7621
|
+
// 供 apply 在「会议还没生成」时按申请单信息预生成邀请函(预置函)
|
|
7622
|
+
invitationFields: shaped.readable,
|
|
7623
|
+
// 提交后回显要用「字段名 → 值」,字段清单先存下来(apply 阶段拿不到 createForm 结果)
|
|
7624
|
+
fieldLabels: form.fields.map((field) => ({ id: String(field.id), name: String(field.name) })),
|
|
7625
|
+
// 已确认的「人员 id → 姓名」,供 apply 回显时把裸 id 换成姓名
|
|
7626
|
+
...autoFilledPerson.length > 0 ? { personLabels: Object.fromEntries(autoFilledPerson.map((one) => [one.id, one.name])) } : {},
|
|
7627
|
+
// 会议记录的客户要靠 apply 补写(表单「参会客户」是 Ebuilder,单据↔会议表不同步)
|
|
7628
|
+
...crmPatchIds.length > 0 ? { crmPatch: { ids: crmPatchIds, count: crmMemberCount === void 0 ? crmPatchIds.length : crmMemberCount } } : {}
|
|
6038
7629
|
},
|
|
6039
|
-
fingerprint: JSON.stringify({ workflowId, main })
|
|
7630
|
+
fingerprint: JSON.stringify({ workflowId, main, ...detailPayload ? { details: detailPayload } : {} })
|
|
6040
7631
|
},
|
|
6041
7632
|
10 * 60 * 1e3
|
|
6042
7633
|
);
|
|
@@ -6048,9 +7639,27 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
6048
7639
|
workflowId,
|
|
6049
7640
|
workflowCandidates: candidates,
|
|
6050
7641
|
...probes.length > 0 ? { workflowProbes: probes } : {},
|
|
7642
|
+
...flowPickNote ? { workflowAutoPicked: { workflowId, source: resolved.source, note: flowPickNote } } : {},
|
|
6051
7643
|
requestName: String(args.mt_name),
|
|
6052
7644
|
fieldMapping: mapped,
|
|
6053
7645
|
formData: { main },
|
|
7646
|
+
// 人话版「即将提交的内容」—— 提交前必须先贴给用户核对(见 SKILL 建会章节)。
|
|
7647
|
+
formPreview: renderFormPreview(
|
|
7648
|
+
form.fields,
|
|
7649
|
+
await decoratePreviewPersonNames(
|
|
7650
|
+
env,
|
|
7651
|
+
main,
|
|
7652
|
+
form.fields,
|
|
7653
|
+
new Map(autoFilledPerson.map((one) => [one.id, one.name]))
|
|
7654
|
+
)
|
|
7655
|
+
),
|
|
7656
|
+
// 召集人/联系人是不是"替用户默认填的"要说清楚,用户才知道能不能改。
|
|
7657
|
+
...autoFilledPerson.length > 0 ? {
|
|
7658
|
+
autoFilled: Object.fromEntries(
|
|
7659
|
+
autoFilledPerson.map((one) => [PERSON_FIELD_LABELS[one.field], `${one.name}(${one.id})`])
|
|
7660
|
+
)
|
|
7661
|
+
} : {},
|
|
7662
|
+
...detailPayload ? { detailRows: { subFormId: Object.keys(detailPayload)[0], count: crmDetailRows.length, rows: crmDetailRows } } : {},
|
|
6054
7663
|
formFieldCount: form.fields.length,
|
|
6055
7664
|
...Object.keys(decisions).length > 0 ? { decisions } : {}
|
|
6056
7665
|
},
|
|
@@ -6061,6 +7670,94 @@ var ebMeetingCreateFlowPrepare = {
|
|
|
6061
7670
|
);
|
|
6062
7671
|
}
|
|
6063
7672
|
};
|
|
7673
|
+
var CRM_PATCH_SETTLE_MS = [4e3, 6e3];
|
|
7674
|
+
async function patchMeetingCrmMembers(env, meetingId, ids, count, settleMsList = CRM_PATCH_SETTLE_MS) {
|
|
7675
|
+
const list = ids.map((id) => String(id ?? "").trim()).filter((id) => id !== "");
|
|
7676
|
+
if (String(meetingId).trim() === "" || list.length === 0) {
|
|
7677
|
+
return { ok: false, error: "\u6CA1\u6709\u4F1A\u8BAE id \u6216\u5BA2\u6237 id" };
|
|
7678
|
+
}
|
|
7679
|
+
const mainTable = {
|
|
7680
|
+
id: String(meetingId).trim(),
|
|
7681
|
+
operate_type: "UPDATE",
|
|
7682
|
+
crm_members: list.join(",")
|
|
7683
|
+
};
|
|
7684
|
+
const total = Number(count);
|
|
7685
|
+
if (Number.isFinite(total) && total > 0) mainTable.crm_total_member = String(total);
|
|
7686
|
+
const write = async () => {
|
|
7687
|
+
const session = await env.host.getSession();
|
|
7688
|
+
await env.host.request({
|
|
7689
|
+
method: "POST",
|
|
7690
|
+
path: `${EB_BASE}/updateFormData/change_meeting`,
|
|
7691
|
+
query: { id: String(meetingId).trim() },
|
|
7692
|
+
operation: "meeting.eb.meeting.create.flow.apply",
|
|
7693
|
+
body: writeBody(String(session.userId), { mainTable, details: {}, operateType: {} }),
|
|
7694
|
+
acceptBusiness: ebBusinessSuccess
|
|
7695
|
+
});
|
|
7696
|
+
};
|
|
7697
|
+
const readBack = async () => {
|
|
7698
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
7699
|
+
const detail = getMeetingOperation2("meeting.eb.meeting.detail");
|
|
7700
|
+
const read = await detail.handler({ id: String(meetingId).trim() }, env);
|
|
7701
|
+
return String(read?.data?.data?.crm_members ?? "").trim();
|
|
7702
|
+
};
|
|
7703
|
+
let lastError = "";
|
|
7704
|
+
for (const settleMs of settleMsList) {
|
|
7705
|
+
try {
|
|
7706
|
+
await write();
|
|
7707
|
+
} catch (error) {
|
|
7708
|
+
return { ok: false, error: String(error?.message ?? error).slice(0, 160) };
|
|
7709
|
+
}
|
|
7710
|
+
await new Promise((resolve6) => setTimeout(resolve6, settleMs));
|
|
7711
|
+
try {
|
|
7712
|
+
const value = await readBack();
|
|
7713
|
+
if (value !== "") return { ok: true, value };
|
|
7714
|
+
lastError = "\u8865\u5199\u540E\u56DE\u8BFB crm_members \u4ECD\u4E3A\u7A7A\uFF08\u591A\u534A\u88AB\u4F1A\u8BAE\u521D\u59CB\u5316\u7684\u540E\u7EED\u5199\u5165\u8986\u76D6\u4E86\uFF09";
|
|
7715
|
+
} catch (error) {
|
|
7716
|
+
lastError = `\u8865\u5199\u6210\u529F\u4F46\u56DE\u8BFB\u5931\u8D25\uFF1A${String(error?.message ?? error).slice(0, 120)}`;
|
|
7717
|
+
}
|
|
7718
|
+
}
|
|
7719
|
+
return { ok: false, error: lastError };
|
|
7720
|
+
}
|
|
7721
|
+
async function renderPreInvitation(payload, env) {
|
|
7722
|
+
const fields = payload?.invitationFields ?? {};
|
|
7723
|
+
const started = Date.now();
|
|
7724
|
+
try {
|
|
7725
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
7726
|
+
const render = getMeetingOperation2("meeting.invitation.render");
|
|
7727
|
+
const rendered = await render.handler(
|
|
7728
|
+
{
|
|
7729
|
+
mt_name: String(fields.mt_name ?? payload?.mtName ?? "").trim(),
|
|
7730
|
+
begin_datetime: String(fields.begin_datetime ?? "").trim(),
|
|
7731
|
+
end_datetime: String(fields.end_datetime ?? "").trim(),
|
|
7732
|
+
address: String(fields.address ?? fields.customize_address ?? "").trim(),
|
|
7733
|
+
hrm_members: String(fields.hrm_members ?? "").trim(),
|
|
7734
|
+
mt_desc: String(fields.mt_desc ?? "").trim(),
|
|
7735
|
+
org_members: String(fields.org_members ?? "").trim(),
|
|
7736
|
+
caller: String(fields.caller ?? "").trim(),
|
|
7737
|
+
contacter: String(fields.contacter ?? "").trim(),
|
|
7738
|
+
total_member: String(fields.total_member ?? "").trim(),
|
|
7739
|
+
// 客户单位(邀请函开头「尊敬的 XXX」):建会时填了参会客户就直接带过去,
|
|
7740
|
+
// 否则整句永远是【待补充】—— 用户看到的就是"客户明明填了,邀请函里却没有"。
|
|
7741
|
+
extra: { guest_org: String(fields.crm_members ?? "").trim() }
|
|
7742
|
+
},
|
|
7743
|
+
env
|
|
7744
|
+
);
|
|
7745
|
+
return {
|
|
7746
|
+
invitation: { pending: true, preRendered: true, ...rendered?.data ?? {} },
|
|
7747
|
+
ms: Date.now() - started
|
|
7748
|
+
};
|
|
7749
|
+
} catch (error) {
|
|
7750
|
+
return {
|
|
7751
|
+
invitation: {
|
|
7752
|
+
pending: true,
|
|
7753
|
+
preRendered: false,
|
|
7754
|
+
ok: false,
|
|
7755
|
+
error: String(error?.message ?? error).slice(0, 200)
|
|
7756
|
+
},
|
|
7757
|
+
ms: Date.now() - started
|
|
7758
|
+
};
|
|
7759
|
+
}
|
|
7760
|
+
}
|
|
6064
7761
|
var ebMeetingCreateFlowApply = {
|
|
6065
7762
|
name: "meeting.eb.meeting.create.flow.apply",
|
|
6066
7763
|
resource: "eb",
|
|
@@ -6074,6 +7771,11 @@ var ebMeetingCreateFlowApply = {
|
|
|
6074
7771
|
{
|
|
6075
7772
|
continuation: { type: "string", description: "prepare \u8FD4\u56DE\u7684\u786E\u8BA4\u7968\u636E\uFF08\u5FC5\u586B\uFF09" },
|
|
6076
7773
|
confirm: { type: "boolean", description: "\u5FC5\u987B\u663E\u5F0F\u4F20 true" },
|
|
7774
|
+
submit_mode: {
|
|
7775
|
+
type: "string",
|
|
7776
|
+
enum: ["direct", "browser"],
|
|
7777
|
+
description: '\u63D0\u4EA4\u65B9\u5F0F\uFF0C\u9ED8\u8BA4 browser\uFF1A\u5728\u5C0Fe \u91CC**\u5F39\u51FA\u6D41\u7A0B\u8868\u5355**\uFF0C\u5B57\u6BB5\u5DF2\u9884\u586B\uFF0C\u7528\u6237\u6838\u5BF9/\u4FEE\u6539\u540E\u81EA\u5DF1\u70B9\u63D0\u4EA4\u3002direct = \u76F4\u63A5\u5199\u670D\u52A1\u7AEF\uFF08\u4F1A\u8BAE\u5F53\u573A\u751F\u6210\u3001\u9080\u8BF7\u51FD\u7528\u771F\u5B9E\u6570\u636E\uFF0C\u4F46\u6CA1\u6709\u4EBA\u5DE5\u6838\u5BF9\u8868\u5355\u8FD9\u4E00\u6B65\uFF09\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8BF4"\u4E0D\u7528\u6211\u786E\u8BA4\uFF0C\u76F4\u63A5\u5EFA"\u65F6\u624D\u4F20 direct'
|
|
7778
|
+
},
|
|
6077
7779
|
waitSeconds: { type: "number", description: "\u63D0\u4EA4\u540E\u7B49\u5F85\u4F1A\u8BAE\u751F\u6210\u7684\u6700\u957F\u79D2\u6570\uFF08\u9ED8\u8BA4 60\uFF0C0 = \u4E0D\u7B49\u5F85\uFF09" }
|
|
6078
7780
|
},
|
|
6079
7781
|
{ required: ["continuation", "confirm"] }
|
|
@@ -6091,9 +7793,9 @@ var ebMeetingCreateFlowApply = {
|
|
|
6091
7793
|
throw meetingValidationError("context_mismatch", "\u786E\u8BA4\u4E0A\u4E0B\u6587\u5DF2\u53D8\u5316\uFF08\u79DF\u6237\u6216\u767B\u5F55\u8D26\u53F7\u4E0D\u540C\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare");
|
|
6092
7794
|
}
|
|
6093
7795
|
const payload = lease?.payload ?? {};
|
|
6094
|
-
const { createWorkflowHost } = await import("./host-
|
|
7796
|
+
const { createWorkflowHost } = await import("./host-7RXEDMAH.js");
|
|
6095
7797
|
const { createWorkflowContinuationSigner } = await import("./continuation-HZIZRZBX.js");
|
|
6096
|
-
const { getWorkflowOperation } = await import("./registry-
|
|
7798
|
+
const { getWorkflowOperation } = await import("./registry-SG2PGVCF.js");
|
|
6097
7799
|
const wfEnv = {
|
|
6098
7800
|
...workflowEnv(env),
|
|
6099
7801
|
host: createWorkflowHost(env.ctx),
|
|
@@ -6101,6 +7803,7 @@ var ebMeetingCreateFlowApply = {
|
|
|
6101
7803
|
};
|
|
6102
7804
|
const submitStartedAt = Date.now();
|
|
6103
7805
|
const submit = getWorkflowOperation("workflow.createRequest");
|
|
7806
|
+
const submitMode = String(args.submit_mode ?? "browser").trim();
|
|
6104
7807
|
const submitted = await submit.handler(
|
|
6105
7808
|
{
|
|
6106
7809
|
// 工作流的入参名是 context(createForm 返回的 continuation 就是它的 context 句柄)
|
|
@@ -6108,7 +7811,8 @@ var ebMeetingCreateFlowApply = {
|
|
|
6108
7811
|
data: payload.data,
|
|
6109
7812
|
action: "submit",
|
|
6110
7813
|
requestName: payload.requestName,
|
|
6111
|
-
confirm: true
|
|
7814
|
+
confirm: true,
|
|
7815
|
+
...submitMode === "browser" ? {} : { forceServerSubmit: true }
|
|
6112
7816
|
},
|
|
6113
7817
|
wfEnv
|
|
6114
7818
|
);
|
|
@@ -6134,6 +7838,33 @@ var ebMeetingCreateFlowApply = {
|
|
|
6134
7838
|
);
|
|
6135
7839
|
}
|
|
6136
7840
|
if (!requestId) {
|
|
7841
|
+
const submitStatus = String(submittedData.status ?? submitted?.status ?? "");
|
|
7842
|
+
if (submitStatus === "BROWSER_FILL") {
|
|
7843
|
+
const pre = await renderPreInvitation(payload, env);
|
|
7844
|
+
return meetingSuccess(
|
|
7845
|
+
"meeting.eb.meeting.create.flow.apply",
|
|
7846
|
+
{
|
|
7847
|
+
status: "BROWSER_FILL",
|
|
7848
|
+
workflowId: payload.workflowId,
|
|
7849
|
+
requestName: payload.requestName,
|
|
7850
|
+
requestId: null,
|
|
7851
|
+
meetingId: null,
|
|
7852
|
+
contextId: submittedData.contextId ?? null,
|
|
7853
|
+
// 宿主要靠这段 <browsertool> 才能把表单拉到浏览器里填,必须原样透出
|
|
7854
|
+
finalMarkdown: submittedData.finalMarkdown ?? null,
|
|
7855
|
+
message: String(submittedData.message ?? ""),
|
|
7856
|
+
invitation: pre.invitation,
|
|
7857
|
+
timings: { submitMs: Date.now() - submitStartedAt, invitationMs: pre.ms }
|
|
7858
|
+
},
|
|
7859
|
+
{
|
|
7860
|
+
warnings: [
|
|
7861
|
+
'\u5F53\u524D\u662F\u5C0Fe \u73AF\u5883\uFF1A\u672C\u6B21**\u6CA1\u6709\u5411\u670D\u52A1\u7AEF\u5199\u5165**\uFF0C\u5EFA\u4F1A\u6D41\u7A0B\u6539\u7531\u6D4F\u89C8\u5668\u9875\u9762\u5B8C\u6210\u586B\u5355\uFF08\u89C1 finalMarkdown\uFF09\u3002\u56E0\u6B64\u8FD8\u6CA1\u6709 requestId / \u4F1A\u8BAE id\uFF0C\u4E5F**\u4E0D\u80FD\u8BF4"\u6D41\u7A0B\u5DF2\u63D0\u4EA4"**\u3002',
|
|
7862
|
+
`\u9080\u8BF7\u51FD\u5DF2\u6309\u7533\u8BF7\u5355\u4FE1\u606F**\u9884\u751F\u6210**\uFF08\u9884\u7F6E\u51FD\uFF0C${String(pre.invitation.filePath ?? "\u89C1 filePath")}\uFF09\uFF1A\u8BF7\u4E0B\u8F7D\u540E\u4EBA\u5DE5\u6838\u5BF9\u3001\u81EA\u884C\u53D1\u9001\uFF1B\u6D41\u7A0B\u5BA1\u6279\u901A\u8FC7\u3001\u4F1A\u8BAE\u751F\u6210\u540E\u53EF\u7528 mtId \u518D\u8DD1\u4E00\u6B21 meeting.invitation.render \u62FF\u5B8C\u6574\u5B57\u6BB5\u7248\u672C\u3002`,
|
|
7863
|
+
'\u26D4 \u4E0D\u8981\u56E0\u4E3A"\u6CA1\u6709 requestId / \u6CA1\u6709\u4F1A\u8BAE id"\u91CD\u590D apply \u2014\u2014 \u586B\u5355\u8981\u5728\u90A3\u4E2A\u6D4F\u89C8\u5668\u9875\u9762\u91CC\u70B9\u63D0\u4EA4\u3002'
|
|
7864
|
+
]
|
|
7865
|
+
}
|
|
7866
|
+
);
|
|
7867
|
+
}
|
|
6137
7868
|
const missing = submittedData.missingFields ?? submittedData.requiredMissing ?? submittedData.missing ?? [];
|
|
6138
7869
|
throw meetingValidationError(
|
|
6139
7870
|
"flow_submit_incomplete",
|
|
@@ -6146,7 +7877,7 @@ var ebMeetingCreateFlowApply = {
|
|
|
6146
7877
|
let meetingId = "";
|
|
6147
7878
|
const timings = { submitMs: Date.now() - submitStartedAt };
|
|
6148
7879
|
if (waitSeconds > 0) {
|
|
6149
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
7880
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6150
7881
|
const list = getMeetingOperation2("meeting.eb.meeting.list");
|
|
6151
7882
|
const deadline = Date.now() + Math.min(waitSeconds, 30) * 1e3;
|
|
6152
7883
|
const pollStart = Date.now();
|
|
@@ -6163,18 +7894,44 @@ var ebMeetingCreateFlowApply = {
|
|
|
6163
7894
|
} catch {
|
|
6164
7895
|
}
|
|
6165
7896
|
if (waited >= 5e3) break;
|
|
6166
|
-
await new Promise((
|
|
7897
|
+
await new Promise((resolve6) => setTimeout(resolve6, 5e3));
|
|
6167
7898
|
waited += 5e3;
|
|
6168
7899
|
}
|
|
6169
7900
|
timings.pollMs = Date.now() - pollStart;
|
|
6170
7901
|
}
|
|
7902
|
+
let crmLinked;
|
|
7903
|
+
const crmPatch = payload?.crmPatch;
|
|
7904
|
+
const crmPatchEnabled = process.env.WEAVER_MEETING_CRM_PATCH === "1";
|
|
7905
|
+
if (meetingId && crmPatchEnabled && Array.isArray(crmPatch?.ids) && crmPatch.ids.length > 0) {
|
|
7906
|
+
const patched = await patchMeetingCrmMembers(env, meetingId, crmPatch.ids, crmPatch.count);
|
|
7907
|
+
crmLinked = {
|
|
7908
|
+
ok: patched.ok,
|
|
7909
|
+
requested: crmPatch.ids.length,
|
|
7910
|
+
...patched.value ? { readBack: patched.value } : {},
|
|
7911
|
+
...patched.error ? { error: patched.error } : {}
|
|
7912
|
+
};
|
|
7913
|
+
if (patched.ok) {
|
|
7914
|
+
warnings.push(`\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u5DF2\u8865\u5199\u5230\u4F1A\u8BAE\u8BB0\u5F55\uFF08crm_members=${patched.value}\uFF09\u3002`);
|
|
7915
|
+
} else {
|
|
7916
|
+
warnings.push(
|
|
7917
|
+
`\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u6CA1\u6709\u56DE\u8BFB\u5230\uFF08${patched.error ?? "\u672A\u77E5\u539F\u56E0"}\uFF09\uFF1A\u5F53\u524D\u8D70\u7684\u662F CLI \u624B\u5DE5\u8865\u5199\uFF08WEAVER_MEETING_CRM_PATCH=1\uFF09\uFF0C\u4E0D\u4F9D\u8D56 ESB \u5B57\u6BB5\u6620\u5C04\u65F6\u624D\u9700\u8981\u5B83\u3002`
|
|
7918
|
+
);
|
|
7919
|
+
}
|
|
7920
|
+
}
|
|
6171
7921
|
let invitation = { pending: true };
|
|
6172
7922
|
if (meetingId) {
|
|
6173
7923
|
const invitationStart = Date.now();
|
|
6174
7924
|
try {
|
|
6175
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
7925
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6176
7926
|
const render = getMeetingOperation2("meeting.invitation.render");
|
|
6177
|
-
const rendered = await render.handler(
|
|
7927
|
+
const rendered = await render.handler(
|
|
7928
|
+
{
|
|
7929
|
+
mtId: meetingId,
|
|
7930
|
+
// 同理:会议主表不存客户名,用建会时填的参会客户补「客户单位」
|
|
7931
|
+
extra: { guest_org: String(payload?.invitationFields?.crm_members ?? "").trim() }
|
|
7932
|
+
},
|
|
7933
|
+
env
|
|
7934
|
+
);
|
|
6178
7935
|
invitation = { pending: false, ...rendered?.data ?? {} };
|
|
6179
7936
|
timings.invitationMs = Date.now() - invitationStart;
|
|
6180
7937
|
} catch (error) {
|
|
@@ -6185,8 +7942,11 @@ var ebMeetingCreateFlowApply = {
|
|
|
6185
7942
|
};
|
|
6186
7943
|
}
|
|
6187
7944
|
} else {
|
|
7945
|
+
const pre = await renderPreInvitation(payload, env);
|
|
7946
|
+
invitation = pre.invitation;
|
|
7947
|
+
timings.invitationMs = pre.ms;
|
|
6188
7948
|
warnings.push(
|
|
6189
|
-
`\u6D41\u7A0B\u5DF2\u63D0\u4EA4\uFF08requestId=${requestId || "\u672A\u8FD4\u56DE"}\uFF09\uFF0C\u4F46 ${waitSeconds}s \u5185\u6CA1\u5728\u4F1A\u8BAE\u8868\u91CC\u67E5\u5230\u300C${payload.mtName}\u300D\u2014\u2014\u591A\u6570\u60C5\u51B5\u662F\u8FD8\u5728\u5BA1\u6279\u4E2D\u3002\
|
|
7949
|
+
`\u6D41\u7A0B\u5DF2\u63D0\u4EA4\uFF08requestId=${requestId || "\u672A\u8FD4\u56DE"}\uFF09\uFF0C\u4F46 ${waitSeconds}s \u5185\u6CA1\u5728\u4F1A\u8BAE\u8868\u91CC\u67E5\u5230\u300C${payload.mtName}\u300D\u2014\u2014\u591A\u6570\u60C5\u51B5\u662F\u8FD8\u5728\u5BA1\u6279\u4E2D\u3002\u5DF2\u6309\u7533\u8BF7\u5355\u4FE1\u606F**\u9884\u751F\u6210**\u9080\u8BF7\u51FD\uFF08\u5C5E\u9884\u7F6E\u51FD\uFF0C\u8BF7\u4EBA\u5DE5\u6838\u5BF9\u540E\u81EA\u884C\u53D1\u9001\uFF09\uFF1B\u5BA1\u6279\u901A\u8FC7\u3001\u4F1A\u8BAE\u751F\u6210\u540E\u53EF\u7528 mtId \u518D\u8DD1\u4E00\u6B21 meeting.invitation.render \u62FF\u5230\u5B8C\u6574\u5B57\u6BB5\u7248\u672C\u3002\u26D4 \u672C operation \u4E0D\u91CD\u590D\u63D0\u4EA4\u6D41\u7A0B \u2014\u2014 \u4E0D\u8981\u56E0\u4E3A"\u6CA1\u6709\u4F1A\u8BAE id"\u5C31\u91CD\u590D apply\u3002`
|
|
6190
7950
|
);
|
|
6191
7951
|
}
|
|
6192
7952
|
return meetingSuccess(
|
|
@@ -6198,6 +7958,19 @@ var ebMeetingCreateFlowApply = {
|
|
|
6198
7958
|
requestId,
|
|
6199
7959
|
requestName: payload.requestName,
|
|
6200
7960
|
meetingId: meetingId || null,
|
|
7961
|
+
// 参会客户有没有真的写进会议记录(表单侧是 Ebuilder,需 apply 补写;回读确认才算 ok)
|
|
7962
|
+
...crmLinked ? { crmLinked } : {},
|
|
7963
|
+
// 提交后回显「实际提交了什么」:字段名 → 值(人员/客户显示姓名,不显示 id)。
|
|
7964
|
+
// 用户要的就是"能看见内容",替代走不通的浏览器填单核对。
|
|
7965
|
+
submittedPreview: renderFormPreview(
|
|
7966
|
+
payload?.fieldLabels ?? [],
|
|
7967
|
+
await decoratePreviewPersonNames(
|
|
7968
|
+
env,
|
|
7969
|
+
payload?.data?.main ?? {},
|
|
7970
|
+
payload?.fieldLabels ?? [],
|
|
7971
|
+
new Map(Object.entries(payload?.personLabels ?? {}))
|
|
7972
|
+
)
|
|
7973
|
+
),
|
|
6201
7974
|
invitation,
|
|
6202
7975
|
result: submitted?.data ?? null
|
|
6203
7976
|
},
|
|
@@ -6210,22 +7983,32 @@ var ebMeetingCreateFlowQuick = {
|
|
|
6210
7983
|
resource: "eb",
|
|
6211
7984
|
method: "meeting.eb.meeting.create.flow.quick",
|
|
6212
7985
|
action: "meeting.eb.meeting.create.flow.quick",
|
|
6213
|
-
summary:
|
|
7986
|
+
summary: '\u4E00\u6B65\u6D41\u7A0B\u5EFA\u4F1A\uFF08prepare+apply \u5408\u5E76\uFF09\uFF1A\u5185\u90E8\u5E76\u884C\u505A\u4F1A\u8BAE\u5BA4\u63A8\u8350/\u51B2\u7A81\u68C0\u6D4B/\u7A7A\u95F2\u65F6\u6BB5\uFF0C\u9ED8\u8BA4**\u5F39\u6D4F\u89C8\u5668\u8868\u5355**\u7ED9\u7528\u6237\u6838\u5BF9\u63D0\u4EA4\uFF08submit_mode=browser\uFF0C\u5C0Fe \u91CC\u9884\u586B\u4EBA\u5458/\u5BA2\u6237\u540E\u7531\u7528\u6237\u70B9\u63D0\u4EA4\uFF1B\u975E\u5C0Fe \u73AF\u5883\u4F1A\u81EA\u52A8\u5199\u670D\u52A1\u7AEF\uFF09\uFF1B\u4F20 submit_mode=direct \u624D\u662F\u670D\u52A1\u7AEF\u76F4\u63D0\uFF08\u62FF requestId + meetingId\uFF0C\u4F1A\u8BAE\u5F53\u573A\u751F\u6210\u3001\u9080\u8BF7\u51FD\u7528\u771F\u5B9E\u6570\u636E\uFF09\u3002\u591A\u6D41\u7A0B\u6216\u9700\u9009\u62E9\u65F6\u4E0D\u63D0\u4EA4\uFF0C\u8FD4\u56DE\u9009\u9879\u3002\u26A0\uFE0F \u7528\u6237\u63D0\u5230\u5BA2\u6237\u540D\u65F6**\u5FC5\u987B\u5148** meeting.eb.crm.search {"keyword":"X"} \u62FF customerId \u518D\u4F20 crm_members:[{id,name}]\uFF1B\u53EA\u628A\u5BA2\u6237\u540D\u5199\u8FDB\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u800C\u4E0D\u4F20 crm_members \u4F1A\u88AB\u76F4\u63A5\u62D2\u7EDD\uFF08crm_member_required\uFF09\u3002\u26D4 \u4E0D\u8981\u7528 submit_mode=browser \u2014\u2014 \u5C0Fe \u586B\u5355\u9875\u4E0D\u7ED9\u6D4F\u89C8\u6309\u94AE\u8D4B\u503C\uFF0C\u53C2\u4F1A\u4EBA\u5458/\u53C2\u4F1A\u5BA2\u6237\u4F1A\u6574\u6BB5\u4E22\u5931',
|
|
6214
7987
|
capability: "eb.meeting",
|
|
6215
7988
|
risk: "high-risk-write",
|
|
6216
7989
|
requiresConfirmation: true,
|
|
6217
7990
|
inputSchema: schemaOf(
|
|
6218
7991
|
{
|
|
6219
7992
|
mt_name: { type: "string", description: "\u4F1A\u8BAE\u540D\u79F0\uFF08\u5FC5\u586B\uFF09" },
|
|
6220
|
-
begin_datetime: {
|
|
6221
|
-
|
|
7993
|
+
begin_datetime: {
|
|
7994
|
+
...SCHEMA_DATETIME_MINUTE,
|
|
7995
|
+
description: "\u5F00\u59CB\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\u3002**\u53EF\u4EE5\u4E0D\u4F20**\uFF1A\u4E0D\u4F20\u4F1A\u6309\u53C2\u4F1A\u4EBA\u4E0E\u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u60C5\u51B5\u63A8\u8350 3 \u4E2A\u65F6\u6BB5\u8BA9\u4F60\u9009\uFF1B\u53EA\u4F20\u5F00\u59CB\u65F6\u95F4\u3001\u4E0D\u4F20\u7ED3\u675F\u65F6\u95F4\u65F6\uFF0C\u6309 durationMinutes\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09\u81EA\u52A8\u7B97\u7ED3\u675F\u65F6\u95F4"
|
|
7996
|
+
},
|
|
7997
|
+
end_datetime: {
|
|
7998
|
+
...SCHEMA_DATETIME_MINUTE,
|
|
7999
|
+
description: "\u7ED3\u675F\u65F6\u95F4\uFF08yyyy-MM-dd HH:mm\uFF09\uFF1B\u4E0D\u4F20\u5219\u6309 durationMinutes \u4ECE\u5F00\u59CB\u65F6\u95F4\u63A8\u7B97\uFF08\u9ED8\u8BA4 60 \u5206\u949F\uFF09"
|
|
8000
|
+
},
|
|
6222
8001
|
mt_desc: { type: "string", description: "\u4F1A\u8BAE\u5185\u5BB9/\u8BF4\u660E" },
|
|
6223
8002
|
address: { type: "string", description: "\u4F1A\u8BAE\u5BA4\uFF08id \u6216\u540D\u79F0\uFF1B\u4E0D\u4F20\u5219\u8FD4\u56DE\u5019\u9009\u8BA9\u7528\u6237\u9009\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u51B3\u5B9A\uFF09" },
|
|
6224
8003
|
customize_address: { type: "string", description: "\u81EA\u5B9A\u4E49\u4F1A\u8BAE\u5730\u70B9" },
|
|
6225
8004
|
hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458 id\uFF0C\u9017\u53F7\u5206\u9694" },
|
|
6226
8005
|
total_member: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570" },
|
|
6227
|
-
caller: { type: "string", description: "\u53EC\u96C6\u4EBA" },
|
|
6228
|
-
contacter: { type: "string", description: "\u8054\u7CFB\u4EBA" },
|
|
8006
|
+
caller: { type: "string", description: "\u53EC\u96C6\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u53EC\u96C6\u4EBA\u624D\u4F20" },
|
|
8007
|
+
contacter: { type: "string", description: "\u8054\u7CFB\u4EBA\uFF08\u5458\u5DE5 id \u6216\u59D3\u540D\uFF09\u3002\u7F3A\u7701 = \u5F53\u524D\u767B\u5F55\u4EBA\uFF0C\u4E0D\u7528\u4F20\uFF1B\u53EA\u6709\u6307\u5B9A\u522B\u4EBA\u5F53\u8054\u7CFB\u4EBA\u624D\u4F20" },
|
|
8008
|
+
mt_type: {
|
|
8009
|
+
type: "string",
|
|
8010
|
+
description: "\u4F1A\u8BAE\u7C7B\u578B\uFF1A\u53EF\u4F20\u7C7B\u578B\u540D\u79F0\u6216 id\uFF08\u5148\u7528 `meeting.eb.type.list` \u67E5\u6709\u54EA\u4E9B\uFF09\u3002**\u5F88\u591A\u79DF\u6237\u7684\u6D41\u7A0B\u8868\u5355\u628A\u300C\u4F1A\u8BAE\u7C7B\u578B\u300D\u8BBE\u4E3A\u5FC5\u586B**\uFF0C\u4E0D\u4F20\u4F1A\u88AB `workflow.createRequest` \u6253\u56DE\u7F3A\u5B57\u6BB5"
|
|
8011
|
+
},
|
|
6229
8012
|
other_remark: { type: "string", description: "\u5907\u6CE8" },
|
|
6230
8013
|
workflowId: {
|
|
6231
8014
|
oneOf: [{ type: "string" }, { type: "array", items: { type: "string" } }],
|
|
@@ -6233,15 +8016,52 @@ var ebMeetingCreateFlowQuick = {
|
|
|
6233
8016
|
},
|
|
6234
8017
|
autoRoom: { type: "boolean", description: "\u9ED8\u8BA4 false\uFF1A\u4E0D\u6307\u5B9A\u4F1A\u8BAE\u5BA4\u65F6\u8FD4\u56DE\u5019\u9009\u8BA9\u7528\u6237\u9009\uFF1B\u4F20 true \u624D\u81EA\u52A8\u91C7\u7528\u63A8\u8350\u4F1A\u8BAE\u5BA4" },
|
|
6235
8018
|
allowNoRoom: { type: "boolean", description: "\u786E\u5B9E\u4E0D\u9700\u8981\u4F1A\u8BAE\u5BA4\uFF08\u7EBF\u4E0A\u4F1A\u7B49\uFF09\u65F6\u4F20 true" },
|
|
8019
|
+
timeConfirmed: {
|
|
8020
|
+
type: "boolean",
|
|
8021
|
+
description: '\u65F6\u95F4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0\uFF1A\u7528\u6237\u539F\u8BDD\u660E\u786E\u7ED9\u4E86\u65F6\u95F4\u3001\u6216\u5728\u65F6\u6BB5\u9009\u9879\u91CC\u70B9\u9009\u540E\u539F\u6837\u56DE\u4F20 value\uFF08\u81EA\u5E26\u6807\u8BB0\uFF09\u65F6\u624D\u4F20 true\uFF1B\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF0CCLI \u4F1A\u8FD4\u56DE\u65F6\u6BB5\u9009\u9879\u8BA9\u7528\u6237\u70B9\u9009'
|
|
8022
|
+
},
|
|
8023
|
+
roomConfirmed: {
|
|
8024
|
+
type: "boolean",
|
|
8025
|
+
description: '\u4F1A\u8BAE\u5BA4\u7684"\u7528\u6237\u5DF2\u786E\u8BA4"\u6807\u8BB0\uFF1A\u7528\u6237\u539F\u8BDD\u660E\u786E\u6307\u5B9A\u3001\u6216\u5728\u623F\u95F4\u9009\u9879\u91CC\u70B9\u9009\u540E\u539F\u6837\u56DE\u4F20 value\uFF08\u81EA\u5E26\u6807\u8BB0\uFF09\u65F6\u624D\u4F20 true\uFF1B\u4E0D\u4F20 = \u672A\u786E\u8BA4\uFF0CCLI \u4F1A\u628A\u6307\u5B9A\u623F\u95F4\u548C\u5019\u9009\u4E00\u8D77\u5217\u51FA\u6765\u8BA9\u7528\u6237\u70B9\u9009'
|
|
8026
|
+
},
|
|
6236
8027
|
confirm: { type: "boolean", description: "\u5FC5\u987B\u663E\u5F0F true \u624D\u4F1A\u771F\u6B63\u63D0\u4EA4" },
|
|
6237
8028
|
waitSeconds: { type: "number", description: "\u63D0\u4EA4\u540E\u7B49\u5F85\u4F1A\u8BAE\u751F\u6210\u7684\u79D2\u6570\uFF08\u9ED8\u8BA4 20\uFF1B\u7B97\u6CD5\u662F\u7ACB\u5373\u67E5\u4E00\u6B21 + 5s \u518D\u67E5\u4E00\u6B21\uFF0C\u4ECD\u672A\u751F\u6210\u5C31\u8FD4\u56DE pending\uFF09" },
|
|
6238
8029
|
enrich: { type: "boolean", description: "\u662F\u5426\u987A\u5E26\u505A\u4F1A\u8BAE\u5BA4\u63A8\u8350/\u51B2\u7A81\u68C0\u6D4B/\u7A7A\u95F2\u65F6\u6BB5\uFF08\u9ED8\u8BA4 true\uFF1B\u4EBA\u3001\u65F6\u95F4\u3001\u623F\u95F4\u90FD\u5DF2\u786E\u5B9A\u65F6\u4F20 false \u53EF\u663E\u8457\u52A0\u5FEB\uFF09" },
|
|
6239
8030
|
extraFields: {
|
|
6240
8031
|
type: "object",
|
|
6241
8032
|
description: '\u6309\u6D41\u7A0B\u8868\u5355\u5B57\u6BB5\u540D\u586B\u989D\u5916\u5B57\u6BB5\uFF08\u79DF\u6237\u81EA\u5EFA\u5B57\u6BB5\u7528\u8FD9\u4E2A\u53E3\u5B50\u5E26\u8FDB\u53BB\uFF09\uFF0C\u5F62\u5982 {"\u53C2\u4F1A\u5BA2\u6237": "xx\u516C\u53F8"}'
|
|
8033
|
+
},
|
|
8034
|
+
dateFrom: {
|
|
8035
|
+
type: "string",
|
|
8036
|
+
description: "\u6CA1\u7ED9\u5177\u4F53\u65F6\u95F4\u65F6\u6309\u54EA\u4E00\u5929\u63A8\u8350\u65F6\u6BB5\uFF08yyyy-MM-dd\uFF1B\u4E0D\u4F20\u9ED8\u8BA4\u660E\u5929\uFF09"
|
|
8037
|
+
},
|
|
8038
|
+
durationMinutes: {
|
|
8039
|
+
type: "number",
|
|
8040
|
+
description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09\uFF1A\u53EA\u7ED9\u4E86\u5F00\u59CB\u65F6\u95F4\u65F6\u7528\u6765\u7B97\u7ED3\u675F\u65F6\u95F4\uFF1B\u63A8\u8350\u65F6\u6BB5\u65F6\u4E5F\u6309\u8FD9\u4E2A\u65F6\u957F\u627E"
|
|
8041
|
+
},
|
|
8042
|
+
workStartHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u65E9\u5C0F\u65F6\uFF08\u9ED8\u8BA4 9\uFF09" },
|
|
8043
|
+
workEndHour: { type: "number", description: "\u63A8\u8350\u65F6\u6BB5\u7684\u6700\u665A\u5C0F\u65F6\uFF08\u9ED8\u8BA4 18\uFF09" },
|
|
8044
|
+
fieldValues: {
|
|
8045
|
+
type: "object",
|
|
8046
|
+
additionalProperties: true,
|
|
8047
|
+
description: '\u6309**\u8868\u5355\u5B57\u6BB5 datakey\uFF08fieldId\uFF09**\u76F4\u63A5\u7ED9\u503C\uFF0C\u5F62\u5982 {"1325677252711735881": "\u7814\u8BA8\u4F1A"}\uFF1B\u4F18\u5148\u7EA7\u6700\u9AD8\uFF0C\u9002\u5408\u5B57\u6BB5\u540D\u5E26\u63D0\u793A\u8BED\u6216\u79DF\u6237\u81EA\u5EFA\u5B57\u6BB5\u3002datakey \u89C1 prepare \u7684 preview.mapped'
|
|
8048
|
+
},
|
|
8049
|
+
flowChoice: {
|
|
8050
|
+
type: "string",
|
|
8051
|
+
enum: ["auto", "ask"],
|
|
8052
|
+
description: "\u591A\u4E2A\u5EFA\u4F1A\u6D41\u7A0B**\u90FD\u6709\u53D1\u8D77\u6743\u9650**\u65F6\uFF1A\u9ED8\u8BA4\uFF08\u4E0D\u4F20 / ask\uFF09= \u8FD4\u56DE\u9009\u9879\u8BA9\u7528\u6237\u6311\uFF1Bauto = \u81EA\u52A8\u53D6\u4F18\u5148\u7EA7\u6700\u9AD8\u7684\u3002\u53EA\u6709 1 \u4E2A\u6709\u6743\u9650\u65F6\u76F4\u63A5\u53D1\u8D77"
|
|
8053
|
+
},
|
|
8054
|
+
crm_skip: {
|
|
8055
|
+
type: "boolean",
|
|
8056
|
+
description: "\u663E\u5F0F\u58F0\u660E\u300C\u8FD9\u6B21\u4E0D\u586B\u53C2\u4F1A\u5BA2\u6237\u300D\u3002\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u91CC\u51FA\u73B0 `\u5BA2\u6237\uFF1AX`\u3001`\u5BA2\u6237\u662FX` \u8FD9\u7C7B\u5B57\u6837\u5374**\u6CA1\u4F20 `crm_members`**\u65F6\uFF0C\u4E00\u6B65\u5EFA\u4F1A\u4F1A\u76F4\u63A5\u62D2\u7EDD\uFF08crm_member_required\uFF09\u2014\u2014\u786E\u8BA4\u8FD9\u4E9B\u5B57\u6837\u4E0D\u662F\u8981\u4E0A\u4F1A\u8868\u7684\u5BA2\u6237\uFF0C\u624D\u4F20 true"
|
|
8057
|
+
},
|
|
8058
|
+
submit_mode: {
|
|
8059
|
+
type: "string",
|
|
8060
|
+
enum: ["direct", "browser"],
|
|
8061
|
+
description: '\u63D0\u4EA4\u65B9\u5F0F\uFF0C\u9ED8\u8BA4 browser\uFF1A\u5728\u5C0Fe \u91CC**\u5F39\u51FA\u6D41\u7A0B\u8868\u5355**\uFF08\u5B57\u6BB5\u5DF2\u9884\u586B\u542B\u4EBA\u5458/\u5BA2\u6237\uFF09\uFF0C\u7528\u6237\u6838\u5BF9\u4FEE\u6539\u540E\u81EA\u5DF1\u70B9\u63D0\u4EA4\u3002direct = \u76F4\u63A5\u5199\u670D\u52A1\u7AEF\uFF08\u4F1A\u8BAE\u5F53\u573A\u751F\u6210\u3001\u9080\u8BF7\u51FD\u7528\u771F\u5B9E\u6570\u636E\uFF0C\u4F46\u6CA1\u6709\u4EBA\u5DE5\u6838\u5BF9\u8868\u5355\u8FD9\u4E00\u6B65\uFF09\uFF1B\u53EA\u6709\u7528\u6237\u660E\u786E\u8BF4"\u4E0D\u7528\u6211\u786E\u8BA4\uFF0C\u76F4\u63A5\u5EFA"\u65F6\u624D\u4F20 direct'
|
|
6242
8062
|
}
|
|
6243
8063
|
},
|
|
6244
|
-
{ required: ["mt_name", "
|
|
8064
|
+
{ required: ["mt_name", "confirm"] }
|
|
6245
8065
|
),
|
|
6246
8066
|
handler: async (args, env) => {
|
|
6247
8067
|
if (args.confirm !== true) {
|
|
@@ -6250,10 +8070,20 @@ var ebMeetingCreateFlowQuick = {
|
|
|
6250
8070
|
"\u4E00\u6B65\u5EFA\u4F1A\u4F1A\u76F4\u63A5\u63D0\u4EA4\u6D41\u7A0B\uFF0C\u5FC5\u987B\u663E\u5F0F\u4F20 confirm=true\uFF1B\u5982\u53EA\u60F3\u770B\u65B9\u6848\uFF0C\u8BF7\u7528 meeting.eb.meeting.create.flow.prepare"
|
|
6251
8071
|
);
|
|
6252
8072
|
}
|
|
6253
|
-
const
|
|
8073
|
+
const crmMentioned = detectCrmMentionInText(args.mt_name, args.mt_desc, args.other_remark);
|
|
8074
|
+
const crmSkipped = args.crm_skip === true;
|
|
8075
|
+
if (crmMentioned && !args.crm_members && !crmSkipped) {
|
|
8076
|
+
throw meetingValidationError(
|
|
8077
|
+
"crm_member_required",
|
|
8078
|
+
`\u4F1A\u8BAE\u540D\u79F0/\u5185\u5BB9\u91CC\u63D0\u5230\u5BA2\u6237\u300C${crmMentioned}\u300D\uFF0C\u4F46\u6CA1\u4F20 crm_members \u2014\u2014 \u63D0\u4EA4\u540E\u300C\u53C2\u4F1A\u5BA2\u6237\u300D\u4F1A\u662F\u7A7A\u7684\u3002\u5148 meeting.eb.crm.search {"keyword":"${crmMentioned}"} \u62FF items[].customerId\uFF0C\u518D\u628A crm_members:[{"id":"<customerId>","name":"<\u5B8C\u6574\u5BA2\u6237\u540D>"}] \u4E00\u8D77\u4F20\uFF08\u5FC5\u987B\u5E26\u540D\u79F0\uFF0C\u53EA\u7ED9 id \u4F1A\u88AB\u9759\u9ED8\u5B58\u7A7A\uFF09\uFF1B\u786E\u5B9E\u4E0D\u9700\u8981\u586B\u53C2\u4F1A\u5BA2\u6237\u5C31\u4F20 crm_skip:true\u3002`
|
|
8079
|
+
);
|
|
8080
|
+
}
|
|
8081
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6254
8082
|
const prepareStartedAt = Date.now();
|
|
8083
|
+
const { submit_mode: _submitMode, confirm: _confirm, ...prepareArgs } = args;
|
|
6255
8084
|
const prepared = await getMeetingOperation2("meeting.eb.meeting.create.flow.prepare").handler(
|
|
6256
|
-
|
|
8085
|
+
// submit_mode 只属于提交阶段,prepare 的 schema 不接受它(additionalProperties:false)
|
|
8086
|
+
prepareArgs,
|
|
6257
8087
|
env
|
|
6258
8088
|
);
|
|
6259
8089
|
if (prepared?.data?.status === "NEEDS_SELECTION") {
|
|
@@ -6269,6 +8099,7 @@ var ebMeetingCreateFlowQuick = {
|
|
|
6269
8099
|
{
|
|
6270
8100
|
continuation,
|
|
6271
8101
|
confirm: true,
|
|
8102
|
+
...args.submit_mode ? { submit_mode: args.submit_mode } : {},
|
|
6272
8103
|
...args.waitSeconds !== void 0 ? { waitSeconds: args.waitSeconds } : {}
|
|
6273
8104
|
},
|
|
6274
8105
|
env
|
|
@@ -6285,6 +8116,12 @@ var ebMeetingCreateFlowQuick = {
|
|
|
6285
8116
|
requestId: applied?.data?.requestId,
|
|
6286
8117
|
meetingId: applied?.data?.meetingId ?? null,
|
|
6287
8118
|
invitation: applied?.data?.invitation ?? null,
|
|
8119
|
+
// 已提交内容回显(字段名 → 值),提交后可直接贴给用户看"到底填进去了什么"
|
|
8120
|
+
submittedPreview: applied?.data?.submittedPreview ?? null,
|
|
8121
|
+
// 小e 环境(BROWSER_FILL)不写服务端,表单靠这段 <browsertool> 在浏览器里填 —— 必须一起透出,
|
|
8122
|
+
// 否则宿主拿不到表单,用户看到的就是"提交了但没反应"。
|
|
8123
|
+
...applied?.data?.contextId ? { contextId: (applied?.data).contextId } : {},
|
|
8124
|
+
...applied?.data?.finalMarkdown ? { finalMarkdown: (applied?.data).finalMarkdown } : {},
|
|
6288
8125
|
decisions: prepared?.data?.preview?.decisions ?? null,
|
|
6289
8126
|
timings: {
|
|
6290
8127
|
...prepared?.data?.preview?.decisions?.timings ?? {},
|
|
@@ -6299,7 +8136,123 @@ var ebMeetingCreateFlowQuick = {
|
|
|
6299
8136
|
);
|
|
6300
8137
|
}
|
|
6301
8138
|
};
|
|
8139
|
+
var ebMeetingCreateSuggest = {
|
|
8140
|
+
name: "meeting.eb.meeting.create.suggest",
|
|
8141
|
+
resource: "eb",
|
|
8142
|
+
method: "meeting.eb.meeting.create.suggest",
|
|
8143
|
+
action: "meeting.eb.meeting.create.suggest",
|
|
8144
|
+
summary: "\u5EFA\u4F1A\u5EFA\u8BAE\uFF1A\u7ED9\u5B9A\u65E5\u671F\u8303\u56F4\u4E0E\u53C2\u4F1A\u4EBA\uFF0C\u63A8\u8350\u300C\u6240\u6709\u4EBA\u90FD\u7A7A\u95F2 + \u8BE5\u65F6\u6BB5\u6709\u53EF\u7528\u4F1A\u8BAE\u5BA4\u300D\u7684\u65F6\u95F4\u5019\u9009\uFF08\u53EA\u8BFB\uFF0C\u4E0D\u5EFA\u4F1A\uFF09",
|
|
8145
|
+
capability: "eb.meeting",
|
|
8146
|
+
risk: "read",
|
|
8147
|
+
inputSchema: schemaOf(
|
|
8148
|
+
{
|
|
8149
|
+
dateFrom: { type: "string", description: "\u8D77\u59CB\u65E5\u671F\uFF08\u5FC5\u586B\uFF0Cyyyy-MM-dd\uFF09" },
|
|
8150
|
+
dateTo: { type: "string", description: "\u7ED3\u675F\u65E5\u671F\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u540C dateFrom\uFF1B\u6700\u591A\u8DE8 14 \u5929\uFF09" },
|
|
8151
|
+
durationMinutes: { type: "number", description: "\u4F1A\u8BAE\u65F6\u957F\uFF08\u5206\u949F\uFF0C\u9ED8\u8BA4 60\uFF09" },
|
|
8152
|
+
hrm_members: { type: "string", description: "\u53C2\u4F1A\u4EBA\u5458\uFF08\u5FC5\u586B\uFF0C\u5458\u5DE5 id \u6216\u59D3\u540D\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u59D3\u540D\u4F1A\u81EA\u52A8\u53CD\u67E5 id\uFF09" },
|
|
8153
|
+
memberCount: { type: "number", description: "\u53C2\u4F1A\u4EBA\u6570\uFF08\u53EF\u9009\uFF0C\u7528\u4E8E\u4F1A\u8BAE\u5BA4\u5BB9\u91CF\u7B5B\u9009\uFF1B\u4E0D\u4F20\u5219\u6309 hrm_members \u4E2A\u6570\uFF09" },
|
|
8154
|
+
workStartHour: { type: "number", description: "\u53EA\u5728\u51E0\u70B9\u4EE5\u540E\u627E\uFF08\u9ED8\u8BA4 9\uFF09" },
|
|
8155
|
+
workEndHour: { type: "number", description: "\u53EA\u5728\u51E0\u70B9\u4EE5\u524D\u627E\uFF08\u9ED8\u8BA4 18\uFF09" },
|
|
8156
|
+
maxSlots: { type: "number", description: "\u6700\u591A\u7ED9\u51E0\u4E2A\u65F6\u95F4\u5019\u9009\uFF08\u9ED8\u8BA4 3\uFF0C\u6700\u5927 8\uFF09" },
|
|
8157
|
+
topN: { type: "number", description: "\u6BCF\u4E2A\u65F6\u95F4\u5019\u9009\u6700\u591A\u5E26\u51E0\u95F4\u4F1A\u8BAE\u5BA4\uFF08\u9ED8\u8BA4 3\uFF09" },
|
|
8158
|
+
includeSchedule: { type: "boolean", description: "\u662F\u5426\u628A\u65E5\u7A0B\uFF08ESB\uFF09\u4E5F\u7B97\u8FDB\u5360\u7528\uFF08\u9ED8\u8BA4 true\uFF09" }
|
|
8159
|
+
},
|
|
8160
|
+
{ required: ["dateFrom", "hrm_members"] }
|
|
8161
|
+
),
|
|
8162
|
+
handler: async (args, env) => {
|
|
8163
|
+
const dateFrom = String(args.dateFrom ?? "").trim().slice(0, 10);
|
|
8164
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateFrom)) {
|
|
8165
|
+
throw meetingValidationError("datetime_invalid", `dateFrom \u5FC5\u987B\u662F yyyy-MM-dd\uFF0C\u6536\u5230\u300C${String(args.dateFrom ?? "")}\u300D`);
|
|
8166
|
+
}
|
|
8167
|
+
const dateTo = String(args.dateTo ?? "").trim().slice(0, 10) || dateFrom;
|
|
8168
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(dateTo)) {
|
|
8169
|
+
throw meetingValidationError("datetime_invalid", `dateTo \u5FC5\u987B\u662F yyyy-MM-dd\uFF0C\u6536\u5230\u300C${String(args.dateTo ?? "")}\u300D`);
|
|
8170
|
+
}
|
|
8171
|
+
const durationMinutes = Number(args.durationMinutes) > 0 ? Number(args.durationMinutes) : 60;
|
|
8172
|
+
const maxSlots = Math.max(1, Math.min(8, Number(args.maxSlots) || 3));
|
|
8173
|
+
const topN = Math.max(1, Math.min(5, Number(args.topN) || 3));
|
|
8174
|
+
const rawMembers = String(args.hrm_members ?? "").split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "");
|
|
8175
|
+
const nameLike = rawMembers.filter((item) => !/^\d+$/.test(item));
|
|
8176
|
+
const nameToId = nameLike.length > 0 ? await import("./schedule-NIJBTYDO.js").then((m) => m.resolveMemberIdsByName(env, nameLike)).catch(() => /* @__PURE__ */ new Map()) : /* @__PURE__ */ new Map();
|
|
8177
|
+
const memberIds = rawMembers.map((item) => nameToId.get(item) ?? item);
|
|
8178
|
+
const unresolved = rawMembers.filter((item) => nameToId.get(item) === void 0 && !/^\d+$/.test(item));
|
|
8179
|
+
const selfId = await env.host.getSession().then((s) => String(s?.userId ?? "")).catch(() => "");
|
|
8180
|
+
const selfIncluded = selfId !== "" && memberIds.includes(selfId);
|
|
8181
|
+
const memberCount = Number(args.memberCount) > 0 ? Number(args.memberCount) : memberIds.length > 0 ? memberIds.length + (selfIncluded ? 0 : 1) : void 0;
|
|
8182
|
+
const warnings = [];
|
|
8183
|
+
if (unresolved.length > 0) {
|
|
8184
|
+
warnings.push(`\u26A0\uFE0F \u8FD9\u4E9B\u53C2\u4F1A\u4EBA\u6CA1\u67E5\u5230\u5458\u5DE5 id\uFF1A${unresolved.join("\u3001")} \u2014\u2014 \u5DF2\u8DF3\u8FC7\uFF0C\u5176\u7A7A\u95F2\u60C5\u51B5**\u672A\u6838\u9A8C**`);
|
|
8185
|
+
}
|
|
8186
|
+
const free = await findCommonFreeSlots(env, {
|
|
8187
|
+
rangeStart: `${dateFrom} 00:00`,
|
|
8188
|
+
rangeEnd: `${dateTo} 23:59`,
|
|
8189
|
+
durationMinutes,
|
|
8190
|
+
members: memberIds,
|
|
8191
|
+
maxSlots,
|
|
8192
|
+
maxDays: 14,
|
|
8193
|
+
includeSchedule: args.includeSchedule !== false,
|
|
8194
|
+
...args.workStartHour !== void 0 ? { workStartHour: Number(args.workStartHour) } : {},
|
|
8195
|
+
...args.workEndHour !== void 0 ? { workEndHour: Number(args.workEndHour) } : {}
|
|
8196
|
+
});
|
|
8197
|
+
await loadRooms(env, { refresh: true }).catch(() => null);
|
|
8198
|
+
const withRooms = await Promise.all((free.slots ?? []).map(async (slot) => {
|
|
8199
|
+
try {
|
|
8200
|
+
const rec = await recommendRooms(env, {
|
|
8201
|
+
beginDatetime: slot.begin,
|
|
8202
|
+
endDatetime: slot.end,
|
|
8203
|
+
...memberCount ? { memberCount } : {},
|
|
8204
|
+
topN
|
|
8205
|
+
});
|
|
8206
|
+
return {
|
|
8207
|
+
begin: slot.begin,
|
|
8208
|
+
end: slot.end,
|
|
8209
|
+
rooms: rec.candidates.map((candidate) => ({
|
|
8210
|
+
id: candidate.id,
|
|
8211
|
+
name: candidate.name,
|
|
8212
|
+
capacityMax: candidate.capacity.max,
|
|
8213
|
+
reasons: candidate.reasons
|
|
8214
|
+
}))
|
|
8215
|
+
};
|
|
8216
|
+
} catch {
|
|
8217
|
+
return { begin: slot.begin, end: slot.end, rooms: [] };
|
|
8218
|
+
}
|
|
8219
|
+
}));
|
|
8220
|
+
const usable = withRooms.filter((slot) => slot.rooms.length > 0);
|
|
8221
|
+
if (usable.length === 0) {
|
|
8222
|
+
const why = (free.slots ?? []).length === 0 ? "\u8BE5\u8303\u56F4\u5185\u6240\u6709\u53C2\u4F1A\u4EBA\u6CA1\u6709\u5171\u540C\u7684\u7A7A\u95F2\u65F6\u6BB5" : `${(free.slots ?? []).length} \u4E2A\u300C\u4EBA\u7A7A\u95F2\u300D\u7684\u65F6\u6BB5\u91CC\uFF0C\u6CA1\u6709\u4E00\u4E2A\u8FD8\u80FD\u8BA2\u5230\u4F1A\u8BAE\u5BA4`;
|
|
8223
|
+
warnings.push(
|
|
8224
|
+
`\u6CA1\u627E\u5230\u540C\u65F6\u6EE1\u8DB3\u300C\u4EBA\u5458\u7A7A\u95F2 + \u4F1A\u8BAE\u5BA4\u7A7A\u95F2\u300D\u7684\u65F6\u95F4\u5019\u9009\uFF1A${why}\u3002\u8BF7\u5982\u5B9E\u544A\u77E5\u7528\u6237\uFF0C\u5E76\u5EFA\u8BAE\u6362\u4E2A\u65E5\u671F\u8303\u56F4\u3001\u7F29\u77ED\u65F6\u957F\uFF0C\u6216\u6539\u4E3A\u7EBF\u4E0A\u4F1A\u8BAE\uFF08allowNoRoom: true\uFF09\u3002`
|
|
8225
|
+
);
|
|
8226
|
+
if (free.blockingSummary) warnings.push(`\u5F53\u5929\u5360\u7528\u6982\u51B5\uFF1A${free.blockingSummary}`);
|
|
8227
|
+
}
|
|
8228
|
+
return meetingSuccess(
|
|
8229
|
+
"meeting.eb.meeting.create.suggest",
|
|
8230
|
+
{
|
|
8231
|
+
dateFrom,
|
|
8232
|
+
dateTo,
|
|
8233
|
+
durationMinutes,
|
|
8234
|
+
// 同样是"让用户点一下":时段候选用选项控件呈现,别写成文本列表
|
|
8235
|
+
ui: { component: "choice", multiple: false, recommendedKey: "T1" },
|
|
8236
|
+
slots: usable.map((slot, index) => ({
|
|
8237
|
+
key: `T${index + 1}`,
|
|
8238
|
+
label: `${slot.begin.slice(5, 10)} ${slot.begin.slice(11)}~${slot.end.slice(11)}`,
|
|
8239
|
+
value: { begin: slot.begin, end: slot.end, address: slot.rooms[0]?.id ?? null },
|
|
8240
|
+
reason: `${memberCount ? `${memberCount} \u4EBA\u5168\u90E8\u7A7A\u95F2\uFF08\u4F1A\u8BAE\u56DE\u6267 + \u65E5\u7A0B\u5DF2\u6838\uFF09\uFF1B` : ""}${slot.rooms.length} \u95F4\u4F1A\u8BAE\u5BA4\u53EF\u7528\uFF1A${slot.rooms.map((room) => room.name).join("\u3001")}`,
|
|
8241
|
+
rooms: slot.rooms
|
|
8242
|
+
})),
|
|
8243
|
+
// 把"人空闲但没房间"的时段也带出来,方便调用方解释为什么被剔除
|
|
8244
|
+
skippedSlots: withRooms.filter((slot) => slot.rooms.length === 0),
|
|
8245
|
+
memberIds,
|
|
8246
|
+
scheduleItems: free.scheduleItems,
|
|
8247
|
+
idle: free.idle,
|
|
8248
|
+
cost: free.cost
|
|
8249
|
+
},
|
|
8250
|
+
warnings.length > 0 ? { warnings } : {}
|
|
8251
|
+
);
|
|
8252
|
+
}
|
|
8253
|
+
};
|
|
6302
8254
|
var meetingEbCreateFlowOperations = [
|
|
8255
|
+
ebMeetingCreateSuggest,
|
|
6303
8256
|
ebMeetingCreateFlowPrepare,
|
|
6304
8257
|
ebMeetingCreateFlowApply,
|
|
6305
8258
|
ebMeetingCreateFlowQuick
|
|
@@ -6392,7 +8345,7 @@ var ebAutoInvitationAfterWrite = async (context) => {
|
|
|
6392
8345
|
const mtId = String(context.dataIds?.[0] ?? "").trim();
|
|
6393
8346
|
if (!isCreate || !enabled || !mtId) return association;
|
|
6394
8347
|
try {
|
|
6395
|
-
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-
|
|
8348
|
+
const { getMeetingOperation: getMeetingOperation2 } = await import("./registry-EP4VTHZS.js");
|
|
6396
8349
|
const render = getMeetingOperation2("meeting.invitation.render");
|
|
6397
8350
|
const result = await render.handler({ mtId }, context.env);
|
|
6398
8351
|
return { ...association ?? {}, invitation: result?.data ?? null };
|
|
@@ -6415,6 +8368,7 @@ var meetingEbOperations = [
|
|
|
6415
8368
|
...meetingEbConflictOperations,
|
|
6416
8369
|
...meetingEbDecisionOperations,
|
|
6417
8370
|
...meetingEbScheduleOperations,
|
|
8371
|
+
...meetingEbCrmOperations,
|
|
6418
8372
|
...meetingEbCreateFlowOperations,
|
|
6419
8373
|
ebRoomRecommendOperation
|
|
6420
8374
|
];
|