@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,356 @@
1
+ <template>
2
+ <div :class="cls.b">
3
+ <div :class="cls.e('toolbar')">
4
+ <u-button size="small" plain @click="hubVisible = true">数据中枢</u-button>
5
+
6
+ <div :class="cls.e('mode-toggle')" role="group" aria-label="视图模式">
7
+ <u-button
8
+ size="small"
9
+ :type="!isPreview ? 'primary' : undefined"
10
+ :plain="isPreview"
11
+ @click="setViewMode('design')"
12
+ >
13
+ 设计模式
14
+ </u-button>
15
+ <u-button
16
+ size="small"
17
+ :type="isPreview ? 'primary' : undefined"
18
+ :plain="!isPreview"
19
+ @click="setViewMode('preview')"
20
+ >
21
+ 预览模式
22
+ </u-button>
23
+ </div>
24
+
25
+ <u-button
26
+ v-if="isPreview"
27
+ size="small"
28
+ type="primary"
29
+ plain
30
+ :loading="exporting"
31
+ @click="exportPreviewXlsx"
32
+ >
33
+ 导出 XLSX
34
+ </u-button>
35
+
36
+ <span :class="cls.e('hint')">
37
+ 在数据中枢配置连接与 SQL
38
+ 数据集,再将左侧字段点击或拖拽到单元格完成绑定;选中已绑定格可通过悬浮卡片调整角色、聚合与条件样式。
39
+ </span>
40
+ </div>
41
+
42
+ <div v-if="!isPreview" :class="cls.e('body')">
43
+ <u-report-field-panel
44
+ :class="cls.e('field-panel')"
45
+ :datasets="catalog"
46
+ :selection-label="selectionLabel"
47
+ :bound-keys="boundKeys"
48
+ @bind="bindField"
49
+ />
50
+
51
+ <div
52
+ ref="gridHostRef"
53
+ :class="cls.e('grid')"
54
+ @dragover="onGridDragOver"
55
+ @dragleave="onGridDragLeave"
56
+ @drop="onGridDrop"
57
+ >
58
+ <u-sheet
59
+ ref="sheetRef"
60
+ :class="cls.e('sheet')"
61
+ :workbook="workbook"
62
+ :rows="DESIGN_ROWS"
63
+ :cols="DESIGN_COLS"
64
+ :show-tabs="false"
65
+ :resolve-cell-style="resolveCellStyle"
66
+ :resolve-cell-renderer="resolveCellRenderer"
67
+ />
68
+
69
+ <u-report-topology-overlay
70
+ :cell="activeCell"
71
+ :binding="activeBinding ?? null"
72
+ :entries="bindingEntries"
73
+ :meta-tick="metaTick"
74
+ :host-el="gridHostEl"
75
+ :get-grid="getDesignGrid"
76
+ :get-binding-at="getBindingAt"
77
+ />
78
+
79
+ <u-report-drop-highlight-overlay
80
+ :cell="dropTargetAddr"
81
+ :host-el="gridHostEl"
82
+ :get-grid="getDesignGrid"
83
+ :dragging="isFieldDragging"
84
+ :fallback-label="selectionLabel"
85
+ />
86
+
87
+ <u-report-float-panel
88
+ :cell="activeCell"
89
+ :binding="activeBinding ?? null"
90
+ :resolved-row-parent-label="resolvedRowParentLabel"
91
+ :resolved-col-parent-label="resolvedColParentLabel"
92
+ :parent-pick-mode="parentPick?.mode ?? null"
93
+ :row-parent-candidates="rowParentCandidates"
94
+ :col-parent-candidates="colParentCandidates"
95
+ :resolve-field-label="resolveFieldLabel"
96
+ :host-el="gridHostEl"
97
+ :get-grid="getDesignGrid"
98
+ @patch="patchActiveBinding"
99
+ @remove="removeActiveBinding"
100
+ @open-rules="rulesDialogVisible = true"
101
+ @start-parent-pick="startParentPick"
102
+ @cancel-parent-pick="cancelParentPick"
103
+ @clear-parent="clearParent"
104
+ />
105
+ </div>
106
+ </div>
107
+
108
+ <div v-else-if="previewTemplate" :class="cls.e('preview')">
109
+ <u-report-viewer
110
+ ref="previewViewerRef"
111
+ :connector="props.connector"
112
+ :template="previewTemplate"
113
+ :workbook="previewWorkbook"
114
+ :col-widths="designColWidths"
115
+ />
116
+ </div>
117
+
118
+ <u-drawer v-model="hubVisible" :class="cls.e('hub-drawer')" show-close>
119
+ <u-report-dataset-hub :hub="designer" @close="hubVisible = false" />
120
+ </u-drawer>
121
+
122
+ <u-report-rules-dialog
123
+ v-model="rulesDialogVisible"
124
+ :rules="activeBinding?.conditionalRules ?? EMPTY_CONDITIONAL_RULES"
125
+ :binding-field="activeBinding?.field ?? ''"
126
+ :dataset-fields="activeDatasetFields"
127
+ :field-type="activeFieldType"
128
+ @save="saveConditionalRules"
129
+ />
130
+ </div>
131
+ </template>
132
+
133
+ <script lang="ts" setup>
134
+ import { UButton, UDrawer } from '@veltra/desktop'
135
+ import type { CellAddress, SheetGrid } from '@veltra/sheet-core'
136
+ import { Workbook } from '@veltra/sheet-core'
137
+ import { bem } from '@veltra/utils'
138
+ import { computed, nextTick, ref, shallowRef, useTemplateRef, watch } from 'vue'
139
+
140
+ import type { ReportTemplate } from '../../report/template'
141
+ import type { ConditionalRule } from '../../report/types'
142
+ import type {
143
+ ReportDesignerEmits,
144
+ ReportDesignerProps,
145
+ ReportViewerExposed,
146
+ SheetExposed,
147
+ _ReportDesignerExposed
148
+ } from '../../types'
149
+ import { USheet } from '../sheet'
150
+ import UReportDatasetHub from './designer-hub.vue'
151
+ import { resolveGridDropAddress } from './designer/cell-coords'
152
+ import { applyGridColWidths, readGridColWidths } from './designer/col-widths'
153
+ import UReportDropHighlightOverlay from './designer/drop-highlight-overlay.vue'
154
+ import UReportFloatPanel from './designer/float-panel.vue'
155
+ import UReportRulesDialog from './designer/rules-dialog.vue'
156
+ import UReportTopologyOverlay from './designer/topology-overlay.vue'
157
+ import { FIELD_DRAG_MIME, parseFieldDragPayload } from './field-panel-helpers'
158
+ import UReportFieldPanel from './field-panel.vue'
159
+ import UReportViewer from './report-viewer.vue'
160
+ import { useReportDesigner } from './use-report-designer'
161
+
162
+ defineOptions({ name: 'UReportDesigner' })
163
+
164
+ const props = withDefaults(defineProps<ReportDesignerProps>(), { connections: () => [] })
165
+ const emit = defineEmits<ReportDesignerEmits>()
166
+
167
+ const cls = bem('report-designer')
168
+
169
+ /** 设计态网格尺寸(列宽捕获范围与之一致) */
170
+ const DESIGN_ROWS = 24
171
+ const DESIGN_COLS = 10
172
+
173
+ /** 条件样式弹窗在无绑定格时的空规则占位 */
174
+ const EMPTY_CONDITIONAL_RULES: ConditionalRule[] = []
175
+
176
+ /** `v-model:connections` 可写代理(连接为纯序列化对象,仅驻留内存) */
177
+ const connections = computed({
178
+ get: () => props.connections,
179
+ set: (value) => emit('update:connections', value)
180
+ })
181
+
182
+ const designer = useReportDesigner({ props, connections })
183
+ const {
184
+ workbook,
185
+ catalog,
186
+ boundKeys,
187
+ activeCell,
188
+ selectionLabel,
189
+ activeBinding,
190
+ activeFieldType,
191
+ activeDatasetFields,
192
+ resolvedRowParentLabel,
193
+ resolvedColParentLabel,
194
+ parentPick,
195
+ rowParentCandidates,
196
+ colParentCandidates,
197
+ bindingEntries,
198
+ metaTick,
199
+ getBindingAt,
200
+ resolveFieldLabel,
201
+ bindField,
202
+ patchActiveBinding,
203
+ startParentPick,
204
+ cancelParentPick,
205
+ pickParentAt,
206
+ clearParent,
207
+ removeActiveBinding,
208
+ resolveCellStyle,
209
+ resolveCellRenderer,
210
+ getTemplate
211
+ } = designer
212
+
213
+ const hubVisible = ref(false)
214
+ const rulesDialogVisible = ref(false)
215
+
216
+ const sheetRef = useTemplateRef<SheetExposed>('sheetRef')
217
+ const previewViewerRef = useTemplateRef<ReportViewerExposed>('previewViewerRef')
218
+ const gridHostRef = useTemplateRef<HTMLElement>('gridHostRef')
219
+ const gridHostEl = computed(() => gridHostRef.value ?? null)
220
+
221
+ /** 字段拖拽落点高亮(dragover 时更新;落空时 overlay 提示回退当前选区) */
222
+ const isFieldDragging = ref(false)
223
+ const dropTargetAddr = ref<CellAddress | null>(null)
224
+
225
+ function getDesignGrid(): SheetGrid | undefined {
226
+ return sheetRef.value?.getGrid()
227
+ }
228
+
229
+ // ---- 设计 / 预览模式切换(预览态内嵌查看器路径,issue 05) ----
230
+
231
+ type ViewMode = 'design' | 'preview'
232
+
233
+ const viewMode = ref<ViewMode>('design')
234
+ const isPreview = computed(() => viewMode.value === 'preview')
235
+
236
+ /** 进入预览时的模板快照(getTemplate 吐出,设计态工作簿不受预览取数影响,切回绑定不丢) */
237
+ const previewTemplate = shallowRef<ReportTemplate | null>(null)
238
+ /** 预览工作簿自持(XLSX 导出需要拿到填充后的 sheet,05 票 workbook? prop 先例) */
239
+ const previewWorkbook = new Workbook()
240
+ /** 当前设计态列宽(sheet-core 列宽未进快照,经 VTable 运行时捕获;导出随快照写宽) */
241
+ const designColWidths = ref<Array<[number, number]>>([])
242
+ const exporting = ref(false)
243
+
244
+ /** 从当前设计网格捕获列宽(网格未就绪则保留旧值) */
245
+ function captureDesignColWidths(): void {
246
+ const widths = readGridColWidths(
247
+ getDesignGrid(),
248
+ Array.from({ length: DESIGN_COLS }, (_, col) => col)
249
+ )
250
+ if (widths) designColWidths.value = widths
251
+ }
252
+
253
+ /** 设计网格重建后补刷新与列宽(restore 不发 content-reset 的场景由 grid 自行订阅,这里只管列宽) */
254
+ function syncDesignGridView(): void {
255
+ const grid = getDesignGrid()
256
+ grid?.flushPending()
257
+ grid?.refresh()
258
+ applyGridColWidths(grid, designColWidths.value)
259
+ }
260
+
261
+ function setViewMode(mode: ViewMode): void {
262
+ if (viewMode.value === mode) return
263
+ if (mode === 'preview') {
264
+ captureDesignColWidths()
265
+ previewTemplate.value = getTemplate()
266
+ }
267
+ viewMode.value = mode
268
+ if (mode === 'design') void nextTick(syncDesignGridView)
269
+ }
270
+
271
+ // 模板 prop 更换:组合式函数内完成载入;组件层切回设计态(预览内容随之作废)
272
+ watch(
273
+ () => props.template,
274
+ () => {
275
+ viewMode.value = 'design'
276
+ }
277
+ )
278
+
279
+ // 父格点选:网格选区变更时写入父格并回到源格
280
+ watch(activeCell, (cell) => {
281
+ if (cell && parentPick.value) pickParentAt(cell)
282
+ })
283
+
284
+ // 徽章文案依赖 catalog(describe 完成 / label 覆盖变更后重绘绑定格;meta 变更由 grid 自行订阅)
285
+ watch(catalog, () => {
286
+ void nextTick(() => getDesignGrid()?.refresh())
287
+ })
288
+
289
+ async function exportPreviewXlsx(): Promise<void> {
290
+ if (!isPreview.value || exporting.value) return
291
+ const viewer = previewViewerRef.value
292
+ if (!viewer) {
293
+ throw new Error('预览查看器尚未就绪,请稍后再导出')
294
+ }
295
+ exporting.value = true
296
+ try {
297
+ await viewer.exportXlsx()
298
+ } finally {
299
+ exporting.value = false
300
+ }
301
+ }
302
+
303
+ function saveConditionalRules(rules: ConditionalRule[]): void {
304
+ patchActiveBinding({ conditionalRules: rules })
305
+ }
306
+
307
+ function clearDropState(): void {
308
+ isFieldDragging.value = false
309
+ dropTargetAddr.value = null
310
+ }
311
+
312
+ function resolveDropAddress(event: DragEvent): CellAddress | null {
313
+ const grid = getDesignGrid()
314
+ const gridEl = gridHostRef.value?.querySelector('.u-sheet__grid-instance') as HTMLElement | null
315
+ if (!grid || !gridEl) return null
316
+ return resolveGridDropAddress(grid, gridEl, event.clientX, event.clientY)
317
+ }
318
+
319
+ function onGridDragOver(event: DragEvent): void {
320
+ if (!event.dataTransfer?.types.includes(FIELD_DRAG_MIME)) return
321
+ event.preventDefault()
322
+ event.dataTransfer.dropEffect = 'copy'
323
+ isFieldDragging.value = true
324
+ dropTargetAddr.value = resolveDropAddress(event)
325
+ }
326
+
327
+ function onGridDragLeave(event: DragEvent): void {
328
+ const host = gridHostRef.value
329
+ const related = event.relatedTarget
330
+ if (host && related instanceof Node && host.contains(related)) return
331
+ clearDropState()
332
+ }
333
+
334
+ function onGridDrop(event: DragEvent): void {
335
+ event.preventDefault()
336
+ clearDropState()
337
+ const raw = event.dataTransfer?.getData(FIELD_DRAG_MIME)
338
+ const payload = raw ? parseFieldDragPayload(raw) : null
339
+ if (!payload) return
340
+
341
+ // 与旧设计器一致:网格未就绪直接放弃;仅 hit-test 落空时回退当前选区
342
+ const grid = getDesignGrid()
343
+ const gridEl = gridHostRef.value?.querySelector('.u-sheet__grid-instance') as HTMLElement | null
344
+ if (!grid || !gridEl) return
345
+
346
+ const dropAddr = resolveDropAddress(event)
347
+ if (dropAddr) {
348
+ bindField(payload.datasetId, payload.fieldName, dropAddr)
349
+ sheetRef.value?.getContext().selectCell(dropAddr)
350
+ } else {
351
+ bindField(payload.datasetId, payload.fieldName)
352
+ }
353
+ }
354
+
355
+ defineExpose<_ReportDesignerExposed>({ getTemplate })
356
+ </script>
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <div :class="cls.b">
3
+ <u-report-filter-bar
4
+ v-if="params.length"
5
+ :query-params="params"
6
+ :values="values"
7
+ @update:values="setValues"
8
+ />
9
+
10
+ <div :class="cls.e('body')">
11
+ <div v-if="loading" :class="cls.e('loading')" aria-live="polite">
12
+ <div :class="cls.e('loading-spinner')" />
13
+ <span>正在加载报表数据…</span>
14
+ </div>
15
+ <div v-else-if="error" :class="cls.e('error')" role="alert">
16
+ {{ error.message }}
17
+ </div>
18
+
19
+ <u-sheet
20
+ ref="sheetRef"
21
+ :class="cls.e('sheet')"
22
+ :workbook="workbook"
23
+ :rows="renderRows"
24
+ :cols="renderCols"
25
+ :show-toolbar="false"
26
+ :show-formula-bar="false"
27
+ :show-tabs="false"
28
+ readonly
29
+ />
30
+ </div>
31
+ </div>
32
+ </template>
33
+
34
+ <script lang="ts" setup>
35
+ import { saveBlob } from '@cat-kit/fe'
36
+ import type { SheetSnapshot } from '@veltra/sheet-core'
37
+ import { Workbook } from '@veltra/sheet-core'
38
+ import { bem } from '@veltra/utils'
39
+ import { computed, nextTick, useTemplateRef, watch } from 'vue'
40
+
41
+ import { exportFilledReportXlsx } from '../../report/export-xlsx'
42
+ import type { ReportViewerProps, _ReportViewerExposed } from '../../types'
43
+ import type { SheetExposed } from '../../types'
44
+ import { USheet } from '../sheet'
45
+ import { applyGridColWidths, readGridColWidths } from './designer/col-widths'
46
+ import UReportFilterBar from './filter-bar.vue'
47
+ import { useReportViewer } from './use-report-viewer'
48
+
49
+ defineOptions({ name: 'UReportViewer' })
50
+
51
+ const props = defineProps<ReportViewerProps>()
52
+
53
+ const cls = bem('report-viewer')
54
+
55
+ /** 网格最小渲染尺寸(与 playground 预览态一致);Filled Report 超出时按快照尺寸放大 */
56
+ const MIN_RENDER_ROWS = 50
57
+ const MIN_RENDER_COLS = 10
58
+
59
+ /** 取数未完成时拒绝导出的可读错误 */
60
+ const EXPORT_NOT_READY_MESSAGE = '报表数据尚未就绪,请等待取数完成后再导出'
61
+ const EXPORT_LOADING_MESSAGE = '报表数据加载中,请稍后再导出'
62
+
63
+ /** 查看器工作簿:宿主可注入(同 USheet `workbook?` 先例),缺省内部自建;模板 / 填充结果都 restore 进活动 sheet 只读展示 */
64
+ const internalWorkbook = new Workbook()
65
+ const workbook = computed(() => props.workbook ?? internalWorkbook)
66
+
67
+ const sheetRef = useTemplateRef<SheetExposed>('sheetRef')
68
+
69
+ const { params, values, loading, error, filledSnapshot, refresh, setValues } =
70
+ useReportViewer(props)
71
+
72
+ const renderRows = computed(() =>
73
+ Math.max(MIN_RENDER_ROWS, filledSnapshot.value?.rows ?? 0, props.template.rows)
74
+ )
75
+ const renderCols = computed(() =>
76
+ Math.max(MIN_RENDER_COLS, filledSnapshot.value?.cols ?? 0, props.template.cols)
77
+ )
78
+
79
+ function exportColIndexes(): number[] {
80
+ return Array.from({ length: renderCols.value }, (_, col) => col)
81
+ }
82
+
83
+ /** 将宿主传入的列宽写入 VTable 运行时(sheet-core 列宽未进快照) */
84
+ function applyRuntimeColWidths(): void {
85
+ if (!props.colWidths?.length) return
86
+ applyGridColWidths(sheetRef.value?.getGrid(), props.colWidths)
87
+ }
88
+
89
+ /**
90
+ * restore 负责尺寸/冻结/行高/选区(静默),restoreContent 发 content-reset
91
+ * 触发网格全量刷新(grid 层订阅直刷,无需手动 flush);history.clear 使填充不进 undo
92
+ */
93
+ function applySnapshot(snapshot: SheetSnapshot): void {
94
+ const sheet = workbook.value.activeSheet
95
+ sheet.restore(snapshot)
96
+ sheet.restoreContent(snapshot)
97
+ sheet.history.clear()
98
+ void nextTick(applyRuntimeColWidths)
99
+ }
100
+
101
+ // 先铺模板静态结构(取数期间 / 取数失败时可见),取数成功后替换为 Filled Report
102
+ watch(() => props.template, applySnapshot, { immediate: true })
103
+ watch(filledSnapshot, (filled) => {
104
+ if (filled) applySnapshot(filled)
105
+ })
106
+ watch(() => props.colWidths, applyRuntimeColWidths)
107
+
108
+ async function exportXlsx(): Promise<void> {
109
+ if (loading.value) {
110
+ throw new Error(EXPORT_LOADING_MESSAGE)
111
+ }
112
+ if (!filledSnapshot.value) {
113
+ throw new Error(EXPORT_NOT_READY_MESSAGE)
114
+ }
115
+
116
+ const sheet = workbook.value.activeSheet
117
+ const colWidths = readGridColWidths(sheetRef.value?.getGrid(), exportColIndexes()) ?? []
118
+ const buffer = await exportFilledReportXlsx(sheet, colWidths)
119
+ saveBlob(
120
+ new Blob([buffer as unknown as BlobPart], {
121
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
122
+ }),
123
+ `${sheet.name || '报表'}.xlsx`
124
+ )
125
+ }
126
+
127
+ defineExpose<_ReportViewerExposed>({ refresh, exportXlsx })
128
+ </script>