weaver-work-cli 0.1.7 → 0.1.20
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 +11 -11
- 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 +432 -0
- package/dist/core/state.js +26 -0
- package/dist/internal/e10/auth/commands.js +2 -2
- package/dist/internal/e10/auth/session.js +14 -0
- package/dist/internal/e10/auth/xiaoe.js +116 -51
- package/dist/internal/e10/request-runtime.js +5 -0
- 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 +346 -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 +969 -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 +623 -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/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/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 +6 -3
- package/dist/shortcuts/workflow/operations/form.js +931 -533
- package/dist/shortcuts/workflow/operations/read.js +462 -81
- package/dist/shortcuts/workflow/operations/shared.js +44 -0
- package/dist/shortcuts/workflow/operations/write.js +760 -56
- 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 +2 -2
- package/docs/hrm.md +19 -9
- 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 +2 -2
- package/scripts/package-skill.mjs +33 -20
- 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/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 +216 -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 +136 -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 +118 -0
- package/skills/weaver-e10-caizhilian/references/org-browser.md +104 -0
- package/skills/weaver-e10-caizhilian/references/setting-attach.md +410 -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 +5079 -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 +54 -6
- package/skills/weaver-e10-hrm/references/employee.md +89 -15
- package/skills/weaver-e10-hrm/references/org.md +7 -4
- 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 +166 -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 +36 -25
- package/skills/weaver-e10-shared/references/e10-auth-and-session.md +10 -31
- package/skills/weaver-e10-shared/references/json-output-contract.md +20 -11
- 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-wenshuding/SKILL.md +5 -16
- package/skills/weaver-e10-wenshuding/references/source-manifest.json +7 -7
- package/skills/weaver-e10-workflow/SKILL.md +32 -37
- package/skills/weaver-e10-workflow/references/source-manifest.json +40 -77
- package/skills/weaver-e10-workflow/references/workflow-batch.md +90 -29
- package/skills/weaver-e10-workflow/references/workflow-create.md +79 -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 +37 -20
- package/skills/weaver-e10-workflow/references/workflow-share.md +18 -2
- package/skills/weaver-e10-workflow/references/workflow-view.md +4 -4
- package/skills/weaver-e10-yepiaotong/SKILL.md +75 -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-issuing.md +5 -5
- 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 +90 -10
- 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,328 @@
|
|
|
1
|
+
import { invoiceValidationError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* invoice 域的输出投影:把面向程序的完整 envelope 裁成面向阅读的视图。
|
|
4
|
+
*
|
|
5
|
+
* 背景:`invoice.list` 单条发票有 40+ 字段(`custom_field_*`、`rb`、`oa` 等对调用方无用),
|
|
6
|
+
* 10 条即 35KB。调用方要拿到"号码/金额/购销方"就得自己写解析脚本。
|
|
7
|
+
* 本模块提供三个出口,让 CLI 直接给出可读结果:
|
|
8
|
+
*
|
|
9
|
+
* - `--view summary`:语义化平表(仅 list 类 operation,字段口径与 `invoice.reim.candidates.list` 一致)
|
|
10
|
+
* - `--view detail`:单张发票的语义详情(仅 `invoice.get`),summary 字段 + 附件/费用说明/查验标记
|
|
11
|
+
* - `--fields a,b.c`:通用点路径投影,点路径必须存在于原结构(最小惊讶)
|
|
12
|
+
*
|
|
13
|
+
* 另有 `--format markdown`(见 markdown.ts):把上面的语义视图渲染成 markdown 文本,
|
|
14
|
+
* 属于"渲染档"而非数据档,与 `--json` 互斥。
|
|
15
|
+
*/
|
|
16
|
+
import { assertMarkdownSupported, markdownViewFor, normalizeFormat, } from './markdown.js';
|
|
17
|
+
/** `--view summary` 支持的 operation:data 结构里含发票列表 items 的读取类操作。 */
|
|
18
|
+
export const SUMMARY_OPERATIONS = new Set(['invoice.list', 'invoice.enterprise.list']);
|
|
19
|
+
/** `--view detail` 支持的 operation:data 结构里含 `infos[]`(每条带 info 包装)的详情类操作。 */
|
|
20
|
+
export const DETAIL_OPERATIONS = new Set(['invoice.get']);
|
|
21
|
+
export const OUTPUT_VIEWS = ['full', 'summary', 'detail'];
|
|
22
|
+
/**
|
|
23
|
+
* summary 视图保留的语义字段。命名与 `invoice.reim.candidates.list` 的 items 对齐
|
|
24
|
+
* (`buyer` = 购买方,`payer` = 销售方),避免同一业务概念在不同 operation 里换名。
|
|
25
|
+
*/
|
|
26
|
+
export const SUMMARY_ITEM_FIELDS = [
|
|
27
|
+
'fid',
|
|
28
|
+
'number',
|
|
29
|
+
'code',
|
|
30
|
+
'typeName',
|
|
31
|
+
'date',
|
|
32
|
+
'amount',
|
|
33
|
+
'total',
|
|
34
|
+
'taxAmount',
|
|
35
|
+
'buyer',
|
|
36
|
+
'buyerTaxNo',
|
|
37
|
+
'payer',
|
|
38
|
+
'payerTaxNo',
|
|
39
|
+
'valid',
|
|
40
|
+
'status',
|
|
41
|
+
'reimState',
|
|
42
|
+
'reimRequests',
|
|
43
|
+
'fileName',
|
|
44
|
+
'detailUrl',
|
|
45
|
+
];
|
|
46
|
+
function asRecord(value) {
|
|
47
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
48
|
+
}
|
|
49
|
+
function text(value) {
|
|
50
|
+
if (value === undefined || value === null)
|
|
51
|
+
return '';
|
|
52
|
+
return String(value).replace(/^\uFEFF/u, '').trim();
|
|
53
|
+
}
|
|
54
|
+
function numberOrUndefined(value) {
|
|
55
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 把一条原始发票对象裁成语义摘要。空值(`''` / `null` / 空数组)直接省键,
|
|
59
|
+
* 票面本身就有的 `'0'`(如税额)保留,避免制造"字段不存在"的歧义。
|
|
60
|
+
*/
|
|
61
|
+
export function summarizeInvoiceItem(item) {
|
|
62
|
+
const comm = asRecord(item.comm_info);
|
|
63
|
+
const pro = asRecord(comm.pro);
|
|
64
|
+
const price = asRecord(comm.price);
|
|
65
|
+
const buyer = asRecord(comm.buyer);
|
|
66
|
+
const payer = asRecord(comm.payer);
|
|
67
|
+
const modify = asRecord(item.modify_info);
|
|
68
|
+
const reimList = Array.isArray(asRecord(item.oreim).list_reim) ? asRecord(item.oreim).list_reim : [];
|
|
69
|
+
const summary = {
|
|
70
|
+
fid: text(item.fid ?? item.id),
|
|
71
|
+
number: text(item.number),
|
|
72
|
+
code: text(item.code),
|
|
73
|
+
typeName: text(pro.cname),
|
|
74
|
+
date: text(pro.date),
|
|
75
|
+
amount: text(price.amount),
|
|
76
|
+
total: text(price.total),
|
|
77
|
+
taxAmount: text(price.dtax),
|
|
78
|
+
buyer: text(buyer.company),
|
|
79
|
+
buyerTaxNo: text(buyer.tcode),
|
|
80
|
+
payer: text(payer.company),
|
|
81
|
+
payerTaxNo: text(payer.tcode),
|
|
82
|
+
valid: numberOrUndefined(pro.valid),
|
|
83
|
+
status: numberOrUndefined(pro.status),
|
|
84
|
+
reimState: numberOrUndefined(pro.sreim),
|
|
85
|
+
reimRequests: reimList.map((entry) => text(asRecord(entry).name)).filter(Boolean),
|
|
86
|
+
fileName: text(modify.fname),
|
|
87
|
+
detailUrl: text(item.detailUrl),
|
|
88
|
+
};
|
|
89
|
+
for (const [key, value] of Object.entries(summary)) {
|
|
90
|
+
if (value === '' || value === undefined || value === null)
|
|
91
|
+
delete summary[key];
|
|
92
|
+
else if (Array.isArray(value) && value.length === 0)
|
|
93
|
+
delete summary[key];
|
|
94
|
+
}
|
|
95
|
+
return summary;
|
|
96
|
+
}
|
|
97
|
+
/** 把 list 类 data 裁成 summary 视图:列表级汇总在前,明细在后。 */
|
|
98
|
+
export function summarizeListData(data) {
|
|
99
|
+
const items = Array.isArray(data.items) ? data.items : [];
|
|
100
|
+
const summary = {};
|
|
101
|
+
for (const key of ['total', 'totalAmount', 'totalAmountExcludingTax', 'hasMore', 'scope']) {
|
|
102
|
+
if (data[key] !== undefined && data[key] !== null)
|
|
103
|
+
summary[key] = data[key];
|
|
104
|
+
}
|
|
105
|
+
summary.items = items.map((item) => summarizeInvoiceItem(asRecord(item)));
|
|
106
|
+
summary.itemCount = summary.items.length;
|
|
107
|
+
return summary;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* detail 视图比 summary 多出来的语义字段:
|
|
111
|
+
* 附件清单、票面费用说明、开票人、查验标记(`is_valid`,与票面 `valid` 不是一个口径)。
|
|
112
|
+
*/
|
|
113
|
+
export const DETAIL_EXTRA_FIELDS = ['expenseNote', 'issuer', 'checkState', 'attachments'];
|
|
114
|
+
/** `--view detail` 下 items 的字段集:summary 语义字段 + detail 附加字段。 */
|
|
115
|
+
export const DETAIL_ITEM_FIELDS = [...SUMMARY_ITEM_FIELDS, ...DETAIL_EXTRA_FIELDS];
|
|
116
|
+
/** `info.ext` 是**字符串化的 JSON**(票面扩展字段),解析失败按空对象处理,不让脏数据打断输出。 */
|
|
117
|
+
function parseExt(value) {
|
|
118
|
+
if (value && typeof value === 'object')
|
|
119
|
+
return asRecord(value);
|
|
120
|
+
const raw = text(value);
|
|
121
|
+
if (!raw)
|
|
122
|
+
return {};
|
|
123
|
+
try {
|
|
124
|
+
return asRecord(JSON.parse(raw));
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return {};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function attachmentOf(entry) {
|
|
131
|
+
const record = asRecord(entry);
|
|
132
|
+
return {
|
|
133
|
+
id: text(record.fileId ?? record.id),
|
|
134
|
+
name: text(record.name),
|
|
135
|
+
type: text(record.type),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 把 `invoice.get` 的一条 `{ info, ret, is_valid, detailUrl }` 裁成语义详情。
|
|
140
|
+
* `info` 与 list 里的发票对象同形,所以直接复用 `summarizeInvoiceItem`,
|
|
141
|
+
* 避免同一业务概念在两条路径上出现两套字段口径。
|
|
142
|
+
*/
|
|
143
|
+
export function summarizeInvoiceDetailItem(wrapper) {
|
|
144
|
+
const info = asRecord(wrapper.info);
|
|
145
|
+
const detail = {
|
|
146
|
+
...summarizeInvoiceItem({
|
|
147
|
+
...info,
|
|
148
|
+
detailUrl: info.detailUrl ?? wrapper.detailUrl,
|
|
149
|
+
}),
|
|
150
|
+
};
|
|
151
|
+
const ext = parseExt(info.ext);
|
|
152
|
+
const expenseNote = text(ext.expenseDesc);
|
|
153
|
+
if (expenseNote)
|
|
154
|
+
detail.expenseNote = expenseNote;
|
|
155
|
+
const issuer = text(ext.issuer);
|
|
156
|
+
if (issuer)
|
|
157
|
+
detail.issuer = issuer;
|
|
158
|
+
// `is_valid` 是查验标记(0=未做过查验登记),与票面 `valid`(票面有效性)不是一个口径,
|
|
159
|
+
// 必须分开命名,否则调用方会把 0 误读成"这张票无效"。
|
|
160
|
+
if (typeof wrapper.is_valid === 'number')
|
|
161
|
+
detail.checkState = wrapper.is_valid;
|
|
162
|
+
const attachments = (Array.isArray(info.flist) ? info.flist : [])
|
|
163
|
+
.map(attachmentOf)
|
|
164
|
+
.filter((attachment) => attachment.id || attachment.name);
|
|
165
|
+
if (attachments.length)
|
|
166
|
+
detail.attachments = attachments;
|
|
167
|
+
return detail;
|
|
168
|
+
}
|
|
169
|
+
/** 把 `invoice.get` 的 data 裁成 detail 视图:保持 items 命名,与 list 视图一致。 */
|
|
170
|
+
export function summarizeDetailData(data) {
|
|
171
|
+
const infos = Array.isArray(data.infos) ? data.infos : [];
|
|
172
|
+
const detail = {};
|
|
173
|
+
if (data.scope !== undefined && data.scope !== null)
|
|
174
|
+
detail.scope = data.scope;
|
|
175
|
+
detail.items = infos.map((entry) => summarizeInvoiceDetailItem(asRecord(entry)));
|
|
176
|
+
detail.itemCount = detail.items.length;
|
|
177
|
+
return detail;
|
|
178
|
+
}
|
|
179
|
+
function readPath(source, path) {
|
|
180
|
+
let current = source;
|
|
181
|
+
for (const segment of path.split('.')) {
|
|
182
|
+
if (current === null || typeof current !== 'object' || Array.isArray(current)) {
|
|
183
|
+
return { found: false, value: undefined };
|
|
184
|
+
}
|
|
185
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
186
|
+
return { found: false, value: undefined };
|
|
187
|
+
}
|
|
188
|
+
current = current[segment];
|
|
189
|
+
}
|
|
190
|
+
return { found: true, value: current };
|
|
191
|
+
}
|
|
192
|
+
function writePath(target, path, value) {
|
|
193
|
+
const segments = path.split('.');
|
|
194
|
+
let node = target;
|
|
195
|
+
for (const segment of segments.slice(0, -1)) {
|
|
196
|
+
if (!node[segment] || typeof node[segment] !== 'object')
|
|
197
|
+
node[segment] = {};
|
|
198
|
+
node = node[segment];
|
|
199
|
+
}
|
|
200
|
+
node[segments[segments.length - 1]] = value;
|
|
201
|
+
}
|
|
202
|
+
/** 按点路径重建嵌套结构,保持与原 JSON 一致的形状。 */
|
|
203
|
+
export function pickPaths(source, fields) {
|
|
204
|
+
const picked = {};
|
|
205
|
+
const missing = [];
|
|
206
|
+
for (const field of fields) {
|
|
207
|
+
const { found, value } = readPath(source, field);
|
|
208
|
+
if (found)
|
|
209
|
+
writePath(picked, field, value);
|
|
210
|
+
else
|
|
211
|
+
missing.push(field);
|
|
212
|
+
}
|
|
213
|
+
return { picked, missing };
|
|
214
|
+
}
|
|
215
|
+
export function normalizeFields(value) {
|
|
216
|
+
if (value === undefined || value === null || value === '')
|
|
217
|
+
return undefined;
|
|
218
|
+
const fields = String(value)
|
|
219
|
+
.split(',')
|
|
220
|
+
.map((item) => item.trim())
|
|
221
|
+
.filter(Boolean);
|
|
222
|
+
if (!fields.length) {
|
|
223
|
+
throw invoiceValidationError('input_invalid', '--fields 必须至少包含一个字段路径');
|
|
224
|
+
}
|
|
225
|
+
return fields;
|
|
226
|
+
}
|
|
227
|
+
export function normalizeView(value) {
|
|
228
|
+
if (value === undefined || value === null || value === '')
|
|
229
|
+
return undefined;
|
|
230
|
+
const view = String(value).trim();
|
|
231
|
+
if (!OUTPUT_VIEWS.includes(view)) {
|
|
232
|
+
throw invoiceValidationError('view_invalid', `--view 只支持 ${OUTPUT_VIEWS.join(' / ')}`);
|
|
233
|
+
}
|
|
234
|
+
return view;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 把投影参数解析成"最终生效的视图"。`--format markdown` 是渲染档,
|
|
238
|
+
* 自带字段口径,因此由 operation 决定视图(list 类 → summary,详情类 → detail);
|
|
239
|
+
* 此时若显式传了别的视图属于口径冲突,直接报错而不是悄悄忽略。
|
|
240
|
+
*/
|
|
241
|
+
export function resolveView(operation, projection) {
|
|
242
|
+
const { view, fields, format } = projection;
|
|
243
|
+
if (format !== 'markdown')
|
|
244
|
+
return view ?? 'full';
|
|
245
|
+
assertMarkdownSupported(operation, format);
|
|
246
|
+
const expected = markdownViewFor(operation);
|
|
247
|
+
if (fields?.length) {
|
|
248
|
+
throw invoiceValidationError('input_conflict', '--format markdown 自带字段口径,不接受 --fields;要自定义字段请用 --fields 输出 JSON');
|
|
249
|
+
}
|
|
250
|
+
if (view && view !== expected) {
|
|
251
|
+
throw invoiceValidationError('input_conflict', `--format markdown 固定使用 ${expected} 视图,与 --view ${view} 冲突`);
|
|
252
|
+
}
|
|
253
|
+
return expected;
|
|
254
|
+
}
|
|
255
|
+
/** 供 CLI 侧解析 `--format`。 */
|
|
256
|
+
export function formatFrom(value) {
|
|
257
|
+
return normalizeFormat(value);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* 在发起业务请求**之前**校验投影参数是否可用。
|
|
261
|
+
* 参数写错就该立刻反馈,而不是先打一次网络请求再报 view_unsupported ——
|
|
262
|
+
* 否则认证失败/网络慢的场景会让人误以为"操作失败"而非"参数不支持"。
|
|
263
|
+
*/
|
|
264
|
+
export function assertProjectionSupported(operation, projection) {
|
|
265
|
+
const { view, fields } = projection;
|
|
266
|
+
if (view && fields?.length) {
|
|
267
|
+
throw invoiceValidationError('input_conflict', '不能同时传 --view 和 --fields');
|
|
268
|
+
}
|
|
269
|
+
if (view === 'summary' && !SUMMARY_OPERATIONS.has(operation)) {
|
|
270
|
+
throw invoiceValidationError('view_unsupported', `${operation} 不支持 --view summary(仅 ${[...SUMMARY_OPERATIONS].join('、')})`);
|
|
271
|
+
}
|
|
272
|
+
if (view === 'detail' && !DETAIL_OPERATIONS.has(operation)) {
|
|
273
|
+
throw invoiceValidationError('view_unsupported', `${operation} 不支持 --view detail(仅 ${[...DETAIL_OPERATIONS].join('、')})`);
|
|
274
|
+
}
|
|
275
|
+
// 渲染档的可用性与冲突同样要在请求前判掉(resolveView 内含格式白名单校验)。
|
|
276
|
+
resolveView(operation, projection);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* 应用投影。返回新的 data 与要写进 envelope `meta` 的说明,
|
|
280
|
+
* 让调用方知道输出被裁剪过、以及是否有写错的字段路径。
|
|
281
|
+
*/
|
|
282
|
+
export function applyInvoiceProjection(operation, data, projection) {
|
|
283
|
+
assertProjectionSupported(operation, projection);
|
|
284
|
+
const { fields } = projection;
|
|
285
|
+
const view = resolveView(operation, projection);
|
|
286
|
+
const activeMeta = (base) => ({
|
|
287
|
+
projection: { view, ...base },
|
|
288
|
+
});
|
|
289
|
+
if (view === 'summary') {
|
|
290
|
+
return {
|
|
291
|
+
data: summarizeListData(data),
|
|
292
|
+
meta: activeMeta({ omittedEmpty: true }),
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
if (view === 'detail') {
|
|
296
|
+
return {
|
|
297
|
+
data: summarizeDetailData(data),
|
|
298
|
+
meta: activeMeta({ omittedEmpty: true }),
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (fields?.length) {
|
|
302
|
+
const targets = Array.isArray(data.items) ? data.items : [data];
|
|
303
|
+
const missingSet = new Set(fields);
|
|
304
|
+
const projected = targets.map((target) => {
|
|
305
|
+
const { picked, missing } = pickPaths(asRecord(target), fields);
|
|
306
|
+
for (const field of fields) {
|
|
307
|
+
if (!missing.includes(field))
|
|
308
|
+
missingSet.delete(field);
|
|
309
|
+
}
|
|
310
|
+
return picked;
|
|
311
|
+
});
|
|
312
|
+
const missingFields = [...missingSet];
|
|
313
|
+
if (missingFields.length === fields.length) {
|
|
314
|
+
throw invoiceValidationError('field_not_found', `--fields 在 ${operation} 的输出里全部未命中:${fields.join(',')}`, { fields });
|
|
315
|
+
}
|
|
316
|
+
const projectedData = Array.isArray(data.items)
|
|
317
|
+
? { ...data, items: projected }
|
|
318
|
+
: projected[0];
|
|
319
|
+
return {
|
|
320
|
+
data: projectedData,
|
|
321
|
+
meta: activeMeta({
|
|
322
|
+
fields,
|
|
323
|
+
...(missingFields.length ? { missingFields } : {}),
|
|
324
|
+
}),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
return { data };
|
|
328
|
+
}
|
|
@@ -32,11 +32,27 @@ export function businessMessage(value) {
|
|
|
32
32
|
value.actionMsg?.msg,
|
|
33
33
|
value.data?.message,
|
|
34
34
|
value.data?.msg,
|
|
35
|
+
// EB(eBuilder formdata)把业务提示放在 datajson 内层:漏掉它时 EB 失败只剩一句
|
|
36
|
+
// “泛微接口返回业务失败”,真实原因(字段/权限/参数)全丢,排查成本极高。
|
|
37
|
+
value.datajson?.msg,
|
|
38
|
+
value.datajson?.message,
|
|
39
|
+
value.datajson?.errMsg,
|
|
40
|
+
value.datajson?.errorMsg,
|
|
41
|
+
value.datajson?.errorMessage,
|
|
35
42
|
];
|
|
36
43
|
for (const item of candidates) {
|
|
37
44
|
if (typeof item === 'string' && item.trim())
|
|
38
45
|
return item;
|
|
39
46
|
}
|
|
47
|
+
// 兜底:返回响应原文摘要,避免完全无法定位的报错。
|
|
48
|
+
try {
|
|
49
|
+
const raw = JSON.stringify(value);
|
|
50
|
+
if (raw && raw !== '{}' && raw !== 'null')
|
|
51
|
+
return `泛微接口返回业务失败:${raw.slice(0, 300)}`;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// 忽略序列化异常,走默认文案
|
|
55
|
+
}
|
|
40
56
|
return '泛微接口返回业务失败';
|
|
41
57
|
}
|
|
42
58
|
function businessCode(value) {
|
|
@@ -145,7 +161,8 @@ export function createMeetingHost(ctx, dependencies = {}) {
|
|
|
145
161
|
exitCode: 1,
|
|
146
162
|
});
|
|
147
163
|
}
|
|
148
|
-
|
|
164
|
+
const acceptBusiness = request.acceptBusiness ?? isBusinessSuccess;
|
|
165
|
+
if (!acceptBusiness(response.value)) {
|
|
149
166
|
const code = businessCode(response.value);
|
|
150
167
|
const message = businessMessage(response.value);
|
|
151
168
|
if (code === 403) {
|
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import { meetingOperationDefinitions } from './operations/registry.js';
|
|
2
2
|
/**
|
|
3
|
+
* 双模式(两套独立接口,路由由 meeting.env.detect 决定:EB 优先,失败回退标准版):
|
|
4
|
+
* - 标准版(Java REST,`/api/meeting/**`):meeting.list / create / change / cancel / delete /
|
|
5
|
+
* receipt / sign.list / sign.mark|back|clear 等,查询与写操作均走标准版契约。
|
|
6
|
+
* - EB 版(eBuilder formdata,`/api/ebuilder/form/formdata/v2/**`,实现见 operations/eb/):
|
|
7
|
+
* meeting.eb.* 覆盖 EB 版全部 interfacePk —— 会议 6.x / 会议室 2.x / 占用 5.x / 签到 1.x /
|
|
8
|
+
* 回执 4.x / 纪要 3.x / 会议类型 3.5 / 议题类型 8.x / 会议议题 9.x / 应用设置 7.x;
|
|
9
|
+
* 读操作单 operation(list 会先 count 再 list),写操作 prepare→apply 确认链。
|
|
10
|
+
* **建会 / 变更的 prepare 会先自动执行会议室与参会人冲突检测**(策略取应用设置
|
|
11
|
+
* room_conflict_chk/room_conflict、member_conflict_chk/member_conflict:命中禁止提交直接拒绝、
|
|
12
|
+
* 仅提醒只给 warnings、检测失败 fail-closed);另提供只读的 meeting.eb.conflict.room /
|
|
13
|
+
* meeting.eb.conflict.member(后者为 2 次请求方案,无 N+1)。
|
|
14
|
+
* 判定 eb 用 meeting.eb.*,判定 standard 用标准版 operations。
|
|
15
|
+
*
|
|
3
16
|
* 未实现能力(禁用边界,不得编造或绕过):
|
|
4
|
-
* - EB 版业务链路(query_mtDetail_list / create_meeting / 三件套 / 议题 / 纪要 / 报表):
|
|
5
|
-
* 依赖 eBuilder formdata 动态字段与工作流集成,未随 v1 实现。
|
|
6
17
|
* - 周期会议走工作流(repeatWorkFlowBaseIds 非空)与 onlyFlowCreate=1 的流程建会:
|
|
7
|
-
* 需要 workflow 集成,create.prepare
|
|
18
|
+
* 需要 workflow 集成,create.prepare 会主动拒绝并提示(EB 版可据 baseSet 的 only_flow_create 判断)。
|
|
8
19
|
* - 提前结束会议(meeting.over):服务端为空实现(假成功),CLI 不提供。
|
|
9
|
-
* -
|
|
10
|
-
*
|
|
20
|
+
* - 本人扫码签到(signMeeting):依赖现场二维码票据(qrticket)与设备 IP,AI 代签会破坏
|
|
21
|
+
* 签到真实性,不提供;请引导用户现场扫码或在会议页面操作。
|
|
22
|
+
* - 回收站(列表/还原/强制还原)、签到二维码与大屏签到、EB 版纪要创建(走 OpenAPI 无自定义接口):待评估。
|
|
23
|
+
* - **标准版**会议室/会议类型管理接口未实现;EB 版用 meeting.eb.room.* / meeting.eb.type.*。
|
|
11
24
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* 均走 prepare→apply 确认链。权限由服务端按会议状态判定并返回原文提示,CLI 原样透传。
|
|
25
|
+
* 权限由服务端按会议状态判定并返回原文提示(如“您没有变更权限!”),CLI 原样透传。
|
|
26
|
+
* delete 为软删(mt_detail.delete_type = 2,进回收站可还原),CLI 暂无还原能力。
|
|
15
27
|
*/
|
|
16
28
|
const WITHHELD = [
|
|
17
|
-
{
|
|
18
|
-
name: 'meeting.eb.*',
|
|
19
|
-
reason: 'EB 版业务链路依赖 eBuilder formdata 动态字段结构与工作流集成,v1 未实现;请使用 EB 版独立流程或后续版本。',
|
|
20
|
-
},
|
|
21
29
|
{
|
|
22
30
|
name: 'meeting.create.workflow',
|
|
23
31
|
reason: 'onlyFlowCreate=1 或周期会议配置工作流时必须走流程建会;CLI v1 未集成工作流发起,create.prepare 会主动拒绝。',
|
|
@@ -28,15 +36,19 @@ const WITHHELD = [
|
|
|
28
36
|
},
|
|
29
37
|
{
|
|
30
38
|
name: 'meeting.sign.qrcode',
|
|
31
|
-
reason: '
|
|
39
|
+
reason: '签到二维码(getQrCode / downLoadQrCode)与大屏签到未实现:入参契约未确认且属大屏/扫码场景,不得猜测参数。',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'meeting.sign.scan',
|
|
43
|
+
reason: '本人扫码签到(signMeeting)不提供:依赖现场二维码票据(qrticket)与设备 IP,由 AI 代签会破坏签到真实性;请引导用户现场扫码或走 H5 签到。补签/补签退/清除签到请用 meeting.sign.mark/back/clear(需确认链)。',
|
|
32
44
|
},
|
|
33
45
|
{
|
|
34
|
-
name: 'meeting.
|
|
35
|
-
reason: '
|
|
46
|
+
name: 'meeting.recycle.*',
|
|
47
|
+
reason: '回收站(getMeetingRecycleList / restoreMeetingRecycle / forceRestoreMeetingRecycle / cleanMeetingRecycleList)未实现。注意 delete 是软删(mt_detail.delete_type=2,会议进回收站可还原),CLI 暂无还原能力,如需恢复请引导用户到会议回收站页面操作。',
|
|
36
48
|
},
|
|
37
49
|
{
|
|
38
50
|
name: 'meeting.room.admin / meeting.type.admin',
|
|
39
|
-
reason: '
|
|
51
|
+
reason: '**标准版**会议室/会议类型管理接口(add/update/delete/lock)未实现;EB 版请用 meeting.eb.room.create/update/delete 与 meeting.eb.type.create/delete。',
|
|
40
52
|
},
|
|
41
53
|
];
|
|
42
54
|
function buildOperations() {
|
|
@@ -53,12 +65,12 @@ function buildOperations() {
|
|
|
53
65
|
export const meetingManifest = {
|
|
54
66
|
schemaVersion: 1,
|
|
55
67
|
name: 'meeting',
|
|
56
|
-
title: '泛微E10
|
|
68
|
+
title: '泛微E10会议管理(双模式:标准版 Java REST + EB 版 eBuilder)',
|
|
57
69
|
version: '1.0.0',
|
|
58
70
|
host: 'e10-meeting',
|
|
59
71
|
status: 'builtin',
|
|
60
72
|
sourceSkill: 'weaver-e10-meeting',
|
|
61
|
-
capabilities: ['env', 'meeting', 'room', 'type', 'conflict', 'lifecycle', 'receipt', 'sign'],
|
|
73
|
+
capabilities: ['env', 'meeting', 'room', 'type', 'conflict', 'lifecycle', 'receipt', 'sign', 'eb'],
|
|
62
74
|
operations: buildOperations(),
|
|
63
75
|
withheldOperations: WITHHELD,
|
|
64
76
|
};
|