weaver-work-cli 0.1.29 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/archive-U766FTFH.js +2537 -0
- package/dist/chunks/archive-oa-DMWEKX3L.js +1317 -0
- package/dist/chunks/asset-TCR7VDEV.js +2109 -0
- package/dist/chunks/attachment-content-AQNX5N3S.js +23 -0
- package/dist/chunks/blog-EVZWGDVM.js +2157 -0
- package/dist/chunks/caizhilian-JOWS6SL5.js +10087 -0
- package/dist/chunks/calendar-5WNCV66Q.js +1195 -0
- package/dist/chunks/chunk-2DUV44UX.js +15606 -0
- package/dist/chunks/chunk-324YPTC2.js +1607 -0
- package/dist/chunks/chunk-65QMVWHS.js +231 -0
- package/dist/chunks/chunk-6V7ZLF34.js +387 -0
- package/dist/chunks/chunk-AC7KJWC5.js +358 -0
- package/dist/chunks/chunk-AJ62BGAW.js +29 -0
- package/dist/chunks/chunk-BUSC6UAE.js +43 -0
- package/dist/chunks/chunk-CVZ2JOSW.js +62 -0
- package/dist/chunks/chunk-D4LTJSJD.js +477 -0
- package/dist/chunks/chunk-EG6ZU444.js +654 -0
- package/dist/chunks/chunk-EZALDOQH.js +383 -0
- package/dist/chunks/chunk-FMPJJYYI.js +106 -0
- package/dist/chunks/chunk-G2JSIUWF.js +769 -0
- package/dist/chunks/chunk-GCG2NMWR.js +703 -0
- package/dist/chunks/chunk-GPMFD4RD.js +75 -0
- package/dist/chunks/chunk-H3WDBYJW.js +508 -0
- package/dist/chunks/chunk-H6XSTSLM.js +2357 -0
- package/dist/chunks/chunk-J7RJTZSV.js +5556 -0
- package/dist/chunks/chunk-LUSPKZKY.js +53 -0
- package/dist/chunks/chunk-NIAJ5ZCG.js +73 -0
- package/dist/chunks/chunk-NOODWMCL.js +584 -0
- package/dist/chunks/chunk-OOUTBLZ4.js +51 -0
- package/dist/chunks/chunk-P26ZWSKU.js +73 -0
- package/dist/chunks/chunk-QWY6PGL6.js +3472 -0
- package/dist/chunks/chunk-R2IJAK7T.js +464 -0
- package/dist/chunks/chunk-R7O5PUWO.js +205 -0
- package/dist/chunks/chunk-RCGYCOMG.js +6962 -0
- package/dist/chunks/chunk-VZTXRG6X.js +403 -0
- package/dist/chunks/chunk-WHD4XMRP.js +161 -0
- package/dist/chunks/chunk-YLCYX7LE.js +371 -0
- package/dist/chunks/chunk-ZEDWSH32.js +68 -0
- package/dist/chunks/continuation-2CKSBLA6.js +11 -0
- package/dist/chunks/continuation-HZIZRZBX.js +13 -0
- package/dist/chunks/continuation-NLECEJPX.js +11 -0
- package/dist/chunks/ebuilder-form-NJ4YK6CC.js +2276 -0
- package/dist/chunks/ehr-MMYN36VA.js +5241 -0
- package/dist/chunks/employee-SAK2QYXX.js +11 -0
- package/dist/chunks/esb-HIWHOU7Q.js +141 -0
- package/dist/chunks/fna-KBACQTA5.js +1444 -0
- package/dist/chunks/host-3OHS5QUX.js +21 -0
- package/dist/chunks/host-IG6KEH5Q.js +19 -0
- package/dist/chunks/host-KQL5N4HO.js +23 -0
- package/dist/chunks/host-LLSZQCWR.js +17 -0
- package/dist/chunks/hrm-LYEC67ZQ.js +244 -0
- package/dist/chunks/im-RN2UKAEU.js +252 -0
- package/dist/chunks/invoice-EEPHLAF6.js +5179 -0
- package/dist/chunks/jiuchuanhui-WVVZYSJE.js +1940 -0
- package/dist/chunks/lazy-dispatch-MDOFFL2S.js +28 -0
- package/dist/chunks/mail-LNQLTF6L.js +2695 -0
- package/dist/chunks/meeting-XSD3BDVQ.js +504 -0
- package/dist/chunks/msg-parse-4GSQ2WTO.js +41 -0
- package/dist/chunks/okr-TMWTIU2K.js +2482 -0
- package/dist/chunks/plan-A2FSFA7T.js +2025 -0
- package/dist/chunks/project-T26QLBQF.js +1361 -0
- package/dist/chunks/registry-2VLUAESA.js +14 -0
- package/dist/chunks/registry-JCFEYXOE.js +18 -0
- package/dist/chunks/registry-NYPYMZXG.js +16 -0
- package/dist/chunks/registry-Q7OQJ3SU.js +19 -0
- package/dist/chunks/registry-ZJMJVWFA.js +19 -0
- package/dist/chunks/room-recommend-UR4ZDZS6.js +20 -0
- package/dist/chunks/schedule-5L2PM4M6.js +24 -0
- package/dist/chunks/state-Y2XBP6YE.js +15 -0
- package/dist/chunks/workflow-TR6PG2SL.js +245 -0
- package/dist/cmd/argv.js +45 -0
- package/dist/cmd/docs/index.js +3 -3
- package/dist/cmd/lazy-dispatch.js +20 -0
- package/dist/cmd/root.js +2 -4
- package/dist/cmd/setup/index.js +2 -2
- package/dist/cmd/skills/index.js +2 -2
- package/dist/core/package-paths.js +47 -0
- package/dist/index.js +163 -7
- package/dist/internal/e10/auth/xiaoe.js +3 -3
- package/dist/internal/e10/request-runtime.js +18 -62
- package/dist/internal/skills/detector.js +2 -2
- package/dist/shortcuts/contract/data/performance-catalog.js +1306 -0
- package/dist/shortcuts/contract/host.js +91 -35
- package/dist/shortcuts/contract/index.js +213 -0
- package/dist/shortcuts/contract/manifest.js +928 -0
- package/dist/shortcuts/contract/ooxml/docx.js +295 -0
- package/dist/shortcuts/contract/ooxml/xlsx.js +221 -0
- package/dist/shortcuts/contract/ooxml/zip.js +158 -0
- package/dist/shortcuts/contract/operations/assistant.js +1156 -0
- package/dist/shortcuts/contract/operations/clause-library.js +522 -0
- package/dist/shortcuts/contract/operations/compare.js +193 -0
- package/dist/shortcuts/contract/operations/credit-page.js +34 -0
- package/dist/shortcuts/contract/operations/flow.js +98 -0
- package/dist/shortcuts/contract/operations/page.js +66 -0
- package/dist/shortcuts/contract/operations/performance.js +733 -0
- package/dist/shortcuts/contract/operations/quote.js +557 -0
- package/dist/shortcuts/contract/operations/recommend.js +78 -0
- package/dist/shortcuts/contract/operations/registry.js +18 -0
- package/dist/shortcuts/contract/operations/review.js +83 -0
- package/dist/shortcuts/contract/operations/shared.js +37 -0
- package/dist/shortcuts/contract/operations/upload.js +108 -0
- package/dist/shortcuts/contract/operations/write.js +3 -2
- package/dist/shortcuts/index.js +140 -40
- package/dist/shortcuts/invoice/manifest.js +34 -11
- package/dist/shortcuts/invoice/operations/reim-auto.js +9 -0
- package/dist/shortcuts/invoice/operations/reim.js +81 -5
- package/dist/shortcuts/invoice/operations/shared.js +12 -5
- package/dist/shortcuts/meeting/host.js +45 -3
- package/dist/shortcuts/meeting/invitation/docx.js +442 -0
- package/dist/shortcuts/meeting/operations/attachment-content.js +418 -0
- package/dist/shortcuts/meeting/operations/attachment.js +442 -0
- package/dist/shortcuts/meeting/operations/eb/cache.js +57 -0
- package/dist/shortcuts/meeting/operations/eb/catalog.js +343 -28
- package/dist/shortcuts/meeting/operations/eb/conflict.js +372 -11
- package/dist/shortcuts/meeting/operations/eb/create-flow.js +710 -0
- package/dist/shortcuts/meeting/operations/eb/decision.js +47 -1
- package/dist/shortcuts/meeting/operations/eb/factory.js +129 -11
- package/dist/shortcuts/meeting/operations/eb/index.js +122 -2
- package/dist/shortcuts/meeting/operations/eb/room-recommend.js +378 -0
- package/dist/shortcuts/meeting/operations/eb/room-summary.js +84 -0
- package/dist/shortcuts/meeting/operations/eb/schedule.js +450 -0
- package/dist/shortcuts/meeting/operations/from-group-chat.js +576 -0
- package/dist/shortcuts/meeting/operations/invitation.js +458 -0
- package/dist/shortcuts/meeting/operations/minute-content.js +266 -0
- package/dist/shortcuts/meeting/operations/pipeline.js +489 -0
- package/dist/shortcuts/meeting/operations/qrcode.js +131 -0
- package/dist/shortcuts/meeting/operations/receipts.js +1 -1
- package/dist/shortcuts/meeting/operations/registry.js +18 -0
- package/dist/shortcuts/meeting/operations/summary.js +276 -0
- package/dist/shortcuts/meeting/operations/task-notify.js +325 -0
- package/dist/shortcuts/meeting/operations.js +42 -1
- package/dist/shortcuts/meeting/qr/encoder.js +427 -0
- package/dist/shortcuts/meeting/qr/render.js +103 -0
- package/dist/shortcuts/workflow/operations/form.js +17 -5
- package/docs/contract.md +39 -4
- package/docs/invoice.md +5 -5
- package/package.json +3 -2
- package/scripts/bundle.mjs +63 -0
- package/skill-template/business-info.json +25 -4
- package/skill-template/domains/jinchengda.md +16 -3
- package/skill-template/domains/yepiaotong.md +1 -1
- package/skills/weaver-e10-jinchengda/SKILL.md +111 -31
- package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +7 -13
- package/skills/weaver-e10-jinchengda/references/contract-ai-assistant.md +150 -0
- package/skills/weaver-e10-jinchengda/references/contract-ai-review.md +87 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +111 -0
- package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +0 -13
- package/skills/weaver-e10-jinchengda/references/contract-credit-page.md +50 -0
- package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +4 -2
- package/skills/weaver-e10-jinchengda/references/contract-doc-compare.md +74 -0
- package/skills/weaver-e10-jinchengda/references/contract-flow-launch.md +84 -0
- package/skills/weaver-e10-jinchengda/references/contract-performance-query.md +29 -0
- package/skills/weaver-e10-jinchengda/references/contract-quote-to-contract.md +28 -0
- package/skills/weaver-e10-jinchengda/references/contract-request-status.md +2 -21
- package/skills/weaver-e10-jinchengda/references/contract-request-write.md +0 -24
- package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +0 -17
- package/skills/weaver-e10-jinchengda/references/contract-template-recommend.md +70 -0
- package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +0 -15
- package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +0 -15
- package/skills/weaver-e10-jinchengda/references/source-manifest.json +1168 -152
- package/skills/weaver-e10-meeting/SKILL.md +493 -17
- package/skills/weaver-e10-meeting/references/meeting-change.md +4 -4
- package/skills/weaver-e10-meeting/references/meeting-create.md +6 -6
- package/skills/weaver-e10-meeting/references/meeting-eb.md +503 -27
- package/skills/weaver-e10-meeting/references/meeting-invitation.md +113 -0
- package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +6 -6
- package/skills/weaver-e10-meeting/references/meeting-minute-file.md +425 -0
- package/skills/weaver-e10-meeting/references/meeting-queries.md +4 -4
- package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +15 -15
- package/skills/weaver-e10-meeting/references/meeting-verification.md +19 -11
- package/skills/weaver-e10-meeting.zip +0 -0
- package/skills/weaver-e10-yepiaotong/SKILL.md +9 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +1 -1
- package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +6 -5
- package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +14 -11
- package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +97 -56
- package/skills/weaver-e10-yepiaotong/references/reim-examples.md +84 -60
- package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +142 -105
- package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +53 -194
- package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -7
- package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +164 -72
- package/skills/weaver-e10-yepiaotong/references/source-manifest.json +6 -0
- package/templates/meeting/invitation.docx +0 -0
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
import { createRequire as __esbuildCreateRequire } from 'node:module';
|
|
2
|
+
const require = __esbuildCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
SCHEMA_ID,
|
|
5
|
+
meetingStateDir,
|
|
6
|
+
meetingSuccess,
|
|
7
|
+
meetingValidationError,
|
|
8
|
+
schemaOf
|
|
9
|
+
} from "./chunk-H6XSTSLM.js";
|
|
10
|
+
|
|
11
|
+
// src/shortcuts/meeting/operations/attachment-content.ts
|
|
12
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
13
|
+
import { join, resolve } from "node:path";
|
|
14
|
+
|
|
15
|
+
// src/shortcuts/meeting/invitation/docx.ts
|
|
16
|
+
import { deflateRawSync, inflateRawSync } from "node:zlib";
|
|
17
|
+
var EOCD_SIG = 101010256;
|
|
18
|
+
var CEN_SIG = 33639248;
|
|
19
|
+
var LOC_SIG = 67324752;
|
|
20
|
+
function findEocd(buf) {
|
|
21
|
+
const min = Math.max(0, buf.length - 65535 - 22);
|
|
22
|
+
for (let i = buf.length - 22; i >= min; i -= 1) {
|
|
23
|
+
if (buf.readUInt32LE(i) === EOCD_SIG) return i;
|
|
24
|
+
}
|
|
25
|
+
throw new Error("docx \u89E3\u6790\u5931\u8D25\uFF1A\u627E\u4E0D\u5230 ZIP \u7ED3\u675F\u8BB0\u5F55\uFF08EOCD\uFF09");
|
|
26
|
+
}
|
|
27
|
+
function readDocxEntries(buf) {
|
|
28
|
+
const eocd = findEocd(buf);
|
|
29
|
+
const count = buf.readUInt16LE(eocd + 10);
|
|
30
|
+
let offset = buf.readUInt32LE(eocd + 16);
|
|
31
|
+
const entries = [];
|
|
32
|
+
for (let i = 0; i < count; i += 1) {
|
|
33
|
+
if (buf.readUInt32LE(offset) !== CEN_SIG) {
|
|
34
|
+
throw new Error("docx \u89E3\u6790\u5931\u8D25\uFF1A\u4E2D\u592E\u76EE\u5F55\u6761\u76EE\u7B7E\u540D\u4E0D\u5339\u914D");
|
|
35
|
+
}
|
|
36
|
+
const method = buf.readUInt16LE(offset + 10);
|
|
37
|
+
const compSize = buf.readUInt32LE(offset + 20);
|
|
38
|
+
const nameLen = buf.readUInt16LE(offset + 28);
|
|
39
|
+
const extraLen = buf.readUInt16LE(offset + 30);
|
|
40
|
+
const commentLen = buf.readUInt16LE(offset + 32);
|
|
41
|
+
const localOffset = buf.readUInt32LE(offset + 42);
|
|
42
|
+
const name = buf.subarray(offset + 46, offset + 46 + nameLen).toString("utf8");
|
|
43
|
+
if (buf.readUInt32LE(localOffset) !== LOC_SIG) {
|
|
44
|
+
throw new Error(`docx \u89E3\u6790\u5931\u8D25\uFF1A${name} \u7684\u672C\u5730\u5934\u7B7E\u540D\u4E0D\u5339\u914D`);
|
|
45
|
+
}
|
|
46
|
+
const localNameLen = buf.readUInt16LE(localOffset + 26);
|
|
47
|
+
const localExtraLen = buf.readUInt16LE(localOffset + 28);
|
|
48
|
+
const dataStart = localOffset + 30 + localNameLen + localExtraLen;
|
|
49
|
+
const raw = buf.subarray(dataStart, dataStart + compSize);
|
|
50
|
+
const data = method === 0 ? Buffer.from(raw) : inflateRawSync(raw);
|
|
51
|
+
entries.push({ name, data });
|
|
52
|
+
offset += 46 + nameLen + extraLen + commentLen;
|
|
53
|
+
}
|
|
54
|
+
return entries;
|
|
55
|
+
}
|
|
56
|
+
var CRC_TABLE = (() => {
|
|
57
|
+
const table = new Int32Array(256);
|
|
58
|
+
for (let i = 0; i < 256; i += 1) {
|
|
59
|
+
let c = i;
|
|
60
|
+
for (let k = 0; k < 8; k += 1) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
61
|
+
table[i] = c;
|
|
62
|
+
}
|
|
63
|
+
return table;
|
|
64
|
+
})();
|
|
65
|
+
function crc32(buf) {
|
|
66
|
+
let crc = -1;
|
|
67
|
+
for (let i = 0; i < buf.length; i += 1) crc = CRC_TABLE[(crc ^ buf[i]) & 255] ^ crc >>> 8;
|
|
68
|
+
return (crc ^ -1) >>> 0;
|
|
69
|
+
}
|
|
70
|
+
function dosDateTime(date) {
|
|
71
|
+
const time = (date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1) & 65535;
|
|
72
|
+
const d = (date.getFullYear() - 1980 << 9 | date.getMonth() + 1 << 5 | date.getDate()) & 65535;
|
|
73
|
+
return { time, date: d };
|
|
74
|
+
}
|
|
75
|
+
function writeDocxEntries(entries, now = /* @__PURE__ */ new Date()) {
|
|
76
|
+
const { time, date } = dosDateTime(now);
|
|
77
|
+
const locals = [];
|
|
78
|
+
const centrals = [];
|
|
79
|
+
let offset = 0;
|
|
80
|
+
for (const entry of entries) {
|
|
81
|
+
const nameBuf = Buffer.from(entry.name, "utf8");
|
|
82
|
+
const crc = crc32(entry.data);
|
|
83
|
+
const deflated = deflateRawSync(entry.data);
|
|
84
|
+
const useDeflate = deflated.length < entry.data.length;
|
|
85
|
+
const payload = useDeflate ? deflated : entry.data;
|
|
86
|
+
const method = useDeflate ? 8 : 0;
|
|
87
|
+
const local = Buffer.alloc(30);
|
|
88
|
+
local.writeUInt32LE(LOC_SIG, 0);
|
|
89
|
+
local.writeUInt16LE(20, 4);
|
|
90
|
+
local.writeUInt16LE(2048, 6);
|
|
91
|
+
local.writeUInt16LE(method, 8);
|
|
92
|
+
local.writeUInt16LE(time, 10);
|
|
93
|
+
local.writeUInt16LE(date, 12);
|
|
94
|
+
local.writeUInt32LE(crc, 14);
|
|
95
|
+
local.writeUInt32LE(payload.length, 18);
|
|
96
|
+
local.writeUInt32LE(entry.data.length, 22);
|
|
97
|
+
local.writeUInt16LE(nameBuf.length, 26);
|
|
98
|
+
local.writeUInt16LE(0, 28);
|
|
99
|
+
const central = Buffer.alloc(46);
|
|
100
|
+
central.writeUInt32LE(CEN_SIG, 0);
|
|
101
|
+
central.writeUInt16LE(20, 4);
|
|
102
|
+
central.writeUInt16LE(20, 6);
|
|
103
|
+
central.writeUInt16LE(2048, 8);
|
|
104
|
+
central.writeUInt16LE(method, 10);
|
|
105
|
+
central.writeUInt16LE(time, 12);
|
|
106
|
+
central.writeUInt16LE(date, 14);
|
|
107
|
+
central.writeUInt32LE(crc, 16);
|
|
108
|
+
central.writeUInt32LE(payload.length, 20);
|
|
109
|
+
central.writeUInt32LE(entry.data.length, 24);
|
|
110
|
+
central.writeUInt16LE(nameBuf.length, 28);
|
|
111
|
+
central.writeUInt16LE(0, 30);
|
|
112
|
+
central.writeUInt16LE(0, 32);
|
|
113
|
+
central.writeUInt16LE(0, 34);
|
|
114
|
+
central.writeUInt16LE(0, 36);
|
|
115
|
+
central.writeUInt32LE(0, 38);
|
|
116
|
+
central.writeUInt32LE(offset, 42);
|
|
117
|
+
locals.push(local, nameBuf, payload);
|
|
118
|
+
centrals.push(central, nameBuf);
|
|
119
|
+
offset += local.length + nameBuf.length + payload.length;
|
|
120
|
+
}
|
|
121
|
+
const centralBuf = Buffer.concat(centrals);
|
|
122
|
+
const eocd = Buffer.alloc(22);
|
|
123
|
+
eocd.writeUInt32LE(EOCD_SIG, 0);
|
|
124
|
+
eocd.writeUInt16LE(0, 4);
|
|
125
|
+
eocd.writeUInt16LE(0, 6);
|
|
126
|
+
eocd.writeUInt16LE(entries.length, 8);
|
|
127
|
+
eocd.writeUInt16LE(entries.length, 10);
|
|
128
|
+
eocd.writeUInt32LE(centralBuf.length, 12);
|
|
129
|
+
eocd.writeUInt32LE(offset, 16);
|
|
130
|
+
eocd.writeUInt16LE(0, 20);
|
|
131
|
+
return Buffer.concat([...locals, centralBuf, eocd]);
|
|
132
|
+
}
|
|
133
|
+
var PENDING_MARK = "\u3010\u5F85\u8865\u5145\u3011";
|
|
134
|
+
function unescapeXml(text) {
|
|
135
|
+
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
136
|
+
}
|
|
137
|
+
function escapeXml(text) {
|
|
138
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
139
|
+
}
|
|
140
|
+
var PLACEHOLDER_RE = /\{([A-Za-z_][A-Za-z0-9_.]*)\}/g;
|
|
141
|
+
var PLACEHOLDER_TEST = /\{[A-Za-z_][A-Za-z0-9_.]*\}/;
|
|
142
|
+
var UNSAFE_PARAGRAPH_RE = /<w:(drawing|pict|hyperlink|fldSimple|sdt|object|txbxContent)\b/;
|
|
143
|
+
function splitParagraph(paraXml) {
|
|
144
|
+
const openMatch = /^<w:p(?:\s[^>]*)?>/.exec(paraXml);
|
|
145
|
+
const open = openMatch ? openMatch[0] : "<w:p>";
|
|
146
|
+
let body = paraXml.slice(open.length).replace(/<\/w:p>\s*$/, "");
|
|
147
|
+
let pPr = "";
|
|
148
|
+
const pPrMatch = /^<w:pPr>[\s\S]*?<\/w:pPr>/.exec(body);
|
|
149
|
+
if (pPrMatch) {
|
|
150
|
+
pPr = pPrMatch[0];
|
|
151
|
+
body = body.slice(pPr.length);
|
|
152
|
+
}
|
|
153
|
+
return { open, pPr, body };
|
|
154
|
+
}
|
|
155
|
+
function parseRuns(body) {
|
|
156
|
+
const runs = [];
|
|
157
|
+
const runRe = /<w:r(?:\s[^>]*)?>([\s\S]*?)<\/w:r>/g;
|
|
158
|
+
let match;
|
|
159
|
+
while ((match = runRe.exec(body)) !== null) {
|
|
160
|
+
const inner = match[1];
|
|
161
|
+
const rPrMatch = /<w:rPr>[\s\S]*?<\/w:rPr>/.exec(inner);
|
|
162
|
+
const rPr = rPrMatch ? rPrMatch[0] : "";
|
|
163
|
+
let text = "";
|
|
164
|
+
const tRe = /<w:t(?:\s[^>]*)?>([\s\S]*?)<\/w:t>/g;
|
|
165
|
+
let tMatch;
|
|
166
|
+
while ((tMatch = tRe.exec(inner)) !== null) text += unescapeXml(tMatch[1]);
|
|
167
|
+
runs.push({ rPr, text });
|
|
168
|
+
}
|
|
169
|
+
return runs;
|
|
170
|
+
}
|
|
171
|
+
function withHighlight(rPr) {
|
|
172
|
+
const highlight = '<w:highlight w:val="yellow"/>';
|
|
173
|
+
if (!rPr) return `<w:rPr>${highlight}</w:rPr>`;
|
|
174
|
+
if (rPr.includes("<w:highlight")) return rPr;
|
|
175
|
+
return rPr.replace(/<\/w:rPr>$/, `${highlight}</w:rPr>`);
|
|
176
|
+
}
|
|
177
|
+
function emitRun(rPr, text) {
|
|
178
|
+
return `<w:r>${rPr}<w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r>`;
|
|
179
|
+
}
|
|
180
|
+
function replaceInParagraph(paraXml, resolver, filled, pending) {
|
|
181
|
+
if (!paraXml.includes("{")) return null;
|
|
182
|
+
const { open, pPr, body } = splitParagraph(paraXml);
|
|
183
|
+
const runs = parseRuns(body);
|
|
184
|
+
if (runs.length === 0) return null;
|
|
185
|
+
const concat = runs.map((run) => run.text).join("");
|
|
186
|
+
if (!PLACEHOLDER_TEST.test(concat)) return null;
|
|
187
|
+
if (UNSAFE_PARAGRAPH_RE.test(paraXml)) return "unsafe";
|
|
188
|
+
PLACEHOLDER_RE.lastIndex = 0;
|
|
189
|
+
const matches = [...concat.matchAll(PLACEHOLDER_RE)];
|
|
190
|
+
if (matches.length === 0) return null;
|
|
191
|
+
const spans = [];
|
|
192
|
+
let cursor = 0;
|
|
193
|
+
for (const run of runs) {
|
|
194
|
+
spans.push({ start: cursor, end: cursor + run.text.length });
|
|
195
|
+
cursor += run.text.length;
|
|
196
|
+
}
|
|
197
|
+
const runAt = (pos) => {
|
|
198
|
+
for (let i = 0; i < spans.length; i += 1) if (pos >= spans[i].start && pos < spans[i].end) return i;
|
|
199
|
+
return spans.length - 1;
|
|
200
|
+
};
|
|
201
|
+
const units = [];
|
|
202
|
+
runs.forEach((run, index) => {
|
|
203
|
+
for (const ch of run.text) units.push({ ch, run: index, highlight: false });
|
|
204
|
+
});
|
|
205
|
+
for (const match of [...matches].reverse()) {
|
|
206
|
+
const key = match[1];
|
|
207
|
+
const start = match.index ?? 0;
|
|
208
|
+
const end = start + match[0].length;
|
|
209
|
+
const value = resolver(key);
|
|
210
|
+
const text = value.pending ? PENDING_MARK : value.text;
|
|
211
|
+
(value.pending ? pending : filled).push(key);
|
|
212
|
+
const firstRun = runAt(start);
|
|
213
|
+
const replacement = [...text].map((ch) => ({ ch, run: firstRun, highlight: Boolean(value.pending) }));
|
|
214
|
+
units.splice(start, end - start, ...replacement);
|
|
215
|
+
}
|
|
216
|
+
const merged = [];
|
|
217
|
+
for (const unit of units) {
|
|
218
|
+
const rPr = runs[unit.run]?.rPr ?? "";
|
|
219
|
+
const last = merged[merged.length - 1];
|
|
220
|
+
if (last && last.rPr === rPr && last.highlight === unit.highlight) last.text += unit.ch;
|
|
221
|
+
else merged.push({ text: unit.ch, rPr, highlight: unit.highlight });
|
|
222
|
+
}
|
|
223
|
+
const rendered = merged.map((run) => emitRun(run.highlight ? withHighlight(run.rPr) : run.rPr, run.text)).join("");
|
|
224
|
+
return `${open}${pPr}${rendered}</w:p>`;
|
|
225
|
+
}
|
|
226
|
+
function replacePlaceholdersInXml(xml, resolver) {
|
|
227
|
+
const filled = [];
|
|
228
|
+
const pending = [];
|
|
229
|
+
let skippedParagraphs = 0;
|
|
230
|
+
const output = xml.replace(/<w:p(?:\s[^>]*)?>[\s\S]*?<\/w:p>/g, (paraXml) => {
|
|
231
|
+
if (!paraXml.includes("{")) return paraXml;
|
|
232
|
+
const replaced = replaceInParagraph(paraXml, resolver, filled, pending);
|
|
233
|
+
if (replaced === "unsafe") {
|
|
234
|
+
skippedParagraphs += 1;
|
|
235
|
+
return paraXml;
|
|
236
|
+
}
|
|
237
|
+
if (replaced === null) return paraXml;
|
|
238
|
+
return replaced;
|
|
239
|
+
});
|
|
240
|
+
return {
|
|
241
|
+
xml: output,
|
|
242
|
+
filled: [...new Set(filled)],
|
|
243
|
+
pending: [...new Set(pending)],
|
|
244
|
+
skippedParagraphs
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
var TR_RE = /<w:tr(?:\s[^>]*)?>[\s\S]*?<\/w:tr>/g;
|
|
248
|
+
var TC_RE = /<w:tc(?:\s[^>]*)?>[\s\S]*?<\/w:tc>/g;
|
|
249
|
+
var WT_RE = /<w:t(?:\s[^>]*)?>([^<]*)<\/w:t>/g;
|
|
250
|
+
function cellText(tc) {
|
|
251
|
+
return [...tc.matchAll(WT_RE)].map((match) => unescapeXml(match[1])).join("");
|
|
252
|
+
}
|
|
253
|
+
function setCellText(tc, text) {
|
|
254
|
+
const tcOpen = /^<w:tc(?:\s[^>]*)?>/.exec(tc)?.[0] ?? "<w:tc>";
|
|
255
|
+
const tcPr = /<w:tcPr>[\s\S]*?<\/w:tcPr>/.exec(tc)?.[0] ?? "";
|
|
256
|
+
const paragraphs = tc.match(/<w:p(?:\s[^>]*)?>[\s\S]*?<\/w:p>/g) ?? [];
|
|
257
|
+
const firstParagraph = paragraphs[0] ?? "<w:p></w:p>";
|
|
258
|
+
const pOpen = /^<w:p(?:\s[^>]*)?>/.exec(firstParagraph)?.[0] ?? "<w:p>";
|
|
259
|
+
const pPr = /<w:pPr>[\s\S]*?<\/w:pPr>/.exec(firstParagraph)?.[0] ?? "";
|
|
260
|
+
const firstRun = /<w:r(?:\s[^>]*)?>[\s\S]*?<\/w:r>/.exec(firstParagraph)?.[0] ?? "";
|
|
261
|
+
const rPr = /<w:rPr>[\s\S]*?<\/w:rPr>/.exec(firstRun)?.[0] ?? /<w:rPr>[\s\S]*?<\/w:rPr>/.exec(pPr)?.[0] ?? "";
|
|
262
|
+
const run = text ? `<w:r>${rPr}<w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r>` : "";
|
|
263
|
+
return `${tcOpen}${tcPr}${pOpen}${pPr}${run}</w:p></w:tc>`;
|
|
264
|
+
}
|
|
265
|
+
function fillTableRowsInXml(xml, option) {
|
|
266
|
+
const rows = option.rows.filter((row) => row.some((cell) => String(cell ?? "").trim() !== ""));
|
|
267
|
+
if (rows.length === 0) return { xml, filled: false, rowCount: 0 };
|
|
268
|
+
const tables = [...xml.matchAll(/<w:tbl(?:\s[^>]*)?>[\s\S]*?<\/w:tbl>/g)];
|
|
269
|
+
for (const table of tables) {
|
|
270
|
+
const tableXml = table[0];
|
|
271
|
+
const tableRows = tableXml.match(TR_RE) ?? [];
|
|
272
|
+
if (tableRows.length < 2) continue;
|
|
273
|
+
const headerRow = tableRows[0];
|
|
274
|
+
const headerText = (headerRow.match(TC_RE) ?? []).map(cellText).join(" ");
|
|
275
|
+
if (!headerText.includes(option.headerKeyword)) continue;
|
|
276
|
+
const dataRows = tableRows.slice(1);
|
|
277
|
+
const cloneSource = dataRows[dataRows.length - 1];
|
|
278
|
+
const shadingFill = (rowXml) => {
|
|
279
|
+
const matched = /<w:shd\b[^>]*w:fill="([^"]*)"/.exec(rowXml);
|
|
280
|
+
return (matched?.[1] ?? "").trim().toUpperCase();
|
|
281
|
+
};
|
|
282
|
+
const isShadedRow = (rowXml) => {
|
|
283
|
+
const fill = shadingFill(rowXml);
|
|
284
|
+
return fill !== "" && fill !== "AUTO" && fill !== "FFFFFF";
|
|
285
|
+
};
|
|
286
|
+
const shadedRow = dataRows.find((row) => isShadedRow(row));
|
|
287
|
+
const plainRow = dataRows.find((row) => !isShadedRow(row));
|
|
288
|
+
const hasZebra = Boolean(shadedRow && plainRow);
|
|
289
|
+
const rebuilt = [headerRow];
|
|
290
|
+
rows.forEach((values, index) => {
|
|
291
|
+
const base = hasZebra ? index % 2 === 0 ? shadedRow : plainRow : dataRows[index] ?? cloneSource;
|
|
292
|
+
const trOpen = /^<w:tr(?:\s[^>]*)?>/.exec(base)?.[0] ?? "<w:tr>";
|
|
293
|
+
const trPr = /<w:trPr>[\s\S]*?<\/w:trPr>/.exec(base)?.[0] ?? "";
|
|
294
|
+
const cells = base.match(TC_RE) ?? [];
|
|
295
|
+
const rebuiltCells = cells.map((cell, cellIndex) => setCellText(cell, values[cellIndex] ?? ""));
|
|
296
|
+
rebuilt.push(`${trOpen}${trPr}${rebuiltCells.join("")}</w:tr>`);
|
|
297
|
+
});
|
|
298
|
+
const firstRowIndex = tableXml.indexOf(headerRow);
|
|
299
|
+
const head = tableXml.slice(0, firstRowIndex);
|
|
300
|
+
const newTableXml = `${head}${rebuilt.join("")}</w:tbl>`;
|
|
301
|
+
const start = table.index ?? 0;
|
|
302
|
+
return {
|
|
303
|
+
xml: `${xml.slice(0, start)}${newTableXml}${xml.slice(start + tableXml.length)}`,
|
|
304
|
+
filled: true,
|
|
305
|
+
rowCount: rows.length
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
return { xml, filled: false, rowCount: 0 };
|
|
309
|
+
}
|
|
310
|
+
var TEXT_PART_RE = /^word\/(document|header\d*|footer\d*|footnotes|endnotes)\.xml$/;
|
|
311
|
+
function renderDocx(template, resolver, options = {}) {
|
|
312
|
+
const entries = readDocxEntries(template);
|
|
313
|
+
const filled = /* @__PURE__ */ new Set();
|
|
314
|
+
const pending = /* @__PURE__ */ new Set();
|
|
315
|
+
let skippedParagraphs = 0;
|
|
316
|
+
let agenda;
|
|
317
|
+
const updated = entries.map((entry) => {
|
|
318
|
+
if (!TEXT_PART_RE.test(entry.name)) return entry;
|
|
319
|
+
let xml = entry.data.toString("utf8");
|
|
320
|
+
if (options.agenda && entry.name === "word/document.xml") {
|
|
321
|
+
const tableResult = fillTableRowsInXml(xml, options.agenda);
|
|
322
|
+
agenda = { filled: tableResult.filled, rowCount: tableResult.rowCount };
|
|
323
|
+
xml = tableResult.xml;
|
|
324
|
+
}
|
|
325
|
+
if (!xml.includes("{")) {
|
|
326
|
+
return xml === entry.data.toString("utf8") ? entry : { name: entry.name, data: Buffer.from(xml, "utf8") };
|
|
327
|
+
}
|
|
328
|
+
const result = replacePlaceholdersInXml(xml, resolver);
|
|
329
|
+
result.filled.forEach((key) => filled.add(key));
|
|
330
|
+
result.pending.forEach((key) => pending.add(key));
|
|
331
|
+
skippedParagraphs += result.skippedParagraphs;
|
|
332
|
+
return { name: entry.name, data: Buffer.from(result.xml, "utf8") };
|
|
333
|
+
});
|
|
334
|
+
return {
|
|
335
|
+
buffer: writeDocxEntries(updated),
|
|
336
|
+
filled: [...filled],
|
|
337
|
+
pending: [...pending],
|
|
338
|
+
skippedParagraphs,
|
|
339
|
+
...options.agenda ? { agenda: agenda ?? { filled: false, rowCount: 0 } } : {}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// src/shortcuts/meeting/operations/attachment-content.ts
|
|
344
|
+
var MEETING_FILE_FIELDS = ["mt_accessorys", "project_files"];
|
|
345
|
+
var FIELD_LABELS = {
|
|
346
|
+
mt_accessorys: "\u4F1A\u8BAE\u9644\u4EF6",
|
|
347
|
+
project_files: "\u9879\u76EE\u6587\u4EF6",
|
|
348
|
+
related_materials: "\u8BAE\u9898\u8D44\u6599"
|
|
349
|
+
};
|
|
350
|
+
var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([".txt", ".md", ".csv", ".json", ".xml", ".html", ".htm", ".log", ".yaml", ".yml", ".tsv"]);
|
|
351
|
+
function looksLikeFileId(value) {
|
|
352
|
+
return /^\d{15,}$/.test(String(value ?? "").trim());
|
|
353
|
+
}
|
|
354
|
+
function parseFileIdList(value) {
|
|
355
|
+
if (value === void 0 || value === null) return [];
|
|
356
|
+
if (Array.isArray(value)) {
|
|
357
|
+
return value.map((item) => item && typeof item === "object" ? String(item.id ?? "") : String(item ?? "")).map((item) => item.trim()).filter((item) => item !== "");
|
|
358
|
+
}
|
|
359
|
+
const text = String(value).trim();
|
|
360
|
+
if (text === "") return [];
|
|
361
|
+
if (text.startsWith("[")) {
|
|
362
|
+
try {
|
|
363
|
+
return parseFileIdList(JSON.parse(text));
|
|
364
|
+
} catch {
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return text.split(/[,;,;\s]+/).map((item) => item.trim()).filter((item) => item !== "" && item !== "[]");
|
|
368
|
+
}
|
|
369
|
+
async function readRawMainTable(env, interfacePk, id, operation) {
|
|
370
|
+
const session = await env.host.getSession();
|
|
371
|
+
const response = await env.host.request({
|
|
372
|
+
method: "POST",
|
|
373
|
+
path: `/api/ebuilder/form/formdata/v2/getFormDataByPk/${interfacePk}`,
|
|
374
|
+
operation,
|
|
375
|
+
body: { datajson: { mainTable: { id }, header: { operator: session.userId } } },
|
|
376
|
+
acceptBusiness: (value) => {
|
|
377
|
+
if (!value || typeof value !== "object") return false;
|
|
378
|
+
if (typeof value.status === "boolean") return value.status;
|
|
379
|
+
return Number(value.code ?? 200) === 200;
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
const dj = response?.datajson ?? response?.data ?? {};
|
|
383
|
+
const rows = dj?.datas ?? dj?.data ?? (Array.isArray(dj) ? dj : []);
|
|
384
|
+
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
385
|
+
return first?.mainTable ?? first ?? {};
|
|
386
|
+
}
|
|
387
|
+
async function listMeetingAttachments(env, mtId) {
|
|
388
|
+
const main = await readRawMainTable(env, "query_mtDetail_info", mtId, "meeting.attachment.list");
|
|
389
|
+
const refs = [];
|
|
390
|
+
for (const field of MEETING_FILE_FIELDS) {
|
|
391
|
+
for (const value of parseFileIdList(main[field])) {
|
|
392
|
+
refs.push({
|
|
393
|
+
fileId: value,
|
|
394
|
+
idLike: looksLikeFileId(value),
|
|
395
|
+
source: field,
|
|
396
|
+
sourceLabel: FIELD_LABELS[field] ?? field,
|
|
397
|
+
ownerId: mtId
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
refs,
|
|
403
|
+
raw: Object.fromEntries(MEETING_FILE_FIELDS.map((field) => [field, main[field] ?? ""]))
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
async function listTopicAttachments(env, topicId) {
|
|
407
|
+
const main = await readRawMainTable(env, "query_mt_topic_info_new", topicId, "meeting.attachment.list");
|
|
408
|
+
return parseFileIdList(main.related_materials).map((value) => ({
|
|
409
|
+
fileId: value,
|
|
410
|
+
idLike: looksLikeFileId(value),
|
|
411
|
+
source: "related_materials",
|
|
412
|
+
sourceLabel: FIELD_LABELS.related_materials,
|
|
413
|
+
ownerId: topicId
|
|
414
|
+
}));
|
|
415
|
+
}
|
|
416
|
+
function extFromContentType(contentType) {
|
|
417
|
+
const text = String(contentType ?? "").toLowerCase();
|
|
418
|
+
if (text.includes("wordprocessingml")) return ".docx";
|
|
419
|
+
if (text.includes("spreadsheetml")) return ".xlsx";
|
|
420
|
+
if (text.includes("presentationml")) return ".pptx";
|
|
421
|
+
if (text.includes("pdf")) return ".pdf";
|
|
422
|
+
if (text.includes("json")) return ".json";
|
|
423
|
+
if (text.includes("html")) return ".html";
|
|
424
|
+
if (text.includes("plain")) return ".txt";
|
|
425
|
+
return "";
|
|
426
|
+
}
|
|
427
|
+
function nameFromDisposition(disposition) {
|
|
428
|
+
const text = String(disposition ?? "");
|
|
429
|
+
const encoded = /filename\*=UTF-8''([^;]+)/i.exec(text);
|
|
430
|
+
if (encoded) {
|
|
431
|
+
try {
|
|
432
|
+
return decodeURIComponent(encoded[1]).trim();
|
|
433
|
+
} catch {
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
const plain = /filename="?([^";]+)"?/i.exec(text);
|
|
437
|
+
return plain ? plain[1].trim() : "";
|
|
438
|
+
}
|
|
439
|
+
async function downloadMeetingFile(env, fileId, options = {}) {
|
|
440
|
+
if (!env.host.download) {
|
|
441
|
+
throw meetingValidationError("download_unsupported", "\u5F53\u524D host \u4E0D\u652F\u6301\u4E8C\u8FDB\u5236\u4E0B\u8F7D\uFF08\u6D4B\u8BD5\u66FF\u8EAB\uFF1F\uFF09\uFF0C\u65E0\u6CD5\u83B7\u53D6\u9644\u4EF6\u5185\u5BB9");
|
|
442
|
+
}
|
|
443
|
+
const response = await env.host.download({
|
|
444
|
+
path: `/api/file/remotedownload/${encodeURIComponent(fileId)}/meeting/true`
|
|
445
|
+
});
|
|
446
|
+
const dispositionName = nameFromDisposition(response.contentDisposition ?? "");
|
|
447
|
+
const ext = extFromContentType(response.contentType);
|
|
448
|
+
const baseName = (options.fileName ?? dispositionName) || `${fileId}${ext}`;
|
|
449
|
+
const safeName = baseName.replace(/[\\/:*?"<>|]/g, "_");
|
|
450
|
+
const dir = options.outDir ? resolve(options.outDir) : join(meetingStateDir(env.ctx), "attachments");
|
|
451
|
+
await mkdir(dir, { recursive: true });
|
|
452
|
+
const target = join(dir, safeName);
|
|
453
|
+
await writeFile(target, response.buffer);
|
|
454
|
+
return { path: target, bytes: response.buffer.length, contentType: response.contentType };
|
|
455
|
+
}
|
|
456
|
+
function decodeText(buffer) {
|
|
457
|
+
const utf8 = buffer.toString("utf8");
|
|
458
|
+
if (utf8.includes("\uFFFD")) {
|
|
459
|
+
try {
|
|
460
|
+
return new TextDecoder("gb18030").decode(buffer);
|
|
461
|
+
} catch {
|
|
462
|
+
return utf8;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return utf8;
|
|
466
|
+
}
|
|
467
|
+
function stripXml(xml) {
|
|
468
|
+
return xml.replace(/<w:p[ >]/g, "\n<w:p ").replace(/<\/w:p>/g, "\n").replace(/<[^>]+>/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\n{2,}/g, "\n").trim();
|
|
469
|
+
}
|
|
470
|
+
function xlsxToText(buffer) {
|
|
471
|
+
const entries = readDocxEntries(buffer);
|
|
472
|
+
const find = (suffix) => {
|
|
473
|
+
const entry = entries.find((item) => item.name === suffix);
|
|
474
|
+
return entry ? Buffer.from(entry.data).toString("utf8") : "";
|
|
475
|
+
};
|
|
476
|
+
const sharedXml = find("xl/sharedStrings.xml");
|
|
477
|
+
const shared = [...sharedXml.matchAll(/<si>([\s\S]*?)<\/si>/g)].map((match) => stripXml(match[1]).replace(/\n/g, " "));
|
|
478
|
+
const sheetPaths = entries.map((item) => item.name).filter((path) => /^xl\/worksheets\/sheet\d+\.xml$/.test(path)).sort();
|
|
479
|
+
const first = sheetPaths[0];
|
|
480
|
+
if (!first) return "";
|
|
481
|
+
const sheetXml = find(first);
|
|
482
|
+
const lines = [];
|
|
483
|
+
for (const rowMatch of sheetXml.matchAll(/<row[^>]*>([\s\S]*?)<\/row>/g)) {
|
|
484
|
+
const cells = [];
|
|
485
|
+
for (const cellMatch of rowMatch[1].matchAll(/<c\b([^>]*)>([\s\S]*?)<\/c>/g)) {
|
|
486
|
+
const attrs = cellMatch[1] ?? "";
|
|
487
|
+
const type = /\bt="([^"]+)"/.exec(attrs)?.[1] ?? "";
|
|
488
|
+
const inner = cellMatch[2] ?? "";
|
|
489
|
+
const value = /<v>([\s\S]*?)<\/v>/.exec(inner)?.[1] ?? "";
|
|
490
|
+
const inline = /<is>([\s\S]*?)<\/is>/.exec(inner)?.[1] ?? "";
|
|
491
|
+
if (type === "s") cells.push(shared[Number(value)] ?? "");
|
|
492
|
+
else if (type === "inlineStr") cells.push(stripXml(inline));
|
|
493
|
+
else cells.push(stripXml(value));
|
|
494
|
+
}
|
|
495
|
+
if (cells.some((cell) => cell !== "")) lines.push(cells.join(" "));
|
|
496
|
+
}
|
|
497
|
+
return lines.join("\n");
|
|
498
|
+
}
|
|
499
|
+
function pptxToText(buffer) {
|
|
500
|
+
const entries = readDocxEntries(buffer);
|
|
501
|
+
return entries.filter((item) => /^ppt\/slides\/slide\d+\.xml$/.test(item.name)).sort((left, right) => left.name.localeCompare(right.name, void 0, { numeric: true })).map((item, index) => `# \u7B2C ${index + 1} \u9875
|
|
502
|
+
${stripXml(Buffer.from(item.data).toString("utf8"))}`).join("\n\n");
|
|
503
|
+
}
|
|
504
|
+
function extractText(buffer, fileName, contentType = "") {
|
|
505
|
+
const lower = String(fileName ?? "").toLowerCase();
|
|
506
|
+
const ext = /\.[a-z0-9]+$/.exec(lower)?.[0] ?? "";
|
|
507
|
+
if (ext === ".docx" || contentType.includes("wordprocessingml")) {
|
|
508
|
+
const entries = readDocxEntries(buffer);
|
|
509
|
+
const document = entries.find((item) => item.name === "word/document.xml");
|
|
510
|
+
return { text: document ? stripXml(Buffer.from(document.data).toString("utf8")) : "", kind: "docx" };
|
|
511
|
+
}
|
|
512
|
+
if (ext === ".xlsx" || contentType.includes("spreadsheetml")) {
|
|
513
|
+
return { text: xlsxToText(buffer), kind: "xlsx" };
|
|
514
|
+
}
|
|
515
|
+
if (ext === ".pptx" || contentType.includes("presentationml")) {
|
|
516
|
+
return { text: pptxToText(buffer), kind: "pptx" };
|
|
517
|
+
}
|
|
518
|
+
if (TEXT_EXTENSIONS.has(ext) || contentType.startsWith("text/") || contentType.includes("json") || contentType.includes("xml")) {
|
|
519
|
+
return { text: decodeText(buffer), kind: "text" };
|
|
520
|
+
}
|
|
521
|
+
return { text: "", kind: "unsupported" };
|
|
522
|
+
}
|
|
523
|
+
var attachmentList = {
|
|
524
|
+
name: "meeting.attachment.list",
|
|
525
|
+
resource: "attachment",
|
|
526
|
+
method: "list",
|
|
527
|
+
action: "meeting.attachment.list",
|
|
528
|
+
summary: "\u67E5\u8BE2\u4F1A\u8BAE/\u8BAE\u9898\u7684\u9644\u4EF6\u6E05\u5355\uFF08\u8FD4\u56DE fileId\uFF09\uFF1A\u4F1A\u8BAE\u9644\u4EF6 mt_accessorys\u3001\u9879\u76EE\u6587\u4EF6 project_files\u3001\u8BAE\u9898\u8D44\u6599 related_materials\uFF1B\u76F4\u63A5\u8BFB EB \u8BE6\u60C5\u539F\u59CB\u503C\uFF0C\u4E0D\u7ECF\u6458\u8981\u5C42",
|
|
529
|
+
capability: "attachment",
|
|
530
|
+
risk: "read",
|
|
531
|
+
inputSchema: schemaOf(
|
|
532
|
+
{
|
|
533
|
+
mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF08\u67E5\u4F1A\u8BAE\u9644\u4EF6\u65F6\u5FC5\u586B\uFF0C\u4E0E topicId \u4E8C\u9009\u4E00\uFF09" },
|
|
534
|
+
topicId: { ...SCHEMA_ID, description: "\u8BAE\u9898 id\uFF08\u67E5\u8BAE\u9898\u8D44\u6599\u65F6\u7528\uFF09" }
|
|
535
|
+
},
|
|
536
|
+
{ required: [] }
|
|
537
|
+
),
|
|
538
|
+
handler: async (args, env) => {
|
|
539
|
+
const mtId = String(args.mtId ?? "").trim();
|
|
540
|
+
const topicId = String(args.topicId ?? "").trim();
|
|
541
|
+
if (!mtId && !topicId) {
|
|
542
|
+
throw meetingValidationError("id_required", "\u5FC5\u987B\u63D0\u4F9B mtId\uFF08\u4F1A\u8BAE\uFF09\u6216 topicId\uFF08\u8BAE\u9898\uFF09");
|
|
543
|
+
}
|
|
544
|
+
const refs = [];
|
|
545
|
+
let raw = {};
|
|
546
|
+
if (mtId) {
|
|
547
|
+
const result = await listMeetingAttachments(env, mtId);
|
|
548
|
+
refs.push(...result.refs);
|
|
549
|
+
raw = result.raw;
|
|
550
|
+
}
|
|
551
|
+
if (topicId) refs.push(...await listTopicAttachments(env, topicId));
|
|
552
|
+
return meetingSuccess(
|
|
553
|
+
"meeting.attachment.list",
|
|
554
|
+
{
|
|
555
|
+
mtId: mtId || null,
|
|
556
|
+
topicId: topicId || null,
|
|
557
|
+
count: refs.length,
|
|
558
|
+
items: refs,
|
|
559
|
+
raw
|
|
560
|
+
},
|
|
561
|
+
refs.length === 0 ? { warnings: ["\u8BE5\u4F1A\u8BAE/\u8BAE\u9898\u5F53\u524D\u6CA1\u6709\u9644\u4EF6\uFF08\u6216\u5B57\u6BB5\u503C\u4E3A\u7A7A\uFF09"] } : {}
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
var attachmentDownload = {
|
|
566
|
+
name: "meeting.attachment.download",
|
|
567
|
+
resource: "attachment",
|
|
568
|
+
method: "download",
|
|
569
|
+
action: "meeting.attachment.download",
|
|
570
|
+
summary: "\u6309 fileId \u4E0B\u8F7D\u9644\u4EF6\u5230\u672C\u5730\uFF08\u9ED8\u8BA4 ~/.weaver-work-cli/meeting/attachments/\uFF09\uFF1B\u4E5F\u53EF\u4F20 mtId \u4E00\u6B21\u4E0B\u8F7D\u8BE5\u4F1A\u8BAE\u5168\u90E8\u9644\u4EF6",
|
|
571
|
+
capability: "attachment",
|
|
572
|
+
risk: "read",
|
|
573
|
+
inputSchema: schemaOf(
|
|
574
|
+
{
|
|
575
|
+
fileId: { ...SCHEMA_ID, description: "\u6587\u4EF6 id\uFF08\u4E0E mtId \u4E8C\u9009\u4E00\uFF09" },
|
|
576
|
+
mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF1A\u4E00\u6B21\u4E0B\u8F7D\u8BE5\u4F1A\u8BAE\u5168\u90E8\u9644\u4EF6\u4E0E\u9879\u76EE\u6587\u4EF6" },
|
|
577
|
+
outDir: { type: "string", description: "\u843D\u5730\u76EE\u5F55\uFF08\u9ED8\u8BA4 <state>/meeting/attachments\uFF09" },
|
|
578
|
+
fileName: { type: "string", description: "\u6307\u5B9A\u6587\u4EF6\u540D\uFF08\u4EC5\u5355\u6587\u4EF6\u65F6\u751F\u6548\uFF09" }
|
|
579
|
+
},
|
|
580
|
+
{ required: [] }
|
|
581
|
+
),
|
|
582
|
+
handler: async (args, env) => {
|
|
583
|
+
const fileId = String(args.fileId ?? "").trim();
|
|
584
|
+
const mtId = String(args.mtId ?? "").trim();
|
|
585
|
+
if (!fileId && !mtId) {
|
|
586
|
+
throw meetingValidationError("id_required", "\u5FC5\u987B\u63D0\u4F9B fileId \u6216 mtId");
|
|
587
|
+
}
|
|
588
|
+
const outDir = typeof args.outDir === "string" && args.outDir.trim() !== "" ? String(args.outDir) : void 0;
|
|
589
|
+
if (fileId) {
|
|
590
|
+
const one = await downloadMeetingFile(env, fileId, {
|
|
591
|
+
...outDir ? { outDir } : {},
|
|
592
|
+
...typeof args.fileName === "string" ? { fileName: String(args.fileName) } : {}
|
|
593
|
+
});
|
|
594
|
+
return meetingSuccess("meeting.attachment.download", { downloaded: [{ fileId, ...one }], count: 1 });
|
|
595
|
+
}
|
|
596
|
+
const refs = (await listMeetingAttachments(env, mtId)).refs;
|
|
597
|
+
if (refs.length === 0) {
|
|
598
|
+
throw meetingValidationError("attachment_empty", `\u4F1A\u8BAE ${mtId} \u6CA1\u6709\u9644\u4EF6\u53EF\u4E0B\u8F7D`);
|
|
599
|
+
}
|
|
600
|
+
const downloaded = [];
|
|
601
|
+
const warnings = [];
|
|
602
|
+
for (const ref of refs) {
|
|
603
|
+
try {
|
|
604
|
+
const one = await downloadMeetingFile(env, ref.fileId, { ...outDir ? { outDir } : {} });
|
|
605
|
+
downloaded.push({ fileId: ref.fileId, source: ref.source, ...one });
|
|
606
|
+
} catch (error) {
|
|
607
|
+
warnings.push(`\u9644\u4EF6 ${ref.fileId}\uFF08${ref.sourceLabel}\uFF09\u4E0B\u8F7D\u5931\u8D25\uFF1A${String(error?.message ?? error).slice(0, 120)}`);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return meetingSuccess(
|
|
611
|
+
"meeting.attachment.download",
|
|
612
|
+
{ mtId, downloaded, count: downloaded.length },
|
|
613
|
+
warnings.length > 0 ? { warnings } : {}
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
var attachmentExtract = {
|
|
618
|
+
name: "meeting.attachment.extract",
|
|
619
|
+
resource: "attachment",
|
|
620
|
+
method: "extract",
|
|
621
|
+
action: "meeting.attachment.extract",
|
|
622
|
+
summary: "\u4E0B\u8F7D\u9644\u4EF6\u5E76\u62BD\u53D6\u7EAF\u6587\u672C\uFF08txt/md/csv/json/docx/xlsx/pptx\uFF09\uFF0C\u8FD4\u56DE\u6B63\u6587\u4E0E txt \u843D\u5730\u8DEF\u5F84\uFF1Bpdf/\u56FE\u7247\u7B49\u4E0D\u652F\u6301\u683C\u5F0F\u4F1A\u660E\u786E\u6807\u6CE8\uFF0C\u4E0D\u7F16\u9020\u5185\u5BB9",
|
|
623
|
+
capability: "attachment",
|
|
624
|
+
risk: "read",
|
|
625
|
+
inputSchema: schemaOf(
|
|
626
|
+
{
|
|
627
|
+
fileId: { ...SCHEMA_ID, description: "\u6587\u4EF6 id\uFF08\u4E0E mtId \u4E8C\u9009\u4E00\uFF09" },
|
|
628
|
+
mtId: { ...SCHEMA_ID, description: "\u4F1A\u8BAE id\uFF1A\u62BD\u53D6\u8BE5\u4F1A\u8BAE\u5168\u90E8\u9644\u4EF6\uFF08\u6700\u591A 10 \u4E2A\uFF09" },
|
|
629
|
+
maxChars: { type: "number", description: "\u6BCF\u4E2A\u6587\u4EF6\u8FD4\u56DE\u6B63\u6587\u7684\u6700\u5927\u5B57\u7B26\u6570\uFF08\u9ED8\u8BA4 4000\uFF0C\u6700\u591A 20000\uFF09" },
|
|
630
|
+
outDir: { type: "string", description: "\u843D\u5730\u76EE\u5F55\uFF08\u9ED8\u8BA4 <state>/meeting/attachments\uFF09" }
|
|
631
|
+
},
|
|
632
|
+
{ required: [] }
|
|
633
|
+
),
|
|
634
|
+
handler: async (args, env) => {
|
|
635
|
+
const fileId = String(args.fileId ?? "").trim();
|
|
636
|
+
const mtId = String(args.mtId ?? "").trim();
|
|
637
|
+
if (!fileId && !mtId) {
|
|
638
|
+
throw meetingValidationError("id_required", "\u5FC5\u987B\u63D0\u4F9B fileId \u6216 mtId");
|
|
639
|
+
}
|
|
640
|
+
const maxChars = Math.max(200, Math.min(2e4, Number(args.maxChars ?? 4e3) || 4e3));
|
|
641
|
+
const outDir = typeof args.outDir === "string" && args.outDir.trim() !== "" ? String(args.outDir) : void 0;
|
|
642
|
+
const refs = fileId ? [{ fileId, idLike: looksLikeFileId(fileId), source: "explicit", sourceLabel: "\u6307\u5B9A\u6587\u4EF6" }] : (await listMeetingAttachments(env, mtId)).refs.slice(0, 10);
|
|
643
|
+
if (refs.length === 0) {
|
|
644
|
+
throw meetingValidationError("attachment_empty", `\u4F1A\u8BAE ${mtId} \u6CA1\u6709\u9644\u4EF6\u53EF\u62BD\u53D6`);
|
|
645
|
+
}
|
|
646
|
+
const files = [];
|
|
647
|
+
const warnings = [];
|
|
648
|
+
for (const ref of refs) {
|
|
649
|
+
try {
|
|
650
|
+
const downloaded = await downloadMeetingFile(env, ref.fileId, { ...outDir ? { outDir } : {} });
|
|
651
|
+
const { readFile } = await import("node:fs/promises");
|
|
652
|
+
const buffer = await readFile(downloaded.path);
|
|
653
|
+
const extracted = extractText(buffer, downloaded.path, downloaded.contentType);
|
|
654
|
+
const text = extracted.text.slice(0, maxChars);
|
|
655
|
+
let textPath;
|
|
656
|
+
const absolutePath = downloaded.path;
|
|
657
|
+
const isPlainText = /\.(txt|md|csv|json|xml|html?|log|ya?ml|tsv)$/i.test(absolutePath);
|
|
658
|
+
if (extracted.text && !isPlainText) {
|
|
659
|
+
textPath = `${absolutePath.replace(/\.[a-z0-9]+$/i, "")}.txt`;
|
|
660
|
+
await writeFile(textPath, extracted.text, "utf8");
|
|
661
|
+
}
|
|
662
|
+
files.push({
|
|
663
|
+
fileId: ref.fileId,
|
|
664
|
+
source: ref.sourceLabel,
|
|
665
|
+
path: downloaded.path,
|
|
666
|
+
bytes: downloaded.bytes,
|
|
667
|
+
kind: extracted.kind,
|
|
668
|
+
chars: extracted.text.length,
|
|
669
|
+
...textPath ? { textPath } : {},
|
|
670
|
+
text
|
|
671
|
+
});
|
|
672
|
+
if (extracted.kind === "unsupported") {
|
|
673
|
+
warnings.push(
|
|
674
|
+
`${downloaded.path} \u662F ${downloaded.contentType || "\u672A\u77E5\u7C7B\u578B"}\uFF0C\u4F1A\u8BAE\u7EBF\u4E0D\u89E3\u6790\u8BE5\u683C\u5F0F\uFF08\u5DF2\u4E0B\u8F7D\uFF0CPDF \u53EF\u7528 pdf \u6280\u80FD\u3001\u56FE\u7247\u7528\u89C6\u89C9\u6A21\u578B\uFF09`
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
} catch (error) {
|
|
678
|
+
warnings.push(`\u9644\u4EF6 ${ref.fileId} \u5904\u7406\u5931\u8D25\uFF1A${String(error?.message ?? error).slice(0, 120)}`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return meetingSuccess(
|
|
682
|
+
"meeting.attachment.extract",
|
|
683
|
+
{ mtId: mtId || null, count: files.length, files },
|
|
684
|
+
warnings.length > 0 ? { warnings } : {}
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
var meetingAttachmentContentOperations = [
|
|
689
|
+
attachmentList,
|
|
690
|
+
attachmentDownload,
|
|
691
|
+
attachmentExtract
|
|
692
|
+
];
|
|
693
|
+
|
|
694
|
+
export {
|
|
695
|
+
renderDocx,
|
|
696
|
+
looksLikeFileId,
|
|
697
|
+
parseFileIdList,
|
|
698
|
+
listMeetingAttachments,
|
|
699
|
+
listTopicAttachments,
|
|
700
|
+
downloadMeetingFile,
|
|
701
|
+
extractText,
|
|
702
|
+
meetingAttachmentContentOperations
|
|
703
|
+
};
|