weaver-work-cli 0.1.8 → 0.1.21
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/README.md +25 -17
- package/dist/cmd/action.js +76 -0
- package/dist/cmd/index.js +2 -0
- package/dist/cmd/refs/index.js +103 -0
- package/dist/cmd/register.js +31 -0
- package/dist/cmd/root.js +1 -0
- package/dist/cmd/setup/index.js +25 -5
- package/dist/cmd/skills/index.js +37 -5
- package/dist/core/connector.js +54 -0
- package/dist/core/context.js +2 -1
- package/dist/core/input.js +48 -0
- package/dist/core/output.js +298 -3
- package/dist/core/refs.js +435 -0
- package/dist/core/state.js +26 -0
- package/dist/internal/e10/auth/commands.js +34 -19
- package/dist/internal/e10/auth/session.js +74 -2
- package/dist/internal/e10/auth/xiaoe.js +359 -94
- package/dist/internal/e10/context.js +18 -6
- package/dist/internal/e10/request-runtime.js +8 -1
- package/dist/internal/skills/install.js +148 -28
- package/dist/internal/skills/reader.js +12 -9
- package/dist/shortcuts/blog/continuation.js +74 -0
- package/dist/shortcuts/blog/errors.js +60 -0
- package/dist/shortcuts/blog/host.js +175 -0
- package/dist/shortcuts/blog/index.js +324 -0
- package/dist/shortcuts/blog/manifest.js +415 -0
- package/dist/shortcuts/blog/operations/comment.js +125 -0
- package/dist/shortcuts/blog/operations/comments.js +31 -0
- package/dist/shortcuts/blog/operations/edit.js +131 -0
- package/dist/shortcuts/blog/operations/export.js +46 -0
- package/dist/shortcuts/blog/operations/like.js +80 -0
- package/dist/shortcuts/blog/operations/publish.js +157 -0
- package/dist/shortcuts/blog/operations/query-user.js +58 -0
- package/dist/shortcuts/blog/operations/query.js +96 -0
- package/dist/shortcuts/blog/operations/registry.js +54 -0
- package/dist/shortcuts/blog/operations/remind.js +176 -0
- package/dist/shortcuts/blog/operations/shared.js +330 -0
- package/dist/shortcuts/blog/operations/types.js +16 -0
- package/dist/shortcuts/blog/operations.js +9 -0
- package/dist/shortcuts/caizhilian/continuation.js +70 -0
- package/dist/shortcuts/caizhilian/errors.js +53 -0
- package/dist/shortcuts/caizhilian/host.js +190 -0
- package/dist/shortcuts/caizhilian/index.js +186 -0
- package/dist/shortcuts/caizhilian/manifest.js +42 -0
- package/dist/shortcuts/caizhilian/operations/api.js +801 -0
- package/dist/shortcuts/caizhilian/operations/confirm.js +75 -0
- package/dist/shortcuts/caizhilian/operations/files.js +306 -0
- package/dist/shortcuts/caizhilian/operations/form.js +170 -0
- package/dist/shortcuts/caizhilian/operations/handlers/collab.js +611 -0
- package/dist/shortcuts/caizhilian/operations/handlers/document.js +890 -0
- package/dist/shortcuts/caizhilian/operations/handlers/file-collection.js +1227 -0
- package/dist/shortcuts/caizhilian/operations/handlers/file-upload.js +192 -0
- package/dist/shortcuts/caizhilian/operations/handlers/fileops.js +570 -0
- package/dist/shortcuts/caizhilian/operations/handlers/folder.js +1024 -0
- package/dist/shortcuts/caizhilian/operations/handlers/search.js +318 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-attach.js +294 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-backup.js +423 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-encrypt.js +238 -0
- package/dist/shortcuts/caizhilian/operations/handlers/setting-storage.js +364 -0
- package/dist/shortcuts/caizhilian/operations/handlers/system.js +106 -0
- package/dist/shortcuts/caizhilian/operations/registry.js +151 -0
- package/dist/shortcuts/caizhilian/operations/shared.js +408 -0
- package/dist/shortcuts/caizhilian/operations/specs.js +698 -0
- package/dist/shortcuts/caizhilian/operations/types.js +57 -0
- package/dist/shortcuts/caizhilian/operations.js +21 -0
- package/dist/shortcuts/contract/continuation.js +70 -0
- package/dist/shortcuts/contract/errors.js +62 -0
- package/dist/shortcuts/contract/host.js +205 -0
- package/dist/shortcuts/contract/index.js +318 -0
- package/dist/shortcuts/contract/manifest.js +596 -0
- package/dist/shortcuts/contract/operations/clause-reference.js +78 -0
- package/dist/shortcuts/contract/operations/form-info.js +371 -0
- package/dist/shortcuts/contract/operations/read.js +118 -0
- package/dist/shortcuts/contract/operations/registry.js +43 -0
- package/dist/shortcuts/contract/operations/request.js +300 -0
- package/dist/shortcuts/contract/operations/shared.js +133 -0
- package/dist/shortcuts/contract/operations/subject.js +157 -0
- package/dist/shortcuts/contract/operations/template.js +81 -0
- package/dist/shortcuts/contract/operations/types.js +7 -0
- package/dist/shortcuts/contract/operations/workflow.js +52 -0
- package/dist/shortcuts/contract/operations/write.js +131 -0
- package/dist/shortcuts/contract/operations.js +8 -0
- package/dist/shortcuts/hrm/index.js +83 -2
- package/dist/shortcuts/hrm/manifest.js +16 -9
- package/dist/shortcuts/hrm/operations/employee.js +160 -30
- package/dist/shortcuts/hrm/operations/org.js +17 -3
- package/dist/shortcuts/hrm/operations/position.js +18 -2
- package/dist/shortcuts/hrm/operations/registry.js +2 -0
- package/dist/shortcuts/hrm/operations/resolve.js +449 -0
- package/dist/shortcuts/index.js +5 -1
- package/dist/shortcuts/invoice/index.js +74 -36
- package/dist/shortcuts/invoice/manifest.js +674 -4
- package/dist/shortcuts/invoice/markdown.js +172 -0
- package/dist/shortcuts/invoice/operations/add.js +3 -3
- package/dist/shortcuts/invoice/operations/delete.js +2 -2
- package/dist/shortcuts/invoice/operations/get.js +10 -2
- package/dist/shortcuts/invoice/operations/import.js +2 -2
- package/dist/shortcuts/invoice/operations/registry.js +8 -1
- package/dist/shortcuts/invoice/operations/reim-auto.js +719 -0
- package/dist/shortcuts/invoice/operations/reim.js +85 -2
- package/dist/shortcuts/invoice/operations/shared.js +75 -8
- package/dist/shortcuts/invoice/operations/update.js +2 -2
- package/dist/shortcuts/invoice/operations/upload-and-validate.js +93 -0
- package/dist/shortcuts/invoice/operations/validate-preview.js +2 -1
- package/dist/shortcuts/invoice/projection.js +328 -0
- package/dist/shortcuts/meeting/host.js +18 -1
- package/dist/shortcuts/meeting/manifest.js +30 -18
- package/dist/shortcuts/meeting/operations/eb/catalog.js +390 -0
- package/dist/shortcuts/meeting/operations/eb/conflict.js +389 -0
- package/dist/shortcuts/meeting/operations/eb/factory.js +389 -0
- package/dist/shortcuts/meeting/operations/eb/index.js +22 -0
- package/dist/shortcuts/meeting/operations/env.js +8 -1
- package/dist/shortcuts/meeting/operations/registry.js +2 -0
- package/dist/shortcuts/meeting/operations/signs.js +216 -2
- package/dist/shortcuts/workflow/endpoints.js +2 -1
- package/dist/shortcuts/workflow/errors.js +8 -2
- package/dist/shortcuts/workflow/host.js +11 -4
- package/dist/shortcuts/workflow/operations/form.js +1016 -590
- package/dist/shortcuts/workflow/operations/read.js +913 -231
- package/dist/shortcuts/workflow/operations/shared.js +21 -0
- package/dist/shortcuts/workflow/operations/write.js +750 -52
- package/dist/shortcuts/workflow/operations.js +36 -10
- package/docs/_catalog.md +6 -0
- package/docs/agent-invoice.md +5 -1
- package/docs/agent-io-channel-design.md +468 -0
- package/docs/agent-skill-install.md +9 -4
- package/docs/blog.md +123 -0
- package/docs/caizhilian.md +304 -0
- package/docs/contract.md +91 -0
- package/docs/e10-auth.md +4 -2
- package/docs/hrm.md +53 -11
- package/docs/invoice.md +5 -1
- package/docs/meeting.md +1 -1
- package/docs/operation-manual.md +15 -3
- package/docs/skill-review-2026-09-19.md +2 -2
- package/package.json +1 -1
- package/scripts/package-skill.mjs +32 -20
- package/scripts/xiaoe_env.py +118 -0
- package/skill-template/business-info.json +113 -14
- package/skill-template/domains/blog.md +24 -0
- package/skill-template/domains/caizhilian.md +22 -0
- package/skill-template/domains/hrm.md +2 -1
- package/skill-template/domains/jinchengda.md +23 -0
- package/skill-template/domains/meeting.md +1 -1
- package/skill-template/domains/workflow.md +1 -1
- package/skill-template/skill-template.md +1 -1
- package/skills/weaver-e10-blog/SKILL.md +111 -0
- package/skills/weaver-e10-blog/references/blog-comment.md +51 -0
- package/skills/weaver-e10-blog/references/blog-comments.md +39 -0
- package/skills/weaver-e10-blog/references/blog-default-permission.md +38 -0
- package/skills/weaver-e10-blog/references/blog-disabled-capabilities.md +11 -0
- package/skills/weaver-e10-blog/references/blog-edit.md +51 -0
- package/skills/weaver-e10-blog/references/blog-export.md +42 -0
- package/skills/weaver-e10-blog/references/blog-like.md +50 -0
- package/skills/weaver-e10-blog/references/blog-publish.md +52 -0
- package/skills/weaver-e10-blog/references/blog-query-user.md +45 -0
- package/skills/weaver-e10-blog/references/blog-query.md +49 -0
- package/skills/weaver-e10-blog/references/blog-remind.md +51 -0
- package/skills/weaver-e10-blog/references/blog-resolve-users.md +38 -0
- package/skills/weaver-e10-blog/references/source-manifest.json +1540 -0
- package/skills/weaver-e10-caizhilian/SKILL.md +217 -0
- package/skills/weaver-e10-caizhilian/references/agent-entry.md +106 -0
- package/skills/weaver-e10-caizhilian/references/collaboration.md +112 -0
- package/skills/weaver-e10-caizhilian/references/document.md +111 -0
- package/skills/weaver-e10-caizhilian/references/file-collection.md +173 -0
- package/skills/weaver-e10-caizhilian/references/file-upload.md +309 -0
- package/skills/weaver-e10-caizhilian/references/files.md +120 -0
- package/skills/weaver-e10-caizhilian/references/folder.md +122 -0
- package/skills/weaver-e10-caizhilian/references/org-browser.md +104 -0
- package/skills/weaver-e10-caizhilian/references/setting-attach.md +440 -0
- package/skills/weaver-e10-caizhilian/references/setting-backup.md +372 -0
- package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +399 -0
- package/skills/weaver-e10-caizhilian/references/setting-storage.md +603 -0
- package/skills/weaver-e10-caizhilian/references/source-manifest.json +5694 -0
- package/skills/weaver-e10-caizhilian/references/withheld.md +93 -0
- package/skills/weaver-e10-caizhilian/references/write-protocol.md +120 -0
- package/skills/weaver-e10-calendar/SKILL.md +4 -3
- package/skills/weaver-e10-ebuilder-form/SKILL.md +4 -9
- package/skills/weaver-e10-ebuilder-form/references/context-routing.md +0 -9
- package/skills/weaver-e10-ebuilder-form/references/custom-api.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/fields-browser.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/list-nlist.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/openapi-read.md +1 -5
- package/skills/weaver-e10-ebuilder-form/references/openapi-write.md +1 -5
- package/skills/weaver-e10-esb/SKILL.md +2 -2
- package/skills/weaver-e10-esb/references/source-manifest.json +9 -9
- package/skills/weaver-e10-hrm/SKILL.md +104 -9
- package/skills/weaver-e10-hrm/references/employee.md +89 -15
- package/skills/weaver-e10-hrm/references/org.md +114 -5
- package/skills/weaver-e10-hrm/references/position.md +14 -7
- package/skills/weaver-e10-hrm/references/source-manifest.json +1 -1
- package/skills/weaver-e10-jinchengda/SKILL.md +167 -0
- package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +82 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +69 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +78 -0
- package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +27 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-status.md +71 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +94 -0
- package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +89 -0
- package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +77 -0
- package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +66 -0
- package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +94 -0
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +259 -0
- package/skills/weaver-e10-jiuchuanhui/SKILL.md +5 -11
- package/skills/weaver-e10-jucailin/SKILL.md +4 -3
- package/skills/weaver-e10-mail/SKILL.md +4 -11
- package/skills/weaver-e10-meeting/SKILL.md +66 -32
- package/skills/weaver-e10-meeting/references/meeting-change.md +5 -2
- package/skills/weaver-e10-meeting/references/meeting-create.md +2 -1
- package/skills/weaver-e10-meeting/references/meeting-eb.md +114 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +9 -8
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +35 -7
- package/skills/weaver-e10-meeting/references/meeting-update.md +1 -1
- package/skills/weaver-e10-okr/SKILL.md +6 -11
- package/skills/weaver-e10-okr/references/source-manifest.json +3 -3
- package/skills/weaver-e10-plan/SKILL.md +3 -3
- package/skills/weaver-e10-plan/references/plan-collect-and-compose.md +1 -1
- package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +1 -1
- package/skills/weaver-e10-plan/references/source-manifest.json +13 -13
- package/skills/weaver-e10-qiyecheng/SKILL.md +4 -10
- package/skills/weaver-e10-qiyecheng/references/source-manifest.json +9 -9
- package/skills/weaver-e10-shared/SKILL.md +42 -34
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +16 -43
- package/skills/weaver-e10-shared/references/json-output-contract.md +20 -11
- package/skills/weaver-e10-shared/references/non-interactive-environment.md +21 -14
- package/skills/weaver-e10-shijingran/SKILL.md +2 -1
- package/skills/weaver-e10-shijingran/references/source-manifest.json +9 -9
- package/skills/weaver-e10-skill-maker/SKILL.md +4 -10
- package/skills/weaver-e10-skill-maker/references/business-skill-generation.md +5 -3
- package/skills/weaver-e10-skill-maker/references/module-cli-generation.md +12 -27
- package/skills/weaver-e10-skill-maker/references/module-gap-audit-and-repair.md +17 -5
- package/skills/weaver-e10-skill-maker/references/source-update-detection.md +4 -27
- package/skills/weaver-e10-skill-maker/references/weaver-skill-style.md +1 -1
- package/skills/weaver-e10-wenshuding/SKILL.md +5 -16
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +7 -7
- package/skills/weaver-e10-workflow/SKILL.md +41 -46
- package/skills/weaver-e10-workflow/references/source-manifest.json +39 -75
- package/skills/weaver-e10-workflow/references/workflow-batch.md +90 -29
- package/skills/weaver-e10-workflow/references/workflow-create.md +83 -109
- package/skills/weaver-e10-workflow/references/workflow-memory.md +19 -9
- package/skills/weaver-e10-workflow/references/workflow-operate.md +2 -2
- package/skills/weaver-e10-workflow/references/workflow-query.md +40 -27
- package/skills/weaver-e10-workflow/references/workflow-share.md +18 -2
- package/skills/weaver-e10-workflow/references/workflow-view.md +3 -4
- package/skills/weaver-e10-yepiaotong/SKILL.md +74 -39
- package/skills/weaver-e10-yepiaotong/references/invoice-detail.md +22 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +3 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-output-view.md +135 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +15 -3
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +1 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-summarize.py +217 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-upload-and-validate.md +88 -0
- package/skills/weaver-e10-yepiaotong/references/invoice-validation-preview.md +7 -2
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +89 -9
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +1 -0
- package/skills/weaver-e10-yepiaotong/references/reim-expense-subject-rules.md +70 -49
- package/skills/weaver-e10-yepiaotong/references/reim-fast-path.md +119 -0
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +55 -36
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +4 -0
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +149 -0
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +125 -5
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +430 -63
- package/skills/weaver-e10-yimiaoban/SKILL.md +4 -12
- package/skills/weaver-e10-yimiaoban/references/source-manifest.json +3 -3
- package/skills/weaver-e10-ziguanjia/SKILL.md +2 -1
- package/skills/weaver-e10-ziguanjia/references/ziguanjia-agent-entry.md +3 -3
- package/tools/weaver-skill-detector-1.0.13/SKILL.md +9 -9
- package/tools/weaver-skill-detector-1.0.13/references/checklist.md +3 -3
- package/tools/weaver-skill-detector-1.0.13/scripts/__pycache__/validate_skill.cpython-313.pyc +0 -0
- package/tools/weaver-skill-detector-1.0.13/scripts/validate_skill.py +98 -91
- package/scripts/sync-connector-skills.mjs +0 -172
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { ContractCliError, contractPartialError, contractPolicyError, contractValidationError } from '../errors.js';
|
|
2
|
+
import { ContractReadOperation, projectRequestLog, projectRequestStatus } from './read.js';
|
|
3
|
+
import { asObject, maskText, objectFingerprint, requireId } from './shared.js';
|
|
4
|
+
import { ContractWriteApplyOperation, ContractWritePrepareOperation } from './write.js';
|
|
5
|
+
const STATUS_PATH = '/api/workflow/core/paService/v1/getRequestStatus';
|
|
6
|
+
/** flowStatus.code:0 草稿、1 审批中、2 已退回、3 正常归档、4 强制结束、5 已作废、6 待提交、7 暂停、8 撤销 */
|
|
7
|
+
const EDITABLE_CODES = new Set([0, 2, 6]);
|
|
8
|
+
const TERMINAL_CODES = new Set([3, 4, 5, 8]);
|
|
9
|
+
async function readStatus(requestId, host) {
|
|
10
|
+
const value = await host.contractRequest({
|
|
11
|
+
method: 'GET',
|
|
12
|
+
path: STATUS_PATH,
|
|
13
|
+
userIdField: 'userid',
|
|
14
|
+
query: { requestId },
|
|
15
|
+
});
|
|
16
|
+
const data = (value?.data ?? {});
|
|
17
|
+
const info = (data.workflowBaseInfo ?? {});
|
|
18
|
+
const flowStatus = (info.flowStatus ?? {});
|
|
19
|
+
return {
|
|
20
|
+
requestId: info.requestId === undefined ? undefined : String(info.requestId),
|
|
21
|
+
workflowId: info.workflowId === undefined ? undefined : String(info.workflowId),
|
|
22
|
+
requestName: info.requestName,
|
|
23
|
+
status: info.status ?? data.status,
|
|
24
|
+
code: flowStatus.code === undefined ? undefined : Number(flowStatus.code),
|
|
25
|
+
desc: flowStatus.desc,
|
|
26
|
+
currentNodeType: data.currentNodeType,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function assertEditable(snapshot, action) {
|
|
30
|
+
if (snapshot.code === undefined)
|
|
31
|
+
return;
|
|
32
|
+
if (EDITABLE_CODES.has(snapshot.code))
|
|
33
|
+
return;
|
|
34
|
+
if (snapshot.code === 1) {
|
|
35
|
+
throw contractPolicyError('already_submitted', `流程已处于审批中,不能${action};如需修改请先撤回/退回`);
|
|
36
|
+
}
|
|
37
|
+
if (TERMINAL_CODES.has(snapshot.code)) {
|
|
38
|
+
throw contractPolicyError('request_closed', `流程已结束(${snapshot.desc ?? snapshot.code}),不能${action}`);
|
|
39
|
+
}
|
|
40
|
+
throw contractPolicyError('request_not_editable', `流程当前状态(${snapshot.desc ?? snapshot.code})不允许${action}`);
|
|
41
|
+
}
|
|
42
|
+
function requireCreateFields(input) {
|
|
43
|
+
const body = { workflowId: requireId(input.workflowId, 'workflowId') };
|
|
44
|
+
if (input.requestname !== undefined)
|
|
45
|
+
body.requestname = String(input.requestname);
|
|
46
|
+
if (input.remark !== undefined)
|
|
47
|
+
body.remark = String(input.remark);
|
|
48
|
+
if (input.isnextflow !== undefined)
|
|
49
|
+
body.isnextflow = Number(input.isnextflow);
|
|
50
|
+
if (input.isVerifyFormRequired !== undefined)
|
|
51
|
+
body.isVerifyFormRequired = input.isVerifyFormRequired === true;
|
|
52
|
+
if (input.requestLevel !== undefined)
|
|
53
|
+
body.requestLevel = Number(input.requestLevel);
|
|
54
|
+
if (input.formData !== undefined)
|
|
55
|
+
body.formData = asObject(input.formData, 'formData');
|
|
56
|
+
if (input.isNewFormData !== undefined)
|
|
57
|
+
body.isNewFormData = input.isNewFormData === true;
|
|
58
|
+
if (input.seniorFormParam !== undefined)
|
|
59
|
+
body.seniorFormParam = asObject(input.seniorFormParam, 'seniorFormParam');
|
|
60
|
+
return body;
|
|
61
|
+
}
|
|
62
|
+
const REQUEST_CREATE_SPEC = {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
path: '/api/workflow/core/paService/v2/doCreateRequest',
|
|
65
|
+
userIdField: 'userid',
|
|
66
|
+
defaults: { isnextflow: 0, requestLevel: 0, isVerifyFormRequired: false },
|
|
67
|
+
body: requireCreateFields,
|
|
68
|
+
fingerprint: (input) => objectFingerprint({
|
|
69
|
+
workflowId: input.workflowId,
|
|
70
|
+
requestname: input.requestname ?? null,
|
|
71
|
+
remark: input.remark ?? null,
|
|
72
|
+
formData: input.formData ?? null,
|
|
73
|
+
}),
|
|
74
|
+
preview: (input) => ({
|
|
75
|
+
action: '创建合同审批流程实例',
|
|
76
|
+
path: '/api/workflow/core/paService/v2/doCreateRequest',
|
|
77
|
+
workflowId: maskText(input.workflowId),
|
|
78
|
+
requestname: input.requestname,
|
|
79
|
+
fieldCount: input.formData === undefined ? 0 : Object.keys(asObject(input.formData, 'formData')).length,
|
|
80
|
+
}),
|
|
81
|
+
async readback(result, _input, host) {
|
|
82
|
+
const requestId = result?.message?.requestId ?? result?.requestId;
|
|
83
|
+
if (!requestId) {
|
|
84
|
+
throw contractPartialError('创建流程接口返回成功但未给出 requestId,结果不确定,禁止自动重试', { result }, { stage: 'readback' });
|
|
85
|
+
}
|
|
86
|
+
const snapshot = await readStatus(String(requestId), host);
|
|
87
|
+
if (snapshot.requestId && snapshot.requestId !== String(requestId)) {
|
|
88
|
+
throw contractPartialError('创建流程后回读的实例 ID 与写入结果不一致,结果不确定', {
|
|
89
|
+
requestId: String(requestId),
|
|
90
|
+
readback: snapshot,
|
|
91
|
+
}, { stage: 'readback' });
|
|
92
|
+
}
|
|
93
|
+
return { requestId: String(requestId), flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
function requireSaveFields(input) {
|
|
97
|
+
const formData = asObject(input.formData, 'formData');
|
|
98
|
+
if (!Array.isArray(formData.dataDetails) || !formData.dataDetails.length) {
|
|
99
|
+
throw contractValidationError('form_data_invalid', 'formData.dataDetails 必须是非空数组');
|
|
100
|
+
}
|
|
101
|
+
const body = {
|
|
102
|
+
requestId: requireId(input.requestId, 'requestId'),
|
|
103
|
+
formData: {
|
|
104
|
+
...(formData.formId === undefined ? {} : { formId: String(formData.formId) }),
|
|
105
|
+
...(formData.module === undefined ? {} : { module: String(formData.module) }),
|
|
106
|
+
dataDetails: formData.dataDetails,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
if (input.workflowId !== undefined)
|
|
110
|
+
body.workflowId = requireId(input.workflowId, 'workflowId');
|
|
111
|
+
if (input.userCurrentNodeId !== undefined)
|
|
112
|
+
body.userCurrentNodeId = requireId(input.userCurrentNodeId, 'userCurrentNodeId');
|
|
113
|
+
if (input.isNewFormData !== undefined)
|
|
114
|
+
body.isNewFormData = input.isNewFormData === true;
|
|
115
|
+
if (input.seniorFormParam !== undefined)
|
|
116
|
+
body.seniorFormParam = asObject(input.seniorFormParam, 'seniorFormParam');
|
|
117
|
+
return body;
|
|
118
|
+
}
|
|
119
|
+
const REQUEST_SAVE_SPEC = {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
path: '/api/workflow/core/paService/v1/saveFormData',
|
|
122
|
+
userIdField: 'userid',
|
|
123
|
+
body: requireSaveFields,
|
|
124
|
+
fingerprint: (input) => objectFingerprint({
|
|
125
|
+
requestId: input.requestId,
|
|
126
|
+
formData: input.formData,
|
|
127
|
+
}),
|
|
128
|
+
preview: (input) => ({
|
|
129
|
+
action: '保存流程表单数据',
|
|
130
|
+
path: '/api/workflow/core/paService/v1/saveFormData',
|
|
131
|
+
requestId: maskText(input.requestId),
|
|
132
|
+
detailCount: Array.isArray(input.formData?.dataDetails)
|
|
133
|
+
? input.formData.dataDetails.length
|
|
134
|
+
: 0,
|
|
135
|
+
}),
|
|
136
|
+
async precheck(input, host) {
|
|
137
|
+
const snapshot = await readStatus(requireId(input.requestId, 'requestId'), host);
|
|
138
|
+
assertEditable(snapshot, '保存表单');
|
|
139
|
+
return { flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
140
|
+
},
|
|
141
|
+
async readback(_result, input, host) {
|
|
142
|
+
const snapshot = await readStatus(requireId(input.requestId, 'requestId'), host);
|
|
143
|
+
return { requestId: snapshot.requestId, flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
const REQUEST_SUBMIT_SPEC = {
|
|
147
|
+
method: 'POST',
|
|
148
|
+
path: '/api/workflow/core/paService/v1/submitRequest',
|
|
149
|
+
userIdField: 'userid',
|
|
150
|
+
defaults: { isVerifyFormRequired: true },
|
|
151
|
+
body: (input) => {
|
|
152
|
+
const body = { requestId: requireId(input.requestId, 'requestId') };
|
|
153
|
+
if (input.remark !== undefined)
|
|
154
|
+
body.remark = String(input.remark);
|
|
155
|
+
if (input.userCurrentNodeId !== undefined)
|
|
156
|
+
body.userCurrentNodeId = requireId(input.userCurrentNodeId, 'userCurrentNodeId');
|
|
157
|
+
if (input.requestName !== undefined)
|
|
158
|
+
body.requestName = String(input.requestName);
|
|
159
|
+
if (input.formdata !== undefined)
|
|
160
|
+
body.formdata = asObject(input.formdata, 'formdata');
|
|
161
|
+
if (input.otherParams !== undefined)
|
|
162
|
+
body.otherParams = String(input.otherParams);
|
|
163
|
+
if (input.isVerifyFormRequired !== undefined)
|
|
164
|
+
body.isVerifyFormRequired = input.isVerifyFormRequired === true;
|
|
165
|
+
return body;
|
|
166
|
+
},
|
|
167
|
+
fingerprint: (input) => objectFingerprint({
|
|
168
|
+
requestId: input.requestId,
|
|
169
|
+
remark: input.remark ?? null,
|
|
170
|
+
requestName: input.requestName ?? null,
|
|
171
|
+
}),
|
|
172
|
+
preview: (input) => ({
|
|
173
|
+
action: '提交合同审批(流程将进入审批流转,不可撤回)',
|
|
174
|
+
path: '/api/workflow/core/paService/v1/submitRequest',
|
|
175
|
+
requestId: maskText(input.requestId),
|
|
176
|
+
requestName: input.requestName,
|
|
177
|
+
secondConfirmation: true,
|
|
178
|
+
}),
|
|
179
|
+
async precheck(input, host) {
|
|
180
|
+
const snapshot = await readStatus(requireId(input.requestId, 'requestId'), host);
|
|
181
|
+
assertEditable(snapshot, '提交审批');
|
|
182
|
+
return { flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
183
|
+
},
|
|
184
|
+
mapError(error) {
|
|
185
|
+
if (error.subtype !== 'business_error')
|
|
186
|
+
return undefined;
|
|
187
|
+
const code = String(error.code ?? '');
|
|
188
|
+
if (code === '1200301') {
|
|
189
|
+
return new ContractCliError('authentication', 'session_expired', '提交返回 1200301(当前 userid 为空),请检查 E10 登录态', {
|
|
190
|
+
code,
|
|
191
|
+
retryable: false,
|
|
192
|
+
details: { hint: '不要自动切换接口或盲目重试;先运行 weaver-work-cli auth status 确认会话' },
|
|
193
|
+
exitCode: 3,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (code === '1200306') {
|
|
197
|
+
return new ContractCliError('api', 'missing_required_fields', '提交返回 1200306(服务端必填校验未通过)', {
|
|
198
|
+
code,
|
|
199
|
+
retryable: false,
|
|
200
|
+
details: { hint: '解析缺失字段列表并逐字段补全后重试(最多 3 轮),不要切换接口' },
|
|
201
|
+
exitCode: 1,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
},
|
|
206
|
+
async readback(result, input, host) {
|
|
207
|
+
const snapshot = await readStatus(requireId(input.requestId, 'requestId'), host);
|
|
208
|
+
if (snapshot.code !== 1 && snapshot.code !== 3) {
|
|
209
|
+
throw contractPartialError('提交接口已返回成功,但回读流程状态不是审批中(1)或已归档(3),结果不确定', {
|
|
210
|
+
result,
|
|
211
|
+
flowStatus: { code: snapshot.code, desc: snapshot.desc },
|
|
212
|
+
}, { stage: 'readback' });
|
|
213
|
+
}
|
|
214
|
+
return { requestId: snapshot.requestId, flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
const REMINDER_KEYS = ['currentOperator', 'doneOperator', 'submitOperator', 'ccOperator', 'otherReminder'];
|
|
218
|
+
function requireSuperviseFields(input) {
|
|
219
|
+
const otherParam = asObject(input.otherParam, 'otherParam');
|
|
220
|
+
if (!REMINDER_KEYS.some((key) => otherParam[key] !== undefined)) {
|
|
221
|
+
throw contractValidationError('other_param_invalid', 'otherParam 必须至少包含 currentOperator、doneOperator、submitOperator、ccOperator、otherReminder 之一');
|
|
222
|
+
}
|
|
223
|
+
const body = { requestId: requireId(input.requestId, 'requestId'), otherParam };
|
|
224
|
+
if (input.remark !== undefined)
|
|
225
|
+
body.remark = String(input.remark);
|
|
226
|
+
return body;
|
|
227
|
+
}
|
|
228
|
+
const REQUEST_SUPERVISE_SPEC = {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
path: '/api/workflow/core/paService/v1/requestSupervise',
|
|
231
|
+
userIdField: 'userId',
|
|
232
|
+
body: requireSuperviseFields,
|
|
233
|
+
validate: (input) => {
|
|
234
|
+
requireSuperviseFields(input);
|
|
235
|
+
},
|
|
236
|
+
fingerprint: (input) => objectFingerprint({
|
|
237
|
+
requestId: input.requestId,
|
|
238
|
+
otherParam: input.otherParam,
|
|
239
|
+
remark: input.remark ?? null,
|
|
240
|
+
}),
|
|
241
|
+
preview: (input) => {
|
|
242
|
+
const otherParam = asObject(input.otherParam, 'otherParam');
|
|
243
|
+
return {
|
|
244
|
+
action: '催办(会向真实接收人发送通知)',
|
|
245
|
+
path: '/api/workflow/core/paService/v1/requestSupervise',
|
|
246
|
+
requestId: maskText(input.requestId),
|
|
247
|
+
targets: REMINDER_KEYS.filter((key) => otherParam[key] !== undefined),
|
|
248
|
+
otherReminder: otherParam.otherReminder === undefined ? undefined : maskText(otherParam.otherReminder),
|
|
249
|
+
secondConfirmation: true,
|
|
250
|
+
};
|
|
251
|
+
},
|
|
252
|
+
async precheck(input, host) {
|
|
253
|
+
const snapshot = await readStatus(requireId(input.requestId, 'requestId'), host);
|
|
254
|
+
if (snapshot.code !== 1) {
|
|
255
|
+
throw contractPolicyError('not_in_approval', `只有审批中(1)的流程可以催办,当前状态为 ${snapshot.desc ?? snapshot.code}`);
|
|
256
|
+
}
|
|
257
|
+
return { flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
258
|
+
},
|
|
259
|
+
async readback(_result, input, host) {
|
|
260
|
+
const snapshot = await readStatus(requireId(input.requestId, 'requestId'), host);
|
|
261
|
+
return { requestId: snapshot.requestId, flowStatus: { code: snapshot.code, desc: snapshot.desc } };
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
export const contractRequestStatusOperation = new ContractReadOperation('contract.request.status', {
|
|
265
|
+
method: 'GET',
|
|
266
|
+
path: STATUS_PATH,
|
|
267
|
+
userIdField: 'userid',
|
|
268
|
+
query: (input) => ({ requestId: requireId(input.requestId, 'requestId') }),
|
|
269
|
+
shape: projectRequestStatus,
|
|
270
|
+
});
|
|
271
|
+
export const contractRequestLogOperation = new ContractReadOperation('contract.request.log', {
|
|
272
|
+
method: 'GET',
|
|
273
|
+
path: '/api/workflow/core/paService/v1/getRequestLog',
|
|
274
|
+
userIdField: 'userid',
|
|
275
|
+
query: (input) => ({
|
|
276
|
+
requestId: requireId(input.requestId, 'requestId'),
|
|
277
|
+
...(input.otherParams === undefined ? {} : { otherParams: String(input.otherParams) }),
|
|
278
|
+
}),
|
|
279
|
+
shape: projectRequestLog,
|
|
280
|
+
});
|
|
281
|
+
export const contractRequestCreatePrepareOperation = new ContractWritePrepareOperation('contract.request.create.prepare', 'contract.request.create.apply', REQUEST_CREATE_SPEC);
|
|
282
|
+
export const contractRequestCreateApplyOperation = new ContractWriteApplyOperation('contract.request.create.apply', REQUEST_CREATE_SPEC);
|
|
283
|
+
export const contractRequestSavePrepareOperation = new ContractWritePrepareOperation('contract.request.save.prepare', 'contract.request.save.apply', REQUEST_SAVE_SPEC);
|
|
284
|
+
export const contractRequestSaveApplyOperation = new ContractWriteApplyOperation('contract.request.save.apply', REQUEST_SAVE_SPEC);
|
|
285
|
+
export const contractRequestSubmitPrepareOperation = new ContractWritePrepareOperation('contract.request.submit.prepare', 'contract.request.submit.apply', REQUEST_SUBMIT_SPEC);
|
|
286
|
+
export const contractRequestSubmitApplyOperation = new ContractWriteApplyOperation('contract.request.submit.apply', REQUEST_SUBMIT_SPEC);
|
|
287
|
+
export const contractRequestSupervisePrepareOperation = new ContractWritePrepareOperation('contract.request.supervise.prepare', 'contract.request.supervise.apply', REQUEST_SUPERVISE_SPEC);
|
|
288
|
+
export const contractRequestSuperviseApplyOperation = new ContractWriteApplyOperation('contract.request.supervise.apply', REQUEST_SUPERVISE_SPEC);
|
|
289
|
+
export const contractRequestOperations = [
|
|
290
|
+
contractRequestStatusOperation,
|
|
291
|
+
contractRequestLogOperation,
|
|
292
|
+
contractRequestCreatePrepareOperation,
|
|
293
|
+
contractRequestCreateApplyOperation,
|
|
294
|
+
contractRequestSavePrepareOperation,
|
|
295
|
+
contractRequestSaveApplyOperation,
|
|
296
|
+
contractRequestSubmitPrepareOperation,
|
|
297
|
+
contractRequestSubmitApplyOperation,
|
|
298
|
+
contractRequestSupervisePrepareOperation,
|
|
299
|
+
contractRequestSuperviseApplyOperation,
|
|
300
|
+
];
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { contractValidationError } from '../errors.js';
|
|
3
|
+
const FORBIDDEN_INPUT_KEYS = new Set([
|
|
4
|
+
'access_token',
|
|
5
|
+
'app_key',
|
|
6
|
+
'app_secret',
|
|
7
|
+
'cookie',
|
|
8
|
+
'eteamsid',
|
|
9
|
+
'token',
|
|
10
|
+
'userid',
|
|
11
|
+
'userId',
|
|
12
|
+
'sedit',
|
|
13
|
+
'dubboFlag',
|
|
14
|
+
'dubboToken',
|
|
15
|
+
'skipFlag',
|
|
16
|
+
]);
|
|
17
|
+
const FORBIDDEN_NORMALIZED_KEYS = new Set([...FORBIDDEN_INPUT_KEYS].map((key) => key.toLowerCase()));
|
|
18
|
+
const ID_PATTERN = /^[1-9]\d*$/u;
|
|
19
|
+
export function asObject(value, name = '业务输入') {
|
|
20
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
21
|
+
throw contractValidationError('input_invalid', `${name}必须是 JSON 对象`);
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
export function assertNoForbiddenKeys(value, location = 'input') {
|
|
26
|
+
if (!value || typeof value !== 'object')
|
|
27
|
+
return;
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
value.forEach((item, index) => assertNoForbiddenKeys(item, `${location}[${index}]`));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const [key, child] of Object.entries(value)) {
|
|
33
|
+
if (key.toLowerCase() === 'userid' && location === 'input') {
|
|
34
|
+
throw contractValidationError('field_forbidden', 'userid 由 CLI 从 E10 会话注入,禁止业务输入携带');
|
|
35
|
+
}
|
|
36
|
+
if (FORBIDDEN_INPUT_KEYS.has(key) || FORBIDDEN_NORMALIZED_KEYS.has(key.toLowerCase())) {
|
|
37
|
+
throw contractValidationError('field_forbidden', `禁止业务输入字段:${location}.${key}`);
|
|
38
|
+
}
|
|
39
|
+
assertNoForbiddenKeys(child, `${location}.${key}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function requireId(value, name) {
|
|
43
|
+
if (typeof value !== 'string' || !ID_PATTERN.test(value)) {
|
|
44
|
+
throw contractValidationError('id_invalid', `${name} 必须是正整数文本 ID(环境相关 ID 只能运行时解析)`);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
export function optionalId(value, name) {
|
|
49
|
+
if (value === undefined || value === null || value === '')
|
|
50
|
+
return undefined;
|
|
51
|
+
return requireId(value, name);
|
|
52
|
+
}
|
|
53
|
+
export function requireNonEmptyString(value, name, maxLength = 500) {
|
|
54
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
55
|
+
throw contractValidationError('input_invalid', `${name} 必须是非空字符串`);
|
|
56
|
+
}
|
|
57
|
+
if (value.length > maxLength) {
|
|
58
|
+
throw contractValidationError('input_invalid', `${name} 不能超过 ${maxLength} 个字符`);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
function canonicalJson(value) {
|
|
63
|
+
if (Array.isArray(value))
|
|
64
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
65
|
+
if (value && typeof value === 'object') {
|
|
66
|
+
return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(',')}}`;
|
|
67
|
+
}
|
|
68
|
+
return JSON.stringify(value);
|
|
69
|
+
}
|
|
70
|
+
export function objectFingerprint(value) {
|
|
71
|
+
return createHash('sha256').update(canonicalJson(value)).digest('hex');
|
|
72
|
+
}
|
|
73
|
+
export function sessionMatches(lease, session) {
|
|
74
|
+
return lease.baseUrl === session.baseUrl && lease.profile === session.profile && lease.userId === session.userId;
|
|
75
|
+
}
|
|
76
|
+
export function maskText(value, keep = 3) {
|
|
77
|
+
const text = String(value ?? '');
|
|
78
|
+
if (!text)
|
|
79
|
+
return '';
|
|
80
|
+
if (text.length <= keep)
|
|
81
|
+
return `${text.charAt(0)}***`;
|
|
82
|
+
return `${text.slice(0, keep)}***(${text.length})`;
|
|
83
|
+
}
|
|
84
|
+
export function maskSummary(input, keys) {
|
|
85
|
+
const summary = {};
|
|
86
|
+
for (const key of keys) {
|
|
87
|
+
if (input[key] === undefined)
|
|
88
|
+
continue;
|
|
89
|
+
summary[key] = maskText(input[key]);
|
|
90
|
+
}
|
|
91
|
+
return summary;
|
|
92
|
+
}
|
|
93
|
+
export function pickKeys(value, keys) {
|
|
94
|
+
const result = {};
|
|
95
|
+
if (!value)
|
|
96
|
+
return result;
|
|
97
|
+
for (const key of keys) {
|
|
98
|
+
if (value[key] !== undefined)
|
|
99
|
+
result[key] = value[key];
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
export function dropKeys(value, keys) {
|
|
104
|
+
if (!value || typeof value !== 'object')
|
|
105
|
+
return value;
|
|
106
|
+
if (Array.isArray(value))
|
|
107
|
+
return value.map((item) => dropKeys(item, keys));
|
|
108
|
+
const result = {};
|
|
109
|
+
for (const [key, child] of Object.entries(value)) {
|
|
110
|
+
if (keys.includes(key))
|
|
111
|
+
continue;
|
|
112
|
+
result[key] = dropKeys(child, keys);
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
export function queryFrom(input, keys) {
|
|
117
|
+
const query = {};
|
|
118
|
+
for (const key of keys) {
|
|
119
|
+
if (input[key] === undefined || input[key] === null || input[key] === '')
|
|
120
|
+
continue;
|
|
121
|
+
query[key] = input[key];
|
|
122
|
+
}
|
|
123
|
+
return query;
|
|
124
|
+
}
|
|
125
|
+
export function bodyFrom(input, keys, extra = {}) {
|
|
126
|
+
const body = { ...extra };
|
|
127
|
+
for (const key of keys) {
|
|
128
|
+
if (input[key] === undefined || input[key] === null || input[key] === '')
|
|
129
|
+
continue;
|
|
130
|
+
body[key] = input[key];
|
|
131
|
+
}
|
|
132
|
+
return body;
|
|
133
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { contractPartialError, contractPolicyError } from '../errors.js';
|
|
2
|
+
import { ContractReadOperation, projectSubjects } from './read.js';
|
|
3
|
+
import { asObject, maskText, objectFingerprint, requireId, requireNonEmptyString } from './shared.js';
|
|
4
|
+
import { ContractWriteApplyOperation, ContractWritePrepareOperation } from './write.js';
|
|
5
|
+
export const contractSubjectAppOperation = new ContractReadOperation('contract.subject.app', {
|
|
6
|
+
method: 'GET',
|
|
7
|
+
path: '/api/bs/ebuilder/app/tags/getAppIds',
|
|
8
|
+
defaults: { tag: '合同管理' },
|
|
9
|
+
query: (input) => ({ tag: input.tag === undefined ? '合同管理' : requireNonEmptyString(input.tag, '应用 Tag') }),
|
|
10
|
+
shape: (value) => ({ code: value.code, msg: value.msg, appIds: value.data }),
|
|
11
|
+
});
|
|
12
|
+
export const contractSubjectFormOperation = new ContractReadOperation('contract.subject.form', {
|
|
13
|
+
method: 'GET',
|
|
14
|
+
path: '/api/ebuilder/form/obj/getObjsByTag',
|
|
15
|
+
query: (input) => ({
|
|
16
|
+
tag: requireNonEmptyString(input.tag, '表单 Tag'),
|
|
17
|
+
appId: requireId(input.appId, 'appId'),
|
|
18
|
+
}),
|
|
19
|
+
shape: projectSubjects,
|
|
20
|
+
});
|
|
21
|
+
export const contractSubjectFieldsOperation = new ContractReadOperation('contract.subject.fields', {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
path: '/api/ebuilder/common/ds/fields',
|
|
24
|
+
defaults: { detailFieldsGroup: true, enableMerge: true, customParam: '{"terminal":""}', params: '[]' },
|
|
25
|
+
form: (input) => ({
|
|
26
|
+
groupId: requireId(input.appId, 'appId'),
|
|
27
|
+
sourceId: requireId(input.objId, 'objId'),
|
|
28
|
+
sourceType: 'FORM',
|
|
29
|
+
detailFieldsGroup: String(input.detailFieldsGroup ?? true),
|
|
30
|
+
enableMerge: String(input.enableMerge ?? true),
|
|
31
|
+
customParam: input.customParam === undefined ? '{"terminal":""}' : String(input.customParam),
|
|
32
|
+
params: input.params === undefined ? '[]' : String(input.params),
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
export const contractSubjectOptionsOperation = new ContractReadOperation('contract.subject.options', {
|
|
36
|
+
method: 'GET',
|
|
37
|
+
path: '/api/ebuilder/common/ds/options',
|
|
38
|
+
query: (input) => ({
|
|
39
|
+
groupId: requireId(input.appId, 'appId'),
|
|
40
|
+
objId: requireId(input.objId, 'objId'),
|
|
41
|
+
sourceType: 'FORM',
|
|
42
|
+
fieldName: requireId(input.fieldName, 'fieldName'),
|
|
43
|
+
}),
|
|
44
|
+
});
|
|
45
|
+
export const contractSubjectQueryOperation = new ContractReadOperation('contract.subject.query', {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
path: '/api/ebuilder/form/dataset/v2/getAllData',
|
|
48
|
+
body: (input) => {
|
|
49
|
+
const objId = requireId(input.objId, 'objId');
|
|
50
|
+
const datajson = { header: { objId } };
|
|
51
|
+
if (input.mainTable !== undefined)
|
|
52
|
+
datajson.mainTable = asObject(input.mainTable, 'mainTable');
|
|
53
|
+
const pageInfo = {};
|
|
54
|
+
if (input.pageNo !== undefined)
|
|
55
|
+
pageInfo.pageNo = Number(input.pageNo);
|
|
56
|
+
if (input.pageSize !== undefined)
|
|
57
|
+
pageInfo.pageSize = Number(input.pageSize);
|
|
58
|
+
if (Object.keys(pageInfo).length)
|
|
59
|
+
datajson.pageInfo = pageInfo;
|
|
60
|
+
const isReturnDetail = input.isReturnDetail === undefined ? 'n' : String(input.isReturnDetail);
|
|
61
|
+
datajson.operationinfo = { isReturnDetail };
|
|
62
|
+
return { datajson };
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
function maskObject(value) {
|
|
66
|
+
const result = {};
|
|
67
|
+
for (const [key, child] of Object.entries(value)) {
|
|
68
|
+
result[key] = child && typeof child === 'object' ? maskObject(child) : maskText(child);
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
function subjectCreateBody(input) {
|
|
73
|
+
const objId = requireId(input.objId, 'objId');
|
|
74
|
+
const mainTable = asObject(input.mainTable, 'mainTable');
|
|
75
|
+
if (!Object.keys(mainTable).length) {
|
|
76
|
+
throw contractPolicyError('empty_main_table', '新建签约主体必须提供至少一个主表字段');
|
|
77
|
+
}
|
|
78
|
+
const record = { mainTable };
|
|
79
|
+
if (input.details !== undefined) {
|
|
80
|
+
const details = asObject(input.details, 'details');
|
|
81
|
+
for (const [key, value] of Object.entries(details))
|
|
82
|
+
record[key] = value;
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
datajson: {
|
|
86
|
+
header: { objId },
|
|
87
|
+
datas: [record],
|
|
88
|
+
operationinfo: {
|
|
89
|
+
fieldNoFindIgnore: input.fieldNoFindIgnore === undefined ? 'true' : String(input.fieldNoFindIgnore),
|
|
90
|
+
doAction: input.doAction === undefined ? 'false' : String(input.doAction),
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const SUBJECT_CREATE_SPEC = {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
path: '/api/ebuilder/form/dataset/v2/saveFormData',
|
|
98
|
+
body: subjectCreateBody,
|
|
99
|
+
fingerprint: (input) => objectFingerprint({
|
|
100
|
+
objId: input.objId,
|
|
101
|
+
mainTable: input.mainTable,
|
|
102
|
+
details: input.details ?? null,
|
|
103
|
+
}),
|
|
104
|
+
preview: (input) => ({
|
|
105
|
+
action: '新建签约主体',
|
|
106
|
+
path: '/api/ebuilder/form/dataset/v2/saveFormData',
|
|
107
|
+
objId: input.objId,
|
|
108
|
+
fieldCount: Object.keys(asObject(input.mainTable, 'mainTable')).length,
|
|
109
|
+
fields: maskObject(asObject(input.mainTable, 'mainTable')),
|
|
110
|
+
}),
|
|
111
|
+
async precheck(input, host) {
|
|
112
|
+
const verify = input.verify;
|
|
113
|
+
if (!verify)
|
|
114
|
+
return { duplicated: false, checked: false };
|
|
115
|
+
const spec = asObject(verify, 'verify');
|
|
116
|
+
const field = requireNonEmptyString(spec.field, 'verify.field');
|
|
117
|
+
const value = String(spec.value ?? '');
|
|
118
|
+
const result = await host.contractRequest({
|
|
119
|
+
method: 'POST',
|
|
120
|
+
path: '/api/ebuilder/form/dataset/v2/getAllData',
|
|
121
|
+
body: {
|
|
122
|
+
datajson: {
|
|
123
|
+
header: { objId: requireId(input.objId, 'objId') },
|
|
124
|
+
mainTable: { [field]: value },
|
|
125
|
+
pageInfo: { pageNo: 1, pageSize: 10 },
|
|
126
|
+
operationinfo: { isReturnDetail: 'n' },
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
const rows = Array.isArray(result?.data?.datajson?.data) ? result.data.datajson.data : [];
|
|
131
|
+
if (rows.length) {
|
|
132
|
+
throw contractPolicyError('already_exists', `字段 ${field} 已存在 ${rows.length} 条签约主体记录,禁止重复新建;请先确认是否复用已有记录`, { field, count: rows.length });
|
|
133
|
+
}
|
|
134
|
+
return { duplicated: false, checked: true, field };
|
|
135
|
+
},
|
|
136
|
+
async readback(result) {
|
|
137
|
+
const payload = (result?.data?.datajson ?? {});
|
|
138
|
+
const dataIds = Array.isArray(payload.dataIds) ? payload.dataIds : [];
|
|
139
|
+
if (payload.status !== true || !dataIds.length) {
|
|
140
|
+
throw contractPartialError('新建接口返回成功但未给出 dataIds,结果不确定,请用查询接口确认是否已创建', {
|
|
141
|
+
result,
|
|
142
|
+
}, { stage: 'readback' });
|
|
143
|
+
}
|
|
144
|
+
return { dataIds, count: dataIds.length };
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
export const contractSubjectCreatePrepareOperation = new ContractWritePrepareOperation('contract.subject.create.prepare', 'contract.subject.create.apply', SUBJECT_CREATE_SPEC);
|
|
148
|
+
export const contractSubjectCreateApplyOperation = new ContractWriteApplyOperation('contract.subject.create.apply', SUBJECT_CREATE_SPEC);
|
|
149
|
+
export const contractSubjectOperations = [
|
|
150
|
+
contractSubjectAppOperation,
|
|
151
|
+
contractSubjectFormOperation,
|
|
152
|
+
contractSubjectFieldsOperation,
|
|
153
|
+
contractSubjectOptionsOperation,
|
|
154
|
+
contractSubjectQueryOperation,
|
|
155
|
+
contractSubjectCreatePrepareOperation,
|
|
156
|
+
contractSubjectCreateApplyOperation,
|
|
157
|
+
];
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ContractReadOperation } from './read.js';
|
|
2
|
+
import { queryFrom, requireId } from './shared.js';
|
|
3
|
+
export const contractTypeTreeOperation = new ContractReadOperation('contract.type.tree', {
|
|
4
|
+
method: 'GET',
|
|
5
|
+
path: '/api/ebd/contract/type/allTypes',
|
|
6
|
+
shape: (value) => ({ code: value.code, msg: value.msg, types: value.data }),
|
|
7
|
+
});
|
|
8
|
+
export const contractTemplateTreeOperation = new ContractReadOperation('contract.template.tree', {
|
|
9
|
+
method: 'GET',
|
|
10
|
+
path: '/api/ebd/contract/tpltree/queryList',
|
|
11
|
+
query: (input) => queryFrom(input, ['treeName', 'parentId', 'treeType', 'isSystem', 'useType', 'appId']),
|
|
12
|
+
});
|
|
13
|
+
export const contractTemplateListOperation = new ContractReadOperation('contract.template.list', {
|
|
14
|
+
method: 'GET',
|
|
15
|
+
path: '/api/ebd/contract/tplinfo/getListPage',
|
|
16
|
+
defaults: { pageNo: 1, pageSize: 10 },
|
|
17
|
+
query: (input) => queryFrom(input, [
|
|
18
|
+
'templateName', 'templateDesc', 'belongId', 'contractType', 'templateStatus', 'source',
|
|
19
|
+
'sourceType', 'templateVersion', 'operateType', 'useType', 'code', 'appId', 'formId',
|
|
20
|
+
'orgId', 'belongSub', 'outTime', 'pageNo', 'pageSize',
|
|
21
|
+
]),
|
|
22
|
+
});
|
|
23
|
+
export const contractTemplateDetailOperation = new ContractReadOperation('contract.template.detail', {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
path: '/api/ebd/contract/tplinfo/getById',
|
|
26
|
+
query: (input) => ({ id: requireId(input.id, '模板 id') }),
|
|
27
|
+
});
|
|
28
|
+
export const contractClauseTreeOperation = new ContractReadOperation('contract.clause.tree', {
|
|
29
|
+
method: 'GET',
|
|
30
|
+
path: '/api/ebd/contract/tree/queryList',
|
|
31
|
+
shape: (value) => ({ code: value.code, msg: value.msg, tree: value.data }),
|
|
32
|
+
});
|
|
33
|
+
export const contractClauseListOperation = new ContractReadOperation('contract.clause.list', {
|
|
34
|
+
method: 'GET',
|
|
35
|
+
path: '/api/ebd/contract/clauseinfo/getListPage',
|
|
36
|
+
defaults: { pageNo: 1, pageSize: 10 },
|
|
37
|
+
query: (input) => queryFrom(input, [
|
|
38
|
+
'belongId', 'clauseName', 'clauseNum', 'clauseStatus', 'clauseGroup',
|
|
39
|
+
'contractType', 'clauseVersion', 'orgId', 'belongSub', 'pageNo', 'pageSize',
|
|
40
|
+
]),
|
|
41
|
+
});
|
|
42
|
+
export const contractClauseGroupListOperation = new ContractReadOperation('contract.clause.group.list', {
|
|
43
|
+
method: 'GET',
|
|
44
|
+
path: '/api/ebd/contract/clausegroup/getListPage',
|
|
45
|
+
defaults: { pageNo: 1, pageSize: 10 },
|
|
46
|
+
query: (input) => queryFrom(input, [
|
|
47
|
+
'belongId', 'clauseName', 'clauseNum', 'clauseStatus', 'contractType', 'pageNo', 'pageSize',
|
|
48
|
+
]),
|
|
49
|
+
});
|
|
50
|
+
export const contractClauseSearchOperation = new ContractReadOperation('contract.clause.search', {
|
|
51
|
+
method: 'GET',
|
|
52
|
+
path: '/api/ebd/contract/clauseinfo/getClauses',
|
|
53
|
+
defaults: { pageNum: 0, pageSize: 10 },
|
|
54
|
+
query: (input) => queryFrom(input, ['id', 'title', 'tagId', 'content', 'group', 'mark', 'pageNum', 'pageSize']),
|
|
55
|
+
});
|
|
56
|
+
export const contractClauseTagsOperation = new ContractReadOperation('contract.clause.tags', {
|
|
57
|
+
method: 'GET',
|
|
58
|
+
path: '/api/ebd/contract/clauseinfo/getClausesConfig',
|
|
59
|
+
defaults: { pageNum: 0, pageSize: 10 },
|
|
60
|
+
query: (input) => queryFrom(input, ['label', 'value', 'pageNum', 'pageSize']),
|
|
61
|
+
});
|
|
62
|
+
export const contractClauseReferenceGetOperation = new ContractReadOperation('contract.clause.reference.get', {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
path: '/api/ebd/contract/clauseReference/selectData',
|
|
65
|
+
defaults: { referenceObjType: 1 },
|
|
66
|
+
body: (input) => queryFrom(input, [
|
|
67
|
+
'fileId', 'requestId', 'clauseId', 'referenceObjType', 'startTime', 'endTime', 'pageNum', 'pageSize',
|
|
68
|
+
]),
|
|
69
|
+
});
|
|
70
|
+
export const contractTemplateOperations = [
|
|
71
|
+
contractTypeTreeOperation,
|
|
72
|
+
contractTemplateTreeOperation,
|
|
73
|
+
contractTemplateListOperation,
|
|
74
|
+
contractTemplateDetailOperation,
|
|
75
|
+
contractClauseTreeOperation,
|
|
76
|
+
contractClauseListOperation,
|
|
77
|
+
contractClauseGroupListOperation,
|
|
78
|
+
contractClauseSearchOperation,
|
|
79
|
+
contractClauseTagsOperation,
|
|
80
|
+
contractClauseReferenceGetOperation,
|
|
81
|
+
];
|