@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,547 @@
1
+ import type { CellAddress } from '@veltra/sheet-core'
2
+ import type { ResolveCellRenderer, ResolveCellStyleHook } from '@veltra/sheet-core'
3
+ import { Workbook } from '@veltra/sheet-core'
4
+ import { computed, onScopeDispose, ref, watch, type ComputedRef, type Ref } from 'vue'
5
+
6
+ import {
7
+ REPORT_META_NAMESPACE,
8
+ applyReportPreset,
9
+ createReportBinding,
10
+ formatCellAddress,
11
+ inferColParentCandidate,
12
+ inferDropPreset,
13
+ inferRowParentCandidate,
14
+ isHorizontalExpandBinding,
15
+ isVerticalExpandBinding,
16
+ listColParentCandidates,
17
+ listRowParentCandidates
18
+ } from '../../report/binding'
19
+ import type { DataConnection, QueryResult, Result } from '../../report/connector'
20
+ import { buildParamDefs } from '../../report/params'
21
+ import {
22
+ assertCompatibleTemplateVersion,
23
+ createReportTemplate,
24
+ getTemplateDatasets,
25
+ resolveParamDefaults,
26
+ type ReportDatasetDef,
27
+ type ReportTemplate
28
+ } from '../../report/template'
29
+ import type { DatasetCatalogItem, DatasetField, ReportBinding } from '../../report/types'
30
+ import type { ReportDesignerProps } from '../../types'
31
+ import { createBindingBadgeRenderer, createBindingBadgeStyleResolver } from './binding-badge'
32
+ import type { TopologyBindingEntry } from './designer/topology'
33
+
34
+ /**
35
+ * 设计器内部数据集:以 `connectionId` 引用连接(连接列表经 `v-model:connections`
36
+ * 注入,是单一事实源);`getTemplate()` 吐出模板时解析为内嵌连接对象(`ReportDatasetDef`)。
37
+ */
38
+ export interface DesignerDataset {
39
+ id: string
40
+ label: string
41
+ connectionId: string
42
+ sql: string
43
+ /** 参数元数据覆盖(label / 类型 / 默认值 / 选项) */
44
+ paramOverrides?: ReportDatasetDef['paramOverrides']
45
+ /** 字段中文名覆盖(name → label) */
46
+ fieldOverrides?: ReportDatasetDef['fieldOverrides']
47
+ /** describe 解析的字段缓存(字段面板 catalog 的数据源;fieldOverrides 在 catalog 层应用) */
48
+ fields?: DatasetField[]
49
+ }
50
+
51
+ /** 数据中枢 drawer 的消费面(`UseReportDesignerReturn` 的子集) */
52
+ export interface DatasetHubController {
53
+ connections: Ref<DataConnection[]>
54
+ datasets: Ref<DesignerDataset[]>
55
+ addConnection: (connection: DataConnection) => void
56
+ updateConnection: (connection: DataConnection) => void
57
+ /** 删除连接并级联删除其数据集 */
58
+ removeConnection: (connectionId: string) => void
59
+ addDataset: (connectionId: string) => DesignerDataset
60
+ updateDataset: (datasetId: string, patch: Partial<Omit<DesignerDataset, 'id'>>) => void
61
+ removeDataset: (datasetId: string) => void
62
+ /** 真实测试连接(契约无状态,新建草稿同样可测) */
63
+ testConnection: (connection: DataConnection) => Promise<Result<void>>
64
+ /** 经连接器 describe 解析字段并写入数据集字段缓存 */
65
+ describeDataset: (datasetId: string) => Promise<Result<DatasetField[]>>
66
+ /** 按参数默认值经连接器取数(数据集记录预览) */
67
+ previewDataset: (datasetId: string) => Promise<Result<QueryResult>>
68
+ }
69
+
70
+ export type ParentPickMode = 'row' | 'col'
71
+
72
+ export interface ParentPickState {
73
+ mode: ParentPickMode
74
+ source: CellAddress
75
+ }
76
+
77
+ export interface UseReportDesignerReturn extends DatasetHubController {
78
+ workbook: ComputedRef<Workbook>
79
+ /** 字段面板目录(数据集 + 应用 fieldOverrides 后的字段 label) */
80
+ catalog: ComputedRef<DatasetCatalogItem[]>
81
+ /** 已绑定字段键集合:`${datasetId}:${fieldName}` */
82
+ boundKeys: ComputedRef<Set<string>>
83
+ /** 当前选区地址(跟随模型 selection-change) */
84
+ activeCell: Ref<CellAddress | null>
85
+ /** 当前选区 A1 标签 */
86
+ selectionLabel: ComputedRef<string>
87
+ /** 当前选区绑定(跟随 meta-change) */
88
+ activeBinding: ComputedRef<ReportBinding | undefined>
89
+ /** 当前选区绑定字段的数据类型(条件规则对话框控件映射用;缺省 number) */
90
+ activeFieldType: ComputedRef<DatasetField['type']>
91
+ /** 当前绑定所属数据集的字段列表(条件规则求值字段选择) */
92
+ activeDatasetFields: ComputedRef<DatasetField[]>
93
+ /** 当前选区绑定的行方向父格 A1 标签(无父格显示 —) */
94
+ resolvedRowParentLabel: ComputedRef<string>
95
+ /** 当前选区绑定的列方向父格 A1 标签(无父格显示 —) */
96
+ resolvedColParentLabel: ComputedRef<string>
97
+ /** 父格点选态(进入后在网格上点目标格写入父格) */
98
+ parentPick: Ref<ParentPickState | null>
99
+ /** 行方向父格下拉候选(同数据集纵向扩展绑定格) */
100
+ rowParentCandidates: ComputedRef<CellAddress[]>
101
+ /** 列方向父格下拉候选(同数据集横向扩展绑定格) */
102
+ colParentCandidates: ComputedRef<CellAddress[]>
103
+ /** 全部绑定条目(拓扑连线数据源;跟随 meta-change) */
104
+ bindingEntries: ComputedRef<TopologyBindingEntry[]>
105
+ /** meta 变更计数(网格覆层组件的同步信号) */
106
+ metaTick: Ref<number>
107
+ getBindingAt: (addr: CellAddress) => ReportBinding | undefined
108
+ /** 字段 label 解析(catalog O(1) 查找;Action Pill 摘要与徽章共用) */
109
+ resolveFieldLabel: (datasetId: string, fieldName: string) => string
110
+ /** 拖拽/点击落格写 Cell Meta 绑定(角色推导与 playground 设计器一致) */
111
+ bindField: (datasetId: string, fieldName: string, addr?: CellAddress) => void
112
+ /** 就地修补当前选区绑定(Action Pill:预设 / 展开方向 / 父格 / 聚合 / 排序 / 条件规则) */
113
+ patchActiveBinding: (patch: Partial<ReportBinding>) => void
114
+ /** 进入父格点选态 */
115
+ startParentPick: (mode: ParentPickMode) => void
116
+ /** 取消父格点选态 */
117
+ cancelParentPick: () => void
118
+ /** 父格点选:将目标格写入当前编辑格的 rowParent / colParent */
119
+ pickParentAt: (target: CellAddress) => void
120
+ /** 清除行 / 列方向父格 */
121
+ clearParent: (mode: ParentPickMode) => void
122
+ /** 清除当前选区绑定 */
123
+ removeActiveBinding: () => void
124
+ /** 绑定格角色底色样式 hook(与徽章 renderer 配套) */
125
+ resolveCellStyle: ResolveCellStyleHook
126
+ /** 绑定格角色徽章渲染 hook(ADR-0004) */
127
+ resolveCellRenderer: ResolveCellRenderer
128
+ /** 取回含 meta 绑定与内嵌数据集定义的 Report Template */
129
+ getTemplate: () => ReportTemplate
130
+ }
131
+
132
+ export interface UseReportDesignerOptions {
133
+ props: ReportDesignerProps
134
+ /** `v-model:connections` 可写代理(get 读 props,set 触发 `update:connections`) */
135
+ connections: Ref<DataConnection[]>
136
+ }
137
+
138
+ /**
139
+ * UReportDesigner 的 headless 编排:连接 / 数据集状态、绑定写 Cell Meta、
140
+ * 角色徽章渲染 hook、`getTemplate()` 模板吐出。不持有 DOM / 网格引用。
141
+ */
142
+ export function useReportDesigner(options: UseReportDesignerOptions): UseReportDesignerReturn {
143
+ const { props, connections } = options
144
+
145
+ /** 设计态工作簿:宿主可注入(USheet / UReportViewer 先例),缺省内部自建 */
146
+ const internalWorkbook = new Workbook()
147
+ const workbook = computed(() => props.workbook ?? internalWorkbook)
148
+
149
+ const datasets = ref<DesignerDataset[]>([])
150
+
151
+ /** meta 变更计数:boundKeys 等派生状态的响应式触发(绑定经命令系统写入后由模型发 meta-change) */
152
+ const metaTick = ref(0)
153
+ const parentPick = ref<ParentPickState | null>(null)
154
+ const offMeta = workbook.value.activeSheet.on('meta-change', () => {
155
+ metaTick.value++
156
+ })
157
+ onScopeDispose(offMeta)
158
+
159
+ /** 稳定选区地址引用(值未变时不替换对象,避免触发下游 watcher) */
160
+ const activeCell = ref<CellAddress | null>(null)
161
+ function syncActiveCell(): void {
162
+ const next = workbook.value.activeSheet.getSelection().activeCell ?? null
163
+ const prev = activeCell.value
164
+ if (!next) {
165
+ activeCell.value = null
166
+ return
167
+ }
168
+ if (prev && prev.row === next.row && prev.col === next.col) return
169
+ activeCell.value = { row: next.row, col: next.col }
170
+ }
171
+ const offSelection = workbook.value.activeSheet.on('selection-change', syncActiveCell)
172
+ onScopeDispose(offSelection)
173
+ syncActiveCell()
174
+
175
+ const selectionLabel = computed(() =>
176
+ activeCell.value ? formatCellAddress(activeCell.value) : '—'
177
+ )
178
+
179
+ const catalog = computed((): DatasetCatalogItem[] =>
180
+ datasets.value.map((dataset) => ({
181
+ id: dataset.id,
182
+ label: dataset.label,
183
+ fields: (dataset.fields ?? []).map((field) => ({
184
+ ...field,
185
+ label: dataset.fieldOverrides?.[field.name]?.label ?? field.label
186
+ }))
187
+ }))
188
+ )
189
+
190
+ /** 字段 label 的 O(1) 查找表(徽章 hook 性能契约) */
191
+ const fieldLabelMap = computed(() => {
192
+ const map = new Map<string, string>()
193
+ for (const dataset of catalog.value) {
194
+ for (const field of dataset.fields) map.set(`${dataset.id}:${field.name}`, field.label)
195
+ }
196
+ return map
197
+ })
198
+
199
+ function resolveFieldLabel(datasetId: string, fieldName: string): string {
200
+ return fieldLabelMap.value.get(`${datasetId}:${fieldName}`) ?? fieldName
201
+ }
202
+
203
+ const boundKeys = computed(() => {
204
+ metaTick.value
205
+ const keys = new Set<string>()
206
+ for (const [, namespace, payload] of workbook.value.activeSheet.entriesCellMeta()) {
207
+ if (namespace !== REPORT_META_NAMESPACE) continue
208
+ const binding = payload as ReportBinding
209
+ keys.add(`${binding.dataset}:${binding.field}`)
210
+ }
211
+ return keys
212
+ })
213
+
214
+ function getBindingAt(addr: CellAddress): ReportBinding | undefined {
215
+ return workbook.value.activeSheet.getCellMeta<ReportBinding>(addr, REPORT_META_NAMESPACE)
216
+ }
217
+
218
+ function bindField(datasetId: string, fieldName: string, addr?: CellAddress): void {
219
+ const dataset = catalog.value.find((item) => item.id === datasetId)
220
+ if (!dataset) return
221
+
222
+ const field = dataset.fields.find((item) => item.name === fieldName)
223
+ const target = addr ?? workbook.value.activeSheet.getSelection().activeCell
224
+ if (!target) return
225
+
226
+ const preset = inferDropPreset(target, field?.type ?? 'string', getBindingAt)
227
+ let binding = createReportBinding(dataset, fieldName)
228
+ binding = applyReportPreset(binding, preset)
229
+
230
+ const rowParent = inferRowParentCandidate(target, getBindingAt)
231
+ if (rowParent) binding.rowParent = rowParent
232
+ const colParent = inferColParentCandidate(target, getBindingAt)
233
+ if (colParent) binding.colParent = colParent
234
+
235
+ workbook.value.activeSheet.setCellMeta(target, REPORT_META_NAMESPACE, binding)
236
+ }
237
+
238
+ // ---- Action Pill / 拓扑连线(playground 设计器平移,行为不变) ----
239
+
240
+ const activeBinding = computed((): ReportBinding | undefined => {
241
+ metaTick.value
242
+ const cell = activeCell.value
243
+ if (!cell) return undefined
244
+ return getBindingAt(cell)
245
+ })
246
+
247
+ const activeFieldType = computed((): DatasetField['type'] => {
248
+ const binding = activeBinding.value
249
+ if (!binding) return 'number'
250
+ const dataset = catalog.value.find((item) => item.id === binding.dataset)
251
+ const field = dataset?.fields.find((item) => item.name === binding.field)
252
+ return field?.type ?? 'number'
253
+ })
254
+
255
+ const activeDatasetFields = computed((): DatasetField[] => {
256
+ const binding = activeBinding.value
257
+ if (!binding) return []
258
+ return catalog.value.find((item) => item.id === binding.dataset)?.fields ?? []
259
+ })
260
+
261
+ const resolvedRowParentLabel = computed(() => {
262
+ metaTick.value
263
+ const binding = activeBinding.value
264
+ if (!binding?.rowParent) return '—'
265
+ return formatCellAddress(binding.rowParent)
266
+ })
267
+
268
+ const resolvedColParentLabel = computed(() => {
269
+ metaTick.value
270
+ const binding = activeBinding.value
271
+ if (!binding?.colParent) return '—'
272
+ return formatCellAddress(binding.colParent)
273
+ })
274
+
275
+ const rowParentCandidates = computed((): CellAddress[] => {
276
+ metaTick.value
277
+ const binding = activeBinding.value
278
+ if (!binding) return []
279
+ return listRowParentCandidates(binding, bindingEntries.value)
280
+ })
281
+
282
+ const colParentCandidates = computed((): CellAddress[] => {
283
+ metaTick.value
284
+ const binding = activeBinding.value
285
+ if (!binding) return []
286
+ return listColParentCandidates(binding, bindingEntries.value)
287
+ })
288
+
289
+ const bindingEntries = computed((): TopologyBindingEntry[] => {
290
+ metaTick.value
291
+ const entries: TopologyBindingEntry[] = []
292
+ for (const [addr, namespace, payload] of workbook.value.activeSheet.entriesCellMeta()) {
293
+ if (namespace !== REPORT_META_NAMESPACE) continue
294
+ entries.push({ addr, binding: payload as ReportBinding })
295
+ }
296
+ return entries
297
+ })
298
+
299
+ function patchActiveBinding(patch: Partial<ReportBinding>): void {
300
+ const cell = activeCell.value
301
+ const binding = activeBinding.value
302
+ if (!cell || !binding) return
303
+
304
+ const next: ReportBinding = { ...binding, ...patch }
305
+ if ('rowParent' in patch && patch.rowParent === undefined) delete next.rowParent
306
+ if ('colParent' in patch && patch.colParent === undefined) delete next.colParent
307
+ if (('aggregate' in patch || 'expand' in patch) && !('preset' in patch)) delete next.preset
308
+
309
+ workbook.value.activeSheet.setCellMeta(cell, REPORT_META_NAMESPACE, next)
310
+ }
311
+
312
+ function startParentPick(mode: ParentPickMode): void {
313
+ const cell = activeCell.value
314
+ if (!cell || !activeBinding.value) return
315
+ parentPick.value = { mode, source: { row: cell.row, col: cell.col } }
316
+ }
317
+
318
+ function cancelParentPick(): void {
319
+ parentPick.value = null
320
+ }
321
+
322
+ function pickParentAt(target: CellAddress): void {
323
+ const pick = parentPick.value
324
+ if (!pick) return
325
+ if (target.row === pick.source.row && target.col === pick.source.col) return
326
+
327
+ const sourceBinding = getBindingAt(pick.source)
328
+ const targetBinding = getBindingAt(target)
329
+ if (!sourceBinding || !targetBinding) return
330
+ if (targetBinding.dataset !== sourceBinding.dataset) return
331
+ if (pick.mode === 'row' && !isVerticalExpandBinding(targetBinding)) return
332
+ if (pick.mode === 'col' && !isHorizontalExpandBinding(targetBinding)) return
333
+
334
+ const patch = pick.mode === 'row' ? { rowParent: { ...target } } : { colParent: { ...target } }
335
+ const next: ReportBinding = { ...sourceBinding, ...patch }
336
+ workbook.value.activeSheet.setCellMeta(pick.source, REPORT_META_NAMESPACE, next)
337
+ parentPick.value = null
338
+ workbook.value.activeSheet.selectCell(pick.source)
339
+ }
340
+
341
+ function clearParent(mode: ParentPickMode): void {
342
+ if (mode === 'row') patchActiveBinding({ rowParent: undefined })
343
+ else patchActiveBinding({ colParent: undefined })
344
+ }
345
+
346
+ function removeActiveBinding(): void {
347
+ const cell = activeCell.value
348
+ if (!cell) return
349
+ workbook.value.activeSheet.clearCellMeta(cell, REPORT_META_NAMESPACE)
350
+ }
351
+
352
+ // ---- 数据中枢:连接 / 数据集 CRUD 与连接器调用 ----
353
+
354
+ function addConnection(connection: DataConnection): void {
355
+ connections.value = [...connections.value, connection]
356
+ }
357
+
358
+ function updateConnection(connection: DataConnection): void {
359
+ connections.value = connections.value.map((item) =>
360
+ item.id === connection.id ? connection : item
361
+ )
362
+ }
363
+
364
+ function removeConnection(connectionId: string): void {
365
+ connections.value = connections.value.filter((item) => item.id !== connectionId)
366
+ // 级联删除其数据集(playground 设计器平移)
367
+ datasets.value = datasets.value.filter((dataset) => dataset.connectionId !== connectionId)
368
+ }
369
+
370
+ let datasetSeq = 0
371
+ function addDataset(connectionId: string): DesignerDataset {
372
+ const dataset: DesignerDataset = {
373
+ id: `dataset-${Date.now()}-${datasetSeq++}`,
374
+ label: '新数据集',
375
+ connectionId,
376
+ sql: ''
377
+ }
378
+ datasets.value = [...datasets.value, dataset]
379
+ return dataset
380
+ }
381
+
382
+ function updateDataset(datasetId: string, patch: Partial<Omit<DesignerDataset, 'id'>>): void {
383
+ datasets.value = datasets.value.map((item) =>
384
+ item.id === datasetId ? { ...item, ...patch } : item
385
+ )
386
+ }
387
+
388
+ function removeDataset(datasetId: string): void {
389
+ datasets.value = datasets.value.filter((item) => item.id !== datasetId)
390
+ }
391
+
392
+ function resolveDatasetConnection(dataset: DesignerDataset): DataConnection | undefined {
393
+ return connections.value.find((item) => item.id === dataset.connectionId)
394
+ }
395
+
396
+ function datasetNotFound(): Result<never> {
397
+ return { ok: false, error: { code: 'DATASET_NOT_FOUND', message: '数据集不存在' } }
398
+ }
399
+
400
+ function connectionNotFound(): Result<never> {
401
+ return { ok: false, error: { code: 'CONNECTION_NOT_FOUND', message: '数据集所属连接不存在' } }
402
+ }
403
+
404
+ function testConnection(connection: DataConnection): Promise<Result<void>> {
405
+ return props.connector.test(connection)
406
+ }
407
+
408
+ async function describeDataset(datasetId: string): Promise<Result<DatasetField[]>> {
409
+ const dataset = datasets.value.find((item) => item.id === datasetId)
410
+ if (!dataset) return datasetNotFound()
411
+ const connection = resolveDatasetConnection(dataset)
412
+ if (!connection) return connectionNotFound()
413
+
414
+ const sql = dataset.sql
415
+ const result = await props.connector.describe(connection, sql)
416
+ // 并发守卫:describe 返回时 SQL 已再变更则丢弃过期结果
417
+ if (result.ok) {
418
+ const current = datasets.value.find((item) => item.id === datasetId)
419
+ if (current && current.sql === sql) updateDataset(datasetId, { fields: result.data })
420
+ }
421
+ return result
422
+ }
423
+
424
+ async function previewDataset(datasetId: string): Promise<Result<QueryResult>> {
425
+ const dataset = datasets.value.find((item) => item.id === datasetId)
426
+ if (!dataset) return datasetNotFound()
427
+ const connection = resolveDatasetConnection(dataset)
428
+ if (!connection) return connectionNotFound()
429
+
430
+ const values = resolveParamDefaults(buildParamDefs(dataset.sql, dataset.paramOverrides))
431
+ return props.connector.query(connection, dataset.sql, values)
432
+ }
433
+
434
+ // ---- 渲染与模板 ----
435
+
436
+ const resolveCellStyle = createBindingBadgeStyleResolver(getBindingAt)
437
+ const resolveCellRenderer = createBindingBadgeRenderer(getBindingAt, resolveFieldLabel)
438
+
439
+ function getTemplate(): ReportTemplate {
440
+ const resolved: ReportDatasetDef[] = datasets.value.flatMap((dataset) => {
441
+ const connection = resolveDatasetConnection(dataset)
442
+ if (!connection) return []
443
+ return [
444
+ {
445
+ id: dataset.id,
446
+ label: dataset.label,
447
+ connection: { ...connection },
448
+ sql: dataset.sql,
449
+ ...(dataset.paramOverrides ? { paramOverrides: dataset.paramOverrides } : {}),
450
+ ...(dataset.fieldOverrides ? { fieldOverrides: dataset.fieldOverrides } : {})
451
+ }
452
+ ]
453
+ })
454
+ // `Sheet.snapshot()` 不产生 datasets 字段(restore 往返会丢失),吐出时附加内嵌数据集定义
455
+ return createReportTemplate(workbook.value.activeSheet.snapshot(), resolved)
456
+ }
457
+
458
+ /**
459
+ * 载入既有 Report Template 继续设计(`template` prop):
460
+ * 快照恢复网格绑定(restore + restoreContent 与查看器同路径);
461
+ * 内嵌数据集定义还原为设计态(connectionId 引用),内嵌连接按 id 合并进
462
+ * v-model 连接列表(仅缺省追加,宿主列表是单一事实源);
463
+ * describe 恢复字段缓存(字段面板数据源),业务错误忽略(字段留空,可在数据中枢重试)。
464
+ */
465
+ function loadTemplate(template: ReportTemplate): void {
466
+ assertCompatibleTemplateVersion(template)
467
+ const sheet = workbook.value.activeSheet
468
+ sheet.restore(template)
469
+ sheet.restoreContent(template)
470
+ sheet.history.clear()
471
+ syncActiveCell()
472
+
473
+ const defs = getTemplateDatasets(template)
474
+ datasets.value = defs.map((def) => ({
475
+ id: def.id,
476
+ label: def.label,
477
+ connectionId: def.connection.id,
478
+ sql: def.sql,
479
+ ...(def.paramOverrides ? { paramOverrides: def.paramOverrides } : {}),
480
+ ...(def.fieldOverrides ? { fieldOverrides: def.fieldOverrides } : {})
481
+ }))
482
+
483
+ const missing = defs
484
+ .map((def) => def.connection)
485
+ .filter((connection) => !connections.value.some((item) => item.id === connection.id))
486
+ if (missing.length > 0) {
487
+ connections.value = [
488
+ ...connections.value,
489
+ ...missing.map((connection) => ({ ...connection }))
490
+ ]
491
+ }
492
+
493
+ for (const dataset of datasets.value) {
494
+ if (dataset.sql.trim()) void describeDataset(dataset.id)
495
+ }
496
+ }
497
+
498
+ // 模板更换:重新载入(仅在提供了 template 时;缺省为空白设计态)
499
+ watch(
500
+ () => props.template,
501
+ (template) => {
502
+ if (template) loadTemplate(template)
503
+ },
504
+ { immediate: true }
505
+ )
506
+
507
+ return {
508
+ workbook,
509
+ connections,
510
+ datasets,
511
+ catalog,
512
+ boundKeys,
513
+ activeCell,
514
+ selectionLabel,
515
+ activeBinding,
516
+ activeFieldType,
517
+ activeDatasetFields,
518
+ resolvedRowParentLabel,
519
+ resolvedColParentLabel,
520
+ parentPick,
521
+ rowParentCandidates,
522
+ colParentCandidates,
523
+ bindingEntries,
524
+ metaTick,
525
+ getBindingAt,
526
+ resolveFieldLabel,
527
+ bindField,
528
+ patchActiveBinding,
529
+ startParentPick,
530
+ cancelParentPick,
531
+ pickParentAt,
532
+ clearParent,
533
+ removeActiveBinding,
534
+ resolveCellStyle,
535
+ resolveCellRenderer,
536
+ getTemplate,
537
+ addConnection,
538
+ updateConnection,
539
+ removeConnection,
540
+ addDataset,
541
+ updateDataset,
542
+ removeDataset,
543
+ testConnection,
544
+ describeDataset,
545
+ previewDataset
546
+ }
547
+ }
@@ -0,0 +1,79 @@
1
+ import type { SheetSnapshot } from '@veltra/sheet-core'
2
+ import { computed, ref, shallowRef, watch, type ComputedRef, type Ref, type ShallowRef } from 'vue'
3
+
4
+ import type { ConnectorError } from '../../report/connector'
5
+ import { renderReport } from '../../report/render'
6
+ import {
7
+ fetchTemplateRecords,
8
+ resolveParamDefaults,
9
+ resolveTemplateParams
10
+ } from '../../report/template'
11
+ import type { ParamValues, QueryParamDef } from '../../report/types'
12
+ import type { ReportViewerProps } from '../../types'
13
+
14
+ export interface UseReportViewerReturn {
15
+ /** Filter Bar 参数(模板实际绑定的数据集的查询参数并集) */
16
+ params: ComputedRef<QueryParamDef[]>
17
+ /** 当前运行时参数值(初始为参数默认值) */
18
+ values: Ref<ParamValues>
19
+ /** 取数中 */
20
+ loading: Ref<boolean>
21
+ /** 最近一次取数的业务错误(可读提示;成功或重新取数时清空) */
22
+ error: ShallowRef<ConnectorError | null>
23
+ /** 最近一次成功展开渲染的 Filled Report 快照(组件壳据此替换网格内容) */
24
+ filledSnapshot: ShallowRef<SheetSnapshot | null>
25
+ /** 重新取数并展开渲染 */
26
+ refresh: () => Promise<void>
27
+ /** Filter Bar 改值:写入新参数值并重新取数 */
28
+ setValues: (next: ParamValues) => void
29
+ }
30
+
31
+ /**
32
+ * UReportViewer 的 headless 编排:参数提取 → 取数 → renderReport 展开。
33
+ * 不持有 DOM / 网格引用;填充快照经 `filledSnapshot` 交给组件壳应用。
34
+ */
35
+ export function useReportViewer(props: ReportViewerProps): UseReportViewerReturn {
36
+ const loading = ref(false)
37
+ const error = shallowRef<ConnectorError | null>(null)
38
+ const filledSnapshot = shallowRef<SheetSnapshot | null>(null)
39
+
40
+ const params = computed(() => resolveTemplateParams(props.template))
41
+ // 初始值由下方 immediate watch 播种(参数默认值)
42
+ const values = shallowRef<ParamValues>({})
43
+
44
+ // 并发守卫:只应用最后一次取数结果(Filter Bar 连续改值时前序结果作废)
45
+ let fetchSeq = 0
46
+
47
+ async function refresh(): Promise<void> {
48
+ const current = ++fetchSeq
49
+ const template = props.template
50
+ loading.value = true
51
+ error.value = null
52
+ const result = await fetchTemplateRecords(props.connector, template, values.value)
53
+ if (current !== fetchSeq) return
54
+ loading.value = false
55
+ if (!result.ok) {
56
+ error.value = result.error
57
+ return
58
+ }
59
+ filledSnapshot.value = renderReport(template, result.data)
60
+ }
61
+
62
+ function setValues(next: ParamValues): void {
63
+ values.value = next
64
+ void refresh()
65
+ }
66
+
67
+ // 模板更换:清空上一模板的填充结果,参数值重置为新模板默认值并重新取数
68
+ watch(
69
+ () => props.template,
70
+ () => {
71
+ filledSnapshot.value = null
72
+ values.value = resolveParamDefaults(params.value)
73
+ void refresh()
74
+ },
75
+ { immediate: true }
76
+ )
77
+
78
+ return { params, values, loading, error, filledSnapshot, refresh, setValues }
79
+ }