@veltra/sheet 2.0.1 → 2.2.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 (339) hide show
  1. package/dist/components/report/binding-badge.js +76 -0
  2. package/dist/components/report/designer/cell-coords.js +46 -0
  3. package/dist/components/report/designer/col-widths.js +15 -0
  4. package/dist/components/report/designer/conditional-rules/helpers.js +139 -0
  5. package/dist/components/report/designer/drop-highlight-overlay.js +76 -0
  6. package/dist/components/report/designer/float-panel.js +385 -0
  7. package/dist/components/report/designer/role.js +17 -0
  8. package/dist/components/report/designer/rule-preview.js +33 -0
  9. package/dist/components/report/designer/rule-row.js +269 -0
  10. package/dist/components/report/designer/rules-dialog.js +135 -0
  11. package/dist/components/report/designer/topology-overlay.js +122 -0
  12. package/dist/components/report/designer/topology.js +64 -0
  13. package/dist/components/report/designer/use-grid-overlay.js +75 -0
  14. package/dist/components/report/designer-hub.js +177 -0
  15. package/dist/components/report/field-panel-helpers.js +33 -0
  16. package/dist/components/report/field-panel.js +132 -0
  17. package/dist/components/report/filter-bar.js +74 -0
  18. package/dist/components/report/hub-connection-form.js +145 -0
  19. package/dist/components/report/hub-dataset-editor.js +394 -0
  20. package/dist/components/report/report-designer.js +343 -0
  21. package/dist/components/report/report-viewer.js +111 -0
  22. package/dist/components/report/style.d.ts +17 -0
  23. package/dist/components/report/style.js +18 -0
  24. package/dist/components/report/style2.css +869 -0
  25. package/dist/components/report/use-report-designer.js +360 -0
  26. package/dist/components/report/use-report-viewer.js +50 -0
  27. package/dist/components/sheet/formula-bar.js +393 -0
  28. package/dist/components/sheet/formula-suggest-list.js +66 -0
  29. package/dist/components/sheet/import-file.js +140 -0
  30. package/dist/components/sheet/insert-count-menu-item.js +68 -0
  31. package/dist/components/sheet/insert-image.js +79 -0
  32. package/dist/components/sheet/popup-helpers.js +73 -0
  33. package/dist/components/sheet/popups/border-popup.js +75 -0
  34. package/dist/components/sheet/popups/border-preset-glyph.js +106 -0
  35. package/dist/components/sheet/popups/export-popup.js +51 -0
  36. package/dist/components/sheet/popups/fill-color-popup.js +37 -0
  37. package/dist/components/sheet/popups/find-popup.js +113 -0
  38. package/dist/components/sheet/popups/font-color-popup.js +37 -0
  39. package/dist/components/sheet/popups/font-size-popup.js +63 -0
  40. package/dist/components/sheet/popups/import.worker.d.ts +21 -0
  41. package/dist/components/sheet/popups/import.worker.js +41 -0
  42. package/dist/components/sheet/popups/insert-image-popup.js +38 -0
  43. package/dist/components/sheet/sheet-context-menu.js +200 -0
  44. package/dist/components/sheet/sheet-tabs.js +162 -0
  45. package/dist/components/sheet/sheet-toolbar.js +106 -0
  46. package/dist/components/sheet/sheet.js +198 -0
  47. package/dist/components/sheet/style.d.ts +11 -0
  48. package/dist/components/sheet/style.js +12 -0
  49. package/dist/components/sheet/style2.css +654 -0
  50. package/dist/components/sheet/use-find-replace.js +161 -0
  51. package/dist/components/sheet/use-formula-ref-select.js +37 -0
  52. package/dist/components/sheet/use-formula-suggest.js +126 -0
  53. package/dist/components/sheet/use-sheet-grid.js +188 -0
  54. package/dist/components/sheet/use-sheet-state.js +122 -0
  55. package/dist/components/sheet/use-sheet-tabs-bar.js +90 -0
  56. package/dist/components/sheet/use-tool-groups.js +42 -0
  57. package/dist/components/sheet/use-tool-popup.js +123 -0
  58. package/dist/components/sheet/use-toolbar-scroll.js +72 -0
  59. package/dist/index.d.ts +18 -26
  60. package/dist/index.js +14 -24
  61. package/dist/report/binding.d.ts +45 -0
  62. package/dist/report/binding.js +175 -0
  63. package/dist/report/connector.d.ts +66 -0
  64. package/dist/report/connector.js +159 -0
  65. package/dist/report/export-xlsx.d.ts +19 -0
  66. package/dist/report/export-xlsx.js +95 -0
  67. package/dist/report/filter-bar.d.ts +10 -0
  68. package/dist/report/filter-bar.js +31 -0
  69. package/dist/report/index.d.ts +12 -0
  70. package/dist/report/params.d.ts +13 -0
  71. package/dist/report/params.js +61 -0
  72. package/dist/report/render/aggregate.js +157 -0
  73. package/dist/report/render/builder.d.ts +12 -0
  74. package/dist/report/render/builder.js +139 -0
  75. package/dist/report/render/coordinate.d.ts +25 -0
  76. package/dist/report/render/coordinate.js +733 -0
  77. package/dist/report/render/index.d.ts +14 -0
  78. package/dist/report/render/index.js +21 -0
  79. package/dist/report/render/style-resolver.js +50 -0
  80. package/dist/report/render/template-index.d.ts +24 -0
  81. package/dist/report/render/template-index.js +137 -0
  82. package/dist/report/rules/evaluate.d.ts +25 -0
  83. package/dist/report/rules/evaluate.js +82 -0
  84. package/dist/report/rules/index.d.ts +2 -0
  85. package/dist/report/template.d.ts +59 -0
  86. package/dist/report/template.js +80 -0
  87. package/dist/report/types.d.ts +85 -0
  88. package/dist/tools/builtin.js +279 -8
  89. package/dist/tools/context.d.ts +54 -11
  90. package/dist/tools/context.js +28 -5
  91. package/dist/tools/download.js +68 -0
  92. package/dist/tools/export.worker.d.ts +16 -0
  93. package/dist/tools/export.worker.js +29 -0
  94. package/dist/tools/registry.d.ts +7 -4
  95. package/dist/tools/registry.js +1 -3
  96. package/dist/types/index.d.ts +3 -1
  97. package/dist/types/report-designer.d.ts +36 -0
  98. package/dist/types/report-viewer.d.ts +38 -0
  99. package/dist/types/sheet.d.ts +22 -5
  100. package/package.json +10 -7
  101. package/src/components/report/__test__/conditional-rules-helpers.test.ts +87 -0
  102. package/src/components/report/__test__/field-panel-helpers.test.ts +65 -0
  103. package/src/components/report/__test__/float-panel-position.test.ts +45 -0
  104. package/src/components/report/__test__/report-designer.test.ts +388 -0
  105. package/src/components/report/__test__/report-viewer.test.ts +334 -0
  106. package/src/components/report/__test__/topology.test.ts +143 -0
  107. package/src/components/report/__test__/use-report-designer.test.ts +565 -0
  108. package/src/components/report/binding-badge.ts +73 -0
  109. package/src/components/report/designer/cell-coords.ts +94 -0
  110. package/src/components/report/designer/col-widths.ts +33 -0
  111. package/src/components/report/designer/conditional-rules/helpers.ts +186 -0
  112. package/src/components/report/designer/drop-highlight-overlay.vue +74 -0
  113. package/src/components/report/designer/float-panel.vue +387 -0
  114. package/src/components/report/designer/role.ts +32 -0
  115. package/src/components/report/designer/rule-preview.vue +40 -0
  116. package/src/components/report/designer/rule-row.vue +252 -0
  117. package/src/components/report/designer/rules-dialog.vue +126 -0
  118. package/src/components/report/designer/topology-overlay.vue +127 -0
  119. package/src/components/report/designer/topology.ts +124 -0
  120. package/src/components/report/designer/use-grid-overlay.ts +113 -0
  121. package/src/components/report/designer-hub.vue +198 -0
  122. package/src/components/report/field-panel-helpers.ts +44 -0
  123. package/src/components/report/field-panel.vue +136 -0
  124. package/src/components/report/filter-bar.vue +77 -0
  125. package/src/components/report/hub-connection-form.vue +124 -0
  126. package/src/components/report/hub-dataset-editor.vue +369 -0
  127. package/src/components/report/index.ts +2 -0
  128. package/src/components/report/report-designer.vue +356 -0
  129. package/src/components/report/report-viewer.vue +128 -0
  130. package/src/components/report/style-designer.scss +583 -0
  131. package/src/components/report/style-hub.scss +292 -0
  132. package/src/components/report/style-viewer.scss +104 -0
  133. package/src/components/report/style.scss +3 -0
  134. package/src/components/report/style.ts +20 -0
  135. package/src/components/report/use-report-designer.ts +547 -0
  136. package/src/components/report/use-report-viewer.ts +79 -0
  137. package/src/components/sheet/__test__/formula-bar.test.ts +474 -0
  138. package/src/components/sheet/__test__/import-file.test.ts +183 -0
  139. package/src/components/sheet/__test__/insert-count-menu-item.test.ts +123 -0
  140. package/src/components/sheet/__test__/insert-image-popup.test.ts +89 -0
  141. package/src/components/sheet/__test__/insert-image.test.ts +100 -0
  142. package/src/components/sheet/__test__/sheet-component.test.ts +993 -0
  143. package/src/components/sheet/__test__/sheet-context-menu.test.ts +206 -0
  144. package/src/components/sheet/__test__/use-formula-ref-select.test.ts +35 -0
  145. package/src/components/sheet/__test__/use-formula-suggest.test.ts +83 -0
  146. package/src/components/sheet/formula-bar.vue +473 -0
  147. package/src/components/sheet/formula-suggest-list.vue +64 -0
  148. package/src/components/sheet/import-file.ts +173 -0
  149. package/src/components/sheet/insert-count-menu-item.vue +69 -0
  150. package/src/components/sheet/insert-image.ts +90 -0
  151. package/src/components/sheet/parsing.ts +11 -0
  152. package/src/components/sheet/popup-helpers.ts +50 -0
  153. package/src/components/sheet/popups/border-popup.vue +93 -0
  154. package/src/components/sheet/popups/border-preset-glyph.vue +111 -0
  155. package/src/components/sheet/popups/export-popup.vue +52 -0
  156. package/src/components/sheet/popups/fill-color-popup.vue +39 -0
  157. package/src/components/sheet/popups/find-popup.vue +111 -0
  158. package/src/components/sheet/popups/font-color-popup.vue +39 -0
  159. package/src/components/sheet/popups/font-size-popup.vue +52 -0
  160. package/src/components/sheet/popups/import.worker.ts +66 -0
  161. package/src/components/sheet/popups/insert-image-popup.vue +39 -0
  162. package/src/components/sheet/sheet-context-menu.ts +229 -0
  163. package/src/components/sheet/sheet-tabs.vue +162 -0
  164. package/src/components/sheet/sheet-toolbar.vue +91 -0
  165. package/src/components/sheet/sheet.vue +211 -0
  166. package/src/components/sheet/style.scss +737 -0
  167. package/src/components/sheet/style.ts +13 -0
  168. package/src/components/sheet/use-find-replace.ts +200 -0
  169. package/src/components/sheet/use-formula-ref-select.ts +34 -0
  170. package/src/components/sheet/use-formula-suggest.ts +150 -0
  171. package/src/components/sheet/use-sheet-grid.ts +247 -0
  172. package/src/components/sheet/use-sheet-state.ts +161 -0
  173. package/src/components/sheet/use-sheet-tabs-bar.ts +115 -0
  174. package/src/components/sheet/use-tool-groups.ts +61 -0
  175. package/src/components/sheet/use-tool-popup.ts +150 -0
  176. package/src/components/sheet/use-toolbar-scroll.ts +95 -0
  177. package/src/env.d.ts +11 -0
  178. package/src/index.ts +39 -14
  179. package/src/report/__test__/binding.test.ts +218 -0
  180. package/src/report/__test__/connector.test.ts +218 -0
  181. package/src/report/__test__/export-xlsx.test.ts +118 -0
  182. package/src/report/__test__/filter-bar.test.ts +58 -0
  183. package/src/report/__test__/params.test.ts +156 -0
  184. package/src/report/__test__/render.test.ts +728 -0
  185. package/src/report/__test__/rules.test.ts +131 -0
  186. package/src/report/__test__/template.test.ts +355 -0
  187. package/src/report/binding.ts +243 -0
  188. package/src/report/connector.ts +205 -0
  189. package/src/report/export-xlsx.ts +118 -0
  190. package/src/report/filter-bar.ts +36 -0
  191. package/src/report/index.ts +13 -0
  192. package/src/report/params.ts +96 -0
  193. package/src/report/render/__test__/aggregate.test.ts +16 -0
  194. package/src/report/render/__test__/coordinate.test.ts +405 -0
  195. package/src/report/render/aggregate.ts +240 -0
  196. package/src/report/render/builder.ts +211 -0
  197. package/src/report/render/coordinate.ts +1239 -0
  198. package/src/report/render/index.ts +30 -0
  199. package/src/report/render/style-resolver.ts +68 -0
  200. package/src/report/render/template-index.ts +200 -0
  201. package/src/report/rules/evaluate.ts +113 -0
  202. package/src/report/rules/index.ts +7 -0
  203. package/src/report/template.ts +141 -0
  204. package/src/report/types.ts +96 -0
  205. package/src/tools/__test__/builtin.test.ts +208 -66
  206. package/src/tools/__test__/context.test.ts +62 -2
  207. package/src/tools/builtin.ts +350 -6
  208. package/src/tools/context.ts +89 -11
  209. package/src/tools/download.ts +82 -0
  210. package/src/tools/export.worker.ts +61 -0
  211. package/src/tools/registry.ts +16 -1
  212. package/src/types/index.ts +2 -0
  213. package/src/types/report-designer.ts +36 -0
  214. package/src/types/report-viewer.ts +37 -0
  215. package/src/types/sheet.ts +26 -3
  216. package/dist/core/address.d.ts +0 -60
  217. package/dist/core/address.js +0 -142
  218. package/dist/core/address.js.map +0 -1
  219. package/dist/core/cell-store.d.ts +0 -61
  220. package/dist/core/cell-store.js +0 -135
  221. package/dist/core/cell-store.js.map +0 -1
  222. package/dist/core/command/default-registry.d.ts +0 -10
  223. package/dist/core/command/default-registry.js +0 -18
  224. package/dist/core/command/default-registry.js.map +0 -1
  225. package/dist/core/command/history.d.ts +0 -64
  226. package/dist/core/command/history.js +0 -127
  227. package/dist/core/command/history.js.map +0 -1
  228. package/dist/core/command/merge-cells.d.ts +0 -21
  229. package/dist/core/command/merge-cells.js +0 -74
  230. package/dist/core/command/merge-cells.js.map +0 -1
  231. package/dist/core/command/registry.d.ts +0 -17
  232. package/dist/core/command/registry.js +0 -26
  233. package/dist/core/command/registry.js.map +0 -1
  234. package/dist/core/command/set-cell-formula.d.ts +0 -17
  235. package/dist/core/command/set-cell-formula.js +0 -29
  236. package/dist/core/command/set-cell-formula.js.map +0 -1
  237. package/dist/core/command/set-cell-value.d.ts +0 -22
  238. package/dist/core/command/set-cell-value.js +0 -35
  239. package/dist/core/command/set-cell-value.js.map +0 -1
  240. package/dist/core/command/types.d.ts +0 -68
  241. package/dist/core/events.js +0 -29
  242. package/dist/core/events.js.map +0 -1
  243. package/dist/core/fill.d.ts +0 -34
  244. package/dist/core/fill.js +0 -320
  245. package/dist/core/fill.js.map +0 -1
  246. package/dist/core/formula/ast.d.ts +0 -58
  247. package/dist/core/formula/ast.js +0 -38
  248. package/dist/core/formula/ast.js.map +0 -1
  249. package/dist/core/formula/dependency-graph.d.ts +0 -70
  250. package/dist/core/formula/dependency-graph.js +0 -269
  251. package/dist/core/formula/dependency-graph.js.map +0 -1
  252. package/dist/core/formula/errors.d.ts +0 -25
  253. package/dist/core/formula/errors.js +0 -36
  254. package/dist/core/formula/errors.js.map +0 -1
  255. package/dist/core/formula/evaluator.d.ts +0 -41
  256. package/dist/core/formula/evaluator.js +0 -154
  257. package/dist/core/formula/evaluator.js.map +0 -1
  258. package/dist/core/formula/functions.d.ts +0 -30
  259. package/dist/core/formula/functions.js +0 -209
  260. package/dist/core/formula/functions.js.map +0 -1
  261. package/dist/core/formula/parser.d.ts +0 -7
  262. package/dist/core/formula/parser.js +0 -208
  263. package/dist/core/formula/parser.js.map +0 -1
  264. package/dist/core/formula/tokenizer.d.ts +0 -37
  265. package/dist/core/formula/tokenizer.js +0 -146
  266. package/dist/core/formula/tokenizer.js.map +0 -1
  267. package/dist/core/merge-manager.d.ts +0 -64
  268. package/dist/core/merge-manager.js +0 -111
  269. package/dist/core/merge-manager.js.map +0 -1
  270. package/dist/core/selection.d.ts +0 -31
  271. package/dist/core/selection.js +0 -62
  272. package/dist/core/selection.js.map +0 -1
  273. package/dist/core/sheet.d.ts +0 -116
  274. package/dist/core/sheet.js +0 -224
  275. package/dist/core/sheet.js.map +0 -1
  276. package/dist/core/workbook.d.ts +0 -43
  277. package/dist/core/workbook.js +0 -77
  278. package/dist/core/workbook.js.map +0 -1
  279. package/dist/grid/sheet-grid.d.ts +0 -81
  280. package/dist/grid/sheet-grid.js +0 -331
  281. package/dist/grid/sheet-grid.js.map +0 -1
  282. package/dist/grid/vtable-theme.js +0 -80
  283. package/dist/grid/vtable-theme.js.map +0 -1
  284. package/dist/tools/builtin.js.map +0 -1
  285. package/dist/tools/context.js.map +0 -1
  286. package/dist/tools/registry.js.map +0 -1
  287. package/dist/vue/index.d.ts +0 -2
  288. package/dist/vue/sheet.js +0 -211
  289. package/dist/vue/sheet.js.map +0 -1
  290. package/dist/vue/sheet.vue.d.ts +0 -24
  291. package/dist/vue/style.d.ts +0 -1
  292. package/dist/vue/style.js +0 -2
  293. package/dist/vue/style2.css +0 -93
  294. package/src/core/__test__/address.test.ts +0 -113
  295. package/src/core/__test__/cell-store.test.ts +0 -97
  296. package/src/core/__test__/command.test.ts +0 -377
  297. package/src/core/__test__/fill.test.ts +0 -140
  298. package/src/core/__test__/formula-adversarial.test.ts +0 -265
  299. package/src/core/__test__/formula-engine.test.ts +0 -470
  300. package/src/core/__test__/formula-functions.test.ts +0 -178
  301. package/src/core/__test__/formula-parser.test.ts +0 -160
  302. package/src/core/__test__/history.test.ts +0 -225
  303. package/src/core/__test__/merge-manager.test.ts +0 -106
  304. package/src/core/__test__/sheet.test.ts +0 -142
  305. package/src/core/address.ts +0 -166
  306. package/src/core/cell-store.ts +0 -173
  307. package/src/core/command/default-registry.ts +0 -15
  308. package/src/core/command/history.ts +0 -167
  309. package/src/core/command/index.ts +0 -7
  310. package/src/core/command/merge-cells.ts +0 -74
  311. package/src/core/command/registry.ts +0 -30
  312. package/src/core/command/set-cell-formula.ts +0 -29
  313. package/src/core/command/set-cell-value.ts +0 -38
  314. package/src/core/command/types.ts +0 -73
  315. package/src/core/events.ts +0 -37
  316. package/src/core/fill.ts +0 -314
  317. package/src/core/formula/ast.ts +0 -66
  318. package/src/core/formula/dependency-graph.ts +0 -329
  319. package/src/core/formula/errors.ts +0 -41
  320. package/src/core/formula/evaluator.ts +0 -219
  321. package/src/core/formula/functions.ts +0 -266
  322. package/src/core/formula/index.ts +0 -7
  323. package/src/core/formula/parser.ts +0 -198
  324. package/src/core/formula/tokenizer.ts +0 -160
  325. package/src/core/merge-manager.ts +0 -158
  326. package/src/core/selection.ts +0 -66
  327. package/src/core/sheet.ts +0 -282
  328. package/src/core/workbook.ts +0 -99
  329. package/src/grid/__test__/canvas-mock.ts +0 -49
  330. package/src/grid/__test__/setup.ts +0 -3
  331. package/src/grid/__test__/sheet-grid-formula.test.ts +0 -140
  332. package/src/grid/__test__/sheet-grid.test.ts +0 -275
  333. package/src/grid/sheet-grid.ts +0 -407
  334. package/src/grid/vtable-theme.ts +0 -61
  335. package/src/vue/__test__/sheet-component.test.ts +0 -267
  336. package/src/vue/sheet.vue +0 -235
  337. package/src/vue/style.scss +0 -94
  338. package/src/vue/style.ts +0 -2
  339. /package/src/{vue → components/sheet}/index.ts +0 -0
@@ -0,0 +1,360 @@
1
+ import { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatCellAddress, inferColParentCandidate, inferDropPreset, inferRowParentCandidate, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates } from "../../report/binding.js";
2
+ import { buildParamDefs } from "../../report/params.js";
3
+ import { assertCompatibleTemplateVersion, createReportTemplate, getTemplateDatasets, resolveParamDefaults } from "../../report/template.js";
4
+ import { createBindingBadgeRenderer, createBindingBadgeStyleResolver } from "./binding-badge.js";
5
+ import { computed, onScopeDispose, ref, watch } from "vue";
6
+ import { Workbook } from "@veltra/sheet-core";
7
+ //#region src/components/report/use-report-designer.ts
8
+ /**
9
+ * UReportDesigner 的 headless 编排:连接 / 数据集状态、绑定写 Cell Meta、
10
+ * 角色徽章渲染 hook、`getTemplate()` 模板吐出。不持有 DOM / 网格引用。
11
+ */
12
+ function useReportDesigner(options) {
13
+ const { props, connections } = options;
14
+ /** 设计态工作簿:宿主可注入(USheet / UReportViewer 先例),缺省内部自建 */
15
+ const internalWorkbook = new Workbook();
16
+ const workbook = computed(() => props.workbook ?? internalWorkbook);
17
+ const datasets = ref([]);
18
+ /** meta 变更计数:boundKeys 等派生状态的响应式触发(绑定经命令系统写入后由模型发 meta-change) */
19
+ const metaTick = ref(0);
20
+ const parentPick = ref(null);
21
+ const offMeta = workbook.value.activeSheet.on("meta-change", () => {
22
+ metaTick.value++;
23
+ });
24
+ onScopeDispose(offMeta);
25
+ /** 稳定选区地址引用(值未变时不替换对象,避免触发下游 watcher) */
26
+ const activeCell = ref(null);
27
+ function syncActiveCell() {
28
+ const next = workbook.value.activeSheet.getSelection().activeCell ?? null;
29
+ const prev = activeCell.value;
30
+ if (!next) {
31
+ activeCell.value = null;
32
+ return;
33
+ }
34
+ if (prev && prev.row === next.row && prev.col === next.col) return;
35
+ activeCell.value = {
36
+ row: next.row,
37
+ col: next.col
38
+ };
39
+ }
40
+ const offSelection = workbook.value.activeSheet.on("selection-change", syncActiveCell);
41
+ onScopeDispose(offSelection);
42
+ syncActiveCell();
43
+ const selectionLabel = computed(() => activeCell.value ? formatCellAddress(activeCell.value) : "—");
44
+ const catalog = computed(() => datasets.value.map((dataset) => ({
45
+ id: dataset.id,
46
+ label: dataset.label,
47
+ fields: (dataset.fields ?? []).map((field) => ({
48
+ ...field,
49
+ label: dataset.fieldOverrides?.[field.name]?.label ?? field.label
50
+ }))
51
+ })));
52
+ /** 字段 label 的 O(1) 查找表(徽章 hook 性能契约) */
53
+ const fieldLabelMap = computed(() => {
54
+ const map = /* @__PURE__ */ new Map();
55
+ for (const dataset of catalog.value) for (const field of dataset.fields) map.set(`${dataset.id}:${field.name}`, field.label);
56
+ return map;
57
+ });
58
+ function resolveFieldLabel(datasetId, fieldName) {
59
+ return fieldLabelMap.value.get(`${datasetId}:${fieldName}`) ?? fieldName;
60
+ }
61
+ const boundKeys = computed(() => {
62
+ metaTick.value;
63
+ const keys = /* @__PURE__ */ new Set();
64
+ for (const [, namespace, payload] of workbook.value.activeSheet.entriesCellMeta()) {
65
+ if (namespace !== "report") continue;
66
+ const binding = payload;
67
+ keys.add(`${binding.dataset}:${binding.field}`);
68
+ }
69
+ return keys;
70
+ });
71
+ function getBindingAt(addr) {
72
+ return workbook.value.activeSheet.getCellMeta(addr, REPORT_META_NAMESPACE);
73
+ }
74
+ function bindField(datasetId, fieldName, addr) {
75
+ const dataset = catalog.value.find((item) => item.id === datasetId);
76
+ if (!dataset) return;
77
+ const field = dataset.fields.find((item) => item.name === fieldName);
78
+ const target = addr ?? workbook.value.activeSheet.getSelection().activeCell;
79
+ if (!target) return;
80
+ const preset = inferDropPreset(target, field?.type ?? "string", getBindingAt);
81
+ let binding = createReportBinding(dataset, fieldName);
82
+ binding = applyReportPreset(binding, preset);
83
+ const rowParent = inferRowParentCandidate(target, getBindingAt);
84
+ if (rowParent) binding.rowParent = rowParent;
85
+ const colParent = inferColParentCandidate(target, getBindingAt);
86
+ if (colParent) binding.colParent = colParent;
87
+ workbook.value.activeSheet.setCellMeta(target, REPORT_META_NAMESPACE, binding);
88
+ }
89
+ const activeBinding = computed(() => {
90
+ metaTick.value;
91
+ const cell = activeCell.value;
92
+ if (!cell) return void 0;
93
+ return getBindingAt(cell);
94
+ });
95
+ const activeFieldType = computed(() => {
96
+ const binding = activeBinding.value;
97
+ if (!binding) return "number";
98
+ return (catalog.value.find((item) => item.id === binding.dataset)?.fields.find((item) => item.name === binding.field))?.type ?? "number";
99
+ });
100
+ const activeDatasetFields = computed(() => {
101
+ const binding = activeBinding.value;
102
+ if (!binding) return [];
103
+ return catalog.value.find((item) => item.id === binding.dataset)?.fields ?? [];
104
+ });
105
+ const resolvedRowParentLabel = computed(() => {
106
+ metaTick.value;
107
+ const binding = activeBinding.value;
108
+ if (!binding?.rowParent) return "—";
109
+ return formatCellAddress(binding.rowParent);
110
+ });
111
+ const resolvedColParentLabel = computed(() => {
112
+ metaTick.value;
113
+ const binding = activeBinding.value;
114
+ if (!binding?.colParent) return "—";
115
+ return formatCellAddress(binding.colParent);
116
+ });
117
+ const rowParentCandidates = computed(() => {
118
+ metaTick.value;
119
+ const binding = activeBinding.value;
120
+ if (!binding) return [];
121
+ return listRowParentCandidates(binding, bindingEntries.value);
122
+ });
123
+ const colParentCandidates = computed(() => {
124
+ metaTick.value;
125
+ const binding = activeBinding.value;
126
+ if (!binding) return [];
127
+ return listColParentCandidates(binding, bindingEntries.value);
128
+ });
129
+ const bindingEntries = computed(() => {
130
+ metaTick.value;
131
+ const entries = [];
132
+ for (const [addr, namespace, payload] of workbook.value.activeSheet.entriesCellMeta()) {
133
+ if (namespace !== "report") continue;
134
+ entries.push({
135
+ addr,
136
+ binding: payload
137
+ });
138
+ }
139
+ return entries;
140
+ });
141
+ function patchActiveBinding(patch) {
142
+ const cell = activeCell.value;
143
+ const binding = activeBinding.value;
144
+ if (!cell || !binding) return;
145
+ const next = {
146
+ ...binding,
147
+ ...patch
148
+ };
149
+ if ("rowParent" in patch && patch.rowParent === void 0) delete next.rowParent;
150
+ if ("colParent" in patch && patch.colParent === void 0) delete next.colParent;
151
+ if (("aggregate" in patch || "expand" in patch) && !("preset" in patch)) delete next.preset;
152
+ workbook.value.activeSheet.setCellMeta(cell, REPORT_META_NAMESPACE, next);
153
+ }
154
+ function startParentPick(mode) {
155
+ const cell = activeCell.value;
156
+ if (!cell || !activeBinding.value) return;
157
+ parentPick.value = {
158
+ mode,
159
+ source: {
160
+ row: cell.row,
161
+ col: cell.col
162
+ }
163
+ };
164
+ }
165
+ function cancelParentPick() {
166
+ parentPick.value = null;
167
+ }
168
+ function pickParentAt(target) {
169
+ const pick = parentPick.value;
170
+ if (!pick) return;
171
+ if (target.row === pick.source.row && target.col === pick.source.col) return;
172
+ const sourceBinding = getBindingAt(pick.source);
173
+ const targetBinding = getBindingAt(target);
174
+ if (!sourceBinding || !targetBinding) return;
175
+ if (targetBinding.dataset !== sourceBinding.dataset) return;
176
+ if (pick.mode === "row" && !isVerticalExpandBinding(targetBinding)) return;
177
+ if (pick.mode === "col" && !isHorizontalExpandBinding(targetBinding)) return;
178
+ const patch = pick.mode === "row" ? { rowParent: { ...target } } : { colParent: { ...target } };
179
+ const next = {
180
+ ...sourceBinding,
181
+ ...patch
182
+ };
183
+ workbook.value.activeSheet.setCellMeta(pick.source, REPORT_META_NAMESPACE, next);
184
+ parentPick.value = null;
185
+ workbook.value.activeSheet.selectCell(pick.source);
186
+ }
187
+ function clearParent(mode) {
188
+ if (mode === "row") patchActiveBinding({ rowParent: void 0 });
189
+ else patchActiveBinding({ colParent: void 0 });
190
+ }
191
+ function removeActiveBinding() {
192
+ const cell = activeCell.value;
193
+ if (!cell) return;
194
+ workbook.value.activeSheet.clearCellMeta(cell, REPORT_META_NAMESPACE);
195
+ }
196
+ function addConnection(connection) {
197
+ connections.value = [...connections.value, connection];
198
+ }
199
+ function updateConnection(connection) {
200
+ connections.value = connections.value.map((item) => item.id === connection.id ? connection : item);
201
+ }
202
+ function removeConnection(connectionId) {
203
+ connections.value = connections.value.filter((item) => item.id !== connectionId);
204
+ datasets.value = datasets.value.filter((dataset) => dataset.connectionId !== connectionId);
205
+ }
206
+ let datasetSeq = 0;
207
+ function addDataset(connectionId) {
208
+ const dataset = {
209
+ id: `dataset-${Date.now()}-${datasetSeq++}`,
210
+ label: "新数据集",
211
+ connectionId,
212
+ sql: ""
213
+ };
214
+ datasets.value = [...datasets.value, dataset];
215
+ return dataset;
216
+ }
217
+ function updateDataset(datasetId, patch) {
218
+ datasets.value = datasets.value.map((item) => item.id === datasetId ? {
219
+ ...item,
220
+ ...patch
221
+ } : item);
222
+ }
223
+ function removeDataset(datasetId) {
224
+ datasets.value = datasets.value.filter((item) => item.id !== datasetId);
225
+ }
226
+ function resolveDatasetConnection(dataset) {
227
+ return connections.value.find((item) => item.id === dataset.connectionId);
228
+ }
229
+ function datasetNotFound() {
230
+ return {
231
+ ok: false,
232
+ error: {
233
+ code: "DATASET_NOT_FOUND",
234
+ message: "数据集不存在"
235
+ }
236
+ };
237
+ }
238
+ function connectionNotFound() {
239
+ return {
240
+ ok: false,
241
+ error: {
242
+ code: "CONNECTION_NOT_FOUND",
243
+ message: "数据集所属连接不存在"
244
+ }
245
+ };
246
+ }
247
+ function testConnection(connection) {
248
+ return props.connector.test(connection);
249
+ }
250
+ async function describeDataset(datasetId) {
251
+ const dataset = datasets.value.find((item) => item.id === datasetId);
252
+ if (!dataset) return datasetNotFound();
253
+ const connection = resolveDatasetConnection(dataset);
254
+ if (!connection) return connectionNotFound();
255
+ const sql = dataset.sql;
256
+ const result = await props.connector.describe(connection, sql);
257
+ if (result.ok) {
258
+ const current = datasets.value.find((item) => item.id === datasetId);
259
+ if (current && current.sql === sql) updateDataset(datasetId, { fields: result.data });
260
+ }
261
+ return result;
262
+ }
263
+ async function previewDataset(datasetId) {
264
+ const dataset = datasets.value.find((item) => item.id === datasetId);
265
+ if (!dataset) return datasetNotFound();
266
+ const connection = resolveDatasetConnection(dataset);
267
+ if (!connection) return connectionNotFound();
268
+ const values = resolveParamDefaults(buildParamDefs(dataset.sql, dataset.paramOverrides));
269
+ return props.connector.query(connection, dataset.sql, values);
270
+ }
271
+ const resolveCellStyle = createBindingBadgeStyleResolver(getBindingAt);
272
+ const resolveCellRenderer = createBindingBadgeRenderer(getBindingAt, resolveFieldLabel);
273
+ function getTemplate() {
274
+ const resolved = datasets.value.flatMap((dataset) => {
275
+ const connection = resolveDatasetConnection(dataset);
276
+ if (!connection) return [];
277
+ return [{
278
+ id: dataset.id,
279
+ label: dataset.label,
280
+ connection: { ...connection },
281
+ sql: dataset.sql,
282
+ ...dataset.paramOverrides ? { paramOverrides: dataset.paramOverrides } : {},
283
+ ...dataset.fieldOverrides ? { fieldOverrides: dataset.fieldOverrides } : {}
284
+ }];
285
+ });
286
+ return createReportTemplate(workbook.value.activeSheet.snapshot(), resolved);
287
+ }
288
+ /**
289
+ * 载入既有 Report Template 继续设计(`template` prop):
290
+ * 快照恢复网格绑定(restore + restoreContent 与查看器同路径);
291
+ * 内嵌数据集定义还原为设计态(connectionId 引用),内嵌连接按 id 合并进
292
+ * v-model 连接列表(仅缺省追加,宿主列表是单一事实源);
293
+ * describe 恢复字段缓存(字段面板数据源),业务错误忽略(字段留空,可在数据中枢重试)。
294
+ */
295
+ function loadTemplate(template) {
296
+ assertCompatibleTemplateVersion(template);
297
+ const sheet = workbook.value.activeSheet;
298
+ sheet.restore(template);
299
+ sheet.restoreContent(template);
300
+ sheet.history.clear();
301
+ syncActiveCell();
302
+ const defs = getTemplateDatasets(template);
303
+ datasets.value = defs.map((def) => ({
304
+ id: def.id,
305
+ label: def.label,
306
+ connectionId: def.connection.id,
307
+ sql: def.sql,
308
+ ...def.paramOverrides ? { paramOverrides: def.paramOverrides } : {},
309
+ ...def.fieldOverrides ? { fieldOverrides: def.fieldOverrides } : {}
310
+ }));
311
+ const missing = defs.map((def) => def.connection).filter((connection) => !connections.value.some((item) => item.id === connection.id));
312
+ if (missing.length > 0) connections.value = [...connections.value, ...missing.map((connection) => ({ ...connection }))];
313
+ for (const dataset of datasets.value) if (dataset.sql.trim()) describeDataset(dataset.id);
314
+ }
315
+ watch(() => props.template, (template) => {
316
+ if (template) loadTemplate(template);
317
+ }, { immediate: true });
318
+ return {
319
+ workbook,
320
+ connections,
321
+ datasets,
322
+ catalog,
323
+ boundKeys,
324
+ activeCell,
325
+ selectionLabel,
326
+ activeBinding,
327
+ activeFieldType,
328
+ activeDatasetFields,
329
+ resolvedRowParentLabel,
330
+ resolvedColParentLabel,
331
+ parentPick,
332
+ rowParentCandidates,
333
+ colParentCandidates,
334
+ bindingEntries,
335
+ metaTick,
336
+ getBindingAt,
337
+ resolveFieldLabel,
338
+ bindField,
339
+ patchActiveBinding,
340
+ startParentPick,
341
+ cancelParentPick,
342
+ pickParentAt,
343
+ clearParent,
344
+ removeActiveBinding,
345
+ resolveCellStyle,
346
+ resolveCellRenderer,
347
+ getTemplate,
348
+ addConnection,
349
+ updateConnection,
350
+ removeConnection,
351
+ addDataset,
352
+ updateDataset,
353
+ removeDataset,
354
+ testConnection,
355
+ describeDataset,
356
+ previewDataset
357
+ };
358
+ }
359
+ //#endregion
360
+ export { useReportDesigner };
@@ -0,0 +1,50 @@
1
+ import { renderReport } from "../../report/render/index.js";
2
+ import { fetchTemplateRecords, resolveParamDefaults, resolveTemplateParams } from "../../report/template.js";
3
+ import { computed, ref, shallowRef, watch } from "vue";
4
+ //#region src/components/report/use-report-viewer.ts
5
+ /**
6
+ * UReportViewer 的 headless 编排:参数提取 → 取数 → renderReport 展开。
7
+ * 不持有 DOM / 网格引用;填充快照经 `filledSnapshot` 交给组件壳应用。
8
+ */
9
+ function useReportViewer(props) {
10
+ const loading = ref(false);
11
+ const error = shallowRef(null);
12
+ const filledSnapshot = shallowRef(null);
13
+ const params = computed(() => resolveTemplateParams(props.template));
14
+ const values = shallowRef({});
15
+ let fetchSeq = 0;
16
+ async function refresh() {
17
+ const current = ++fetchSeq;
18
+ const template = props.template;
19
+ loading.value = true;
20
+ error.value = null;
21
+ const result = await fetchTemplateRecords(props.connector, template, values.value);
22
+ if (current !== fetchSeq) return;
23
+ loading.value = false;
24
+ if (!result.ok) {
25
+ error.value = result.error;
26
+ return;
27
+ }
28
+ filledSnapshot.value = renderReport(template, result.data);
29
+ }
30
+ function setValues(next) {
31
+ values.value = next;
32
+ refresh();
33
+ }
34
+ watch(() => props.template, () => {
35
+ filledSnapshot.value = null;
36
+ values.value = resolveParamDefaults(params.value);
37
+ refresh();
38
+ }, { immediate: true });
39
+ return {
40
+ params,
41
+ values,
42
+ loading,
43
+ error,
44
+ filledSnapshot,
45
+ refresh,
46
+ setValues
47
+ };
48
+ }
49
+ //#endregion
50
+ export { useReportViewer };