@agile-team/mach-report 1.2.1 → 2.0.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.
- package/README.md +86 -255
- package/dist/ReportPreview-Cr0IH1Rz.cjs +6 -0
- package/dist/ReportPreview-DwknBgsJ.js +1266 -0
- package/dist/defaults.d.ts +3 -7
- package/dist/format.d.ts +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +621 -758
- package/dist/layout/textwrap.d.ts +1 -1
- package/dist/pdf.cjs +1 -1
- package/dist/pdf.js +1 -1
- package/dist/plugin-Cj3c2wJc.cjs +1 -0
- package/dist/plugin-DJf_6_fl.js +18 -0
- package/dist/schema/render-plan.d.ts +1 -9
- package/dist/sql/expr.d.ts +3 -3
- package/dist/sql.d.cts +1 -1
- package/dist/sql.d.ts +1 -1
- package/dist/style-CFZ-HE2s.cjs +3 -0
- package/dist/{style-6ihHKVCM.js → style-DnmtG7Gl.js} +69 -81
- package/dist/style.css +1 -1
- package/dist/vue/ReportPreview.d.ts +3 -12
- package/dist/vue/adapters.d.ts +6 -12
- package/dist/vue/async.d.cts +7 -22
- package/dist/vue/async.d.ts +7 -22
- package/dist/vue/local-adapter.d.ts +1 -2
- package/dist/vue/plugin.d.ts +12 -34
- package/dist/vue-async.cjs +1 -1
- package/dist/vue-async.js +6 -6
- package/dist/vue.cjs +1 -1
- package/dist/vue.js +48 -48
- package/package.json +2 -12
- package/dist/ReportPreview-CJLvkTVn.cjs +0 -6
- package/dist/ReportPreview-mZiGtf0L.js +0 -1231
- package/dist/compat/jh4j-template.d.ts +0 -12
- package/dist/manager/api.d.ts +0 -45
- package/dist/manager/index.d.ts +0 -2
- package/dist/manager/types.d.ts +0 -50
- package/dist/manager.cjs +0 -1
- package/dist/manager.d.cts +0 -5
- package/dist/manager.d.ts +0 -5
- package/dist/manager.js +0 -104
- package/dist/plugin-C4qpbdMJ.cjs +0 -1
- package/dist/plugin-DcmAPK_K.js +0 -85
- package/dist/style-Xq08-IsV.cjs +0 -3
package/README.md
CHANGED
|
@@ -1,304 +1,135 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# 📊 MachReport
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**独立的 TypeScript 报表引擎与 Vue 3 预览组件**
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
提供 jh4j-cloud-report 的 `gridPlan` 接入与迁移工具;具体模板是否可替换,以真实环境验收为准。
|
|
7
|
+
用自己的模板和数据生成报表,或接入项目已有的报表数据接口;统一预览、打印与导出。
|
|
9
8
|
|
|
10
|
-
[](https://www.npmjs.com/package/@agile-team/mach-report)
|
|
11
10
|
[](https://github.com/ChenyCHENYU/MachReport/actions/workflows/ci.yml)
|
|
12
|
-
[](https://www.npmjs.com/package/@agile-team/mach-report)
|
|
14
|
-
[](#-license)
|
|
11
|
+
[](https://www.npmjs.com/package/@agile-team/mach-report)
|
|
15
12
|
|
|
16
|
-
[快速开始](#快速开始) · [
|
|
13
|
+
[快速开始](#快速开始) · [接入项目数据](#接入项目数据) · [能力一览](#能力一览) · [文档](#文档)
|
|
17
14
|
|
|
18
15
|
</div>
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
## MachReport 做什么
|
|
18
|
+
|
|
19
|
+
| 环节 | 能力 |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| 定义报表 | TypeScript 模板 DSL 或 JSON 模板,支持明细、分组、总计和分页 |
|
|
22
|
+
| 提供数据 | 本地数据集,或由项目实现 `PlanFetcher` 返回 `RenderPlan` |
|
|
23
|
+
| 展示与交互 | Vue 3 预览组件、缩放、搜索、缩略图、参数面板、页级虚拟化 |
|
|
24
|
+
| 输出 | 浏览器打印、PDF、XLSX、逐页图片、Word 兼容文档 |
|
|
25
|
+
|
|
26
|
+
MachReport 不预设网关地址、鉴权方式或报表服务。组件只通过 `fetcher` 获取项目的渲染计划。
|
|
21
27
|
|
|
22
28
|
## 快速开始
|
|
23
29
|
|
|
30
|
+
**1. 安装**
|
|
31
|
+
|
|
24
32
|
```bash
|
|
25
|
-
pnpm add @agile-team/mach-report
|
|
33
|
+
pnpm add @agile-team/mach-report
|
|
26
34
|
```
|
|
27
35
|
|
|
36
|
+
**2. 用本地模板注册数据源**
|
|
37
|
+
|
|
28
38
|
```ts
|
|
29
|
-
// main.ts
|
|
30
|
-
import {
|
|
39
|
+
// main.ts
|
|
40
|
+
import { createApp } from "vue";
|
|
41
|
+
import App from "./App.vue";
|
|
42
|
+
import { createTemplate } from "@agile-team/mach-report";
|
|
43
|
+
import { createLocalFetcher, machReportPlugin } from "@agile-team/mach-report/vue";
|
|
31
44
|
import "@agile-team/mach-report/vue/style.css";
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
const template = createTemplate()
|
|
47
|
+
.page("a4")
|
|
48
|
+
.text("第一张报表", { leftMm: 20, topMm: 20, widthMm: 100, heightMm: 10 })
|
|
49
|
+
.build();
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
const fetcher = createLocalFetcher({ demo: { template } });
|
|
52
|
+
const app = createApp(App);
|
|
53
|
+
app.use(machReportPlugin, { fetcher });
|
|
54
|
+
app.mount("#app");
|
|
40
55
|
```
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
## 核心能力
|
|
45
|
-
|
|
46
|
-
| 域 | 能力 |
|
|
47
|
-
|---|---|
|
|
48
|
-
| **报表语义** | 分组小计 / 总合计(防孤行)、页码占位符 `{page}/{totalPages}`、列格式化(千分位 / 日期 / 百分比)、条件格式规则 |
|
|
49
|
-
| **模板体系** | DSL / JSON / jh4j 存量导入三来源;多模板拼接;公共页眉页脚;参数面板(声明式查询条件)。存量导入的富文本、图片类和子报表可能降级,需按模板验收 |
|
|
50
|
-
| **渲染性能** | 页级虚拟化;transform 缩放;Canvas 窗口化分页器;内部性能预算见下文 |
|
|
51
|
-
| **导出出口** | PDF 前端矢量直出、Excel 真表格、Word 兼容 HTML `.doc`、图片 PNG/JPEG(每页一张)、逐页打印;复杂版式以 PDF 验收 |
|
|
52
|
-
| **预览交互** | 搜索(跳页 + 高亮)、Ctrl+滚轮 / 键盘缩放翻页、缩略图侧栏、缩放记忆、调试面板 `?mrp-debug=1` |
|
|
53
|
-
| **工程健壮性** | 加载竞态代际令牌、结构化错误码、请求超时、批量打印合并文档、渲染计划规模告警、导出保真提示 |
|
|
54
|
-
|
|
55
|
-
<details>
|
|
56
|
-
<summary><b>单包架构说明(为什么只有一个包)</b></summary>
|
|
57
|
-
|
|
58
|
-
框架组件在 `./vue` 子路径(vue 声明为 **optional peer**——React / Node 宿主不会被装上 vue);
|
|
59
|
-
pdf-lib / node-sql-parser / exceljs 分别内联进 `./pdf` `./sql` `./xlsx` 子路径产物——**不导入不进依赖图**,
|
|
60
|
-
主入口零框架耦合零重依赖(ESLint 边界规则 + 产物守卫测试双保险)。
|
|
61
|
-
自引用(self-reference)让 `./vue` 静态复用引擎、PDF 懒加载走 `./pdf`,运行时引擎代码全局单份。
|
|
62
|
-
ESM + CJS 双格式 + `.d.ts/.d.cts` 双声明,Node ≥ 18。
|
|
63
|
-
|
|
64
|
-
</details>
|
|
65
|
-
|
|
66
|
-
<details>
|
|
67
|
-
<summary><b>三种集成姿势(全局插件 / 局部导入 / 异步入口)</b></summary>
|
|
68
|
-
|
|
69
|
-
**① 全局插件(推荐)**:上文快速开始即是。插件注册全局组件 `<MachReportPreview>`(懒加载分片零首屏成本)、注入数据面 / PDF 导出器 / 配置中心。
|
|
70
|
-
|
|
71
|
-
**② 局部导入**——单页面使用:
|
|
57
|
+
**3. 在页面中预览**
|
|
72
58
|
|
|
73
59
|
```vue
|
|
74
|
-
<script setup lang="ts">
|
|
75
|
-
import { ReportPreview, createLocalFetcher } from "@agile-team/mach-report/vue";
|
|
76
|
-
const fetcher = createLocalFetcher({
|
|
77
|
-
T1: { tempId: "T1", template, datasets: { detail: rows } }
|
|
78
|
-
});
|
|
79
|
-
</script>
|
|
80
60
|
<template>
|
|
81
|
-
<
|
|
61
|
+
<MachReportPreview report-id="demo" height="70vh" />
|
|
82
62
|
</template>
|
|
83
63
|
```
|
|
84
64
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
|
-
import AsyncMachReportPlugin, { preloadMachReport } from "@agile-team/mach-report/vue/async";
|
|
89
|
-
app.use(AsyncMachReportPlugin, { baseUrl: "/sub/mach-report" });
|
|
90
|
-
void preloadMachReport(); // 路由 hover 时预取,正式渲染零等待
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
</details>
|
|
94
|
-
|
|
95
|
-
<details>
|
|
96
|
-
<summary><b>配置中心(presets / 文案 / 主题 / 日志通道)</b></summary>
|
|
97
|
-
|
|
98
|
-
```ts
|
|
99
|
-
// src/config/mach-report.config.ts —— 集中到独立配置文件
|
|
100
|
-
import { defineMachReportConfig, defineMachReportPreset } from "@agile-team/mach-report/vue";
|
|
101
|
-
|
|
102
|
-
export default defineMachReportConfig({
|
|
103
|
-
defaults: {
|
|
104
|
-
gapPx: 18,
|
|
105
|
-
pdfFontUrl: "/simhei.ttf",
|
|
106
|
-
showParams: true, // 参数面板
|
|
107
|
-
messages: { title: "Report Preview" }, // 全量文案可覆写(i18n)
|
|
108
|
-
theme: { shellBg: "#2b2b2b", btnActiveBg: "#1677ff" }, // --mrp-* 主题变量
|
|
109
|
-
logger: console // 校验告警通道(静默传 SILENT_LOGGER)
|
|
110
|
-
},
|
|
111
|
-
presets: {
|
|
112
|
-
lean: defineMachReportPreset({ showExport: false, showPrint: false }), // 纯预览
|
|
113
|
-
print: defineMachReportPreset({ showPdfWindow: false })
|
|
114
|
-
},
|
|
115
|
-
defaultPreset: "lean"
|
|
116
|
-
});
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**优先级**:`组件 props` > `provideMachReportConfig(overlay)`(路由级响应式叠加)> `preset` > `defaults` > `内置缺省`。
|
|
120
|
-
|
|
121
|
-
**参数面板**:模板声明 `.params([...])` 或 prop `:param-defs`,组件自动生成查询条件(text / number / date / select、必填、默认值、查询 / 重置 / 回车),查询时面板值与 `props.params` 合并;编程式 `setParams(values)` 同步面板并查询。
|
|
122
|
-
|
|
123
|
-
**主题**也可不经配置中心,直接在宿主 CSS 覆写 `--mrp-shell-bg / --mrp-toolbar-bg / --mrp-btn-*`。
|
|
124
|
-
|
|
125
|
-
</details>
|
|
126
|
-
|
|
127
|
-
<details>
|
|
128
|
-
<summary><b>模板 DSL 与报表语义</b></summary>
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
|
-
const template = createTemplate()
|
|
132
|
-
.params([ // 参数面板:声明式查询条件
|
|
133
|
-
{ field: "whCode", label: "仓库", type: "select", required: true,
|
|
134
|
-
options: [{ label: "全部仓库", value: "ALL" }], defaultValue: "ALL" },
|
|
135
|
-
{ field: "date", label: "日期", type: "date", defaultValue: "2026-09-30" }
|
|
136
|
-
])
|
|
137
|
-
.page("a4", { landscape: true, margins: { marginTopMm: 12 } }) // 纸张预设 + 横向
|
|
138
|
-
.text("出库单", { leftMm: 70, topMm: 2, widthMm: 70 }, { fontSize: 16, bold: true, align: "center" })
|
|
139
|
-
.text("第 {page} 页 / 共 {totalPages} 页", { leftMm: 65, topMm: 285, widthMm: 80 }, { align: "center" })
|
|
140
|
-
.barcode("CK-001", { leftMm: 12, topMm: 14, widthMm: 40, heightMm: 12 })
|
|
141
|
-
.list("detail", { leftMm: 12, topMm: 32, widthMm: 186 }, [
|
|
142
|
-
{ header: "物料", field: "name", widthMm: 96 },
|
|
143
|
-
{ header: "数量", field: "qty", widthMm: 45, format: { kind: "number", thousands: true } },
|
|
144
|
-
{ header: "金额", field: "amount", widthMm: 45,
|
|
145
|
-
format: { kind: "number", thousands: true, digits: 2 },
|
|
146
|
-
rules: [{ when: { field: "amount", op: "<", value: 0 }, style: { color: "#cc0000" } }] },
|
|
147
|
-
{ header: "日期", field: "date", widthMm: 45, format: { kind: "date", pattern: "YYYY-MM-DD" } }
|
|
148
|
-
], {
|
|
149
|
-
groupBy: { field: "wh", headerTemplate: "仓库:{value}", subtotal: ["qty", "amount"] },
|
|
150
|
-
grandTotal: true
|
|
151
|
-
})
|
|
152
|
-
.build();
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
语义要点:格式化在进 RenderPlan 前完成(三后端零感知,`digits` 显式精确保留、日期按本地日历日解析);
|
|
156
|
-
分组 Map 归组与数据顺序无关;条件规则命中才克隆样式(热路径驻留不破坏);含占位符的文本转为页锚,每个输出页克隆注入。
|
|
157
|
-
|
|
158
|
-
</details>
|
|
159
|
-
|
|
160
|
-
<details>
|
|
161
|
-
<summary><b>数据面(fetcher 生态:零配置 / jh4j / 本地 / 自定义)</b></summary>
|
|
162
|
-
|
|
163
|
-
| 工具 | 场景 |
|
|
164
|
-
|---|---|
|
|
165
|
-
| 内置(零配置) | 插件不传 request / fetcher 时自动用全局 fetch 同源请求 `/report/codePrintReport/gridPlan` |
|
|
166
|
-
| `createFetchRequest({ baseUrl, headers, credentials, timeoutMs })` | 零依赖 fetch 适配(AbortController 超时 + 错误语义) |
|
|
167
|
-
| `createJh4jGridPlanFetcher({ request, baseUrl })` | 接宿主 axios 风格客户端,消费 jh4j gridPlan(路径 / 出入参契约兼容) |
|
|
168
|
-
| `createLocalFetcher({ [tempId]: { template, datasets } })` | 本地模板(离线 / 单测 / 无后端);面板参数用 `:param-defs="template.params"` 直取 |
|
|
65
|
+
使用 Vue 组件需要 Vue 3。只使用引擎或 Node.js 导出时,无需导入 `/vue` 子路径。
|
|
169
66
|
|
|
170
|
-
|
|
171
|
-
任何后端能吐 RenderPlan JSON 就能接(schema 有校验器与文档)。
|
|
67
|
+
## 接入项目数据
|
|
172
68
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<details>
|
|
176
|
-
<summary><b>引擎 API(框架无关,子路径按需)</b></summary>
|
|
69
|
+
项目已有接口时,实现一个 `PlanFetcher`,返回 MachReport 的 `RenderPlan`。接口路径、请求库、鉴权和数据映射都由项目决定:
|
|
177
70
|
|
|
178
71
|
```ts
|
|
179
|
-
import {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
72
|
+
import type { RenderPlan } from "@agile-team/mach-report";
|
|
73
|
+
import type { PlanFetcher } from "@agile-team/mach-report/vue";
|
|
74
|
+
|
|
75
|
+
const fetcher: PlanFetcher = async ({ reportIds, params }) => {
|
|
76
|
+
const response = await fetch("/api/report-plan", {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
body: JSON.stringify({ reportIds, params })
|
|
80
|
+
});
|
|
81
|
+
if (!response.ok) throw new Error(`报表加载失败:HTTP ${response.status}`);
|
|
82
|
+
return (await response.json()) as RenderPlan;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// 在 main.ts 中替换本地 fetcher 的注册;也可传给单个 ReportPreview。
|
|
86
|
+
app.use(machReportPlugin, { fetcher });
|
|
191
87
|
```
|
|
192
88
|
|
|
193
|
-
|
|
89
|
+
`/api/report-plan` 是示例路径,请替换为项目接口。需要从现有业务数据生成 `RenderPlan` 时,可在客户端或服务端调用 `paginateTemplate(template, datasets)`;[API 文档](https://github.com/ChenyCHENYU/MachReport/blob/main/docs/API.md)给出完整类型与示例。
|
|
194
90
|
|
|
91
|
+
```text
|
|
92
|
+
模板 + 数据 ── paginateTemplate ──┐
|
|
93
|
+
├─ RenderPlan ─┬─ 预览 / 打印
|
|
94
|
+
项目数据接口 ── 自定义 PlanFetcher ┘ ├─ PDF / XLSX
|
|
95
|
+
└─ 图片 / Word 兼容文档
|
|
195
96
|
```
|
|
196
|
-
模板 JSON ──+──> paginateTemplate(template, datasets) ──> RenderPlan
|
|
197
|
-
│ ├──> DOM 虚拟化预览
|
|
198
|
-
jh4j gridPlan ──(契约兼容消费) ├──> Canvas 窗口化分页器
|
|
199
|
-
├──> PDF 矢量直出
|
|
200
|
-
└──> print(named pages)
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**大报表 Canvas**:`createCanvasPager(plan, { dpr, overscan }).attach(scrollContainer)` —— 视口窗口 + 画布池复用 + 每帧限量绘制 + resize 自适应。
|
|
204
|
-
|
|
205
|
-
**批量打印**:`printPlans([plan1, plan2], { onProgress })` 多单合并单文档(混合纸张 named pages),只弹一次打印框。
|
|
206
97
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<details>
|
|
210
|
-
<summary><b>性能预算与比较边界</b></summary>
|
|
211
|
-
|
|
212
|
-
`perf-budget.test.ts` 是内部回归门槛:5,000 行分页 < 600ms、DOM 渲染 < 120ms/页、1,000 页窗口计算 100 次 < 50ms(测试环境口径)。它不含网关取数、真实字体加载、打印机或浏览器下载耗时。与 jh4j / FineReport 的性能比较需使用相同模板、数据、机器和网络做端到端测量;方法见[验收文档](https://github.com/ChenyCHENYU/MachReport/blob/main/docs/comparison-and-acceptance.md)。
|
|
213
|
-
|
|
214
|
-
</details>
|
|
215
|
-
|
|
216
|
-
<details>
|
|
217
|
-
<summary><b>Node 无头导出通道(同一引擎两端执行)</b></summary>
|
|
218
|
-
|
|
219
|
-
引擎框架无关——`renderPlanToPdf` / `renderPlanToXlsx` 及 `loadFontWithCache` 均可在 **Node 18+** 直接运行
|
|
220
|
-
(无 IndexedDB 环境自动降级内存缓存),解锁服务端场景而**不需要另写一套渲染**:
|
|
221
|
-
|
|
222
|
-
```ts
|
|
223
|
-
// server.ts —— 定时任务 / 邮件推送 / 归档,无浏览器环境
|
|
224
|
-
import { renderPlanToPdf } from "@agile-team/mach-report/pdf";
|
|
225
|
-
import { loadFontWithCache } from "@agile-team/mach-report/pdf";
|
|
226
|
-
import { renderPlanToXlsx } from "@agile-team/mach-report/xlsx";
|
|
227
|
-
|
|
228
|
-
const font = await loadFontWithCache("/path/to/simhei.ttf"); // 读文件系统可自行替换
|
|
229
|
-
const { bytes } = await renderPlanToPdf(plan, font ? { customFontBytes: font } : {});
|
|
230
|
-
await fs.writeFile("archive.pdf", bytes);
|
|
231
|
-
```
|
|
98
|
+
## 能力一览
|
|
232
99
|
|
|
233
|
-
|
|
100
|
+
| 领域 | 已提供 |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| 报表语义 | 明细分页、分组小计、总计、页码占位符、列格式化、条件格式 |
|
|
103
|
+
| 预览 | DOM / Canvas、页级虚拟化、缩放、搜索、缩略图、参数面板 |
|
|
104
|
+
| 导出 | PDF、真正的 `.xlsx`、PNG / JPEG、Word 兼容 HTML `.doc`、逐页打印 |
|
|
105
|
+
| 工程接入 | Vue 插件或局部组件、自定义数据源、结构化错误、导出进度与告警 |
|
|
106
|
+
| 按需入口 | `/vue`、`/pdf`、`/xlsx`、`/sql`;主入口为框架无关的引擎 |
|
|
234
107
|
|
|
235
|
-
|
|
108
|
+
中文 PDF 需配置包含所用汉字的字体 `pdfFontUrl`;缺字时导出会报错。XLSX 保留表格数据与结构,不承诺 PDF 式像素排版;`.doc` 是 Word 可打开的 HTML 文档,并非 `.docx`。
|
|
236
109
|
|
|
237
|
-
|
|
238
|
-
<summary><b>从 jh4j 迁移(契约对照)</b></summary>
|
|
110
|
+
## 文档
|
|
239
111
|
|
|
240
|
-
|
|
|
241
|
-
|
|
242
|
-
|
|
|
243
|
-
|
|
|
244
|
-
|
|
|
245
|
-
| 存量 SQL | `#{}` `${}` `{if}` 三语法零改写;AST 级单 SELECT 校验加严 |
|
|
246
|
-
| 模块联邦 | expose 名对齐,宿主配 `/sub/mach-report/` 网关即可灰度共存 |
|
|
112
|
+
| 入口 | 内容 |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| [API 速查](https://github.com/ChenyCHENYU/MachReport/blob/main/docs/API.md) | `RenderPlan`、模板 DSL、Vue 属性与事件、配置、导出 |
|
|
115
|
+
| [最小示例](https://github.com/ChenyCHENYU/MachReport/tree/main/examples/minimal) | 本地报表、多页预览与交互 |
|
|
116
|
+
| [模块联邦示例](https://github.com/ChenyCHENYU/MachReport/tree/main/examples/fed-host) | 远程加载报表组件 |
|
|
247
117
|
|
|
248
|
-
|
|
118
|
+
## 本地开发
|
|
249
119
|
|
|
250
|
-
|
|
251
|
-
<summary><b>打印兼容性指引(实战排障)</b></summary>
|
|
252
|
-
|
|
253
|
-
| 现象 | 原因与处理 |
|
|
254
|
-
|---|---|
|
|
255
|
-
| 表格底色打印丢失 | 浏览器默认关闭"背景图形"——打印对话框勾选*背景图形* |
|
|
256
|
-
| 混合纸张按 A4 输出 | named pages 需较新内核(Chrome 85+ / Safari 16+ / Firefox 133+),旧内核退化统一纸张 |
|
|
257
|
-
| iOS App 内打印无效 | WKWebView 限制——引导用户走"分享 → 打印"或导出 PDF |
|
|
258
|
-
| 字体首载后失效 | PDF 字体走 IndexedDB 缓存(15s 超时回退内置西文字体),清理站点数据后重新拉取 |
|
|
259
|
-
|
|
260
|
-
</details>
|
|
261
|
-
|
|
262
|
-
<details>
|
|
263
|
-
<summary><b>架构与质量门禁</b></summary>
|
|
264
|
-
|
|
265
|
-
```
|
|
266
|
-
MachReport(pnpm monorepo · TS strict · 单 npm 包)
|
|
267
|
-
├── packages/
|
|
268
|
-
│ ├── mach-report/ # 唯一发布包(零运行时依赖,ESM+CJS)
|
|
269
|
-
│ │ └── src/
|
|
270
|
-
│ │ ├── layout/ render/ schema/ builder/ compat/ format.ts # 引擎核心
|
|
271
|
-
│ │ └── pdf/ sql/ manager/ xlsx/ vue/ # 子路径域(重依赖/框架按需隔离)
|
|
272
|
-
│ └── federation/ # 模块联邦远程入口(部署产物,不发 npm)
|
|
273
|
-
├── examples/ # minimal 演示 + fed-host 联邦宿主实证
|
|
274
|
-
├── e2e/ docs/ assets/
|
|
275
|
-
```
|
|
120
|
+
需要 Node.js ≥ 18 和 pnpm ≥ 11。
|
|
276
121
|
|
|
277
122
|
```bash
|
|
278
|
-
pnpm
|
|
279
|
-
|
|
123
|
+
pnpm install
|
|
124
|
+
pnpm typecheck
|
|
125
|
+
pnpm lint
|
|
126
|
+
pnpm test
|
|
127
|
+
pnpm build
|
|
128
|
+
pnpm exec playwright test
|
|
280
129
|
```
|
|
281
130
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
</details>
|
|
285
|
-
|
|
286
|
-
## 路线图
|
|
287
|
-
|
|
288
|
-
- v1.0(已完成):单包架构 · 报表语义四件套 · 参数面板 · 交互完整面 · 双远端 + npm 定版
|
|
289
|
-
- 设计器画布(拖拽 / 属性面板 / 撤销栈)——独立立项,规划中
|
|
290
|
-
- 管理端控制台 UI(`./manager` API 已就绪)——独立立项,规划中
|
|
291
|
-
- 交叉表 / 公式列——按真实需求排期
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
<div align="center">
|
|
296
|
-
|
|
297
|
-
**Mach 家族**:[MachTable](https://www.npmjs.com/package/@agile-team/mach-table)(数据表格)→ **MachReport**(打印报表)
|
|
298
|
-
|
|
299
|
-
Source-available © ChenyCHENYU (Agile Team). 使用需事先取得书面授权,详见 [LICENSE](LICENSE)。
|
|
300
|
-
|
|
301
|
-
</div>
|
|
131
|
+
发布与协作约定见 [AGENTS.md](https://github.com/ChenyCHENYU/MachReport/blob/main/AGENTS.md)。
|
|
302
132
|
|
|
133
|
+
## 许可
|
|
303
134
|
|
|
304
|
-
|
|
135
|
+
Source-available © ChenyCHENYU (Agile Team)。使用需事先取得书面授权,详见 [LICENSE](https://github.com/ChenyCHENYU/MachReport/blob/main/LICENSE)。
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";var at=Object.create;var ke=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var it=Object.getPrototypeOf,ut=Object.prototype.hasOwnProperty;var ct=(t,n,l,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of st(n))!ut.call(t,o)&&o!==l&&ke(t,o,{get:()=>n[o],enumerable:!(a=lt(n,o))||a.enumerable});return t};var Ce=(t,n,l)=>(l=t!=null?at(it(t)):{},ct(n||!t||!t.__esModule?ke(l,"default",{value:t,enumerable:!0}):l,t));const e=require("vue"),H=require("@agile-team/mach-report"),O=require("./plugin-Cj3c2wJc.cjs");function de(t){return t==null?[]:Array.isArray(t)?t.map(String).filter(n=>n!==""):String(t).split(",").map(n=>n.trim()).filter(n=>n!=="")}function dt(t){return de(t).join(",")}class Q extends Error{constructor(n){super(n),this.name="PlanLoadError"}}function mt(t={}){const{baseUrl:n="",headers:l,credentials:a,timeoutMs:o=3e4}=t,r=n.replace(/\/+$/,"");return async({url:i,method:p,params:u})=>{const f=u&&Object.keys(u).length>0?`?${new URLSearchParams(u)}`:"",d=new AbortController,v=setTimeout(()=>d.abort(),o);let b;try{b=await fetch(`${r}${i}${f}`,{method:p.toUpperCase(),headers:{Accept:"application/json",...l},credentials:a,signal:d.signal})}catch(w){throw w instanceof DOMException&&w.name==="AbortError"?new Q(`请求超时(${o}ms): ${i}`):new Q(`请求失败(${i}): ${w instanceof Error?w.message:String(w)}`)}finally{clearTimeout(v)}if(!b.ok)throw new Q(`HTTP ${b.status} ${i}`);return b.json()}}function Re(t,n,l={}){const a=l.pxPerMm??3.7795275590551185,o=e.computed(()=>Math.max(0,e.unref(l.gapPx)??18)),r=e.ref(0),i=e.ref(800),p=e.computed(()=>(t.value?.pages??[]).map(b=>b.pageHeightMm*a)),u=e.computed(()=>{const b=t.value?.pages??[];let w=0,k=0;for(const C of b)w+=C.pageHeightMm*a+o.value,k=Math.max(k,C.pageWidthMm*a);return{w:k,h:w}}),f=e.computed(()=>H.computePageWindow({pageHeightsPx:p.value,viewportHeightPx:i.value/n.value,scrollTopPx:r.value/n.value,overscan:1,gapPx:o.value})),d=e.computed(()=>{const b=t.value;if(!b)return[];const{start:w,end:k}=f.value;return k<w?[]:b.pages.slice(w,k+1).map((C,M)=>({page:C,index:w+M}))});function v(b,w){let k=0;return C=>{k||(k=requestAnimationFrame(()=>{if(k=0,r.value=C.scrollTop,i.value=C.clientHeight||800,w.value<=0)return;const M=C.querySelectorAll(".mrp-page-holder");if(!M.length)return;const c=C.getBoundingClientRect().top+56;let h=1;M.forEach(m=>{m.getBoundingClientRect().top<=c&&(h=Number(m.dataset.page??1))}),b.value=Math.max(1,Math.min(w.value,h))}))}}return{contentSize:u,windowRange:f,visiblePages:d,makeScrollHandler:v,refreshViewport(b){b&&(i.value=b.clientHeight||800)}}}function Se(t){const n=e.ref(1),l=e.ref("fit");function a(){requestAnimationFrame(()=>{const r=t();!r||!r.viewport||(n.value=Math.min(1,Math.max(.3,(r.viewport.clientWidth-48)/Math.max(1,r.pageWidthPx))))})}function o(r){r==="fit"?(l.value="fit",a()):(l.value="raw",n.value=r/100)}return{zoom:n,zoomMode:l,applyFitZoom:a,setZoom:o}}const ee=8;function te(){return new Promise(t=>setTimeout(t,0))}function _(t){return`p${Math.round(t.pageWidthMm)}x${Math.round(t.pageHeightMm)}`}function me(t){const n=new Map;return t.pages.forEach(o=>{n.has(_(o))||n.set(_(o),o)}),`<!doctype html><html><head><meta charset="utf-8"><style>${`.mr-page{margin:0 auto;page-break-after:always;}
|
|
2
|
+
.mr-page tr{break-inside:avoid;page-break-inside:avoid;}
|
|
3
|
+
.mr-comp{break-inside:avoid;page-break-inside:avoid;}
|
|
4
|
+
${[...n.values()].map(o=>`@page ${_(o)}{size:${Math.round(o.pageWidthMm)}mm ${Math.round(o.pageHeightMm)}mm;margin:0;}`).join(`
|
|
5
|
+
`)}
|
|
6
|
+
body{margin:0;background:#fff;}`}</style></head><body>`}function pe(t){const n=H.renderPage(t,96,{},document);return n.style.page=_(t),n.outerHTML}function fe(t){return{head:me(t),pageChunks:t.pages.map(pe)}}async function pt(t,n={}){const l={schemaVersion:"mach-report-batch-print",pages:t.flatMap(i=>i.pages)};if(l.pages.length===0)return;const a=me(l),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);let r=!1;try{const i=o.contentDocument;i.open(),i.write(a);for(let p=0;p<l.pages.length;p++)i.write(pe(l.pages[p])),p%ee===ee-1&&(n.onProgress?.(p+1,l.pages.length),await te());i.write("</body></html>"),i.close(),await te(),n.onProgress?.(l.pages.length,l.pages.length),r=!0,o.contentWindow?.focus(),o.contentWindow?.print()}catch(i){n.onError?.(i instanceof Error?`批量打印失败: ${i.message}`:"批量打印失败")}finally{r?setTimeout(()=>o.remove(),6e4):o.remove()}}function Me(t){const{head:n,pageChunks:l}=fe(t);return{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]-->${n.replace(/^<!doctype html><html><head>/,"")}`}${l.join("")}</body></html>`,filename:"mach-report.doc"}}function Te(t,n){let l=null,a=!1,o=null,r=null,i=null;function p(){l?.remove(),l=null}function u(c,h){const m=URL.createObjectURL(c),g=document.createElement("a");g.href=m,g.download=h,g.click(),setTimeout(()=>URL.revokeObjectURL(m),1e4)}async function f(){if(a)return;const c=t.value;if(!c||c.pages.length===0)return;a=!0,p();const h=me(c);l=document.createElement("iframe"),l.style.cssText="position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;",document.body.appendChild(l);const m=l;try{const g=m.contentDocument;g.open(),g.write(h);for(let E=0;E<c.pages.length;E++)if(g.write(pe(c.pages[E])),E%ee===ee-1&&await te(),m!==l)return;g.write("</body></html>"),g.close(),await te(),m.contentWindow?.focus(),m.contentWindow?.print()}catch{n.onError("调用打印失败,请改用导出 PDF")}finally{a=!1}}function d(c){if(o?.plan===c)return o.promise;const h=n.getPdfExporter()(c,n.onWarning).finally(()=>{o?.promise===h&&(o=null)});return o={plan:c,promise:h},h}async function v(){const c=t.value;if(!c||c.pages.length===0)return;if(r?.plan===c)return r.promise;n.onBusy?.("PDF");const h={},m=(async()=>{try{const g=await d(c);if(t.value!==c)return;u(new Blob([g],{type:"application/pdf"}),"mach-report.pdf")}catch(g){n.onError(g instanceof Error?`PDF 导出失败: ${g.message}`:"PDF 导出失败","pdf")}finally{n.onBusy?.(null),r?.token===h&&(r=null)}})();return r={plan:c,promise:m,token:h},m}async function b(){const c=t.value;if(!(!c||c.pages.length===0)){n.onBusy?.("Excel");try{const{renderPlanToXlsx:h}=await import("@agile-team/mach-report/xlsx"),{buffer:m,warnings:g}=await h(c);if(t.value!==c)return;g.length>0&&n.onWarning?.(`Excel 有 ${g.length} 处内容未导出:${g.slice(0,2).join(";")}`),u(new Blob([m],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}),"mach-report.xlsx")}catch(h){n.onError(h instanceof Error?`Excel 导出失败: ${h.message}`:"Excel 导出失败","export")}finally{n.onBusy?.(null)}}}async function w(){const c=t.value;if(!c||c.pages.length===0)return;if(i?.plan===c)return i.promise;n.onBusy?.("图片");const h={},m=(async()=>{try{const{blobs:g}=await H.renderPlanToImages(c,{dpr:Math.min(2,typeof devicePixelRatio=="number"?devicePixelRatio:1)});if(t.value!==c)return;g.forEach((E,$)=>{u(E,g.length>1?`mach-report-page-${$+1}.png`:"mach-report.png")})}catch(g){n.onError(g instanceof Error?`图片导出失败: ${g.message}`:"图片导出失败","export")}finally{n.onBusy?.(null),i?.token===h&&(i=null)}})();return i={plan:c,promise:m,token:h},m}function k(){const c=t.value;if(!(!c||c.pages.length===0))try{const{html:h,filename:m}=Me(c);u(new Blob([h],{type:"application/msword;charset=utf-8"}),m)}catch(h){n.onError(h instanceof Error?`Word 导出失败: ${h.message}`:"Word 导出失败","export")}}function C(c){const h=t.value;if(!h||h.pages.length===0)return;if(c==="pdf"){v();return}if(c==="xlsx"||c==="excel"){b();return}if(c==="png"||c==="image"){w();return}if(c==="word"||c==="doc"){k();return}if(c!=="html"){n.onError(`不支持的导出格式:${c}`,"export");return}const{head:m,pageChunks:g}=fe(h),E=`${m}${g.join("")}</body></html>`;u(new Blob([E],{type:"text/html;charset=utf-8"}),"mach-report.html")}function M(){const c=t.value;if(!c||c.pages.length===0)return;const h=window.open("","_blank");if(!h){n.onError("浏览器拦截了弹窗,请允许弹窗后重试");return}d(c).then(m=>{if(t.value!==c){h.close();return}const g=URL.createObjectURL(new Blob([m],{type:"application/pdf"})),E=h.document;E.title="PDF 预览",E.documentElement.style.height="100%",E.body.style.cssText="margin:0;height:100%;";const $=E.createElement("iframe");$.title="PDF 预览",$.style.cssText="display:block;width:100%;height:100%;border:0;",$.src=g,E.body.replaceChildren($),setTimeout(()=>URL.revokeObjectURL(g),6e4)}).catch(m=>{h.close(),n.onError(m instanceof Error?`PDF 预览失败: ${m.message}`:"PDF 预览失败","pdf")})}return{print:f,exportAs:C,exportImages:w,exportWord:k,openPdfWindow:M,releasePrintFrame:p}}const Ne="mrp-hit";function ft(t){t.querySelectorAll(`mark.${Ne}`).forEach(l=>{const a=l.parentNode;if(a){for(;l.firstChild;)a.insertBefore(l.firstChild,l);l.remove(),a.normalize()}})}function gt(t,n){const l=n.trim();if(!l)return 0;const a=l.toLowerCase(),o=document.createTreeWalker(t,NodeFilter.SHOW_TEXT,{acceptNode(p){const u=p.parentElement;return!u||u.closest("mark")||/^(SCRIPT|STYLE)$/.test(u.tagName)?NodeFilter.FILTER_REJECT:(p.nodeValue??"").toLowerCase().includes(a)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT}}),r=[];for(let p=o.nextNode();p;p=o.nextNode())r.push(p);let i=0;for(const p of r){const u=p.nodeValue??"",f=u.toLowerCase(),d=p.parentElement;if(!d)continue;const v=document.createDocumentFragment();let b=0,w=f.indexOf(a);for(;w>=0;){w>b&&v.appendChild(document.createTextNode(u.slice(b,w)));const k=document.createElement("mark");k.className=Ne,k.textContent=u.slice(w,w+l.length),v.appendChild(k),i++,b=w+l.length,w=f.indexOf(a,b)}b<u.length&&v.appendChild(document.createTextNode(u.slice(b))),d.replaceChild(v,p)}return i}function $e(t,n){let l=0,a=t.toLowerCase().indexOf(n);for(;a>=0;)l++,a=t.toLowerCase().indexOf(n,a+n.length);return l}function vt(t){const{plan:n,gotoPage:l,highlight:a,clearHighlights:o}=t,r=t.debounceMs??200,i=e.ref(!1),p=e.ref(""),u=e.ref(""),f=e.ref(0);let d=null;const v=e.computed(()=>{const m=p.value.trim().toLowerCase(),g=n.value;if(!m||!g)return[];const E=[];return g.pages.forEach(($,G)=>{for(const D of $.components)if(D.grid){for(const I of D.grid.cells??[])for(const A of I??[])if(typeof A?.text=="string")for(let Z=0;Z<$e(A.text,m);Z++)E.push(G)}else if(D.kind==="text"&&typeof D.text=="string")for(let I=0;I<$e(D.text,m);I++)E.push(G)}),E}),b=e.computed(()=>v.value.length);function w(m){if(u.value=m,d&&clearTimeout(d),m.trim()===""){d=null,p.value="",f.value=0;return}d=setTimeout(()=>{d=null,p.value=u.value,f.value=0;const g=v.value[0];g!=null&&l(g+1)},r)}function k(m){const g=v.value.length;g!==0&&(f.value=(f.value+m+g)%g,l(v.value[f.value]+1))}function C(){i.value=!i.value}function M(m){const g=p.value.trim();g&&a(m,g)}function c(m){o(m)}function h(){u.value="",p.value="",f.value=0,d&&clearTimeout(d),d=null}return{visible:i,query:p,matchIndex:f,matchCount:b,toggle:C,onInput:w,onNav:k,apply:M,clear:c,reset:h}}function ht(t,n){const l=e.computed(()=>{if(t.value)return!0;if(typeof location>"u")return!1;try{return new URLSearchParams(location.search).get("mrp-debug")==="1"}catch{return!1}}),a=e.computed(()=>!l.value||!n.plan.value?0:Math.round(JSON.stringify(n.plan.value).length/1024)),o=e.computed(()=>!l.value||!n.plan.value?null:{pages:n.pageCount.value,window:`${n.windowRange.value.start}-${n.windowRange.value.end}`,zoom:`${Math.round(n.zoom.value*100)}%`,loadMs:`${n.loadMs.value}ms`,planKB:a.value});return{enabled:l,debugStats:o}}function yt(t,n){const{thumbsRoot:l,visible:a,renderThumbCanvas:o}=n;let r=null;function i(f,d){if(!t.value||f.childElementCount>0)return;const v=o(d);v&&(v.style.width="100%",v.style.height="100%",v.style.display="block",f.appendChild(v))}return{schedule:()=>{!a.value||!t.value||!l.value||typeof IntersectionObserver>"u"||(r?.disconnect(),r=new IntersectionObserver(f=>{for(const d of f){if(!d.isIntersecting)continue;const v=d.target;i(v,Number(v.dataset.thumb??1)-1),r?.unobserve(v)}},{root:l.value,rootMargin:"200px"}),l.value.querySelectorAll("[data-thumb]").forEach(f=>{r.observe(f)}))},destroy:()=>{r?.disconnect(),r=null}}}function wt(){const t=e.shallowRef(0);return{loadMs:t,start(){return typeof performance<"u"?performance.now():0},end(n){t.value=n?Math.round(performance.now()-n):0}}}const bt={class:"mrp-toolbar"},Et={class:"mrp-title"},Pt=["disabled"],xt={class:"mrp-pageinfo"},kt=["disabled"],Ct={key:1,class:"mrp-search"},$t=["placeholder","value"],Bt={key:0,class:"mrp-search-count"},Rt=["disabled"],St=["disabled"],Mt=e.defineComponent({__name:"ReportToolbar",props:{pageCount:{},currentPage:{},zoomMode:{},zoom:{},showExport:{type:Boolean},showPrint:{type:Boolean},showPdfWindow:{type:Boolean},messages:{},search:{},thumbsVisible:{type:Boolean}},emits:["goto","zoom","export","print","pdf-window","search-input","search-nav","search-toggle","thumbs-toggle"],setup(t){const n=t,l=e.ref(null);e.watch(()=>n.search.visible,o=>{o&&e.nextTick(()=>l.value?.focus())});function a(o,r,i){return o.replace("{cur}",String(r)).replace("{total}",String(i))}return(o,r)=>(e.openBlock(),e.createElementBlock("div",bt,[e.createElementVNode("span",Et,e.toDisplayString(t.messages.title),1),t.pageCount>0?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("button",{class:"mrp-nav",type:"button",disabled:t.currentPage<=1,onClick:r[0]||(r[0]=i=>o.$emit("goto",t.currentPage-1))},e.toDisplayString(t.messages.prevPage),9,Pt),e.createElementVNode("span",xt,e.toDisplayString(a(t.messages.pageInfo,t.currentPage,t.pageCount)),1),e.createElementVNode("button",{class:"mrp-nav",type:"button",disabled:t.currentPage>=t.pageCount,onClick:r[1]||(r[1]=i=>o.$emit("goto",t.currentPage+1))},e.toDisplayString(t.messages.nextPage),9,kt)],64)):e.createCommentVNode("",!0),r[17]||(r[17]=e.createElementVNode("span",{class:"mrp-spacer"},null,-1)),t.search.visible?(e.openBlock(),e.createElementBlock("div",Ct,[e.createElementVNode("input",{ref_key:"searchInputRef",ref:l,class:"mrp-search-input",type:"text",placeholder:t.messages.searchPlaceholder,value:t.search.query,onInput:r[2]||(r[2]=i=>o.$emit("search-input",i.target.value))},null,40,$t),t.search.query?(e.openBlock(),e.createElementBlock("span",Bt,e.toDisplayString(a(t.messages.matchInfo,t.search.matchIndex+1,t.search.matchCount)),1)):e.createCommentVNode("",!0),e.createElementVNode("button",{class:"mrp-nav",type:"button",disabled:t.search.matchCount===0,onClick:r[3]||(r[3]=i=>o.$emit("search-nav",-1))},e.toDisplayString(t.messages.prevMatch),9,Rt),e.createElementVNode("button",{class:"mrp-nav",type:"button",disabled:t.search.matchCount===0,onClick:r[4]||(r[4]=i=>o.$emit("search-nav",1))},e.toDisplayString(t.messages.nextMatch),9,St)])):e.createCommentVNode("",!0),e.createElementVNode("button",{class:e.normalizeClass(["mrp-nav",{"mrp-active":t.search.visible}]),type:"button",title:"Ctrl+F",onClick:r[5]||(r[5]=i=>o.$emit("search-toggle"))}," 🔍 ",2),e.createElementVNode("button",{class:e.normalizeClass(["mrp-nav",{"mrp-active":t.thumbsVisible}]),type:"button",onClick:r[6]||(r[6]=i=>o.$emit("thumbs-toggle"))}," ▦ "+e.toDisplayString(t.messages.thumbnails),3),e.createElementVNode("button",{class:e.normalizeClass(["mrp-nav",{"mrp-active":t.zoomMode==="fit"}]),type:"button",onClick:r[7]||(r[7]=i=>o.$emit("zoom","fit"))},e.toDisplayString(t.messages.fitWidth),3),e.createElementVNode("button",{class:e.normalizeClass(["mrp-nav",{"mrp-active":t.zoomMode==="raw"&&Math.round(t.zoom*100)===100}]),type:"button",onClick:r[8]||(r[8]=i=>o.$emit("zoom",100))}," 100% ",2),e.createElementVNode("button",{class:e.normalizeClass(["mrp-nav",{"mrp-active":t.zoomMode==="raw"&&Math.round(t.zoom*100)===150}]),type:"button",onClick:r[9]||(r[9]=i=>o.$emit("zoom",150))}," 150% ",2),t.showExport?(e.openBlock(),e.createElementBlock("button",{key:2,class:"mrp-nav",type:"button",onClick:r[10]||(r[10]=i=>o.$emit("export","html"))},e.toDisplayString(t.messages.exportHtml),1)):e.createCommentVNode("",!0),t.showExport?(e.openBlock(),e.createElementBlock("button",{key:3,class:"mrp-nav",type:"button",onClick:r[11]||(r[11]=i=>o.$emit("export","pdf"))},e.toDisplayString(t.messages.exportPdf),1)):e.createCommentVNode("",!0),t.showExport?(e.openBlock(),e.createElementBlock("button",{key:4,class:"mrp-nav",type:"button",onClick:r[12]||(r[12]=i=>o.$emit("export","xlsx"))},e.toDisplayString(t.messages.exportExcel),1)):e.createCommentVNode("",!0),t.showExport?(e.openBlock(),e.createElementBlock("button",{key:5,class:"mrp-nav",type:"button",onClick:r[13]||(r[13]=i=>o.$emit("export","png"))},e.toDisplayString(t.messages.exportImage),1)):e.createCommentVNode("",!0),t.showExport?(e.openBlock(),e.createElementBlock("button",{key:6,class:"mrp-nav",type:"button",onClick:r[14]||(r[14]=i=>o.$emit("export","word"))},e.toDisplayString(t.messages.exportWord),1)):e.createCommentVNode("",!0),t.showPrint?(e.openBlock(),e.createElementBlock("button",{key:7,class:"mrp-nav",type:"button",onClick:r[15]||(r[15]=i=>o.$emit("print"))},e.toDisplayString(t.messages.print),1)):e.createCommentVNode("",!0),t.showPdfWindow?(e.openBlock(),e.createElementBlock("button",{key:8,class:"mrp-nav",type:"button",onClick:r[16]||(r[16]=i=>o.$emit("pdf-window"))},e.toDisplayString(t.messages.pdfWindow),1)):e.createCommentVNode("",!0)]))}}),ge=(t,n)=>{const l=t.__vccOpts||t;for(const[a,o]of n)l[a]=o;return l},De=ge(Mt,[["__scopeId","data-v-48cc0980"]]),Tt={class:"mrp-params"},Nt={class:"mrp-params-title"},Dt={class:"mrp-params-grid"},Vt={class:"mrp-param-label"},Ft={key:0,class:"mrp-param-star"},zt=["value","onChange"],It={value:"",disabled:"",hidden:""},Wt=["value"],Lt=["type","placeholder","value","onInput"],Ht={class:"mrp-params-actions"},Ot=e.defineComponent({__name:"ReportParamPanel",props:{defs:{},modelValue:{},messages:{},attempted:{type:Boolean}},emits:["update:modelValue","query","reset"],setup(t,{emit:n}){const l=t,a=n,o=e.ref({...l.modelValue});e.watch(()=>l.modelValue,u=>{o.value={...u}});const r=e.computed(()=>l.defs.map(u=>({def:u,label:u.label??u.field,value:o.value[u.field]??""})));function i(u,f){o.value={...o.value,[u]:f},a("update:modelValue",{...o.value})}function p(u){const f=l.defs.find(d=>d.field===u);return l.attempted&&f?.required===!0&&!(o.value[u]??"").trim()}return(u,f)=>(e.openBlock(),e.createElementBlock("div",Tt,[e.createElementVNode("span",Nt,e.toDisplayString(t.messages.paramsTitle),1),e.createElementVNode("div",Dt,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(r.value,d=>(e.openBlock(),e.createElementBlock("label",{key:d.def.field,class:e.normalizeClass(["mrp-param",{"mrp-param-missing":p(d.def.field)}])},[e.createElementVNode("span",Vt,[e.createTextVNode(e.toDisplayString(d.label),1),d.def.required?(e.openBlock(),e.createElementBlock("i",Ft,"*")):e.createCommentVNode("",!0)]),(d.def.type??"text")==="select"?(e.openBlock(),e.createElementBlock("select",{key:0,class:"mrp-param-input",value:d.value,onChange:v=>i(d.def.field,v.target.value),onKeydown:f[0]||(f[0]=e.withKeys(v=>u.$emit("query"),["enter"]))},[e.createElementVNode("option",It,e.toDisplayString(d.def.placeholder??`请选择${d.label}`),1),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(d.def.options??[],v=>(e.openBlock(),e.createElementBlock("option",{key:v.value,value:v.value},e.toDisplayString(v.label),9,Wt))),128))],40,zt)):(e.openBlock(),e.createElementBlock("input",{key:1,class:"mrp-param-input",type:d.def.type==="number"?"number":d.def.type==="date"?"date":"text",placeholder:d.def.placeholder??`请输入${d.label}`,value:d.value,onInput:v=>i(d.def.field,v.target.value),onKeydown:f[1]||(f[1]=e.withKeys(v=>u.$emit("query"),["enter"]))},null,40,Lt))],2))),128))]),e.createElementVNode("div",Ht,[e.createElementVNode("button",{class:"mrp-nav mrp-param-query",type:"button",onClick:f[2]||(f[2]=d=>u.$emit("query"))},e.toDisplayString(t.messages.query),1),e.createElementVNode("button",{class:"mrp-nav",type:"button",onClick:f[3]||(f[3]=d=>u.$emit("reset"))},e.toDisplayString(t.messages.reset),1)])]))}}),Ve=ge(Ot,[["__scopeId","data-v-aafce92d"]]),Fe={title:"报表预览",prevPage:"‹ 上一页",nextPage:"下一页 ›",pageInfo:"{cur} / {total}",fitWidth:"适宽",exportHtml:"导出 HTML",exportPdf:"导出 PDF",exportExcel:"导出 Excel",exportImage:"导出图片",exportWord:"导出 Word",exporting:"正在生成 {format}…",print:"打印",pdfWindow:"PDF 窗口",loading:"报表渲染中…",empty:"暂无预览数据",errorPrefix:"",retry:"重试",searchPlaceholder:"搜索报表内容",matchInfo:"{cur}/{total}",prevMatch:"‹",nextMatch:"›",thumbnails:"缩略图",paramsTitle:"查询条件",query:"查 询",reset:"重 置",paramRequired:"请填写{label}"},ze={shellBg:"#525659",shellFg:"#e8e8e8",toolbarBg:"#323639",toolbarBorder:"#22252a",toolbarFg:"#e8e8e8",btnFg:"#cfcfcf",btnBorder:"#4a4d52",btnHoverBg:"#414549",btnHoverFg:"#ffffff",btnActiveBg:"#2d5fb8"};function At(t){return t}function qt(t){return t}const z={showExport:!0,showPrint:!0,showPdfWindow:!0,showParams:!0,gapPx:18,pdfFontUrl:"/simhei.ttf",logger:console},Ut={warn:()=>{},info:()=>{}};function Ie(t,n){const l=n?t?.presets?.[n]:t?.defaultPreset?t?.presets?.[t.defaultPreset]:void 0,a={...t?.defaults,...l};return{showExport:a.showExport??z.showExport,showPrint:a.showPrint??z.showPrint,showPdfWindow:a.showPdfWindow??z.showPdfWindow,showParams:a.showParams??z.showParams,gapPx:a.gapPx??z.gapPx,pdfFontUrl:a.pdfFontUrl??z.pdfFontUrl,theme:{...ze,...a.theme},messages:{...Fe,...a.messages},logger:a.logger??z.logger}}function We(t){const n={};return t.shellBg!=null&&(n["--mrp-shell-bg"]=t.shellBg),t.shellFg!=null&&(n["--mrp-shell-fg"]=t.shellFg),t.toolbarBg!=null&&(n["--mrp-toolbar-bg"]=t.toolbarBg),t.toolbarBorder!=null&&(n["--mrp-toolbar-border"]=t.toolbarBorder),t.toolbarFg!=null&&(n["--mrp-toolbar-fg"]=t.toolbarFg),t.btnFg!=null&&(n["--mrp-btn-fg"]=t.btnFg),t.btnBorder!=null&&(n["--mrp-btn-border"]=t.btnBorder),t.btnHoverBg!=null&&(n["--mrp-btn-hover-bg"]=t.btnHoverBg),t.btnHoverFg!=null&&(n["--mrp-btn-hover-fg"]=t.btnHoverFg),t.btnActiveBg!=null&&(n["--mrp-btn-active-bg"]=t.btnActiveBg),n}function jt(t){const n=e.inject(O.MACH_REPORT_CONFIG_KEY,null),l=e.computed(()=>{const a=n?.value??null,o="defaults"in t&&"presets"in t?t:{defaults:t,presets:{}};return a?{defaults:{...a.defaults,...o.defaults},presets:{...a.presets,...o.presets},defaultPreset:o.defaultPreset??a.defaultPreset}:o});e.provide(O.MACH_REPORT_CONFIG_KEY,l)}function Le(){return e.inject(O.MACH_REPORT_CONFIG_KEY,e.computed(()=>null))}function He(t={fontUrl:"/simhei.ttf"}){let n=null;return async(l,a)=>{n||(n=await import("@agile-team/mach-report/pdf"));const o=t.fontUrl?await n.loadFontWithCache(t.fontUrl):null,{bytes:r,unsupportedTextCount:i,pageErrors:p,fidelityWarnings:u}=await n.renderPlanToPdf(l,o?{customFontBytes:o}:{});if(i>0)throw new Error(`PDF 中有 ${i} 行文字无法编码;请部署支持所用文字的字体并配置 pdfFontUrl`);if(p.length>0)throw new Error(`PDF 有 ${p.length} 页渲染失败:${p[0]}`);return u.length>0&&a?.(`PDF 有 ${u.length} 处版式降级:${u.slice(0,2).join(";")}`),r}}class K extends Error{constructor(n,l,a){super(l),this.name="MachReportError",this.code=n,this.cause=a}}function Oe(t){return t instanceof K?{code:t.code,cause:t.cause}:{code:"render",cause:t}}const Kt={class:"mrp-main"},Gt={key:0,class:"mrp-state"},Zt={key:1,class:"mrp-state mrp-error"},Yt={key:2,class:"mrp-state"},Jt=["data-page"],Xt=["onClick"],Qt=["data-thumb"],_t={class:"mrp-thumb-no"},en={class:"mrp-overlay"},tn={key:2,class:"mrp-debug","aria-hidden":"true"},X=96/25.4,Be="mach-report:ui",nn=e.defineComponent({__name:"ReportPreview",props:{reportId:{type:[String,Array],default:null},params:{type:Object,default:()=>({})},height:{type:String,default:"100vh"},autoLoad:{type:Boolean,default:!0},showExport:{type:Boolean,default:void 0},showPrint:{type:Boolean,default:void 0},showPdfWindow:{type:Boolean,default:void 0},gapPx:{type:Number,default:void 0},messages:{type:Object,default:void 0},preset:{type:String,default:void 0},debug:{type:Boolean,default:!1},paramDefs:{type:Array,default:void 0},showParams:{type:Boolean,default:void 0},fetcher:{type:Function,default:null}},emits:["loaded","error","warning"],setup(t,{expose:n,emit:l}){e.useCssVars(s=>({v0e7a3c30:C.value+"px"}));const a=t,o=l,r=e.shallowRef(null),i=e.ref(!1),p=e.ref(""),u=e.ref(null),f=e.ref(1),d=e.ref(null),v=e.ref(null),b=e.ref(null),w=e.ref(!1),k=wt(),C=e.computed(()=>Math.max(0,A.value)),M=e.inject(O.MACH_REPORT_FETCHER_KEY,null),c=e.inject(O.MACH_REPORT_PDF_EXPORTER_KEY,null),h=e.computed(()=>de(a.reportId)),m=e.computed(()=>r.value?.pages.length??0),g=Le(),E=e.computed(()=>Ie(g.value,a.preset)),$=e.computed(()=>({...E.value.messages,...a.messages})),G=e.computed(()=>a.showExport??E.value.showExport),D=e.computed(()=>a.showPrint??E.value.showPrint),I=e.computed(()=>a.showPdfWindow??E.value.showPdfWindow),A=e.computed(()=>a.gapPx??E.value.gapPx),Z=e.computed(()=>a.showParams??E.value.showParams);let ve=null,ne=null;function qe(){if(c)return c;const s=E.value.pdfFontUrl;return(!ne||ve!==s)&&(ve=s,ne=He({fontUrl:s})),ne}const V=e.computed(()=>a.paramDefs??[]),F=e.ref({}),oe=e.ref(!1);function Y(s){const y={};for(const P of s)y[P.field]=a.params[P.field]??P.defaultValue??"";F.value=y,oe.value=!1}Y(V.value),e.watch(V,s=>Y(s)),e.watch(()=>JSON.stringify(a.params),()=>Y(V.value));const Ue=e.computed(()=>{const s={...a.params};for(const[y,P]of Object.entries(F.value))P===""?delete s[y]:s[y]=P;return s});function je(){return V.value.filter(s=>s.required===!0&&!(F.value[s.field]??"").trim())}function Ke(){oe.value=!0;const s=je();if(s.length>0){const y=s[0].label??s[0].field,P=$.value.paramRequired.replace("{label}",y);p.value=P,o("error",P,{code:"param"});return}N()}function Ge(){Y(V.value)}const Ze=e.computed(()=>({height:a.height,...We(E.value.theme)})),{zoom:S,zoomMode:W,applyFitZoom:he,setZoom:re}=Se(()=>({viewport:v.value,pageWidthPx:(r.value?.pages[0]?.pageWidthMm??210)*X})),Ye=Re(r,S,{pxPerMm:X,gapPx:A}),{contentSize:ae,windowRange:q,visiblePages:Je,makeScrollHandler:Xe,refreshViewport:ye}=Ye,Qe=Xe(f,m);function le(s){W.value="raw",S.value=Math.min(3,Math.max(.3,s))}function se(){we(),r.value=null,f.value=1,B.reset()}let J=0;async function N(){const s=++J,y=a.fetcher??M;if(h.value.length===0){p.value="缺少报表 ID",se(),o("error",p.value,{code:"param"});return}if(!y){p.value="未提供渲染数据源 fetcher",se(),o("error",p.value,{code:"config"});return}i.value=!0,p.value="",u.value=null,se();const P=k.start();try{const x=await y({reportIds:h.value,params:{...Ue.value}});if(s!==J)return;const R=H.validateRenderPlan(x);if(!R.ok){const U=R.errors.slice(0,3).map(j=>`${j.path}: ${j.message}`).join("; ");throw new K("validate",`渲染计划校验失败(${R.errors.length} 处): ${U}`)}R.warnings.length>0&&E.value.logger.warn("[mach-report] 渲染计划告警:",R.warnings),r.value=x,f.value=1,k.end(P),v.value&&(v.value.scrollTop=0),W.value==="fit"&&he(),o("loaded",x.pages.length)}catch(x){if(s!==J)return;const R=x instanceof K?x:new K("fetch",x instanceof Error?x.message:"预览加载失败",x);p.value=R.message,o("error",R.message,Oe(R))}finally{s===J&&(i.value=!1)}}function T(s){if(m.value<=0)return;const y=Math.max(1,Math.min(m.value,s));f.value=y;const P=v.value;if(!P)return;let x=0;for(let R=0;R<y-1;R++)x+=(r.value?.pages[R]?.pageHeightMm??0)*X+C.value;P.scrollTop=x*S.value}const{print:ie,exportAs:ue,openPdfWindow:ce,releasePrintFrame:we}=Te(r,{getPdfExporter:qe,onError:(s,y)=>{u.value={kind:"error",message:s},o("error",s,{code:y??"print"})},onWarning:s=>{u.value={kind:"warning",message:s},o("warning",s)},onBusy:s=>{s?u.value={kind:"progress",message:$.value.exporting.replace("{format}",s)}:u.value?.kind==="progress"&&(u.value=null)}});function be(s,y={}){F.value={...F.value,...s},y.reload!==!1&&N()}const _e={reload:N,print:ie,exportAs:ue,openPdfWindow:ce,gotoPage:T,setParams:be};e.provide(O.MACH_REPORT_CONTROLLER_KEY,_e);const B=vt({plan:r,gotoPage:T,highlight:gt,clearHighlights:ft});function et(s){s.ctrlKey&&(s.preventDefault(),le(S.value*(s.deltaY<0?1.1:1/1.1)))}function tt(s){if((s.ctrlKey||s.metaKey)&&s.key.toLowerCase()==="f"){s.preventDefault(),B.visible.value||B.toggle();return}switch(s.key){case"PageDown":s.preventDefault(),T(f.value+1);break;case"PageUp":s.preventDefault(),T(f.value-1);break;case"Home":s.preventDefault(),T(1);break;case"End":s.preventDefault(),T(m.value);break;case"+":case"=":s.preventDefault(),le(S.value*1.1);break;case"-":s.preventDefault(),le(S.value/1.1);break}}function nt(){try{localStorage.setItem(Be,JSON.stringify({zoomMode:W.value==="fit"?"fit":Math.round(S.value*100)}))}catch{}}e.watch([W,S],nt),e.watchEffect(()=>{const s=r.value;if(!s)return;const y=d.value;if(!y)return;y.querySelectorAll(".mrp-page-holder").forEach(x=>{const R=Number(x.dataset.page??0)-1,U=s.pages[R];if(!U||x.childElementCount>0){if(x.firstElementChild){const xe=x.firstElementChild;B.clear(xe),B.apply(xe)}return}x.style.width=`${U.pageWidthMm*X}px`;const j=H.renderPage(U,96,{},document);B.apply(j),x.appendChild(j)})},{flush:"post"}),e.watch(()=>B.query.value,s=>{s||d.value?.querySelectorAll(".mrp-page-holder").forEach(y=>{B.clear(y)})});const Ee=yt(r,{thumbsRoot:b,visible:w,renderThumbCanvas:s=>{try{const{canvases:y}=H.renderPlanToCanvas(r.value,{start:s,end:s,dpr:.2});return y[0]??null}catch{return null}}});e.watchEffect(()=>{Ee.schedule()},{flush:"post"});const ot=e.computed(()=>a.debug),{debugStats:L}=ht(ot,{plan:r,pageCount:m,windowRange:q,zoom:S,loadMs:k.loadMs});function Pe(){ye(v.value),W.value==="fit"&&he()}function rt(){try{const s=JSON.parse(localStorage.getItem(Be)??"{}");s.zoomMode==="fit"?re("fit"):typeof s.zoomMode=="number"&&re(s.zoomMode)}catch{}}return e.onMounted(()=>{window.addEventListener("resize",Pe),ye(v.value),rt(),a.autoLoad&&N()}),e.onUnmounted(()=>{window.removeEventListener("resize",Pe),Ee.destroy(),B.reset(),we()}),e.watch(()=>[a.reportId,JSON.stringify(a.params)],()=>{a.autoLoad&&N()}),e.watch(()=>a.fetcher??M,()=>{a.autoLoad&&N()}),n({reload:N,print:ie,exportAs:ue,openPdfWindow:ce,gotoPage:T,setParams:be}),(s,y)=>(e.openBlock(),e.createElementBlock("div",{class:"mach-report-preview",style:e.normalizeStyle(Ze.value)},[Z.value&&V.value.length>0?(e.openBlock(),e.createBlock(Ve,{key:0,defs:V.value,modelValue:F.value,"onUpdate:modelValue":y[0]||(y[0]=P=>F.value=P),messages:$.value,attempted:oe.value,onQuery:Ke,onReset:Ge},null,8,["defs","modelValue","messages","attempted"])):e.createCommentVNode("",!0),e.createVNode(De,{"page-count":m.value,"current-page":f.value,"zoom-mode":e.unref(W),zoom:e.unref(S),"show-export":G.value,"show-print":D.value,"show-pdf-window":I.value,messages:$.value,search:{visible:e.unref(B).visible.value,query:e.unref(B).query.value,matchIndex:e.unref(B).matchIndex.value,matchCount:e.unref(B).matchCount.value},"thumbs-visible":w.value,onGoto:T,onZoom:e.unref(re),onExport:y[1]||(y[1]=P=>e.unref(ue)(P)),onPrint:e.unref(ie),onPdfWindow:e.unref(ce),onSearchInput:e.unref(B).onInput,onSearchNav:e.unref(B).onNav,onSearchToggle:e.unref(B).toggle,onThumbsToggle:y[2]||(y[2]=P=>w.value=!w.value)},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"]),u.value?(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(["mrp-export-notice",`mrp-export-${u.value.kind}`]),role:"alert"},e.toDisplayString(u.value.message),3)):e.createCommentVNode("",!0),e.createElementVNode("div",Kt,[e.createElementVNode("div",{ref_key:"viewportRef",ref:v,class:"mrp-body",tabindex:"0",onWheel:et,onKeydown:tt,onScrollPassive:y[3]||(y[3]=P=>e.unref(Qe)(P.target))},[i.value?(e.openBlock(),e.createElementBlock("div",Gt,e.toDisplayString($.value.loading),1)):p.value?(e.openBlock(),e.createElementBlock("div",Zt,[e.createTextVNode(e.toDisplayString(p.value)+" ",1),e.createElementVNode("button",{class:"mrp-retry",type:"button",onClick:N},e.toDisplayString($.value.retry),1)])):!r.value||m.value===0?(e.openBlock(),e.createElementBlock("div",Yt,e.toDisplayString($.value.empty),1)):(e.openBlock(),e.createElementBlock("div",{key:3,class:"mrp-scale",style:e.normalizeStyle({width:`${e.unref(ae).w*e.unref(S)}px`,height:`${e.unref(ae).h*e.unref(S)}px`})},[e.createElementVNode("div",{ref_key:"containerRef",ref:d,class:"mrp-scale-inner",style:e.normalizeStyle({transform:`scale(${e.unref(S)})`,transformOrigin:"top left",width:`${e.unref(ae).w}px`})},[e.unref(q).padTopPx>0?(e.openBlock(),e.createElementBlock("div",{key:0,class:"mrp-spacer-top",style:e.normalizeStyle({height:`${e.unref(q).padTopPx}px`}),"aria-hidden":"true"},null,4)):e.createCommentVNode("",!0),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(Je),P=>(e.openBlock(),e.createElementBlock("div",{key:P.index,class:"mrp-page-holder","data-page":P.index+1},null,8,Jt))),128)),e.unref(q).padBottomPx>0?(e.openBlock(),e.createElementBlock("div",{key:1,class:"mrp-spacer-bottom",style:e.normalizeStyle({height:`${e.unref(q).padBottomPx}px`}),"aria-hidden":"true"},null,4)):e.createCommentVNode("",!0)],4)],4))],544),w.value&&m.value>0?(e.openBlock(),e.createElementBlock("aside",{key:0,ref_key:"thumbsRef",ref:b,class:"mrp-thumbs"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(r.value?.pages??[],(P,x)=>(e.openBlock(),e.createElementBlock("div",{key:x,class:e.normalizeClass(["mrp-thumb",{"mrp-thumb-active":x+1===f.value}]),onClick:R=>T(x+1)},[e.createElementVNode("div",{class:"mrp-thumb-box","data-thumb":x+1,style:e.normalizeStyle({height:`${Math.round(P.pageHeightMm/P.pageWidthMm*116)}px`})},null,12,Qt),e.createElementVNode("span",_t,e.toDisplayString(x+1),1)],10,Xt))),128))],512)):e.createCommentVNode("",!0)]),e.createElementVNode("div",en,[e.renderSlot(s.$slots,"default",{},void 0,!0)]),e.unref(L)?(e.openBlock(),e.createElementBlock("div",tn,[y[4]||(y[4]=e.createElementVNode("div",null,"mach-report debug",-1)),e.createElementVNode("div",null,"pages: "+e.toDisplayString(e.unref(L).pages)+" | window: ["+e.toDisplayString(e.unref(L).window)+"]",1),e.createElementVNode("div",null,"zoom: "+e.toDisplayString(e.unref(L).zoom)+" | load: "+e.toDisplayString(e.unref(L).loadMs),1),e.createElementVNode("div",null,"plan: "+e.toDisplayString(e.unref(L).planKB)+"KB",1)])):e.createCommentVNode("",!0)],4))}}),Ae=ge(nn,[["__scopeId","data-v-249dbb78"]]),on=Object.freeze(Object.defineProperty({__proto__:null,default:Ae},Symbol.toStringTag,{value:"Module"}));exports.DEFAULT_MESSAGES=Fe;exports.DEFAULT_THEME=ze;exports.MachReportError=K;exports.PlanLoadError=Q;exports.ReportParamPanel=Ve;exports.ReportPreview=Ae;exports.ReportPreview$1=on;exports.ReportToolbar=De;exports.SILENT_LOGGER=Ut;exports.buildPrintDocument=fe;exports.buildWordHtml=Me;exports.createDefaultPdfExporter=He;exports.createFetchRequest=mt;exports.defineMachReportConfig=At;exports.defineMachReportPreset=qt;exports.joinReportIds=dt;exports.normalizeReportIds=de;exports.printPlans=pt;exports.provideMachReportConfig=jt;exports.resolveConfig=Ie;exports.themeToCssVars=We;exports.toErrorDetail=Oe;exports.useMachReportConfig=Le;exports.usePageWindow=Re;exports.usePrintExport=Te;exports.useZoom=Se;
|