@agile-team/mach-report 2.4.1 → 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,1910 +0,0 @@
1
- import { computed as F, unref as E, ref as A, onScopeDispose as Te, getCurrentScope as tn, watch as _, shallowRef as xe, defineComponent as dt, nextTick as nn, openBlock as C, createElementBlock as M, createElementVNode as S, toDisplayString as R, Fragment as Re, createCommentVNode as j, normalizeClass as de, renderList as Ne, createTextVNode as it, withKeys as Ct, inject as He, provide as St, useCssVars as rn, watchEffect as Mt, onMounted as an, onUnmounted as on, normalizeStyle as ce, createBlock as ln, createVNode as sn, renderSlot as un } from "vue";
2
- import { renderPlanToImages as cn, renderPage as Ot, getReportCellContext as Ft, createReportCellEdit as dn, applyReportCellEdit as fn, ReportCellEditError as Dt, paginateTemplate as pn, validateRenderPlan as Rt, ReportSourceError as mn, renderPlanToCanvas as vn } from "@agile-team/mach-report";
3
- import { c as Bt } from "./page-window-index-CIuT4BAv.js";
4
- import { i as gn, b as hn } from "./render-plan-CXBWRog4.js";
5
- import { b as ut, c as bn, d as wn, a as yn } from "./plugin-CKnSVuVe.js";
6
- function Wt(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 Wt(e).join(",");
11
- }
12
- class ot 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, D = P.indexOf("?"), k = D >= 0 ? P.slice(0, D) : P, O = new URLSearchParams(D >= 0 ? P.slice(D + 1) : "");
23
- for (const [N, K] of Object.entries(m)) O.set(N, K);
24
- f = `${k}?${O}${I}`;
25
- }
26
- const p = (w, I) => {
27
- const P = new ot(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 ot(`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 ot ? w : p(`请求失败(${l}): ${w instanceof Error ? w.message : String(w)}`, w);
53
- } finally {
54
- clearTimeout($), b?.removeEventListener("abort", x);
55
- }
56
- };
57
- }
58
- function xn(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 Bt(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((D, k) => ({ page: D, index: I + k }));
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 D = Math.max(0, P.scrollTop + 32) / t.value;
85
- w.value = Math.min(I.value, c.value.pageAt(D) + 1);
86
- }));
87
- };
88
- }
89
- function $() {
90
- h = !0, p && cancelAnimationFrame(p), p = 0;
91
- }
92
- return Te($), {
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 Pn(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 tn() && Te(n), { zoom: t, zoomMode: o, applyFitZoom: a, setZoom: l };
124
- }
125
- const je = 8;
126
- function qe() {
127
- return new Promise((e) => setTimeout(e, 0));
128
- }
129
- function Le(e) {
130
- return `p${e.pageWidthMm}x${e.pageHeightMm}`.replace(/[.+]/g, "_");
131
- }
132
- function ft(e) {
133
- const t = /* @__PURE__ */ new Map();
134
- return e.pages.forEach((n) => {
135
- t.has(Le(n)) || t.set(Le(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 ${Le(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 pt(e) {
146
- const t = Ot(e, 96, {}, document);
147
- return t.style.page = Le(e), t.outerHTML;
148
- }
149
- function At(e) {
150
- return { head: ft(e), pageChunks: e.pages.map(pt) };
151
- }
152
- async function Gr(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 = ft(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(pt(o.pages[c])), c % je === je - 1 && (t.onProgress?.(c + 1, o.pages.length), await qe());
166
- l.write("</body></html>"), l.close(), await qe(), 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 En(e) {
174
- const { head: t, pageChunks: o } = At(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 $n(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++, k(), x(), I();
205
- }
206
- const D = _(e, P, { flush: "sync" });
207
- function k() {
208
- o?.remove(), o = null;
209
- }
210
- function O() {
211
- n = !0, a++, D(), k(), I(), l.clear(), t.onPrinting?.(!1);
212
- }
213
- function N(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), k();
225
- const y = ft(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(pt(u.pages[V])), V % je === je - 1 && await qe(), T !== o) return;
233
- if (B.write("</body></html>"), B.close(), await qe(), !i(u, d) || T !== o) return;
234
- T.contentWindow?.focus(), T.contentWindow?.print();
235
- } catch {
236
- T === o && k(), 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
- N(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 J() {
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
- N(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 cn(u, {
301
- dpr: Math.min(2, typeof devicePixelRatio == "number" ? devicePixelRatio : 1)
302
- });
303
- if (!i(u, d)) return;
304
- B.forEach((V, ee) => {
305
- N(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 } = En(u);
323
- N(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 J();
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 } = At(d), B = `${y}${T.join("")}</body></html>`;
356
- N(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 Z() {
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: Z,
393
- invalidatePending: P,
394
- releasePrintFrame: k,
395
- dispose: O
396
- };
397
- }
398
- const Lt = "mrp-hit";
399
- function kn(e) {
400
- e.querySelectorAll(`mark.${Lt}`).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 = Lt, 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 Mn = /* @__PURE__ */ new Set(["line", "rect", "ellipse", "chart"]);
434
- function* Fn(e) {
435
- for (const t of e.cells ?? [])
436
- for (const o of t ?? [])
437
- yield o?.text ?? "", yield* o?.children ?? [];
438
- }
439
- function* Rn(e) {
440
- if (hn(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* Tn(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 "", !gn(r) && (r.kind === "text" ? t.push(Rn(r)) : r.grid ? t.push(Fn(r.grid)) : Mn.has(r.kind) || (yield r.fallbackText ?? ""));
460
- }
461
- }
462
- function* In(e) {
463
- for (let t = 0; t < e.pages.length; t++) {
464
- for (const o of Tn(e.pages[t].components)) yield { text: o, pageIndex: t };
465
- yield { text: "", pageIndex: t };
466
- }
467
- }
468
- function Sn(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 On(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 k = c.value;
480
- let O = 0, N = f.length - 1;
481
- for (; O < N; ) {
482
- const X = O + N >>> 1;
483
- f[X].cumulative <= k ? O = X + 1 : N = X;
484
- }
485
- const K = f[O];
486
- return K ? { pageIndex: K.pageIndex, occurrence: k - (f[O - 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(k) {
493
- l.value = k, c.value = 0, m.value = 0, f = [], b.value = !1;
494
- const O = k.trim().toLowerCase(), N = t.value;
495
- if (!O || !N) return;
496
- b.value = !0;
497
- const K = x, X = In(N), Q = [];
498
- let J = 0;
499
- function se() {
500
- if (i = null, K !== x || N !== t.value) return;
501
- const U = performance.now();
502
- let me = 0;
503
- for (; me < 5e3 && performance.now() - U < 4; ) {
504
- const Z = X.next();
505
- if (Z.done) {
506
- f = Q, m.value = J, b.value = !1, f[0] && o(f[0].pageIndex + 1);
507
- return;
508
- }
509
- const u = Sn(Z.value.text, O);
510
- if (u > 0) {
511
- J += u;
512
- const d = Q[Q.length - 1];
513
- d?.pageIndex === Z.value.pageIndex ? d.cumulative = J : Q.push({ pageIndex: Z.value.pageIndex, cumulative: J });
514
- }
515
- me++;
516
- }
517
- i = setTimeout(se, 0);
518
- }
519
- se();
520
- }
521
- function I(k) {
522
- if ($(), l.value = k, c.value = m.value = 0, f = [], !k.trim()) {
523
- w("");
524
- return;
525
- }
526
- b.value = !0, h = setTimeout(() => {
527
- h = null, w(k);
528
- }, Math.max(0, E(e.debounceMs) ?? 200));
529
- }
530
- function P(k) {
531
- const O = m.value;
532
- if (O === 0 || b.value) return;
533
- c.value = (c.value + k + O) % O;
534
- const N = p.value;
535
- N && o(N.pageIndex + 1);
536
- }
537
- function D() {
538
- $(), l.value = "", c.value = m.value = 0, f = [];
539
- }
540
- return _(t, D, { flush: "sync" }), Te(D), {
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: (k) => {
553
- l.value.trim() && r(k, l.value.trim());
554
- },
555
- clear: (k) => {
556
- n(k);
557
- },
558
- reset: D
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 Bn(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(() => Bt(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: D } = b.value;
585
- return c.value.slice(P, D + 1).map((k, O) => ({ index: P + O, height: k }));
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, D = e.value, k = o.value;
601
- let O = 0;
602
- function N() {
603
- if (p = 0, !(i || !r.value || e.value !== D || o.value !== k)) {
604
- for (let K = 0; O < P.length && K < 2; K++, O++) {
605
- const X = P[O].index, Q = k.querySelector(`[data-thumb="${X + 1}"]`);
606
- if (!Q || Q.childElementCount > 0) continue;
607
- const J = n(X);
608
- J && (J.style.width = "100%", J.style.height = "100%", J.style.display = "block", Q.appendChild(J));
609
- }
610
- O < P.length && (p = requestAnimationFrame(N));
611
- }
612
- }
613
- p = requestAnimationFrame(N);
614
- }
615
- function I() {
616
- i = !0, p && cancelAnimationFrame(p), h && cancelAnimationFrame(h), p = h = 0;
617
- }
618
- return Te(I), { schedule: w, destroy: I, onScroll: $, windowRange: b, visibleThumbs: f };
619
- }
620
- function Wn() {
621
- const e = xe(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 An = { class: "mrp-toolbar" }, Ln = { class: "mrp-title" }, zn = ["disabled"], Nn = { class: "mrp-pageinfo" }, Hn = ["disabled"], jn = ["disabled"], qn = {
633
- key: 2,
634
- class: "mrp-search"
635
- }, Un = ["placeholder", "value"], Vn = {
636
- key: 0,
637
- class: "mrp-search-count",
638
- role: "status"
639
- }, Kn = ["disabled"], Jn = ["disabled"], Yn = ["disabled"], Zn = ["disabled"], Gn = ["disabled"], Xn = ["disabled"], Qn = ["disabled"], _n = ["disabled"], er = ["disabled"], tr = /* @__PURE__ */ dt({
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 && nn(() => 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) => (C(), M("div", An, [
668
- S("span", Ln, R(e.messages.title), 1),
669
- e.pageCount > 0 ? (C(), M(Re, { 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, zn),
676
- S("span", Nn, 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 ? (C(), 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, jn)) : j("", !0),
692
- e.search.visible ? (C(), M("div", qn, [
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, Un),
702
- e.search.query ? (C(), M("span", Vn, 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, Kn),
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, Jn)
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 ? (C(), 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 ? (C(), 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 ? (C(), 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, Gn)) : j("", !0),
763
- e.showExport ? (C(), 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, Xn)) : j("", !0),
770
- e.showExport ? (C(), 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, Qn)) : j("", !0),
777
- e.showPrint ? (C(), 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, _n)) : j("", !0),
784
- e.showPdfWindow ? (C(), 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, er)) : j("", !0)
791
- ]));
792
- }
793
- }), mt = (e, t) => {
794
- const o = e.__vccOpts || e;
795
- for (const [r, n] of t)
796
- o[r] = n;
797
- return o;
798
- }, nr = /* @__PURE__ */ mt(tr, [["__scopeId", "data-v-1c2568a7"]]), rr = { class: "mrp-params" }, ar = { class: "mrp-params-title" }, or = { class: "mrp-params-grid" }, lr = { class: "mrp-param-label" }, sr = {
799
- key: 0,
800
- class: "mrp-param-star"
801
- }, ir = ["value", "onChange"], ur = {
802
- value: "",
803
- disabled: "",
804
- hidden: ""
805
- }, cr = ["value"], dr = ["type", "placeholder", "value", "onInput"], fr = { class: "mrp-params-actions" }, pr = /* @__PURE__ */ dt({
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) => (C(), M("div", rr, [
837
- S("span", ar, R(e.messages.paramsTitle), 1),
838
- S("div", or, [
839
- (C(!0), M(Re, null, Ne(a.value, (f) => (C(), M("label", {
840
- key: f.def.field,
841
- class: de(["mrp-param", { "mrp-param-missing": c(f.def.field) }])
842
- }, [
843
- S("span", lr, [
844
- it(R(f.label), 1),
845
- f.def.required ? (C(), M("i", sr, "*")) : j("", !0)
846
- ]),
847
- (f.def.type ?? "text") === "select" ? (C(), 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", ur, R(f.def.placeholder ?? `请选择${f.label}`), 1),
855
- (C(!0), M(Re, null, Ne(f.def.options ?? [], (p) => (C(), M("option", {
856
- key: p.value,
857
- value: p.value
858
- }, R(p.label), 9, cr))), 128))
859
- ], 40, ir)) : (C(), 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, dr))
868
- ], 2))), 128))
869
- ]),
870
- S("div", fr, [
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
- }), mr = /* @__PURE__ */ mt(pr, [["__scopeId", "data-v-aafce92d"]]), vr = {
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
- }, gr = {
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 hr(e = {}) {
934
- return { ...e, defaults: e.defaults ?? {}, presets: e.presets ?? {} };
935
- }
936
- function Xr(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
- }, Qr = { warn: () => {
948
- }, info: () => {
949
- } };
950
- function ze(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 br(e, t) {
961
- const o = t ? e?.presets?.[t] : e?.defaultPreset ? e?.presets?.[e.defaultPreset] : void 0, r = ze(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: { ...gr, ...r.theme },
970
- messages: { ...vr, ...r.messages },
971
- logger: r.logger ?? he.logger,
972
- preview: {
973
- overscanPages: Tt(r.preview?.overscanPages, 1, 10, !0),
974
- searchDebounceMs: Tt(r.preview?.searchDebounceMs, 200, 2e3)
975
- },
976
- xlsx: { ...r.xlsx },
977
- editable: r.editable ?? !1,
978
- excelImport: r.excelImport ?? !1
979
- };
980
- }
981
- function Tt(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 wr(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 _r(e) {
991
- const t = He(ut, null), o = F(() => {
992
- const r = t?.value ?? null, n = "defaults" in e || "presets" in e || "defaultPreset" in e ? hr(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] = ze(
997
- ze(r.presets[l], n.defaults),
998
- n.presets[l]
999
- );
1000
- return {
1001
- defaults: ze(r.defaults, n.defaults),
1002
- presets: a,
1003
- defaultPreset: n.defaultPreset ?? r.defaultPreset
1004
- };
1005
- });
1006
- St(ut, o);
1007
- }
1008
- function yr() {
1009
- return He(ut, F(() => null));
1010
- }
1011
- const It = /* @__PURE__ */ new Map(), we = /* @__PURE__ */ new Map(), xr = 15e3;
1012
- function ct(e, t) {
1013
- return Object.assign(new Error(e), { cause: t });
1014
- }
1015
- function Fe(e, t) {
1016
- return `PDF 字体 ${JSON.stringify(e)}:${t}。请部署支持报表文字的字体文件,并将 pdfFontUrl 配置为可访问的字体 URL;西文报表可设为空串`;
1017
- }
1018
- function Ue(e) {
1019
- if (e?.reason instanceof Error && e.reason.name === "AbortError") return e.reason;
1020
- const t = ct("PDF 字体检查已取消", e?.reason);
1021
- return t.name = "AbortError", t;
1022
- }
1023
- async function Pr(e, t) {
1024
- let o = !1;
1025
- const r = setTimeout(() => {
1026
- o = !0, t.abort();
1027
- }, xr);
1028
- try {
1029
- const n = await fetch(e, { method: "HEAD", signal: t.signal });
1030
- if (t.signal.aborted) throw Ue(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: Fe(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: Fe(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: Fe(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 Ue(t.signal);
1057
- return {
1058
- status: "error",
1059
- fontUrl: e,
1060
- message: Fe(e, o ? "字体检查超时,请检查网络或字体服务" : "字体检查失败,请检查网络、字体服务或跨域访问配置"),
1061
- cause: n
1062
- };
1063
- } finally {
1064
- clearTimeout(r);
1065
- }
1066
- }
1067
- function Er(e, t) {
1068
- if (t?.aborted) return Promise.reject(Ue(t));
1069
- if (!e)
1070
- return Promise.resolve({ status: "disabled", fontUrl: e, message: "已停用自定义 PDF 字体;内置字体用于西文,其他文字会在导出时校验" });
1071
- const o = It.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: Pr(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" && It.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(Ue(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 $r(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 ct(Fe(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 ct(`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) => Er(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 kr(e) {
1133
- return e instanceof pe ? { code: e.code, cause: e.cause } : { code: "render", cause: e };
1134
- }
1135
- function ye(e) {
1136
- return JSON.parse(JSON.stringify(e));
1137
- }
1138
- function Cr(e) {
1139
- const t = e.closest(".mrp-page-holder"), o = e.closest("[data-mr-component-index]");
1140
- if (!t || !o) return null;
1141
- const r = {
1142
- pageIndex: Number(t.dataset.page) - 1,
1143
- componentIndex: Number(o.dataset.mrComponentIndex),
1144
- rowIndex: Number(e.dataset.mrRowIndex),
1145
- columnIndex: Number(e.dataset.mrColumnIndex)
1146
- };
1147
- return Object.values(r).every((n) => Number.isInteger(n) && n >= 0) ? r : null;
1148
- }
1149
- function Mr(e, t, o) {
1150
- const r = e.ownerDocument.createElement("textarea");
1151
- 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;
1152
- }
1153
- function Fr(e) {
1154
- const t = xe(null), o = A(!1), r = xe([]);
1155
- let n = null;
1156
- function a() {
1157
- const i = t.value;
1158
- t.value = null, o.value = !1, n = null, i?.controller.abort(), i?.input.remove();
1159
- }
1160
- function l() {
1161
- a(), r.value = [];
1162
- }
1163
- function c(i) {
1164
- return t.value === i && !i.controller.signal.aborted && e.plan.value === i.plan;
1165
- }
1166
- function m(i) {
1167
- const x = e.options.value, $ = Ft(i.plan, i.address);
1168
- if (!(typeof x == "object" ? x === i.options : x === !0) || !$?.editable || i.options.canEdit?.($) === !1)
1169
- throw new Dt("readonly");
1170
- }
1171
- async function b(i) {
1172
- try {
1173
- m(i);
1174
- const x = dn(i.plan, i.address, i.input.value);
1175
- if (Object.is(x.value, x.previousValue))
1176
- return a(), !0;
1177
- const $ = { signal: i.controller.signal }, w = await i.options.validate?.(ye(x), $);
1178
- if (!c(i)) return !1;
1179
- if (w) throw new Error(w);
1180
- if (m(i), await i.options.save?.(ye(x), $), !c(i)) return !1;
1181
- m(i);
1182
- const I = fn(i.plan, x);
1183
- return a(), r.value = [...r.value, x], e.plan.value = I, e.onChange(ye(x)), !0;
1184
- } catch (x) {
1185
- 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;
1186
- } finally {
1187
- t.value === i && (o.value = !1);
1188
- }
1189
- }
1190
- async function f() {
1191
- if (n) return n;
1192
- const i = t.value;
1193
- if (!i) return !0;
1194
- if (!c(i))
1195
- return a(), !1;
1196
- o.value = !0, i.input.disabled = !0;
1197
- const x = b(i);
1198
- n = x;
1199
- const $ = await x;
1200
- return n === x && (n = null), $;
1201
- }
1202
- function p(i) {
1203
- i.stopPropagation(), !i.isComposing && (i.key === "Escape" && (i.preventDefault(), a()), i.key === "Enter" && !i.shiftKey && (i.preventDefault(), f()));
1204
- }
1205
- async function h(i) {
1206
- if (!e.options.value || e.blocked()) return;
1207
- const x = i.target;
1208
- if (!(x instanceof Element) || x.closest(".mrp-cell-editor")) return;
1209
- const $ = x.closest("td[data-mr-row-index]");
1210
- if (!$ || !await f() || !$.isConnected) return;
1211
- const w = e.plan.value, I = Cr($);
1212
- if (!w || !I || !e.options.value || e.blocked()) return;
1213
- const P = typeof e.options.value == "object" ? e.options.value : {};
1214
- try {
1215
- const D = Ft(w, I);
1216
- if (!D?.editable || P.canEdit?.(D) === !1) return;
1217
- const k = Mr($, e.label(), D.value);
1218
- t.value = { plan: w, address: I, input: k, controller: new AbortController(), options: P }, k.addEventListener("keydown", p), k.addEventListener("blur", () => {
1219
- o.value || f();
1220
- }), k.focus(), k.select();
1221
- } catch (D) {
1222
- e.onError(D instanceof Error ? D.message : "无法编辑单元格", D);
1223
- }
1224
- }
1225
- return _(e.options, (i, x) => {
1226
- (!i || i !== x) && a();
1227
- }, { flush: "sync" }), _(e.plan, () => {
1228
- t.value && e.plan.value !== t.value.plan && a();
1229
- }, { flush: "sync" }), Te(l), {
1230
- active: t,
1231
- saving: o,
1232
- changes: r,
1233
- cancel: a,
1234
- reset: l,
1235
- commit: f,
1236
- onDoubleClick: h,
1237
- getChanges: () => ye(r.value)
1238
- };
1239
- }
1240
- const Rr = {
1241
- key: 2,
1242
- class: "mrp-edit-hint",
1243
- role: "status"
1244
- }, Tr = {
1245
- key: 4,
1246
- class: "mrp-export-notice mrp-export-warning",
1247
- role: "status"
1248
- }, Ir = { class: "mrp-main" }, Sr = {
1249
- key: 0,
1250
- class: "mrp-state"
1251
- }, Or = {
1252
- key: 1,
1253
- class: "mrp-state mrp-error"
1254
- }, Dr = {
1255
- key: 2,
1256
- class: "mrp-state"
1257
- }, Br = ["data-page"], Wr = ["onClick"], Ar = ["data-thumb"], Lr = { class: "mrp-thumb-no" }, zr = { class: "mrp-overlay" }, Nr = {
1258
- key: 5,
1259
- class: "mrp-debug",
1260
- "aria-hidden": "true"
1261
- }, Ae = 96 / 25.4, lt = "mach-report:ui", st = "mach-report:ui:wide", Hr = /* @__PURE__ */ dt({
1262
- __name: "ReportPreview",
1263
- props: {
1264
- reportId: {
1265
- type: [String, Array],
1266
- default: null
1267
- },
1268
- params: {
1269
- type: Object,
1270
- default: () => ({})
1271
- },
1272
- height: { type: String, default: "100vh" },
1273
- autoLoad: { type: Boolean, default: !0 },
1274
- /** 以下显隐/间距不传时走配置中心(preset > defaults > 内置缺省) */
1275
- showExport: { type: Boolean, default: void 0 },
1276
- showPrint: { type: Boolean, default: void 0 },
1277
- showPdfWindow: { type: Boolean, default: void 0 },
1278
- /** 页间距(px);不传走配置中心 */
1279
- gapPx: { type: Number, default: void 0 },
1280
- /** 工具栏/状态文案覆写(不传走配置中心 messages) */
1281
- messages: { type: Object, default: void 0 },
1282
- /** 启用的 preset 名(不传用配置中心 defaultPreset) */
1283
- preset: { type: String, default: void 0 },
1284
- /** 调试面板(也可用 URL ?mrp-debug=1 开启) */
1285
- debug: { type: Boolean, default: !1 },
1286
- /** 参数定义(优先级:prop > 模板 params;有定义且未关闭时显示查询面板) */
1287
- paramDefs: {
1288
- type: Array,
1289
- default: void 0
1290
- },
1291
- /** 参数面板显隐(不传走配置中心,缺省 true;有参数定义才渲染) */
1292
- showParams: { type: Boolean, default: void 0 },
1293
- editable: { type: [Boolean, Object], default: void 0 },
1294
- excelImport: { type: [Boolean, Object], default: void 0 },
1295
- fetcher: {
1296
- type: Function,
1297
- default: null
1298
- }
1299
- },
1300
- emits: ["loaded", "error", "warning", "cell-edit", "template-import"],
1301
- setup(e, { expose: t, emit: o }) {
1302
- rn((s) => ({
1303
- a2d6c888: N.value + "px"
1304
- }));
1305
- const r = e, n = o, a = xe(null), l = A(!1), c = A(""), m = xe(null), b = A(null), f = A(!1), p = xe(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), D = A(null), k = Wn(), O = F(() => !!a.value?.pages.length && a.value.pages.every((s) => s.layout === "wide")), N = F(() => Math.max(0, ee.value));
1306
- let K = lt;
1307
- const X = He(bn, null), Q = He(wn, null), J = F(() => Wt(r.reportId)), se = F(() => r.fetcher ?? X), U = F(() => a.value?.pages.length ?? 0), me = F(() => Object.freeze({
1308
- loading: l.value,
1309
- hasPlan: U.value > 0,
1310
- pageCount: U.value,
1311
- currentPage: i.value,
1312
- exporting: b.value,
1313
- printing: f.value,
1314
- canExport: !l.value && !P.value && !q.saving.value && U.value > 0 && b.value === null,
1315
- canPrint: !l.value && !P.value && !q.saving.value && U.value > 0 && !f.value,
1316
- error: m.value,
1317
- pdfFont: p.value,
1318
- editing: q.active.value !== null,
1319
- saving: q.saving.value,
1320
- importing: P.value,
1321
- dirty: q.changes.value.length > 0
1322
- }));
1323
- function Z(s, v, g) {
1324
- m.value = Object.freeze({ message: s, code: v, cause: g }), n("error", s, { code: v, cause: g });
1325
- }
1326
- const u = yr(), d = F(() => br(u.value, r.preset)), y = F(() => ({
1327
- ...d.value.messages,
1328
- ...r.messages
1329
- })), 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 ?? (O.value ? 0 : d.value.gapPx)), oe = F(() => r.showParams ?? d.value.showParams), vt = F(() => r.editable ?? d.value.editable), Ie = F(() => r.excelImport ?? d.value.excelImport);
1330
- function zt(s) {
1331
- return s instanceof Dt ? {
1332
- number: y.value.editInvalidNumber,
1333
- boolean: y.value.editInvalidBoolean,
1334
- conflict: y.value.editConflict
1335
- }[s.code] ?? s.message : s instanceof Error ? s.message : "单元格保存失败";
1336
- }
1337
- const q = Fr({
1338
- plan: a,
1339
- options: vt,
1340
- blocked: () => l.value || P.value || b.value !== null || f.value,
1341
- label: () => y.value.editCell ?? "编辑单元格",
1342
- errorMessage: zt,
1343
- onChange: (s) => {
1344
- m.value = null, h.value = null, n("cell-edit", s);
1345
- },
1346
- onError: (s, v) => {
1347
- h.value = { kind: "error", message: s }, Z(s, "edit", v);
1348
- }
1349
- });
1350
- let gt = null, Ve = null;
1351
- function ht() {
1352
- if (Q) return Q;
1353
- const s = d.value.pdfFontUrl;
1354
- return (!Ve || gt !== s) && (gt = s, Ve = $r({ fontUrl: s })), Ve;
1355
- }
1356
- let Se = 0, Pe = null, Oe = null, ie = !1;
1357
- function Ke() {
1358
- Se++, Pe?.abort(), Pe = null;
1359
- }
1360
- async function De() {
1361
- if (ie) throw new pe("config", "报表预览已卸载");
1362
- Ke();
1363
- const s = Se, v = new AbortController();
1364
- Pe = v;
1365
- const g = d.value.pdfFontUrl;
1366
- p.value = Object.freeze({ status: "checking", fontUrl: g });
1367
- try {
1368
- const z = ht(), L = z.checkFont ? await z.checkFont(v.signal) : { status: "unverified", fontUrl: "", message: "自定义 PDF 导出器未提供字体预检查;字体由宿主确认" };
1369
- return !ie && s === Se && !v.signal.aborted && (p.value = Object.freeze({ ...L })), L;
1370
- } catch (z) {
1371
- if (v.signal.aborted) throw z;
1372
- const L = {
1373
- status: "error",
1374
- fontUrl: g,
1375
- message: z instanceof Error ? z.message : "PDF 字体检查失败",
1376
- cause: z
1377
- };
1378
- return !ie && s === Se && (p.value = Object.freeze(L)), L;
1379
- } finally {
1380
- Pe === v && (Pe = null);
1381
- }
1382
- }
1383
- function Nt() {
1384
- De().catch(() => {
1385
- });
1386
- }
1387
- _(
1388
- [a, () => d.value.pdfFontUrl, T, V],
1389
- () => {
1390
- const s = p.value.fontUrl === d.value.pdfFontUrl;
1391
- s && p.value.status === "available" || (Ke(), (!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(() => {
1392
- }));
1393
- },
1394
- { immediate: !0 }
1395
- );
1396
- const fe = F(
1397
- () => r.paramDefs ?? se.value?.getParamDefs?.(J.value) ?? []
1398
- ), ve = A({}), Je = A(!1);
1399
- function Ee(s) {
1400
- const v = {};
1401
- for (const g of s)
1402
- v[g.field] = r.params[g.field] ?? g.defaultValue ?? "";
1403
- ve.value = v, Je.value = !1;
1404
- }
1405
- Ee(fe.value), _(fe, (s) => Ee(s)), _(J, () => Ee(fe.value)), _(() => JSON.stringify(r.params), () => Ee(fe.value));
1406
- const Ht = F(() => {
1407
- const s = { ...r.params };
1408
- for (const [v, g] of Object.entries(ve.value))
1409
- g === "" ? delete s[v] : s[v] = g;
1410
- return s;
1411
- });
1412
- function jt() {
1413
- return fe.value.filter(
1414
- (s) => s.required === !0 && !(ve.value[s.field] ?? "").trim()
1415
- );
1416
- }
1417
- function qt() {
1418
- Je.value = !0;
1419
- const s = jt();
1420
- if (s.length > 0) {
1421
- const v = s[0].label ?? s[0].field, g = y.value.paramRequired.replace("{label}", v);
1422
- c.value = g, Z(g, "param");
1423
- return;
1424
- }
1425
- ge();
1426
- }
1427
- function Ut() {
1428
- Ee(fe.value);
1429
- }
1430
- const Vt = F(() => ({
1431
- height: r.height,
1432
- ...wr(d.value.theme)
1433
- })), { zoom: te, zoomMode: $e, applyFitZoom: bt, setZoom: ke } = Pn(() => ({
1434
- viewport: $.value,
1435
- pageWidthPx: Ye.contentSize.value.w || 210 * Ae
1436
- })), Ye = xn(a, te, {
1437
- pxPerMm: Ae,
1438
- gapPx: ee,
1439
- overscan: F(() => d.value.preview.overscanPages)
1440
- }), { contentSize: Ze, windowRange: Ce, visiblePages: wt, makeScrollHandler: Kt, refreshViewport: Ge } = Ye, Jt = Kt(i, U);
1441
- function Xe(s) {
1442
- ke(s * 100);
1443
- }
1444
- function Be() {
1445
- P.value = !1, q.reset(), yt(), a.value = null, i.value = 1, H.reset();
1446
- }
1447
- let Y = 0, re = null;
1448
- async function ge() {
1449
- if (ie) return;
1450
- const s = ++Y;
1451
- P.value = !1, re?.abort(), re = null;
1452
- const v = se.value;
1453
- if (l.value = !1, m.value = null, J.value.length === 0) {
1454
- c.value = "缺少报表 ID", Be(), Z(c.value, "param");
1455
- return;
1456
- }
1457
- if (!v) {
1458
- c.value = "未提供渲染数据源 fetcher", Be(), Z(c.value, "config");
1459
- return;
1460
- }
1461
- l.value = !0, c.value = "", h.value = null, Be();
1462
- const g = k.start(), z = new AbortController();
1463
- re = z;
1464
- const L = /* @__PURE__ */ new Set();
1465
- function ae(W) {
1466
- s !== Y || z.signal.aborted || L.has(W) || (L.add(W), d.value.logger.warn("[mach-report] 报表告警:", W), n("warning", W));
1467
- }
1468
- try {
1469
- const W = await v({
1470
- reportIds: J.value,
1471
- params: { ...Ht.value },
1472
- signal: z.signal,
1473
- onWarning: ae
1474
- });
1475
- if (s !== Y) return;
1476
- const G = Rt(W);
1477
- if (!G.ok) {
1478
- const We = G.errors.slice(0, 3).map((kt) => `${kt.path}: ${kt.message}`).join("; ");
1479
- throw new pe(
1480
- "validate",
1481
- `渲染计划校验失败(${G.errors.length} 处): ${We}`
1482
- );
1483
- }
1484
- if (G.warnings.forEach((We) => ae(`${We.path}: ${We.message}`)), s !== Y || z.signal.aborted) return;
1485
- a.value = W, i.value = 1, k.end(g), $.value && ($.value.scrollTop = 0, $.value.scrollLeft = 0);
1486
- const ne = O.value ? st : lt;
1487
- ne !== K && (K = ne, at()), $e.value === "fit" && bt(), n("loaded", W.pages.length);
1488
- } catch (W) {
1489
- if (s !== Y) return;
1490
- const G = W instanceof pe ? W : W instanceof mn ? new pe(W.code, W.message, W.cause) : new pe(
1491
- "fetch",
1492
- W instanceof Error ? W.message : "预览加载失败",
1493
- W
1494
- );
1495
- c.value = G.message;
1496
- const ne = kr(G);
1497
- Z(G.message, ne.code, ne.cause);
1498
- } finally {
1499
- s === Y && (l.value = !1), re === z && (re = null);
1500
- }
1501
- }
1502
- function ue(s) {
1503
- if (ie || U.value <= 0) return;
1504
- const v = Math.max(1, Math.min(U.value, s));
1505
- i.value = v;
1506
- const g = $.value;
1507
- g && (g.scrollTop = Ye.pageOffsetPx(v - 1) * te.value, Ge(g));
1508
- }
1509
- const Me = $n(a, {
1510
- getPdfExporter: ht,
1511
- getXlsxOptions: () => d.value.xlsx,
1512
- onError: (s, v) => {
1513
- h.value = { kind: "error", message: s }, Z(s, v ?? "print");
1514
- },
1515
- onWarning: (s) => {
1516
- h.value = { kind: "warning", message: s }, n("warning", s);
1517
- },
1518
- onBusy: (s) => {
1519
- b.value = s, s ? h.value = {
1520
- kind: "progress",
1521
- message: y.value.exporting.replace("{format}", s)
1522
- } : h.value?.kind === "progress" && (h.value = null);
1523
- },
1524
- onPrinting: (s) => {
1525
- f.value = s;
1526
- }
1527
- }), { releasePrintFrame: yt, dispose: Yt } = Me;
1528
- async function Qe() {
1529
- l.value || P.value || q.active.value && !await q.commit() || (m.value = null, await Me.print());
1530
- }
1531
- async function _e(s) {
1532
- l.value || P.value || q.active.value && !await q.commit() || (m.value = null, await Me.exportAs(s));
1533
- }
1534
- function et() {
1535
- if (l.value || P.value || q.active.value) {
1536
- h.value = { kind: "warning", message: y.value.editingHint ?? "请先确认单元格修改" };
1537
- return;
1538
- }
1539
- m.value = null, Me.openPdfWindow();
1540
- }
1541
- async function xt(s, v = {}) {
1542
- ie || (ve.value = { ...ve.value, ...s }, v.reload !== !1 && await ge());
1543
- }
1544
- const Zt = {
1545
- reload: ge,
1546
- print: Qe,
1547
- exportAs: _e,
1548
- openPdfWindow: et,
1549
- gotoPage: ue,
1550
- setParams: xt,
1551
- checkPdfFont: De,
1552
- importExcel: tt,
1553
- getPlan: Pt,
1554
- getChanges: q.getChanges,
1555
- get state() {
1556
- return me.value;
1557
- }
1558
- };
1559
- St(yn, Zt);
1560
- function Pt() {
1561
- return a.value ? ye(a.value) : null;
1562
- }
1563
- async function tt(s, v) {
1564
- if (ie) throw new pe("config", "报表预览已卸载");
1565
- const g = ++Y;
1566
- re?.abort(), re = null, l.value = !1, q.cancel(), Me.invalidatePending(), P.value = !0, m.value = null, h.value = { kind: "progress", message: y.value.importing ?? "正在导入 Excel…" };
1567
- try {
1568
- const { importExcelTemplate: z } = await import("@agile-team/mach-report/xlsx");
1569
- if (g !== Y) return null;
1570
- const L = typeof Ie.value == "object" ? Ie.value : {}, ae = await z(s, { ...L, ...v, limits: { ...L.limits, ...v?.limits } });
1571
- if (g !== Y) return null;
1572
- const W = pn(ye(ae.template), {}).plan, G = Rt(W);
1573
- if (!G.ok) throw new Error(G.errors.map((ne) => ne.message).slice(0, 3).join("; "));
1574
- for (const ne of ae.warnings) {
1575
- if (g !== Y) return null;
1576
- n("warning", ne);
1577
- }
1578
- return g !== Y ? null : (q.reset(), yt(), H.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 = O.value ? st : lt, at(), n("template-import", ae), g === Y && n("loaded", W.pages.length), ae);
1579
- } catch (z) {
1580
- if (g !== Y) return null;
1581
- const L = new pe("import", z instanceof Error ? z.message : "Excel 模板导入失败", z);
1582
- throw h.value = { kind: "error", message: L.message }, Z(L.message, "import", z), L;
1583
- } finally {
1584
- g === Y && (P.value = !1);
1585
- }
1586
- }
1587
- function Gt(s) {
1588
- const v = s.target, g = v.files?.[0];
1589
- v.value = "", g && tt(g).catch(() => {
1590
- });
1591
- }
1592
- const H = On({
1593
- plan: a,
1594
- gotoPage: ue,
1595
- debounceMs: F(() => d.value.preview.searchDebounceMs),
1596
- highlight: Cn,
1597
- clearHighlights: kn
1598
- });
1599
- function Xt(s) {
1600
- s.ctrlKey && (s.preventDefault(), Xe(te.value * (s.deltaY < 0 ? 1.1 : 1 / 1.1)));
1601
- }
1602
- function Qt(s) {
1603
- if (!(s.target instanceof Element && s.target.closest("input,textarea,select,[contenteditable='true']"))) {
1604
- if ((s.ctrlKey || s.metaKey) && s.key.toLowerCase() === "f") {
1605
- s.preventDefault(), H.visible.value || H.toggle();
1606
- return;
1607
- }
1608
- switch (s.key) {
1609
- case "PageDown":
1610
- s.preventDefault(), ue(i.value + 1);
1611
- break;
1612
- case "PageUp":
1613
- s.preventDefault(), ue(i.value - 1);
1614
- break;
1615
- case "Home":
1616
- s.preventDefault(), ue(1);
1617
- break;
1618
- case "End":
1619
- s.preventDefault(), ue(U.value);
1620
- break;
1621
- case "+":
1622
- case "=":
1623
- s.preventDefault(), Xe(te.value * 1.1);
1624
- break;
1625
- case "-":
1626
- s.preventDefault(), Xe(te.value / 1.1);
1627
- break;
1628
- }
1629
- }
1630
- }
1631
- function _t() {
1632
- try {
1633
- localStorage.setItem(
1634
- K,
1635
- JSON.stringify({ zoomMode: $e.value === "fit" ? "fit" : Math.round(te.value * 100) })
1636
- );
1637
- } catch {
1638
- }
1639
- }
1640
- _([$e, te], _t);
1641
- let nt = "";
1642
- const Et = /* @__PURE__ */ new WeakMap();
1643
- function $t(s = !1) {
1644
- const v = H.activeMatch.value;
1645
- if (!O.value || !v) return;
1646
- const g = `${H.query.value}:${H.matchIndex.value}:${v.pageIndex}`;
1647
- if (!s && g === nt) return;
1648
- const L = x.value?.querySelector(`[data-page="${v.pageIndex + 1}"]`)?.querySelectorAll("mark.mrp-hit")[v.occurrence];
1649
- L && (L.scrollIntoView?.({ block: "nearest", inline: "nearest" }), nt = g);
1650
- }
1651
- Mt(() => {
1652
- const s = a.value;
1653
- if (!s) return;
1654
- const v = H.activeMatch.value;
1655
- H.matchIndex.value, v || (nt = ""), wt.value;
1656
- const g = x.value;
1657
- if (!g) return;
1658
- g.querySelectorAll(".mrp-page-holder").forEach((L) => {
1659
- const ae = Number(L.dataset.page ?? 0) - 1, W = s.pages[ae];
1660
- if (!W || L.childElementCount > 0 && Et.get(L) === W) {
1661
- if (L.firstElementChild) {
1662
- const ne = L.firstElementChild;
1663
- H.clear(ne), H.apply(ne);
1664
- }
1665
- return;
1666
- }
1667
- L.style.width = `${W.pageWidthMm * Ae}px`;
1668
- const G = Ot(W, 96, {}, document);
1669
- H.apply(G), L.replaceChildren(G), Et.set(L, W);
1670
- }), $t();
1671
- }, { flush: "post" }), _(() => H.query.value, (s) => {
1672
- s || x.value?.querySelectorAll(".mrp-page-holder").forEach((v) => {
1673
- H.clear(v);
1674
- });
1675
- });
1676
- const le = Bn(a, {
1677
- thumbsRoot: w,
1678
- visible: I,
1679
- renderThumbCanvas: (s) => {
1680
- try {
1681
- const v = a.value.pages[s], g = Math.min(0.2, 116 / Math.max(1, v.pageWidthMm * Ae)), { canvases: z } = vn(a.value, { start: s, end: s, dpr: g });
1682
- return z[0] ?? null;
1683
- } catch {
1684
- return null;
1685
- }
1686
- }
1687
- });
1688
- Mt(() => {
1689
- le.schedule();
1690
- }, { flush: "post" });
1691
- const en = F(() => r.debug), { debugStats: be } = Dn(en, {
1692
- plan: a,
1693
- pageCount: U,
1694
- windowRange: Ce,
1695
- zoom: te,
1696
- loadMs: k.loadMs
1697
- });
1698
- function rt() {
1699
- Ge($.value), le.schedule(), $e.value === "fit" && bt(), $t(!0);
1700
- }
1701
- function at() {
1702
- ke(K === st ? 100 : "fit");
1703
- try {
1704
- const s = JSON.parse(localStorage.getItem(K) ?? "{}");
1705
- s.zoomMode === "fit" ? ke("fit") : typeof s.zoomMode == "number" && ke(s.zoomMode);
1706
- } catch {
1707
- }
1708
- }
1709
- return an(() => {
1710
- window.addEventListener("resize", rt), typeof ResizeObserver < "u" && $.value && (Oe = new ResizeObserver(rt), Oe.observe($.value)), Ge($.value), at(), r.autoLoad && ge();
1711
- }), on(() => {
1712
- ie = !0, q.reset(), P.value = !1, Ke(), Y++, re?.abort(), re = null, window.removeEventListener("resize", rt), Oe?.disconnect(), Oe = null, le.destroy(), H.reset(), Yt();
1713
- }), _(
1714
- () => [JSON.stringify(J.value), JSON.stringify(r.params), se.value],
1715
- () => {
1716
- if (r.autoLoad) {
1717
- ge();
1718
- return;
1719
- }
1720
- Y++, re?.abort(), re = null, l.value = !1, c.value = "", m.value = null, h.value = null, Be();
1721
- }
1722
- ), t({ reload: ge, print: Qe, exportAs: _e, openPdfWindow: et, gotoPage: ue, setParams: xt, checkPdfFont: De, importExcel: tt, getPlan: Pt, getChanges: q.getChanges, state: me }), (s, v) => (C(), M("div", {
1723
- class: de(["mach-report-preview", { "mrp-wide-report": O.value }]),
1724
- style: ce(Vt.value)
1725
- }, [
1726
- oe.value && fe.value.length > 0 ? (C(), ln(mr, {
1727
- key: 0,
1728
- defs: fe.value,
1729
- modelValue: ve.value,
1730
- "onUpdate:modelValue": v[0] || (v[0] = (g) => ve.value = g),
1731
- messages: y.value,
1732
- attempted: Je.value,
1733
- onQuery: qt,
1734
- onReset: Ut
1735
- }, null, 8, ["defs", "modelValue", "messages", "attempted"])) : j("", !0),
1736
- sn(nr, {
1737
- "page-count": U.value,
1738
- "current-page": i.value,
1739
- "zoom-mode": E($e),
1740
- zoom: E(te),
1741
- "show-export": T.value,
1742
- "show-print": B.value,
1743
- "show-pdf-window": V.value,
1744
- messages: y.value,
1745
- search: { visible: E(H).visible.value, query: E(H).query.value, matchIndex: E(H).matchIndex.value, matchCount: E(H).matchCount.value, searching: E(H).searching.value },
1746
- "thumbs-visible": I.value,
1747
- "show-import": !!Ie.value,
1748
- busy: l.value || P.value || E(q).saving.value,
1749
- onGoto: ue,
1750
- onZoom: E(ke),
1751
- onExport: v[1] || (v[1] = (g) => _e(g)),
1752
- onPrint: Qe,
1753
- onPdfWindow: et,
1754
- onSearchInput: E(H).onInput,
1755
- onSearchNav: E(H).onNav,
1756
- onSearchToggle: E(H).toggle,
1757
- onThumbsToggle: v[2] || (v[2] = (g) => I.value = !I.value),
1758
- onImportExcel: v[3] || (v[3] = (g) => D.value?.click())
1759
- }, 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"]),
1760
- Ie.value ? (C(), M("input", {
1761
- key: 1,
1762
- ref_key: "importInputRef",
1763
- ref: D,
1764
- class: "mrp-import-input",
1765
- type: "file",
1766
- accept: ".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
1767
- hidden: "",
1768
- onChange: Gt
1769
- }, null, 544)) : j("", !0),
1770
- vt.value && U.value > 0 ? (C(), M("div", Rr, R(E(q).saving.value ? y.value.saving : y.value.editingHint), 1)) : j("", !0),
1771
- h.value ? (C(), M("div", {
1772
- key: 3,
1773
- class: de(["mrp-export-notice", `mrp-export-${h.value.kind}`]),
1774
- role: "alert"
1775
- }, R(h.value.message), 3)) : j("", !0),
1776
- p.value.status === "error" && (T.value || V.value) ? (C(), M("div", Tr, [
1777
- it(R(y.value.pdfFontUnavailable) + " ", 1),
1778
- S("button", {
1779
- type: "button",
1780
- onClick: Nt
1781
- }, R(y.value.retry), 1)
1782
- ])) : j("", !0),
1783
- S("div", Ir, [
1784
- S("div", {
1785
- ref_key: "viewportRef",
1786
- ref: $,
1787
- class: "mrp-body",
1788
- tabindex: "0",
1789
- onWheel: Xt,
1790
- onKeydown: Qt,
1791
- onDblclick: v[4] || (v[4] = //@ts-ignore
1792
- (...g) => E(q).onDoubleClick && E(q).onDoubleClick(...g)),
1793
- onScrollPassive: v[5] || (v[5] = (g) => E(Jt)(g.target))
1794
- }, [
1795
- l.value ? (C(), M("div", Sr, R(y.value.loading), 1)) : c.value ? (C(), M("div", Or, [
1796
- it(R(c.value) + " ", 1),
1797
- S("button", {
1798
- class: "mrp-retry",
1799
- type: "button",
1800
- onClick: ge
1801
- }, R(y.value.retry), 1)
1802
- ])) : !a.value || U.value === 0 ? (C(), M("div", Dr, R(y.value.empty), 1)) : (C(), M("div", {
1803
- key: 3,
1804
- class: "mrp-scale",
1805
- style: ce({ width: `${E(Ze).w * E(te)}px`, height: `${E(Ze).h * E(te)}px` })
1806
- }, [
1807
- S("div", {
1808
- ref_key: "containerRef",
1809
- ref: x,
1810
- class: "mrp-scale-inner",
1811
- style: ce({ transform: `scale(${E(te)})`, transformOrigin: "top left", width: `${E(Ze).w}px` })
1812
- }, [
1813
- E(Ce).padTopPx > 0 ? (C(), M("div", {
1814
- key: 0,
1815
- class: "mrp-spacer-top",
1816
- style: ce({ height: `${E(Ce).padTopPx}px` }),
1817
- "aria-hidden": "true"
1818
- }, null, 4)) : j("", !0),
1819
- (C(!0), M(Re, null, Ne(E(wt), (g) => (C(), M("div", {
1820
- key: g.index,
1821
- class: "mrp-page-holder",
1822
- "data-page": g.index + 1
1823
- }, null, 8, Br))), 128)),
1824
- E(Ce).padBottomPx > 0 ? (C(), M("div", {
1825
- key: 1,
1826
- class: "mrp-spacer-bottom",
1827
- style: ce({ height: `${E(Ce).padBottomPx}px` }),
1828
- "aria-hidden": "true"
1829
- }, null, 4)) : j("", !0)
1830
- ], 4)
1831
- ], 4))
1832
- ], 544),
1833
- I.value && U.value > 0 ? (C(), M("aside", {
1834
- key: 0,
1835
- ref_key: "thumbsRef",
1836
- ref: w,
1837
- class: "mrp-thumbs",
1838
- onScrollPassive: v[6] || (v[6] = //@ts-ignore
1839
- (...g) => E(le).onScroll && E(le).onScroll(...g))
1840
- }, [
1841
- E(le).windowRange.value.padTopPx > 0 ? (C(), M("div", {
1842
- key: 0,
1843
- class: "mrp-thumb-spacer",
1844
- style: ce({ height: `${E(le).windowRange.value.padTopPx}px` }),
1845
- "aria-hidden": "true"
1846
- }, null, 4)) : j("", !0),
1847
- (C(!0), M(Re, null, Ne(E(le).visibleThumbs.value, (g) => (C(), M("div", {
1848
- key: g.index,
1849
- class: de(["mrp-thumb", { "mrp-thumb-active": g.index + 1 === i.value }]),
1850
- style: ce({ height: `${g.height + 20}px` }),
1851
- onClick: (z) => ue(g.index + 1)
1852
- }, [
1853
- S("div", {
1854
- class: "mrp-thumb-box",
1855
- "data-thumb": g.index + 1,
1856
- style: ce({ height: `${g.height}px` })
1857
- }, null, 12, Ar),
1858
- S("span", Lr, R(g.index + 1), 1)
1859
- ], 14, Wr))), 128)),
1860
- E(le).windowRange.value.padBottomPx > 0 ? (C(), M("div", {
1861
- key: 1,
1862
- class: "mrp-thumb-spacer",
1863
- style: ce({ height: `${E(le).windowRange.value.padBottomPx}px` }),
1864
- "aria-hidden": "true"
1865
- }, null, 4)) : j("", !0)
1866
- ], 544)) : j("", !0)
1867
- ]),
1868
- S("div", zr, [
1869
- un(s.$slots, "default", {}, void 0, !0)
1870
- ]),
1871
- E(be) ? (C(), M("div", Nr, [
1872
- v[7] || (v[7] = S("div", null, "mach-report debug", -1)),
1873
- S("div", null, "pages: " + R(E(be).pages) + " | window: [" + R(E(be).window) + "]", 1),
1874
- S("div", null, "zoom: " + R(E(be).zoom) + " | load: " + R(E(be).loadMs), 1),
1875
- S("div", null, "plan: " + R(E(be).planKB) + "KB", 1)
1876
- ])) : j("", !0)
1877
- ], 6));
1878
- }
1879
- }), jr = /* @__PURE__ */ mt(Hr, [["__scopeId", "data-v-fa6fd3bb"]]), ea = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1880
- __proto__: null,
1881
- default: jr
1882
- }, Symbol.toStringTag, { value: "Module" }));
1883
- export {
1884
- vr as D,
1885
- pe as M,
1886
- ot as P,
1887
- mr as R,
1888
- Qr as S,
1889
- gr as a,
1890
- jr as b,
1891
- nr as c,
1892
- At as d,
1893
- En as e,
1894
- $r as f,
1895
- Zr as g,
1896
- hr as h,
1897
- Xr as i,
1898
- Yr as j,
1899
- _r as k,
1900
- kr as l,
1901
- xn as m,
1902
- Wt as n,
1903
- $n as o,
1904
- Gr as p,
1905
- Pn as q,
1906
- br as r,
1907
- ea as s,
1908
- wr as t,
1909
- yr as u
1910
- };