@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.
Files changed (45) hide show
  1. package/README.md +86 -255
  2. package/dist/ReportPreview-Cr0IH1Rz.cjs +6 -0
  3. package/dist/ReportPreview-DwknBgsJ.js +1266 -0
  4. package/dist/defaults.d.ts +3 -7
  5. package/dist/format.d.ts +1 -1
  6. package/dist/index.cjs +5 -5
  7. package/dist/index.d.cts +0 -1
  8. package/dist/index.d.ts +0 -1
  9. package/dist/index.js +621 -758
  10. package/dist/layout/textwrap.d.ts +1 -1
  11. package/dist/pdf.cjs +1 -1
  12. package/dist/pdf.js +1 -1
  13. package/dist/plugin-Cj3c2wJc.cjs +1 -0
  14. package/dist/plugin-DJf_6_fl.js +18 -0
  15. package/dist/schema/render-plan.d.ts +1 -9
  16. package/dist/sql/expr.d.ts +3 -3
  17. package/dist/sql.d.cts +1 -1
  18. package/dist/sql.d.ts +1 -1
  19. package/dist/style-CFZ-HE2s.cjs +3 -0
  20. package/dist/{style-6ihHKVCM.js → style-DnmtG7Gl.js} +69 -81
  21. package/dist/style.css +1 -1
  22. package/dist/vue/ReportPreview.d.ts +3 -12
  23. package/dist/vue/adapters.d.ts +6 -12
  24. package/dist/vue/async.d.cts +7 -22
  25. package/dist/vue/async.d.ts +7 -22
  26. package/dist/vue/local-adapter.d.ts +1 -2
  27. package/dist/vue/plugin.d.ts +12 -34
  28. package/dist/vue-async.cjs +1 -1
  29. package/dist/vue-async.js +6 -6
  30. package/dist/vue.cjs +1 -1
  31. package/dist/vue.js +48 -48
  32. package/package.json +2 -12
  33. package/dist/ReportPreview-CJLvkTVn.cjs +0 -6
  34. package/dist/ReportPreview-mZiGtf0L.js +0 -1231
  35. package/dist/compat/jh4j-template.d.ts +0 -12
  36. package/dist/manager/api.d.ts +0 -45
  37. package/dist/manager/index.d.ts +0 -2
  38. package/dist/manager/types.d.ts +0 -50
  39. package/dist/manager.cjs +0 -1
  40. package/dist/manager.d.cts +0 -5
  41. package/dist/manager.d.ts +0 -5
  42. package/dist/manager.js +0 -104
  43. package/dist/plugin-C4qpbdMJ.cjs +0 -1
  44. package/dist/plugin-DcmAPK_K.js +0 -85
  45. package/dist/style-Xq08-IsV.cjs +0 -3
package/README.md CHANGED
@@ -1,304 +1,135 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://raw.githubusercontent.com/ChenyCHENYU/MachReport/main/assets/mach-report-logo.svg" alt="MachReport" width="760" />
3
+ # 📊 MachReport
4
4
 
5
- # @agile-team/mach-report
5
+ **独立的 TypeScript 报表引擎与 Vue 3 预览组件**
6
6
 
7
- **面向 B 端打印报表的高性能 TypeScript 引擎**:模板 → RenderPlan 单真相源 → 屏幕 / PDF / Excel / 打印四出口,
8
- 提供 jh4j-cloud-report 的 `gridPlan` 接入与迁移工具;具体模板是否可替换,以真实环境验收为准。
7
+ 用自己的模板和数据生成报表,或接入项目已有的报表数据接口;统一预览、打印与导出。
9
8
 
10
- [![npm](https://img.shields.io/npm/v/@agile-team/mach-report.svg?color=2d5fb8)](https://www.npmjs.com/package/@agile-team/mach-report)
9
+ [![npm](https://img.shields.io/npm/v/@agile-team/mach-report.svg)](https://www.npmjs.com/package/@agile-team/mach-report)
11
10
  [![CI](https://github.com/ChenyCHENYU/MachReport/actions/workflows/ci.yml/badge.svg)](https://github.com/ChenyCHENYU/MachReport/actions/workflows/ci.yml)
12
- [![dependencies](https://img.shields.io/badge/dependencies-0-2ea44f)](https://www.npmjs.com/package/@agile-team/mach-report)
13
- [![node](https://img.shields.io/badge/node-%3E%3D18-2d5fb8)](https://www.npmjs.com/package/@agile-team/mach-report)
14
- [![license](https://img.shields.io/badge/license-Source--Available-4a4d52)](#-license)
11
+ [![Node.js](https://img.shields.io/badge/Node.js-%E2%89%A518-2455a6)](https://www.npmjs.com/package/@agile-team/mach-report)
15
12
 
16
- [快速开始](#快速开始) · [核心能力](#核心能力) · [配置中心](#配置中心) · [引擎 API](#引擎-api) · [从 jh4j 迁移](#从-jh4j-迁移)
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 # 唯一依赖:vue 为可选 peer,重能力全部子路径按需
33
+ pnpm add @agile-team/mach-report
26
34
  ```
27
35
 
36
+ **2. 用本地模板注册数据源**
37
+
28
38
  ```ts
29
- // main.ts —— 入口一次注册,业务页面从此零胶水代码
30
- import { machReportPlugin } from "@agile-team/mach-report/vue";
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
- app.use(machReportPlugin); // 零配置:同源直连 jh4j 端点
34
- // 或 app.use(machReportPlugin, { baseUrl: "/sub/mach-report", request: axios });
35
- ```
46
+ const template = createTemplate()
47
+ .page("a4")
48
+ .text("第一张报表", { leftMm: 20, topMm: 20, widthMm: 100, heightMm: 10 })
49
+ .build();
36
50
 
37
- ```vue
38
- <!-- 任意业务页面:一行组件。打印 / PDF / Excel / 搜索 / 缩略图 / 参数面板全部内置 -->
39
- <MachReportPreview temp-id="CK_TEMPLATE_001" :params="{ id: '9' }" height="calc(100vh - 206px)" />
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
- 零配置适用于同源且浏览器请求已带鉴权的部署;宿主通过请求拦截器加 token 时,请传入宿主 `request`。中文 PDF 需部署支持中文的字体并配置 `pdfFontUrl`,缺字时导出会报错,避免下载不完整文件。完整验收边界见[对标与实用化验收](https://github.com/ChenyCHENYU/MachReport/blob/main/docs/comparison-and-acceptance.md)。
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
- <ReportPreview temp-id="T1" :fetcher="fetcher" @loaded="onLoaded" @error="onError" />
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
- 自定义数据面只需实现:`type PlanFetcher = (input: { tempIds, furnitureTempId?, params }) => Promise<RenderPlan>`——
171
- 任何后端能吐 RenderPlan JSON 就能接(schema 有校验器与文档)。
67
+ ## 接入项目数据
172
68
 
173
- </details>
174
-
175
- <details>
176
- <summary><b>引擎 API(框架无关,子路径按需)</b></summary>
69
+ 项目已有接口时,实现一个 `PlanFetcher`,返回 MachReport 的 `RenderPlan`。接口路径、请求库、鉴权和数据映射都由项目决定:
177
70
 
178
71
  ```ts
179
- import {
180
- createTemplate, paginateTemplate, // 模板 DSL / 分页计算
181
- renderPlan, renderPage, // RenderPlan → DOM
182
- renderPlanToCanvas, createCanvasPager, // 位图渲染 / 窗口化分页器(大报表)
183
- computePageWindow, validateRenderPlan, // 虚拟化窗口 / 计划校验(JSON path 定位)
184
- importJh4jTemplateContent, // jh4j 模板 content → 本地模板
185
- wrapText, createCanvasMeasurer // 文本测量(可注入,三端折行一致)
186
- } from "@agile-team/mach-report";
187
- import { renderPlanToPdf } from "@agile-team/mach-report/pdf"; // PDF 直出(pdf-lib 已内联)
188
- import { renderPlanToXlsx } from "@agile-team/mach-report/xlsx"; // Excel 导出
189
- import { renderDynamicSql } from "@agile-team/mach-report/sql"; // 动态 SQL(AST 校验)
190
- import { createReportAdminClient } from "@agile-team/mach-report/manager"; // 管理端 API
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
- </details>
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
- 与 jh4j"服务端另写一套渲染"本质不同:**一份渲染代码两端执行**,服务端只做无头宿主(定时生成、批量归档、合规留档回传)。
100
+ | 领域 | 已提供 |
101
+ | --- | --- |
102
+ | 报表语义 | 明细分页、分组小计、总计、页码占位符、列格式化、条件格式 |
103
+ | 预览 | DOM / Canvas、页级虚拟化、缩放、搜索、缩略图、参数面板 |
104
+ | 导出 | PDF、真正的 `.xlsx`、PNG / JPEG、Word 兼容 HTML `.doc`、逐页打印 |
105
+ | 工程接入 | Vue 插件或局部组件、自定义数据源、结构化错误、导出进度与告警 |
106
+ | 按需入口 | `/vue`、`/pdf`、`/xlsx`、`/sql`;主入口为框架无关的引擎 |
234
107
 
235
- </details>
108
+ 中文 PDF 需配置包含所用汉字的字体 `pdfFontUrl`;缺字时导出会报错。XLSX 保留表格数据与结构,不承诺 PDF 式像素排版;`.doc` 是 Word 可打开的 HTML 文档,并非 `.docx`。
236
109
 
237
- <details>
238
- <summary><b>从 jh4j 迁移(契约对照)</b></summary>
110
+ ## 文档
239
111
 
240
- | 契约项 | 对齐方式 |
241
- |---|---|
242
- | 组件 props / 事件 / ref | `temp-id / furniture-temp-id / params / height / auto-load / show-*`;`loaded / error`;`reload / print / exportAs / openPdfWindow / gotoPage / setParams` |
243
- | 数据接口 | `/report/codePrintReport/gridPlan` 路径与出入参兼容 |
244
- | 存量模板 | `importJh4jTemplateContent` 逆向 schema 直接转换(含告警清单) |
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
- </details>
118
+ ## 本地开发
249
119
 
250
- <details>
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 typecheck && pnpm lint && pnpm test && pnpm build && pnpm exec playwright test
279
- # TS strict(含 vue-tsc) · ESLint 0 错 0 警 · 全量单测(纯逻辑 node 环境分流) · 真 Chromium E2E(0 重试) · 七入口构建
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
- 关键设计决策:单真相源渲染 / 单包子路径架构 / 自引用复用 / 三后端共享几何与样式解析 / 性能预算门禁 / 变更日志(changesets)。
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
- **v1.2.1** · 单包多入口 · 类型、单测与浏览器验证 · 语义化版本演进
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;