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,1227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* caizhilian.file-collection — 文件采集(FTP/SFTP)
|
|
3
|
+
*
|
|
4
|
+
* 覆盖文件采集的完整生命周期:
|
|
5
|
+
* - 任务列表/详情/保存/删除/另存为/开关切换
|
|
6
|
+
* - 全宗 ID 更新(归档分支)
|
|
7
|
+
* - 连接器查询/创建、FTP 资源创建
|
|
8
|
+
* - 动作流搜索/检测/创建/启用/绑定
|
|
9
|
+
* - 扫描/运行/取消、等待完成、结果归一化
|
|
10
|
+
*
|
|
11
|
+
* 接口:
|
|
12
|
+
* - 列任务:GET /api/file/coll/taskTable
|
|
13
|
+
* - 读表单:GET /api/file/coll/taskForm
|
|
14
|
+
* - 保存任务:POST /api/file/coll/save
|
|
15
|
+
* - 另存为:POST /api/file/coll/saveAs
|
|
16
|
+
* - 切换开关:POST /api/file/coll/switch
|
|
17
|
+
* - 检查存储:GET /api/file/coll/checkStorageConnect
|
|
18
|
+
* - 扫描:POST /api/file/coll/scan
|
|
19
|
+
* - 扫描进度:GET /api/file/coll/scan/progress
|
|
20
|
+
* - 运行/暂停:POST /api/file/coll/run
|
|
21
|
+
* - 运行进度:GET /api/file/coll/run/progress
|
|
22
|
+
* - 详情:GET /api/file/coll/detailTable
|
|
23
|
+
* - 取消:POST /api/file/coll/cancel
|
|
24
|
+
* - 删除:POST /api/file/coll/delete
|
|
25
|
+
* - 连接器列表:GET /api/bs/esb/setting/connector/getConnectorListPage
|
|
26
|
+
* - 资源列表:GET /api/bs/esb/setting/resource/getResourceListPage
|
|
27
|
+
* - 创建连接器:POST /api/bs/esb/setting/systemPool/save
|
|
28
|
+
* - 创建 FTP 资源:POST /api/bs/esb/setting/resource/ftp/save
|
|
29
|
+
* - 动作流列表:POST /api/bs/esb/setting/application/getApplicationListPage
|
|
30
|
+
* - 动作流详情:GET /api/bs/esb/setting/application/getAppById/{id}
|
|
31
|
+
* - 动作流版本:GET /api/bs/esb/setting/application/version/versionList/{id}
|
|
32
|
+
* - 动作流设计:GET /api/bs/esb/setting/flow/design/getDesignBySceneId/{id}
|
|
33
|
+
* - 创建动作流:POST /api/bs/esb/setting/application/save
|
|
34
|
+
* - 注册变量:POST /api/bs/esb/setting/application/variable/addVariable
|
|
35
|
+
* - 校验设计:POST /api/bs/esb/setting/flow/design/check
|
|
36
|
+
* - 保存设计:POST /api/bs/esb/setting/flow/design/saveDesign
|
|
37
|
+
* - 启用动作流:GET /api/bs/esb/setting/application/startUseApp/{id}
|
|
38
|
+
*/
|
|
39
|
+
import { CaizhilianCliError } from '../../errors.js';
|
|
40
|
+
import { caizhilianSuccess } from '../types.js';
|
|
41
|
+
import { requireId, requireNonEmpty } from '../shared.js';
|
|
42
|
+
const ACTION = 'caizhilian.file-collection';
|
|
43
|
+
// ── 接口路径 ──────────────────────────────────────────────
|
|
44
|
+
const LIST_TASKS_PATH = '/api/file/coll/taskTable';
|
|
45
|
+
const GET_TASK_FORM_PATH = '/api/file/coll/taskForm';
|
|
46
|
+
const SAVE_TASK_PATH = '/api/file/coll/save';
|
|
47
|
+
const SAVE_AS_TASK_PATH = '/api/file/coll/saveAs';
|
|
48
|
+
const CHECK_STORAGE_PATH = '/api/file/coll/checkStorageConnect';
|
|
49
|
+
const SCAN_PATH = '/api/file/coll/scan';
|
|
50
|
+
const SCAN_PROGRESS_PATH = '/api/file/coll/scan/progress';
|
|
51
|
+
const RUN_PATH = '/api/file/coll/run';
|
|
52
|
+
const RUN_PROGRESS_PATH = '/api/file/coll/run/progress';
|
|
53
|
+
const DETAIL_TABLE_PATH = '/api/file/coll/detailTable';
|
|
54
|
+
const CANCEL_PATH = '/api/file/coll/cancel';
|
|
55
|
+
const DELETE_PATH = '/api/file/coll/delete';
|
|
56
|
+
const SWITCH_PATH = '/api/file/coll/switch';
|
|
57
|
+
const SAVE_AS_PATH = '/api/file/coll/saveAs';
|
|
58
|
+
const CONNECTOR_LIST_PATH = '/api/bs/esb/setting/connector/getConnectorListPage';
|
|
59
|
+
const RESOURCE_LIST_PATH = '/api/bs/esb/setting/resource/getResourceListPage';
|
|
60
|
+
const SYSTEM_POOL_SAVE_PATH = '/api/bs/esb/setting/systemPool/save';
|
|
61
|
+
const FTP_RESOURCE_SAVE_PATH = '/api/bs/esb/setting/resource/ftp/save';
|
|
62
|
+
const APP_LIST_PATH = '/api/bs/esb/setting/application/getApplicationListPage';
|
|
63
|
+
const APP_DETAIL_PATH = '/api/bs/esb/setting/application/getAppById';
|
|
64
|
+
const APP_VERSION_PATH = '/api/bs/esb/setting/application/version/versionList';
|
|
65
|
+
const DESIGN_BY_SCENE_PATH = '/api/bs/esb/setting/flow/design/getDesignBySceneId';
|
|
66
|
+
const APP_SAVE_PATH = '/api/bs/esb/setting/application/save';
|
|
67
|
+
const APP_VARIABLE_PATH = '/api/bs/esb/setting/application/variable/addVariable';
|
|
68
|
+
const DESIGN_CHECK_PATH = '/api/bs/esb/setting/flow/design/check';
|
|
69
|
+
const DESIGN_SAVE_PATH = '/api/bs/esb/setting/flow/design/saveDesign';
|
|
70
|
+
const APP_ENABLE_PATH = '/api/bs/esb/setting/application/startUseApp';
|
|
71
|
+
// ── 辅助函数 ──────────────────────────────────────────────
|
|
72
|
+
function asRecord(value) {
|
|
73
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
74
|
+
}
|
|
75
|
+
function asList(value) {
|
|
76
|
+
return Array.isArray(value) ? value : [];
|
|
77
|
+
}
|
|
78
|
+
function isPlainObject(value) {
|
|
79
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
80
|
+
}
|
|
81
|
+
// ── 列出采集任务 ──────────────────────────────────────────
|
|
82
|
+
async function listTasks(args, env) {
|
|
83
|
+
const response = await env.host.request({
|
|
84
|
+
method: 'GET',
|
|
85
|
+
path: LIST_TASKS_PATH,
|
|
86
|
+
operation: ACTION,
|
|
87
|
+
});
|
|
88
|
+
const data = asRecord(response);
|
|
89
|
+
if (!data.status && !data.success) {
|
|
90
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询采集任务失败'), {
|
|
91
|
+
code: data.code ?? data.status,
|
|
92
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询采集任务失败') },
|
|
93
|
+
exitCode: 1,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const result = asRecord(data.data);
|
|
97
|
+
const tasks = asList(result.data || result).map((item) => ({
|
|
98
|
+
id: item.id,
|
|
99
|
+
name: item.taskName || '',
|
|
100
|
+
status: item.status || '',
|
|
101
|
+
source_type: item.sourceType || '',
|
|
102
|
+
create_time: item.createTime || '',
|
|
103
|
+
}));
|
|
104
|
+
return caizhilianSuccess(ACTION, {
|
|
105
|
+
tasks,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// ── 获取采集任务详情 ──────────────────────────────────────
|
|
109
|
+
async function getTaskForm(args, env) {
|
|
110
|
+
const taskId = args.id ? requireId(args.id, 'id') : '';
|
|
111
|
+
const url = taskId ? `${GET_TASK_FORM_PATH}?id=${taskId}` : GET_TASK_FORM_PATH;
|
|
112
|
+
const response = await env.host.request({
|
|
113
|
+
method: 'GET',
|
|
114
|
+
path: url,
|
|
115
|
+
operation: ACTION,
|
|
116
|
+
});
|
|
117
|
+
const data = asRecord(response);
|
|
118
|
+
if (!data.status && !data.success) {
|
|
119
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询采集任务失败'), {
|
|
120
|
+
code: data.code ?? data.status,
|
|
121
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询采集任务失败') },
|
|
122
|
+
exitCode: 1,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const result = asRecord(data.data);
|
|
126
|
+
return caizhilianSuccess(ACTION, {
|
|
127
|
+
form: result,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// ── 检查存储连接 ──────────────────────────────────────────
|
|
131
|
+
async function checkStorage(args, env) {
|
|
132
|
+
const response = await env.host.request({
|
|
133
|
+
method: 'GET',
|
|
134
|
+
path: CHECK_STORAGE_PATH,
|
|
135
|
+
operation: ACTION,
|
|
136
|
+
});
|
|
137
|
+
const data = asRecord(response);
|
|
138
|
+
const connected = data.data ?? data.status ?? data.success;
|
|
139
|
+
return caizhilianSuccess(ACTION, {
|
|
140
|
+
connected: !!connected,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// ── 扫描(prepare/apply)──────────────────────────────────────
|
|
144
|
+
async function scanPrepare(args, env) {
|
|
145
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
146
|
+
const fullColl = args.full_coll ?? false;
|
|
147
|
+
// 签发 continuation(键名与 targetKeys 保持一致,均为 snake_case)
|
|
148
|
+
const continuation = await env.continuation.issue({
|
|
149
|
+
operation: 'caizhilian.file-collection.scan.apply',
|
|
150
|
+
task_id: taskId,
|
|
151
|
+
full_coll: fullColl,
|
|
152
|
+
});
|
|
153
|
+
return caizhilianSuccess('caizhilian.file-collection.scan.prepare', {
|
|
154
|
+
task_id: taskId,
|
|
155
|
+
full_coll: fullColl,
|
|
156
|
+
continuation,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async function scanApply(args, env, lease) {
|
|
160
|
+
const taskId = lease.task_id;
|
|
161
|
+
const fullColl = lease.full_coll;
|
|
162
|
+
const response = await env.host.request({
|
|
163
|
+
method: 'POST',
|
|
164
|
+
path: SCAN_PATH,
|
|
165
|
+
body: { taskId, fullColl },
|
|
166
|
+
operation: 'caizhilian.file-collection.scan.apply',
|
|
167
|
+
});
|
|
168
|
+
const data = asRecord(response);
|
|
169
|
+
if (!data.status && !data.success) {
|
|
170
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '扫描失败'), {
|
|
171
|
+
code: data.code ?? data.status,
|
|
172
|
+
details: { action: 'caizhilian.file-collection.scan.apply', message: String(data.msg || data.message || '扫描失败') },
|
|
173
|
+
exitCode: 1,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
const result = asRecord(data.data);
|
|
177
|
+
return caizhilianSuccess('caizhilian.file-collection.scan.apply', {
|
|
178
|
+
runtime_id: result.runtimeId || result.id || '',
|
|
179
|
+
status: result.status || '',
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// ── 扫描进度 ──────────────────────────────────────────────
|
|
183
|
+
async function scanProgress(args, env) {
|
|
184
|
+
const response = await env.host.request({
|
|
185
|
+
method: 'GET',
|
|
186
|
+
path: SCAN_PROGRESS_PATH,
|
|
187
|
+
operation: ACTION,
|
|
188
|
+
});
|
|
189
|
+
const data = asRecord(response);
|
|
190
|
+
if (!data.status && !data.success) {
|
|
191
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询扫描进度失败'), {
|
|
192
|
+
code: data.code ?? data.status,
|
|
193
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询扫描进度失败') },
|
|
194
|
+
exitCode: 1,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const result = asRecord(data.data);
|
|
198
|
+
return caizhilianSuccess(ACTION, {
|
|
199
|
+
progress: result,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// ── 运行/暂停(prepare/apply)──────────────────────────────────────
|
|
203
|
+
async function runPrepare(args, env) {
|
|
204
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
205
|
+
const action = args.action || 'run';
|
|
206
|
+
// 签发 continuation(键名与 targetKeys 保持一致,均为 snake_case)
|
|
207
|
+
const continuation = await env.continuation.issue({
|
|
208
|
+
operation: 'caizhilian.file-collection.run.apply',
|
|
209
|
+
task_id: taskId,
|
|
210
|
+
action,
|
|
211
|
+
});
|
|
212
|
+
return caizhilianSuccess('caizhilian.file-collection.run.prepare', {
|
|
213
|
+
task_id: taskId,
|
|
214
|
+
action,
|
|
215
|
+
continuation,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
async function runApply(args, env, lease) {
|
|
219
|
+
const taskId = lease.task_id;
|
|
220
|
+
const action = lease.action;
|
|
221
|
+
const response = await env.host.request({
|
|
222
|
+
method: 'POST',
|
|
223
|
+
path: RUN_PATH,
|
|
224
|
+
body: { taskId, action },
|
|
225
|
+
operation: 'caizhilian.file-collection.run.apply',
|
|
226
|
+
});
|
|
227
|
+
const data = asRecord(response);
|
|
228
|
+
if (!data.status && !data.success) {
|
|
229
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '运行失败'), {
|
|
230
|
+
code: data.code ?? data.status,
|
|
231
|
+
details: { action: 'caizhilian.file-collection.run.apply', message: String(data.msg || data.message || '运行失败') },
|
|
232
|
+
exitCode: 1,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
const result = asRecord(data.data);
|
|
236
|
+
return caizhilianSuccess('caizhilian.file-collection.run.apply', {
|
|
237
|
+
status: result.status || '',
|
|
238
|
+
action,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
// ── 运行进度 ──────────────────────────────────────────────
|
|
242
|
+
async function runProgress(args, env) {
|
|
243
|
+
const response = await env.host.request({
|
|
244
|
+
method: 'GET',
|
|
245
|
+
path: RUN_PROGRESS_PATH,
|
|
246
|
+
operation: ACTION,
|
|
247
|
+
});
|
|
248
|
+
const data = asRecord(response);
|
|
249
|
+
if (!data.status && !data.success) {
|
|
250
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询运行进度失败'), {
|
|
251
|
+
code: data.code ?? data.status,
|
|
252
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询运行进度失败') },
|
|
253
|
+
exitCode: 1,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
const result = asRecord(data.data);
|
|
257
|
+
return caizhilianSuccess(ACTION, {
|
|
258
|
+
progress: result,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
// ── 采集详情 ──────────────────────────────────────────────
|
|
262
|
+
async function detailTable(args, env) {
|
|
263
|
+
const response = await env.host.request({
|
|
264
|
+
method: 'GET',
|
|
265
|
+
path: DETAIL_TABLE_PATH,
|
|
266
|
+
operation: ACTION,
|
|
267
|
+
});
|
|
268
|
+
const data = asRecord(response);
|
|
269
|
+
if (!data.status && !data.success) {
|
|
270
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '查询采集详情失败'), {
|
|
271
|
+
code: data.code ?? data.status,
|
|
272
|
+
details: { action: ACTION, message: String(data.msg || data.message || '查询采集详情失败') },
|
|
273
|
+
exitCode: 1,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
const result = asRecord(data.data);
|
|
277
|
+
return caizhilianSuccess(ACTION, {
|
|
278
|
+
details: result,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
// ── 取消采集(prepare/apply)──────────────────────────────────────
|
|
282
|
+
async function cancelPrepare(args, env) {
|
|
283
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
284
|
+
// 签发 continuation(键名与 targetKeys 保持一致,均为 snake_case)
|
|
285
|
+
const continuation = await env.continuation.issue({
|
|
286
|
+
operation: 'caizhilian.file-collection.cancel.apply',
|
|
287
|
+
task_id: taskId,
|
|
288
|
+
});
|
|
289
|
+
return caizhilianSuccess('caizhilian.file-collection.cancel.prepare', {
|
|
290
|
+
task_id: taskId,
|
|
291
|
+
continuation,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
async function cancelApply(args, env, lease) {
|
|
295
|
+
const taskId = lease.task_id;
|
|
296
|
+
const response = await env.host.request({
|
|
297
|
+
method: 'POST',
|
|
298
|
+
path: CANCEL_PATH,
|
|
299
|
+
body: { taskId },
|
|
300
|
+
operation: 'caizhilian.file-collection.cancel.apply',
|
|
301
|
+
});
|
|
302
|
+
const data = asRecord(response);
|
|
303
|
+
if (!data.status && !data.success) {
|
|
304
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '取消失败'), {
|
|
305
|
+
code: data.code ?? data.status,
|
|
306
|
+
details: { action: 'caizhilian.file-collection.cancel.apply', message: String(data.msg || data.message || '取消失败') },
|
|
307
|
+
exitCode: 1,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return caizhilianSuccess('caizhilian.file-collection.cancel.apply', {
|
|
311
|
+
cancelled: true,
|
|
312
|
+
task_id: taskId,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
// ── 删除采集任务(prepare/apply)──────────────────────────────────────
|
|
316
|
+
async function deleteTaskPrepare(args, env) {
|
|
317
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
318
|
+
// 签发 continuation(键名与 targetKeys 保持一致,均为 snake_case)
|
|
319
|
+
const continuation = await env.continuation.issue({
|
|
320
|
+
operation: 'caizhilian.file-collection.delete.apply',
|
|
321
|
+
task_id: taskId,
|
|
322
|
+
});
|
|
323
|
+
return caizhilianSuccess('caizhilian.file-collection.delete.prepare', {
|
|
324
|
+
task_id: taskId,
|
|
325
|
+
continuation,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
async function deleteTaskApply(args, env, lease) {
|
|
329
|
+
const taskId = lease.task_id;
|
|
330
|
+
const response = await env.host.request({
|
|
331
|
+
method: 'POST',
|
|
332
|
+
path: DELETE_PATH,
|
|
333
|
+
body: { taskId },
|
|
334
|
+
operation: 'caizhilian.file-collection.delete.apply',
|
|
335
|
+
});
|
|
336
|
+
const data = asRecord(response);
|
|
337
|
+
if (!data.status && !data.success) {
|
|
338
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '删除失败'), {
|
|
339
|
+
code: data.code ?? data.status,
|
|
340
|
+
details: { action: 'caizhilian.file-collection.delete.apply', message: String(data.msg || data.message || '删除失败') },
|
|
341
|
+
exitCode: 1,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return caizhilianSuccess('caizhilian.file-collection.delete.apply', {
|
|
345
|
+
deleted: true,
|
|
346
|
+
task_id: taskId,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
// ── 保存采集任务(prepare/apply)──────────────────────────────────────
|
|
350
|
+
async function saveTaskPrepare(args, env) {
|
|
351
|
+
const sourceId = requireNonEmpty(args.source_id, 'source_id');
|
|
352
|
+
const workflowId = requireNonEmpty(args.workflow_id, 'workflow_id');
|
|
353
|
+
const taskName = args.task_name || '';
|
|
354
|
+
const retainDirStruct = args.retain_dir_struct ?? true;
|
|
355
|
+
const taskFilePath = args.task_file_path || '/';
|
|
356
|
+
// 签发 continuation(键名与 targetKeys 保持一致,均为 snake_case)
|
|
357
|
+
const continuation = await env.continuation.issue({
|
|
358
|
+
operation: 'caizhilian.file-collection.task.save.apply',
|
|
359
|
+
source_id: sourceId,
|
|
360
|
+
workflow_id: workflowId,
|
|
361
|
+
task_name: taskName,
|
|
362
|
+
retain_dir_struct: retainDirStruct,
|
|
363
|
+
task_file_path: taskFilePath,
|
|
364
|
+
});
|
|
365
|
+
return caizhilianSuccess('caizhilian.file-collection.task.save.prepare', {
|
|
366
|
+
source_id: sourceId,
|
|
367
|
+
workflow_id: workflowId,
|
|
368
|
+
task_name: taskName,
|
|
369
|
+
retain_dir_struct: retainDirStruct,
|
|
370
|
+
task_file_path: taskFilePath,
|
|
371
|
+
continuation,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
async function saveTaskApply(args, env, lease) {
|
|
375
|
+
const sourceId = lease.source_id;
|
|
376
|
+
const workflowId = lease.workflow_id;
|
|
377
|
+
const taskName = lease.task_name;
|
|
378
|
+
const retainDirStruct = lease.retain_dir_struct;
|
|
379
|
+
const taskFilePath = lease.task_file_path;
|
|
380
|
+
const payload = {
|
|
381
|
+
taskStatus: '0',
|
|
382
|
+
taskName: taskName || `文件采集(${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }).replace(/[/:]/g, '').replace(' ', ' ').substring(0, 15)})`,
|
|
383
|
+
taskSourceId: sourceId,
|
|
384
|
+
taskSourceType: 'ftp',
|
|
385
|
+
taskWorkflowId: workflowId,
|
|
386
|
+
taskFilePath: taskFilePath || '/',
|
|
387
|
+
retainDirStruct: retainDirStruct,
|
|
388
|
+
taskMethod: '1',
|
|
389
|
+
deleteType: '0',
|
|
390
|
+
taskSource: sourceId,
|
|
391
|
+
};
|
|
392
|
+
const response = await env.host.request({
|
|
393
|
+
method: 'POST',
|
|
394
|
+
path: SAVE_TASK_PATH,
|
|
395
|
+
body: payload,
|
|
396
|
+
operation: 'caizhilian.file-collection.task.save.apply',
|
|
397
|
+
});
|
|
398
|
+
const data = asRecord(response);
|
|
399
|
+
if (!data.status && !data.success) {
|
|
400
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '保存采集任务失败'), {
|
|
401
|
+
code: data.code ?? data.status,
|
|
402
|
+
details: { action: 'caizhilian.file-collection.task.save.apply', message: String(data.msg || data.message || '保存采集任务失败') },
|
|
403
|
+
exitCode: 1,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
const result = asRecord(data.data);
|
|
407
|
+
return caizhilianSuccess('caizhilian.file-collection.task.save.apply', {
|
|
408
|
+
task_id: result.id || '',
|
|
409
|
+
task_name: taskName,
|
|
410
|
+
source_id: sourceId,
|
|
411
|
+
workflow_id: workflowId,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
// ── 切换任务启用/禁用(prepare/apply)────────────────────────
|
|
415
|
+
async function switchTaskPrepare(args, env) {
|
|
416
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
417
|
+
const taskStatus = args.task_status;
|
|
418
|
+
const taskSwitch = args.task_switch;
|
|
419
|
+
const continuation = await env.continuation.issue({
|
|
420
|
+
operation: 'caizhilian.file-collection.task.switch.apply',
|
|
421
|
+
task_id: taskId, task_status: taskStatus, task_switch: taskSwitch,
|
|
422
|
+
});
|
|
423
|
+
return caizhilianSuccess('caizhilian.file-collection.task.switch.prepare', {
|
|
424
|
+
task_id: taskId, task_status: taskStatus, task_switch: taskSwitch, continuation,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
async function switchTaskApply(args, env, lease) {
|
|
428
|
+
const taskId = lease.task_id;
|
|
429
|
+
const taskStatus = lease.task_status;
|
|
430
|
+
const taskSwitch = lease.task_switch;
|
|
431
|
+
const response = await env.host.request({
|
|
432
|
+
method: 'POST',
|
|
433
|
+
path: SWITCH_PATH,
|
|
434
|
+
body: { id: taskId, taskStatus, taskSwitch },
|
|
435
|
+
operation: 'caizhilian.file-collection.task.switch.apply',
|
|
436
|
+
});
|
|
437
|
+
const data = asRecord(response);
|
|
438
|
+
if (!data.status && !data.success) {
|
|
439
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '切换任务状态失败'), {
|
|
440
|
+
code: data.code ?? data.status,
|
|
441
|
+
details: { action: 'caizhilian.file-collection.task.switch.apply', message: String(data.msg || data.message || '切换任务状态失败') },
|
|
442
|
+
exitCode: 1,
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
return caizhilianSuccess('caizhilian.file-collection.task.switch.apply', {
|
|
446
|
+
task_id: taskId, task_status: taskStatus, task_switch: taskSwitch,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
// ── 另存为采集任务(prepare/apply)────────────────────────
|
|
450
|
+
async function saveAsTaskPrepare(args, env) {
|
|
451
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
452
|
+
const continuation = await env.continuation.issue({
|
|
453
|
+
operation: 'caizhilian.file-collection.task.save-as.apply',
|
|
454
|
+
task_id: taskId,
|
|
455
|
+
});
|
|
456
|
+
return caizhilianSuccess('caizhilian.file-collection.task.save-as.prepare', {
|
|
457
|
+
task_id: taskId, continuation,
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
async function saveAsTaskApply(args, env, lease) {
|
|
461
|
+
const taskId = lease.task_id;
|
|
462
|
+
const response = await env.host.request({
|
|
463
|
+
method: 'POST',
|
|
464
|
+
path: SAVE_AS_PATH,
|
|
465
|
+
body: { id: taskId },
|
|
466
|
+
operation: 'caizhilian.file-collection.task.save-as.apply',
|
|
467
|
+
});
|
|
468
|
+
const data = asRecord(response);
|
|
469
|
+
if (!data.status && !data.success) {
|
|
470
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '另存为失败'), {
|
|
471
|
+
code: data.code ?? data.status,
|
|
472
|
+
details: { action: 'caizhilian.file-collection.task.save-as.apply', message: String(data.msg || data.message || '另存为失败') },
|
|
473
|
+
exitCode: 1,
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
const result = asRecord(data.data);
|
|
477
|
+
return caizhilianSuccess('caizhilian.file-collection.task.save-as.apply', {
|
|
478
|
+
new_task_id: result.id || '',
|
|
479
|
+
source_task_id: taskId,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
// ── 更新任务全宗 ID(prepare/apply)────────────────────────
|
|
483
|
+
async function updateFondsPrepare(args, env) {
|
|
484
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
485
|
+
const fondsId = requireId(args.fonds_id, 'fonds_id');
|
|
486
|
+
const continuation = await env.continuation.issue({
|
|
487
|
+
operation: 'caizhilian.file-collection.task.update-fonds.apply',
|
|
488
|
+
task_id: taskId, fonds_id: fondsId,
|
|
489
|
+
});
|
|
490
|
+
return caizhilianSuccess('caizhilian.file-collection.task.update-fonds.prepare', {
|
|
491
|
+
task_id: taskId, fonds_id: fondsId, continuation,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
async function updateFondsApply(args, env, lease) {
|
|
495
|
+
const taskId = lease.task_id;
|
|
496
|
+
const fondsId = lease.fonds_id;
|
|
497
|
+
// 先读取当前表单
|
|
498
|
+
const formResponse = await env.host.request({
|
|
499
|
+
method: 'GET',
|
|
500
|
+
path: `${GET_TASK_FORM_PATH}?id=${taskId}`,
|
|
501
|
+
operation: 'caizhilian.file-collection.task.update-fonds.apply',
|
|
502
|
+
});
|
|
503
|
+
const formData = asRecord(formResponse);
|
|
504
|
+
const form = asRecord(formData.data);
|
|
505
|
+
// 组装更新 payload:保留表单字段,覆盖 fondsId
|
|
506
|
+
const payload = { ...form };
|
|
507
|
+
payload.fondsId = fondsId;
|
|
508
|
+
delete payload.fontId;
|
|
509
|
+
payload.taskType = 3;
|
|
510
|
+
// 处理 extParam 中的 fondsId
|
|
511
|
+
if (payload.extParam) {
|
|
512
|
+
try {
|
|
513
|
+
const extParam = JSON.parse(payload.extParam);
|
|
514
|
+
extParam.fondsId = fondsId;
|
|
515
|
+
payload.extParam = JSON.stringify(extParam);
|
|
516
|
+
}
|
|
517
|
+
catch { /* extParam 非 JSON 时忽略 */ }
|
|
518
|
+
}
|
|
519
|
+
const response = await env.host.request({
|
|
520
|
+
method: 'POST',
|
|
521
|
+
path: SAVE_TASK_PATH,
|
|
522
|
+
body: payload,
|
|
523
|
+
operation: 'caizhilian.file-collection.task.update-fonds.apply',
|
|
524
|
+
});
|
|
525
|
+
const data = asRecord(response);
|
|
526
|
+
if (!data.status && !data.success) {
|
|
527
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '更新全宗失败'), {
|
|
528
|
+
code: data.code ?? data.status,
|
|
529
|
+
details: { action: 'caizhilian.file-collection.task.update-fonds.apply', message: String(data.msg || data.message || '更新全宗失败') },
|
|
530
|
+
exitCode: 1,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
return caizhilianSuccess('caizhilian.file-collection.task.update-fonds.apply', {
|
|
534
|
+
task_id: taskId, fonds_id: fondsId,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
// ── 查询连接器和资源 ─────────────────────────────────────
|
|
538
|
+
async function queryConnectors(args, env) {
|
|
539
|
+
const nameFilter = args.name || '';
|
|
540
|
+
const protocolType = args.protocol_type || 'nas,ftp,sftp';
|
|
541
|
+
const pageSize = args.page_size ?? 20;
|
|
542
|
+
const pageNo = args.page_no ?? 1;
|
|
543
|
+
const maxPages = args.max_pages ?? 5;
|
|
544
|
+
const allConnectors = [];
|
|
545
|
+
for (let page = 1; page <= maxPages; page++) {
|
|
546
|
+
const response = await env.host.request({
|
|
547
|
+
method: 'GET',
|
|
548
|
+
path: `${CONNECTOR_LIST_PATH}?pageSize=${pageSize}¤t=${page}&protocolType=${protocolType}${nameFilter ? `&name=${encodeURIComponent(nameFilter)}` : ''}`,
|
|
549
|
+
operation: ACTION,
|
|
550
|
+
});
|
|
551
|
+
const data = asRecord(response);
|
|
552
|
+
const result = asRecord(data.data);
|
|
553
|
+
const records = asList(result.data || result.records || result);
|
|
554
|
+
if (records.length === 0)
|
|
555
|
+
break;
|
|
556
|
+
allConnectors.push(...records);
|
|
557
|
+
if (records.length < pageSize)
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
// 只保留 FTP 类型的连接器
|
|
561
|
+
const ftpConnectors = allConnectors.filter((c) => c.product === 'FTP');
|
|
562
|
+
// 查询每个连接器的资源
|
|
563
|
+
const enriched = [];
|
|
564
|
+
for (const connector of ftpConnectors) {
|
|
565
|
+
const resourceResponse = await env.host.request({
|
|
566
|
+
method: 'GET',
|
|
567
|
+
path: `${RESOURCE_LIST_PATH}?systemPk=${connector.id}&showDefalt=true&connectorType=ftp¤t=1&pageSize=100`,
|
|
568
|
+
operation: ACTION,
|
|
569
|
+
});
|
|
570
|
+
const resourceData = asRecord(resourceResponse);
|
|
571
|
+
const resourceResult = asRecord(resourceData.data);
|
|
572
|
+
const resources = asList(resourceResult.data || resourceResult.records || resourceResult);
|
|
573
|
+
enriched.push({
|
|
574
|
+
id: connector.id,
|
|
575
|
+
name: connector.name || '',
|
|
576
|
+
product: connector.product || '',
|
|
577
|
+
resources: resources.map((r) => ({
|
|
578
|
+
id: r.id,
|
|
579
|
+
name: r.name || '',
|
|
580
|
+
type: r.type || '',
|
|
581
|
+
status: r.status ?? '',
|
|
582
|
+
link_address: r.linkAddressSpan || r.linkAddress || '',
|
|
583
|
+
})),
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
return caizhilianSuccess(ACTION, {
|
|
587
|
+
ftp_connector_total: enriched.length,
|
|
588
|
+
ftp_connectors: enriched,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
// ── 创建连接器(prepare/apply)────────────────────────
|
|
592
|
+
async function createConnectorPrepare(args, env) {
|
|
593
|
+
const name = args.name || `文件采集FTP连接器(${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }).replace(/[/:]/g, '').replace(' ', ' ').substring(0, 15)})`;
|
|
594
|
+
const company = args.company || '文件采集';
|
|
595
|
+
const continuation = await env.continuation.issue({
|
|
596
|
+
operation: 'caizhilian.file-collection.connector.create.apply',
|
|
597
|
+
name, company,
|
|
598
|
+
});
|
|
599
|
+
return caizhilianSuccess('caizhilian.file-collection.connector.create.prepare', {
|
|
600
|
+
name, company, continuation,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
async function createConnectorApply(args, env, lease) {
|
|
604
|
+
const name = lease.name;
|
|
605
|
+
const company = lease.company;
|
|
606
|
+
const response = await env.host.request({
|
|
607
|
+
method: 'POST',
|
|
608
|
+
path: SYSTEM_POOL_SAVE_PATH,
|
|
609
|
+
body: {
|
|
610
|
+
name, company,
|
|
611
|
+
website: '', product: 'FTP', productWebsite: '', edition: '',
|
|
612
|
+
description: '', icon: '', id: '', connectorType: 'ftp',
|
|
613
|
+
},
|
|
614
|
+
operation: 'caizhilian.file-collection.connector.create.apply',
|
|
615
|
+
});
|
|
616
|
+
const data = asRecord(response);
|
|
617
|
+
if (!data.status && !data.success) {
|
|
618
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '创建连接器失败'), {
|
|
619
|
+
code: data.code ?? data.status,
|
|
620
|
+
details: { action: 'caizhilian.file-collection.connector.create.apply', message: String(data.msg || data.message || '创建连接器失败') },
|
|
621
|
+
exitCode: 1,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
const result = asRecord(data.data);
|
|
625
|
+
return caizhilianSuccess('caizhilian.file-collection.connector.create.apply', {
|
|
626
|
+
id: result.id || result.systemPk || '',
|
|
627
|
+
name,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
// ── 创建 FTP/SFTP 资源(prepare/apply)────────────────────────
|
|
631
|
+
async function createResourcePrepare(args, env) {
|
|
632
|
+
const remoteHost = requireNonEmpty(args.remote_host, 'remote_host');
|
|
633
|
+
const remotePort = requireNonEmpty(args.remote_port, 'remote_port');
|
|
634
|
+
const remoteUsername = requireNonEmpty(args.remote_username, 'remote_username');
|
|
635
|
+
const remotePassword = requireNonEmpty(args.remote_password, 'remote_password');
|
|
636
|
+
const transferProtocol = requireNonEmpty(args.transfer_protocol, 'transfer_protocol');
|
|
637
|
+
const systemPk = args.system_pk || '';
|
|
638
|
+
const name = args.name || '文件采集FTP连接';
|
|
639
|
+
const continuation = await env.continuation.issue({
|
|
640
|
+
operation: 'caizhilian.file-collection.resource.create.apply',
|
|
641
|
+
system_pk: systemPk, name, remote_host: remoteHost, remote_port: remotePort,
|
|
642
|
+
remote_username: remoteUsername, remote_password: remotePassword, transfer_protocol: transferProtocol,
|
|
643
|
+
});
|
|
644
|
+
return caizhilianSuccess('caizhilian.file-collection.resource.create.prepare', {
|
|
645
|
+
system_pk: systemPk, name, remote_host: remoteHost, remote_port: remotePort,
|
|
646
|
+
remote_username: remoteUsername, transfer_protocol: transferProtocol, continuation,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
async function createResourceApply(args, env, lease) {
|
|
650
|
+
let systemPk = lease.system_pk;
|
|
651
|
+
const name = lease.name;
|
|
652
|
+
const remoteHost = lease.remote_host;
|
|
653
|
+
const remotePort = lease.remote_port;
|
|
654
|
+
const remoteUsername = lease.remote_username;
|
|
655
|
+
const remotePassword = lease.remote_password;
|
|
656
|
+
const transferProtocol = lease.transfer_protocol;
|
|
657
|
+
let systemPoolCreated = false;
|
|
658
|
+
// 如果没有连接器 ID,先自动创建
|
|
659
|
+
if (!systemPk) {
|
|
660
|
+
const connResponse = await env.host.request({
|
|
661
|
+
method: 'POST',
|
|
662
|
+
path: SYSTEM_POOL_SAVE_PATH,
|
|
663
|
+
body: {
|
|
664
|
+
name: `文件采集FTP连接器(${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }).replace(/[/:]/g, '').replace(' ', ' ').substring(0, 15)})`,
|
|
665
|
+
company: '文件采集',
|
|
666
|
+
website: '', product: 'FTP', productWebsite: '', edition: '',
|
|
667
|
+
description: '', icon: '', id: '', connectorType: 'ftp',
|
|
668
|
+
},
|
|
669
|
+
operation: 'caizhilian.file-collection.resource.create.apply',
|
|
670
|
+
});
|
|
671
|
+
const connData = asRecord(connResponse);
|
|
672
|
+
const connResult = asRecord(connData.data);
|
|
673
|
+
systemPk = connResult.id || connResult.systemPk || '';
|
|
674
|
+
systemPoolCreated = true;
|
|
675
|
+
}
|
|
676
|
+
const response = await env.host.request({
|
|
677
|
+
method: 'POST',
|
|
678
|
+
path: FTP_RESOURCE_SAVE_PATH,
|
|
679
|
+
body: {
|
|
680
|
+
encoding: 'UTF-8',
|
|
681
|
+
connectionMode: 2,
|
|
682
|
+
name,
|
|
683
|
+
remoteHost,
|
|
684
|
+
remotePort: String(remotePort),
|
|
685
|
+
remoteUsername,
|
|
686
|
+
remotePassword,
|
|
687
|
+
requestTimeout: '60',
|
|
688
|
+
responseTimeout: 60,
|
|
689
|
+
retryTime: '0',
|
|
690
|
+
systemPk,
|
|
691
|
+
transferMode: 2,
|
|
692
|
+
transferProtocol,
|
|
693
|
+
type: 'ftp',
|
|
694
|
+
},
|
|
695
|
+
operation: 'caizhilian.file-collection.resource.create.apply',
|
|
696
|
+
});
|
|
697
|
+
const data = asRecord(response);
|
|
698
|
+
if (!data.status && !data.success) {
|
|
699
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '创建资源失败'), {
|
|
700
|
+
code: data.code ?? data.status,
|
|
701
|
+
details: { action: 'caizhilian.file-collection.resource.create.apply', message: String(data.msg || data.message || '创建资源失败') },
|
|
702
|
+
exitCode: 1,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
const result = asRecord(data.data);
|
|
706
|
+
return caizhilianSuccess('caizhilian.file-collection.resource.create.apply', {
|
|
707
|
+
id: result.id || '',
|
|
708
|
+
name,
|
|
709
|
+
system_pk: systemPk,
|
|
710
|
+
system_pool_created: systemPoolCreated,
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
// ── 搜索动作流 ─────────────────────────────────────
|
|
714
|
+
async function searchWorkflows(args, env) {
|
|
715
|
+
const nameFilter = args.name_contains || '';
|
|
716
|
+
const pageSize = args.page_size ?? 50;
|
|
717
|
+
const pageNo = args.page_no ?? 1;
|
|
718
|
+
const response = await env.host.request({
|
|
719
|
+
method: 'POST',
|
|
720
|
+
path: APP_LIST_PATH,
|
|
721
|
+
body: {
|
|
722
|
+
current: pageNo, pageSize,
|
|
723
|
+
action: '', componentType: '', orgId: '',
|
|
724
|
+
createDates: [], creator: [], event: [],
|
|
725
|
+
type: [], updateDates: [], appIds: [],
|
|
726
|
+
skipId: '', thirdParty: '', appLevel: '', templateId: '',
|
|
727
|
+
name: '', status: '', moudle: 'esb',
|
|
728
|
+
isDelete: 0, orderType: '', orderStatus: '',
|
|
729
|
+
},
|
|
730
|
+
operation: ACTION,
|
|
731
|
+
});
|
|
732
|
+
const data = asRecord(response);
|
|
733
|
+
const result = asRecord(data.data);
|
|
734
|
+
let candidates = asList(result.data || result.records || result);
|
|
735
|
+
// 客户端过滤
|
|
736
|
+
if (nameFilter) {
|
|
737
|
+
const lower = nameFilter.toLowerCase();
|
|
738
|
+
candidates = candidates.filter((c) => (c.name || '').toLowerCase().includes(lower));
|
|
739
|
+
}
|
|
740
|
+
return caizhilianSuccess(ACTION, {
|
|
741
|
+
version: 'file_collection_action_flow_candidates.v1',
|
|
742
|
+
candidates: candidates.map((c, i) => ({
|
|
743
|
+
ordinal: i + 1,
|
|
744
|
+
id: c.id,
|
|
745
|
+
name: c.name || '',
|
|
746
|
+
status: c.status ?? '',
|
|
747
|
+
update_time: c.updateTime || '',
|
|
748
|
+
})),
|
|
749
|
+
candidate_count: candidates.length,
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
// ── 检测动作流兼容性 ─────────────────────────────────────
|
|
753
|
+
async function inspectWorkflow(args, env) {
|
|
754
|
+
const applicationId = requireId(args.application_id, 'application_id');
|
|
755
|
+
const archiveRequired = args.archive_required ?? false;
|
|
756
|
+
const retainDirStruct = args.retain_dir_struct ?? false;
|
|
757
|
+
// 1. 获取应用信息
|
|
758
|
+
const appResponse = await env.host.request({
|
|
759
|
+
method: 'GET',
|
|
760
|
+
path: `${APP_DETAIL_PATH}/${applicationId}`,
|
|
761
|
+
operation: ACTION,
|
|
762
|
+
});
|
|
763
|
+
const appData = asRecord(appResponse);
|
|
764
|
+
const app = asRecord(appData.data);
|
|
765
|
+
// 2. 获取版本列表
|
|
766
|
+
const versionResponse = await env.host.request({
|
|
767
|
+
method: 'GET',
|
|
768
|
+
path: `${APP_VERSION_PATH}/${applicationId}`,
|
|
769
|
+
operation: ACTION,
|
|
770
|
+
});
|
|
771
|
+
const versionData = asRecord(versionResponse);
|
|
772
|
+
const versions = asList(versionData.data);
|
|
773
|
+
// 找到活动版本
|
|
774
|
+
const activeVersion = versions.find((v) => String(v.activeVersion) === '1' || v.activeVersion === true) || versions[0];
|
|
775
|
+
if (!activeVersion) {
|
|
776
|
+
return caizhilianSuccess(ACTION, {
|
|
777
|
+
validation: { compatible: false, issues: ['未找到活动版本'] },
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
const sceneId = activeVersion.sceneId || '';
|
|
781
|
+
const secretKey = activeVersion.secretKey || '';
|
|
782
|
+
// 3. 获取设计物
|
|
783
|
+
let design = {};
|
|
784
|
+
if (sceneId) {
|
|
785
|
+
const designResponse = await env.host.request({
|
|
786
|
+
method: 'GET',
|
|
787
|
+
path: `${DESIGN_BY_SCENE_PATH}/${sceneId}`,
|
|
788
|
+
operation: ACTION,
|
|
789
|
+
});
|
|
790
|
+
const designData = asRecord(designResponse);
|
|
791
|
+
design = asRecord(designData.data);
|
|
792
|
+
}
|
|
793
|
+
// 4. 合规检测
|
|
794
|
+
const issues = [];
|
|
795
|
+
const triggers = asList(design.triggers || design.event);
|
|
796
|
+
const actions = asList(design.actions);
|
|
797
|
+
// 检测触发器
|
|
798
|
+
const customTrigger = triggers.find((t) => t.type === 'CustomTrigger' || t.componentType === 'CustomTrigger');
|
|
799
|
+
if (!customTrigger) {
|
|
800
|
+
issues.push('缺少 CustomTrigger 触发器');
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
const inputs = asList(customTrigger.inputs || customTrigger.input);
|
|
804
|
+
const inputNames = inputs.map((i) => i.name || i.key || '');
|
|
805
|
+
if (!inputNames.includes('fileId'))
|
|
806
|
+
issues.push('触发器缺少 fileId 输入');
|
|
807
|
+
if (!inputNames.includes('filename'))
|
|
808
|
+
issues.push('触发器缺少 filename 输入');
|
|
809
|
+
if (!inputNames.includes('employeeId'))
|
|
810
|
+
issues.push('触发器缺少 employeeId 输入');
|
|
811
|
+
if (archiveRequired && !inputNames.includes('fondsId'))
|
|
812
|
+
issues.push('归档模式下触发器缺少 fondsId 输入');
|
|
813
|
+
if (retainDirStruct && !inputNames.includes('folderId'))
|
|
814
|
+
issues.push('维持目录结构时触发器缺少 folderId 输入');
|
|
815
|
+
}
|
|
816
|
+
// 检测动作节点
|
|
817
|
+
const docSave = actions.find((a) => a.type === 'DocumentSave' || a.componentType === 'DocumentSave');
|
|
818
|
+
if (!docSave) {
|
|
819
|
+
issues.push('缺少 DocumentSave 动作节点');
|
|
820
|
+
}
|
|
821
|
+
const outputNode = actions.find((a) => a.type === 'Output' || a.componentType === 'Output');
|
|
822
|
+
if (!outputNode) {
|
|
823
|
+
issues.push('缺少 Output 动作节点');
|
|
824
|
+
}
|
|
825
|
+
const compatible = issues.length === 0;
|
|
826
|
+
return caizhilianSuccess(ACTION, {
|
|
827
|
+
validation: {
|
|
828
|
+
compatible,
|
|
829
|
+
issues,
|
|
830
|
+
workflow: { id: app.id, name: app.name, status: app.status },
|
|
831
|
+
},
|
|
832
|
+
selection: compatible ? {
|
|
833
|
+
application_id: app.id,
|
|
834
|
+
scene_id: sceneId,
|
|
835
|
+
secret_key: secretKey,
|
|
836
|
+
version: 'file_collection_workflow_selection.v1',
|
|
837
|
+
} : undefined,
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
// ── 创建动作流(prepare/apply)────────────────────────
|
|
841
|
+
/** 标准文件采集动作流设计模板(CustomTrigger → DocumentSave → Output) */
|
|
842
|
+
function buildActionFlowDesign(opts) {
|
|
843
|
+
const { appId, sceneId, secretKey, retainDirStruct } = opts;
|
|
844
|
+
// 确定性 ID 生成(基于 SHA-256 前 19 位数字)
|
|
845
|
+
const hash = (s) => {
|
|
846
|
+
let h = 0;
|
|
847
|
+
for (let i = 0; i < s.length; i++)
|
|
848
|
+
h = ((h << 5) - h + s.charCodeAt(i)) | 0;
|
|
849
|
+
return Math.abs(h);
|
|
850
|
+
};
|
|
851
|
+
const triggerId = 1000000000000000000 + (hash(`${appId}-trigger`) % 900000000000000000);
|
|
852
|
+
const docSaveId = 1000000000000000000 + (hash(`${appId}-docsave`) % 900000000000000000);
|
|
853
|
+
const outputId = 1000000000000000000 + (hash(`${appId}-output`) % 900000000000000000);
|
|
854
|
+
const fileFolder = retainDirStruct
|
|
855
|
+
? { formula: '${SelectParams.mainTable.folderId}', type: 'field' }
|
|
856
|
+
: { formula: '200', type: 'fixed' };
|
|
857
|
+
return {
|
|
858
|
+
saveAndStart: true,
|
|
859
|
+
appId, sceneId, secretKey,
|
|
860
|
+
appName: 'weaver-file-collection',
|
|
861
|
+
event: {
|
|
862
|
+
componentType: 'CustomTrigger',
|
|
863
|
+
id: String(triggerId),
|
|
864
|
+
inputs: [
|
|
865
|
+
{ name: 'fileId', type: 'string' },
|
|
866
|
+
{ name: 'filename', type: 'string' },
|
|
867
|
+
{ name: 'employeeId', type: 'string' },
|
|
868
|
+
...(retainDirStruct ? [{ name: 'folderId', type: 'string' }] : []),
|
|
869
|
+
],
|
|
870
|
+
},
|
|
871
|
+
actions: [
|
|
872
|
+
{
|
|
873
|
+
componentType: 'DocumentSave',
|
|
874
|
+
id: String(docSaveId),
|
|
875
|
+
fileFolder,
|
|
876
|
+
nextActionId: String(outputId),
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
componentType: 'Output',
|
|
880
|
+
id: String(outputId),
|
|
881
|
+
customParamSetting: [
|
|
882
|
+
{ name: 'docId', type: 'string', value: '${DocumentSave.Response.entry.docId}' },
|
|
883
|
+
],
|
|
884
|
+
},
|
|
885
|
+
],
|
|
886
|
+
addIds: [String(triggerId), String(docSaveId), String(outputId)],
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
async function createWorkflowPrepare(args, env) {
|
|
890
|
+
const name = args.name || `文件采集动作流(${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }).replace(/[/:]/g, '').replace(' ', ' ').substring(0, 15)})`;
|
|
891
|
+
const archiveRequired = args.archive_required ?? false;
|
|
892
|
+
const retainDirStruct = args.retain_dir_struct ?? false;
|
|
893
|
+
const continuation = await env.continuation.issue({
|
|
894
|
+
operation: 'caizhilian.file-collection.workflow.create.apply',
|
|
895
|
+
name, archive_required: archiveRequired, retain_dir_struct: retainDirStruct,
|
|
896
|
+
});
|
|
897
|
+
return caizhilianSuccess('caizhilian.file-collection.workflow.create.prepare', {
|
|
898
|
+
name, archive_required: archiveRequired, retain_dir_struct: retainDirStruct, continuation,
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
async function createWorkflowApply(args, env, lease) {
|
|
902
|
+
const name = lease.name;
|
|
903
|
+
const archiveRequired = lease.archive_required;
|
|
904
|
+
const retainDirStruct = lease.retain_dir_struct;
|
|
905
|
+
const applyOp = 'caizhilian.file-collection.workflow.create.apply';
|
|
906
|
+
// 1. 创建应用
|
|
907
|
+
const saveResponse = await env.host.request({
|
|
908
|
+
method: 'POST',
|
|
909
|
+
path: APP_SAVE_PATH,
|
|
910
|
+
body: { name, type: 0, moudle: 'esb', description: 'weaver-file-collection dynamically generated action flow' },
|
|
911
|
+
operation: applyOp,
|
|
912
|
+
});
|
|
913
|
+
const saveData = asRecord(saveResponse);
|
|
914
|
+
const saveResult = asRecord(saveData.data);
|
|
915
|
+
const appId = String(saveResult.id || '');
|
|
916
|
+
if (!appId)
|
|
917
|
+
throw new CaizhilianCliError('api', 'business_error', '创建动作流应用失败:未返回应用 ID', { exitCode: 1 });
|
|
918
|
+
// 2. 获取版本列表
|
|
919
|
+
const versionResponse = await env.host.request({
|
|
920
|
+
method: 'GET',
|
|
921
|
+
path: `${APP_VERSION_PATH}/${appId}`,
|
|
922
|
+
operation: applyOp,
|
|
923
|
+
});
|
|
924
|
+
const versionData = asRecord(versionResponse);
|
|
925
|
+
const versions = asList(versionData.data);
|
|
926
|
+
const activeVersion = versions[0] || {};
|
|
927
|
+
const sceneId = activeVersion.sceneId || '';
|
|
928
|
+
const secretKey = activeVersion.secretKey || '';
|
|
929
|
+
// 3. 注册变量
|
|
930
|
+
const variables = ['fileId', 'filename', 'employeeId'];
|
|
931
|
+
if (archiveRequired)
|
|
932
|
+
variables.push('fondsId');
|
|
933
|
+
if (retainDirStruct)
|
|
934
|
+
variables.push('folderId');
|
|
935
|
+
for (const varName of variables) {
|
|
936
|
+
await env.host.request({
|
|
937
|
+
method: 'POST',
|
|
938
|
+
path: APP_VARIABLE_PATH,
|
|
939
|
+
body: { appId, sceneId, variableName: varName, variableType: 'string', variableValue: '' },
|
|
940
|
+
operation: applyOp,
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
// 4. 生成并保存设计
|
|
944
|
+
const design = buildActionFlowDesign({ appId, sceneId, secretKey, retainDirStruct });
|
|
945
|
+
// 5. 校验设计
|
|
946
|
+
await env.host.request({
|
|
947
|
+
method: 'POST',
|
|
948
|
+
path: DESIGN_CHECK_PATH,
|
|
949
|
+
body: design,
|
|
950
|
+
operation: applyOp,
|
|
951
|
+
});
|
|
952
|
+
// 6. 保存设计
|
|
953
|
+
await env.host.request({
|
|
954
|
+
method: 'POST',
|
|
955
|
+
path: DESIGN_SAVE_PATH,
|
|
956
|
+
body: design,
|
|
957
|
+
operation: applyOp,
|
|
958
|
+
});
|
|
959
|
+
// 7. 启用
|
|
960
|
+
await env.host.request({
|
|
961
|
+
method: 'GET',
|
|
962
|
+
path: `${APP_ENABLE_PATH}/${appId}`,
|
|
963
|
+
operation: applyOp,
|
|
964
|
+
});
|
|
965
|
+
return caizhilianSuccess(applyOp, {
|
|
966
|
+
id: appId,
|
|
967
|
+
scene_id: sceneId,
|
|
968
|
+
name,
|
|
969
|
+
registered_variables: variables,
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
// ── 启用动作流(prepare/apply)────────────────────────
|
|
973
|
+
async function enableWorkflowPrepare(args, env) {
|
|
974
|
+
const applicationId = requireId(args.application_id, 'application_id');
|
|
975
|
+
const continuation = await env.continuation.issue({
|
|
976
|
+
operation: 'caizhilian.file-collection.workflow.enable.apply',
|
|
977
|
+
application_id: applicationId,
|
|
978
|
+
});
|
|
979
|
+
return caizhilianSuccess('caizhilian.file-collection.workflow.enable.prepare', {
|
|
980
|
+
application_id: applicationId, continuation,
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
async function enableWorkflowApply(args, env, lease) {
|
|
984
|
+
const applicationId = lease.application_id;
|
|
985
|
+
const response = await env.host.request({
|
|
986
|
+
method: 'GET',
|
|
987
|
+
path: `${APP_ENABLE_PATH}/${applicationId}`,
|
|
988
|
+
operation: 'caizhilian.file-collection.workflow.enable.apply',
|
|
989
|
+
});
|
|
990
|
+
const data = asRecord(response);
|
|
991
|
+
if (!data.status && !data.success) {
|
|
992
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '启用动作流失败'), {
|
|
993
|
+
code: data.code ?? data.status,
|
|
994
|
+
details: { action: 'caizhilian.file-collection.workflow.enable.apply', message: String(data.msg || data.message || '启用动作流失败') },
|
|
995
|
+
exitCode: 1,
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
return caizhilianSuccess('caizhilian.file-collection.workflow.enable.apply', {
|
|
999
|
+
application_id: applicationId, enabled: true,
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
// ── 更新任务关联的动作流(prepare/apply)────────────────────────
|
|
1003
|
+
async function updateTaskWorkflowPrepare(args, env) {
|
|
1004
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
1005
|
+
const workflowId = requireId(args.workflow_id, 'workflow_id');
|
|
1006
|
+
const continuation = await env.continuation.issue({
|
|
1007
|
+
operation: 'caizhilian.file-collection.workflow.update-task.apply',
|
|
1008
|
+
task_id: taskId, workflow_id: workflowId,
|
|
1009
|
+
});
|
|
1010
|
+
return caizhilianSuccess('caizhilian.file-collection.workflow.update-task.prepare', {
|
|
1011
|
+
task_id: taskId, workflow_id: workflowId, continuation,
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
async function updateTaskWorkflowApply(args, env, lease) {
|
|
1015
|
+
const taskId = lease.task_id;
|
|
1016
|
+
const workflowId = lease.workflow_id;
|
|
1017
|
+
const applyOp = 'caizhilian.file-collection.workflow.update-task.apply';
|
|
1018
|
+
// 读取当前表单
|
|
1019
|
+
const formResponse = await env.host.request({
|
|
1020
|
+
method: 'GET',
|
|
1021
|
+
path: `${GET_TASK_FORM_PATH}?id=${taskId}`,
|
|
1022
|
+
operation: applyOp,
|
|
1023
|
+
});
|
|
1024
|
+
const formData = asRecord(formResponse);
|
|
1025
|
+
const form = asRecord(formData.data);
|
|
1026
|
+
// 更新 workflowId
|
|
1027
|
+
const payload = { ...form, taskWorkflowId: workflowId };
|
|
1028
|
+
const response = await env.host.request({
|
|
1029
|
+
method: 'POST',
|
|
1030
|
+
path: SAVE_TASK_PATH,
|
|
1031
|
+
body: payload,
|
|
1032
|
+
operation: applyOp,
|
|
1033
|
+
});
|
|
1034
|
+
const data = asRecord(response);
|
|
1035
|
+
if (!data.status && !data.success) {
|
|
1036
|
+
throw new CaizhilianCliError('api', 'business_error', String(data.msg || data.message || '更新任务动作流失败'), {
|
|
1037
|
+
code: data.code ?? data.status,
|
|
1038
|
+
details: { action: applyOp, message: String(data.msg || data.message || '更新任务动作流失败') },
|
|
1039
|
+
exitCode: 1,
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
return caizhilianSuccess(applyOp, {
|
|
1043
|
+
task_id: taskId, workflow_id: workflowId,
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
// ── 等待扫描完成 ─────────────────────────────────────
|
|
1047
|
+
async function waitScanCompletion(args, env) {
|
|
1048
|
+
const runtimeId = requireNonEmpty(args.runtime_id, 'runtime_id');
|
|
1049
|
+
const timeoutSeconds = args.timeout_seconds ?? 300;
|
|
1050
|
+
const intervalSeconds = args.interval_seconds ?? 3;
|
|
1051
|
+
const deadline = Date.now() + timeoutSeconds * 1000;
|
|
1052
|
+
while (Date.now() < deadline) {
|
|
1053
|
+
const response = await env.host.request({
|
|
1054
|
+
method: 'GET',
|
|
1055
|
+
path: `${SCAN_PROGRESS_PATH}?runtimeId=${runtimeId}`,
|
|
1056
|
+
operation: ACTION,
|
|
1057
|
+
});
|
|
1058
|
+
const data = asRecord(response);
|
|
1059
|
+
const result = asRecord(data.data);
|
|
1060
|
+
if (result.finish === true || result.finish === 'true') {
|
|
1061
|
+
return caizhilianSuccess(ACTION, {
|
|
1062
|
+
runtime_id: runtimeId,
|
|
1063
|
+
finished: true,
|
|
1064
|
+
progress: result,
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
await new Promise(resolve => setTimeout(resolve, intervalSeconds * 1000));
|
|
1068
|
+
}
|
|
1069
|
+
throw new CaizhilianCliError('api', 'timeout', `扫描等待超时(${timeoutSeconds}秒)`, {
|
|
1070
|
+
details: { runtime_id: runtimeId, timeout_seconds: timeoutSeconds },
|
|
1071
|
+
exitCode: 1,
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
// ── 查询运行结果并归一化 ─────────────────────────────────────
|
|
1075
|
+
async function getRunResult(args, env) {
|
|
1076
|
+
const taskId = requireId(args.task_id, 'task_id');
|
|
1077
|
+
// 1. 查询运行进度
|
|
1078
|
+
const progressResponse = await env.host.request({
|
|
1079
|
+
method: 'GET',
|
|
1080
|
+
path: `${RUN_PROGRESS_PATH}?id=${taskId}`,
|
|
1081
|
+
operation: ACTION,
|
|
1082
|
+
});
|
|
1083
|
+
const progressData = asRecord(progressResponse);
|
|
1084
|
+
const progress = asRecord(progressData.data);
|
|
1085
|
+
if (!progress.finish && progress.finish !== 'true') {
|
|
1086
|
+
return caizhilianSuccess(ACTION, {
|
|
1087
|
+
version: 'file_collection_result.v1',
|
|
1088
|
+
status: 'collection_running',
|
|
1089
|
+
task_id: taskId,
|
|
1090
|
+
file_collection_ok: false,
|
|
1091
|
+
message: '采集任务仍在运行中',
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
// 2. 查询成功和失败明细
|
|
1095
|
+
let successfulCount = 0;
|
|
1096
|
+
let failedCount = 0;
|
|
1097
|
+
try {
|
|
1098
|
+
const successResponse = await env.host.request({
|
|
1099
|
+
method: 'GET',
|
|
1100
|
+
path: `${DETAIL_TABLE_PATH}?fileCollTaskId=${taskId}&detailType=true`,
|
|
1101
|
+
operation: ACTION,
|
|
1102
|
+
});
|
|
1103
|
+
const successData = asRecord(successResponse);
|
|
1104
|
+
const successResult = asRecord(successData.data);
|
|
1105
|
+
successfulCount = asList(successResult.data || successResult).length;
|
|
1106
|
+
}
|
|
1107
|
+
catch { /* 查询失败时计数为 0 */ }
|
|
1108
|
+
try {
|
|
1109
|
+
const failedResponse = await env.host.request({
|
|
1110
|
+
method: 'GET',
|
|
1111
|
+
path: `${DETAIL_TABLE_PATH}?fileCollTaskId=${taskId}&detailType=false`,
|
|
1112
|
+
operation: ACTION,
|
|
1113
|
+
});
|
|
1114
|
+
const failedData = asRecord(failedResponse);
|
|
1115
|
+
const failedResult = asRecord(failedData.data);
|
|
1116
|
+
failedCount = asList(failedResult.data || failedResult).length;
|
|
1117
|
+
}
|
|
1118
|
+
catch { /* 查询失败时计数为 0 */ }
|
|
1119
|
+
// 3. 归一化结果
|
|
1120
|
+
let status;
|
|
1121
|
+
let fileCollectionOk;
|
|
1122
|
+
let message;
|
|
1123
|
+
if (failedCount > 0) {
|
|
1124
|
+
status = 'collection_completed_with_failures';
|
|
1125
|
+
fileCollectionOk = false;
|
|
1126
|
+
message = `采集完成,但有 ${failedCount} 个文件失败`;
|
|
1127
|
+
}
|
|
1128
|
+
else if (successfulCount > 0) {
|
|
1129
|
+
status = 'collection_succeeded';
|
|
1130
|
+
fileCollectionOk = true;
|
|
1131
|
+
message = `采集成功,共 ${successfulCount} 个文件`;
|
|
1132
|
+
}
|
|
1133
|
+
else {
|
|
1134
|
+
status = 'collection_completed_without_files';
|
|
1135
|
+
fileCollectionOk = false;
|
|
1136
|
+
message = '采集完成,但无文件记录';
|
|
1137
|
+
}
|
|
1138
|
+
return caizhilianSuccess(ACTION, {
|
|
1139
|
+
version: 'file_collection_result.v1',
|
|
1140
|
+
status,
|
|
1141
|
+
task_id: taskId,
|
|
1142
|
+
file_counts: { successful: successfulCount, failed: failedCount, total: successfulCount + failedCount },
|
|
1143
|
+
file_collection_ok: fileCollectionOk,
|
|
1144
|
+
message,
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
// ── 处理器汇总 ────────────────────────────────────────────
|
|
1148
|
+
export const caizhilianFileCollectionHandlers = {
|
|
1149
|
+
'caizhilian.file-collection.task.list': { execute: listTasks },
|
|
1150
|
+
'caizhilian.file-collection.task.form': { execute: getTaskForm },
|
|
1151
|
+
'caizhilian.file-collection.task.save': {
|
|
1152
|
+
prepare: saveTaskPrepare,
|
|
1153
|
+
apply: saveTaskApply,
|
|
1154
|
+
targetKeys: ['source_id', 'workflow_id'],
|
|
1155
|
+
},
|
|
1156
|
+
'caizhilian.file-collection.storage.check': { execute: checkStorage },
|
|
1157
|
+
'caizhilian.file-collection.scan': {
|
|
1158
|
+
prepare: scanPrepare,
|
|
1159
|
+
apply: scanApply,
|
|
1160
|
+
targetKeys: ['task_id'],
|
|
1161
|
+
},
|
|
1162
|
+
'caizhilian.file-collection.scan.progress': { execute: scanProgress },
|
|
1163
|
+
'caizhilian.file-collection.run': {
|
|
1164
|
+
prepare: runPrepare,
|
|
1165
|
+
apply: runApply,
|
|
1166
|
+
targetKeys: ['task_id'],
|
|
1167
|
+
},
|
|
1168
|
+
'caizhilian.file-collection.run.progress': { execute: runProgress },
|
|
1169
|
+
'caizhilian.file-collection.detail': { execute: detailTable },
|
|
1170
|
+
'caizhilian.file-collection.cancel': {
|
|
1171
|
+
prepare: cancelPrepare,
|
|
1172
|
+
apply: cancelApply,
|
|
1173
|
+
targetKeys: ['task_id'],
|
|
1174
|
+
},
|
|
1175
|
+
'caizhilian.file-collection.delete': {
|
|
1176
|
+
prepare: deleteTaskPrepare,
|
|
1177
|
+
apply: deleteTaskApply,
|
|
1178
|
+
targetKeys: ['task_id'],
|
|
1179
|
+
},
|
|
1180
|
+
// ── 任务管理补充 ──
|
|
1181
|
+
'caizhilian.file-collection.task.switch': {
|
|
1182
|
+
prepare: switchTaskPrepare,
|
|
1183
|
+
apply: switchTaskApply,
|
|
1184
|
+
targetKeys: ['task_id'],
|
|
1185
|
+
},
|
|
1186
|
+
'caizhilian.file-collection.task.save-as': {
|
|
1187
|
+
prepare: saveAsTaskPrepare,
|
|
1188
|
+
apply: saveAsTaskApply,
|
|
1189
|
+
targetKeys: ['task_id'],
|
|
1190
|
+
},
|
|
1191
|
+
'caizhilian.file-collection.task.update-fonds': {
|
|
1192
|
+
prepare: updateFondsPrepare,
|
|
1193
|
+
apply: updateFondsApply,
|
|
1194
|
+
targetKeys: ['task_id'],
|
|
1195
|
+
},
|
|
1196
|
+
// ── 连接器/资源管理 ──
|
|
1197
|
+
'caizhilian.file-collection.connector.query': { execute: queryConnectors },
|
|
1198
|
+
'caizhilian.file-collection.connector.create': {
|
|
1199
|
+
prepare: createConnectorPrepare,
|
|
1200
|
+
apply: createConnectorApply,
|
|
1201
|
+
},
|
|
1202
|
+
'caizhilian.file-collection.resource.create': {
|
|
1203
|
+
prepare: createResourcePrepare,
|
|
1204
|
+
apply: createResourceApply,
|
|
1205
|
+
targetKeys: ['remote_host'],
|
|
1206
|
+
},
|
|
1207
|
+
// ── 动作流管理 ──
|
|
1208
|
+
'caizhilian.file-collection.workflow.search': { execute: searchWorkflows },
|
|
1209
|
+
'caizhilian.file-collection.workflow.inspect': { execute: inspectWorkflow },
|
|
1210
|
+
'caizhilian.file-collection.workflow.create': {
|
|
1211
|
+
prepare: createWorkflowPrepare,
|
|
1212
|
+
apply: createWorkflowApply,
|
|
1213
|
+
},
|
|
1214
|
+
'caizhilian.file-collection.workflow.enable': {
|
|
1215
|
+
prepare: enableWorkflowPrepare,
|
|
1216
|
+
apply: enableWorkflowApply,
|
|
1217
|
+
targetKeys: ['application_id'],
|
|
1218
|
+
},
|
|
1219
|
+
'caizhilian.file-collection.workflow.update-task': {
|
|
1220
|
+
prepare: updateTaskWorkflowPrepare,
|
|
1221
|
+
apply: updateTaskWorkflowApply,
|
|
1222
|
+
targetKeys: ['task_id'],
|
|
1223
|
+
},
|
|
1224
|
+
// ── 等待与结果验证 ──
|
|
1225
|
+
'caizhilian.file-collection.scan.wait': { execute: waitScanCompletion },
|
|
1226
|
+
'caizhilian.file-collection.run.result': { execute: getRunResult },
|
|
1227
|
+
};
|