@agile-team/mach-report 0.8.0 → 0.9.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.
@@ -0,0 +1,923 @@
1
+ import { ref as T, computed as x, shallowRef as Ce, defineComponent as ke, watch as X, nextTick as Ae, openBlock as M, createElementBlock as C, createElementVNode as y, toDisplayString as P, Fragment as ge, createCommentVNode as L, normalizeClass as V, inject as ae, provide as $e, useCssVars as Ue, watchEffect as Pe, onMounted as je, onUnmounted as qe, normalizeStyle as q, createVNode as Ke, unref as m, createTextVNode as Ve, renderList as xe, renderSlot as Ge } from "vue";
2
+ import { computePageWindow as Ye, renderPage as Re, validateRenderPlan as Ze, renderPlanToCanvas as Je } from "@agile-team/mach-report";
3
+ import { a as he, b as Xe, c as Qe, n as _e, M as et, e as tt } from "./plugin-vi2GjP43.js";
4
+ function nt(e, o, a = {}) {
5
+ const n = a.pxPerMm ?? 3.7795275590551185, r = a.gapPx ?? 18, t = T(0), s = T(800), l = x(
6
+ () => (e.value?.pages ?? []).map((u) => u.pageHeightMm * n)
7
+ ), d = x(() => {
8
+ const u = e.value?.pages ?? [];
9
+ let f = 0, p = 0;
10
+ for (const b of u)
11
+ f += b.pageHeightMm * n + r, p = Math.max(p, b.pageWidthMm * n);
12
+ return { w: p, h: f };
13
+ }), h = x(
14
+ () => Ye({
15
+ pageHeightsPx: l.value,
16
+ viewportHeightPx: s.value / o.value,
17
+ scrollTopPx: t.value / o.value,
18
+ overscan: 1,
19
+ gapPx: r
20
+ })
21
+ ), g = x(() => {
22
+ const u = e.value;
23
+ if (!u) return [];
24
+ const { start: f, end: p } = h.value;
25
+ return p < f ? [] : u.pages.slice(f, p + 1).map((b, k) => ({ page: b, index: f + k }));
26
+ });
27
+ function i(u, f) {
28
+ let p = 0;
29
+ return (b) => {
30
+ p || (p = requestAnimationFrame(() => {
31
+ if (p = 0, t.value = b.scrollTop, s.value = b.clientHeight || 800, f.value <= 0) return;
32
+ const k = b.querySelectorAll(".mrp-page-holder");
33
+ if (!k.length) return;
34
+ const W = b.getBoundingClientRect().top + 56;
35
+ let H = 1;
36
+ k.forEach((w) => {
37
+ w.getBoundingClientRect().top <= W && (H = Number(w.dataset.page ?? 1));
38
+ }), u.value = Math.max(1, Math.min(f.value, H));
39
+ }));
40
+ };
41
+ }
42
+ return {
43
+ contentSize: d,
44
+ windowRange: h,
45
+ visiblePages: g,
46
+ makeScrollHandler: i,
47
+ refreshViewport(u) {
48
+ u && (s.value = u.clientHeight || 800);
49
+ }
50
+ };
51
+ }
52
+ function ot(e) {
53
+ const o = T(1), a = T("fit");
54
+ function n() {
55
+ requestAnimationFrame(() => {
56
+ const t = e();
57
+ !t || !t.viewport || (o.value = Math.min(
58
+ 1,
59
+ Math.max(0.3, (t.viewport.clientWidth - 48) / Math.max(1, t.pageWidthPx))
60
+ ));
61
+ });
62
+ }
63
+ function r(t) {
64
+ t === "fit" ? (a.value = "fit", n()) : (a.value = "raw", o.value = t / 100);
65
+ }
66
+ return { zoom: o, zoomMode: a, applyFitZoom: n, setZoom: r };
67
+ }
68
+ const se = 8;
69
+ function le() {
70
+ return new Promise((e) => setTimeout(e, 0));
71
+ }
72
+ function te(e) {
73
+ return `p${Math.round(e.pageWidthMm)}x${Math.round(e.pageHeightMm)}`;
74
+ }
75
+ function oe(e) {
76
+ const o = /* @__PURE__ */ new Map();
77
+ e.pages.forEach((s) => {
78
+ o.has(te(s)) || o.set(te(s), s);
79
+ });
80
+ const r = `<!doctype html><html><head><meta charset="utf-8"><style>${`.mr-page{margin:0 auto;page-break-after:always;}
81
+ .mr-page tr{break-inside:avoid;page-break-inside:avoid;}
82
+ .mr-comp{break-inside:avoid;page-break-inside:avoid;}
83
+ ${[...o.values()].map(
84
+ (s) => `@page ${te(s)}{size:${Math.round(s.pageWidthMm)}mm ${Math.round(s.pageHeightMm)}mm;margin:0;}`
85
+ ).join(`
86
+ `)}
87
+ body{margin:0;background:#fff;}`}</style></head><body>`, t = e.pages.map((s) => {
88
+ const l = Re(s, 96, {}, document);
89
+ return l.style.page = te(s), l.outerHTML;
90
+ });
91
+ return { head: r, pageChunks: t };
92
+ }
93
+ async function Kt(e, o = {}) {
94
+ const a = {
95
+ pages: e.flatMap((l) => l.pages)
96
+ };
97
+ if (a.pages.length === 0) return;
98
+ const { head: n, pageChunks: r } = oe(a), t = document.createElement("iframe");
99
+ t.style.cssText = "position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;", document.body.appendChild(t);
100
+ let s = !1;
101
+ try {
102
+ const l = t.contentDocument;
103
+ l.open(), l.write(n);
104
+ for (let d = 0; d < r.length; d++)
105
+ l.write(r[d]), d % se === se - 1 && (o.onProgress?.(d + 1, r.length), await le());
106
+ l.write("</body></html>"), l.close(), await le(), o.onProgress?.(r.length, r.length), s = !0, t.contentWindow?.focus(), t.contentWindow?.print();
107
+ } catch (l) {
108
+ o.onError?.(l instanceof Error ? `批量打印失败: ${l.message}` : "批量打印失败");
109
+ } finally {
110
+ s ? setTimeout(() => t.remove(), 6e4) : t.remove();
111
+ }
112
+ }
113
+ function rt(e, o) {
114
+ let a = null, n = !1, r = null;
115
+ function t() {
116
+ a?.remove(), a = null;
117
+ }
118
+ function s(i, u) {
119
+ const f = URL.createObjectURL(i), p = document.createElement("a");
120
+ p.href = f, p.download = u, p.click(), setTimeout(() => URL.revokeObjectURL(f), 1e4);
121
+ }
122
+ async function l() {
123
+ if (n) return;
124
+ const i = e.value;
125
+ if (!i || i.pages.length === 0) return;
126
+ n = !0, t();
127
+ const { head: u, pageChunks: f } = oe(i);
128
+ a = document.createElement("iframe"), a.style.cssText = "position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;", document.body.appendChild(a);
129
+ const p = a;
130
+ try {
131
+ const b = p.contentDocument;
132
+ b.open(), b.write(u);
133
+ for (let k = 0; k < f.length; k++)
134
+ if (b.write(f[k]), k % se === se - 1 && await le(), p !== a) return;
135
+ b.write("</body></html>"), b.close(), await le(), p.contentWindow?.focus(), p.contentWindow?.print();
136
+ } catch {
137
+ o.onError("调用打印失败,请改用导出 PDF");
138
+ } finally {
139
+ n = !1;
140
+ }
141
+ }
142
+ async function d() {
143
+ if (r) return r;
144
+ const i = e.value;
145
+ if (!(!i || i.pages.length === 0))
146
+ return r = (async () => {
147
+ try {
148
+ const u = await o.getPdfExporter()(i);
149
+ s(
150
+ new Blob([u], { type: "application/pdf" }),
151
+ "mach-report.pdf"
152
+ );
153
+ } catch (u) {
154
+ o.onError(u instanceof Error ? `PDF 导出失败: ${u.message}` : "PDF 导出失败");
155
+ } finally {
156
+ r = null;
157
+ }
158
+ })(), r;
159
+ }
160
+ function h(i) {
161
+ const u = e.value;
162
+ if (!u || u.pages.length === 0) return;
163
+ if (i === "pdf") {
164
+ d();
165
+ return;
166
+ }
167
+ const { head: f, pageChunks: p } = oe(u), b = `${f}${p.join("")}</body></html>`;
168
+ s(new Blob([b], { type: "text/html;charset=utf-8" }), `mach-report.${i === "html" ? "html" : i}`);
169
+ }
170
+ function g() {
171
+ const i = e.value;
172
+ if (!i || i.pages.length === 0) return;
173
+ const { head: u, pageChunks: f } = oe(i), p = `${u}${f.join("")}</body></html>`, b = new Blob([p], { type: "text/html;charset=utf-8" }), k = URL.createObjectURL(b), W = window.open(k, "_blank");
174
+ if (!W) {
175
+ o.onError("浏览器拦截了弹窗,请允许弹窗后重试"), URL.revokeObjectURL(k);
176
+ return;
177
+ }
178
+ setTimeout(() => W.print(), 400), setTimeout(() => URL.revokeObjectURL(k), 1e4);
179
+ }
180
+ return {
181
+ print: l,
182
+ exportAs: h,
183
+ openPdfWindow: g,
184
+ releasePrintFrame: t
185
+ };
186
+ }
187
+ const Te = "mrp-hit";
188
+ function at(e) {
189
+ e.querySelectorAll(`mark.${Te}`).forEach((a) => {
190
+ const n = a.parentNode;
191
+ if (n) {
192
+ for (; a.firstChild; ) n.insertBefore(a.firstChild, a);
193
+ a.remove(), n.normalize();
194
+ }
195
+ });
196
+ }
197
+ function st(e, o) {
198
+ const a = o.trim();
199
+ if (!a) return 0;
200
+ const n = a.toLowerCase(), r = document.createTreeWalker(e, NodeFilter.SHOW_TEXT, {
201
+ acceptNode(l) {
202
+ const d = l.parentElement;
203
+ return !d || d.closest("mark") || /^(SCRIPT|STYLE)$/.test(d.tagName) ? NodeFilter.FILTER_REJECT : (l.nodeValue ?? "").toLowerCase().includes(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
204
+ }
205
+ }), t = [];
206
+ for (let l = r.nextNode(); l; l = r.nextNode()) t.push(l);
207
+ let s = 0;
208
+ for (const l of t) {
209
+ const d = l.nodeValue ?? "", h = d.toLowerCase(), g = l.parentElement;
210
+ if (!g) continue;
211
+ const i = document.createDocumentFragment();
212
+ let u = 0, f = h.indexOf(n);
213
+ for (; f >= 0; ) {
214
+ f > u && i.appendChild(document.createTextNode(d.slice(u, f)));
215
+ const p = document.createElement("mark");
216
+ p.className = Te, p.textContent = d.slice(f, f + a.length), i.appendChild(p), s++, u = f + a.length, f = h.indexOf(n, u);
217
+ }
218
+ u < d.length && i.appendChild(document.createTextNode(d.slice(u))), g.replaceChild(i, l);
219
+ }
220
+ return s;
221
+ }
222
+ function Ee(e, o) {
223
+ let a = 0, n = e.toLowerCase().indexOf(o);
224
+ for (; n >= 0; )
225
+ a++, n = e.toLowerCase().indexOf(o, n + o.length);
226
+ return a;
227
+ }
228
+ function lt(e) {
229
+ const { plan: o, gotoPage: a, highlight: n, clearHighlights: r } = e, t = e.debounceMs ?? 200, s = T(!1), l = T(""), d = T(""), h = T(0);
230
+ let g = null;
231
+ const i = x(() => {
232
+ const w = l.value.trim().toLowerCase(), S = o.value;
233
+ if (!w || !S) return [];
234
+ const B = [];
235
+ return S.pages.forEach((N, Q) => {
236
+ for (const O of N.components)
237
+ if (O.grid) {
238
+ for (const D of O.grid.cells ?? [])
239
+ for (const G of D ?? [])
240
+ if (typeof G?.text == "string")
241
+ for (let _ = 0; _ < Ee(G.text, w); _++) B.push(Q);
242
+ } else if (O.kind === "text" && typeof O.text == "string")
243
+ for (let D = 0; D < Ee(O.text, w); D++) B.push(Q);
244
+ }), B;
245
+ }), u = x(() => i.value.length);
246
+ function f(w) {
247
+ if (d.value = w, g && clearTimeout(g), w.trim() === "") {
248
+ g = null, l.value = "", h.value = 0;
249
+ return;
250
+ }
251
+ g = setTimeout(() => {
252
+ g = null, l.value = d.value, h.value = 0;
253
+ const S = i.value[0];
254
+ S != null && a(S + 1);
255
+ }, t);
256
+ }
257
+ function p(w) {
258
+ const S = i.value.length;
259
+ S !== 0 && (h.value = (h.value + w + S) % S, a(i.value[h.value] + 1));
260
+ }
261
+ function b() {
262
+ s.value = !s.value;
263
+ }
264
+ function k(w) {
265
+ const S = l.value.trim();
266
+ S && n(w, S);
267
+ }
268
+ function W(w) {
269
+ r(w);
270
+ }
271
+ function H() {
272
+ d.value = "", l.value = "", h.value = 0, g && clearTimeout(g), g = null;
273
+ }
274
+ return {
275
+ visible: s,
276
+ query: l,
277
+ matchIndex: h,
278
+ matchCount: u,
279
+ toggle: b,
280
+ onInput: f,
281
+ onNav: p,
282
+ apply: k,
283
+ clear: W,
284
+ reset: H
285
+ };
286
+ }
287
+ function it(e, o) {
288
+ const a = x(() => {
289
+ if (e.value) return !0;
290
+ if (typeof location > "u") return !1;
291
+ try {
292
+ return new URLSearchParams(location.search).get("mrp-debug") === "1";
293
+ } catch {
294
+ return !1;
295
+ }
296
+ }), n = x(() => !a.value || !o.plan.value ? 0 : Math.round(JSON.stringify(o.plan.value).length / 1024)), r = x(() => !a.value || !o.plan.value ? null : {
297
+ pages: o.pageCount.value,
298
+ window: `${o.windowRange.value.start}-${o.windowRange.value.end}`,
299
+ zoom: `${Math.round(o.zoom.value * 100)}%`,
300
+ loadMs: `${o.loadMs.value}ms`,
301
+ planKB: n.value
302
+ });
303
+ return { enabled: a, debugStats: r };
304
+ }
305
+ function ut(e, o) {
306
+ const { thumbsRoot: a, visible: n, renderThumbCanvas: r } = o;
307
+ let t = null;
308
+ function s(h, g) {
309
+ if (!e.value || h.childElementCount > 0) return;
310
+ const i = r(g);
311
+ i && (i.style.width = "100%", i.style.height = "100%", i.style.display = "block", h.appendChild(i));
312
+ }
313
+ return { schedule: () => {
314
+ !n.value || !e.value || !a.value || typeof IntersectionObserver > "u" || (t?.disconnect(), t = new IntersectionObserver(
315
+ (h) => {
316
+ for (const g of h) {
317
+ if (!g.isIntersecting) continue;
318
+ const i = g.target;
319
+ s(i, Number(i.dataset.thumb ?? 1) - 1), t?.unobserve(i);
320
+ }
321
+ },
322
+ { root: a.value, rootMargin: "200px" }
323
+ ), a.value.querySelectorAll("[data-thumb]").forEach((h) => {
324
+ t.observe(h);
325
+ }));
326
+ }, destroy: () => {
327
+ t?.disconnect(), t = null;
328
+ } };
329
+ }
330
+ function ct() {
331
+ const e = Ce(0);
332
+ return {
333
+ loadMs: e,
334
+ start() {
335
+ return typeof performance < "u" ? performance.now() : 0;
336
+ },
337
+ end(o) {
338
+ e.value = o ? Math.round(performance.now() - o) : 0;
339
+ }
340
+ };
341
+ }
342
+ const dt = { class: "mrp-toolbar" }, ft = { class: "mrp-title" }, pt = ["disabled"], mt = { class: "mrp-pageinfo" }, gt = ["disabled"], ht = {
343
+ key: 1,
344
+ class: "mrp-search"
345
+ }, vt = ["placeholder", "value"], bt = {
346
+ key: 0,
347
+ class: "mrp-search-count"
348
+ }, wt = ["disabled"], yt = ["disabled"], Pt = /* @__PURE__ */ ke({
349
+ __name: "ReportToolbar",
350
+ props: {
351
+ pageCount: {},
352
+ currentPage: {},
353
+ zoomMode: {},
354
+ zoom: {},
355
+ showExport: { type: Boolean },
356
+ showPrint: { type: Boolean },
357
+ showPdfWindow: { type: Boolean },
358
+ messages: {},
359
+ search: {},
360
+ thumbsVisible: { type: Boolean }
361
+ },
362
+ emits: ["goto", "zoom", "export", "print", "pdf-window", "search-input", "search-nav", "search-toggle", "thumbs-toggle"],
363
+ setup(e) {
364
+ const o = e, a = T(null);
365
+ X(
366
+ () => o.search.visible,
367
+ (r) => {
368
+ r && Ae(() => a.value?.focus());
369
+ }
370
+ );
371
+ function n(r, t, s) {
372
+ return r.replace("{cur}", String(t)).replace("{total}", String(s));
373
+ }
374
+ return (r, t) => (M(), C("div", dt, [
375
+ y("span", ft, P(e.messages.title), 1),
376
+ e.pageCount > 0 ? (M(), C(ge, { key: 0 }, [
377
+ y("button", {
378
+ class: "mrp-nav",
379
+ type: "button",
380
+ disabled: e.currentPage <= 1,
381
+ onClick: t[0] || (t[0] = (s) => r.$emit("goto", e.currentPage - 1))
382
+ }, P(e.messages.prevPage), 9, pt),
383
+ y("span", mt, P(n(e.messages.pageInfo, e.currentPage, e.pageCount)), 1),
384
+ y("button", {
385
+ class: "mrp-nav",
386
+ type: "button",
387
+ disabled: e.currentPage >= e.pageCount,
388
+ onClick: t[1] || (t[1] = (s) => r.$emit("goto", e.currentPage + 1))
389
+ }, P(e.messages.nextPage), 9, gt)
390
+ ], 64)) : L("", !0),
391
+ t[14] || (t[14] = y("span", { class: "mrp-spacer" }, null, -1)),
392
+ e.search.visible ? (M(), C("div", ht, [
393
+ y("input", {
394
+ ref_key: "searchInputRef",
395
+ ref: a,
396
+ class: "mrp-search-input",
397
+ type: "text",
398
+ placeholder: e.messages.searchPlaceholder,
399
+ value: e.search.query,
400
+ onInput: t[2] || (t[2] = (s) => r.$emit("search-input", s.target.value))
401
+ }, null, 40, vt),
402
+ e.search.query ? (M(), C("span", bt, P(n(e.messages.matchInfo, e.search.matchIndex + 1, e.search.matchCount)), 1)) : L("", !0),
403
+ y("button", {
404
+ class: "mrp-nav",
405
+ type: "button",
406
+ disabled: e.search.matchCount === 0,
407
+ onClick: t[3] || (t[3] = (s) => r.$emit("search-nav", -1))
408
+ }, P(e.messages.prevMatch), 9, wt),
409
+ y("button", {
410
+ class: "mrp-nav",
411
+ type: "button",
412
+ disabled: e.search.matchCount === 0,
413
+ onClick: t[4] || (t[4] = (s) => r.$emit("search-nav", 1))
414
+ }, P(e.messages.nextMatch), 9, yt)
415
+ ])) : L("", !0),
416
+ y("button", {
417
+ class: V(["mrp-nav", { "mrp-active": e.search.visible }]),
418
+ type: "button",
419
+ title: "Ctrl+F",
420
+ onClick: t[5] || (t[5] = (s) => r.$emit("search-toggle"))
421
+ }, " 🔍 ", 2),
422
+ y("button", {
423
+ class: V(["mrp-nav", { "mrp-active": e.thumbsVisible }]),
424
+ type: "button",
425
+ onClick: t[6] || (t[6] = (s) => r.$emit("thumbs-toggle"))
426
+ }, " ▦ " + P(e.messages.thumbnails), 3),
427
+ y("button", {
428
+ class: V(["mrp-nav", { "mrp-active": e.zoomMode === "fit" }]),
429
+ type: "button",
430
+ onClick: t[7] || (t[7] = (s) => r.$emit("zoom", "fit"))
431
+ }, P(e.messages.fitWidth), 3),
432
+ y("button", {
433
+ class: V(["mrp-nav", { "mrp-active": e.zoomMode === "raw" && Math.round(e.zoom * 100) === 100 }]),
434
+ type: "button",
435
+ onClick: t[8] || (t[8] = (s) => r.$emit("zoom", 100))
436
+ }, " 100% ", 2),
437
+ y("button", {
438
+ class: V(["mrp-nav", { "mrp-active": e.zoomMode === "raw" && Math.round(e.zoom * 100) === 150 }]),
439
+ type: "button",
440
+ onClick: t[9] || (t[9] = (s) => r.$emit("zoom", 150))
441
+ }, " 150% ", 2),
442
+ e.showExport ? (M(), C("button", {
443
+ key: 2,
444
+ class: "mrp-nav",
445
+ type: "button",
446
+ onClick: t[10] || (t[10] = (s) => r.$emit("export", "html"))
447
+ }, P(e.messages.exportHtml), 1)) : L("", !0),
448
+ e.showExport ? (M(), C("button", {
449
+ key: 3,
450
+ class: "mrp-nav",
451
+ type: "button",
452
+ onClick: t[11] || (t[11] = (s) => r.$emit("export", "pdf"))
453
+ }, P(e.messages.exportPdf), 1)) : L("", !0),
454
+ e.showPrint ? (M(), C("button", {
455
+ key: 4,
456
+ class: "mrp-nav",
457
+ type: "button",
458
+ onClick: t[12] || (t[12] = (s) => r.$emit("print"))
459
+ }, P(e.messages.print), 1)) : L("", !0),
460
+ e.showPdfWindow ? (M(), C("button", {
461
+ key: 5,
462
+ class: "mrp-nav",
463
+ type: "button",
464
+ onClick: t[13] || (t[13] = (s) => r.$emit("pdf-window"))
465
+ }, P(e.messages.pdfWindow), 1)) : L("", !0)
466
+ ]));
467
+ }
468
+ }), Se = (e, o) => {
469
+ const a = e.__vccOpts || e;
470
+ for (const [n, r] of o)
471
+ a[n] = r;
472
+ return a;
473
+ }, xt = /* @__PURE__ */ Se(Pt, [["__scopeId", "data-v-f50c26e8"]]), Et = {
474
+ title: "报表预览",
475
+ prevPage: "‹ 上一页",
476
+ nextPage: "下一页 ›",
477
+ pageInfo: "{cur} / {total}",
478
+ fitWidth: "适宽",
479
+ exportHtml: "导出 HTML",
480
+ exportPdf: "导出 PDF",
481
+ print: "打印",
482
+ pdfWindow: "PDF 窗口",
483
+ loading: "报表渲染中…",
484
+ empty: "暂无预览数据",
485
+ errorPrefix: "",
486
+ retry: "重试",
487
+ searchPlaceholder: "搜索报表内容",
488
+ matchInfo: "{cur}/{total}",
489
+ prevMatch: "‹",
490
+ nextMatch: "›",
491
+ thumbnails: "缩略图"
492
+ }, Mt = {
493
+ shellBg: "#525659",
494
+ shellFg: "#e8e8e8",
495
+ toolbarBg: "#323639",
496
+ toolbarBorder: "#22252a",
497
+ toolbarFg: "#e8e8e8",
498
+ btnFg: "#cfcfcf",
499
+ btnBorder: "#4a4d52",
500
+ btnHoverBg: "#414549",
501
+ btnHoverFg: "#ffffff",
502
+ btnActiveBg: "#2d5fb8"
503
+ };
504
+ function Vt(e) {
505
+ return e;
506
+ }
507
+ function Gt(e) {
508
+ return e;
509
+ }
510
+ const K = {
511
+ showExport: !0,
512
+ showPrint: !0,
513
+ showPdfWindow: !0,
514
+ gapPx: 18,
515
+ pdfFontUrl: "/simhei.ttf",
516
+ logger: console
517
+ }, Yt = { warn: () => {
518
+ }, info: () => {
519
+ } };
520
+ function Ct(e, o) {
521
+ const a = o ? e?.presets?.[o] : e?.defaultPreset ? e?.presets?.[e.defaultPreset] : void 0, n = { ...e?.defaults, ...a };
522
+ return {
523
+ showExport: n.showExport ?? K.showExport,
524
+ showPrint: n.showPrint ?? K.showPrint,
525
+ showPdfWindow: n.showPdfWindow ?? K.showPdfWindow,
526
+ gapPx: n.gapPx ?? K.gapPx,
527
+ pdfFontUrl: n.pdfFontUrl ?? K.pdfFontUrl,
528
+ theme: { ...Mt, ...n.theme },
529
+ messages: { ...Et, ...n.messages },
530
+ logger: n.logger ?? K.logger
531
+ };
532
+ }
533
+ function kt(e) {
534
+ const o = {};
535
+ return e.shellBg != null && (o["--mrp-shell-bg"] = e.shellBg), e.shellFg != null && (o["--mrp-shell-fg"] = e.shellFg), e.toolbarBg != null && (o["--mrp-toolbar-bg"] = e.toolbarBg), e.toolbarBorder != null && (o["--mrp-toolbar-border"] = e.toolbarBorder), e.toolbarFg != null && (o["--mrp-toolbar-fg"] = e.toolbarFg), e.btnFg != null && (o["--mrp-btn-fg"] = e.btnFg), e.btnBorder != null && (o["--mrp-btn-border"] = e.btnBorder), e.btnHoverBg != null && (o["--mrp-btn-hover-bg"] = e.btnHoverBg), e.btnHoverFg != null && (o["--mrp-btn-hover-fg"] = e.btnHoverFg), e.btnActiveBg != null && (o["--mrp-btn-active-bg"] = e.btnActiveBg), o;
536
+ }
537
+ function Zt(e) {
538
+ const o = ae(he, null), a = x(() => {
539
+ const n = o?.value ?? null, r = "defaults" in e && "presets" in e ? e : { defaults: e, presets: {} };
540
+ return n ? {
541
+ defaults: { ...n.defaults, ...r.defaults },
542
+ presets: { ...n.presets, ...r.presets },
543
+ defaultPreset: r.defaultPreset ?? n.defaultPreset
544
+ } : r;
545
+ });
546
+ $e(he, a);
547
+ }
548
+ function $t() {
549
+ return ae(he, x(() => null));
550
+ }
551
+ class re extends Error {
552
+ constructor(o, a, n) {
553
+ super(a), this.name = "MachReportError", this.code = o, this.cause = n;
554
+ }
555
+ }
556
+ function Rt(e) {
557
+ return e instanceof re ? { code: e.code, cause: e.cause } : { code: "render", cause: e };
558
+ }
559
+ const Tt = { class: "mrp-main" }, St = {
560
+ key: 0,
561
+ class: "mrp-state"
562
+ }, Ft = {
563
+ key: 1,
564
+ class: "mrp-state mrp-error"
565
+ }, It = {
566
+ key: 2,
567
+ class: "mrp-state"
568
+ }, Bt = ["data-page"], Lt = ["onClick"], zt = ["data-thumb"], Wt = { class: "mrp-thumb-no" }, Ht = { class: "mrp-overlay" }, Ot = {
569
+ key: 0,
570
+ class: "mrp-debug",
571
+ "aria-hidden": "true"
572
+ }, ne = 96 / 25.4, Me = "mach-report:ui", Nt = /* @__PURE__ */ ke({
573
+ __name: "ReportPreview",
574
+ props: {
575
+ tempId: {
576
+ type: [String, Array],
577
+ default: null
578
+ },
579
+ furnitureTempId: { type: String, default: "" },
580
+ params: {
581
+ type: Object,
582
+ default: () => ({})
583
+ },
584
+ height: { type: String, default: "100vh" },
585
+ autoLoad: { type: Boolean, default: !0 },
586
+ /** 以下显隐/间距不传时走配置中心(preset > defaults > 内置缺省) */
587
+ showExport: { type: Boolean, default: void 0 },
588
+ showPrint: { type: Boolean, default: void 0 },
589
+ showPdfWindow: { type: Boolean, default: void 0 },
590
+ /** 页间距(px);不传走配置中心 */
591
+ gapPx: { type: Number, default: void 0 },
592
+ /** 工具栏/状态文案覆写(不传走配置中心 messages) */
593
+ messages: { type: Object, default: void 0 },
594
+ /** 启用的 preset 名(不传用配置中心 defaultPreset) */
595
+ preset: { type: String, default: void 0 },
596
+ /** 调试面板(也可用 URL ?mrp-debug=1 开启) */
597
+ debug: { type: Boolean, default: !1 },
598
+ fetcher: {
599
+ type: Function,
600
+ default: null
601
+ }
602
+ },
603
+ emits: ["loaded", "error"],
604
+ setup(e, { expose: o, emit: a }) {
605
+ Ue((c) => ({
606
+ v6094bc50: p.value + "px"
607
+ }));
608
+ const n = e, r = a, t = Ce(null), s = T(!1), l = T(""), d = T(1), h = T(null), g = T(null), i = T(null), u = T(!1), f = ct(), p = x(() => Math.max(0, G.value)), b = ae(Xe, null), W = ae(Qe, null) ?? tt({ fontUrl: "/simhei.ttf" }), H = x(() => _e(n.tempId)), w = x(() => t.value?.pages.length ?? 0), S = $t(), B = x(() => Ct(S.value, n.preset)), N = x(() => ({
609
+ ...B.value.messages,
610
+ ...n.messages
611
+ })), Q = x(() => n.showExport ?? B.value.showExport), O = x(() => n.showPrint ?? B.value.showPrint), D = x(() => n.showPdfWindow ?? B.value.showPdfWindow), G = x(() => n.gapPx ?? B.value.gapPx), _ = x(() => ({
612
+ height: n.height,
613
+ ...kt(B.value.theme)
614
+ })), { zoom: I, zoomMode: A, applyFitZoom: ve, setZoom: ie } = ot(() => ({
615
+ viewport: g.value,
616
+ pageWidthPx: (t.value?.pages[0]?.pageWidthMm ?? 210) * ne
617
+ })), Fe = nt(t, I, {
618
+ pxPerMm: ne,
619
+ gapPx: G.value
620
+ }), { contentSize: ue, windowRange: Y, visiblePages: Ie, makeScrollHandler: Be, refreshViewport: be } = Fe, Le = Be(d, w);
621
+ function ce(c) {
622
+ A.value = "raw", I.value = Math.min(3, Math.max(0.3, c));
623
+ }
624
+ function de() {
625
+ t.value = null, d.value = 1, F.reset();
626
+ }
627
+ let ee = 0;
628
+ async function U() {
629
+ const c = ++ee, E = n.fetcher ?? b;
630
+ if (H.value.length === 0) {
631
+ l.value = "缺少报表模板 ID", de(), r("error", l.value, { code: "param" });
632
+ return;
633
+ }
634
+ if (!E) {
635
+ l.value = "未提供渲染数据源 fetcher", de(), r("error", l.value, { code: "config" });
636
+ return;
637
+ }
638
+ s.value = !0, l.value = "", de();
639
+ const $ = f.start();
640
+ try {
641
+ const v = await E({
642
+ tempIds: H.value,
643
+ furnitureTempId: n.furnitureTempId || void 0,
644
+ params: { ...n.params }
645
+ });
646
+ if (c !== ee) return;
647
+ const R = Ze(v);
648
+ if (!R.ok) {
649
+ const Z = R.errors.slice(0, 3).map((J) => `${J.path}: ${J.message}`).join("; ");
650
+ throw new re(
651
+ "validate",
652
+ `渲染计划校验失败(${R.errors.length} 处): ${Z}`
653
+ );
654
+ }
655
+ R.warnings.length > 0 && B.value.logger.warn("[mach-report] 渲染计划告警:", R.warnings), t.value = v, d.value = 1, f.end($), g.value && (g.value.scrollTop = 0), A.value === "fit" && ve(), r("loaded", v.pages.length);
656
+ } catch (v) {
657
+ if (c !== ee) return;
658
+ const R = v instanceof re ? v : new re(
659
+ "fetch",
660
+ v instanceof Error ? v.message : "预览加载失败",
661
+ v
662
+ );
663
+ l.value = R.message, r("error", R.message, Rt(R));
664
+ } finally {
665
+ c === ee && (s.value = !1);
666
+ }
667
+ }
668
+ function z(c) {
669
+ if (w.value <= 0) return;
670
+ const E = Math.max(1, Math.min(w.value, c));
671
+ d.value = E;
672
+ const $ = g.value;
673
+ if (!$) return;
674
+ let v = 0;
675
+ for (let R = 0; R < E - 1; R++)
676
+ v += (t.value?.pages[R]?.pageHeightMm ?? 0) * ne + p.value;
677
+ $.scrollTop = v * I.value;
678
+ }
679
+ const { print: fe, exportAs: pe, openPdfWindow: me, releasePrintFrame: ze } = rt(t, {
680
+ getPdfExporter: () => W,
681
+ onError: (c) => r("error", c, { code: "print" })
682
+ });
683
+ $e(et, { reload: U, print: fe, exportAs: pe, openPdfWindow: me, gotoPage: z });
684
+ const F = lt({
685
+ plan: t,
686
+ gotoPage: z,
687
+ highlight: st,
688
+ clearHighlights: at
689
+ });
690
+ function We(c) {
691
+ c.ctrlKey && (c.preventDefault(), ce(I.value * (c.deltaY < 0 ? 1.1 : 1 / 1.1)));
692
+ }
693
+ function He(c) {
694
+ if ((c.ctrlKey || c.metaKey) && c.key.toLowerCase() === "f") {
695
+ c.preventDefault(), F.visible.value || F.toggle();
696
+ return;
697
+ }
698
+ switch (c.key) {
699
+ case "PageDown":
700
+ c.preventDefault(), z(d.value + 1);
701
+ break;
702
+ case "PageUp":
703
+ c.preventDefault(), z(d.value - 1);
704
+ break;
705
+ case "Home":
706
+ c.preventDefault(), z(1);
707
+ break;
708
+ case "End":
709
+ c.preventDefault(), z(w.value);
710
+ break;
711
+ case "+":
712
+ case "=":
713
+ c.preventDefault(), ce(I.value * 1.1);
714
+ break;
715
+ case "-":
716
+ c.preventDefault(), ce(I.value / 1.1);
717
+ break;
718
+ }
719
+ }
720
+ function Oe() {
721
+ try {
722
+ localStorage.setItem(
723
+ Me,
724
+ JSON.stringify({ zoomMode: A.value === "fit" ? "fit" : Math.round(I.value * 100) })
725
+ );
726
+ } catch {
727
+ }
728
+ }
729
+ X([A, I], Oe), Pe(() => {
730
+ const c = t.value;
731
+ if (!c) return;
732
+ const E = h.value;
733
+ if (!E) return;
734
+ E.querySelectorAll(".mrp-page-holder").forEach((v) => {
735
+ const R = Number(v.dataset.page ?? 0) - 1, Z = c.pages[R];
736
+ if (!Z || v.childElementCount > 0) {
737
+ v.firstElementChild && F.apply(v.firstElementChild);
738
+ return;
739
+ }
740
+ v.style.width = `${Z.pageWidthMm * ne}px`;
741
+ const J = Re(Z, 96, {}, document);
742
+ F.apply(J), v.appendChild(J);
743
+ });
744
+ }, { flush: "post" }), X(() => F.query.value, (c) => {
745
+ c || h.value?.querySelectorAll(".mrp-page-holder").forEach((E) => {
746
+ F.clear(E);
747
+ });
748
+ });
749
+ const we = ut(t, {
750
+ thumbsRoot: i,
751
+ visible: u,
752
+ renderThumbCanvas: (c) => {
753
+ try {
754
+ const { canvases: E } = Je(t.value, { start: c, end: c, dpr: 0.2 });
755
+ return E[0] ?? null;
756
+ } catch {
757
+ return null;
758
+ }
759
+ }
760
+ });
761
+ Pe(() => {
762
+ we.schedule();
763
+ }, { flush: "post" });
764
+ const Ne = x(() => n.debug), { debugStats: j } = it(Ne, {
765
+ plan: t,
766
+ pageCount: w,
767
+ windowRange: Y,
768
+ zoom: I,
769
+ loadMs: f.loadMs
770
+ });
771
+ function ye() {
772
+ be(g.value), A.value === "fit" && ve();
773
+ }
774
+ function De() {
775
+ try {
776
+ const c = JSON.parse(localStorage.getItem(Me) ?? "{}");
777
+ c.zoomMode === "fit" ? ie("fit") : typeof c.zoomMode == "number" && ie(c.zoomMode);
778
+ } catch {
779
+ }
780
+ }
781
+ return je(() => {
782
+ window.addEventListener("resize", ye), be(g.value), De(), n.autoLoad && U();
783
+ }), qe(() => {
784
+ window.removeEventListener("resize", ye), we.destroy(), ze();
785
+ }), X(
786
+ () => [n.tempId, n.furnitureTempId, JSON.stringify(n.params)],
787
+ () => {
788
+ n.autoLoad && U();
789
+ }
790
+ ), X(
791
+ () => n.fetcher ?? b,
792
+ () => {
793
+ n.autoLoad && U();
794
+ }
795
+ ), o({ reload: U, print: fe, exportAs: pe, openPdfWindow: me, gotoPage: z }), (c, E) => (M(), C("div", {
796
+ class: "mach-report-preview",
797
+ style: q(_.value)
798
+ }, [
799
+ Ke(xt, {
800
+ "page-count": w.value,
801
+ "current-page": d.value,
802
+ "zoom-mode": m(A),
803
+ zoom: m(I),
804
+ "show-export": Q.value,
805
+ "show-print": O.value,
806
+ "show-pdf-window": D.value,
807
+ messages: N.value,
808
+ search: { visible: m(F).visible.value, query: m(F).query.value, matchIndex: m(F).matchIndex.value, matchCount: m(F).matchCount.value },
809
+ "thumbs-visible": u.value,
810
+ onGoto: z,
811
+ onZoom: m(ie),
812
+ onExport: E[0] || (E[0] = ($) => m(pe)($)),
813
+ onPrint: m(fe),
814
+ onPdfWindow: m(me),
815
+ onSearchInput: m(F).onInput,
816
+ onSearchNav: m(F).onNav,
817
+ onSearchToggle: m(F).toggle,
818
+ onThumbsToggle: E[1] || (E[1] = ($) => u.value = !u.value)
819
+ }, null, 8, ["page-count", "current-page", "zoom-mode", "zoom", "show-export", "show-print", "show-pdf-window", "messages", "search", "thumbs-visible", "onZoom", "onPrint", "onPdfWindow", "onSearchInput", "onSearchNav", "onSearchToggle"]),
820
+ y("div", Tt, [
821
+ y("div", {
822
+ ref_key: "viewportRef",
823
+ ref: g,
824
+ class: "mrp-body",
825
+ tabindex: "0",
826
+ onWheel: We,
827
+ onKeydown: He,
828
+ onScrollPassive: E[2] || (E[2] = ($) => m(Le)($.target))
829
+ }, [
830
+ s.value ? (M(), C("div", St, P(N.value.loading), 1)) : l.value ? (M(), C("div", Ft, [
831
+ Ve(P(l.value) + " ", 1),
832
+ y("button", {
833
+ class: "mrp-retry",
834
+ type: "button",
835
+ onClick: U
836
+ }, P(N.value.retry), 1)
837
+ ])) : !t.value || w.value === 0 ? (M(), C("div", It, P(N.value.empty), 1)) : (M(), C("div", {
838
+ key: 3,
839
+ class: "mrp-scale",
840
+ style: q({ width: `${m(ue).w * m(I)}px`, height: `${m(ue).h * m(I)}px` })
841
+ }, [
842
+ y("div", {
843
+ ref_key: "containerRef",
844
+ ref: h,
845
+ class: "mrp-scale-inner",
846
+ style: q({ transform: `scale(${m(I)})`, transformOrigin: "top left", width: `${m(ue).w}px` })
847
+ }, [
848
+ m(Y).padTopPx > 0 ? (M(), C("div", {
849
+ key: 0,
850
+ class: "mrp-spacer-top",
851
+ style: q({ height: `${m(Y).padTopPx}px` }),
852
+ "aria-hidden": "true"
853
+ }, null, 4)) : L("", !0),
854
+ (M(!0), C(ge, null, xe(m(Ie), ($) => (M(), C("div", {
855
+ key: $.index,
856
+ class: "mrp-page-holder",
857
+ "data-page": $.index + 1
858
+ }, null, 8, Bt))), 128)),
859
+ m(Y).padBottomPx > 0 ? (M(), C("div", {
860
+ key: 1,
861
+ class: "mrp-spacer-bottom",
862
+ style: q({ height: `${m(Y).padBottomPx}px` }),
863
+ "aria-hidden": "true"
864
+ }, null, 4)) : L("", !0)
865
+ ], 4)
866
+ ], 4))
867
+ ], 544),
868
+ u.value && w.value > 0 ? (M(), C("aside", {
869
+ key: 0,
870
+ ref_key: "thumbsRef",
871
+ ref: i,
872
+ class: "mrp-thumbs"
873
+ }, [
874
+ (M(!0), C(ge, null, xe(t.value?.pages ?? [], ($, v) => (M(), C("div", {
875
+ key: v,
876
+ class: V(["mrp-thumb", { "mrp-thumb-active": v + 1 === d.value }]),
877
+ onClick: (R) => z(v + 1)
878
+ }, [
879
+ y("div", {
880
+ class: "mrp-thumb-box",
881
+ "data-thumb": v + 1,
882
+ style: q({ height: `${Math.round($.pageHeightMm / $.pageWidthMm * 116)}px` })
883
+ }, null, 12, zt),
884
+ y("span", Wt, P(v + 1), 1)
885
+ ], 10, Lt))), 128))
886
+ ], 512)) : L("", !0)
887
+ ]),
888
+ y("div", Ht, [
889
+ Ge(c.$slots, "default", {}, void 0, !0)
890
+ ]),
891
+ m(j) ? (M(), C("div", Ot, [
892
+ E[3] || (E[3] = y("div", null, "mach-report debug", -1)),
893
+ y("div", null, "pages: " + P(m(j).pages) + " | window: [" + P(m(j).window) + "]", 1),
894
+ y("div", null, "zoom: " + P(m(j).zoom) + " | load: " + P(m(j).loadMs), 1),
895
+ y("div", null, "plan: " + P(m(j).planKB) + "KB", 1)
896
+ ])) : L("", !0)
897
+ ], 4));
898
+ }
899
+ }), Dt = /* @__PURE__ */ Se(Nt, [["__scopeId", "data-v-02570f40"]]), Jt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
900
+ __proto__: null,
901
+ default: Dt
902
+ }, Symbol.toStringTag, { value: "Module" }));
903
+ export {
904
+ Et as D,
905
+ re as M,
906
+ Dt as R,
907
+ Yt as S,
908
+ Mt as a,
909
+ xt as b,
910
+ oe as c,
911
+ Vt as d,
912
+ Gt as e,
913
+ Zt as f,
914
+ Rt as g,
915
+ nt as h,
916
+ rt as i,
917
+ ot as j,
918
+ Jt as k,
919
+ Kt as p,
920
+ Ct as r,
921
+ kt as t,
922
+ $t as u
923
+ };