weaver-work-cli 0.1.29 → 0.1.31
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-U766FTFH.js +2537 -0
- package/dist/chunks/archive-oa-DMWEKX3L.js +1317 -0
- package/dist/chunks/asset-TCR7VDEV.js +2109 -0
- package/dist/chunks/attachment-content-AQNX5N3S.js +23 -0
- package/dist/chunks/blog-EVZWGDVM.js +2157 -0
- package/dist/chunks/caizhilian-JOWS6SL5.js +10087 -0
- package/dist/chunks/calendar-5WNCV66Q.js +1195 -0
- package/dist/chunks/chunk-2DUV44UX.js +15606 -0
- package/dist/chunks/chunk-324YPTC2.js +1607 -0
- package/dist/chunks/chunk-65QMVWHS.js +231 -0
- package/dist/chunks/chunk-6V7ZLF34.js +387 -0
- package/dist/chunks/chunk-AC7KJWC5.js +358 -0
- package/dist/chunks/chunk-AJ62BGAW.js +29 -0
- package/dist/chunks/chunk-BUSC6UAE.js +43 -0
- package/dist/chunks/chunk-CVZ2JOSW.js +62 -0
- package/dist/chunks/chunk-D4LTJSJD.js +477 -0
- package/dist/chunks/chunk-EG6ZU444.js +654 -0
- package/dist/chunks/chunk-EZALDOQH.js +383 -0
- package/dist/chunks/chunk-FMPJJYYI.js +106 -0
- package/dist/chunks/chunk-G2JSIUWF.js +769 -0
- package/dist/chunks/chunk-GCG2NMWR.js +703 -0
- package/dist/chunks/chunk-GPMFD4RD.js +75 -0
- package/dist/chunks/chunk-H3WDBYJW.js +508 -0
- package/dist/chunks/chunk-H6XSTSLM.js +2357 -0
- package/dist/chunks/chunk-J7RJTZSV.js +5556 -0
- package/dist/chunks/chunk-LUSPKZKY.js +53 -0
- package/dist/chunks/chunk-NIAJ5ZCG.js +73 -0
- package/dist/chunks/chunk-NOODWMCL.js +584 -0
- package/dist/chunks/chunk-OOUTBLZ4.js +51 -0
- package/dist/chunks/chunk-P26ZWSKU.js +73 -0
- package/dist/chunks/chunk-QWY6PGL6.js +3472 -0
- package/dist/chunks/chunk-R2IJAK7T.js +464 -0
- package/dist/chunks/chunk-R7O5PUWO.js +205 -0
- package/dist/chunks/chunk-RCGYCOMG.js +6962 -0
- package/dist/chunks/chunk-VZTXRG6X.js +403 -0
- package/dist/chunks/chunk-WHD4XMRP.js +161 -0
- package/dist/chunks/chunk-YLCYX7LE.js +371 -0
- package/dist/chunks/chunk-ZEDWSH32.js +68 -0
- package/dist/chunks/continuation-2CKSBLA6.js +11 -0
- package/dist/chunks/continuation-HZIZRZBX.js +13 -0
- package/dist/chunks/continuation-NLECEJPX.js +11 -0
- package/dist/chunks/ebuilder-form-NJ4YK6CC.js +2276 -0
- package/dist/chunks/ehr-MMYN36VA.js +5241 -0
- package/dist/chunks/employee-SAK2QYXX.js +11 -0
- package/dist/chunks/esb-HIWHOU7Q.js +141 -0
- package/dist/chunks/fna-KBACQTA5.js +1444 -0
- package/dist/chunks/host-3OHS5QUX.js +21 -0
- package/dist/chunks/host-IG6KEH5Q.js +19 -0
- package/dist/chunks/host-KQL5N4HO.js +23 -0
- package/dist/chunks/host-LLSZQCWR.js +17 -0
- package/dist/chunks/hrm-LYEC67ZQ.js +244 -0
- package/dist/chunks/im-RN2UKAEU.js +252 -0
- package/dist/chunks/invoice-EEPHLAF6.js +5179 -0
- package/dist/chunks/jiuchuanhui-WVVZYSJE.js +1940 -0
- package/dist/chunks/lazy-dispatch-MDOFFL2S.js +28 -0
- package/dist/chunks/mail-LNQLTF6L.js +2695 -0
- package/dist/chunks/meeting-XSD3BDVQ.js +504 -0
- package/dist/chunks/msg-parse-4GSQ2WTO.js +41 -0
- package/dist/chunks/okr-TMWTIU2K.js +2482 -0
- package/dist/chunks/plan-A2FSFA7T.js +2025 -0
- package/dist/chunks/project-T26QLBQF.js +1361 -0
- package/dist/chunks/registry-2VLUAESA.js +14 -0
- package/dist/chunks/registry-JCFEYXOE.js +18 -0
- package/dist/chunks/registry-NYPYMZXG.js +16 -0
- package/dist/chunks/registry-Q7OQJ3SU.js +19 -0
- package/dist/chunks/registry-ZJMJVWFA.js +19 -0
- package/dist/chunks/room-recommend-UR4ZDZS6.js +20 -0
- package/dist/chunks/schedule-5L2PM4M6.js +24 -0
- package/dist/chunks/state-Y2XBP6YE.js +15 -0
- package/dist/chunks/workflow-TR6PG2SL.js +245 -0
- package/dist/cmd/argv.js +45 -0
- package/dist/cmd/docs/index.js +3 -3
- package/dist/cmd/lazy-dispatch.js +20 -0
- package/dist/cmd/root.js +2 -4
- package/dist/cmd/setup/index.js +2 -2
- package/dist/cmd/skills/index.js +2 -2
- package/dist/core/package-paths.js +47 -0
- package/dist/index.js +163 -7
- package/dist/internal/e10/auth/xiaoe.js +3 -3
- package/dist/internal/e10/request-runtime.js +18 -62
- package/dist/internal/skills/detector.js +2 -2
- package/dist/shortcuts/contract/data/performance-catalog.js +1306 -0
- package/dist/shortcuts/contract/host.js +91 -35
- package/dist/shortcuts/contract/index.js +213 -0
- package/dist/shortcuts/contract/manifest.js +928 -0
- package/dist/shortcuts/contract/ooxml/docx.js +295 -0
- package/dist/shortcuts/contract/ooxml/xlsx.js +221 -0
- package/dist/shortcuts/contract/ooxml/zip.js +158 -0
- package/dist/shortcuts/contract/operations/assistant.js +1156 -0
- package/dist/shortcuts/contract/operations/clause-library.js +522 -0
- package/dist/shortcuts/contract/operations/compare.js +193 -0
- package/dist/shortcuts/contract/operations/credit-page.js +34 -0
- package/dist/shortcuts/contract/operations/flow.js +98 -0
- package/dist/shortcuts/contract/operations/page.js +66 -0
- package/dist/shortcuts/contract/operations/performance.js +733 -0
- package/dist/shortcuts/contract/operations/quote.js +557 -0
- package/dist/shortcuts/contract/operations/recommend.js +78 -0
- package/dist/shortcuts/contract/operations/registry.js +18 -0
- package/dist/shortcuts/contract/operations/review.js +83 -0
- package/dist/shortcuts/contract/operations/shared.js +37 -0
- package/dist/shortcuts/contract/operations/upload.js +108 -0
- package/dist/shortcuts/contract/operations/write.js +3 -2
- package/dist/shortcuts/index.js +140 -40
- package/dist/shortcuts/invoice/manifest.js +34 -11
- package/dist/shortcuts/invoice/operations/reim-auto.js +9 -0
- package/dist/shortcuts/invoice/operations/reim.js +81 -5
- package/dist/shortcuts/invoice/operations/shared.js +12 -5
- package/dist/shortcuts/meeting/host.js +45 -3
- package/dist/shortcuts/meeting/invitation/docx.js +442 -0
- package/dist/shortcuts/meeting/operations/attachment-content.js +418 -0
- package/dist/shortcuts/meeting/operations/attachment.js +442 -0
- package/dist/shortcuts/meeting/operations/eb/cache.js +57 -0
- package/dist/shortcuts/meeting/operations/eb/catalog.js +343 -28
- package/dist/shortcuts/meeting/operations/eb/conflict.js +372 -11
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +710 -0
- package/dist/shortcuts/meeting/operations/eb/decision.js +47 -1
- package/dist/shortcuts/meeting/operations/eb/factory.js +129 -11
- package/dist/shortcuts/meeting/operations/eb/index.js +122 -2
- package/dist/shortcuts/meeting/operations/eb/room-recommend.js +378 -0
- package/dist/shortcuts/meeting/operations/eb/room-summary.js +84 -0
- package/dist/shortcuts/meeting/operations/eb/schedule.js +450 -0
- package/dist/shortcuts/meeting/operations/from-group-chat.js +576 -0
- package/dist/shortcuts/meeting/operations/invitation.js +458 -0
- package/dist/shortcuts/meeting/operations/minute-content.js +266 -0
- package/dist/shortcuts/meeting/operations/pipeline.js +489 -0
- package/dist/shortcuts/meeting/operations/qrcode.js +131 -0
- package/dist/shortcuts/meeting/operations/receipts.js +1 -1
- package/dist/shortcuts/meeting/operations/registry.js +18 -0
- package/dist/shortcuts/meeting/operations/summary.js +276 -0
- package/dist/shortcuts/meeting/operations/task-notify.js +325 -0
- package/dist/shortcuts/meeting/operations.js +42 -1
- package/dist/shortcuts/meeting/qr/encoder.js +427 -0
- package/dist/shortcuts/meeting/qr/render.js +103 -0
- package/dist/shortcuts/workflow/operations/form.js +17 -5
- package/docs/contract.md +39 -4
- package/docs/invoice.md +5 -5
- package/package.json +3 -2
- package/scripts/bundle.mjs +63 -0
- package/skill-template/business-info.json +25 -4
- package/skill-template/domains/jinchengda.md +16 -3
- package/skill-template/domains/yepiaotong.md +1 -1
- package/skills/weaver-e10-jinchengda/SKILL.md +111 -31
- package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +7 -13
- package/skills/weaver-e10-jinchengda/references/contract-ai-assistant.md +150 -0
- package/skills/weaver-e10-jinchengda/references/contract-ai-review.md +87 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +111 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +0 -13
- package/skills/weaver-e10-jinchengda/references/contract-credit-page.md +50 -0
- package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +4 -2
- package/skills/weaver-e10-jinchengda/references/contract-doc-compare.md +74 -0
- package/skills/weaver-e10-jinchengda/references/contract-flow-launch.md +84 -0
- package/skills/weaver-e10-jinchengda/references/contract-performance-query.md +29 -0
- package/skills/weaver-e10-jinchengda/references/contract-quote-to-contract.md +28 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-status.md +2 -21
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +0 -24
- package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +0 -17
- package/skills/weaver-e10-jinchengda/references/contract-template-recommend.md +70 -0
- package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +0 -15
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +1168 -152
- package/skills/weaver-e10-meeting/SKILL.md +493 -17
- package/skills/weaver-e10-meeting/references/meeting-change.md +4 -4
- package/skills/weaver-e10-meeting/references/meeting-create.md +6 -6
- package/skills/weaver-e10-meeting/references/meeting-eb.md +503 -27
- package/skills/weaver-e10-meeting/references/meeting-invitation.md +113 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +6 -6
- package/skills/weaver-e10-meeting/references/meeting-minute-file.md +425 -0
- package/skills/weaver-e10-meeting/references/meeting-queries.md +4 -4
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +15 -15
- package/skills/weaver-e10-meeting/references/meeting-verification.md +19 -11
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-yepiaotong/SKILL.md +9 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +1 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +6 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +14 -11
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +97 -56
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +84 -60
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +142 -105
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +53 -194
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -7
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +164 -72
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +6 -0
- package/templates/meeting/invitation.docx +0 -0
|
@@ -0,0 +1,2025 @@
|
|
|
1
|
+
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
|
+
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
E10ApiError,
|
|
5
|
+
createE10RequestRuntime,
|
|
6
|
+
requireE10Session
|
|
7
|
+
} from "./chunk-H3WDBYJW.js";
|
|
8
|
+
import {
|
|
9
|
+
E10_SESSION_EXPIRED_MESSAGE,
|
|
10
|
+
getActiveProfile
|
|
11
|
+
} from "./chunk-324YPTC2.js";
|
|
12
|
+
import {
|
|
13
|
+
CliError,
|
|
14
|
+
isCliError,
|
|
15
|
+
toErrorEnvelope
|
|
16
|
+
} from "./chunk-LUSPKZKY.js";
|
|
17
|
+
import "./chunk-BUSC6UAE.js";
|
|
18
|
+
|
|
19
|
+
// src/shortcuts/plan/index.ts
|
|
20
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
21
|
+
|
|
22
|
+
// src/shortcuts/plan/continuation.ts
|
|
23
|
+
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
24
|
+
import { existsSync } from "node:fs";
|
|
25
|
+
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
26
|
+
import { homedir } from "node:os";
|
|
27
|
+
import { resolve } from "node:path";
|
|
28
|
+
|
|
29
|
+
// src/shortcuts/plan/errors.ts
|
|
30
|
+
var PlanCliError = class extends CliError {
|
|
31
|
+
type;
|
|
32
|
+
subtype;
|
|
33
|
+
code;
|
|
34
|
+
retryable;
|
|
35
|
+
stage;
|
|
36
|
+
details;
|
|
37
|
+
partialData;
|
|
38
|
+
constructor(type, subtype, message, options = {}) {
|
|
39
|
+
super(message, options.exitCode ?? 5 /* InternalError */);
|
|
40
|
+
this.name = "PlanCliError";
|
|
41
|
+
this.type = type;
|
|
42
|
+
this.subtype = subtype;
|
|
43
|
+
this.code = options.code;
|
|
44
|
+
this.retryable = options.retryable ?? false;
|
|
45
|
+
this.stage = options.stage;
|
|
46
|
+
this.details = options.details;
|
|
47
|
+
this.partialData = options.partialData;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
function planValidationError(subtype, message, details) {
|
|
51
|
+
return new PlanCliError("validation", subtype, message, {
|
|
52
|
+
details,
|
|
53
|
+
exitCode: 2 /* UsageError */
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function planAuthError(subtype, message, details) {
|
|
57
|
+
return new PlanCliError("authentication", subtype, message, {
|
|
58
|
+
details,
|
|
59
|
+
exitCode: 3 /* AuthError */
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function planNetworkError(subtype, message, options = {}) {
|
|
63
|
+
return new PlanCliError("network", subtype, message, {
|
|
64
|
+
...options,
|
|
65
|
+
retryable: options.retryable ?? true,
|
|
66
|
+
exitCode: 4 /* NetworkError */
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function planApiError(subtype, message, details) {
|
|
70
|
+
return new PlanCliError("api", subtype, message, {
|
|
71
|
+
details,
|
|
72
|
+
exitCode: 1 /* GeneralError */
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function planConfirmationError(action, details) {
|
|
76
|
+
return new PlanCliError("confirmation", "required", "\u8BE5\u64CD\u4F5C\u9700\u8981\u660E\u786E\u786E\u8BA4", {
|
|
77
|
+
details: { action, ...details },
|
|
78
|
+
exitCode: 10 /* ConfirmationRequired */
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function planUnsupportedError(subtype, message, details) {
|
|
82
|
+
return new PlanCliError("policy", subtype, message, {
|
|
83
|
+
details,
|
|
84
|
+
exitCode: 6 /* PolicyError */
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function planPartialError(message, partialData, details) {
|
|
88
|
+
return new PlanCliError("partial", "write_uncertain", message, {
|
|
89
|
+
details,
|
|
90
|
+
partialData,
|
|
91
|
+
exitCode: 11 /* Partial */
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function isPlanErrorType(error, type) {
|
|
95
|
+
return Boolean(error && typeof error === "object" && error.type === type);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/shortcuts/plan/continuation.ts
|
|
99
|
+
function planStateRoot(ctx) {
|
|
100
|
+
const configured = ctx?.config?.path();
|
|
101
|
+
if (configured) return resolve(configured, "..");
|
|
102
|
+
return process.env.WEAVER_WORK_CLI_HOME || process.env.WORK_CLI_HOME || resolve(homedir(), ".weaver-work-cli");
|
|
103
|
+
}
|
|
104
|
+
async function loadKey(ctx) {
|
|
105
|
+
const keysDir = resolve(planStateRoot(ctx), "keys");
|
|
106
|
+
const filename = resolve(keysDir, "plan-continuation.key");
|
|
107
|
+
await mkdir(keysDir, { recursive: true, mode: 448 });
|
|
108
|
+
if (existsSync(filename)) return readFile(filename);
|
|
109
|
+
const key = randomBytes(32);
|
|
110
|
+
try {
|
|
111
|
+
await writeFile(filename, key, { flag: "wx", mode: 384 });
|
|
112
|
+
if (process.platform !== "win32") await chmod(filename, 384).catch(() => void 0);
|
|
113
|
+
return key;
|
|
114
|
+
} catch {
|
|
115
|
+
return readFile(filename);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function encode(value) {
|
|
119
|
+
return Buffer.from(JSON.stringify(value)).toString("base64url");
|
|
120
|
+
}
|
|
121
|
+
function signature(payload, key) {
|
|
122
|
+
return createHmac("sha256", key).update(payload).digest("base64url");
|
|
123
|
+
}
|
|
124
|
+
function createPlanContinuationSigner(ctx) {
|
|
125
|
+
return {
|
|
126
|
+
async issue(payload, ttlMs = 10 * 6e4) {
|
|
127
|
+
const issuedAt = Date.now();
|
|
128
|
+
const body = encode({ ...payload, issuedAt, expiresAt: issuedAt + ttlMs });
|
|
129
|
+
const sig = signature(body, await loadKey(ctx));
|
|
130
|
+
return `${body}.${sig}`;
|
|
131
|
+
},
|
|
132
|
+
async verify(token, expectedOperation) {
|
|
133
|
+
if (typeof token !== "string" || !token.includes(".")) {
|
|
134
|
+
throw planValidationError("continuation_invalid", "continuation \u65E0\u6548");
|
|
135
|
+
}
|
|
136
|
+
const [body, provided] = token.split(".");
|
|
137
|
+
const expected = signature(body, await loadKey(ctx));
|
|
138
|
+
const valid = provided.length === expected.length && timingSafeEqual(Buffer.from(provided), Buffer.from(expected));
|
|
139
|
+
if (!valid) throw planValidationError("continuation_invalid", "continuation \u7B7E\u540D\u6821\u9A8C\u5931\u8D25");
|
|
140
|
+
let value;
|
|
141
|
+
try {
|
|
142
|
+
value = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
|
|
143
|
+
} catch {
|
|
144
|
+
throw planValidationError("continuation_invalid", "continuation \u5185\u5BB9\u65E0\u6CD5\u89E3\u6790");
|
|
145
|
+
}
|
|
146
|
+
if (value.operation !== expectedOperation) {
|
|
147
|
+
throw planValidationError("continuation_mismatch", "continuation \u4E0D\u5C5E\u4E8E\u5F53\u524D\u64CD\u4F5C");
|
|
148
|
+
}
|
|
149
|
+
if (!Number.isSafeInteger(value.expiresAt) || value.expiresAt < Date.now()) {
|
|
150
|
+
throw planValidationError("continuation_expired", "continuation \u5DF2\u8FC7\u671F");
|
|
151
|
+
}
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/shortcuts/plan/host.ts
|
|
158
|
+
import { createHash } from "node:crypto";
|
|
159
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
160
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
161
|
+
import { resolve as resolve2 } from "node:path";
|
|
162
|
+
function inferProfile(ctx) {
|
|
163
|
+
const options = ctx.getGlobalOptions();
|
|
164
|
+
return options.profile || getActiveProfile();
|
|
165
|
+
}
|
|
166
|
+
function cacheFilename(root, key) {
|
|
167
|
+
const digest = createHash("sha256").update(key).digest("hex").slice(0, 40);
|
|
168
|
+
return resolve2(root, "cache", "plan", `${digest}.json`);
|
|
169
|
+
}
|
|
170
|
+
async function readCacheFile(root, key) {
|
|
171
|
+
const file = cacheFilename(root, key);
|
|
172
|
+
if (!existsSync2(file)) return void 0;
|
|
173
|
+
try {
|
|
174
|
+
const parsed = JSON.parse(await readFile2(file, "utf8"));
|
|
175
|
+
if (parsed.key !== key) return void 0;
|
|
176
|
+
if (typeof parsed.expiresAt === "number" && parsed.expiresAt < Date.now()) return void 0;
|
|
177
|
+
return parsed.value;
|
|
178
|
+
} catch {
|
|
179
|
+
return void 0;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function writeCacheFile(root, key, value, ttlMs) {
|
|
183
|
+
const file = cacheFilename(root, key);
|
|
184
|
+
await mkdir2(resolve2(file, ".."), { recursive: true });
|
|
185
|
+
const payload = {
|
|
186
|
+
key,
|
|
187
|
+
value,
|
|
188
|
+
expiresAt: ttlMs === void 0 ? null : Date.now() + ttlMs,
|
|
189
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
190
|
+
};
|
|
191
|
+
await writeFile2(file, `${JSON.stringify(payload)}
|
|
192
|
+
`, "utf8");
|
|
193
|
+
}
|
|
194
|
+
function businessMessage(value) {
|
|
195
|
+
if (!value || typeof value !== "object") return "\u6CDB\u5FAE\u63A5\u53E3\u8FD4\u56DE\u4E1A\u52A1\u5931\u8D25";
|
|
196
|
+
const candidates = [
|
|
197
|
+
value.msg,
|
|
198
|
+
value.message,
|
|
199
|
+
value.resultMsg,
|
|
200
|
+
value.datajson?.message,
|
|
201
|
+
value.datajson?.msg
|
|
202
|
+
];
|
|
203
|
+
for (const item of candidates) {
|
|
204
|
+
if (typeof item === "string" && item.trim()) return item;
|
|
205
|
+
}
|
|
206
|
+
return "\u6CDB\u5FAE\u63A5\u53E3\u8FD4\u56DE\u4E1A\u52A1\u5931\u8D25";
|
|
207
|
+
}
|
|
208
|
+
function isDatajsonSuccess(value) {
|
|
209
|
+
const status = value?.datajson?.status;
|
|
210
|
+
return status === true || status === "true";
|
|
211
|
+
}
|
|
212
|
+
function isFlagSuccess(value) {
|
|
213
|
+
const status = value?.status;
|
|
214
|
+
return status === "1" || status === 1 || status === true;
|
|
215
|
+
}
|
|
216
|
+
function isWeaverCodeSuccess(value) {
|
|
217
|
+
if (!value || typeof value !== "object") return false;
|
|
218
|
+
if (Number(value.code) !== 200) return false;
|
|
219
|
+
return value.status !== false && value.status !== "false";
|
|
220
|
+
}
|
|
221
|
+
function assertPath(requestPath) {
|
|
222
|
+
if (typeof requestPath !== "string" || !requestPath.startsWith("/") || requestPath.startsWith("//")) {
|
|
223
|
+
throw planValidationError("path_invalid", "\u8BF7\u6C42\u8DEF\u5F84\u5FC5\u987B\u662F\u76F8\u5BF9\u7EDD\u5BF9\u8DEF\u5F84");
|
|
224
|
+
}
|
|
225
|
+
if (/^https?:/i.test(requestPath) || /[\r\n]/.test(requestPath) || requestPath.includes("/../")) {
|
|
226
|
+
throw planValidationError("path_invalid", "\u8BF7\u6C42\u8DEF\u5F84\u4E0D\u5141\u8BB8\u8DE8\u57DF\u6216\u8DEF\u5F84\u9003\u9038");
|
|
227
|
+
}
|
|
228
|
+
if (!requestPath.startsWith("/api/")) {
|
|
229
|
+
throw planValidationError("path_not_allowed", "\u8BA1\u5212\u62A5\u544A\u6A21\u5757\u53EA\u80FD\u8C03\u7528 /api/ \u8DEF\u5F84");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function omitEmptyQueryValues(query) {
|
|
233
|
+
if (!query) return void 0;
|
|
234
|
+
return Object.fromEntries(
|
|
235
|
+
Object.entries(query).filter(([, value]) => value !== "" && value !== void 0 && value !== null)
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
function mapRuntimeNetworkError(error) {
|
|
239
|
+
if (error instanceof E10ApiError && error.type === "network") {
|
|
240
|
+
throw planNetworkError(error.subtype, error.message, {
|
|
241
|
+
retryable: error.retryable,
|
|
242
|
+
details: error.details
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
function createPlanHost(ctx, dependencies = {}) {
|
|
248
|
+
let e10Session = null;
|
|
249
|
+
let sessionContext = null;
|
|
250
|
+
const requireSession = dependencies.requireSession || requireE10Session;
|
|
251
|
+
const cacheRoot = planStateRoot(ctx);
|
|
252
|
+
async function ensureSession() {
|
|
253
|
+
if (!e10Session) {
|
|
254
|
+
e10Session = await requireSession(ctx);
|
|
255
|
+
sessionContext = {
|
|
256
|
+
baseUrl: e10Session.getBaseUrl(),
|
|
257
|
+
profile: inferProfile(ctx),
|
|
258
|
+
userId: e10Session.userId,
|
|
259
|
+
tenantKey: e10Session.tenantKey,
|
|
260
|
+
eteamsId: e10Session.eteamsId
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return e10Session;
|
|
264
|
+
}
|
|
265
|
+
async function getSession() {
|
|
266
|
+
await ensureSession();
|
|
267
|
+
return sessionContext;
|
|
268
|
+
}
|
|
269
|
+
async function runtime() {
|
|
270
|
+
return createE10RequestRuntime(ctx, await ensureSession(), {
|
|
271
|
+
interceptors: dependencies.interceptors,
|
|
272
|
+
fetch: dependencies.fetch
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
async function request(request2) {
|
|
276
|
+
const { method, path, query, body, operation, timeoutMs = 3e4 } = request2;
|
|
277
|
+
assertPath(path);
|
|
278
|
+
let response;
|
|
279
|
+
try {
|
|
280
|
+
response = await (await runtime()).requestJson({
|
|
281
|
+
module: "plan",
|
|
282
|
+
operation,
|
|
283
|
+
method: (method || "POST").toUpperCase(),
|
|
284
|
+
path,
|
|
285
|
+
query: omitEmptyQueryValues(query),
|
|
286
|
+
body,
|
|
287
|
+
headers: { "X-Requested-With": "XMLHttpRequest" },
|
|
288
|
+
timeoutMs
|
|
289
|
+
});
|
|
290
|
+
} catch (error) {
|
|
291
|
+
mapRuntimeNetworkError(error);
|
|
292
|
+
}
|
|
293
|
+
if (response.status === 401 || response.status === 302) {
|
|
294
|
+
throw planAuthError(
|
|
295
|
+
"session_expired",
|
|
296
|
+
E10_SESSION_EXPIRED_MESSAGE,
|
|
297
|
+
{ httpStatus: response.status }
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
if (response.parseError) {
|
|
301
|
+
throw planNetworkError("protocol", `\u63A5\u53E3\u8FD4\u56DE\u4E0D\u662F\u5408\u6CD5 JSON\uFF08HTTP ${response.status}\uFF09`, { retryable: false });
|
|
302
|
+
}
|
|
303
|
+
if (response.status === 404) {
|
|
304
|
+
throw new PlanCliError("api", "endpoint_not_found", `\u63A5\u53E3\u8FD4\u56DE 404\uFF0C\u5F53\u524D\u73AF\u5883\u53EF\u80FD\u672A\u5B89\u88C5\u300C\u8BA1\u5212\u62A5\u544A\u300D\u76F8\u5173\u5E94\u7528\u6216\u63A5\u53E3\uFF08${path}\uFF09`, {
|
|
305
|
+
code: response.status,
|
|
306
|
+
details: { path },
|
|
307
|
+
exitCode: 1
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
if (response.status < 200 || response.status >= 300) {
|
|
311
|
+
throw new PlanCliError("api", "http_error", `\u6CDB\u5FAE\u63A5\u53E3 HTTP ${response.status}`, {
|
|
312
|
+
code: response.status,
|
|
313
|
+
details: { status: response.status, message: businessMessage(response.value) },
|
|
314
|
+
exitCode: 1
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
return response.value;
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
request,
|
|
321
|
+
getSession,
|
|
322
|
+
getCache: (key) => readCacheFile(cacheRoot, key),
|
|
323
|
+
setCache: (key, value, ttlMs) => writeCacheFile(cacheRoot, key, value, ttlMs)
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/shortcuts/plan/operations/types.ts
|
|
328
|
+
function planSuccess(action, data, meta) {
|
|
329
|
+
const payload = { ok: true, action, data };
|
|
330
|
+
if (meta && Object.keys(meta).length > 0) payload.meta = meta;
|
|
331
|
+
return payload;
|
|
332
|
+
}
|
|
333
|
+
function schemaOf(properties, options = {}) {
|
|
334
|
+
return {
|
|
335
|
+
type: "object",
|
|
336
|
+
additionalProperties: false,
|
|
337
|
+
properties,
|
|
338
|
+
...options.required?.length ? { required: options.required } : {},
|
|
339
|
+
...options.oneOf?.length ? { oneOf: options.oneOf } : {},
|
|
340
|
+
...options.anyOf?.length ? { anyOf: options.anyOf } : {},
|
|
341
|
+
...options.description ? { description: options.description } : {}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
var SCHEMA_ID = {
|
|
345
|
+
oneOf: [{ type: "integer" }, { type: "string", pattern: "^\\d+$" }]
|
|
346
|
+
};
|
|
347
|
+
var REPORT_TYPE_VALUES = ["week", "month", "season", "halfYear", "year"];
|
|
348
|
+
var SCHEMA_REPORT_TYPE = { type: "string", enum: [...REPORT_TYPE_VALUES] };
|
|
349
|
+
var POST_STATUS_LABELS = {
|
|
350
|
+
"0": "\u8349\u7A3F",
|
|
351
|
+
"1": "\u5DF2\u53D1\u5E03",
|
|
352
|
+
"2": "\u5DF2\u64A4\u56DE",
|
|
353
|
+
"3": "\u5BA1\u6279\u4E2D",
|
|
354
|
+
"4": "\u88AB\u9000\u56DE"
|
|
355
|
+
};
|
|
356
|
+
var POST_TIME_STATUS_LABELS = {
|
|
357
|
+
"1": "\u6B63\u5E38\u63D0\u4EA4",
|
|
358
|
+
"2": "\u8865\u4EA4"
|
|
359
|
+
};
|
|
360
|
+
var REPORT_TYPE_LABELS = {
|
|
361
|
+
week: "\u5468\u62A5",
|
|
362
|
+
month: "\u6708\u62A5",
|
|
363
|
+
season: "\u5B63\u62A5",
|
|
364
|
+
halfYear: "\u5E74\u4E2D\u62A5\u544A",
|
|
365
|
+
year: "\u5E74\u62A5"
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// src/shortcuts/plan/operations/shared.ts
|
|
369
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
370
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
371
|
+
function asObject(value) {
|
|
372
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
373
|
+
throw planValidationError("input_not_object", "\u8F93\u5165\u5FC5\u987B\u662F JSON \u5BF9\u8C61");
|
|
374
|
+
}
|
|
375
|
+
return value;
|
|
376
|
+
}
|
|
377
|
+
function assertNoForbiddenKeys(input) {
|
|
378
|
+
for (const key of Object.keys(input)) {
|
|
379
|
+
if (FORBIDDEN_KEYS.has(key)) {
|
|
380
|
+
throw planValidationError("forbidden_key", `\u8F93\u5165\u5305\u542B\u975E\u6CD5\u5B57\u6BB5\uFF1A${key}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function toIdString(value, field) {
|
|
385
|
+
if (value === void 0 || value === null || value === "") {
|
|
386
|
+
throw planValidationError("id_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57 ID\uFF08\u96EA\u82B1 ID \u8BF7\u7528\u5B57\u7B26\u4E32\u4F20\u9012\uFF09`);
|
|
387
|
+
}
|
|
388
|
+
const text = String(value);
|
|
389
|
+
if (!/^\d+$/.test(text)) {
|
|
390
|
+
throw planValidationError("id_invalid", `${field} \u5FC5\u987B\u662F\u6570\u5B57 ID`);
|
|
391
|
+
}
|
|
392
|
+
return text;
|
|
393
|
+
}
|
|
394
|
+
function toIdListText(value, field) {
|
|
395
|
+
const list = [];
|
|
396
|
+
if (Array.isArray(value)) {
|
|
397
|
+
for (const item of value) {
|
|
398
|
+
if (item === void 0 || item === null || item === "") continue;
|
|
399
|
+
list.push(String(item));
|
|
400
|
+
}
|
|
401
|
+
} else if (typeof value === "string" || typeof value === "number") {
|
|
402
|
+
for (const part of String(value).split(",")) {
|
|
403
|
+
const trimmed = part.trim();
|
|
404
|
+
if (trimmed) list.push(trimmed);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (list.length === 0) {
|
|
408
|
+
throw planValidationError("ids_required", `${field} \u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u4EBA\u5458 ID`);
|
|
409
|
+
}
|
|
410
|
+
for (const id of list) {
|
|
411
|
+
if (!/^\d+$/.test(id)) {
|
|
412
|
+
throw planValidationError("ids_invalid", `${field} \u5FC5\u987B\u662F\u4EBA\u5458 ID\uFF08\u6570\u5B57\u5B57\u7B26\u4E32\uFF09`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return list.join(",");
|
|
416
|
+
}
|
|
417
|
+
function assertReportType(value) {
|
|
418
|
+
const text = typeof value === "string" ? value : String(value);
|
|
419
|
+
if (!REPORT_TYPE_VALUES.includes(text)) {
|
|
420
|
+
throw planValidationError("type_invalid", `type \u53D6\u503C\u5FC5\u987B\u662F ${REPORT_TYPE_VALUES.join(" / ")} \u4E4B\u4E00`);
|
|
421
|
+
}
|
|
422
|
+
return text;
|
|
423
|
+
}
|
|
424
|
+
function resolveYear(value) {
|
|
425
|
+
if (value === void 0 || value === null || value === "") return (/* @__PURE__ */ new Date()).getFullYear();
|
|
426
|
+
const numeric = Number(value);
|
|
427
|
+
if (!Number.isInteger(numeric) || numeric < 1970 || numeric > 9999) {
|
|
428
|
+
throw planValidationError("year_invalid", "year \u5FC5\u987B\u662F\u56DB\u4F4D\u6574\u6570\u5E74\u4EFD");
|
|
429
|
+
}
|
|
430
|
+
return numeric;
|
|
431
|
+
}
|
|
432
|
+
function resolveSerialNumber(value) {
|
|
433
|
+
if (value === void 0 || value === null || value === "") {
|
|
434
|
+
throw planValidationError("serial_number_required", "serialNumber\uFF08\u62A5\u544A\u5468\u671F\uFF09\u5FC5\u586B");
|
|
435
|
+
}
|
|
436
|
+
const numeric = Number(value);
|
|
437
|
+
if (!Number.isInteger(numeric) || numeric <= 0) {
|
|
438
|
+
throw planValidationError("serial_number_invalid", "serialNumber\uFF08\u62A5\u544A\u5468\u671F\uFF09\u5FC5\u987B\u662F\u6B63\u6574\u6570");
|
|
439
|
+
}
|
|
440
|
+
return numeric;
|
|
441
|
+
}
|
|
442
|
+
function requireConfirm(args, action) {
|
|
443
|
+
if (args.confirm !== true) {
|
|
444
|
+
throw planConfirmationError(action, {
|
|
445
|
+
hint: "\u91CD\u65B0\u8C03\u7528\u65F6\u4F20\u5165 confirm=true \u4E0E prepare \u8FD4\u56DE\u7684 continuation"
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
function fingerprint(value) {
|
|
450
|
+
return createHash2("sha256").update(JSON.stringify(value ?? null)).digest("hex").slice(0, 32);
|
|
451
|
+
}
|
|
452
|
+
function compact(mainTable) {
|
|
453
|
+
for (const key of Object.keys(mainTable)) {
|
|
454
|
+
const value = mainTable[key];
|
|
455
|
+
if (value === void 0 || value === null || value === "") delete mainTable[key];
|
|
456
|
+
}
|
|
457
|
+
return mainTable;
|
|
458
|
+
}
|
|
459
|
+
function optionValue(value) {
|
|
460
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
461
|
+
if (Array.isArray(value)) {
|
|
462
|
+
const first = value[0];
|
|
463
|
+
if (first === void 0 || first === null) return void 0;
|
|
464
|
+
if (typeof first === "string" || typeof first === "number") return String(first);
|
|
465
|
+
if (typeof first === "object") {
|
|
466
|
+
const record = first;
|
|
467
|
+
const candidate = record.id ?? record.value ?? record.name;
|
|
468
|
+
if (candidate === void 0 || candidate === null || candidate === "") return void 0;
|
|
469
|
+
return String(candidate);
|
|
470
|
+
}
|
|
471
|
+
return void 0;
|
|
472
|
+
}
|
|
473
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
474
|
+
return void 0;
|
|
475
|
+
}
|
|
476
|
+
function asNumber(value) {
|
|
477
|
+
if (value === void 0 || value === null || value === "") return null;
|
|
478
|
+
const numeric = Number(value);
|
|
479
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
480
|
+
}
|
|
481
|
+
function asText(value) {
|
|
482
|
+
if (value === void 0 || value === null) return null;
|
|
483
|
+
const text = String(value);
|
|
484
|
+
return text === "" ? null : text;
|
|
485
|
+
}
|
|
486
|
+
function typeLabelOf(type) {
|
|
487
|
+
return type ? REPORT_TYPE_LABELS[type] ?? null : null;
|
|
488
|
+
}
|
|
489
|
+
function normalizeStandardReport(workReport, detailUrl) {
|
|
490
|
+
const postStatus = optionValue(workReport?.postStatus) ?? null;
|
|
491
|
+
const type = optionValue(workReport?.type) ?? null;
|
|
492
|
+
const postTimeStatus = optionValue(workReport?.postTimeStatus) ?? null;
|
|
493
|
+
return {
|
|
494
|
+
reportId: asText(workReport?.id),
|
|
495
|
+
title: asText(workReport?.title),
|
|
496
|
+
content: asText(workReport?.content),
|
|
497
|
+
summary: asText(workReport?.summary),
|
|
498
|
+
plans: asText(workReport?.plans),
|
|
499
|
+
year: asNumber(workReport?.year),
|
|
500
|
+
type,
|
|
501
|
+
typeLabel: typeLabelOf(type),
|
|
502
|
+
serialNumber: asNumber(workReport?.serialNumber),
|
|
503
|
+
postStatus,
|
|
504
|
+
postStatusLabel: postStatus ? POST_STATUS_LABELS[postStatus] ?? null : null,
|
|
505
|
+
postTime: asNumber(workReport?.postTime),
|
|
506
|
+
postTimeStatus,
|
|
507
|
+
postTimeStatusLabel: postTimeStatus ? POST_TIME_STATUS_LABELS[postTimeStatus] ?? null : null,
|
|
508
|
+
creator: {
|
|
509
|
+
id: asText(workReport?.creator?.id ?? workReport?.creator?.employeeId),
|
|
510
|
+
name: asText(workReport?.creator?.name ?? workReport?.creator?.employeeId)
|
|
511
|
+
},
|
|
512
|
+
detailUrl
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
function normalizeEbReport(mainTable, detailUrl) {
|
|
516
|
+
const postStatus = optionValue(mainTable?.f_post_status) ?? null;
|
|
517
|
+
const type = optionValue(mainTable?.f_type) ?? null;
|
|
518
|
+
const postTimeStatus = optionValue(mainTable?.f_post_time_status) ?? null;
|
|
519
|
+
return {
|
|
520
|
+
reportId: asText(mainTable?.id),
|
|
521
|
+
title: asText(mainTable?.f_title ?? mainTable?.name),
|
|
522
|
+
content: asText(mainTable?.f_content),
|
|
523
|
+
summary: asText(mainTable?.f_summary),
|
|
524
|
+
plans: asText(mainTable?.f_plans),
|
|
525
|
+
year: asNumber(mainTable?.f_year),
|
|
526
|
+
type,
|
|
527
|
+
typeLabel: typeLabelOf(type),
|
|
528
|
+
serialNumber: asNumber(mainTable?.f_serial_number),
|
|
529
|
+
postStatus,
|
|
530
|
+
postStatusLabel: postStatus ? POST_STATUS_LABELS[postStatus] ?? null : null,
|
|
531
|
+
postTime: asNumber(mainTable?.f_post_time),
|
|
532
|
+
postTimeStatus,
|
|
533
|
+
postTimeStatusLabel: postTimeStatus ? POST_TIME_STATUS_LABELS[postTimeStatus] ?? null : null,
|
|
534
|
+
creator: {
|
|
535
|
+
id: asText(mainTable?.creator),
|
|
536
|
+
name: null
|
|
537
|
+
},
|
|
538
|
+
detailUrl
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
function ebMainTables(value) {
|
|
542
|
+
const datas = value?.datajson?.datas;
|
|
543
|
+
if (!Array.isArray(datas)) return [];
|
|
544
|
+
const list = [];
|
|
545
|
+
for (const item of datas) {
|
|
546
|
+
if (item && typeof item === "object" && item.mainTable && typeof item.mainTable === "object") {
|
|
547
|
+
list.push(item.mainTable);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return list;
|
|
551
|
+
}
|
|
552
|
+
function assertLinkSupported(link, supported, capability, message, details) {
|
|
553
|
+
if (link !== supported) {
|
|
554
|
+
throw planUnsupportedError("link_unsupported", message, { capability, link, expectedLink: supported, ...details || {} });
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
async function ensureConfirmLease(args, action, env) {
|
|
558
|
+
requireConfirm(args, action);
|
|
559
|
+
const lease = await env.continuation.verify(args.continuation, action);
|
|
560
|
+
const session = await env.host.getSession();
|
|
561
|
+
if (lease.baseUrl !== session.baseUrl || lease.profile !== session.profile || lease.userId !== session.userId) {
|
|
562
|
+
throw planValidationError("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");
|
|
563
|
+
}
|
|
564
|
+
return lease;
|
|
565
|
+
}
|
|
566
|
+
function defaultRemindContent(type, year, serialNumber) {
|
|
567
|
+
switch (type) {
|
|
568
|
+
case "week":
|
|
569
|
+
return `\u8BF7\u63D0\u4EA4${year}\u5E74\u7B2C${serialNumber}\u5468\u7684\u62A5\u544A`;
|
|
570
|
+
case "month":
|
|
571
|
+
return `\u8BF7\u63D0\u4EA4${year}\u5E74${serialNumber}\u6708\u7684\u62A5\u544A`;
|
|
572
|
+
case "season":
|
|
573
|
+
return `\u8BF7\u63D0\u4EA4${year}\u5E74\u7B2C${serialNumber}\u5B63\u5EA6\u7684\u62A5\u544A`;
|
|
574
|
+
case "halfYear":
|
|
575
|
+
return `\u8BF7\u63D0\u4EA4${year}\u5E74\u5E74\u4E2D\u62A5\u544A`;
|
|
576
|
+
case "year":
|
|
577
|
+
return `\u8BF7\u63D0\u4EA4${year}\u5E74\u5E74\u5EA6\u62A5\u544A`;
|
|
578
|
+
default:
|
|
579
|
+
return `\u8BF7\u63D0\u4EA4${year}\u5E74\u7684\u62A5\u544A`;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// src/shortcuts/plan/operations/link.ts
|
|
584
|
+
var PLAN_APP_TAG = "weaver-wrplan-eb";
|
|
585
|
+
var PLAN_EB_FORM_TAG = "uf_plan_work_report";
|
|
586
|
+
var VERSION_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
587
|
+
var EB_FORM_ID_FIXED = {
|
|
588
|
+
tt1pa2w2i3: "1029659181695361024"
|
|
589
|
+
};
|
|
590
|
+
function versionCacheKey(tenantKey) {
|
|
591
|
+
return `plan:version:${tenantKey}`;
|
|
592
|
+
}
|
|
593
|
+
function ebFormCacheKey(tenantKey) {
|
|
594
|
+
return `plan:ebform:${tenantKey}`;
|
|
595
|
+
}
|
|
596
|
+
async function resolveLink(host, options = {}) {
|
|
597
|
+
const session = await host.getSession();
|
|
598
|
+
const key = versionCacheKey(session.tenantKey);
|
|
599
|
+
if (!options.refresh) {
|
|
600
|
+
const cached = await host.getCache(key);
|
|
601
|
+
const value = cached && typeof cached === "object" ? cached : null;
|
|
602
|
+
if (value && (value.link === "standard" || value.link === "eb")) {
|
|
603
|
+
return {
|
|
604
|
+
link: value.link,
|
|
605
|
+
verName: value.verName ?? null,
|
|
606
|
+
tenantKey: session.tenantKey,
|
|
607
|
+
cached: true,
|
|
608
|
+
degraded: false,
|
|
609
|
+
reason: null,
|
|
610
|
+
checkedAt: typeof value.checkedAt === "string" ? value.checkedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
let verName = null;
|
|
615
|
+
let degraded = false;
|
|
616
|
+
let reason = null;
|
|
617
|
+
try {
|
|
618
|
+
const response = await host.request({
|
|
619
|
+
method: "POST",
|
|
620
|
+
path: "/api/ebuilder/form/formdata/v2/getFormDataList/plan_searchAppver",
|
|
621
|
+
operation: "plan.version.check",
|
|
622
|
+
body: {
|
|
623
|
+
datajson: {
|
|
624
|
+
mainTable: {},
|
|
625
|
+
pageInfo: { pageNo: "1", pageSize: "10" },
|
|
626
|
+
header: { operator: session.userId }
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
const mainTable = ebMainTables(response)[0];
|
|
631
|
+
verName = optionValue(mainTable?.ver_name) ?? null;
|
|
632
|
+
} catch (error) {
|
|
633
|
+
if (isPlanErrorType(error, "api")) {
|
|
634
|
+
degraded = true;
|
|
635
|
+
reason = error.message;
|
|
636
|
+
} else {
|
|
637
|
+
throw error;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
const link = verName === "V2" ? "eb" : "standard";
|
|
641
|
+
const info = {
|
|
642
|
+
link,
|
|
643
|
+
verName,
|
|
644
|
+
tenantKey: session.tenantKey,
|
|
645
|
+
cached: false,
|
|
646
|
+
degraded,
|
|
647
|
+
reason,
|
|
648
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
649
|
+
};
|
|
650
|
+
if (!degraded) await host.setCache(key, info, VERSION_CACHE_TTL_MS);
|
|
651
|
+
return info;
|
|
652
|
+
}
|
|
653
|
+
function firstId(value) {
|
|
654
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
655
|
+
const first = value[0];
|
|
656
|
+
if (typeof first === "string" || typeof first === "number") return String(first);
|
|
657
|
+
if (first && typeof first === "object") {
|
|
658
|
+
const record = first;
|
|
659
|
+
const candidate = record.id ?? record.idobjId ?? record.objId ?? record.value;
|
|
660
|
+
if (candidate !== void 0 && candidate !== null && candidate !== "") return String(candidate);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
664
|
+
return void 0;
|
|
665
|
+
}
|
|
666
|
+
async function resolveEbFormId(host) {
|
|
667
|
+
const session = await host.getSession();
|
|
668
|
+
const fixed = EB_FORM_ID_FIXED[session.tenantKey];
|
|
669
|
+
const templateOf = (idobjId2) => `/sp/ebdfpage/card/0/${idobjId2}/{reportId}`;
|
|
670
|
+
if (fixed) {
|
|
671
|
+
return {
|
|
672
|
+
appTag: PLAN_APP_TAG,
|
|
673
|
+
appId: null,
|
|
674
|
+
formTag: PLAN_EB_FORM_TAG,
|
|
675
|
+
idobjId: fixed,
|
|
676
|
+
source: "fixed",
|
|
677
|
+
detailUrlTemplate: templateOf(fixed)
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
const key = ebFormCacheKey(session.tenantKey);
|
|
681
|
+
const cached = await host.getCache(key);
|
|
682
|
+
const cachedValue = cached && typeof cached === "object" ? cached : null;
|
|
683
|
+
if (cachedValue && typeof cachedValue.idobjId === "string" && cachedValue.idobjId) {
|
|
684
|
+
return {
|
|
685
|
+
appTag: PLAN_APP_TAG,
|
|
686
|
+
appId: typeof cachedValue.appId === "string" ? cachedValue.appId : null,
|
|
687
|
+
formTag: PLAN_EB_FORM_TAG,
|
|
688
|
+
idobjId: cachedValue.idobjId,
|
|
689
|
+
source: "cache",
|
|
690
|
+
detailUrlTemplate: templateOf(cachedValue.idobjId)
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
const appIdsResponse = await host.request({
|
|
694
|
+
method: "GET",
|
|
695
|
+
path: "/api/bs/ebuilder/app/tags/getAppIds",
|
|
696
|
+
query: { tag: PLAN_APP_TAG },
|
|
697
|
+
operation: "plan.eb.form.resolve"
|
|
698
|
+
}).catch(() => void 0);
|
|
699
|
+
const appId = firstId(appIdsResponse?.data);
|
|
700
|
+
if (!appId) {
|
|
701
|
+
throw planApiError(
|
|
702
|
+
"eb_app_not_found",
|
|
703
|
+
"\u672A\u68C0\u6D4B\u5230\u300C\u8BA1\u5212\u62A5\u544A\u300Debuilder \u5E94\u7528\uFF08appTag: weaver-wrplan-eb\uFF09\uFF0C\u65E0\u6CD5\u751F\u6210\u62A5\u544A\u8BE6\u60C5\u9875\u94FE\u63A5"
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
const formResponse = await host.request({
|
|
707
|
+
method: "GET",
|
|
708
|
+
path: "/api/ebuilder/form/obj/getObjsByTag",
|
|
709
|
+
query: { tag: PLAN_EB_FORM_TAG, appId },
|
|
710
|
+
operation: "plan.eb.form.resolve"
|
|
711
|
+
}).catch(() => void 0);
|
|
712
|
+
const idobjId = firstId(formResponse?.data);
|
|
713
|
+
if (!idobjId) {
|
|
714
|
+
throw planApiError(
|
|
715
|
+
"eb_form_not_found",
|
|
716
|
+
"\u672A\u627E\u5230\u62A5\u544A\u8BE6\u60C5 ebuilder \u8868\u5355\uFF08tag: uf_plan_work_report\uFF09\uFF0C\u65E0\u6CD5\u751F\u6210\u62A5\u544A\u8BE6\u60C5\u9875\u94FE\u63A5"
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
const info = {
|
|
720
|
+
appTag: PLAN_APP_TAG,
|
|
721
|
+
appId,
|
|
722
|
+
formTag: PLAN_EB_FORM_TAG,
|
|
723
|
+
idobjId,
|
|
724
|
+
source: "dynamic",
|
|
725
|
+
detailUrlTemplate: templateOf(idobjId)
|
|
726
|
+
};
|
|
727
|
+
await host.setCache(key, { appId, idobjId });
|
|
728
|
+
return info;
|
|
729
|
+
}
|
|
730
|
+
async function buildDetailUrl(host, link, reportId) {
|
|
731
|
+
if (!reportId) return null;
|
|
732
|
+
if (link === "standard") return `/sp/plan/detail/${reportId}`;
|
|
733
|
+
const form = await resolveEbFormId(host);
|
|
734
|
+
return `/sp/ebdfpage/card/0/${form.idobjId}/${reportId}`;
|
|
735
|
+
}
|
|
736
|
+
function hasOwn(value, key) {
|
|
737
|
+
return Boolean(value && typeof value === "object" && Object.prototype.hasOwnProperty.call(value, key));
|
|
738
|
+
}
|
|
739
|
+
async function lookupReport(host, link, query) {
|
|
740
|
+
const session = await host.getSession();
|
|
741
|
+
const warnings = [];
|
|
742
|
+
if (query.id) {
|
|
743
|
+
if (link === "standard") {
|
|
744
|
+
const response2 = await host.request({
|
|
745
|
+
method: "POST",
|
|
746
|
+
path: "/api/workrelate/plan/workreport/view",
|
|
747
|
+
query: { id: query.id },
|
|
748
|
+
operation: "plan.report.get"
|
|
749
|
+
});
|
|
750
|
+
const hasReport = Boolean(hasOwn(response2, "workReport") && response2.workReport);
|
|
751
|
+
const report2 = hasReport ? normalizeStandardReport(response2.workReport, await buildDetailUrl(host, "standard", query.id)) : null;
|
|
752
|
+
return { link, exists: hasReport, report: report2, precheck: "checked", warnings };
|
|
753
|
+
}
|
|
754
|
+
if (query.year === void 0 || !query.type || query.serialNumber === void 0) {
|
|
755
|
+
warnings.push("eb \u94FE\u8DEF\u6CA1\u6709\u6309\u62A5\u544A id \u67E5\u8BE2\u8BE6\u60C5\u7684\u63A5\u53E3\uFF0C\u7F3A\u5C11 year/type/serialNumber \u65F6\u65E0\u6CD5\u505A\u5199\u5165\u524D\u6821\u9A8C");
|
|
756
|
+
return { link, exists: null, report: null, precheck: "skipped", warnings };
|
|
757
|
+
}
|
|
758
|
+
const byPeriod = await lookupReport(host, "eb", {
|
|
759
|
+
year: query.year,
|
|
760
|
+
type: query.type,
|
|
761
|
+
serialNumber: query.serialNumber,
|
|
762
|
+
creatorUserId: query.creatorUserId
|
|
763
|
+
});
|
|
764
|
+
if (byPeriod.report && byPeriod.report.reportId && byPeriod.report.reportId !== query.id) {
|
|
765
|
+
warnings.push(`\u6309\u5468\u671F\u67E5\u8BE2\u5230\u7684\u62A5\u544A id\uFF08${byPeriod.report.reportId}\uFF09\u4E0E\u4F20\u5165\u7684 id\uFF08${query.id}\uFF09\u4E0D\u4E00\u81F4`);
|
|
766
|
+
return { link, exists: false, report: null, precheck: "checked", warnings };
|
|
767
|
+
}
|
|
768
|
+
return { ...byPeriod, warnings: [...warnings, ...byPeriod.warnings] };
|
|
769
|
+
}
|
|
770
|
+
if (query.year === void 0 || !query.type || query.serialNumber === void 0) {
|
|
771
|
+
throw planApiError("lookup_incomplete", "\u6309\u5468\u671F\u67E5\u8BE2\u62A5\u544A\u8BE6\u60C5\u5FC5\u987B\u540C\u65F6\u63D0\u4F9B year\u3001type\u3001serialNumber");
|
|
772
|
+
}
|
|
773
|
+
const creator = query.creatorUserId || session.userId;
|
|
774
|
+
if (link === "standard") {
|
|
775
|
+
const response2 = await host.request({
|
|
776
|
+
method: "POST",
|
|
777
|
+
path: "/api/workrelate/plan/workreport/view",
|
|
778
|
+
query: {
|
|
779
|
+
year: query.year,
|
|
780
|
+
serialNumber: query.serialNumber,
|
|
781
|
+
type: query.type,
|
|
782
|
+
creatorUserId: creator
|
|
783
|
+
},
|
|
784
|
+
operation: "plan.report.get"
|
|
785
|
+
});
|
|
786
|
+
const hasReport = Boolean(hasOwn(response2, "workReport") && response2.workReport);
|
|
787
|
+
const report2 = hasReport ? normalizeStandardReport(
|
|
788
|
+
response2.workReport,
|
|
789
|
+
await buildDetailUrl(host, "standard", String(response2.workReport.id ?? ""))
|
|
790
|
+
) : null;
|
|
791
|
+
return { link, exists: hasReport, report: report2, precheck: "checked", warnings };
|
|
792
|
+
}
|
|
793
|
+
const response = await host.request({
|
|
794
|
+
method: "POST",
|
|
795
|
+
path: "/api/ebuilder/form/formdata/v2/getFormDataByPk/plan_queryPlan",
|
|
796
|
+
operation: "plan.report.get",
|
|
797
|
+
body: {
|
|
798
|
+
datajson: {
|
|
799
|
+
mainTable: compact({
|
|
800
|
+
creator,
|
|
801
|
+
f_year: query.year,
|
|
802
|
+
f_type: query.type,
|
|
803
|
+
f_serial_number: query.serialNumber
|
|
804
|
+
}),
|
|
805
|
+
header: { operator: session.userId }
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
if (!isDatajsonSuccess(response)) {
|
|
810
|
+
throw planApiError("business_error", businessMessage(response), { response: businessMessage(response) });
|
|
811
|
+
}
|
|
812
|
+
const mainTable = ebMainTables(response)[0];
|
|
813
|
+
const exists = Boolean(mainTable && mainTable.id);
|
|
814
|
+
const report = exists ? normalizeEbReport(mainTable, await buildDetailUrl(host, "eb", String(mainTable.id))) : null;
|
|
815
|
+
return { link, exists, report, precheck: "checked", warnings };
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// src/shortcuts/plan/operations/read.ts
|
|
819
|
+
var COMMENT_MODULE = "workreport";
|
|
820
|
+
async function commentTotalCount(host, reportId) {
|
|
821
|
+
const response = await host.request({
|
|
822
|
+
method: "POST",
|
|
823
|
+
path: "/api/plan/common/comment/commentPage",
|
|
824
|
+
operation: "plan.report.get",
|
|
825
|
+
body: {
|
|
826
|
+
pageNo: 1,
|
|
827
|
+
pageSize: 1,
|
|
828
|
+
targetId: reportId,
|
|
829
|
+
module: COMMENT_MODULE,
|
|
830
|
+
foldCommentList: false
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
const total = response?.data?.page?.totalCount;
|
|
834
|
+
const numeric = Number(total);
|
|
835
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
836
|
+
}
|
|
837
|
+
var planReportGet = {
|
|
838
|
+
name: "plan.report.get",
|
|
839
|
+
resource: "plan",
|
|
840
|
+
method: "report.get",
|
|
841
|
+
action: "plan.report.get",
|
|
842
|
+
summary: "\u6309\u62A5\u544A id \u6216\u6309\u5468\u671F\uFF08\u5E74\u4EFD+\u7C7B\u578B+\u5468\u671F+\u521B\u5EFA\u4EBA\uFF09\u67E5\u8BE2\u5355\u4E2A\u62A5\u544A\u8BE6\u60C5\uFF0C\u5E76\u6309\u89C4\u5219\u9644\u5E26\u8BC4\u8BBA\u603B\u6761\u6570",
|
|
843
|
+
capability: "plan",
|
|
844
|
+
risk: "read",
|
|
845
|
+
inputSchema: schemaOf(
|
|
846
|
+
{
|
|
847
|
+
id: { ...SCHEMA_ID, description: "\u62A5\u544A id\uFF1B\u4E0E\u5468\u671F\u53C2\u6570\u4E8C\u9009\u4E00\uFF0C\u7ED9 id \u65F6\u5FFD\u7565\u5468\u671F\u53C2\u6570" },
|
|
848
|
+
year: { type: "integer", description: "\u62A5\u544A\u5E74\u4EFD\uFF1B\u7F3A\u7701\u53D6\u672C\u5E74" },
|
|
849
|
+
type: { ...SCHEMA_REPORT_TYPE, description: "\u62A5\u544A\u7C7B\u578B" },
|
|
850
|
+
serialNumber: { type: "integer", minimum: 1, description: "\u62A5\u544A\u5468\u671F" },
|
|
851
|
+
creatorUserId: { ...SCHEMA_ID, description: "\u62A5\u544A\u521B\u5EFA\u4EBA id\uFF1B\u7F3A\u7701\u4E3A\u5F53\u524D\u767B\u5F55\u4EBA" },
|
|
852
|
+
withComments: { type: "boolean", default: true, description: "\u6807\u51C6\u7248\u94FE\u8DEF\u4E0B\u662F\u5426\u540C\u65F6\u67E5\u8BE2\u8BC4\u8BBA\u603B\u6761\u6570" }
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
oneOf: [{ required: ["id"] }, { required: ["type", "serialNumber"] }]
|
|
856
|
+
}
|
|
857
|
+
),
|
|
858
|
+
handler: async (args, { host }) => {
|
|
859
|
+
const warnings = [];
|
|
860
|
+
const query = args.id !== void 0 && args.id !== "" ? { id: toIdString(args.id, "id") } : {
|
|
861
|
+
year: resolveYear(args.year),
|
|
862
|
+
type: assertReportType(args.type),
|
|
863
|
+
serialNumber: resolveSerialNumber(args.serialNumber),
|
|
864
|
+
...args.creatorUserId !== void 0 && args.creatorUserId !== "" ? { creatorUserId: toIdString(args.creatorUserId, "creatorUserId") } : {}
|
|
865
|
+
};
|
|
866
|
+
const linkInfo = await resolveLink(host);
|
|
867
|
+
const result = await lookupReport(host, linkInfo.link, query);
|
|
868
|
+
warnings.push(...result.warnings);
|
|
869
|
+
const data = {
|
|
870
|
+
link: result.link,
|
|
871
|
+
exists: result.exists,
|
|
872
|
+
report: result.report,
|
|
873
|
+
detailUrl: result.report?.detailUrl ?? null,
|
|
874
|
+
warnings
|
|
875
|
+
};
|
|
876
|
+
if (result.link === "eb") {
|
|
877
|
+
data.commentsSupported = false;
|
|
878
|
+
warnings.push("eb \u94FE\u8DEF\u672A\u63D0\u4F9B\u62A5\u544A\u8BC4\u8BBA\u63A5\u53E3\uFF0C\u8BC4\u8BBA\u603B\u6761\u6570\u4E0D\u53EF\u7528");
|
|
879
|
+
} else if (result.exists && result.report?.reportId && args.withComments !== false) {
|
|
880
|
+
try {
|
|
881
|
+
const total = await commentTotalCount(host, result.report.reportId);
|
|
882
|
+
if (total !== null && total > 0) {
|
|
883
|
+
data.commentCount = total;
|
|
884
|
+
data.commentHint = `\u8BE5\u62A5\u544A\u4E0B\u5171\u6709${total}\u6761\u8BC4\u8BBA\uFF0C\u662F\u5426\u9700\u8981\u67E5\u770B\u8BC4\u8BBA\u5185\u5BB9\uFF1F`;
|
|
885
|
+
}
|
|
886
|
+
} catch {
|
|
887
|
+
warnings.push("\u8BC4\u8BBA\u603B\u6761\u6570\u67E5\u8BE2\u5931\u8D25\uFF0C\u62A5\u544A\u8BE6\u60C5\u5DF2\u8FD4\u56DE");
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return planSuccess("plan.report.get", data);
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
function pageArgs(args) {
|
|
894
|
+
const pageNo = args.pageNo === void 0 || args.pageNo === "" ? 1 : Number(args.pageNo);
|
|
895
|
+
const pageSize = args.pageSize === void 0 || args.pageSize === "" ? 10 : Number(args.pageSize);
|
|
896
|
+
if (!Number.isInteger(pageNo) || pageNo < 1) {
|
|
897
|
+
throw planValidationError("page_invalid", "pageNo \u5FC5\u987B\u662F\u4E0D\u5C0F\u4E8E 1 \u7684\u6574\u6570");
|
|
898
|
+
}
|
|
899
|
+
if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > 100) {
|
|
900
|
+
throw planValidationError("page_invalid", "pageSize \u5FC5\u987B\u662F 1~100 \u7684\u6574\u6570");
|
|
901
|
+
}
|
|
902
|
+
return { pageNo, pageSize };
|
|
903
|
+
}
|
|
904
|
+
var planReportPage = {
|
|
905
|
+
name: "plan.report.page",
|
|
906
|
+
resource: "plan",
|
|
907
|
+
method: "report.page",
|
|
908
|
+
action: "plan.report.page",
|
|
909
|
+
summary: "\u5206\u9875\u67E5\u8BE2\u62A5\u544A\u5217\u8868\uFF08\u5171\u4EAB\u7ED9\u6211\u7684\u62A5\u544A / \u6211\u81EA\u5DF1\u4E0E\u4ED6\u4EBA\u5171\u4EAB\u7684\u62A5\u544A\uFF09\uFF0C\u8FD4\u56DE\u53EF\u76F4\u63A5\u8DF3\u8F6C\u8BE6\u60C5\u7684\u884C\u6570\u636E",
|
|
910
|
+
capability: "plan",
|
|
911
|
+
risk: "read",
|
|
912
|
+
inputSchema: schemaOf({
|
|
913
|
+
scope: { type: "string", enum: ["share", "mine"], default: "share", description: "share-\u5171\u4EAB\u7ED9\u6211\u7684\uFF1Bmine-\u6211\u81EA\u5DF1\u53CA\u4ED6\u4EBA\u5171\u4EAB\u7ED9\u6211\u7684\uFF08eb \u94FE\u8DEF\u6309\u521B\u5EFA\u4EBA\u7B5B\u9009\uFF09" },
|
|
914
|
+
unreadOnly: { type: "boolean", default: false, description: "\u4EC5\u770B\u672A\u8BFB\uFF08\u6807\u51C6\u7248\u4E13\u5C5E\uFF09" },
|
|
915
|
+
year: { type: "integer", description: "\u62A5\u544A\u5E74\u4EFD\u7B5B\u9009" },
|
|
916
|
+
type: { ...SCHEMA_REPORT_TYPE, description: "\u62A5\u544A\u7C7B\u578B\u7B5B\u9009" },
|
|
917
|
+
serialNumber: { type: "integer", minimum: 1, description: "\u62A5\u544A\u5468\u671F\u7B5B\u9009" },
|
|
918
|
+
creatorUserId: { ...SCHEMA_ID, description: "\u62A5\u544A\u521B\u5EFA\u4EBA id \u7B5B\u9009\uFF08eb \u94FE\u8DEF\u652F\u6301\uFF09" },
|
|
919
|
+
onlyIncludeSubs: { type: "boolean", description: "\u662F\u5426\u53EA\u5305\u542B\u4E0B\u5C5E\uFF08\u6807\u51C6\u7248\u4E13\u5C5E\uFF09" },
|
|
920
|
+
pageNo: { type: "integer", minimum: 1, default: 1, description: "\u9875\u7801" },
|
|
921
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100, default: 10, description: "\u6BCF\u9875\u6761\u6570" }
|
|
922
|
+
}),
|
|
923
|
+
handler: async (args, { host }) => {
|
|
924
|
+
const { pageNo, pageSize } = pageArgs(args);
|
|
925
|
+
const warnings = [];
|
|
926
|
+
const linkInfo = await resolveLink(host);
|
|
927
|
+
const session = await host.getSession();
|
|
928
|
+
const rows = [];
|
|
929
|
+
if (linkInfo.link === "standard") {
|
|
930
|
+
if (args.scope === "mine") {
|
|
931
|
+
warnings.push("\u6807\u51C6\u7248\u5206\u9875\u63A5\u53E3\u53EA\u8FD4\u56DE\u300C\u5171\u4EAB\u7ED9\u6211\u7684\u62A5\u544A\u300D\uFF0Cscope=mine \u4E0D\u80FD\u4F5C\u4E3A\u521B\u5EFA\u4EBA\u8FC7\u6EE4\u6761\u4EF6");
|
|
932
|
+
}
|
|
933
|
+
if (args.creatorUserId !== void 0 && args.creatorUserId !== "") {
|
|
934
|
+
warnings.push("\u6807\u51C6\u7248\u5206\u9875\u63A5\u53E3\u4E0D\u652F\u6301\u6309\u521B\u5EFA\u4EBA\u7B5B\u9009\uFF0CcreatorUserId \u5DF2\u5FFD\u7565");
|
|
935
|
+
}
|
|
936
|
+
const query = {
|
|
937
|
+
type: args.unreadOnly === true ? "unreadPage" : "sharePage",
|
|
938
|
+
pageNo,
|
|
939
|
+
pageSize
|
|
940
|
+
};
|
|
941
|
+
if (args.type !== void 0) query.workReportType = assertReportType(args.type);
|
|
942
|
+
if (args.onlyIncludeSubs !== void 0) query.onlyIncludeSubs = args.onlyIncludeSubs === true;
|
|
943
|
+
const response2 = await host.request({
|
|
944
|
+
method: "GET",
|
|
945
|
+
path: "/api/workrelate/plan/workreport/indexGet",
|
|
946
|
+
query,
|
|
947
|
+
operation: "plan.report.page"
|
|
948
|
+
});
|
|
949
|
+
const result = response2?.page?.result;
|
|
950
|
+
if (Array.isArray(result)) {
|
|
951
|
+
for (const row of result) {
|
|
952
|
+
const reportId = row?.id === void 0 || row?.id === null || row?.id === "" ? null : String(row.id);
|
|
953
|
+
rows.push(normalizeStandardReport(row, await buildDetailUrl(host, "standard", reportId)));
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return planSuccess("plan.report.page", {
|
|
957
|
+
link: "standard",
|
|
958
|
+
pageNo,
|
|
959
|
+
pageSize,
|
|
960
|
+
count: rows.length,
|
|
961
|
+
rows,
|
|
962
|
+
warnings
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
if (args.unreadOnly === true) warnings.push("eb \u94FE\u8DEF\u5206\u9875\u63A5\u53E3\u4E0D\u652F\u6301\u300C\u4EC5\u770B\u672A\u8BFB\u300D\uFF0CunreadOnly \u5DF2\u5FFD\u7565");
|
|
966
|
+
if (args.onlyIncludeSubs !== void 0) warnings.push("eb \u94FE\u8DEF\u5206\u9875\u63A5\u53E3\u4E0D\u652F\u6301 onlyIncludeSubs\uFF0C\u5DF2\u5FFD\u7565");
|
|
967
|
+
const creator = args.creatorUserId !== void 0 && args.creatorUserId !== "" ? toIdString(args.creatorUserId, "creatorUserId") : session.userId;
|
|
968
|
+
const mainTable = { creator };
|
|
969
|
+
if (args.year !== void 0) mainTable.f_year = resolveYear(args.year);
|
|
970
|
+
if (args.type !== void 0) mainTable.f_type = assertReportType(args.type);
|
|
971
|
+
if (args.serialNumber !== void 0) mainTable.f_serial_number = resolveSerialNumber(args.serialNumber);
|
|
972
|
+
const response = await host.request({
|
|
973
|
+
method: "POST",
|
|
974
|
+
path: "/api/ebuilder/form/formdata/v2/getFormDataList/plan_pageQueryPlan",
|
|
975
|
+
operation: "plan.report.page",
|
|
976
|
+
body: {
|
|
977
|
+
datajson: {
|
|
978
|
+
mainTable,
|
|
979
|
+
pageInfo: { pageNo: String(pageNo), pageSize: String(pageSize) },
|
|
980
|
+
header: { operator: session.userId }
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
for (const item of ebMainTables(response)) {
|
|
985
|
+
const reportId = item?.id === void 0 || item?.id === null || item?.id === "" ? null : String(item.id);
|
|
986
|
+
rows.push(normalizeEbReport(item, await buildDetailUrl(host, "eb", reportId)));
|
|
987
|
+
}
|
|
988
|
+
return planSuccess("plan.report.page", {
|
|
989
|
+
link: "eb",
|
|
990
|
+
pageNo,
|
|
991
|
+
pageSize,
|
|
992
|
+
count: rows.length,
|
|
993
|
+
rows,
|
|
994
|
+
warnings
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
var planCommentList = {
|
|
999
|
+
name: "plan.comment.list",
|
|
1000
|
+
resource: "plan",
|
|
1001
|
+
method: "comment.list",
|
|
1002
|
+
action: "plan.comment.list",
|
|
1003
|
+
summary: "\u5206\u9875\u67E5\u8BE2\u67D0\u4EFD\u62A5\u544A\u7684\u8BC4\u8BBA\u5185\u5BB9\uFF08\u6807\u51C6\u7248\u94FE\u8DEF\uFF09\uFF1B\u4EC5\u5728\u7528\u6237\u660E\u786E\u8981\u6C42\u67E5\u770B\u8BC4\u8BBA\u5185\u5BB9\u65F6\u8C03\u7528",
|
|
1004
|
+
capability: "plan",
|
|
1005
|
+
risk: "read",
|
|
1006
|
+
inputSchema: schemaOf({
|
|
1007
|
+
reportId: { ...SCHEMA_ID, description: "\u62A5\u544A id" },
|
|
1008
|
+
pageNo: { type: "integer", minimum: 1, default: 1, description: "\u9875\u7801" },
|
|
1009
|
+
pageSize: { type: "integer", minimum: 1, maximum: 100, default: 10, description: "\u6BCF\u9875\u6761\u6570" }
|
|
1010
|
+
}, { required: ["reportId"] }),
|
|
1011
|
+
handler: async (args, { host }) => {
|
|
1012
|
+
const { pageNo, pageSize } = pageArgs(args);
|
|
1013
|
+
const reportId = toIdString(args.reportId, "reportId");
|
|
1014
|
+
const linkInfo = await resolveLink(host);
|
|
1015
|
+
assertLinkSupported(
|
|
1016
|
+
linkInfo.link,
|
|
1017
|
+
"standard",
|
|
1018
|
+
"plan.comment.list",
|
|
1019
|
+
"eb \u94FE\u8DEF\u672A\u63D0\u4F9B\u62A5\u544A\u8BC4\u8BBA\u63A5\u53E3\uFF0C\u65E0\u6CD5\u67E5\u8BE2\u8BC4\u8BBA\u5185\u5BB9\uFF1B\u5F53\u524D\u79DF\u6237\u8D70 e10-ebuilder \u94FE\u8DEF"
|
|
1020
|
+
);
|
|
1021
|
+
const response = await host.request({
|
|
1022
|
+
method: "POST",
|
|
1023
|
+
path: "/api/plan/common/comment/commentPage",
|
|
1024
|
+
operation: "plan.comment.list",
|
|
1025
|
+
body: {
|
|
1026
|
+
pageNo,
|
|
1027
|
+
pageSize,
|
|
1028
|
+
targetId: reportId,
|
|
1029
|
+
module: COMMENT_MODULE,
|
|
1030
|
+
foldCommentList: false
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
const page = response?.data?.page ?? {};
|
|
1034
|
+
const result = Array.isArray(page.result) ? page.result : [];
|
|
1035
|
+
const totalCount = Number(page.totalCount);
|
|
1036
|
+
return planSuccess("plan.comment.list", {
|
|
1037
|
+
link: "standard",
|
|
1038
|
+
reportId,
|
|
1039
|
+
pageNo,
|
|
1040
|
+
pageSize,
|
|
1041
|
+
totalCount: Number.isFinite(totalCount) ? totalCount : result.length,
|
|
1042
|
+
comments: result.map((item) => ({
|
|
1043
|
+
commentId: item?.id ?? null,
|
|
1044
|
+
commentorId: item?.commentor?.id ?? null,
|
|
1045
|
+
commentorName: item?.commentor?.username ?? item?.commentor?.name ?? null,
|
|
1046
|
+
content: item?.content ?? item?.originContent ?? null,
|
|
1047
|
+
addTime: item?.addTime ?? null,
|
|
1048
|
+
parentCommentId: item?.parent?.id ?? null
|
|
1049
|
+
}))
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
var planReadOperations = [
|
|
1054
|
+
planReportGet,
|
|
1055
|
+
planReportPage,
|
|
1056
|
+
planCommentList
|
|
1057
|
+
];
|
|
1058
|
+
|
|
1059
|
+
// src/shortcuts/plan/operations/version.ts
|
|
1060
|
+
var planVersionCheck = {
|
|
1061
|
+
name: "plan.version.check",
|
|
1062
|
+
resource: "plan",
|
|
1063
|
+
method: "version.check",
|
|
1064
|
+
action: "plan.version.check",
|
|
1065
|
+
summary: "\u5224\u5B9A\u5F53\u524D\u79DF\u6237\u7684\u8BA1\u5212\u62A5\u544A\u63A5\u53E3\u94FE\u8DEF\uFF08standard / eb\uFF09\uFF0C\u547D\u4E2D 1 \u5929\u79DF\u6237\u7F13\u5B58\u65F6\u8DF3\u8FC7\u63A5\u53E3\u8C03\u7528",
|
|
1066
|
+
capability: "plan",
|
|
1067
|
+
risk: "read",
|
|
1068
|
+
inputSchema: schemaOf({
|
|
1069
|
+
refresh: { type: "boolean", default: false, description: "true \u65F6\u5FFD\u7565\u7F13\u5B58\u91CD\u65B0\u8C03\u7528\u7248\u672C\u63A5\u53E3" }
|
|
1070
|
+
}),
|
|
1071
|
+
handler: async (args, { host }) => {
|
|
1072
|
+
const info = await resolveLink(host, { refresh: args.refresh === true });
|
|
1073
|
+
return planSuccess("plan.version.check", {
|
|
1074
|
+
...info,
|
|
1075
|
+
versionInterface: "plan_searchAppver"
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
var planEbFormResolve = {
|
|
1080
|
+
name: "plan.eb.form.resolve",
|
|
1081
|
+
resource: "plan",
|
|
1082
|
+
method: "eb.form.resolve",
|
|
1083
|
+
action: "plan.eb.form.resolve",
|
|
1084
|
+
summary: "\u89E3\u6790 ebuilder \u62A5\u544A\u8BE6\u60C5\u8868\u5355 id\uFF08idobjId\uFF09\uFF0C\u7528\u4E8E\u751F\u6210\u62A5\u544A\u8BE6\u60C5\u9875\u94FE\u63A5\uFF1B\u89E3\u6790\u7ED3\u679C\u6309\u79DF\u6237\u957F\u671F\u7F13\u5B58",
|
|
1085
|
+
capability: "plan",
|
|
1086
|
+
risk: "read",
|
|
1087
|
+
inputSchema: schemaOf({}),
|
|
1088
|
+
handler: async (_args, { host }) => {
|
|
1089
|
+
const info = await resolveEbFormId(host);
|
|
1090
|
+
return planSuccess("plan.eb.form.resolve", {
|
|
1091
|
+
...info,
|
|
1092
|
+
appTag: info.appTag,
|
|
1093
|
+
formTag: PLAN_EB_FORM_TAG
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
var planVersionOperations = [
|
|
1098
|
+
planVersionCheck,
|
|
1099
|
+
planEbFormResolve
|
|
1100
|
+
];
|
|
1101
|
+
|
|
1102
|
+
// src/shortcuts/plan/operations/write.ts
|
|
1103
|
+
var CONTINUATION_TTL_SECONDS = 600;
|
|
1104
|
+
var REMIND_MESSAGE_EVENT_CODE = 14;
|
|
1105
|
+
var BODY_KEYS = ["content", "summary", "plans"];
|
|
1106
|
+
function textField(value, field) {
|
|
1107
|
+
if (value === void 0 || value === null) return void 0;
|
|
1108
|
+
if (typeof value !== "string") {
|
|
1109
|
+
throw planValidationError("field_invalid", `${field} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\uFF08\u652F\u6301 HTML \u7247\u6BB5\uFF09`);
|
|
1110
|
+
}
|
|
1111
|
+
return value;
|
|
1112
|
+
}
|
|
1113
|
+
function bodyFields(args) {
|
|
1114
|
+
const content = textField(args.content, "content");
|
|
1115
|
+
const summary = textField(args.summary, "summary");
|
|
1116
|
+
const plans = textField(args.plans, "plans");
|
|
1117
|
+
if (content === void 0 && summary === void 0 && plans === void 0) {
|
|
1118
|
+
throw planValidationError("body_required", "content\uFF08\u5DE5\u4F5C\u6210\u6548\uFF09\u3001summary\uFF08\u603B\u7ED3\u5FC3\u5F97\uFF09\u3001plans\uFF08\u8BA1\u5212\u5185\u5BB9\uFF09\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A");
|
|
1119
|
+
}
|
|
1120
|
+
return { content, summary, plans };
|
|
1121
|
+
}
|
|
1122
|
+
function buildEbTitle(userName, type, year, serialNumber) {
|
|
1123
|
+
switch (type) {
|
|
1124
|
+
case "week":
|
|
1125
|
+
return `${userName}${year}\u5E74\u7B2C${serialNumber}\u5468\u7684\u62A5\u544A`;
|
|
1126
|
+
case "month":
|
|
1127
|
+
return `${userName}${year}\u5E74${serialNumber}\u6708\u7684\u62A5\u544A`;
|
|
1128
|
+
case "season":
|
|
1129
|
+
return `${userName}${year}\u5E74\u7B2C${serialNumber}\u5B63\u5EA6\u7684\u62A5\u544A`;
|
|
1130
|
+
case "halfYear":
|
|
1131
|
+
return `${userName}${year}\u5E74\u5E74\u4E2D\u62A5\u544A`;
|
|
1132
|
+
case "year":
|
|
1133
|
+
return `${userName}${year}\u5E74\u5E74\u5EA6\u62A5\u544A`;
|
|
1134
|
+
default:
|
|
1135
|
+
return `${userName}${year}\u5E74\u7684\u62A5\u544A`;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
function payloadFromLease(args, lease, businessKeys) {
|
|
1139
|
+
const payload = { ...lease.payload || {} };
|
|
1140
|
+
for (const key of businessKeys) {
|
|
1141
|
+
if (args[key] !== void 0 && String(args[key]) !== String(payload[key])) {
|
|
1142
|
+
throw planValidationError("target_changed", `${key} \u4E0E prepare \u65F6\u7684\u5FEB\u7167\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare`);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
return payload;
|
|
1146
|
+
}
|
|
1147
|
+
async function assertSameLink(host, expected) {
|
|
1148
|
+
const current = await resolveLink(host);
|
|
1149
|
+
if (current.link !== expected) {
|
|
1150
|
+
throw planValidationError("link_changed", `\u63A5\u53E3\u94FE\u8DEF\u5DF2\u4ECE ${expected} \u53D8\u4E3A ${current.link}\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C prepare`);
|
|
1151
|
+
}
|
|
1152
|
+
return current.link;
|
|
1153
|
+
}
|
|
1154
|
+
function isNetworkError(error) {
|
|
1155
|
+
return isPlanErrorType(error, "network");
|
|
1156
|
+
}
|
|
1157
|
+
async function issueConfirmation(env, operation, link, payload) {
|
|
1158
|
+
const session = await env.host.getSession();
|
|
1159
|
+
return env.continuation.issue(
|
|
1160
|
+
{
|
|
1161
|
+
operation,
|
|
1162
|
+
baseUrl: session.baseUrl,
|
|
1163
|
+
profile: session.profile,
|
|
1164
|
+
userId: session.userId,
|
|
1165
|
+
link,
|
|
1166
|
+
payload,
|
|
1167
|
+
fingerprint: fingerprint(payload)
|
|
1168
|
+
},
|
|
1169
|
+
CONTINUATION_TTL_SECONDS * 1e3
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
async function sendWrite(env, operation, request, uncertainty) {
|
|
1173
|
+
try {
|
|
1174
|
+
return await env.host.request({ ...request, operation });
|
|
1175
|
+
} catch (error) {
|
|
1176
|
+
if (isNetworkError(error)) {
|
|
1177
|
+
throw planPartialError(uncertainty.message, uncertainty.partialData, { stage: uncertainty.stage });
|
|
1178
|
+
}
|
|
1179
|
+
throw error;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
var CREATE_KEYS = ["content", "summary", "plans", "year", "type", "serialNumber", "title"];
|
|
1183
|
+
var planReportCreatePrepare = {
|
|
1184
|
+
name: "plan.report.create.prepare",
|
|
1185
|
+
resource: "plan",
|
|
1186
|
+
method: "report.create.prepare",
|
|
1187
|
+
action: "plan.report.create.prepare",
|
|
1188
|
+
summary: "\u51C6\u5907\u65B0\u5EFA\u62A5\u544A\uFF1A\u6821\u9A8C\u5FC5\u586B\u3001\u9ED8\u8BA4\u5E74\u4EFD\u3001\u6309\u5468\u671F\u67E5\u91CD\u5E76\u751F\u6210\u786E\u8BA4\u9884\u89C8\uFF0C\u4E0D\u5199\u5165",
|
|
1189
|
+
capability: "plan",
|
|
1190
|
+
risk: "read-before-write",
|
|
1191
|
+
requiresConfirmation: true,
|
|
1192
|
+
inputSchema: schemaOf({
|
|
1193
|
+
content: { type: "string", description: "\u5DE5\u4F5C\u6210\u6548\uFF08\u652F\u6301 HTML \u7247\u6BB5\uFF09" },
|
|
1194
|
+
summary: { type: "string", description: "\u603B\u7ED3\u5FC3\u5F97\uFF08\u652F\u6301 HTML \u7247\u6BB5\uFF09" },
|
|
1195
|
+
plans: { type: "string", description: "\u8BA1\u5212\u5185\u5BB9\uFF08\u652F\u6301 HTML \u7247\u6BB5\uFF09" },
|
|
1196
|
+
year: { type: "integer", description: "\u62A5\u544A\u5E74\u4EFD\uFF1B\u7F3A\u7701\u53D6\u672C\u5E74" },
|
|
1197
|
+
type: { ...SCHEMA_REPORT_TYPE, description: "\u62A5\u544A\u7C7B\u578B" },
|
|
1198
|
+
serialNumber: { type: "integer", minimum: 1, description: "\u62A5\u544A\u5468\u671F" },
|
|
1199
|
+
title: { type: "string", description: "\u62A5\u544A\u540D\u79F0\uFF1Beb \u94FE\u8DEF\u53EF\u7531 userName \u81EA\u52A8\u751F\u6210" },
|
|
1200
|
+
userName: { type: "string", minLength: 1, description: "\u5F53\u524D\u767B\u5F55\u4EBA\u59D3\u540D\uFF0Ceb \u94FE\u8DEF\u81EA\u52A8\u751F\u6210\u62A5\u544A\u540D\u79F0\u65F6\u5FC5\u586B\uFF08\u53EF\u7531 weaver-e10-hrm \u89E3\u6790\uFF09" }
|
|
1201
|
+
}, {
|
|
1202
|
+
required: ["type", "serialNumber"],
|
|
1203
|
+
anyOf: [{ required: ["content"] }, { required: ["summary"] }, { required: ["plans"] }]
|
|
1204
|
+
}),
|
|
1205
|
+
handler: async (args, env) => {
|
|
1206
|
+
const { host, continuation } = env;
|
|
1207
|
+
const body = bodyFields(args);
|
|
1208
|
+
const year = resolveYear(args.year);
|
|
1209
|
+
const type = assertReportType(args.type);
|
|
1210
|
+
const serialNumber = resolveSerialNumber(args.serialNumber);
|
|
1211
|
+
const linkInfo = await resolveLink(host);
|
|
1212
|
+
const existing = await lookupReport(host, linkInfo.link, { year, type, serialNumber });
|
|
1213
|
+
if (existing.exists) {
|
|
1214
|
+
return planSuccess("plan.report.create.prepare", {
|
|
1215
|
+
status: "ALREADY_EXISTS",
|
|
1216
|
+
link: linkInfo.link,
|
|
1217
|
+
targets: { year, type, serialNumber },
|
|
1218
|
+
existingReport: existing.report,
|
|
1219
|
+
hint: "\u8BE5\u5468\u671F\u62A5\u544A\u5DF2\u5B58\u5728\uFF0C\u4E0D\u5F97\u91CD\u590D\u521B\u5EFA\uFF1B\u8BF7\u5148\u8BE2\u95EE\u7528\u6237\u662F\u5426\u6539\u4E3A\u7F16\u8F91\u8BE5\u62A5\u544A",
|
|
1220
|
+
warnings: existing.warnings
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
const explicitTitle = textField(args.title, "title");
|
|
1224
|
+
let title = explicitTitle ?? null;
|
|
1225
|
+
if (!title && linkInfo.link === "eb") {
|
|
1226
|
+
const userName = textField(args.userName, "userName");
|
|
1227
|
+
if (!userName) {
|
|
1228
|
+
throw planValidationError(
|
|
1229
|
+
"userName_required",
|
|
1230
|
+
"eb \u94FE\u8DEF\u9700\u8981\u52A8\u6001\u751F\u6210\u62A5\u544A\u540D\u79F0\uFF0C\u8BF7\u5148\u901A\u8FC7 weaver-e10-hrm \u89E3\u6790\u5F53\u524D\u767B\u5F55\u4EBA\u59D3\u540D\u540E\u4F20\u5165 userName\uFF0C\u6216\u76F4\u63A5\u4F20\u5165 title"
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
title = buildEbTitle(userName, type, year, serialNumber);
|
|
1234
|
+
}
|
|
1235
|
+
const payload = {
|
|
1236
|
+
...body.content === void 0 ? {} : { content: body.content },
|
|
1237
|
+
...body.summary === void 0 ? {} : { summary: body.summary },
|
|
1238
|
+
...body.plans === void 0 ? {} : { plans: body.plans },
|
|
1239
|
+
year,
|
|
1240
|
+
type,
|
|
1241
|
+
serialNumber,
|
|
1242
|
+
...title ? { title } : {}
|
|
1243
|
+
};
|
|
1244
|
+
const token = await issueConfirmation(env, "plan.report.create.apply", linkInfo.link, payload);
|
|
1245
|
+
return planSuccess("plan.report.create.prepare", {
|
|
1246
|
+
status: "AWAITING_CONFIRMATION",
|
|
1247
|
+
link: linkInfo.link,
|
|
1248
|
+
targets: { year, type, serialNumber },
|
|
1249
|
+
preview: payload,
|
|
1250
|
+
continuation: token,
|
|
1251
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS,
|
|
1252
|
+
warnings: existing.warnings
|
|
1253
|
+
});
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
var planReportCreateApply = {
|
|
1257
|
+
name: "plan.report.create.apply",
|
|
1258
|
+
resource: "plan",
|
|
1259
|
+
method: "report.create.apply",
|
|
1260
|
+
action: "plan.report.create.apply",
|
|
1261
|
+
summary: "\u63D0\u4EA4\u65B0\u5EFA\u62A5\u544A\uFF1B\u5FC5\u987B\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u8C03\u7528\uFF0C\u4E14\u8981\u6C42 prepare \u8FD4\u56DE\u7684 continuation",
|
|
1262
|
+
capability: "plan",
|
|
1263
|
+
risk: "high-risk-write",
|
|
1264
|
+
requiresConfirmation: true,
|
|
1265
|
+
inputSchema: schemaOf({
|
|
1266
|
+
content: { type: "string" },
|
|
1267
|
+
summary: { type: "string" },
|
|
1268
|
+
plans: { type: "string" },
|
|
1269
|
+
year: { type: "integer" },
|
|
1270
|
+
type: { ...SCHEMA_REPORT_TYPE },
|
|
1271
|
+
serialNumber: { type: "integer", minimum: 1 },
|
|
1272
|
+
title: { type: "string" },
|
|
1273
|
+
confirm: { const: true },
|
|
1274
|
+
continuation: { type: "string", minLength: 1 }
|
|
1275
|
+
}, { required: ["confirm", "continuation"] }),
|
|
1276
|
+
handler: async (args, env) => {
|
|
1277
|
+
const lease = await ensureConfirmLease(args, "plan.report.create.apply", env);
|
|
1278
|
+
const payload = payloadFromLease(args, lease, [...CREATE_KEYS]);
|
|
1279
|
+
const link = await assertSameLink(env.host, lease.link ?? "standard");
|
|
1280
|
+
const session = await env.host.getSession();
|
|
1281
|
+
const year = resolveYear(payload.year);
|
|
1282
|
+
const type = assertReportType(payload.type);
|
|
1283
|
+
const serialNumber = resolveSerialNumber(payload.serialNumber);
|
|
1284
|
+
const existing = await lookupReport(env.host, link, { year, type, serialNumber });
|
|
1285
|
+
if (existing.exists) {
|
|
1286
|
+
throw planValidationError("report_exists", "\u8BE5\u5468\u671F\u62A5\u544A\u5DF2\u5B58\u5728\uFF0C\u7981\u6B62\u91CD\u590D\u521B\u5EFA\uFF1B\u8BF7\u6539\u7528 plan.report.update.prepare \u7F16\u8F91");
|
|
1287
|
+
}
|
|
1288
|
+
const response = await sendWrite(
|
|
1289
|
+
env,
|
|
1290
|
+
"plan.report.create.apply",
|
|
1291
|
+
link === "standard" ? {
|
|
1292
|
+
method: "POST",
|
|
1293
|
+
path: "/api/workrelate/plan/workreport/create",
|
|
1294
|
+
body: {
|
|
1295
|
+
workReport: {
|
|
1296
|
+
content: payload.content ?? "",
|
|
1297
|
+
summary: payload.summary ?? "",
|
|
1298
|
+
plans: payload.plans ?? "",
|
|
1299
|
+
year,
|
|
1300
|
+
type,
|
|
1301
|
+
serialNumber
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
} : {
|
|
1305
|
+
method: "POST",
|
|
1306
|
+
path: "/api/ebuilder/form/formdata/v2/saveFormData/plan_createPlan",
|
|
1307
|
+
body: {
|
|
1308
|
+
datajson: {
|
|
1309
|
+
operationinfo: { printCost: false },
|
|
1310
|
+
datas: [{
|
|
1311
|
+
mainTable: compact({
|
|
1312
|
+
f_content: payload.content,
|
|
1313
|
+
f_summary: payload.summary,
|
|
1314
|
+
f_plans: payload.plans,
|
|
1315
|
+
f_title: payload.title,
|
|
1316
|
+
f_year: year,
|
|
1317
|
+
f_type: type,
|
|
1318
|
+
f_serial_number: serialNumber,
|
|
1319
|
+
f_post_status: "0"
|
|
1320
|
+
})
|
|
1321
|
+
}],
|
|
1322
|
+
header: { operator: session.userId }
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
},
|
|
1326
|
+
{
|
|
1327
|
+
message: "\u521B\u5EFA\u62A5\u544A\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u62A5\u544A\u662F\u5426\u5DF2\u521B\u5EFA\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u8BF7\u5148\u7528 plan.report.get \u6309\u5468\u671F\u56DE\u67E5",
|
|
1328
|
+
partialData: { targets: { year, type, serialNumber } },
|
|
1329
|
+
stage: "create"
|
|
1330
|
+
}
|
|
1331
|
+
);
|
|
1332
|
+
const result = { link, status: "COMPLETE" };
|
|
1333
|
+
if (link === "standard") {
|
|
1334
|
+
if (!isFlagSuccess(response)) {
|
|
1335
|
+
throw planApiError("business_error", businessMessage(response), { stage: "create" });
|
|
1336
|
+
}
|
|
1337
|
+
const reportId = response?.workReport?.id ?? null;
|
|
1338
|
+
result.reportId = reportId === null ? null : String(reportId);
|
|
1339
|
+
result.title = response?.workReport?.title ?? payload.title ?? null;
|
|
1340
|
+
} else {
|
|
1341
|
+
if (!isDatajsonSuccess(response)) {
|
|
1342
|
+
throw planApiError("business_error", businessMessage(response), { stage: "create" });
|
|
1343
|
+
}
|
|
1344
|
+
const dataIds = response?.datajson?.dataIds;
|
|
1345
|
+
const reportId = Array.isArray(dataIds) && dataIds.length > 0 ? String(dataIds[0]) : null;
|
|
1346
|
+
result.reportId = reportId;
|
|
1347
|
+
result.title = payload.title ?? null;
|
|
1348
|
+
}
|
|
1349
|
+
result.detailUrl = await buildDetailUrl(env.host, link, result.reportId ?? null);
|
|
1350
|
+
return planSuccess("plan.report.create.apply", result);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
var planReportUpdatePrepare = {
|
|
1354
|
+
name: "plan.report.update.prepare",
|
|
1355
|
+
resource: "plan",
|
|
1356
|
+
method: "report.update.prepare",
|
|
1357
|
+
action: "plan.report.update.prepare",
|
|
1358
|
+
summary: "\u51C6\u5907\u4FEE\u6539\u62A5\u544A\uFF1A\u5B9A\u4F4D\u76EE\u6807\u62A5\u544A\u3001\u5408\u5E76\u6539\u52A8\u5E76\u751F\u6210 before/after \u9884\u89C8\uFF0C\u4E0D\u5199\u5165",
|
|
1359
|
+
capability: "plan",
|
|
1360
|
+
risk: "read-before-write",
|
|
1361
|
+
requiresConfirmation: true,
|
|
1362
|
+
inputSchema: schemaOf({
|
|
1363
|
+
id: { ...SCHEMA_ID, description: "\u62A5\u544A id\uFF1B\u4E0D\u4F20\u65F6\u6309\u5468\u671F\u5B9A\u4F4D" },
|
|
1364
|
+
year: { type: "integer", description: "\u62A5\u544A\u5E74\u4EFD" },
|
|
1365
|
+
type: { ...SCHEMA_REPORT_TYPE, description: "\u62A5\u544A\u7C7B\u578B" },
|
|
1366
|
+
serialNumber: { type: "integer", minimum: 1, description: "\u62A5\u544A\u5468\u671F" },
|
|
1367
|
+
creatorUserId: { ...SCHEMA_ID, description: "\u62A5\u544A\u521B\u5EFA\u4EBA id\uFF1B\u7F3A\u7701\u4E3A\u5F53\u524D\u767B\u5F55\u4EBA" },
|
|
1368
|
+
content: { type: "string", description: "\u65B0\u7684\u5DE5\u4F5C\u6210\u6548" },
|
|
1369
|
+
summary: { type: "string", description: "\u65B0\u7684\u603B\u7ED3\u5FC3\u5F97" },
|
|
1370
|
+
plans: { type: "string", description: "\u65B0\u7684\u8BA1\u5212\u5185\u5BB9" }
|
|
1371
|
+
}, {
|
|
1372
|
+
anyOf: [{ required: ["id"] }, { required: ["type", "serialNumber"] }]
|
|
1373
|
+
}),
|
|
1374
|
+
handler: async (args, env) => {
|
|
1375
|
+
const changed = bodyFields(args);
|
|
1376
|
+
const target = await locateTarget(args, env);
|
|
1377
|
+
const before = target.report ? {
|
|
1378
|
+
content: target.report.content ?? "",
|
|
1379
|
+
summary: target.report.summary ?? "",
|
|
1380
|
+
plans: target.report.plans ?? ""
|
|
1381
|
+
} : null;
|
|
1382
|
+
const after = {
|
|
1383
|
+
content: changed.content ?? before?.content ?? "",
|
|
1384
|
+
summary: changed.summary ?? before?.summary ?? "",
|
|
1385
|
+
plans: changed.plans ?? before?.plans ?? ""
|
|
1386
|
+
};
|
|
1387
|
+
const payload = {
|
|
1388
|
+
reportId: target.reportId,
|
|
1389
|
+
...after,
|
|
1390
|
+
year: target.report?.year ?? (args.year === void 0 || args.year === "" ? null : resolveYear(args.year)),
|
|
1391
|
+
type: target.report?.type ?? (args.type === void 0 ? null : assertReportType(args.type)),
|
|
1392
|
+
serialNumber: target.report?.serialNumber ?? (args.serialNumber === void 0 || args.serialNumber === "" ? null : resolveSerialNumber(args.serialNumber))
|
|
1393
|
+
};
|
|
1394
|
+
const token = await issueConfirmation(env, "plan.report.update.apply", target.link, payload);
|
|
1395
|
+
return planSuccess("plan.report.update.prepare", {
|
|
1396
|
+
status: "AWAITING_CONFIRMATION",
|
|
1397
|
+
link: target.link,
|
|
1398
|
+
preview: { reportId: target.reportId, title: target.title, before, after, precheck: target.precheck },
|
|
1399
|
+
changedFields: BODY_KEYS.filter((key) => changed[key] !== void 0),
|
|
1400
|
+
continuation: token,
|
|
1401
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS,
|
|
1402
|
+
warnings: target.warnings
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
var planReportUpdateApply = {
|
|
1407
|
+
name: "plan.report.update.apply",
|
|
1408
|
+
resource: "plan",
|
|
1409
|
+
method: "report.update.apply",
|
|
1410
|
+
action: "plan.report.update.apply",
|
|
1411
|
+
summary: "\u63D0\u4EA4\u4FEE\u6539\u62A5\u544A\uFF1B\u5FC5\u987B\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u8C03\u7528\uFF0C\u4E14\u8981\u6C42 prepare \u8FD4\u56DE\u7684 continuation",
|
|
1412
|
+
capability: "plan",
|
|
1413
|
+
risk: "high-risk-write",
|
|
1414
|
+
requiresConfirmation: true,
|
|
1415
|
+
inputSchema: schemaOf({
|
|
1416
|
+
content: { type: "string" },
|
|
1417
|
+
summary: { type: "string" },
|
|
1418
|
+
plans: { type: "string" },
|
|
1419
|
+
confirm: { const: true },
|
|
1420
|
+
continuation: { type: "string", minLength: 1 }
|
|
1421
|
+
}, { required: ["confirm", "continuation"] }),
|
|
1422
|
+
handler: async (args, env) => {
|
|
1423
|
+
const lease = await ensureConfirmLease(args, "plan.report.update.apply", env);
|
|
1424
|
+
const payload = payloadFromLease(args, lease, [...BODY_KEYS]);
|
|
1425
|
+
const link = await assertSameLink(env.host, lease.link ?? "standard");
|
|
1426
|
+
const reportId = toIdString(payload.reportId, "reportId");
|
|
1427
|
+
const session = await env.host.getSession();
|
|
1428
|
+
const response = await sendWrite(
|
|
1429
|
+
env,
|
|
1430
|
+
"plan.report.update.apply",
|
|
1431
|
+
link === "standard" ? {
|
|
1432
|
+
method: "POST",
|
|
1433
|
+
path: `/api/workrelate/plan/workreport/${encodeURIComponent(reportId)}`,
|
|
1434
|
+
body: {
|
|
1435
|
+
workReport: {
|
|
1436
|
+
content: payload.content ?? "",
|
|
1437
|
+
summary: payload.summary ?? "",
|
|
1438
|
+
plans: payload.plans ?? ""
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
} : {
|
|
1442
|
+
method: "POST",
|
|
1443
|
+
path: "/api/ebuilder/form/formdata/v2/updateFormData/plan_updatePlan",
|
|
1444
|
+
body: {
|
|
1445
|
+
datajson: {
|
|
1446
|
+
operationinfo: { printCost: false },
|
|
1447
|
+
datas: [{
|
|
1448
|
+
mainTable: compact({
|
|
1449
|
+
id: reportId,
|
|
1450
|
+
f_content: payload.content,
|
|
1451
|
+
f_summary: payload.summary,
|
|
1452
|
+
f_plans: payload.plans
|
|
1453
|
+
})
|
|
1454
|
+
}],
|
|
1455
|
+
header: { operator: session.userId }
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
},
|
|
1459
|
+
{
|
|
1460
|
+
message: "\u4FEE\u6539\u62A5\u544A\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u62A5\u544A\u662F\u5426\u5DF2\u66F4\u65B0\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u8BF7\u5148\u7528 plan.report.get \u56DE\u67E5",
|
|
1461
|
+
partialData: { reportId },
|
|
1462
|
+
stage: "update"
|
|
1463
|
+
}
|
|
1464
|
+
);
|
|
1465
|
+
if (link === "standard") {
|
|
1466
|
+
const updated = response?.isUpdated;
|
|
1467
|
+
if (!(updated === "1" || updated === 1 || updated === true)) {
|
|
1468
|
+
throw planApiError("business_error", businessMessage(response), { stage: "update" });
|
|
1469
|
+
}
|
|
1470
|
+
} else if (!isDatajsonSuccess(response)) {
|
|
1471
|
+
throw planApiError("business_error", businessMessage(response), { stage: "update" });
|
|
1472
|
+
}
|
|
1473
|
+
return planSuccess("plan.report.update.apply", {
|
|
1474
|
+
link,
|
|
1475
|
+
status: "COMPLETE",
|
|
1476
|
+
reportId,
|
|
1477
|
+
detailUrl: await buildDetailUrl(env.host, link, reportId)
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
var TARGET_SCHEMA = {
|
|
1482
|
+
id: { ...SCHEMA_ID, description: "\u62A5\u544A id\uFF1B\u4E0E\u5468\u671F\u53C2\u6570\u4E8C\u9009\u4E00" },
|
|
1483
|
+
year: { type: "integer", description: "\u62A5\u544A\u5E74\u4EFD" },
|
|
1484
|
+
type: { ...SCHEMA_REPORT_TYPE, description: "\u62A5\u544A\u7C7B\u578B" },
|
|
1485
|
+
serialNumber: { type: "integer", minimum: 1, description: "\u62A5\u544A\u5468\u671F" },
|
|
1486
|
+
creatorUserId: { ...SCHEMA_ID, description: "\u62A5\u544A\u521B\u5EFA\u4EBA id\uFF1B\u7F3A\u7701\u4E3A\u5F53\u524D\u767B\u5F55\u4EBA" }
|
|
1487
|
+
};
|
|
1488
|
+
async function locateTarget(args, env) {
|
|
1489
|
+
const linkInfo = await resolveLink(env.host);
|
|
1490
|
+
const query = args.id !== void 0 && args.id !== "" ? {
|
|
1491
|
+
id: toIdString(args.id, "id"),
|
|
1492
|
+
...args.type !== void 0 && args.serialNumber !== void 0 ? { year: resolveYear(args.year), type: assertReportType(args.type), serialNumber: resolveSerialNumber(args.serialNumber) } : {}
|
|
1493
|
+
} : {
|
|
1494
|
+
year: resolveYear(args.year),
|
|
1495
|
+
type: assertReportType(args.type),
|
|
1496
|
+
serialNumber: resolveSerialNumber(args.serialNumber),
|
|
1497
|
+
...args.creatorUserId !== void 0 && args.creatorUserId !== "" ? { creatorUserId: toIdString(args.creatorUserId, "creatorUserId") } : {}
|
|
1498
|
+
};
|
|
1499
|
+
const target = await lookupReport(env.host, linkInfo.link, query);
|
|
1500
|
+
const warnings = [...target.warnings];
|
|
1501
|
+
if (target.exists === false) {
|
|
1502
|
+
throw planValidationError("not_found", "\u672A\u627E\u5230\u76EE\u6807\u62A5\u544A\uFF0C\u8BF7\u5148\u786E\u8BA4\u62A5\u544A id \u6216\u5468\u671F\u4FE1\u606F");
|
|
1503
|
+
}
|
|
1504
|
+
if (!target.report?.reportId) {
|
|
1505
|
+
if (args.id === void 0 || args.id === "") {
|
|
1506
|
+
throw planValidationError("lookup_incomplete", "\u7F3A\u5C11\u53EF\u7528\u4E8E\u5B9A\u4F4D\u62A5\u544A\u7684 id \u6216\u5468\u671F\u4FE1\u606F");
|
|
1507
|
+
}
|
|
1508
|
+
warnings.push("\u5F53\u524D\u94FE\u8DEF\u65E0\u6CD5\u6309\u62A5\u544A id \u9884\u68C0\u62A5\u544A\u72B6\u6001\uFF0C\u5DF2\u8DF3\u8FC7\u5199\u5165\u524D\u6821\u9A8C\uFF1B\u5982\u53EF\u63D0\u4F9B year/type/serialNumber \u5C06\u81EA\u52A8\u8865\u68C0");
|
|
1509
|
+
return {
|
|
1510
|
+
link: linkInfo.link,
|
|
1511
|
+
reportId: toIdString(args.id, "id"),
|
|
1512
|
+
report: null,
|
|
1513
|
+
postStatus: null,
|
|
1514
|
+
title: null,
|
|
1515
|
+
precheck: "skipped",
|
|
1516
|
+
warnings
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
return {
|
|
1520
|
+
link: linkInfo.link,
|
|
1521
|
+
reportId: target.report.reportId,
|
|
1522
|
+
report: target.report,
|
|
1523
|
+
postStatus: target.report.postStatus,
|
|
1524
|
+
title: target.report.title,
|
|
1525
|
+
precheck: "checked",
|
|
1526
|
+
warnings
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
var planReportPublishPrepare = {
|
|
1530
|
+
name: "plan.report.publish.prepare",
|
|
1531
|
+
resource: "plan",
|
|
1532
|
+
method: "report.publish.prepare",
|
|
1533
|
+
action: "plan.report.publish.prepare",
|
|
1534
|
+
summary: "\u51C6\u5907\u53D1\u5E03\u62A5\u544A\uFF1A\u5B9A\u4F4D\u76EE\u6807\u3001\u6821\u9A8C\u5F53\u524D\u53D1\u5E03\u72B6\u6001\u5E76\u751F\u6210\u786E\u8BA4\u9884\u89C8\uFF0C\u4E0D\u5199\u5165",
|
|
1535
|
+
capability: "plan",
|
|
1536
|
+
risk: "read-before-write",
|
|
1537
|
+
requiresConfirmation: true,
|
|
1538
|
+
inputSchema: schemaOf({ ...TARGET_SCHEMA }, {
|
|
1539
|
+
anyOf: [{ required: ["id"] }, { required: ["type", "serialNumber"] }]
|
|
1540
|
+
}),
|
|
1541
|
+
handler: async (args, env) => {
|
|
1542
|
+
const target = await locateTarget(args, env);
|
|
1543
|
+
if (target.postStatus === "1") {
|
|
1544
|
+
throw planValidationError("already_published", "\u8BE5\u62A5\u544A\u5DF2\u662F\u300C\u5DF2\u53D1\u5E03\u300D\u72B6\u6001\uFF0C\u65E0\u9700\u91CD\u590D\u53D1\u5E03");
|
|
1545
|
+
}
|
|
1546
|
+
const token = await issueConfirmation(env, "plan.report.publish.apply", target.link, {
|
|
1547
|
+
reportId: target.reportId,
|
|
1548
|
+
title: target.title,
|
|
1549
|
+
postStatus: target.postStatus
|
|
1550
|
+
});
|
|
1551
|
+
return planSuccess("plan.report.publish.prepare", {
|
|
1552
|
+
status: "AWAITING_CONFIRMATION",
|
|
1553
|
+
link: target.link,
|
|
1554
|
+
preview: {
|
|
1555
|
+
reportId: target.reportId,
|
|
1556
|
+
title: target.title,
|
|
1557
|
+
postStatus: target.postStatus,
|
|
1558
|
+
postStatusLabel: target.postStatus === null ? null : POST_STATUS_LABELS[target.postStatus] ?? null,
|
|
1559
|
+
precheck: target.precheck
|
|
1560
|
+
},
|
|
1561
|
+
continuation: token,
|
|
1562
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS,
|
|
1563
|
+
warnings: target.warnings
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
var planReportPublishApply = {
|
|
1568
|
+
name: "plan.report.publish.apply",
|
|
1569
|
+
resource: "plan",
|
|
1570
|
+
method: "report.publish.apply",
|
|
1571
|
+
action: "plan.report.publish.apply",
|
|
1572
|
+
summary: "\u63D0\u4EA4\u53D1\u5E03\u62A5\u544A\uFF1B\u5FC5\u987B\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u8C03\u7528\uFF0C\u4E14\u8981\u6C42 prepare \u8FD4\u56DE\u7684 continuation",
|
|
1573
|
+
capability: "plan",
|
|
1574
|
+
risk: "high-risk-write",
|
|
1575
|
+
requiresConfirmation: true,
|
|
1576
|
+
inputSchema: schemaOf({
|
|
1577
|
+
confirm: { const: true },
|
|
1578
|
+
continuation: { type: "string", minLength: 1 }
|
|
1579
|
+
}, { required: ["confirm", "continuation"] }),
|
|
1580
|
+
handler: async (args, env) => {
|
|
1581
|
+
const lease = await ensureConfirmLease(args, "plan.report.publish.apply", env);
|
|
1582
|
+
const link = await assertSameLink(env.host, lease.link ?? "standard");
|
|
1583
|
+
const reportId = toIdString((lease.payload || {}).reportId, "reportId");
|
|
1584
|
+
const response = await sendWrite(
|
|
1585
|
+
env,
|
|
1586
|
+
"plan.report.publish.apply",
|
|
1587
|
+
link === "standard" ? {
|
|
1588
|
+
method: "POST",
|
|
1589
|
+
path: "/api/workrelate/plan/workreport/sendReport",
|
|
1590
|
+
body: { workReportId: reportId }
|
|
1591
|
+
} : {
|
|
1592
|
+
method: "POST",
|
|
1593
|
+
path: "/api/secondev/planebapp/main/sendReport",
|
|
1594
|
+
body: { reportFormDataId: reportId }
|
|
1595
|
+
},
|
|
1596
|
+
{
|
|
1597
|
+
message: "\u53D1\u5E03\u62A5\u544A\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u62A5\u544A\u662F\u5426\u5DF2\u53D1\u5E03\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u8BF7\u5148\u7528 plan.report.get \u56DE\u67E5",
|
|
1598
|
+
partialData: { reportId },
|
|
1599
|
+
stage: "publish"
|
|
1600
|
+
}
|
|
1601
|
+
);
|
|
1602
|
+
if (link === "standard") {
|
|
1603
|
+
if (!isFlagSuccess(response)) {
|
|
1604
|
+
throw planApiError("business_error", businessMessage(response), { stage: "publish" });
|
|
1605
|
+
}
|
|
1606
|
+
} else if (Number(response?.code) !== 200) {
|
|
1607
|
+
throw planApiError("business_error", businessMessage(response), { stage: "publish" });
|
|
1608
|
+
}
|
|
1609
|
+
return planSuccess("plan.report.publish.apply", {
|
|
1610
|
+
link,
|
|
1611
|
+
status: "COMPLETE",
|
|
1612
|
+
reportId,
|
|
1613
|
+
detailUrl: await buildDetailUrl(env.host, link, reportId)
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
var planReportWithdrawPrepare = {
|
|
1618
|
+
name: "plan.report.withdraw.prepare",
|
|
1619
|
+
resource: "plan",
|
|
1620
|
+
method: "report.withdraw.prepare",
|
|
1621
|
+
action: "plan.report.withdraw.prepare",
|
|
1622
|
+
summary: "\u51C6\u5907\u64A4\u56DE\u62A5\u544A\uFF1A\u5B9A\u4F4D\u76EE\u6807\u3001\u6821\u9A8C\u5176\u4E3A\u300C\u5DF2\u53D1\u5E03\u300D\u72B6\u6001\u5E76\u751F\u6210\u786E\u8BA4\u9884\u89C8\uFF0C\u4E0D\u5199\u5165",
|
|
1623
|
+
capability: "plan",
|
|
1624
|
+
risk: "read-before-write",
|
|
1625
|
+
requiresConfirmation: true,
|
|
1626
|
+
inputSchema: schemaOf({ ...TARGET_SCHEMA }, {
|
|
1627
|
+
anyOf: [{ required: ["id"] }, { required: ["type", "serialNumber"] }]
|
|
1628
|
+
}),
|
|
1629
|
+
handler: async (args, env) => {
|
|
1630
|
+
const target = await locateTarget(args, env);
|
|
1631
|
+
assertLinkSupported(
|
|
1632
|
+
target.link,
|
|
1633
|
+
"standard",
|
|
1634
|
+
"plan.report.withdraw",
|
|
1635
|
+
"eb \u94FE\u8DEF\u7684\u64A4\u56DE\u62A5\u544A\u901A\u8FC7 ESB \u52A8\u4F5C\u6D41\u300Ceb\u64A4\u56DE\u62A5\u544A\u300D\u5B9E\u73B0\uFF0C\u5F53\u524D CLI \u672A\u83B7\u5F97\u8BE5\u52A8\u4F5C\u6D41\u7684\u552F\u4E00\u6807\u8BC6\uFF08uniqueIndent\uFF09\uFF0C\u8BF7\u6539\u7528 weaver-e10-customesb-execute skill \u6267\u884C\u540C\u540D\u52A8\u4F5C\u6D41"
|
|
1636
|
+
);
|
|
1637
|
+
if (target.precheck === "checked" && target.postStatus !== "1") {
|
|
1638
|
+
throw planValidationError("not_published", "\u8BE5\u62A5\u544A\u5F53\u524D\u4E0D\u662F\u300C\u5DF2\u53D1\u5E03\u300D\u72B6\u6001\uFF0C\u65E0\u6CD5\u64A4\u56DE");
|
|
1639
|
+
}
|
|
1640
|
+
const token = await issueConfirmation(env, "plan.report.withdraw.apply", target.link, {
|
|
1641
|
+
reportId: target.reportId,
|
|
1642
|
+
title: target.title
|
|
1643
|
+
});
|
|
1644
|
+
return planSuccess("plan.report.withdraw.prepare", {
|
|
1645
|
+
status: "AWAITING_CONFIRMATION",
|
|
1646
|
+
link: target.link,
|
|
1647
|
+
preview: { reportId: target.reportId, title: target.title, postStatus: target.postStatus },
|
|
1648
|
+
continuation: token,
|
|
1649
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS,
|
|
1650
|
+
warnings: target.warnings
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
var planReportWithdrawApply = {
|
|
1655
|
+
name: "plan.report.withdraw.apply",
|
|
1656
|
+
resource: "plan",
|
|
1657
|
+
method: "report.withdraw.apply",
|
|
1658
|
+
action: "plan.report.withdraw.apply",
|
|
1659
|
+
summary: "\u63D0\u4EA4\u64A4\u56DE\u62A5\u544A\uFF08\u4EC5\u6807\u51C6\u7248\u94FE\u8DEF\uFF09\uFF1B\u5FC5\u987B\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u8C03\u7528",
|
|
1660
|
+
capability: "plan",
|
|
1661
|
+
risk: "high-risk-write",
|
|
1662
|
+
requiresConfirmation: true,
|
|
1663
|
+
inputSchema: schemaOf({
|
|
1664
|
+
confirm: { const: true },
|
|
1665
|
+
continuation: { type: "string", minLength: 1 }
|
|
1666
|
+
}, { required: ["confirm", "continuation"] }),
|
|
1667
|
+
handler: async (args, env) => {
|
|
1668
|
+
const lease = await ensureConfirmLease(args, "plan.report.withdraw.apply", env);
|
|
1669
|
+
const link = await assertSameLink(env.host, lease.link ?? "standard");
|
|
1670
|
+
assertLinkSupported(
|
|
1671
|
+
link,
|
|
1672
|
+
"standard",
|
|
1673
|
+
"plan.report.withdraw",
|
|
1674
|
+
"eb \u94FE\u8DEF\u7684\u64A4\u56DE\u62A5\u544A\u901A\u8FC7 ESB \u52A8\u4F5C\u6D41\u300Ceb\u64A4\u56DE\u62A5\u544A\u300D\u5B9E\u73B0\uFF0C\u8BF7\u6539\u7528 weaver-e10-customesb-execute skill \u6267\u884C\u540C\u540D\u52A8\u4F5C\u6D41"
|
|
1675
|
+
);
|
|
1676
|
+
const reportId = toIdString((lease.payload || {}).reportId, "reportId");
|
|
1677
|
+
const response = await sendWrite(
|
|
1678
|
+
env,
|
|
1679
|
+
"plan.report.withdraw.apply",
|
|
1680
|
+
{
|
|
1681
|
+
method: "POST",
|
|
1682
|
+
path: "/api/workrelate/plan/workreport/takeBackReport",
|
|
1683
|
+
body: { id: reportId }
|
|
1684
|
+
},
|
|
1685
|
+
{
|
|
1686
|
+
message: "\u64A4\u56DE\u62A5\u544A\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u62A5\u544A\u662F\u5426\u5DF2\u64A4\u56DE\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u8BF7\u5148\u7528 plan.report.get \u56DE\u67E5",
|
|
1687
|
+
partialData: { reportId },
|
|
1688
|
+
stage: "withdraw"
|
|
1689
|
+
}
|
|
1690
|
+
);
|
|
1691
|
+
if (!isFlagSuccess(response)) {
|
|
1692
|
+
throw planApiError("business_error", businessMessage(response), { stage: "withdraw" });
|
|
1693
|
+
}
|
|
1694
|
+
return planSuccess("plan.report.withdraw.apply", {
|
|
1695
|
+
link,
|
|
1696
|
+
status: "COMPLETE",
|
|
1697
|
+
reportId,
|
|
1698
|
+
detailUrl: await buildDetailUrl(env.host, link, reportId)
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1701
|
+
};
|
|
1702
|
+
var planReportRemindPrepare = {
|
|
1703
|
+
name: "plan.report.remind.prepare",
|
|
1704
|
+
resource: "plan",
|
|
1705
|
+
method: "report.remind.prepare",
|
|
1706
|
+
action: "plan.report.remind.prepare",
|
|
1707
|
+
summary: "\u51C6\u5907\u53D1\u9001\u62A5\u544A\u63D0\u4EA4\u63D0\u9192\uFF1A\u5F52\u4E00\u5316\u4EBA\u5458 ID\u3001\u6309\u5468\u671F\u751F\u6210\u9ED8\u8BA4\u6587\u6848\u5E76\u751F\u6210\u786E\u8BA4\u9884\u89C8\uFF0C\u4E0D\u53D1\u9001",
|
|
1708
|
+
capability: "plan",
|
|
1709
|
+
risk: "read-before-write",
|
|
1710
|
+
requiresConfirmation: true,
|
|
1711
|
+
inputSchema: schemaOf({
|
|
1712
|
+
personIds: {
|
|
1713
|
+
oneOf: [
|
|
1714
|
+
{ type: "array", items: { type: "string", pattern: "^\\d+$" }, minItems: 1 },
|
|
1715
|
+
{ type: "string", pattern: "^\\d+(,\\d+)*$" }
|
|
1716
|
+
],
|
|
1717
|
+
description: "\u9700\u8981\u63D0\u9192\u7684\u4EBA\u5458 ID\uFF08\u6570\u7EC4\u6216\u82F1\u6587\u9017\u53F7\u62FC\u63A5\u5B57\u7B26\u4E32\uFF09"
|
|
1718
|
+
},
|
|
1719
|
+
year: { type: "integer", description: "\u62A5\u544A\u5E74\u4EFD\uFF1B\u7F3A\u7701\u53D6\u672C\u5E74" },
|
|
1720
|
+
type: { ...SCHEMA_REPORT_TYPE, description: "\u62A5\u544A\u7C7B\u578B" },
|
|
1721
|
+
serialNumber: { type: "integer", minimum: 1, description: "\u62A5\u544A\u5468\u671F" },
|
|
1722
|
+
content: { type: "string", description: "\u63D0\u9192\u6587\u6848\uFF1B\u7F3A\u7701\u6309\u5468\u671F\u751F\u6210\u9ED8\u8BA4\u6587\u6848" }
|
|
1723
|
+
}, { required: ["personIds", "type", "serialNumber"] }),
|
|
1724
|
+
handler: async (args, env) => {
|
|
1725
|
+
const linkInfo = await resolveLink(env.host);
|
|
1726
|
+
assertLinkSupported(
|
|
1727
|
+
linkInfo.link,
|
|
1728
|
+
"standard",
|
|
1729
|
+
"plan.report.remind",
|
|
1730
|
+
"eb \u94FE\u8DEF\u672A\u63D0\u4F9B\u62A5\u544A\u63D0\u4EA4\u63D0\u9192\u63A5\u53E3\uFF1B\u5F53\u524D\u79DF\u6237\u8D70 e10-ebuilder \u94FE\u8DEF\uFF0C\u65E0\u6CD5\u53D1\u9001\u63D0\u4EA4\u63D0\u9192"
|
|
1731
|
+
);
|
|
1732
|
+
const ids = toIdListText(args.personIds, "personIds");
|
|
1733
|
+
const year = resolveYear(args.year);
|
|
1734
|
+
const type = assertReportType(args.type);
|
|
1735
|
+
const serialNumber = resolveSerialNumber(args.serialNumber);
|
|
1736
|
+
const content = textField(args.content, "content") ?? defaultRemindContent(type, year, serialNumber);
|
|
1737
|
+
const token = await issueConfirmation(env, "plan.report.remind.apply", linkInfo.link, {
|
|
1738
|
+
ids,
|
|
1739
|
+
content,
|
|
1740
|
+
year,
|
|
1741
|
+
type,
|
|
1742
|
+
serialNumber
|
|
1743
|
+
});
|
|
1744
|
+
return planSuccess("plan.report.remind.prepare", {
|
|
1745
|
+
status: "AWAITING_CONFIRMATION",
|
|
1746
|
+
link: linkInfo.link,
|
|
1747
|
+
preview: {
|
|
1748
|
+
personIds: ids.split(","),
|
|
1749
|
+
targets: { year, type, serialNumber },
|
|
1750
|
+
content,
|
|
1751
|
+
messageEventCode: REMIND_MESSAGE_EVENT_CODE
|
|
1752
|
+
},
|
|
1753
|
+
continuation: token,
|
|
1754
|
+
expiresInSeconds: CONTINUATION_TTL_SECONDS
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
var planReportRemindApply = {
|
|
1759
|
+
name: "plan.report.remind.apply",
|
|
1760
|
+
resource: "plan",
|
|
1761
|
+
method: "report.remind.apply",
|
|
1762
|
+
action: "plan.report.remind.apply",
|
|
1763
|
+
summary: "\u63D0\u4EA4\u53D1\u9001\u62A5\u544A\u63D0\u4EA4\u63D0\u9192\uFF1B\u5FC5\u987B\u5728\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u8C03\u7528\uFF0C\u4E14\u8981\u6C42 prepare \u8FD4\u56DE\u7684 continuation",
|
|
1764
|
+
capability: "plan",
|
|
1765
|
+
risk: "high-risk-write",
|
|
1766
|
+
requiresConfirmation: true,
|
|
1767
|
+
inputSchema: schemaOf({
|
|
1768
|
+
confirm: { const: true },
|
|
1769
|
+
continuation: { type: "string", minLength: 1 }
|
|
1770
|
+
}, { required: ["confirm", "continuation"] }),
|
|
1771
|
+
handler: async (args, env) => {
|
|
1772
|
+
const lease = await ensureConfirmLease(args, "plan.report.remind.apply", env);
|
|
1773
|
+
const link = await assertSameLink(env.host, lease.link ?? "standard");
|
|
1774
|
+
assertLinkSupported(
|
|
1775
|
+
link,
|
|
1776
|
+
"standard",
|
|
1777
|
+
"plan.report.remind",
|
|
1778
|
+
"eb \u94FE\u8DEF\u672A\u63D0\u4F9B\u62A5\u544A\u63D0\u4EA4\u63D0\u9192\u63A5\u53E3\uFF0C\u65E0\u6CD5\u53D1\u9001\u63D0\u4EA4\u63D0\u9192"
|
|
1779
|
+
);
|
|
1780
|
+
const payload = lease.payload || {};
|
|
1781
|
+
const ids = toIdListText(payload.ids, "ids");
|
|
1782
|
+
const content = String(payload.content ?? "");
|
|
1783
|
+
const response = await sendWrite(
|
|
1784
|
+
env,
|
|
1785
|
+
"plan.report.remind.apply",
|
|
1786
|
+
{
|
|
1787
|
+
method: "POST",
|
|
1788
|
+
path: "/api/workrelate/plan/workreportmsg/send",
|
|
1789
|
+
body: { ids, content, messageEventCode: REMIND_MESSAGE_EVENT_CODE }
|
|
1790
|
+
},
|
|
1791
|
+
{
|
|
1792
|
+
message: "\u63D0\u9192\u8BF7\u6C42\u53D1\u9001\u540E\u8FDE\u63A5\u4E2D\u65AD\uFF0C\u662F\u5426\u5DF2\u53D1\u9001\u4E0D\u786E\u5B9A\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF1B\u8BF7\u8BE2\u95EE\u7528\u6237\u540E\u518D\u51B3\u5B9A\u662F\u5426\u91CD\u53D1",
|
|
1793
|
+
partialData: { ids, content },
|
|
1794
|
+
stage: "remind"
|
|
1795
|
+
}
|
|
1796
|
+
);
|
|
1797
|
+
if (!isWeaverCodeSuccess(response) || !response?.data) {
|
|
1798
|
+
throw planApiError("business_error", businessMessage(response), { stage: "remind" });
|
|
1799
|
+
}
|
|
1800
|
+
return planSuccess("plan.report.remind.apply", {
|
|
1801
|
+
link,
|
|
1802
|
+
status: "COMPLETE",
|
|
1803
|
+
personIds: ids.split(","),
|
|
1804
|
+
content
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
var planWriteOperations = [
|
|
1809
|
+
planReportCreatePrepare,
|
|
1810
|
+
planReportCreateApply,
|
|
1811
|
+
planReportUpdatePrepare,
|
|
1812
|
+
planReportUpdateApply,
|
|
1813
|
+
planReportPublishPrepare,
|
|
1814
|
+
planReportPublishApply,
|
|
1815
|
+
planReportWithdrawPrepare,
|
|
1816
|
+
planReportWithdrawApply,
|
|
1817
|
+
planReportRemindPrepare,
|
|
1818
|
+
planReportRemindApply
|
|
1819
|
+
];
|
|
1820
|
+
|
|
1821
|
+
// src/shortcuts/plan/operations/registry.ts
|
|
1822
|
+
function buildRegistry() {
|
|
1823
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1824
|
+
const definitions = [
|
|
1825
|
+
...planVersionOperations,
|
|
1826
|
+
...planReadOperations,
|
|
1827
|
+
...planWriteOperations
|
|
1828
|
+
];
|
|
1829
|
+
for (const definition of definitions) {
|
|
1830
|
+
if (registry.has(definition.name)) {
|
|
1831
|
+
throw new Error(`duplicate plan operation: ${definition.name}`);
|
|
1832
|
+
}
|
|
1833
|
+
registry.set(definition.name, definition);
|
|
1834
|
+
}
|
|
1835
|
+
return registry;
|
|
1836
|
+
}
|
|
1837
|
+
var planOperationRegistry = buildRegistry();
|
|
1838
|
+
function planOperationDefinitions() {
|
|
1839
|
+
return [...planOperationRegistry.values()];
|
|
1840
|
+
}
|
|
1841
|
+
function getPlanOperation(operation) {
|
|
1842
|
+
const definition = planOperationRegistry.get(operation);
|
|
1843
|
+
if (!definition) {
|
|
1844
|
+
throw planValidationError("operation_unknown", `\u8BA1\u5212\u62A5\u544A\u6A21\u5757\u4E0D\u652F\u6301\u64CD\u4F5C\uFF1A${operation}`);
|
|
1845
|
+
}
|
|
1846
|
+
return definition;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
// src/shortcuts/plan/manifest.ts
|
|
1850
|
+
var WITHHELD = [
|
|
1851
|
+
{
|
|
1852
|
+
name: "plan.report.withdraw.eb",
|
|
1853
|
+
reason: "eb \u94FE\u8DEF\u64A4\u56DE\u62A5\u544A\u901A\u8FC7 ESB \u52A8\u4F5C\u6D41\u300Ceb\u64A4\u56DE\u62A5\u544A\u300D\u5B9E\u73B0\uFF0C\u6E90\u8D44\u6599\u672A\u63D0\u4F9B\u52A8\u4F5C\u6D41 uniqueIndent\uFF0C\u65E0\u6CD5\u5728\u672C\u6A21\u5757\u5185\u89E6\u53D1\uFF1B\u6539\u7531 weaver-e10-customesb-execute skill \u6267\u884C\u540C\u540D\u52A8\u4F5C\u6D41"
|
|
1854
|
+
},
|
|
1855
|
+
{
|
|
1856
|
+
name: "plan.report.remind.eb",
|
|
1857
|
+
reason: "eb \u94FE\u8DEF\u62A5\u544A\u63D0\u4EA4\u63D0\u9192\u63A5\u53E3\u672A\u5728\u6E90\u8D44\u6599\u4E2D\u7ED9\u51FA\uFF0Cplan.report.remind.* \u4EC5\u652F\u6301\u6807\u51C6\u7248\u94FE\u8DEF"
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
name: "plan.comment.list.eb",
|
|
1861
|
+
reason: "eb \u94FE\u8DEF\u62A5\u544A\u8BC4\u8BBA\u63A5\u53E3\u672A\u5728\u6E90\u8D44\u6599\u4E2D\u7ED9\u51FA\uFF0Cplan.comment.list \u4EC5\u652F\u6301\u6807\u51C6\u7248\u94FE\u8DEF"
|
|
1862
|
+
}
|
|
1863
|
+
];
|
|
1864
|
+
function buildOperations() {
|
|
1865
|
+
return planOperationDefinitions().map((definition) => ({
|
|
1866
|
+
name: definition.name,
|
|
1867
|
+
resource: definition.resource,
|
|
1868
|
+
summary: definition.summary,
|
|
1869
|
+
...definition.capability ? { capability: definition.capability } : {},
|
|
1870
|
+
risk: definition.risk,
|
|
1871
|
+
...definition.requiresConfirmation ? { requiresConfirmation: true } : {},
|
|
1872
|
+
inputSchema: definition.inputSchema
|
|
1873
|
+
}));
|
|
1874
|
+
}
|
|
1875
|
+
var planManifest = {
|
|
1876
|
+
schemaVersion: 1,
|
|
1877
|
+
name: "plan",
|
|
1878
|
+
title: "\u6CDB\u5FAEE10\u8BA1\u5212\u62A5\u544A\uFF08\u62A5\u544A\u67E5\u8BE2/\u65B0\u5EFA/\u4FEE\u6539/\u53D1\u5E03/\u64A4\u56DE/\u63D0\u4EA4\u63D0\u9192/\u8BC4\u8BBA\uFF09",
|
|
1879
|
+
version: "0.1.0",
|
|
1880
|
+
host: "e10-plan",
|
|
1881
|
+
status: "builtin",
|
|
1882
|
+
sourceSkill: "weaver-e10-plan",
|
|
1883
|
+
capabilities: ["plan"],
|
|
1884
|
+
/** 报告侧接口链路路由:先读租户缓存(1 天),未命中调用 plan_searchAppver 读取 ver_name。 */
|
|
1885
|
+
linkRouting: {
|
|
1886
|
+
versionInterface: "plan_searchAppver",
|
|
1887
|
+
versionField: "ver_name",
|
|
1888
|
+
ebWhen: "V2",
|
|
1889
|
+
cacheKeyPrefix: "plan:version:",
|
|
1890
|
+
cacheTtlSeconds: 86400,
|
|
1891
|
+
ebFormTag: "uf_plan_work_report",
|
|
1892
|
+
ebAppTag: "weaver-wrplan-eb"
|
|
1893
|
+
},
|
|
1894
|
+
operations: buildOperations(),
|
|
1895
|
+
withheldOperations: WITHHELD
|
|
1896
|
+
};
|
|
1897
|
+
|
|
1898
|
+
// src/shortcuts/plan/operations.ts
|
|
1899
|
+
async function executePlanOperation(operation, rawInput, context) {
|
|
1900
|
+
const definition = getPlanOperation(operation);
|
|
1901
|
+
const input = asObject(rawInput);
|
|
1902
|
+
assertNoForbiddenKeys(input);
|
|
1903
|
+
return definition.handler(input, context);
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
// src/shortcuts/plan/index.ts
|
|
1907
|
+
function asOptions(value) {
|
|
1908
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1909
|
+
}
|
|
1910
|
+
async function readStdin() {
|
|
1911
|
+
const chunks = [];
|
|
1912
|
+
for await (const chunk of process.stdin) {
|
|
1913
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1914
|
+
}
|
|
1915
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1916
|
+
}
|
|
1917
|
+
function stripBom(value) {
|
|
1918
|
+
return value.replace(/^\uFEFF+/, "");
|
|
1919
|
+
}
|
|
1920
|
+
async function inputFrom(options, extra = {}) {
|
|
1921
|
+
const opts = asOptions(options);
|
|
1922
|
+
let input = {};
|
|
1923
|
+
if (opts.input && opts.inputJson) {
|
|
1924
|
+
throw planValidationError("input_conflict", "\u4E0D\u80FD\u540C\u65F6\u4F20 --input \u548C --input-json");
|
|
1925
|
+
}
|
|
1926
|
+
if (opts.inputJson) {
|
|
1927
|
+
input = parseJsonInput(String(opts.inputJson), "--input-json");
|
|
1928
|
+
}
|
|
1929
|
+
if (opts.input) {
|
|
1930
|
+
let raw;
|
|
1931
|
+
try {
|
|
1932
|
+
raw = stripBom(opts.input === "-" ? await readStdin() : await readFile3(String(opts.input), "utf8"));
|
|
1933
|
+
} catch {
|
|
1934
|
+
throw planValidationError("input_unreadable", `\u65E0\u6CD5\u8BFB\u53D6 --input\uFF1A${String(opts.input)}`);
|
|
1935
|
+
}
|
|
1936
|
+
input = parseJsonInput(raw, "--input");
|
|
1937
|
+
}
|
|
1938
|
+
return {
|
|
1939
|
+
...input,
|
|
1940
|
+
...Object.fromEntries(Object.entries(extra).filter(([, value]) => value !== void 0 && value !== ""))
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
function parseJsonInput(raw, label) {
|
|
1944
|
+
try {
|
|
1945
|
+
const parsed = JSON.parse(stripBom(raw));
|
|
1946
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1947
|
+
throw new Error("input must be an object");
|
|
1948
|
+
}
|
|
1949
|
+
return parsed;
|
|
1950
|
+
} catch {
|
|
1951
|
+
throw planValidationError("input_invalid", `${label} \u4E0D\u662F\u5408\u6CD5 JSON \u5BF9\u8C61`);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
function successEnvelope(operation, result) {
|
|
1955
|
+
return {
|
|
1956
|
+
schemaVersion: 1,
|
|
1957
|
+
ok: true,
|
|
1958
|
+
operation,
|
|
1959
|
+
data: result.data === void 0 ? null : result.data,
|
|
1960
|
+
...result.meta ? { meta: result.meta } : {},
|
|
1961
|
+
warnings: []
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
function failureEnvelope(error) {
|
|
1965
|
+
const structured = error;
|
|
1966
|
+
return {
|
|
1967
|
+
schemaVersion: 1,
|
|
1968
|
+
ok: false,
|
|
1969
|
+
...structured?.partialData === void 0 ? {} : { data: structured.partialData },
|
|
1970
|
+
error: toErrorEnvelope(error)
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
async function executeAndPrint(ctx, operation, input) {
|
|
1974
|
+
try {
|
|
1975
|
+
const result = await executePlanOperation(operation, input, {
|
|
1976
|
+
ctx,
|
|
1977
|
+
host: createPlanHost(ctx),
|
|
1978
|
+
continuation: createPlanContinuationSigner(ctx)
|
|
1979
|
+
});
|
|
1980
|
+
ctx.output.write(successEnvelope(operation, result), { json: true });
|
|
1981
|
+
} catch (error) {
|
|
1982
|
+
console.error(JSON.stringify(failureEnvelope(error), null, 2));
|
|
1983
|
+
process.exitCode = isCliError(error) ? error.exitCode : 1 /* GeneralError */;
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
var planShortcut = {
|
|
1987
|
+
name: "plan",
|
|
1988
|
+
description: "\u6CDB\u5FAEE10\u8BA1\u5212\u62A5\u544A CLI\uFF08\u67E5\u8BE2/\u65B0\u5EFA/\u4FEE\u6539/\u53D1\u5E03/\u64A4\u56DE/\u63D0\u4EA4\u63D0\u9192/\u8BC4\u8BBA\uFF09",
|
|
1989
|
+
category: "shortcut",
|
|
1990
|
+
register({ program, action }) {
|
|
1991
|
+
const plan = program.command("plan").description("\u6CDB\u5FAEE10\u8BA1\u5212\u62A5\u544A\uFF08\u62A5\u544A\u8BE6\u60C5/\u5217\u8868/\u65B0\u5EFA/\u4FEE\u6539/\u53D1\u5E03/\u64A4\u56DE/\u63D0\u4EA4\u63D0\u9192/\u8BC4\u8BBA\uFF09");
|
|
1992
|
+
plan.command("schema").description("Print plan operation manifest for agents").action(action((ctx) => {
|
|
1993
|
+
ctx.output.write(planManifest, { json: true });
|
|
1994
|
+
}));
|
|
1995
|
+
plan.command("run").description("Run a plan operation with JSON input").argument("<operation>", "operation name, e.g. plan.report.get").option("--input <path>", "JSON input file, or - for stdin").option("--input-json <json>", "inline JSON input object").action(action(async (ctx, operation, options) => {
|
|
1996
|
+
await executeAndPrint(ctx, String(operation), await inputFrom(options));
|
|
1997
|
+
}));
|
|
1998
|
+
plan.command("route").description("\u5224\u5B9A\u5F53\u524D\u79DF\u6237\u62A5\u544A\u63A5\u53E3\u94FE\u8DEF\uFF08plan.version.check \u8584\u5305\u88C5\uFF09").option("--refresh", "\u5FFD\u7565 1 \u5929\u79DF\u6237\u7F13\u5B58\uFF0C\u5F3A\u5236\u91CD\u65B0\u5224\u5B9A").action(action(async (ctx, options) => {
|
|
1999
|
+
const opts = asOptions(options);
|
|
2000
|
+
await executeAndPrint(ctx, "plan.version.check", opts.refresh ? { refresh: true } : {});
|
|
2001
|
+
}));
|
|
2002
|
+
plan.command("get").description("\u67E5\u8BE2\u5355\u4EFD\u62A5\u544A\u8BE6\u60C5\uFF08plan.report.get \u8584\u5305\u88C5\uFF09").option("--input <path>", "JSON input file, or - for stdin").option("--input-json <json>", "inline JSON input object").option("--id <id>", "\u62A5\u544A id").option("--year <year>", "\u62A5\u544A\u5E74\u4EFD").option("--type <type>", "\u62A5\u544A\u7C7B\u578B\uFF1Aweek/month/season/halfYear/year").option("--serial-number <n>", "\u62A5\u544A\u5468\u671F").option("--creator-user-id <id>", "\u62A5\u544A\u521B\u5EFA\u4EBA id").action(action(async (ctx, options) => {
|
|
2003
|
+
const opts = asOptions(options);
|
|
2004
|
+
await executeAndPrint(ctx, "plan.report.get", await inputFrom(options, {
|
|
2005
|
+
id: opts.id,
|
|
2006
|
+
year: opts.year,
|
|
2007
|
+
type: opts.type,
|
|
2008
|
+
serialNumber: opts.serialNumber,
|
|
2009
|
+
creatorUserId: opts.creatorUserId
|
|
2010
|
+
}));
|
|
2011
|
+
}));
|
|
2012
|
+
plan.command("list").description("\u5206\u9875\u67E5\u8BE2\u62A5\u544A\u5217\u8868\uFF08plan.report.page \u8584\u5305\u88C5\uFF09").option("--input <path>", "JSON input file, or - for stdin").option("--input-json <json>", "inline JSON input object").option("--page-no <n>", "\u9875\u7801").option("--page-size <n>", "\u6BCF\u9875\u6761\u6570").action(action(async (ctx, options) => {
|
|
2013
|
+
const opts = asOptions(options);
|
|
2014
|
+
await executeAndPrint(ctx, "plan.report.page", await inputFrom(options, {
|
|
2015
|
+
pageNo: opts.pageNo,
|
|
2016
|
+
pageSize: opts.pageSize
|
|
2017
|
+
}));
|
|
2018
|
+
}));
|
|
2019
|
+
}
|
|
2020
|
+
};
|
|
2021
|
+
export {
|
|
2022
|
+
inputFrom,
|
|
2023
|
+
planShortcut,
|
|
2024
|
+
successEnvelope
|
|
2025
|
+
};
|