@agile-team/mach-report 2.4.0 → 2.5.0

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.
@@ -1,1907 +0,0 @@
1
- import { computed as F, unref as E, ref as A, onScopeDispose as Re, getCurrentScope as en, watch as _, shallowRef as ye, defineComponent as ct, nextTick as tn, openBlock as k, createElementBlock as M, createElementVNode as S, toDisplayString as R, Fragment as Fe, createCommentVNode as j, normalizeClass as de, renderList as ze, createTextVNode as st, withKeys as Ct, inject as He, provide as It, useCssVars as nn, watchEffect as kt, onMounted as rn, onUnmounted as an, normalizeStyle as ce, createBlock as on, createVNode as ln, renderSlot as sn } from "vue";
2
- import { renderPlanToImages as un, renderPage as St, getReportCellContext as Mt, createReportCellEdit as cn, applyReportCellEdit as dn, ReportCellEditError as Dt, paginateTemplate as fn, validateRenderPlan as Ft, ReportSourceError as pn, renderPlanToCanvas as mn } from "@agile-team/mach-report";
3
- import { c as Ot } from "./page-window-index-CIuT4BAv.js";
4
- import { i as vn, b as gn } from "./render-plan-CXBWRog4.js";
5
- import { b as it, c as hn, d as bn, a as wn } from "./plugin-DRnvIbdP.js";
6
- function Bt(e) {
7
- return e == null ? [] : Array.isArray(e) ? e.map(String).filter((t) => t !== "") : String(e).split(",").map((t) => t.trim()).filter((t) => t !== "");
8
- }
9
- function Yr(e) {
10
- return Bt(e).join(",");
11
- }
12
- class at extends Error {
13
- constructor(t) {
14
- super(t), this.name = "PlanLoadError";
15
- }
16
- }
17
- function Zr(e = {}) {
18
- const { baseUrl: t = "", headers: o, credentials: r, timeoutMs: n = 3e4 } = e, a = t.replace(/\/+$/, "");
19
- return async ({ url: l, method: c, params: m, signal: b }) => {
20
- let f = `${a}${l}`;
21
- if (m && Object.keys(m).length > 0) {
22
- const w = f.indexOf("#"), I = w >= 0 ? f.slice(w) : "", P = w >= 0 ? f.slice(0, w) : f, O = P.indexOf("?"), C = O >= 0 ? P.slice(0, O) : P, D = new URLSearchParams(O >= 0 ? P.slice(O + 1) : "");
23
- for (const [H, K] of Object.entries(m)) D.set(H, K);
24
- f = `${C}?${D}${I}`;
25
- }
26
- const p = (w, I) => {
27
- const P = new at(w);
28
- return Object.defineProperty(P, "cause", { value: I, configurable: !0, writable: !0 }), P;
29
- };
30
- if (b?.aborted)
31
- throw p(`请求已取消: ${l}`, b.reason);
32
- const h = new AbortController();
33
- let i;
34
- const x = () => {
35
- h.signal.aborted || (i = "external", h.abort(b?.reason));
36
- };
37
- b?.addEventListener("abort", x, { once: !0 });
38
- const $ = setTimeout(() => {
39
- h.signal.aborted || (i = "timeout", h.abort());
40
- }, n);
41
- try {
42
- const w = await fetch(f, {
43
- method: c.toUpperCase(),
44
- headers: { Accept: "application/json", ...o },
45
- credentials: r,
46
- signal: h.signal
47
- });
48
- if (!w.ok)
49
- throw new at(`HTTP ${w.status} ${l}`);
50
- return await w.json();
51
- } catch (w) {
52
- throw i === "timeout" ? p(`请求超时(${n}ms): ${l}`, w) : i === "external" ? p(`请求已取消: ${l}`, w) : w instanceof at ? w : p(`请求失败(${l}): ${w instanceof Error ? w.message : String(w)}`, w);
53
- } finally {
54
- clearTimeout($), b?.removeEventListener("abort", x);
55
- }
56
- };
57
- }
58
- function yn(e, t, o = {}) {
59
- const r = o.pxPerMm ?? 3.7795275590551185, n = F(() => Math.max(0, E(o.gapPx) ?? 18)), a = A(0), l = A(800), c = F(() => {
60
- const w = e.value?.pages ?? [];
61
- return Ot(w.map((I) => I.pageHeightMm * r), n.value);
62
- }), m = F(() => {
63
- let w = 0;
64
- for (const I of e.value?.pages ?? []) w = Math.max(w, I.pageWidthMm * r);
65
- return { w, h: c.value.totalHeightPx };
66
- }), b = F(() => c.value.window(
67
- l.value / t.value,
68
- a.value / t.value,
69
- E(o.overscan) ?? 1
70
- )), f = F(() => {
71
- const w = e.value;
72
- if (!w) return [];
73
- const { start: I, end: P } = b.value;
74
- return w.pages.slice(I, P + 1).map((O, C) => ({ page: O, index: I + C }));
75
- });
76
- let p = 0, h = !1;
77
- function i(w) {
78
- w && (a.value = w.scrollTop, l.value = w.clientHeight || 800);
79
- }
80
- function x(w, I) {
81
- return (P) => {
82
- p || h || (p = requestAnimationFrame(() => {
83
- if (p = 0, h || (i(P), I.value <= 0)) return;
84
- const O = Math.max(0, P.scrollTop + 32) / t.value;
85
- w.value = Math.min(I.value, c.value.pageAt(O) + 1);
86
- }));
87
- };
88
- }
89
- function $() {
90
- h = !0, p && cancelAnimationFrame(p), p = 0;
91
- }
92
- return Re($), {
93
- contentSize: m,
94
- windowRange: b,
95
- visiblePages: f,
96
- makeScrollHandler: x,
97
- refreshViewport: i,
98
- pageOffsetPx: (w) => c.value.offsetAt(w),
99
- destroy: $
100
- };
101
- }
102
- function xn(e) {
103
- const t = A(1), o = A("fit");
104
- let r = 0;
105
- function n() {
106
- r && cancelAnimationFrame(r), r = 0;
107
- }
108
- function a() {
109
- n(), r = requestAnimationFrame(() => {
110
- if (r = 0, o.value !== "fit") return;
111
- const c = e();
112
- !c?.viewport || c.viewport.clientWidth <= 48 || !Number.isFinite(c.pageWidthPx) || (t.value = Math.min(1, (c.viewport.clientWidth - 48) / Math.max(1, c.pageWidthPx)));
113
- });
114
- }
115
- function l(c) {
116
- if (c === "fit")
117
- o.value = "fit", a();
118
- else {
119
- if (!Number.isFinite(c)) return;
120
- n(), o.value = "raw", t.value = Math.min(3, Math.max(0.3, c / 100));
121
- }
122
- }
123
- return en() && Re(n), { zoom: t, zoomMode: o, applyFitZoom: a, setZoom: l };
124
- }
125
- const Ne = 8;
126
- function je() {
127
- return new Promise((e) => setTimeout(e, 0));
128
- }
129
- function Ae(e) {
130
- return `p${e.pageWidthMm}x${e.pageHeightMm}`.replace(/[.+]/g, "_");
131
- }
132
- function dt(e) {
133
- const t = /* @__PURE__ */ new Map();
134
- return e.pages.forEach((n) => {
135
- t.has(Ae(n)) || t.set(Ae(n), n);
136
- }), `<!doctype html><html><head><meta charset="utf-8"><style>${`.mr-page{margin:0 auto;page-break-after:always;}
137
- .mr-page tr{break-inside:avoid;page-break-inside:avoid;}
138
- .mr-comp{break-inside:avoid;page-break-inside:avoid;}
139
- ${[...t.values()].map(
140
- (n) => `@page ${Ae(n)}{size:${n.pageWidthMm}mm ${n.pageHeightMm}mm;margin:0;}`
141
- ).join(`
142
- `)}
143
- body{margin:0;background:#fff;}`}</style></head><body>`;
144
- }
145
- function ft(e) {
146
- const t = St(e, 96, {}, document);
147
- return t.style.page = Ae(e), t.outerHTML;
148
- }
149
- function Wt(e) {
150
- return { head: dt(e), pageChunks: e.pages.map(ft) };
151
- }
152
- async function Jr(e, t = {}) {
153
- const o = {
154
- schemaVersion: "mach-report-batch-print",
155
- pages: e.flatMap((l) => l.pages)
156
- };
157
- if (o.pages.length === 0) return;
158
- const r = dt(o), n = document.createElement("iframe");
159
- n.style.cssText = "position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;", document.body.appendChild(n);
160
- let a = !1;
161
- try {
162
- const l = n.contentDocument;
163
- l.open(), l.write(r);
164
- for (let c = 0; c < o.pages.length; c++)
165
- l.write(ft(o.pages[c])), c % Ne === Ne - 1 && (t.onProgress?.(c + 1, o.pages.length), await je());
166
- l.write("</body></html>"), l.close(), await je(), t.onProgress?.(o.pages.length, o.pages.length), a = !0, n.contentWindow?.focus(), n.contentWindow?.print();
167
- } catch (l) {
168
- t.onError?.(l instanceof Error ? `批量打印失败: ${l.message}` : "批量打印失败");
169
- } finally {
170
- a ? setTimeout(() => n.remove(), 6e4) : n.remove();
171
- }
172
- }
173
- function Pn(e) {
174
- const { head: t, pageChunks: o } = Wt(e);
175
- return {
176
- html: `${`<!doctype html><html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head><meta charset="utf-8"><!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:Zoom>100</w:Zoom></w:WordDocument></xml><![endif]-->${t.replace(/^<!doctype html><html><head>/, "")}`}${o.join("")}</body></html>`,
177
- filename: "mach-report.doc"
178
- };
179
- }
180
- function En(e, t) {
181
- let o = null, r = !1, n = !1, a = 0;
182
- const l = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map();
183
- let m = null, b = null, f = null, p = null, h = null;
184
- function i(u, d) {
185
- return !n && e.value === u && a === d;
186
- }
187
- function x() {
188
- if (n) return;
189
- const u = [...l.values()].reverse().find((d) => i(d.plan, d.epoch))?.format ?? null;
190
- u !== m && (m = u, t.onBusy?.(u));
191
- }
192
- function $(u, d, y) {
193
- const T = {};
194
- return l.set(T, { plan: u, epoch: d, format: y }), x(), T;
195
- }
196
- function w(u) {
197
- l.delete(u), x();
198
- }
199
- function I() {
200
- for (const [u, d] of c)
201
- i(d.plan, d.epoch) || (u.close(), c.delete(u));
202
- }
203
- function P() {
204
- a++, C(), x(), I();
205
- }
206
- const O = _(e, P, { flush: "sync" });
207
- function C() {
208
- o?.remove(), o = null;
209
- }
210
- function D() {
211
- n = !0, a++, O(), C(), I(), l.clear(), t.onPrinting?.(!1);
212
- }
213
- function H(u, d) {
214
- const y = URL.createObjectURL(u);
215
- setTimeout(() => URL.revokeObjectURL(y), 1e4);
216
- const T = document.createElement("a");
217
- T.href = y, T.download = d, T.click();
218
- }
219
- async function K() {
220
- if (r) return;
221
- const u = e.value;
222
- if (n || !u || u.pages.length === 0) return;
223
- const d = a;
224
- r = !0, t.onPrinting?.(!0), C();
225
- const y = dt(u);
226
- o = document.createElement("iframe"), o.style.cssText = "position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;", document.body.appendChild(o);
227
- const T = o;
228
- try {
229
- const B = T.contentDocument;
230
- B.open(), B.write(y);
231
- for (let V = 0; V < u.pages.length; V++)
232
- if (B.write(ft(u.pages[V])), V % Ne === Ne - 1 && await je(), T !== o) return;
233
- if (B.write("</body></html>"), B.close(), await je(), !i(u, d) || T !== o) return;
234
- T.contentWindow?.focus(), T.contentWindow?.print();
235
- } catch {
236
- T === o && C(), i(u, d) && t.onError("调用打印失败,请改用导出 PDF", "print");
237
- } finally {
238
- r = !1, n || t.onPrinting?.(!1);
239
- }
240
- }
241
- function X(u, d) {
242
- if (b?.plan === u && b.epoch === d) return b.promise;
243
- const y = Promise.resolve().then(() => {
244
- if (!i(u, d)) throw new Error("报表已切换或卸载");
245
- return t.getPdfExporter()(u, (T) => {
246
- i(u, d) && t.onWarning?.(T);
247
- });
248
- }).finally(() => {
249
- b?.promise === y && (b = null);
250
- });
251
- return b = { plan: u, epoch: d, promise: y }, y;
252
- }
253
- async function Q() {
254
- const u = e.value;
255
- if (n || !u || u.pages.length === 0) return;
256
- const d = a;
257
- if (f?.plan === u && f.epoch === d) return f.promise;
258
- const y = $(u, d, "PDF"), T = (async () => {
259
- try {
260
- const B = await X(u, d);
261
- if (!i(u, d)) return;
262
- H(new Blob([B], { type: "application/pdf" }), "mach-report.pdf");
263
- } catch (B) {
264
- i(u, d) && t.onError(B instanceof Error ? `PDF 导出失败: ${B.message}` : "PDF 导出失败", "pdf");
265
- } finally {
266
- w(y), f?.token === y && (f = null);
267
- }
268
- })();
269
- return f = { plan: u, epoch: d, promise: T, token: y }, T;
270
- }
271
- async function Y() {
272
- const u = e.value;
273
- if (n || !u || u.pages.length === 0) return;
274
- const d = a;
275
- if (p?.plan === u && p.epoch === d) return p.promise;
276
- const y = { ...t.getXlsxOptions?.() }, T = $(u, d, "Excel"), B = (async () => {
277
- try {
278
- const { renderPlanToXlsx: V } = await import("@agile-team/mach-report/xlsx");
279
- if (!i(u, d)) return;
280
- const { buffer: ee, warnings: oe } = await V(u, y);
281
- if (!i(u, d) || (oe.length > 0 && t.onWarning?.(`Excel 导出有 ${oe.length} 条提示:${oe.slice(0, 2).join(";")}`), !i(u, d))) return;
282
- H(new Blob([ee], {
283
- type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
284
- }), "mach-report.xlsx");
285
- } catch (V) {
286
- i(u, d) && t.onError(V instanceof Error ? `Excel 导出失败: ${V.message}` : "Excel 导出失败", "export");
287
- } finally {
288
- w(T), p?.token === T && (p = null);
289
- }
290
- })();
291
- return p = { plan: u, epoch: d, promise: B, token: T }, B;
292
- }
293
- async function se() {
294
- const u = e.value;
295
- if (n || !u || u.pages.length === 0) return;
296
- const d = a;
297
- if (h?.plan === u && h.epoch === d) return h.promise;
298
- const y = $(u, d, "图片"), T = (async () => {
299
- try {
300
- const { blobs: B } = await un(u, {
301
- dpr: Math.min(2, typeof devicePixelRatio == "number" ? devicePixelRatio : 1)
302
- });
303
- if (!i(u, d)) return;
304
- B.forEach((V, ee) => {
305
- H(V, B.length > 1 ? `mach-report-page-${ee + 1}.png` : "mach-report.png");
306
- });
307
- } catch (B) {
308
- i(u, d) && t.onError(
309
- B instanceof Error ? `图片导出失败: ${B.message}` : "图片导出失败",
310
- "export"
311
- );
312
- } finally {
313
- w(y), h?.token === y && (h = null);
314
- }
315
- })();
316
- return h = { plan: u, epoch: d, promise: T, token: y }, T;
317
- }
318
- function U() {
319
- const u = e.value;
320
- if (!(n || !u || u.pages.length === 0))
321
- try {
322
- const { html: d, filename: y } = Pn(u);
323
- H(new Blob([d], { type: "application/msword;charset=utf-8" }), y);
324
- } catch (d) {
325
- t.onError(
326
- d instanceof Error ? `Word 导出失败: ${d.message}` : "Word 导出失败",
327
- "export"
328
- );
329
- }
330
- }
331
- async function me(u) {
332
- const d = e.value;
333
- if (!(n || !d || d.pages.length === 0)) {
334
- if (u === "pdf") {
335
- await Q();
336
- return;
337
- }
338
- if (u === "xlsx" || u === "excel") {
339
- await Y();
340
- return;
341
- }
342
- if (u === "png" || u === "image") {
343
- await se();
344
- return;
345
- }
346
- if (u === "word" || u === "doc") {
347
- U();
348
- return;
349
- }
350
- if (u !== "html") {
351
- t.onError(`不支持的导出格式:${u}`, "export");
352
- return;
353
- }
354
- try {
355
- const { head: y, pageChunks: T } = Wt(d), B = `${y}${T.join("")}</body></html>`;
356
- H(new Blob([B], { type: "text/html;charset=utf-8" }), "mach-report.html");
357
- } catch (y) {
358
- t.onError(y instanceof Error ? `HTML 导出失败: ${y.message}` : "HTML 导出失败", "export");
359
- }
360
- }
361
- }
362
- function J() {
363
- const u = e.value;
364
- if (n || !u || u.pages.length === 0) return;
365
- const d = a, y = window.open("", "_blank");
366
- if (!y) {
367
- t.onError("浏览器拦截了弹窗,请允许弹窗后重试", "pdf");
368
- return;
369
- }
370
- c.set(y, { plan: u, epoch: d });
371
- const T = $(u, d, "PDF");
372
- X(u, d).then((B) => {
373
- if (!i(u, d) || y.closed) {
374
- c.delete(y) && y.close();
375
- return;
376
- }
377
- const V = URL.createObjectURL(new Blob([B], { type: "application/pdf" }));
378
- setTimeout(() => URL.revokeObjectURL(V), 6e4);
379
- const ee = y.document;
380
- ee.title = "PDF 预览", ee.documentElement.style.height = "100%", ee.body.style.cssText = "margin:0;height:100%;";
381
- const oe = ee.createElement("iframe");
382
- oe.title = "PDF 预览", oe.style.cssText = "display:block;width:100%;height:100%;border:0;", oe.src = V, ee.body.replaceChildren(oe), c.delete(y);
383
- }).catch((B) => {
384
- y.close(), c.delete(y), i(u, d) && t.onError(B instanceof Error ? `PDF 预览失败: ${B.message}` : "PDF 预览失败", "pdf");
385
- }).finally(() => w(T));
386
- }
387
- return {
388
- print: K,
389
- exportAs: me,
390
- exportImages: se,
391
- exportWord: U,
392
- openPdfWindow: J,
393
- invalidatePending: P,
394
- releasePrintFrame: C,
395
- dispose: D
396
- };
397
- }
398
- const At = "mrp-hit";
399
- function $n(e) {
400
- e.querySelectorAll(`mark.${At}`).forEach((o) => {
401
- const r = o.parentNode;
402
- if (r) {
403
- for (; o.firstChild; ) r.insertBefore(o.firstChild, o);
404
- o.remove(), r.normalize();
405
- }
406
- });
407
- }
408
- function Cn(e, t) {
409
- const o = t.trim();
410
- if (!o) return 0;
411
- const r = o.toLowerCase(), n = document.createTreeWalker(e, NodeFilter.SHOW_TEXT, {
412
- acceptNode(c) {
413
- const m = c.parentElement;
414
- return !m || m.closest("mark") || /^(SCRIPT|STYLE)$/.test(m.tagName) ? NodeFilter.FILTER_REJECT : (c.nodeValue ?? "").toLowerCase().includes(r) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
415
- }
416
- }), a = [];
417
- for (let c = n.nextNode(); c; c = n.nextNode()) a.push(c);
418
- let l = 0;
419
- for (const c of a) {
420
- const m = c.nodeValue ?? "", b = m.toLowerCase(), f = c.parentElement;
421
- if (!f) continue;
422
- const p = document.createDocumentFragment();
423
- let h = 0, i = b.indexOf(r);
424
- for (; i >= 0; ) {
425
- i > h && p.appendChild(document.createTextNode(m.slice(h, i)));
426
- const x = document.createElement("mark");
427
- x.className = At, x.textContent = m.slice(i, i + o.length), p.appendChild(x), l++, h = i + o.length, i = b.indexOf(r, h);
428
- }
429
- h < m.length && p.appendChild(document.createTextNode(m.slice(h))), f.replaceChild(p, c);
430
- }
431
- return l;
432
- }
433
- const kn = /* @__PURE__ */ new Set(["line", "rect", "ellipse", "chart"]);
434
- function* Mn(e) {
435
- for (const t of e.cells ?? [])
436
- for (const o of t ?? [])
437
- yield o?.text ?? "", yield* o?.children ?? [];
438
- }
439
- function* Fn(e) {
440
- if (gn(e))
441
- for (const t of e.richParagraphs)
442
- for (const o of t.segments ?? [])
443
- yield (o.kind === "field" ? o.field : o.text) ?? "";
444
- else e.lines?.length ? yield* e.lines : yield e.text ?? "";
445
- }
446
- function* Rn(e) {
447
- const t = [e.values()];
448
- for (; t.length > 0; ) {
449
- const o = t[t.length - 1].next();
450
- if (o.done) {
451
- t.pop();
452
- continue;
453
- }
454
- const r = o.value;
455
- if (typeof r == "string") {
456
- yield r;
457
- continue;
458
- }
459
- yield "", !vn(r) && (r.kind === "text" ? t.push(Fn(r)) : r.grid ? t.push(Mn(r.grid)) : kn.has(r.kind) || (yield r.fallbackText ?? ""));
460
- }
461
- }
462
- function* Tn(e) {
463
- for (let t = 0; t < e.pages.length; t++) {
464
- for (const o of Rn(e.pages[t].components)) yield { text: o, pageIndex: t };
465
- yield { text: "", pageIndex: t };
466
- }
467
- }
468
- function In(e, t) {
469
- const o = e.toLowerCase();
470
- let r = 0;
471
- for (let n = o.indexOf(t); n >= 0; n = o.indexOf(t, n + t.length)) r++;
472
- return r;
473
- }
474
- function Sn(e) {
475
- const { plan: t, gotoPage: o, highlight: r, clearHighlights: n } = e, a = A(!1), l = A(""), c = A(0), m = A(0), b = A(!1);
476
- let f = [];
477
- const p = F(() => {
478
- if (m.value === 0) return null;
479
- const C = c.value;
480
- let D = 0, H = f.length - 1;
481
- for (; D < H; ) {
482
- const X = D + H >>> 1;
483
- f[X].cumulative <= C ? D = X + 1 : H = X;
484
- }
485
- const K = f[D];
486
- return K ? { pageIndex: K.pageIndex, occurrence: C - (f[D - 1]?.cumulative ?? 0) } : null;
487
- });
488
- let h = null, i = null, x = 0;
489
- function $() {
490
- x++, h && clearTimeout(h), i && clearTimeout(i), h = i = null, b.value = !1;
491
- }
492
- function w(C) {
493
- l.value = C, c.value = 0, m.value = 0, f = [], b.value = !1;
494
- const D = C.trim().toLowerCase(), H = t.value;
495
- if (!D || !H) return;
496
- b.value = !0;
497
- const K = x, X = Tn(H), Q = [];
498
- let Y = 0;
499
- function se() {
500
- if (i = null, K !== x || H !== t.value) return;
501
- const U = performance.now();
502
- let me = 0;
503
- for (; me < 5e3 && performance.now() - U < 4; ) {
504
- const J = X.next();
505
- if (J.done) {
506
- f = Q, m.value = Y, b.value = !1, f[0] && o(f[0].pageIndex + 1);
507
- return;
508
- }
509
- const u = In(J.value.text, D);
510
- if (u > 0) {
511
- Y += u;
512
- const d = Q[Q.length - 1];
513
- d?.pageIndex === J.value.pageIndex ? d.cumulative = Y : Q.push({ pageIndex: J.value.pageIndex, cumulative: Y });
514
- }
515
- me++;
516
- }
517
- i = setTimeout(se, 0);
518
- }
519
- se();
520
- }
521
- function I(C) {
522
- if ($(), l.value = C, c.value = m.value = 0, f = [], !C.trim()) {
523
- w("");
524
- return;
525
- }
526
- b.value = !0, h = setTimeout(() => {
527
- h = null, w(C);
528
- }, Math.max(0, E(e.debounceMs) ?? 200));
529
- }
530
- function P(C) {
531
- const D = m.value;
532
- if (D === 0 || b.value) return;
533
- c.value = (c.value + C + D) % D;
534
- const H = p.value;
535
- H && o(H.pageIndex + 1);
536
- }
537
- function O() {
538
- $(), l.value = "", c.value = m.value = 0, f = [];
539
- }
540
- return _(t, O, { flush: "sync" }), Re(O), {
541
- visible: a,
542
- query: l,
543
- matchIndex: c,
544
- matchCount: m,
545
- activeMatch: p,
546
- searching: b,
547
- toggle: () => {
548
- a.value = !a.value;
549
- },
550
- onInput: I,
551
- onNav: P,
552
- apply: (C) => {
553
- l.value.trim() && r(C, l.value.trim());
554
- },
555
- clear: (C) => {
556
- n(C);
557
- },
558
- reset: O
559
- };
560
- }
561
- function Dn(e, t) {
562
- const o = F(() => {
563
- if (e.value) return !0;
564
- if (typeof location > "u") return !1;
565
- try {
566
- return new URLSearchParams(location.search).get("mrp-debug") === "1";
567
- } catch {
568
- return !1;
569
- }
570
- }), r = F(() => !o.value || !t.plan.value ? 0 : Math.round(JSON.stringify(t.plan.value).length / 1024)), n = F(() => !o.value || !t.plan.value ? null : {
571
- pages: t.pageCount.value,
572
- window: `${t.windowRange.value.start}-${t.windowRange.value.end}`,
573
- zoom: `${Math.round(t.zoom.value * 100)}%`,
574
- loadMs: `${t.loadMs.value}ms`,
575
- planKB: r.value
576
- });
577
- return { enabled: o, debugStats: n };
578
- }
579
- function On(e, t) {
580
- const { thumbsRoot: o, visible: r, renderThumbCanvas: n } = t, a = A(0), l = A(800), c = F(() => (e.value?.pages ?? []).map(
581
- (P) => Math.round(P.pageHeightMm / P.pageWidthMm * 116)
582
- )), m = F(() => Ot(c.value.map((P) => P + 20), 8)), b = F(() => m.value.window(l.value, a.value, 1)), f = F(() => {
583
- if (!r.value) return [];
584
- const { start: P, end: O } = b.value;
585
- return c.value.slice(P, O + 1).map((C, D) => ({ index: P + D, height: C }));
586
- });
587
- let p = 0, h = 0, i = !1;
588
- function x() {
589
- const P = o.value;
590
- P && (a.value = P.scrollTop, l.value = P.clientHeight || 800);
591
- }
592
- function $() {
593
- i || h || (h = requestAnimationFrame(() => {
594
- h = 0, x();
595
- }));
596
- }
597
- function w() {
598
- if (f.value, p && cancelAnimationFrame(p), p = 0, i || !r.value || !e.value || !o.value) return;
599
- x();
600
- const P = f.value, O = e.value, C = o.value;
601
- let D = 0;
602
- function H() {
603
- if (p = 0, !(i || !r.value || e.value !== O || o.value !== C)) {
604
- for (let K = 0; D < P.length && K < 2; K++, D++) {
605
- const X = P[D].index, Q = C.querySelector(`[data-thumb="${X + 1}"]`);
606
- if (!Q || Q.childElementCount > 0) continue;
607
- const Y = n(X);
608
- Y && (Y.style.width = "100%", Y.style.height = "100%", Y.style.display = "block", Q.appendChild(Y));
609
- }
610
- D < P.length && (p = requestAnimationFrame(H));
611
- }
612
- }
613
- p = requestAnimationFrame(H);
614
- }
615
- function I() {
616
- i = !0, p && cancelAnimationFrame(p), h && cancelAnimationFrame(h), p = h = 0;
617
- }
618
- return Re(I), { schedule: w, destroy: I, onScroll: $, windowRange: b, visibleThumbs: f };
619
- }
620
- function Bn() {
621
- const e = ye(0);
622
- return {
623
- loadMs: e,
624
- start() {
625
- return typeof performance < "u" ? performance.now() : 0;
626
- },
627
- end(t) {
628
- e.value = t ? Math.round(performance.now() - t) : 0;
629
- }
630
- };
631
- }
632
- const Wn = { class: "mrp-toolbar" }, An = { class: "mrp-title" }, Ln = ["disabled"], zn = { class: "mrp-pageinfo" }, Hn = ["disabled"], Nn = ["disabled"], jn = {
633
- key: 2,
634
- class: "mrp-search"
635
- }, qn = ["placeholder", "value"], Un = {
636
- key: 0,
637
- class: "mrp-search-count",
638
- role: "status"
639
- }, Vn = ["disabled"], Kn = ["disabled"], Yn = ["disabled"], Zn = ["disabled"], Jn = ["disabled"], Gn = ["disabled"], Xn = ["disabled"], Qn = ["disabled"], _n = ["disabled"], er = /* @__PURE__ */ ct({
640
- __name: "ReportToolbar",
641
- props: {
642
- pageCount: {},
643
- currentPage: {},
644
- zoomMode: {},
645
- zoom: {},
646
- showExport: { type: Boolean },
647
- showPrint: { type: Boolean },
648
- showPdfWindow: { type: Boolean },
649
- messages: {},
650
- search: {},
651
- thumbsVisible: { type: Boolean },
652
- showImport: { type: Boolean },
653
- busy: { type: Boolean }
654
- },
655
- emits: ["goto", "zoom", "export", "print", "pdf-window", "search-input", "search-nav", "search-toggle", "thumbs-toggle", "import-excel"],
656
- setup(e) {
657
- const t = e, o = A(null);
658
- _(
659
- () => t.search.visible,
660
- (n) => {
661
- n && tn(() => o.value?.focus());
662
- }
663
- );
664
- function r(n, a, l) {
665
- return n.replace("{cur}", String(a)).replace("{total}", String(l));
666
- }
667
- return (n, a) => (k(), M("div", Wn, [
668
- S("span", An, R(e.messages.title), 1),
669
- e.pageCount > 0 ? (k(), M(Fe, { key: 0 }, [
670
- S("button", {
671
- class: "mrp-nav",
672
- type: "button",
673
- disabled: e.currentPage <= 1,
674
- onClick: a[0] || (a[0] = (l) => n.$emit("goto", e.currentPage - 1))
675
- }, R(e.messages.prevPage), 9, Ln),
676
- S("span", zn, R(r(e.messages.pageInfo, e.currentPage, e.pageCount)), 1),
677
- S("button", {
678
- class: "mrp-nav",
679
- type: "button",
680
- disabled: e.currentPage >= e.pageCount,
681
- onClick: a[1] || (a[1] = (l) => n.$emit("goto", e.currentPage + 1))
682
- }, R(e.messages.nextPage), 9, Hn)
683
- ], 64)) : j("", !0),
684
- a[18] || (a[18] = S("span", { class: "mrp-spacer" }, null, -1)),
685
- e.showImport ? (k(), M("button", {
686
- key: 1,
687
- class: "mrp-nav mrp-import-excel",
688
- type: "button",
689
- disabled: e.busy,
690
- onClick: a[2] || (a[2] = (l) => n.$emit("import-excel"))
691
- }, R(e.messages.importExcel ?? "导入 Excel 模板"), 9, Nn)) : j("", !0),
692
- e.search.visible ? (k(), M("div", jn, [
693
- S("input", {
694
- ref_key: "searchInputRef",
695
- ref: o,
696
- class: "mrp-search-input",
697
- type: "text",
698
- placeholder: e.messages.searchPlaceholder,
699
- value: e.search.query,
700
- onInput: a[3] || (a[3] = (l) => n.$emit("search-input", l.target.value))
701
- }, null, 40, qn),
702
- e.search.query ? (k(), M("span", Un, R(e.search.searching ? e.messages.searching ?? "搜索中…" : r(e.messages.matchInfo, e.search.matchCount > 0 ? e.search.matchIndex + 1 : 0, e.search.matchCount)), 1)) : j("", !0),
703
- S("button", {
704
- class: "mrp-nav",
705
- type: "button",
706
- disabled: e.search.matchCount === 0,
707
- onClick: a[4] || (a[4] = (l) => n.$emit("search-nav", -1))
708
- }, R(e.messages.prevMatch), 9, Vn),
709
- S("button", {
710
- class: "mrp-nav",
711
- type: "button",
712
- disabled: e.search.matchCount === 0,
713
- onClick: a[5] || (a[5] = (l) => n.$emit("search-nav", 1))
714
- }, R(e.messages.nextMatch), 9, Kn)
715
- ])) : j("", !0),
716
- S("button", {
717
- class: de(["mrp-nav", { "mrp-active": e.search.visible }]),
718
- type: "button",
719
- title: "Ctrl+F",
720
- onClick: a[6] || (a[6] = (l) => n.$emit("search-toggle"))
721
- }, " 🔍 ", 2),
722
- S("button", {
723
- class: de(["mrp-nav", { "mrp-active": e.thumbsVisible }]),
724
- type: "button",
725
- onClick: a[7] || (a[7] = (l) => n.$emit("thumbs-toggle"))
726
- }, " ▦ " + R(e.messages.thumbnails), 3),
727
- S("button", {
728
- class: de(["mrp-nav", { "mrp-active": e.zoomMode === "fit" }]),
729
- type: "button",
730
- onClick: a[8] || (a[8] = (l) => n.$emit("zoom", "fit"))
731
- }, R(e.messages.fitWidth), 3),
732
- S("button", {
733
- class: de(["mrp-nav", { "mrp-active": e.zoomMode === "raw" && Math.round(e.zoom * 100) === 100 }]),
734
- type: "button",
735
- onClick: a[9] || (a[9] = (l) => n.$emit("zoom", 100))
736
- }, " 100% ", 2),
737
- S("button", {
738
- class: de(["mrp-nav", { "mrp-active": e.zoomMode === "raw" && Math.round(e.zoom * 100) === 150 }]),
739
- type: "button",
740
- onClick: a[10] || (a[10] = (l) => n.$emit("zoom", 150))
741
- }, " 150% ", 2),
742
- e.showExport ? (k(), M("button", {
743
- key: 3,
744
- class: "mrp-nav",
745
- type: "button",
746
- disabled: e.busy,
747
- onClick: a[11] || (a[11] = (l) => n.$emit("export", "html"))
748
- }, R(e.messages.exportHtml), 9, Yn)) : j("", !0),
749
- e.showExport ? (k(), M("button", {
750
- key: 4,
751
- class: "mrp-nav",
752
- type: "button",
753
- disabled: e.busy,
754
- onClick: a[12] || (a[12] = (l) => n.$emit("export", "pdf"))
755
- }, R(e.messages.exportPdf), 9, Zn)) : j("", !0),
756
- e.showExport ? (k(), M("button", {
757
- key: 5,
758
- class: "mrp-nav",
759
- type: "button",
760
- disabled: e.busy,
761
- onClick: a[13] || (a[13] = (l) => n.$emit("export", "xlsx"))
762
- }, R(e.messages.exportExcel), 9, Jn)) : j("", !0),
763
- e.showExport ? (k(), M("button", {
764
- key: 6,
765
- class: "mrp-nav",
766
- type: "button",
767
- disabled: e.busy,
768
- onClick: a[14] || (a[14] = (l) => n.$emit("export", "png"))
769
- }, R(e.messages.exportImage), 9, Gn)) : j("", !0),
770
- e.showExport ? (k(), M("button", {
771
- key: 7,
772
- class: "mrp-nav",
773
- type: "button",
774
- disabled: e.busy,
775
- onClick: a[15] || (a[15] = (l) => n.$emit("export", "word"))
776
- }, R(e.messages.exportWord), 9, Xn)) : j("", !0),
777
- e.showPrint ? (k(), M("button", {
778
- key: 8,
779
- class: "mrp-nav",
780
- type: "button",
781
- disabled: e.busy,
782
- onClick: a[16] || (a[16] = (l) => n.$emit("print"))
783
- }, R(e.messages.print), 9, Qn)) : j("", !0),
784
- e.showPdfWindow ? (k(), M("button", {
785
- key: 9,
786
- class: "mrp-nav",
787
- type: "button",
788
- disabled: e.busy,
789
- onClick: a[17] || (a[17] = (l) => n.$emit("pdf-window"))
790
- }, R(e.messages.pdfWindow), 9, _n)) : j("", !0)
791
- ]));
792
- }
793
- }), pt = (e, t) => {
794
- const o = e.__vccOpts || e;
795
- for (const [r, n] of t)
796
- o[r] = n;
797
- return o;
798
- }, tr = /* @__PURE__ */ pt(er, [["__scopeId", "data-v-1c2568a7"]]), nr = { class: "mrp-params" }, rr = { class: "mrp-params-title" }, ar = { class: "mrp-params-grid" }, or = { class: "mrp-param-label" }, lr = {
799
- key: 0,
800
- class: "mrp-param-star"
801
- }, sr = ["value", "onChange"], ir = {
802
- value: "",
803
- disabled: "",
804
- hidden: ""
805
- }, ur = ["value"], cr = ["type", "placeholder", "value", "onInput"], dr = { class: "mrp-params-actions" }, fr = /* @__PURE__ */ ct({
806
- __name: "ReportParamPanel",
807
- props: {
808
- defs: {},
809
- modelValue: {},
810
- messages: {},
811
- attempted: { type: Boolean }
812
- },
813
- emits: ["update:modelValue", "query", "reset"],
814
- setup(e, { emit: t }) {
815
- const o = e, r = t, n = A({ ...o.modelValue });
816
- _(
817
- () => o.modelValue,
818
- (m) => {
819
- n.value = { ...m };
820
- }
821
- );
822
- const a = F(
823
- () => o.defs.map((m) => ({
824
- def: m,
825
- label: m.label ?? m.field,
826
- value: n.value[m.field] ?? ""
827
- }))
828
- );
829
- function l(m, b) {
830
- n.value = { ...n.value, [m]: b }, r("update:modelValue", { ...n.value });
831
- }
832
- function c(m) {
833
- const b = o.defs.find((f) => f.field === m);
834
- return o.attempted && b?.required === !0 && !(n.value[m] ?? "").trim();
835
- }
836
- return (m, b) => (k(), M("div", nr, [
837
- S("span", rr, R(e.messages.paramsTitle), 1),
838
- S("div", ar, [
839
- (k(!0), M(Fe, null, ze(a.value, (f) => (k(), M("label", {
840
- key: f.def.field,
841
- class: de(["mrp-param", { "mrp-param-missing": c(f.def.field) }])
842
- }, [
843
- S("span", or, [
844
- st(R(f.label), 1),
845
- f.def.required ? (k(), M("i", lr, "*")) : j("", !0)
846
- ]),
847
- (f.def.type ?? "text") === "select" ? (k(), M("select", {
848
- key: 0,
849
- class: "mrp-param-input",
850
- value: f.value,
851
- onChange: (p) => l(f.def.field, p.target.value),
852
- onKeydown: b[0] || (b[0] = Ct((p) => m.$emit("query"), ["enter"]))
853
- }, [
854
- S("option", ir, R(f.def.placeholder ?? `请选择${f.label}`), 1),
855
- (k(!0), M(Fe, null, ze(f.def.options ?? [], (p) => (k(), M("option", {
856
- key: p.value,
857
- value: p.value
858
- }, R(p.label), 9, ur))), 128))
859
- ], 40, sr)) : (k(), M("input", {
860
- key: 1,
861
- class: "mrp-param-input",
862
- type: f.def.type === "number" ? "number" : f.def.type === "date" ? "date" : "text",
863
- placeholder: f.def.placeholder ?? `请输入${f.label}`,
864
- value: f.value,
865
- onInput: (p) => l(f.def.field, p.target.value),
866
- onKeydown: b[1] || (b[1] = Ct((p) => m.$emit("query"), ["enter"]))
867
- }, null, 40, cr))
868
- ], 2))), 128))
869
- ]),
870
- S("div", dr, [
871
- S("button", {
872
- class: "mrp-nav mrp-param-query",
873
- type: "button",
874
- onClick: b[2] || (b[2] = (f) => m.$emit("query"))
875
- }, R(e.messages.query), 1),
876
- S("button", {
877
- class: "mrp-nav",
878
- type: "button",
879
- onClick: b[3] || (b[3] = (f) => m.$emit("reset"))
880
- }, R(e.messages.reset), 1)
881
- ])
882
- ]));
883
- }
884
- }), pr = /* @__PURE__ */ pt(fr, [["__scopeId", "data-v-aafce92d"]]), mr = {
885
- title: "报表预览",
886
- prevPage: "‹ 上一页",
887
- nextPage: "下一页 ›",
888
- pageInfo: "{cur} / {total}",
889
- fitWidth: "适宽",
890
- exportHtml: "导出 HTML",
891
- exportPdf: "导出 PDF",
892
- exportExcel: "导出 Excel",
893
- exportImage: "导出图片",
894
- exportWord: "导出 Word",
895
- exporting: "正在生成 {format}…",
896
- print: "打印",
897
- pdfWindow: "PDF 窗口",
898
- loading: "报表渲染中…",
899
- empty: "暂无预览数据",
900
- errorPrefix: "",
901
- retry: "重试",
902
- pdfFontUnavailable: "PDF 字体尚未就绪,请联系管理员检查字体配置;预览及其它导出仍可使用。",
903
- searchPlaceholder: "搜索报表内容",
904
- matchInfo: "{cur}/{total}",
905
- prevMatch: "‹",
906
- nextMatch: "›",
907
- thumbnails: "缩略图",
908
- paramsTitle: "查询条件",
909
- query: "查 询",
910
- reset: "重 置",
911
- paramRequired: "请填写{label}",
912
- searching: "搜索中…",
913
- importExcel: "导入 Excel 模板",
914
- importing: "正在导入 Excel…",
915
- editCell: "编辑单元格",
916
- editingHint: "双击单元格编辑 · Enter 确认 · Esc 取消",
917
- saving: "正在保存修改…",
918
- editInvalidNumber: "请输入有效数字;清空表示无值",
919
- editInvalidBoolean: "请输入 true / false、是 / 否或 1 / 0",
920
- editConflict: "该单元格已变化,请重新打开编辑"
921
- }, vr = {
922
- shellBg: "#525659",
923
- shellFg: "#e8e8e8",
924
- toolbarBg: "#323639",
925
- toolbarBorder: "#22252a",
926
- toolbarFg: "#e8e8e8",
927
- btnFg: "#cfcfcf",
928
- btnBorder: "#4a4d52",
929
- btnHoverBg: "#414549",
930
- btnHoverFg: "#ffffff",
931
- btnActiveBg: "#2d5fb8"
932
- };
933
- function gr(e = {}) {
934
- return { ...e, defaults: e.defaults ?? {}, presets: e.presets ?? {} };
935
- }
936
- function Gr(e) {
937
- return e;
938
- }
939
- const he = {
940
- showExport: !0,
941
- showPrint: !0,
942
- showPdfWindow: !0,
943
- showParams: !0,
944
- gapPx: 18,
945
- pdfFontUrl: "/simhei.ttf",
946
- logger: console
947
- }, Xr = { warn: () => {
948
- }, info: () => {
949
- } };
950
- function Le(e, t) {
951
- return {
952
- ...e,
953
- ...t,
954
- theme: { ...e?.theme, ...t?.theme },
955
- messages: { ...e?.messages, ...t?.messages },
956
- preview: { ...e?.preview, ...t?.preview },
957
- xlsx: { ...e?.xlsx, ...t?.xlsx }
958
- };
959
- }
960
- function hr(e, t) {
961
- const o = t ? e?.presets?.[t] : e?.defaultPreset ? e?.presets?.[e.defaultPreset] : void 0, r = Le(e?.defaults, o);
962
- return {
963
- showExport: r.showExport ?? he.showExport,
964
- showPrint: r.showPrint ?? he.showPrint,
965
- showPdfWindow: r.showPdfWindow ?? he.showPdfWindow,
966
- showParams: r.showParams ?? he.showParams,
967
- gapPx: r.gapPx ?? he.gapPx,
968
- pdfFontUrl: r.pdfFontUrl ?? he.pdfFontUrl,
969
- theme: { ...vr, ...r.theme },
970
- messages: { ...mr, ...r.messages },
971
- logger: r.logger ?? he.logger,
972
- preview: {
973
- overscanPages: Rt(r.preview?.overscanPages, 1, 10, !0),
974
- searchDebounceMs: Rt(r.preview?.searchDebounceMs, 200, 2e3)
975
- },
976
- xlsx: { ...r.xlsx },
977
- editable: r.editable ?? !1,
978
- excelImport: r.excelImport ?? !1
979
- };
980
- }
981
- function Rt(e, t, o, r = !1) {
982
- if (e == null || !Number.isFinite(e)) return t;
983
- const n = Math.max(0, Math.min(o, e));
984
- return r ? Math.floor(n) : n;
985
- }
986
- function br(e) {
987
- const t = {};
988
- return e.shellBg != null && (t["--mrp-shell-bg"] = e.shellBg), e.shellFg != null && (t["--mrp-shell-fg"] = e.shellFg), e.toolbarBg != null && (t["--mrp-toolbar-bg"] = e.toolbarBg), e.toolbarBorder != null && (t["--mrp-toolbar-border"] = e.toolbarBorder), e.toolbarFg != null && (t["--mrp-toolbar-fg"] = e.toolbarFg), e.btnFg != null && (t["--mrp-btn-fg"] = e.btnFg), e.btnBorder != null && (t["--mrp-btn-border"] = e.btnBorder), e.btnHoverBg != null && (t["--mrp-btn-hover-bg"] = e.btnHoverBg), e.btnHoverFg != null && (t["--mrp-btn-hover-fg"] = e.btnHoverFg), e.btnActiveBg != null && (t["--mrp-btn-active-bg"] = e.btnActiveBg), t;
989
- }
990
- function Qr(e) {
991
- const t = He(it, null), o = F(() => {
992
- const r = t?.value ?? null, n = "defaults" in e || "presets" in e || "defaultPreset" in e ? gr(e) : { defaults: e, presets: {} };
993
- if (!r) return n;
994
- const a = { ...r.presets, ...n.presets };
995
- for (const l of Object.keys(a))
996
- a[l] = Le(
997
- Le(r.presets[l], n.defaults),
998
- n.presets[l]
999
- );
1000
- return {
1001
- defaults: Le(r.defaults, n.defaults),
1002
- presets: a,
1003
- defaultPreset: n.defaultPreset ?? r.defaultPreset
1004
- };
1005
- });
1006
- It(it, o);
1007
- }
1008
- function wr() {
1009
- return He(it, F(() => null));
1010
- }
1011
- const Tt = /* @__PURE__ */ new Map(), we = /* @__PURE__ */ new Map(), yr = 15e3;
1012
- function ut(e, t) {
1013
- return Object.assign(new Error(e), { cause: t });
1014
- }
1015
- function Me(e, t) {
1016
- return `PDF 字体 ${JSON.stringify(e)}:${t}。请部署支持报表文字的字体文件,并将 pdfFontUrl 配置为可访问的字体 URL;西文报表可设为空串`;
1017
- }
1018
- function qe(e) {
1019
- if (e?.reason instanceof Error && e.reason.name === "AbortError") return e.reason;
1020
- const t = ut("PDF 字体检查已取消", e?.reason);
1021
- return t.name = "AbortError", t;
1022
- }
1023
- async function xr(e, t) {
1024
- let o = !1;
1025
- const r = setTimeout(() => {
1026
- o = !0, t.abort();
1027
- }, yr);
1028
- try {
1029
- const n = await fetch(e, { method: "HEAD", signal: t.signal });
1030
- if (t.signal.aborted) throw qe(t.signal);
1031
- if (n.status === 405 || n.status === 501 || n.type === "opaque")
1032
- return {
1033
- status: "unverified",
1034
- fontUrl: e,
1035
- message: `PDF 字体 ${JSON.stringify(e)} 无法通过 HEAD 检查验证;仍可尝试导出,届时会加载并校验字体`
1036
- };
1037
- if (!n.ok) {
1038
- const l = new Error(`字体请求返回 HTTP ${n.status}`);
1039
- return { status: "error", fontUrl: e, message: Me(e, l.message), cause: l };
1040
- }
1041
- const a = n.headers.get("content-type") ?? "";
1042
- if (/text\/html|application\/xhtml\+xml/i.test(a)) {
1043
- const l = new Error("字体 URL 返回 HTML 页面(可能是 SPA 路由回退),不是字体文件");
1044
- return { status: "error", fontUrl: e, message: Me(e, l.message), cause: l };
1045
- }
1046
- if (/^text\//i.test(a) || /(?:\/|\+)json(?:\s*;|$)/i.test(a)) {
1047
- const l = new Error(`字体 URL 返回 ${a} 文本响应,不是字体文件`);
1048
- return { status: "error", fontUrl: e, message: Me(e, l.message), cause: l };
1049
- }
1050
- return {
1051
- status: "available",
1052
- fontUrl: e,
1053
- message: "PDF 字体资源可达;文字覆盖范围将在实际导出时校验"
1054
- };
1055
- } catch (n) {
1056
- if (t.signal.aborted && !o) throw qe(t.signal);
1057
- return {
1058
- status: "error",
1059
- fontUrl: e,
1060
- message: Me(e, o ? "字体检查超时,请检查网络或字体服务" : "字体检查失败,请检查网络、字体服务或跨域访问配置"),
1061
- cause: n
1062
- };
1063
- } finally {
1064
- clearTimeout(r);
1065
- }
1066
- }
1067
- function Pr(e, t) {
1068
- if (t?.aborted) return Promise.reject(qe(t));
1069
- if (!e)
1070
- return Promise.resolve({ status: "disabled", fontUrl: e, message: "已停用自定义 PDF 字体;内置字体用于西文,其他文字会在导出时校验" });
1071
- const o = Tt.get(e);
1072
- if (o) return Promise.resolve(o);
1073
- let r = we.get(e);
1074
- if (!r) {
1075
- const a = new AbortController();
1076
- r = { controller: a, promise: xr(e, a), subscribers: 0 };
1077
- const l = r;
1078
- we.set(e, l), l.promise = l.promise.then((c) => (!a.signal.aborted && c.status === "available" && Tt.set(e, c), c)).finally(() => {
1079
- we.get(e) === l && we.delete(e);
1080
- });
1081
- }
1082
- const n = r;
1083
- return n.subscribers++, new Promise((a, l) => {
1084
- let c = !1;
1085
- const m = () => c ? !1 : (c = !0, n.subscribers--, t?.removeEventListener("abort", b), !0), b = () => {
1086
- m() && (n.subscribers === 0 && (we.get(e) === n && we.delete(e), n.controller.abort()), l(qe(t)));
1087
- };
1088
- t?.addEventListener("abort", b, { once: !0 }), n.promise.then(
1089
- (f) => {
1090
- m() && a(f);
1091
- },
1092
- (f) => {
1093
- m() && l(f);
1094
- }
1095
- ), t?.aborted && b();
1096
- });
1097
- }
1098
- function Er(e = { fontUrl: "/simhei.ttf" }) {
1099
- let t = null;
1100
- const o = async (r, n) => {
1101
- t || (t = await import("@agile-team/mach-report/pdf"));
1102
- let a = null;
1103
- if (e.fontUrl)
1104
- try {
1105
- if (a = await t.loadFontWithCache(e.fontUrl, { strict: !0 }), !a?.byteLength) throw new Error("字体文件为空或加载失败");
1106
- } catch (p) {
1107
- const h = p instanceof Error ? p.message : String(p);
1108
- throw ut(Me(e.fontUrl, h), p);
1109
- }
1110
- let l;
1111
- try {
1112
- l = await t.renderPlanToPdf(r, a ? { customFontBytes: a } : {});
1113
- } catch (p) {
1114
- if (!a) throw p;
1115
- const h = p instanceof Error ? p.message : String(p);
1116
- throw ut(`PDF 生成失败:${h}。当前字体 URL 为 ${JSON.stringify(e.fontUrl)};请确认该文件是有效字体,或重新配置 pdfFontUrl`, p);
1117
- }
1118
- const { bytes: c, unsupportedTextCount: m, pageErrors: b, fidelityWarnings: f } = l;
1119
- if (m > 0)
1120
- throw new Error(`PDF 中有 ${m} 行文字无法编码;请部署支持所用文字的字体并配置 pdfFontUrl`);
1121
- if (b.length > 0)
1122
- throw new Error(`PDF 有 ${b.length} 页渲染失败:${b[0]}`);
1123
- return f.length > 0 && n?.(`PDF 有 ${f.length} 处版式降级:${f.slice(0, 2).join(";")}`), c;
1124
- };
1125
- return o.checkFont = (r) => Pr(e.fontUrl, r), o;
1126
- }
1127
- class pe extends Error {
1128
- constructor(t, o, r) {
1129
- super(o), this.name = "MachReportError", this.code = t, this.cause = r;
1130
- }
1131
- }
1132
- function $r(e) {
1133
- return e instanceof pe ? { code: e.code, cause: e.cause } : { code: "render", cause: e };
1134
- }
1135
- function Cr(e) {
1136
- const t = e.closest(".mrp-page-holder"), o = e.closest("[data-mr-component-index]");
1137
- if (!t || !o) return null;
1138
- const r = {
1139
- pageIndex: Number(t.dataset.page) - 1,
1140
- componentIndex: Number(o.dataset.mrComponentIndex),
1141
- rowIndex: Number(e.dataset.mrRowIndex),
1142
- columnIndex: Number(e.dataset.mrColumnIndex)
1143
- };
1144
- return Object.values(r).every((n) => Number.isInteger(n) && n >= 0) ? r : null;
1145
- }
1146
- function kr(e, t, o) {
1147
- const r = e.ownerDocument.createElement("textarea");
1148
- return r.className = "mrp-cell-editor", r.setAttribute("aria-label", t), r.value = o == null ? "" : String(o), r.style.cssText = "position:absolute;inset:0;width:100%;height:100%;min-height:20px;box-sizing:border-box;z-index:10;resize:none;margin:0;padding:2px 4px;border:2px solid #2563eb;outline:none;background:#fff;color:#111;font:inherit;line-height:1.25;white-space:pre-wrap;", e.appendChild(r), r;
1149
- }
1150
- function Mr(e) {
1151
- const t = ye(null), o = A(!1), r = ye([]);
1152
- let n = null;
1153
- function a() {
1154
- const i = t.value;
1155
- t.value = null, o.value = !1, n = null, i?.controller.abort(), i?.input.remove();
1156
- }
1157
- function l() {
1158
- a(), r.value = [];
1159
- }
1160
- function c(i) {
1161
- return t.value === i && !i.controller.signal.aborted && e.plan.value === i.plan;
1162
- }
1163
- function m(i) {
1164
- const x = e.options.value, $ = Mt(i.plan, i.address);
1165
- if (!(typeof x == "object" ? x === i.options : x === !0) || !$?.editable || i.options.canEdit?.($) === !1)
1166
- throw new Dt("readonly");
1167
- }
1168
- async function b(i) {
1169
- try {
1170
- m(i);
1171
- const x = cn(i.plan, i.address, i.input.value);
1172
- if (Object.is(x.value, x.previousValue))
1173
- return a(), !0;
1174
- const $ = { signal: i.controller.signal }, w = await i.options.validate?.(structuredClone(x), $);
1175
- if (!c(i)) return !1;
1176
- if (w) throw new Error(w);
1177
- if (m(i), await i.options.save?.(structuredClone(x), $), !c(i)) return !1;
1178
- m(i);
1179
- const I = dn(i.plan, x);
1180
- return a(), r.value = [...r.value, x], e.plan.value = I, e.onChange(structuredClone(x)), !0;
1181
- } catch (x) {
1182
- return c(i) && (e.onError(e.errorMessage?.(x) ?? (x instanceof Error ? x.message : "单元格保存失败"), x), i.input.disabled = !1, i.input.setAttribute("aria-invalid", "true"), i.input.focus()), !1;
1183
- } finally {
1184
- t.value === i && (o.value = !1);
1185
- }
1186
- }
1187
- async function f() {
1188
- if (n) return n;
1189
- const i = t.value;
1190
- if (!i) return !0;
1191
- if (!c(i))
1192
- return a(), !1;
1193
- o.value = !0, i.input.disabled = !0;
1194
- const x = b(i);
1195
- n = x;
1196
- const $ = await x;
1197
- return n === x && (n = null), $;
1198
- }
1199
- function p(i) {
1200
- i.stopPropagation(), !i.isComposing && (i.key === "Escape" && (i.preventDefault(), a()), i.key === "Enter" && !i.shiftKey && (i.preventDefault(), f()));
1201
- }
1202
- async function h(i) {
1203
- if (!e.options.value || e.blocked()) return;
1204
- const x = i.target;
1205
- if (!(x instanceof Element) || x.closest(".mrp-cell-editor")) return;
1206
- const $ = x.closest("td[data-mr-row-index]");
1207
- if (!$ || !await f() || !$.isConnected) return;
1208
- const w = e.plan.value, I = Cr($);
1209
- if (!w || !I || !e.options.value || e.blocked()) return;
1210
- const P = typeof e.options.value == "object" ? e.options.value : {};
1211
- try {
1212
- const O = Mt(w, I);
1213
- if (!O?.editable || P.canEdit?.(O) === !1) return;
1214
- const C = kr($, e.label(), O.value);
1215
- t.value = { plan: w, address: I, input: C, controller: new AbortController(), options: P }, C.addEventListener("keydown", p), C.addEventListener("blur", () => {
1216
- o.value || f();
1217
- }), C.focus(), C.select();
1218
- } catch (O) {
1219
- e.onError(O instanceof Error ? O.message : "无法编辑单元格", O);
1220
- }
1221
- }
1222
- return _(e.options, (i, x) => {
1223
- (!i || i !== x) && a();
1224
- }, { flush: "sync" }), _(e.plan, () => {
1225
- t.value && e.plan.value !== t.value.plan && a();
1226
- }, { flush: "sync" }), Re(l), {
1227
- active: t,
1228
- saving: o,
1229
- changes: r,
1230
- cancel: a,
1231
- reset: l,
1232
- commit: f,
1233
- onDoubleClick: h,
1234
- getChanges: () => structuredClone(r.value)
1235
- };
1236
- }
1237
- const Fr = {
1238
- key: 2,
1239
- class: "mrp-edit-hint",
1240
- role: "status"
1241
- }, Rr = {
1242
- key: 4,
1243
- class: "mrp-export-notice mrp-export-warning",
1244
- role: "status"
1245
- }, Tr = { class: "mrp-main" }, Ir = {
1246
- key: 0,
1247
- class: "mrp-state"
1248
- }, Sr = {
1249
- key: 1,
1250
- class: "mrp-state mrp-error"
1251
- }, Dr = {
1252
- key: 2,
1253
- class: "mrp-state"
1254
- }, Or = ["data-page"], Br = ["onClick"], Wr = ["data-thumb"], Ar = { class: "mrp-thumb-no" }, Lr = { class: "mrp-overlay" }, zr = {
1255
- key: 5,
1256
- class: "mrp-debug",
1257
- "aria-hidden": "true"
1258
- }, We = 96 / 25.4, ot = "mach-report:ui", lt = "mach-report:ui:wide", Hr = /* @__PURE__ */ ct({
1259
- __name: "ReportPreview",
1260
- props: {
1261
- reportId: {
1262
- type: [String, Array],
1263
- default: null
1264
- },
1265
- params: {
1266
- type: Object,
1267
- default: () => ({})
1268
- },
1269
- height: { type: String, default: "100vh" },
1270
- autoLoad: { type: Boolean, default: !0 },
1271
- /** 以下显隐/间距不传时走配置中心(preset > defaults > 内置缺省) */
1272
- showExport: { type: Boolean, default: void 0 },
1273
- showPrint: { type: Boolean, default: void 0 },
1274
- showPdfWindow: { type: Boolean, default: void 0 },
1275
- /** 页间距(px);不传走配置中心 */
1276
- gapPx: { type: Number, default: void 0 },
1277
- /** 工具栏/状态文案覆写(不传走配置中心 messages) */
1278
- messages: { type: Object, default: void 0 },
1279
- /** 启用的 preset 名(不传用配置中心 defaultPreset) */
1280
- preset: { type: String, default: void 0 },
1281
- /** 调试面板(也可用 URL ?mrp-debug=1 开启) */
1282
- debug: { type: Boolean, default: !1 },
1283
- /** 参数定义(优先级:prop > 模板 params;有定义且未关闭时显示查询面板) */
1284
- paramDefs: {
1285
- type: Array,
1286
- default: void 0
1287
- },
1288
- /** 参数面板显隐(不传走配置中心,缺省 true;有参数定义才渲染) */
1289
- showParams: { type: Boolean, default: void 0 },
1290
- editable: { type: [Boolean, Object], default: void 0 },
1291
- excelImport: { type: [Boolean, Object], default: void 0 },
1292
- fetcher: {
1293
- type: Function,
1294
- default: null
1295
- }
1296
- },
1297
- emits: ["loaded", "error", "warning", "cell-edit", "template-import"],
1298
- setup(e, { expose: t, emit: o }) {
1299
- nn((s) => ({
1300
- v587d5a34: H.value + "px"
1301
- }));
1302
- const r = e, n = o, a = ye(null), l = A(!1), c = A(""), m = ye(null), b = A(null), f = A(!1), p = ye(Object.freeze({ status: "unchecked", fontUrl: "" })), h = A(null), i = A(1), x = A(null), $ = A(null), w = A(null), I = A(!1), P = A(!1), O = A(null), C = Bn(), D = F(() => !!a.value?.pages.length && a.value.pages.every((s) => s.layout === "wide")), H = F(() => Math.max(0, ee.value));
1303
- let K = ot;
1304
- const X = He(hn, null), Q = He(bn, null), Y = F(() => Bt(r.reportId)), se = F(() => r.fetcher ?? X), U = F(() => a.value?.pages.length ?? 0), me = F(() => Object.freeze({
1305
- loading: l.value,
1306
- hasPlan: U.value > 0,
1307
- pageCount: U.value,
1308
- currentPage: i.value,
1309
- exporting: b.value,
1310
- printing: f.value,
1311
- canExport: !l.value && !P.value && !q.saving.value && U.value > 0 && b.value === null,
1312
- canPrint: !l.value && !P.value && !q.saving.value && U.value > 0 && !f.value,
1313
- error: m.value,
1314
- pdfFont: p.value,
1315
- editing: q.active.value !== null,
1316
- saving: q.saving.value,
1317
- importing: P.value,
1318
- dirty: q.changes.value.length > 0
1319
- }));
1320
- function J(s, v, g) {
1321
- m.value = Object.freeze({ message: s, code: v, cause: g }), n("error", s, { code: v, cause: g });
1322
- }
1323
- const u = wr(), d = F(() => hr(u.value, r.preset)), y = F(() => ({
1324
- ...d.value.messages,
1325
- ...r.messages
1326
- })), T = F(() => r.showExport ?? d.value.showExport), B = F(() => r.showPrint ?? d.value.showPrint), V = F(() => r.showPdfWindow ?? d.value.showPdfWindow), ee = F(() => r.gapPx ?? (D.value ? 0 : d.value.gapPx)), oe = F(() => r.showParams ?? d.value.showParams), mt = F(() => r.editable ?? d.value.editable), Te = F(() => r.excelImport ?? d.value.excelImport);
1327
- function Lt(s) {
1328
- return s instanceof Dt ? {
1329
- number: y.value.editInvalidNumber,
1330
- boolean: y.value.editInvalidBoolean,
1331
- conflict: y.value.editConflict
1332
- }[s.code] ?? s.message : s instanceof Error ? s.message : "单元格保存失败";
1333
- }
1334
- const q = Mr({
1335
- plan: a,
1336
- options: mt,
1337
- blocked: () => l.value || P.value || b.value !== null || f.value,
1338
- label: () => y.value.editCell ?? "编辑单元格",
1339
- errorMessage: Lt,
1340
- onChange: (s) => {
1341
- m.value = null, h.value = null, n("cell-edit", s);
1342
- },
1343
- onError: (s, v) => {
1344
- h.value = { kind: "error", message: s }, J(s, "edit", v);
1345
- }
1346
- });
1347
- let vt = null, Ue = null;
1348
- function gt() {
1349
- if (Q) return Q;
1350
- const s = d.value.pdfFontUrl;
1351
- return (!Ue || vt !== s) && (vt = s, Ue = Er({ fontUrl: s })), Ue;
1352
- }
1353
- let Ie = 0, xe = null, Se = null, ie = !1;
1354
- function Ve() {
1355
- Ie++, xe?.abort(), xe = null;
1356
- }
1357
- async function De() {
1358
- if (ie) throw new pe("config", "报表预览已卸载");
1359
- Ve();
1360
- const s = Ie, v = new AbortController();
1361
- xe = v;
1362
- const g = d.value.pdfFontUrl;
1363
- p.value = Object.freeze({ status: "checking", fontUrl: g });
1364
- try {
1365
- const z = gt(), L = z.checkFont ? await z.checkFont(v.signal) : { status: "unverified", fontUrl: "", message: "自定义 PDF 导出器未提供字体预检查;字体由宿主确认" };
1366
- return !ie && s === Ie && !v.signal.aborted && (p.value = Object.freeze({ ...L })), L;
1367
- } catch (z) {
1368
- if (v.signal.aborted) throw z;
1369
- const L = {
1370
- status: "error",
1371
- fontUrl: g,
1372
- message: z instanceof Error ? z.message : "PDF 字体检查失败",
1373
- cause: z
1374
- };
1375
- return !ie && s === Ie && (p.value = Object.freeze(L)), L;
1376
- } finally {
1377
- xe === v && (xe = null);
1378
- }
1379
- }
1380
- function zt() {
1381
- De().catch(() => {
1382
- });
1383
- }
1384
- _(
1385
- [a, () => d.value.pdfFontUrl, T, V],
1386
- () => {
1387
- const s = p.value.fontUrl === d.value.pdfFontUrl;
1388
- s && p.value.status === "available" || (Ve(), (!s || p.value.status === "checking") && (p.value = Object.freeze({ status: "unchecked", fontUrl: d.value.pdfFontUrl })), !ie && U.value > 0 && (T.value || V.value) && De().catch(() => {
1389
- }));
1390
- },
1391
- { immediate: !0 }
1392
- );
1393
- const fe = F(
1394
- () => r.paramDefs ?? se.value?.getParamDefs?.(Y.value) ?? []
1395
- ), ve = A({}), Ke = A(!1);
1396
- function Pe(s) {
1397
- const v = {};
1398
- for (const g of s)
1399
- v[g.field] = r.params[g.field] ?? g.defaultValue ?? "";
1400
- ve.value = v, Ke.value = !1;
1401
- }
1402
- Pe(fe.value), _(fe, (s) => Pe(s)), _(Y, () => Pe(fe.value)), _(() => JSON.stringify(r.params), () => Pe(fe.value));
1403
- const Ht = F(() => {
1404
- const s = { ...r.params };
1405
- for (const [v, g] of Object.entries(ve.value))
1406
- g === "" ? delete s[v] : s[v] = g;
1407
- return s;
1408
- });
1409
- function Nt() {
1410
- return fe.value.filter(
1411
- (s) => s.required === !0 && !(ve.value[s.field] ?? "").trim()
1412
- );
1413
- }
1414
- function jt() {
1415
- Ke.value = !0;
1416
- const s = Nt();
1417
- if (s.length > 0) {
1418
- const v = s[0].label ?? s[0].field, g = y.value.paramRequired.replace("{label}", v);
1419
- c.value = g, J(g, "param");
1420
- return;
1421
- }
1422
- ge();
1423
- }
1424
- function qt() {
1425
- Pe(fe.value);
1426
- }
1427
- const Ut = F(() => ({
1428
- height: r.height,
1429
- ...br(d.value.theme)
1430
- })), { zoom: te, zoomMode: Ee, applyFitZoom: ht, setZoom: $e } = xn(() => ({
1431
- viewport: $.value,
1432
- pageWidthPx: Ye.contentSize.value.w || 210 * We
1433
- })), Ye = yn(a, te, {
1434
- pxPerMm: We,
1435
- gapPx: ee,
1436
- overscan: F(() => d.value.preview.overscanPages)
1437
- }), { contentSize: Ze, windowRange: Ce, visiblePages: bt, makeScrollHandler: Vt, refreshViewport: Je } = Ye, Kt = Vt(i, U);
1438
- function Ge(s) {
1439
- $e(s * 100);
1440
- }
1441
- function Oe() {
1442
- P.value = !1, q.reset(), wt(), a.value = null, i.value = 1, N.reset();
1443
- }
1444
- let Z = 0, re = null;
1445
- async function ge() {
1446
- if (ie) return;
1447
- const s = ++Z;
1448
- P.value = !1, re?.abort(), re = null;
1449
- const v = se.value;
1450
- if (l.value = !1, m.value = null, Y.value.length === 0) {
1451
- c.value = "缺少报表 ID", Oe(), J(c.value, "param");
1452
- return;
1453
- }
1454
- if (!v) {
1455
- c.value = "未提供渲染数据源 fetcher", Oe(), J(c.value, "config");
1456
- return;
1457
- }
1458
- l.value = !0, c.value = "", h.value = null, Oe();
1459
- const g = C.start(), z = new AbortController();
1460
- re = z;
1461
- const L = /* @__PURE__ */ new Set();
1462
- function ae(W) {
1463
- s !== Z || z.signal.aborted || L.has(W) || (L.add(W), d.value.logger.warn("[mach-report] 报表告警:", W), n("warning", W));
1464
- }
1465
- try {
1466
- const W = await v({
1467
- reportIds: Y.value,
1468
- params: { ...Ht.value },
1469
- signal: z.signal,
1470
- onWarning: ae
1471
- });
1472
- if (s !== Z) return;
1473
- const G = Ft(W);
1474
- if (!G.ok) {
1475
- const Be = G.errors.slice(0, 3).map(($t) => `${$t.path}: ${$t.message}`).join("; ");
1476
- throw new pe(
1477
- "validate",
1478
- `渲染计划校验失败(${G.errors.length} 处): ${Be}`
1479
- );
1480
- }
1481
- if (G.warnings.forEach((Be) => ae(`${Be.path}: ${Be.message}`)), s !== Z || z.signal.aborted) return;
1482
- a.value = W, i.value = 1, C.end(g), $.value && ($.value.scrollTop = 0, $.value.scrollLeft = 0);
1483
- const ne = D.value ? lt : ot;
1484
- ne !== K && (K = ne, rt()), Ee.value === "fit" && ht(), n("loaded", W.pages.length);
1485
- } catch (W) {
1486
- if (s !== Z) return;
1487
- const G = W instanceof pe ? W : W instanceof pn ? new pe(W.code, W.message, W.cause) : new pe(
1488
- "fetch",
1489
- W instanceof Error ? W.message : "预览加载失败",
1490
- W
1491
- );
1492
- c.value = G.message;
1493
- const ne = $r(G);
1494
- J(G.message, ne.code, ne.cause);
1495
- } finally {
1496
- s === Z && (l.value = !1), re === z && (re = null);
1497
- }
1498
- }
1499
- function ue(s) {
1500
- if (ie || U.value <= 0) return;
1501
- const v = Math.max(1, Math.min(U.value, s));
1502
- i.value = v;
1503
- const g = $.value;
1504
- g && (g.scrollTop = Ye.pageOffsetPx(v - 1) * te.value, Je(g));
1505
- }
1506
- const ke = En(a, {
1507
- getPdfExporter: gt,
1508
- getXlsxOptions: () => d.value.xlsx,
1509
- onError: (s, v) => {
1510
- h.value = { kind: "error", message: s }, J(s, v ?? "print");
1511
- },
1512
- onWarning: (s) => {
1513
- h.value = { kind: "warning", message: s }, n("warning", s);
1514
- },
1515
- onBusy: (s) => {
1516
- b.value = s, s ? h.value = {
1517
- kind: "progress",
1518
- message: y.value.exporting.replace("{format}", s)
1519
- } : h.value?.kind === "progress" && (h.value = null);
1520
- },
1521
- onPrinting: (s) => {
1522
- f.value = s;
1523
- }
1524
- }), { releasePrintFrame: wt, dispose: Yt } = ke;
1525
- async function Xe() {
1526
- l.value || P.value || q.active.value && !await q.commit() || (m.value = null, await ke.print());
1527
- }
1528
- async function Qe(s) {
1529
- l.value || P.value || q.active.value && !await q.commit() || (m.value = null, await ke.exportAs(s));
1530
- }
1531
- function _e() {
1532
- if (l.value || P.value || q.active.value) {
1533
- h.value = { kind: "warning", message: y.value.editingHint ?? "请先确认单元格修改" };
1534
- return;
1535
- }
1536
- m.value = null, ke.openPdfWindow();
1537
- }
1538
- async function yt(s, v = {}) {
1539
- ie || (ve.value = { ...ve.value, ...s }, v.reload !== !1 && await ge());
1540
- }
1541
- const Zt = {
1542
- reload: ge,
1543
- print: Xe,
1544
- exportAs: Qe,
1545
- openPdfWindow: _e,
1546
- gotoPage: ue,
1547
- setParams: yt,
1548
- checkPdfFont: De,
1549
- importExcel: et,
1550
- getPlan: xt,
1551
- getChanges: q.getChanges,
1552
- get state() {
1553
- return me.value;
1554
- }
1555
- };
1556
- It(wn, Zt);
1557
- function xt() {
1558
- return a.value ? structuredClone(a.value) : null;
1559
- }
1560
- async function et(s, v) {
1561
- if (ie) throw new pe("config", "报表预览已卸载");
1562
- const g = ++Z;
1563
- re?.abort(), re = null, l.value = !1, q.cancel(), ke.invalidatePending(), P.value = !0, m.value = null, h.value = { kind: "progress", message: y.value.importing ?? "正在导入 Excel…" };
1564
- try {
1565
- const { importExcelTemplate: z } = await import("@agile-team/mach-report/xlsx");
1566
- if (g !== Z) return null;
1567
- const L = typeof Te.value == "object" ? Te.value : {}, ae = await z(s, { ...L, ...v, limits: { ...L.limits, ...v?.limits } });
1568
- if (g !== Z) return null;
1569
- const W = fn(structuredClone(ae.template), {}).plan, G = Ft(W);
1570
- if (!G.ok) throw new Error(G.errors.map((ne) => ne.message).slice(0, 3).join("; "));
1571
- for (const ne of ae.warnings) {
1572
- if (g !== Z) return null;
1573
- n("warning", ne);
1574
- }
1575
- return g !== Z ? null : (q.reset(), wt(), N.reset(), a.value = W, i.value = 1, c.value = "", h.value = ae.warnings.length ? { kind: "warning", message: ae.warnings.join(";") } : null, $.value && ($.value.scrollTop = 0, $.value.scrollLeft = 0), K = D.value ? lt : ot, rt(), n("template-import", ae), g === Z && n("loaded", W.pages.length), ae);
1576
- } catch (z) {
1577
- if (g !== Z) return null;
1578
- const L = new pe("import", z instanceof Error ? z.message : "Excel 模板导入失败", z);
1579
- throw h.value = { kind: "error", message: L.message }, J(L.message, "import", z), L;
1580
- } finally {
1581
- g === Z && (P.value = !1);
1582
- }
1583
- }
1584
- function Jt(s) {
1585
- const v = s.target, g = v.files?.[0];
1586
- v.value = "", g && et(g).catch(() => {
1587
- });
1588
- }
1589
- const N = Sn({
1590
- plan: a,
1591
- gotoPage: ue,
1592
- debounceMs: F(() => d.value.preview.searchDebounceMs),
1593
- highlight: Cn,
1594
- clearHighlights: $n
1595
- });
1596
- function Gt(s) {
1597
- s.ctrlKey && (s.preventDefault(), Ge(te.value * (s.deltaY < 0 ? 1.1 : 1 / 1.1)));
1598
- }
1599
- function Xt(s) {
1600
- if (!(s.target instanceof Element && s.target.closest("input,textarea,select,[contenteditable='true']"))) {
1601
- if ((s.ctrlKey || s.metaKey) && s.key.toLowerCase() === "f") {
1602
- s.preventDefault(), N.visible.value || N.toggle();
1603
- return;
1604
- }
1605
- switch (s.key) {
1606
- case "PageDown":
1607
- s.preventDefault(), ue(i.value + 1);
1608
- break;
1609
- case "PageUp":
1610
- s.preventDefault(), ue(i.value - 1);
1611
- break;
1612
- case "Home":
1613
- s.preventDefault(), ue(1);
1614
- break;
1615
- case "End":
1616
- s.preventDefault(), ue(U.value);
1617
- break;
1618
- case "+":
1619
- case "=":
1620
- s.preventDefault(), Ge(te.value * 1.1);
1621
- break;
1622
- case "-":
1623
- s.preventDefault(), Ge(te.value / 1.1);
1624
- break;
1625
- }
1626
- }
1627
- }
1628
- function Qt() {
1629
- try {
1630
- localStorage.setItem(
1631
- K,
1632
- JSON.stringify({ zoomMode: Ee.value === "fit" ? "fit" : Math.round(te.value * 100) })
1633
- );
1634
- } catch {
1635
- }
1636
- }
1637
- _([Ee, te], Qt);
1638
- let tt = "";
1639
- const Pt = /* @__PURE__ */ new WeakMap();
1640
- function Et(s = !1) {
1641
- const v = N.activeMatch.value;
1642
- if (!D.value || !v) return;
1643
- const g = `${N.query.value}:${N.matchIndex.value}:${v.pageIndex}`;
1644
- if (!s && g === tt) return;
1645
- const L = x.value?.querySelector(`[data-page="${v.pageIndex + 1}"]`)?.querySelectorAll("mark.mrp-hit")[v.occurrence];
1646
- L && (L.scrollIntoView?.({ block: "nearest", inline: "nearest" }), tt = g);
1647
- }
1648
- kt(() => {
1649
- const s = a.value;
1650
- if (!s) return;
1651
- const v = N.activeMatch.value;
1652
- N.matchIndex.value, v || (tt = ""), bt.value;
1653
- const g = x.value;
1654
- if (!g) return;
1655
- g.querySelectorAll(".mrp-page-holder").forEach((L) => {
1656
- const ae = Number(L.dataset.page ?? 0) - 1, W = s.pages[ae];
1657
- if (!W || L.childElementCount > 0 && Pt.get(L) === W) {
1658
- if (L.firstElementChild) {
1659
- const ne = L.firstElementChild;
1660
- N.clear(ne), N.apply(ne);
1661
- }
1662
- return;
1663
- }
1664
- L.style.width = `${W.pageWidthMm * We}px`;
1665
- const G = St(W, 96, {}, document);
1666
- N.apply(G), L.replaceChildren(G), Pt.set(L, W);
1667
- }), Et();
1668
- }, { flush: "post" }), _(() => N.query.value, (s) => {
1669
- s || x.value?.querySelectorAll(".mrp-page-holder").forEach((v) => {
1670
- N.clear(v);
1671
- });
1672
- });
1673
- const le = On(a, {
1674
- thumbsRoot: w,
1675
- visible: I,
1676
- renderThumbCanvas: (s) => {
1677
- try {
1678
- const v = a.value.pages[s], g = Math.min(0.2, 116 / Math.max(1, v.pageWidthMm * We)), { canvases: z } = mn(a.value, { start: s, end: s, dpr: g });
1679
- return z[0] ?? null;
1680
- } catch {
1681
- return null;
1682
- }
1683
- }
1684
- });
1685
- kt(() => {
1686
- le.schedule();
1687
- }, { flush: "post" });
1688
- const _t = F(() => r.debug), { debugStats: be } = Dn(_t, {
1689
- plan: a,
1690
- pageCount: U,
1691
- windowRange: Ce,
1692
- zoom: te,
1693
- loadMs: C.loadMs
1694
- });
1695
- function nt() {
1696
- Je($.value), le.schedule(), Ee.value === "fit" && ht(), Et(!0);
1697
- }
1698
- function rt() {
1699
- $e(K === lt ? 100 : "fit");
1700
- try {
1701
- const s = JSON.parse(localStorage.getItem(K) ?? "{}");
1702
- s.zoomMode === "fit" ? $e("fit") : typeof s.zoomMode == "number" && $e(s.zoomMode);
1703
- } catch {
1704
- }
1705
- }
1706
- return rn(() => {
1707
- window.addEventListener("resize", nt), typeof ResizeObserver < "u" && $.value && (Se = new ResizeObserver(nt), Se.observe($.value)), Je($.value), rt(), r.autoLoad && ge();
1708
- }), an(() => {
1709
- ie = !0, q.reset(), P.value = !1, Ve(), Z++, re?.abort(), re = null, window.removeEventListener("resize", nt), Se?.disconnect(), Se = null, le.destroy(), N.reset(), Yt();
1710
- }), _(
1711
- () => [JSON.stringify(Y.value), JSON.stringify(r.params), se.value],
1712
- () => {
1713
- if (r.autoLoad) {
1714
- ge();
1715
- return;
1716
- }
1717
- Z++, re?.abort(), re = null, l.value = !1, c.value = "", m.value = null, h.value = null, Oe();
1718
- }
1719
- ), t({ reload: ge, print: Xe, exportAs: Qe, openPdfWindow: _e, gotoPage: ue, setParams: yt, checkPdfFont: De, importExcel: et, getPlan: xt, getChanges: q.getChanges, state: me }), (s, v) => (k(), M("div", {
1720
- class: de(["mach-report-preview", { "mrp-wide-report": D.value }]),
1721
- style: ce(Ut.value)
1722
- }, [
1723
- oe.value && fe.value.length > 0 ? (k(), on(pr, {
1724
- key: 0,
1725
- defs: fe.value,
1726
- modelValue: ve.value,
1727
- "onUpdate:modelValue": v[0] || (v[0] = (g) => ve.value = g),
1728
- messages: y.value,
1729
- attempted: Ke.value,
1730
- onQuery: jt,
1731
- onReset: qt
1732
- }, null, 8, ["defs", "modelValue", "messages", "attempted"])) : j("", !0),
1733
- ln(tr, {
1734
- "page-count": U.value,
1735
- "current-page": i.value,
1736
- "zoom-mode": E(Ee),
1737
- zoom: E(te),
1738
- "show-export": T.value,
1739
- "show-print": B.value,
1740
- "show-pdf-window": V.value,
1741
- messages: y.value,
1742
- search: { visible: E(N).visible.value, query: E(N).query.value, matchIndex: E(N).matchIndex.value, matchCount: E(N).matchCount.value, searching: E(N).searching.value },
1743
- "thumbs-visible": I.value,
1744
- "show-import": !!Te.value,
1745
- busy: l.value || P.value || E(q).saving.value,
1746
- onGoto: ue,
1747
- onZoom: E($e),
1748
- onExport: v[1] || (v[1] = (g) => Qe(g)),
1749
- onPrint: Xe,
1750
- onPdfWindow: _e,
1751
- onSearchInput: E(N).onInput,
1752
- onSearchNav: E(N).onNav,
1753
- onSearchToggle: E(N).toggle,
1754
- onThumbsToggle: v[2] || (v[2] = (g) => I.value = !I.value),
1755
- onImportExcel: v[3] || (v[3] = (g) => O.value?.click())
1756
- }, null, 8, ["page-count", "current-page", "zoom-mode", "zoom", "show-export", "show-print", "show-pdf-window", "messages", "search", "thumbs-visible", "show-import", "busy", "onZoom", "onSearchInput", "onSearchNav", "onSearchToggle"]),
1757
- Te.value ? (k(), M("input", {
1758
- key: 1,
1759
- ref_key: "importInputRef",
1760
- ref: O,
1761
- class: "mrp-import-input",
1762
- type: "file",
1763
- accept: ".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1764
- hidden: "",
1765
- onChange: Jt
1766
- }, null, 544)) : j("", !0),
1767
- mt.value && U.value > 0 ? (k(), M("div", Fr, R(E(q).saving.value ? y.value.saving : y.value.editingHint), 1)) : j("", !0),
1768
- h.value ? (k(), M("div", {
1769
- key: 3,
1770
- class: de(["mrp-export-notice", `mrp-export-${h.value.kind}`]),
1771
- role: "alert"
1772
- }, R(h.value.message), 3)) : j("", !0),
1773
- p.value.status === "error" && (T.value || V.value) ? (k(), M("div", Rr, [
1774
- st(R(y.value.pdfFontUnavailable) + " ", 1),
1775
- S("button", {
1776
- type: "button",
1777
- onClick: zt
1778
- }, R(y.value.retry), 1)
1779
- ])) : j("", !0),
1780
- S("div", Tr, [
1781
- S("div", {
1782
- ref_key: "viewportRef",
1783
- ref: $,
1784
- class: "mrp-body",
1785
- tabindex: "0",
1786
- onWheel: Gt,
1787
- onKeydown: Xt,
1788
- onDblclick: v[4] || (v[4] = //@ts-ignore
1789
- (...g) => E(q).onDoubleClick && E(q).onDoubleClick(...g)),
1790
- onScrollPassive: v[5] || (v[5] = (g) => E(Kt)(g.target))
1791
- }, [
1792
- l.value ? (k(), M("div", Ir, R(y.value.loading), 1)) : c.value ? (k(), M("div", Sr, [
1793
- st(R(c.value) + " ", 1),
1794
- S("button", {
1795
- class: "mrp-retry",
1796
- type: "button",
1797
- onClick: ge
1798
- }, R(y.value.retry), 1)
1799
- ])) : !a.value || U.value === 0 ? (k(), M("div", Dr, R(y.value.empty), 1)) : (k(), M("div", {
1800
- key: 3,
1801
- class: "mrp-scale",
1802
- style: ce({ width: `${E(Ze).w * E(te)}px`, height: `${E(Ze).h * E(te)}px` })
1803
- }, [
1804
- S("div", {
1805
- ref_key: "containerRef",
1806
- ref: x,
1807
- class: "mrp-scale-inner",
1808
- style: ce({ transform: `scale(${E(te)})`, transformOrigin: "top left", width: `${E(Ze).w}px` })
1809
- }, [
1810
- E(Ce).padTopPx > 0 ? (k(), M("div", {
1811
- key: 0,
1812
- class: "mrp-spacer-top",
1813
- style: ce({ height: `${E(Ce).padTopPx}px` }),
1814
- "aria-hidden": "true"
1815
- }, null, 4)) : j("", !0),
1816
- (k(!0), M(Fe, null, ze(E(bt), (g) => (k(), M("div", {
1817
- key: g.index,
1818
- class: "mrp-page-holder",
1819
- "data-page": g.index + 1
1820
- }, null, 8, Or))), 128)),
1821
- E(Ce).padBottomPx > 0 ? (k(), M("div", {
1822
- key: 1,
1823
- class: "mrp-spacer-bottom",
1824
- style: ce({ height: `${E(Ce).padBottomPx}px` }),
1825
- "aria-hidden": "true"
1826
- }, null, 4)) : j("", !0)
1827
- ], 4)
1828
- ], 4))
1829
- ], 544),
1830
- I.value && U.value > 0 ? (k(), M("aside", {
1831
- key: 0,
1832
- ref_key: "thumbsRef",
1833
- ref: w,
1834
- class: "mrp-thumbs",
1835
- onScrollPassive: v[6] || (v[6] = //@ts-ignore
1836
- (...g) => E(le).onScroll && E(le).onScroll(...g))
1837
- }, [
1838
- E(le).windowRange.value.padTopPx > 0 ? (k(), M("div", {
1839
- key: 0,
1840
- class: "mrp-thumb-spacer",
1841
- style: ce({ height: `${E(le).windowRange.value.padTopPx}px` }),
1842
- "aria-hidden": "true"
1843
- }, null, 4)) : j("", !0),
1844
- (k(!0), M(Fe, null, ze(E(le).visibleThumbs.value, (g) => (k(), M("div", {
1845
- key: g.index,
1846
- class: de(["mrp-thumb", { "mrp-thumb-active": g.index + 1 === i.value }]),
1847
- style: ce({ height: `${g.height + 20}px` }),
1848
- onClick: (z) => ue(g.index + 1)
1849
- }, [
1850
- S("div", {
1851
- class: "mrp-thumb-box",
1852
- "data-thumb": g.index + 1,
1853
- style: ce({ height: `${g.height}px` })
1854
- }, null, 12, Wr),
1855
- S("span", Ar, R(g.index + 1), 1)
1856
- ], 14, Br))), 128)),
1857
- E(le).windowRange.value.padBottomPx > 0 ? (k(), M("div", {
1858
- key: 1,
1859
- class: "mrp-thumb-spacer",
1860
- style: ce({ height: `${E(le).windowRange.value.padBottomPx}px` }),
1861
- "aria-hidden": "true"
1862
- }, null, 4)) : j("", !0)
1863
- ], 544)) : j("", !0)
1864
- ]),
1865
- S("div", Lr, [
1866
- sn(s.$slots, "default", {}, void 0, !0)
1867
- ]),
1868
- E(be) ? (k(), M("div", zr, [
1869
- v[7] || (v[7] = S("div", null, "mach-report debug", -1)),
1870
- S("div", null, "pages: " + R(E(be).pages) + " | window: [" + R(E(be).window) + "]", 1),
1871
- S("div", null, "zoom: " + R(E(be).zoom) + " | load: " + R(E(be).loadMs), 1),
1872
- S("div", null, "plan: " + R(E(be).planKB) + "KB", 1)
1873
- ])) : j("", !0)
1874
- ], 6));
1875
- }
1876
- }), Nr = /* @__PURE__ */ pt(Hr, [["__scopeId", "data-v-8dab9187"]]), _r = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1877
- __proto__: null,
1878
- default: Nr
1879
- }, Symbol.toStringTag, { value: "Module" }));
1880
- export {
1881
- mr as D,
1882
- pe as M,
1883
- at as P,
1884
- pr as R,
1885
- Xr as S,
1886
- vr as a,
1887
- Nr as b,
1888
- tr as c,
1889
- Wt as d,
1890
- Pn as e,
1891
- Er as f,
1892
- Zr as g,
1893
- gr as h,
1894
- Gr as i,
1895
- Yr as j,
1896
- Qr as k,
1897
- $r as l,
1898
- yn as m,
1899
- Bt as n,
1900
- En as o,
1901
- Jr as p,
1902
- xn as q,
1903
- hr as r,
1904
- _r as s,
1905
- br as t,
1906
- wr as u
1907
- };