@veltra/sheet 2.4.0 → 2.5.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 (142) hide show
  1. package/dist/index.d.ts +2 -19
  2. package/dist/index.js +2 -15
  3. package/dist/types/index.d.ts +1 -3
  4. package/package.json +2 -3
  5. package/src/index.ts +1 -27
  6. package/src/types/index.ts +0 -2
  7. package/dist/components/report/binding-badge.js +0 -118
  8. package/dist/components/report/designer/cell-coords.js +0 -46
  9. package/dist/components/report/designer/col-widths.js +0 -29
  10. package/dist/components/report/designer/conditional-rules/helpers.js +0 -139
  11. package/dist/components/report/designer/drill-dialog.js +0 -258
  12. package/dist/components/report/designer/drop-highlight-overlay.js +0 -76
  13. package/dist/components/report/designer/float-panel.js +0 -434
  14. package/dist/components/report/designer/role.js +0 -17
  15. package/dist/components/report/designer/rule-preview.js +0 -33
  16. package/dist/components/report/designer/rule-row.js +0 -253
  17. package/dist/components/report/designer/rules-dialog.js +0 -118
  18. package/dist/components/report/designer/topology-overlay.js +0 -122
  19. package/dist/components/report/designer/topology.js +0 -64
  20. package/dist/components/report/designer/use-grid-overlay.js +0 -75
  21. package/dist/components/report/designer-hub.js +0 -177
  22. package/dist/components/report/field-panel-helpers.js +0 -33
  23. package/dist/components/report/field-panel.js +0 -132
  24. package/dist/components/report/filter-bar.js +0 -74
  25. package/dist/components/report/hub-connection-form.js +0 -145
  26. package/dist/components/report/hub-dataset-editor.js +0 -409
  27. package/dist/components/report/preview-grid-size.js +0 -32
  28. package/dist/components/report/print.js +0 -39
  29. package/dist/components/report/report-designer.js +0 -428
  30. package/dist/components/report/report-viewer.js +0 -253
  31. package/dist/components/report/style.d.ts +0 -17
  32. package/dist/components/report/style.js +0 -18
  33. package/dist/components/report/style2.css +0 -965
  34. package/dist/components/report/use-report-designer.js +0 -387
  35. package/dist/components/report/use-report-viewer.js +0 -140
  36. package/dist/report/binding.d.ts +0 -83
  37. package/dist/report/binding.js +0 -334
  38. package/dist/report/connector.d.ts +0 -66
  39. package/dist/report/connector.js +0 -159
  40. package/dist/report/drill.d.ts +0 -48
  41. package/dist/report/drill.js +0 -78
  42. package/dist/report/export-xlsx.d.ts +0 -13
  43. package/dist/report/export-xlsx.js +0 -13
  44. package/dist/report/filter-bar.d.ts +0 -10
  45. package/dist/report/filter-bar.js +0 -31
  46. package/dist/report/index.d.ts +0 -14
  47. package/dist/report/params.d.ts +0 -13
  48. package/dist/report/params.js +0 -61
  49. package/dist/report/print.d.ts +0 -23
  50. package/dist/report/print.js +0 -197
  51. package/dist/report/render/aggregate.js +0 -193
  52. package/dist/report/render/builder.d.ts +0 -12
  53. package/dist/report/render/builder.js +0 -139
  54. package/dist/report/render/coordinate.d.ts +0 -25
  55. package/dist/report/render/coordinate.js +0 -733
  56. package/dist/report/render/index.d.ts +0 -14
  57. package/dist/report/render/index.js +0 -21
  58. package/dist/report/render/style-resolver.js +0 -50
  59. package/dist/report/render/template-index.d.ts +0 -24
  60. package/dist/report/render/template-index.js +0 -137
  61. package/dist/report/rules/evaluate.d.ts +0 -25
  62. package/dist/report/rules/evaluate.js +0 -82
  63. package/dist/report/rules/index.d.ts +0 -2
  64. package/dist/report/template.d.ts +0 -63
  65. package/dist/report/template.js +0 -83
  66. package/dist/report/types.d.ts +0 -103
  67. package/dist/types/report-designer.d.ts +0 -51
  68. package/dist/types/report-viewer.d.ts +0 -57
  69. package/src/components/report/__test__/binding-badge.test.ts +0 -92
  70. package/src/components/report/__test__/conditional-rules-helpers.test.ts +0 -88
  71. package/src/components/report/__test__/field-panel-helpers.test.ts +0 -65
  72. package/src/components/report/__test__/float-panel-position.test.ts +0 -45
  73. package/src/components/report/__test__/preview-grid-size.test.ts +0 -63
  74. package/src/components/report/__test__/report-designer.test.ts +0 -559
  75. package/src/components/report/__test__/report-drill.test.ts +0 -692
  76. package/src/components/report/__test__/report-viewer.test.ts +0 -400
  77. package/src/components/report/__test__/topology.test.ts +0 -143
  78. package/src/components/report/__test__/use-report-designer.test.ts +0 -804
  79. package/src/components/report/binding-badge.ts +0 -122
  80. package/src/components/report/designer/cell-coords.ts +0 -95
  81. package/src/components/report/designer/col-widths.ts +0 -56
  82. package/src/components/report/designer/conditional-rules/helpers.ts +0 -189
  83. package/src/components/report/designer/drill-dialog.vue +0 -245
  84. package/src/components/report/designer/drop-highlight-overlay.vue +0 -75
  85. package/src/components/report/designer/float-panel.vue +0 -444
  86. package/src/components/report/designer/role.ts +0 -32
  87. package/src/components/report/designer/rule-preview.vue +0 -40
  88. package/src/components/report/designer/rule-row.vue +0 -252
  89. package/src/components/report/designer/rules-dialog.vue +0 -110
  90. package/src/components/report/designer/topology-overlay.vue +0 -128
  91. package/src/components/report/designer/topology.ts +0 -124
  92. package/src/components/report/designer/use-grid-overlay.ts +0 -114
  93. package/src/components/report/designer-hub.vue +0 -198
  94. package/src/components/report/field-panel-helpers.ts +0 -44
  95. package/src/components/report/field-panel.vue +0 -136
  96. package/src/components/report/filter-bar.vue +0 -77
  97. package/src/components/report/hub-connection-form.vue +0 -124
  98. package/src/components/report/hub-dataset-editor.vue +0 -387
  99. package/src/components/report/index.ts +0 -2
  100. package/src/components/report/preview-grid-size.ts +0 -33
  101. package/src/components/report/print.ts +0 -44
  102. package/src/components/report/report-designer.vue +0 -454
  103. package/src/components/report/report-viewer.vue +0 -289
  104. package/src/components/report/style-designer.scss +0 -653
  105. package/src/components/report/style-hub.scss +0 -292
  106. package/src/components/report/style-viewer.scss +0 -144
  107. package/src/components/report/style.scss +0 -3
  108. package/src/components/report/style.ts +0 -20
  109. package/src/components/report/use-report-designer.ts +0 -603
  110. package/src/components/report/use-report-viewer.ts +0 -227
  111. package/src/report/__test__/binding.test.ts +0 -320
  112. package/src/report/__test__/connector.test.ts +0 -239
  113. package/src/report/__test__/drill.test.ts +0 -194
  114. package/src/report/__test__/export-xlsx.test.ts +0 -96
  115. package/src/report/__test__/filter-bar.test.ts +0 -58
  116. package/src/report/__test__/params.test.ts +0 -156
  117. package/src/report/__test__/print.test.ts +0 -170
  118. package/src/report/__test__/render.test.ts +0 -856
  119. package/src/report/__test__/rules.test.ts +0 -131
  120. package/src/report/__test__/template.test.ts +0 -366
  121. package/src/report/binding.ts +0 -474
  122. package/src/report/connector.ts +0 -206
  123. package/src/report/drill.ts +0 -112
  124. package/src/report/export-xlsx.ts +0 -15
  125. package/src/report/filter-bar.ts +0 -36
  126. package/src/report/index.ts +0 -16
  127. package/src/report/params.ts +0 -96
  128. package/src/report/print.ts +0 -234
  129. package/src/report/render/__test__/aggregate.test.ts +0 -16
  130. package/src/report/render/__test__/coordinate.test.ts +0 -405
  131. package/src/report/render/aggregate.ts +0 -289
  132. package/src/report/render/builder.ts +0 -211
  133. package/src/report/render/coordinate.ts +0 -1239
  134. package/src/report/render/index.ts +0 -30
  135. package/src/report/render/style-resolver.ts +0 -68
  136. package/src/report/render/template-index.ts +0 -200
  137. package/src/report/rules/evaluate.ts +0 -113
  138. package/src/report/rules/index.ts +0 -7
  139. package/src/report/template.ts +0 -145
  140. package/src/report/types.ts +0 -116
  141. package/src/types/report-designer.ts +0 -55
  142. package/src/types/report-viewer.ts +0 -54
@@ -1,454 +0,0 @@
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="gridRows"
63
- :cols="gridCols"
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-drop-highlight-overlay
88
- v-for="addr in pickCandidateCells"
89
- :key="`pick-${addr.row}-${addr.col}`"
90
- :cell="addr"
91
- :host-el="gridHostEl"
92
- :get-grid="getDesignGrid"
93
- :dragging="false"
94
- fallback-label=""
95
- />
96
-
97
- <div v-if="parentPick" :class="cls.e('pick-hint')" role="status">
98
- {{ parentPick.mode === 'row' ? '点击分组头作为行方向父格' : '点击分组头作为列方向父格' }}
99
- </div>
100
-
101
- <u-report-float-panel
102
- :cell="activeCell"
103
- :binding="activeBinding ?? null"
104
- :resolved-row-parent-label="resolvedRowParentLabel"
105
- :resolved-col-parent-label="resolvedColParentLabel"
106
- :parent-pick-mode="parentPick?.mode ?? null"
107
- :row-parent-candidates="rowParentCandidates"
108
- :col-parent-candidates="colParentCandidates"
109
- :show-drill="hasDrillTemplates"
110
- :resolve-field-label="resolveFieldLabel"
111
- :get-binding-at="getBindingAt"
112
- :host-el="gridHostEl"
113
- :get-grid="getDesignGrid"
114
- @patch="patchActiveBinding"
115
- @remove="removeActiveBinding"
116
- @open-rules="rulesDialogVisible = true"
117
- @open-drill="drillDialogVisible = true"
118
- @start-parent-pick="startParentPick"
119
- @cancel-parent-pick="cancelParentPick"
120
- @clear-parent="clearParent"
121
- />
122
- </div>
123
- </div>
124
-
125
- <div v-else-if="previewTemplate" :class="cls.e('preview')">
126
- <u-report-viewer
127
- ref="previewViewerRef"
128
- :connector="props.connector"
129
- :template="previewTemplate"
130
- :workbook="previewWorkbook"
131
- :resolve-template="props.resolveTemplate"
132
- />
133
- </div>
134
-
135
- <u-drawer v-model="hubVisible" :class="cls.e('hub-drawer')" show-close>
136
- <u-report-dataset-hub :hub="designer" @close="onHubClose" />
137
- </u-drawer>
138
-
139
- <u-report-rules-dialog
140
- v-model="rulesDialogVisible"
141
- :rules="activeBinding?.conditionalRules ?? EMPTY_CONDITIONAL_RULES"
142
- :binding-field="activeBinding?.field ?? ''"
143
- :dataset-fields="activeDatasetFields"
144
- :field-type="activeFieldType"
145
- @save="saveConditionalRules"
146
- />
147
-
148
- <u-report-drill-dialog
149
- v-if="hasDrillTemplates"
150
- v-model="drillDialogVisible"
151
- :templates="props.drillTemplates ?? []"
152
- :fields="activeDatasetFields"
153
- :drill="activeBinding?.drill"
154
- :resolve-template="props.resolveTemplate"
155
- @save="saveDrill"
156
- @remove="removeDrill"
157
- />
158
- </div>
159
- </template>
160
-
161
- <script lang="ts" setup>
162
- import { UButton, UDrawer } from '@veltra/desktop'
163
- import type { CellAddress } from '@veltra/sheet-core'
164
- import { Workbook } from '@veltra/sheet-core'
165
- import type { SheetGrid } from '@veltra/sheet-core/grid'
166
- import { bem } from '@veltra/utils'
167
- import { computed, nextTick, onScopeDispose, ref, shallowRef, useTemplateRef, watch } from 'vue'
168
-
169
- import type { ReportTemplate } from '../../report/template'
170
- import type { ConditionalRule, ReportDrillConfig } from '../../report/types'
171
- import type {
172
- ReportDesignerEmits,
173
- ReportDesignerProps,
174
- ReportViewerExposed,
175
- SheetExposed,
176
- _ReportDesignerExposed
177
- } from '../../types'
178
- import { USheet } from '../sheet'
179
- import UReportDatasetHub from './designer-hub.vue'
180
- import { resolveGridDropAddress } from './designer/cell-coords'
181
- import { applyGridColWidths, applySheetColWidths, readGridColWidths } from './designer/col-widths'
182
- import UReportDrillDialog from './designer/drill-dialog.vue'
183
- import UReportDropHighlightOverlay from './designer/drop-highlight-overlay.vue'
184
- import UReportFloatPanel from './designer/float-panel.vue'
185
- import UReportRulesDialog from './designer/rules-dialog.vue'
186
- import UReportTopologyOverlay from './designer/topology-overlay.vue'
187
- import { FIELD_DRAG_MIME, parseFieldDragPayload } from './field-panel-helpers'
188
- import UReportFieldPanel from './field-panel.vue'
189
- import UReportViewer from './report-viewer.vue'
190
- import { useReportDesigner } from './use-report-designer'
191
-
192
- defineOptions({ name: 'UReportDesigner' })
193
-
194
- /** 与 `ReportDesignerProps` 交叉显式列出下钻 props,避免 SFC 对跨文件 interface 漏抽 runtime 声明 */
195
- type DesignerRuntimeProps = ReportDesignerProps & {
196
- drillTemplates?: ReportDesignerProps['drillTemplates']
197
- resolveTemplate?: ReportDesignerProps['resolveTemplate']
198
- }
199
-
200
- const props = withDefaults(defineProps<DesignerRuntimeProps>(), { connections: () => [] })
201
- const emit = defineEmits<ReportDesignerEmits>()
202
-
203
- const cls = bem('report-designer')
204
-
205
- /** 设计态网格默认尺寸(新建模板;已声明尺寸后以模型为准,避免删行后被 props 撑回) */
206
- const DESIGN_ROWS = 24
207
- const DESIGN_COLS = 10
208
-
209
- /** 条件样式弹窗在无绑定格时的空规则占位 */
210
- const EMPTY_CONDITIONAL_RULES: ConditionalRule[] = []
211
-
212
- /** `v-model:connections` 可写代理(连接为纯序列化对象,仅驻留内存) */
213
- const connections = computed({
214
- get: () => props.connections,
215
- set: (value) => emit('update:connections', value)
216
- })
217
-
218
- const designer = useReportDesigner({ props, connections })
219
- const {
220
- workbook,
221
- catalog,
222
- boundKeys,
223
- activeCell,
224
- selectionLabel,
225
- activeBinding,
226
- activeFieldType,
227
- activeDatasetFields,
228
- resolvedRowParentLabel,
229
- resolvedColParentLabel,
230
- parentPick,
231
- rowParentCandidates,
232
- colParentCandidates,
233
- bindingEntries,
234
- metaTick,
235
- getBindingAt,
236
- resolveFieldLabel,
237
- bindField,
238
- patchActiveBinding,
239
- startParentPick,
240
- cancelParentPick,
241
- pickParentAt,
242
- clearParent,
243
- removeActiveBinding,
244
- resolveCellStyle,
245
- resolveCellRenderer,
246
- getTemplate
247
- } = designer
248
-
249
- /** 渲染行列数跟随模型(删行后不再被固定 props 经 ensureTableSize 撑回) */
250
- const gridRows = computed(() => {
251
- const rows = workbook.value.activeSheet.rows
252
- return rows > 0 ? rows : DESIGN_ROWS
253
- })
254
- const gridCols = computed(() => {
255
- const cols = workbook.value.activeSheet.cols
256
- return cols > 0 ? cols : DESIGN_COLS
257
- })
258
-
259
- const hubVisible = ref(false)
260
- const rulesDialogVisible = ref(false)
261
- const drillDialogVisible = ref(false)
262
-
263
- /** 宿主传入可下钻模板列表时才出现下钻配置入口(不传则无入口,spec 兼容性要求) */
264
- const hasDrillTemplates = computed(() => (props.drillTemplates?.length ?? 0) > 0)
265
-
266
- const pickCandidateCells = computed((): CellAddress[] => {
267
- if (!parentPick.value) return []
268
- return parentPick.value.mode === 'row' ? rowParentCandidates.value : colParentCandidates.value
269
- })
270
-
271
- function onHubClose(): void {
272
- hubVisible.value = false
273
- }
274
-
275
- watch(hubVisible, (open) => {
276
- if (!open) emit('datasets-change')
277
- })
278
-
279
- watch(
280
- () => designer.datasets.value,
281
- () => emit('datasets-change'),
282
- { deep: true }
283
- )
284
-
285
- const sheetRef = useTemplateRef<SheetExposed>('sheetRef')
286
- const previewViewerRef = useTemplateRef<ReportViewerExposed>('previewViewerRef')
287
- const gridHostRef = useTemplateRef<HTMLElement>('gridHostRef')
288
- const gridHostEl = computed(() => gridHostRef.value ?? null)
289
-
290
- /** 字段拖拽落点高亮(dragover 时更新;落空时 overlay 提示回退当前选区) */
291
- const isFieldDragging = ref(false)
292
- const dropTargetAddr = ref<CellAddress | null>(null)
293
-
294
- function getDesignGrid(): SheetGrid | undefined {
295
- return sheetRef.value?.getGrid()
296
- }
297
-
298
- // ---- 设计 / 预览模式切换(预览态内嵌查看器路径,issue 05) ----
299
-
300
- type ViewMode = 'design' | 'preview'
301
-
302
- const viewMode = ref<ViewMode>('design')
303
- const isPreview = computed(() => viewMode.value === 'preview')
304
-
305
- /** 进入预览时的模板快照(getTemplate 吐出,设计态工作簿不受预览取数影响,切回绑定不丢) */
306
- const previewTemplate = shallowRef<ReportTemplate | null>(null)
307
- /** 预览工作簿自持(XLSX 导出需要拿到填充后的 sheet,05 票 workbook? prop 先例) */
308
- const previewWorkbook = new Workbook()
309
- /** 当前设计态列宽(与 Sheet 模型同步;getTemplate 经 snapshot.colWidths 吐出) */
310
- const designColWidths = ref<Array<[number, number]>>([])
311
- const exporting = ref(false)
312
-
313
- /** 从当前设计网格捕获列宽并写回 Sheet 模型(网格未就绪则保留旧值) */
314
- function captureDesignColWidths(): void {
315
- const widths = readGridColWidths(
316
- getDesignGrid(),
317
- Array.from({ length: gridCols.value }, (_, col) => col)
318
- )
319
- if (!widths) return
320
- // 仅保留相对默认列宽有变化的条目,避免快照膨胀
321
- const custom = widths.filter(([, width]) => width > 0)
322
- designColWidths.value = custom
323
- applySheetColWidths(workbook.value.activeSheet, custom)
324
- }
325
-
326
- /** 设计网格重建后补刷新与列宽(restore 不发 content-reset 的场景由 grid 自行订阅,这里只管列宽) */
327
- function syncDesignGridView(): void {
328
- const grid = getDesignGrid()
329
- grid?.flushPending()
330
- grid?.refresh()
331
- applyGridColWidths(grid, designColWidths.value)
332
- }
333
-
334
- function setViewMode(mode: ViewMode): void {
335
- if (viewMode.value === mode) return
336
- if (mode === 'preview') {
337
- captureDesignColWidths()
338
- previewTemplate.value = getTemplate()
339
- }
340
- viewMode.value = mode
341
- if (mode === 'design') void nextTick(syncDesignGridView)
342
- }
343
-
344
- // 模板更换:组合式函数内完成载入;组件层切回设计态并恢复列宽
345
- watch(
346
- () => props.template,
347
- (template) => {
348
- viewMode.value = 'design'
349
- designColWidths.value = template?.colWidths?.length
350
- ? template.colWidths.map(([col, width]) => [col, width] as [number, number])
351
- : []
352
- if (designColWidths.value.length) {
353
- applySheetColWidths(workbook.value.activeSheet, designColWidths.value)
354
- }
355
- void nextTick(syncDesignGridView)
356
- }
357
- )
358
-
359
- // 父格点选:网格选区变更时写入父格并回到源格
360
- watch(activeCell, (cell) => {
361
- if (cell && parentPick.value) pickParentAt(cell)
362
- })
363
-
364
- // 徽章文案依赖 catalog(describe 完成 / label 覆盖变更后重绘绑定格;meta 变更由 grid 自行订阅)
365
- watch(catalog, () => {
366
- void nextTick(() => getDesignGrid()?.refresh())
367
- })
368
-
369
- const offStructureChange = workbook.value.activeSheet.on('structure-change', () => {
370
- void nextTick(syncDesignGridView)
371
- })
372
- onScopeDispose(offStructureChange)
373
-
374
- async function exportPreviewXlsx(): Promise<void> {
375
- if (!isPreview.value || exporting.value) return
376
- const viewer = previewViewerRef.value
377
- if (!viewer) {
378
- throw new Error('预览查看器尚未就绪,请稍后再导出')
379
- }
380
- exporting.value = true
381
- try {
382
- await viewer.exportXlsx()
383
- } finally {
384
- exporting.value = false
385
- }
386
- }
387
-
388
- function saveConditionalRules(rules: ConditionalRule[]): void {
389
- patchActiveBinding({ conditionalRules: rules })
390
- }
391
-
392
- function saveDrill(drill: ReportDrillConfig): void {
393
- patchActiveBinding({ drill })
394
- }
395
-
396
- function removeDrill(): void {
397
- patchActiveBinding({ drill: undefined })
398
- }
399
-
400
- function clearDropState(): void {
401
- isFieldDragging.value = false
402
- dropTargetAddr.value = null
403
- }
404
-
405
- function resolveDropAddress(event: DragEvent): CellAddress | null {
406
- const grid = getDesignGrid()
407
- const gridEl = gridHostRef.value?.querySelector('.u-sheet__grid-instance') as HTMLElement | null
408
- if (!grid || !gridEl) return null
409
- return resolveGridDropAddress(grid, gridEl, event.clientX, event.clientY)
410
- }
411
-
412
- function onGridDragOver(event: DragEvent): void {
413
- if (!event.dataTransfer?.types.includes(FIELD_DRAG_MIME)) return
414
- event.preventDefault()
415
- event.dataTransfer.dropEffect = 'copy'
416
- isFieldDragging.value = true
417
- dropTargetAddr.value = resolveDropAddress(event)
418
- }
419
-
420
- function onGridDragLeave(event: DragEvent): void {
421
- const host = gridHostRef.value
422
- const related = event.relatedTarget
423
- if (host && related instanceof Node && host.contains(related)) return
424
- clearDropState()
425
- }
426
-
427
- function onGridDrop(event: DragEvent): void {
428
- event.preventDefault()
429
- clearDropState()
430
- const raw = event.dataTransfer?.getData(FIELD_DRAG_MIME)
431
- const payload = raw ? parseFieldDragPayload(raw) : null
432
- if (!payload) return
433
-
434
- // 与旧设计器一致:网格未就绪直接放弃;仅 hit-test 落空时回退当前选区
435
- const grid = getDesignGrid()
436
- const gridEl = gridHostRef.value?.querySelector('.u-sheet__grid-instance') as HTMLElement | null
437
- if (!grid || !gridEl) return
438
-
439
- const dropAddr = resolveDropAddress(event)
440
- if (dropAddr) {
441
- bindField(payload.datasetId, payload.fieldName, dropAddr)
442
- sheetRef.value?.getContext().selectCell(dropAddr)
443
- } else {
444
- bindField(payload.datasetId, payload.fieldName)
445
- }
446
- }
447
-
448
- defineExpose<_ReportDesignerExposed>({
449
- getTemplate: () => {
450
- captureDesignColWidths()
451
- return getTemplate()
452
- }
453
- })
454
- </script>