@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.
- package/dist/index.d.ts +2 -19
- package/dist/index.js +2 -15
- package/dist/types/index.d.ts +1 -3
- package/package.json +2 -3
- package/src/index.ts +1 -27
- package/src/types/index.ts +0 -2
- package/dist/components/report/binding-badge.js +0 -118
- package/dist/components/report/designer/cell-coords.js +0 -46
- package/dist/components/report/designer/col-widths.js +0 -29
- package/dist/components/report/designer/conditional-rules/helpers.js +0 -139
- package/dist/components/report/designer/drill-dialog.js +0 -258
- package/dist/components/report/designer/drop-highlight-overlay.js +0 -76
- package/dist/components/report/designer/float-panel.js +0 -434
- package/dist/components/report/designer/role.js +0 -17
- package/dist/components/report/designer/rule-preview.js +0 -33
- package/dist/components/report/designer/rule-row.js +0 -253
- package/dist/components/report/designer/rules-dialog.js +0 -118
- package/dist/components/report/designer/topology-overlay.js +0 -122
- package/dist/components/report/designer/topology.js +0 -64
- package/dist/components/report/designer/use-grid-overlay.js +0 -75
- package/dist/components/report/designer-hub.js +0 -177
- package/dist/components/report/field-panel-helpers.js +0 -33
- package/dist/components/report/field-panel.js +0 -132
- package/dist/components/report/filter-bar.js +0 -74
- package/dist/components/report/hub-connection-form.js +0 -145
- package/dist/components/report/hub-dataset-editor.js +0 -409
- package/dist/components/report/preview-grid-size.js +0 -32
- package/dist/components/report/print.js +0 -39
- package/dist/components/report/report-designer.js +0 -428
- package/dist/components/report/report-viewer.js +0 -253
- package/dist/components/report/style.d.ts +0 -17
- package/dist/components/report/style.js +0 -18
- package/dist/components/report/style2.css +0 -965
- package/dist/components/report/use-report-designer.js +0 -387
- package/dist/components/report/use-report-viewer.js +0 -140
- package/dist/report/binding.d.ts +0 -83
- package/dist/report/binding.js +0 -334
- package/dist/report/connector.d.ts +0 -66
- package/dist/report/connector.js +0 -159
- package/dist/report/drill.d.ts +0 -48
- package/dist/report/drill.js +0 -78
- package/dist/report/export-xlsx.d.ts +0 -13
- package/dist/report/export-xlsx.js +0 -13
- package/dist/report/filter-bar.d.ts +0 -10
- package/dist/report/filter-bar.js +0 -31
- package/dist/report/index.d.ts +0 -14
- package/dist/report/params.d.ts +0 -13
- package/dist/report/params.js +0 -61
- package/dist/report/print.d.ts +0 -23
- package/dist/report/print.js +0 -197
- package/dist/report/render/aggregate.js +0 -193
- package/dist/report/render/builder.d.ts +0 -12
- package/dist/report/render/builder.js +0 -139
- package/dist/report/render/coordinate.d.ts +0 -25
- package/dist/report/render/coordinate.js +0 -733
- package/dist/report/render/index.d.ts +0 -14
- package/dist/report/render/index.js +0 -21
- package/dist/report/render/style-resolver.js +0 -50
- package/dist/report/render/template-index.d.ts +0 -24
- package/dist/report/render/template-index.js +0 -137
- package/dist/report/rules/evaluate.d.ts +0 -25
- package/dist/report/rules/evaluate.js +0 -82
- package/dist/report/rules/index.d.ts +0 -2
- package/dist/report/template.d.ts +0 -63
- package/dist/report/template.js +0 -83
- package/dist/report/types.d.ts +0 -103
- package/dist/types/report-designer.d.ts +0 -51
- package/dist/types/report-viewer.d.ts +0 -57
- package/src/components/report/__test__/binding-badge.test.ts +0 -92
- package/src/components/report/__test__/conditional-rules-helpers.test.ts +0 -88
- package/src/components/report/__test__/field-panel-helpers.test.ts +0 -65
- package/src/components/report/__test__/float-panel-position.test.ts +0 -45
- package/src/components/report/__test__/preview-grid-size.test.ts +0 -63
- package/src/components/report/__test__/report-designer.test.ts +0 -559
- package/src/components/report/__test__/report-drill.test.ts +0 -692
- package/src/components/report/__test__/report-viewer.test.ts +0 -400
- package/src/components/report/__test__/topology.test.ts +0 -143
- package/src/components/report/__test__/use-report-designer.test.ts +0 -804
- package/src/components/report/binding-badge.ts +0 -122
- package/src/components/report/designer/cell-coords.ts +0 -95
- package/src/components/report/designer/col-widths.ts +0 -56
- package/src/components/report/designer/conditional-rules/helpers.ts +0 -189
- package/src/components/report/designer/drill-dialog.vue +0 -245
- package/src/components/report/designer/drop-highlight-overlay.vue +0 -75
- package/src/components/report/designer/float-panel.vue +0 -444
- package/src/components/report/designer/role.ts +0 -32
- package/src/components/report/designer/rule-preview.vue +0 -40
- package/src/components/report/designer/rule-row.vue +0 -252
- package/src/components/report/designer/rules-dialog.vue +0 -110
- package/src/components/report/designer/topology-overlay.vue +0 -128
- package/src/components/report/designer/topology.ts +0 -124
- package/src/components/report/designer/use-grid-overlay.ts +0 -114
- package/src/components/report/designer-hub.vue +0 -198
- package/src/components/report/field-panel-helpers.ts +0 -44
- package/src/components/report/field-panel.vue +0 -136
- package/src/components/report/filter-bar.vue +0 -77
- package/src/components/report/hub-connection-form.vue +0 -124
- package/src/components/report/hub-dataset-editor.vue +0 -387
- package/src/components/report/index.ts +0 -2
- package/src/components/report/preview-grid-size.ts +0 -33
- package/src/components/report/print.ts +0 -44
- package/src/components/report/report-designer.vue +0 -454
- package/src/components/report/report-viewer.vue +0 -289
- package/src/components/report/style-designer.scss +0 -653
- package/src/components/report/style-hub.scss +0 -292
- package/src/components/report/style-viewer.scss +0 -144
- package/src/components/report/style.scss +0 -3
- package/src/components/report/style.ts +0 -20
- package/src/components/report/use-report-designer.ts +0 -603
- package/src/components/report/use-report-viewer.ts +0 -227
- package/src/report/__test__/binding.test.ts +0 -320
- package/src/report/__test__/connector.test.ts +0 -239
- package/src/report/__test__/drill.test.ts +0 -194
- package/src/report/__test__/export-xlsx.test.ts +0 -96
- package/src/report/__test__/filter-bar.test.ts +0 -58
- package/src/report/__test__/params.test.ts +0 -156
- package/src/report/__test__/print.test.ts +0 -170
- package/src/report/__test__/render.test.ts +0 -856
- package/src/report/__test__/rules.test.ts +0 -131
- package/src/report/__test__/template.test.ts +0 -366
- package/src/report/binding.ts +0 -474
- package/src/report/connector.ts +0 -206
- package/src/report/drill.ts +0 -112
- package/src/report/export-xlsx.ts +0 -15
- package/src/report/filter-bar.ts +0 -36
- package/src/report/index.ts +0 -16
- package/src/report/params.ts +0 -96
- package/src/report/print.ts +0 -234
- package/src/report/render/__test__/aggregate.test.ts +0 -16
- package/src/report/render/__test__/coordinate.test.ts +0 -405
- package/src/report/render/aggregate.ts +0 -289
- package/src/report/render/builder.ts +0 -211
- package/src/report/render/coordinate.ts +0 -1239
- package/src/report/render/index.ts +0 -30
- package/src/report/render/style-resolver.ts +0 -68
- package/src/report/render/template-index.ts +0 -200
- package/src/report/rules/evaluate.ts +0 -113
- package/src/report/rules/index.ts +0 -7
- package/src/report/template.ts +0 -145
- package/src/report/types.ts +0 -116
- package/src/types/report-designer.ts +0 -55
- package/src/types/report-viewer.ts +0 -54
|
@@ -1,692 +0,0 @@
|
|
|
1
|
-
import { Sheet, Workbook } from '@veltra/sheet-core'
|
|
2
|
-
import type { CellAddress } from '@veltra/sheet-core'
|
|
3
|
-
import { SheetGrid } from '@veltra/sheet-core/grid'
|
|
4
|
-
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
5
|
-
import { createApp, h, nextTick, type App } from 'vue'
|
|
6
|
-
|
|
7
|
-
import { UReportViewer } from '../../../index'
|
|
8
|
-
import { REPORT_META_NAMESPACE } from '../../../report/binding'
|
|
9
|
-
import type { DataConnection, DataConnector } from '../../../report/connector'
|
|
10
|
-
import { createReportTemplate } from '../../../report/template'
|
|
11
|
-
import type { ReportDatasetDef, ReportTemplate } from '../../../report/template'
|
|
12
|
-
import type { ParamValues, ReportBinding } from '../../../report/types'
|
|
13
|
-
import type { ReportViewerExposed, SheetExposed } from '../../../types'
|
|
14
|
-
|
|
15
|
-
// ---- 内联 fixtures:stub connector(按 SQL 路由行记录)+ 三级下钻模板 ----
|
|
16
|
-
|
|
17
|
-
const MYSQL: DataConnection = {
|
|
18
|
-
id: 'c1',
|
|
19
|
-
label: 'stub MySQL',
|
|
20
|
-
type: 'mysql',
|
|
21
|
-
host: '127.0.0.1',
|
|
22
|
-
port: 3306,
|
|
23
|
-
database: 'demo',
|
|
24
|
-
username: 'root',
|
|
25
|
-
password: ''
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const SUMMARY_SQL = 'SELECT region, total FROM summary WHERE region LIKE ${keyword}'
|
|
29
|
-
const ORDERS_SQL = 'SELECT customer, amount FROM orders WHERE region LIKE ${p_region}'
|
|
30
|
-
const ITEMS_SQL = 'SELECT item, qty FROM items WHERE customer LIKE ${p_customer}'
|
|
31
|
-
const SELF_SQL = 'SELECT region FROM t WHERE region LIKE ${p_region}'
|
|
32
|
-
|
|
33
|
-
const SUMMARY_DATASET: ReportDatasetDef = {
|
|
34
|
-
id: 'summary',
|
|
35
|
-
label: '地区汇总',
|
|
36
|
-
connection: MYSQL,
|
|
37
|
-
sql: SUMMARY_SQL
|
|
38
|
-
}
|
|
39
|
-
const ORDERS_DATASET: ReportDatasetDef = {
|
|
40
|
-
id: 'orders',
|
|
41
|
-
label: '销售明细',
|
|
42
|
-
connection: MYSQL,
|
|
43
|
-
sql: ORDERS_SQL
|
|
44
|
-
}
|
|
45
|
-
const ITEMS_DATASET: ReportDatasetDef = {
|
|
46
|
-
id: 'items',
|
|
47
|
-
label: '项目明细',
|
|
48
|
-
connection: MYSQL,
|
|
49
|
-
sql: ITEMS_SQL
|
|
50
|
-
}
|
|
51
|
-
const SELF_DATASET: ReportDatasetDef = {
|
|
52
|
-
id: 'self',
|
|
53
|
-
label: '自指报表',
|
|
54
|
-
connection: MYSQL,
|
|
55
|
-
sql: SELF_SQL
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const SUMMARY_ROWS: Record<string, unknown>[] = [
|
|
59
|
-
{ region: '华东', total: 300 },
|
|
60
|
-
{ region: '华南', total: 100 }
|
|
61
|
-
]
|
|
62
|
-
const ORDER_ROWS: Record<string, unknown>[] = [
|
|
63
|
-
{ customer: '甲公司', amount: 100 },
|
|
64
|
-
{ customer: '乙公司', amount: 200 }
|
|
65
|
-
]
|
|
66
|
-
const ITEM_ROWS: Record<string, unknown>[] = [{ item: 'X 项目', qty: 1 }]
|
|
67
|
-
|
|
68
|
-
/** 主表:地区分组格配下钻(→ tpl-detail,region → p_region);总额汇总格不配下钻 */
|
|
69
|
-
function createSummaryTemplate(openMode: 'switch' | 'dialog' = 'switch'): ReportTemplate {
|
|
70
|
-
const sheet = new Sheet()
|
|
71
|
-
sheet.setCells([
|
|
72
|
-
{ addr: { row: 0, col: 0 }, data: { v: '地区' } },
|
|
73
|
-
{ addr: { row: 0, col: 1 }, data: { v: '总额' } }
|
|
74
|
-
])
|
|
75
|
-
const group: ReportBinding = {
|
|
76
|
-
dataset: 'summary',
|
|
77
|
-
field: 'region',
|
|
78
|
-
aggregate: 'group',
|
|
79
|
-
expand: 'down',
|
|
80
|
-
drill: { target: 'tpl-detail', mapping: { region: 'p_region' }, openMode }
|
|
81
|
-
}
|
|
82
|
-
sheet.setCellMeta({ row: 1, col: 0 }, REPORT_META_NAMESPACE, group)
|
|
83
|
-
const total: ReportBinding = {
|
|
84
|
-
dataset: 'summary',
|
|
85
|
-
field: 'total',
|
|
86
|
-
aggregate: 'sum',
|
|
87
|
-
expand: 'none',
|
|
88
|
-
rowParent: { row: 1, col: 0 }
|
|
89
|
-
}
|
|
90
|
-
sheet.setCellMeta({ row: 1, col: 1 }, REPORT_META_NAMESPACE, total)
|
|
91
|
-
sheet.ensureTableSize(50, 10)
|
|
92
|
-
return createReportTemplate(sheet.snapshot(), [SUMMARY_DATASET])
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** 明细表:客户明细格配下钻(→ tpl-third,customer → p_customer) */
|
|
96
|
-
function createDetailTemplate(): ReportTemplate {
|
|
97
|
-
const sheet = new Sheet()
|
|
98
|
-
sheet.setCells([
|
|
99
|
-
{ addr: { row: 0, col: 0 }, data: { v: '客户' } },
|
|
100
|
-
{ addr: { row: 0, col: 1 }, data: { v: '金额' } }
|
|
101
|
-
])
|
|
102
|
-
const customer: ReportBinding = {
|
|
103
|
-
dataset: 'orders',
|
|
104
|
-
field: 'customer',
|
|
105
|
-
aggregate: 'list',
|
|
106
|
-
expand: 'down',
|
|
107
|
-
drill: { target: 'tpl-third', mapping: { customer: 'p_customer' }, openMode: 'switch' }
|
|
108
|
-
}
|
|
109
|
-
sheet.setCellMeta({ row: 1, col: 0 }, REPORT_META_NAMESPACE, customer)
|
|
110
|
-
const amount: ReportBinding = {
|
|
111
|
-
dataset: 'orders',
|
|
112
|
-
field: 'amount',
|
|
113
|
-
aggregate: 'list',
|
|
114
|
-
expand: 'down'
|
|
115
|
-
}
|
|
116
|
-
sheet.setCellMeta({ row: 1, col: 1 }, REPORT_META_NAMESPACE, amount)
|
|
117
|
-
sheet.ensureTableSize(50, 10)
|
|
118
|
-
return createReportTemplate(sheet.snapshot(), [ORDERS_DATASET])
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** 第三级:无下钻的明细表 */
|
|
122
|
-
function createThirdTemplate(): ReportTemplate {
|
|
123
|
-
const sheet = new Sheet()
|
|
124
|
-
sheet.setCells([{ addr: { row: 0, col: 0 }, data: { v: '项目' } }])
|
|
125
|
-
const item: ReportBinding = { dataset: 'items', field: 'item', aggregate: 'list', expand: 'down' }
|
|
126
|
-
sheet.setCellMeta({ row: 1, col: 0 }, REPORT_META_NAMESPACE, item)
|
|
127
|
-
sheet.ensureTableSize(50, 10)
|
|
128
|
-
return createReportTemplate(sheet.snapshot(), [ITEMS_DATASET])
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** 自指表:地区分组格下钻指向自身(region → p_region) */
|
|
132
|
-
function createSelfTemplate(): ReportTemplate {
|
|
133
|
-
const sheet = new Sheet()
|
|
134
|
-
sheet.setCells([{ addr: { row: 0, col: 0 }, data: { v: '地区' } }])
|
|
135
|
-
const region: ReportBinding = {
|
|
136
|
-
dataset: 'self',
|
|
137
|
-
field: 'region',
|
|
138
|
-
aggregate: 'group',
|
|
139
|
-
expand: 'down',
|
|
140
|
-
drill: { target: 'tpl-self', mapping: { region: 'p_region' }, openMode: 'switch' }
|
|
141
|
-
}
|
|
142
|
-
sheet.setCellMeta({ row: 1, col: 0 }, REPORT_META_NAMESPACE, region)
|
|
143
|
-
sheet.ensureTableSize(50, 10)
|
|
144
|
-
return createReportTemplate(sheet.snapshot(), [SELF_DATASET])
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
interface QueryCall {
|
|
148
|
-
connection: DataConnection
|
|
149
|
-
sql: string
|
|
150
|
-
values: ParamValues
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/** stub connector:记录 query 调用,按 SQL 路由到对应行记录 */
|
|
154
|
-
function createStubConnector(rowsBySql: Record<string, Record<string, unknown>[]>) {
|
|
155
|
-
const calls: QueryCall[] = []
|
|
156
|
-
const connector: DataConnector = {
|
|
157
|
-
test: () => Promise.resolve({ ok: true, data: undefined }),
|
|
158
|
-
describe: () => Promise.resolve({ ok: true, data: [] }),
|
|
159
|
-
query: (connection, sql, values) => {
|
|
160
|
-
calls.push({ connection, sql, values })
|
|
161
|
-
return Promise.resolve({ ok: true, data: { fields: [], rows: rowsBySql[sql] ?? [] } })
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return { connector, calls }
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/** stub 宿主契约:按 ref 从模板表解析(异步形态) */
|
|
168
|
-
function createTemplateResolver(map: Record<string, ReportTemplate>) {
|
|
169
|
-
return vi.fn((ref: string) => Promise.resolve(map[ref]))
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// ---- 挂载与等待 ----
|
|
173
|
-
|
|
174
|
-
const apps: App[] = []
|
|
175
|
-
const containers: HTMLElement[] = []
|
|
176
|
-
|
|
177
|
-
function mountViewer(props: {
|
|
178
|
-
connector: DataConnector
|
|
179
|
-
template: ReportTemplate
|
|
180
|
-
workbook?: Workbook
|
|
181
|
-
resolveTemplate?: (ref: string) => Promise<ReportTemplate | undefined>
|
|
182
|
-
}) {
|
|
183
|
-
const el = document.createElement('div')
|
|
184
|
-
el.style.width = '800px'
|
|
185
|
-
el.style.height = '600px'
|
|
186
|
-
document.body.appendChild(el)
|
|
187
|
-
containers.push(el)
|
|
188
|
-
const exposedRef = { value: undefined as ReportViewerExposed | undefined }
|
|
189
|
-
const app = createApp({
|
|
190
|
-
render: () =>
|
|
191
|
-
h(UReportViewer, {
|
|
192
|
-
...props,
|
|
193
|
-
ref: (value: unknown) => {
|
|
194
|
-
exposedRef.value = value as ReportViewerExposed | undefined
|
|
195
|
-
}
|
|
196
|
-
})
|
|
197
|
-
})
|
|
198
|
-
app.mount(el)
|
|
199
|
-
apps.push(app)
|
|
200
|
-
return { app, el, exposedRef }
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/** 内嵌 USheet 的活动 sheet(弹框内查看器未注入 workbook 时用) */
|
|
204
|
-
function nestedActiveSheet(el: HTMLElement) {
|
|
205
|
-
const sheetEl = el.querySelector('.u-sheet') as
|
|
206
|
-
| (HTMLElement & { __vueParentComponent?: { exposed?: SheetExposed } })
|
|
207
|
-
| null
|
|
208
|
-
return sheetEl?.__vueParentComponent?.exposed?.getActiveSheet()
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** 下钻弹框(UDialog Teleport 到 body;class 打在对话框根上) */
|
|
212
|
-
function drillDialogEl(): HTMLElement | null {
|
|
213
|
-
return document.querySelector('.u-report-viewer__drill-dialog')
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
async function openDrillDialog(el: HTMLElement): Promise<HTMLElement> {
|
|
217
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
218
|
-
dispatchGridClick(el)
|
|
219
|
-
await flushViewer()
|
|
220
|
-
await flushViewer()
|
|
221
|
-
const dialog = drillDialogEl()
|
|
222
|
-
expect(dialog).toBeTruthy()
|
|
223
|
-
return dialog!
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/** 等待取数 / 下钻解析(宏/微任务)+ 填充快照应用(watch + nextTick)落定 */
|
|
227
|
-
async function flushViewer(): Promise<void> {
|
|
228
|
-
await nextTick()
|
|
229
|
-
await new Promise((resolve) => setTimeout(resolve, 0))
|
|
230
|
-
await nextTick()
|
|
231
|
-
await nextTick()
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/** 网格命中测试 mock:网格随内容尺寸重建,按原型 mock 一次,逐次改返回值 */
|
|
235
|
-
let hitSpy: ReturnType<typeof vi.spyOn> | null = null
|
|
236
|
-
|
|
237
|
-
function mockHitAddr(addr: CellAddress | null): void {
|
|
238
|
-
if (!hitSpy) {
|
|
239
|
-
hitSpy = vi.spyOn(SheetGrid.prototype, 'hitTestSheetAddr')
|
|
240
|
-
}
|
|
241
|
-
hitSpy.mockReturnValue(addr)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/** 在网格上模拟一次单击(pointerdown + click 同坐标) */
|
|
245
|
-
function dispatchGridClick(el: HTMLElement, x = 10, y = 10): void {
|
|
246
|
-
const gridEl = el.querySelector('.u-sheet__grid-instance')!
|
|
247
|
-
gridEl.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, clientX: x, clientY: y }))
|
|
248
|
-
gridEl.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: x, clientY: y }))
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function dispatchGridPointerMove(el: HTMLElement, x = 10, y = 10): void {
|
|
252
|
-
const gridEl = el.querySelector('.u-sheet__grid-instance')!
|
|
253
|
-
gridEl.dispatchEvent(new PointerEvent('pointermove', { bubbles: true, clientX: x, clientY: y }))
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
async function clickButton(button: HTMLElement): Promise<void> {
|
|
257
|
-
button.dispatchEvent(new MouseEvent('click', { bubbles: true }))
|
|
258
|
-
await flushViewer()
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
afterEach(() => {
|
|
262
|
-
hitSpy?.mockRestore()
|
|
263
|
-
hitSpy = null
|
|
264
|
-
while (apps.length) apps.pop()!.unmount()
|
|
265
|
-
while (containers.length) containers.pop()!.remove()
|
|
266
|
-
document.querySelectorAll('.u-dialog__overlay').forEach((node) => node.remove())
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
const SHEET_CLS = 'u-report-viewer__sheet'
|
|
270
|
-
const DRILL_HOVER_CLS = 'u-report-viewer__sheet--drill-hover'
|
|
271
|
-
const DRILL_BAR_CLS = '.u-report-viewer__drill-bar'
|
|
272
|
-
|
|
273
|
-
describe('UReportViewer 下钻(查看器内切换)', () => {
|
|
274
|
-
it('单击配了下钻的分组格:解析目标模板、映射参数带入 Filter Bar 并取数渲染', async () => {
|
|
275
|
-
const { connector, calls } = createStubConnector({
|
|
276
|
-
[SUMMARY_SQL]: SUMMARY_ROWS,
|
|
277
|
-
[ORDERS_SQL]: ORDER_ROWS
|
|
278
|
-
})
|
|
279
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-detail': createDetailTemplate() })
|
|
280
|
-
const workbook = new Workbook()
|
|
281
|
-
const { el } = mountViewer({
|
|
282
|
-
connector,
|
|
283
|
-
template: createSummaryTemplate(),
|
|
284
|
-
workbook,
|
|
285
|
-
resolveTemplate
|
|
286
|
-
})
|
|
287
|
-
await flushViewer()
|
|
288
|
-
expect(calls).toHaveLength(1)
|
|
289
|
-
expect(calls[0]).toMatchObject({ sql: SUMMARY_SQL, values: { keyword: '' } })
|
|
290
|
-
|
|
291
|
-
// 单击 (1,0) 华东分组格
|
|
292
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
293
|
-
dispatchGridClick(el)
|
|
294
|
-
await flushViewer()
|
|
295
|
-
|
|
296
|
-
// 宿主契约按 target 引用解析
|
|
297
|
-
expect(resolveTemplate).toHaveBeenCalledWith('tpl-detail')
|
|
298
|
-
// 映射参数带入详情报取数
|
|
299
|
-
expect(calls).toHaveLength(2)
|
|
300
|
-
expect(calls[1]).toMatchObject({ sql: ORDERS_SQL, values: { p_region: '华东' } })
|
|
301
|
-
// Filter Bar 自动填入映射值
|
|
302
|
-
const input = el.querySelector<HTMLInputElement>('.u-report-filter-bar .u-input input')!
|
|
303
|
-
expect(input.value).toBe('华东')
|
|
304
|
-
// 详情报渲染:当前可见层替换为明细数据
|
|
305
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('甲公司')
|
|
306
|
-
// 栈深 1:出现回退入口
|
|
307
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeTruthy()
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
it('未配置下钻的格子(静态格 / 无 drill 绑定格)单击不跳转', async () => {
|
|
311
|
-
const { connector, calls } = createStubConnector({ [SUMMARY_SQL]: SUMMARY_ROWS })
|
|
312
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-detail': createDetailTemplate() })
|
|
313
|
-
const { el } = mountViewer({
|
|
314
|
-
connector,
|
|
315
|
-
template: createSummaryTemplate(),
|
|
316
|
-
workbook: new Workbook(),
|
|
317
|
-
resolveTemplate
|
|
318
|
-
})
|
|
319
|
-
await flushViewer()
|
|
320
|
-
expect(calls).toHaveLength(1)
|
|
321
|
-
|
|
322
|
-
// 静态表头格
|
|
323
|
-
mockHitAddr({ row: 0, col: 0 })
|
|
324
|
-
dispatchGridClick(el)
|
|
325
|
-
await flushViewer()
|
|
326
|
-
// 无 drill 的汇总绑定格
|
|
327
|
-
mockHitAddr({ row: 1, col: 1 })
|
|
328
|
-
dispatchGridClick(el)
|
|
329
|
-
await flushViewer()
|
|
330
|
-
|
|
331
|
-
expect(resolveTemplate).not.toHaveBeenCalled()
|
|
332
|
-
expect(calls).toHaveLength(1)
|
|
333
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
it('拖拽框选(位移超阈值)不触发下钻,同点位单击触发', async () => {
|
|
337
|
-
const { connector } = createStubConnector({
|
|
338
|
-
[SUMMARY_SQL]: SUMMARY_ROWS,
|
|
339
|
-
[ORDERS_SQL]: ORDER_ROWS
|
|
340
|
-
})
|
|
341
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-detail': createDetailTemplate() })
|
|
342
|
-
const { el } = mountViewer({
|
|
343
|
-
connector,
|
|
344
|
-
template: createSummaryTemplate(),
|
|
345
|
-
workbook: new Workbook(),
|
|
346
|
-
resolveTemplate
|
|
347
|
-
})
|
|
348
|
-
await flushViewer()
|
|
349
|
-
|
|
350
|
-
const gridEl = el.querySelector('.u-sheet__grid-instance')!
|
|
351
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
352
|
-
// 拖拽框选:pointerdown 与 click 位移 80px
|
|
353
|
-
gridEl.dispatchEvent(
|
|
354
|
-
new PointerEvent('pointerdown', { bubbles: true, clientX: 10, clientY: 10 })
|
|
355
|
-
)
|
|
356
|
-
gridEl.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: 90, clientY: 10 }))
|
|
357
|
-
await flushViewer()
|
|
358
|
-
expect(resolveTemplate).not.toHaveBeenCalled()
|
|
359
|
-
|
|
360
|
-
// 同点位单击:正常触发
|
|
361
|
-
dispatchGridClick(el)
|
|
362
|
-
await flushViewer()
|
|
363
|
-
expect(resolveTemplate).toHaveBeenCalledWith('tpl-detail')
|
|
364
|
-
})
|
|
365
|
-
|
|
366
|
-
it('多层下钻逐级回退:回退后该层 Filter Bar 为当时值并重新取数渲染', async () => {
|
|
367
|
-
const { connector, calls } = createStubConnector({
|
|
368
|
-
[SUMMARY_SQL]: SUMMARY_ROWS,
|
|
369
|
-
[ORDERS_SQL]: ORDER_ROWS,
|
|
370
|
-
[ITEMS_SQL]: ITEM_ROWS
|
|
371
|
-
})
|
|
372
|
-
const resolveTemplate = createTemplateResolver({
|
|
373
|
-
'tpl-detail': createDetailTemplate(),
|
|
374
|
-
'tpl-third': createThirdTemplate()
|
|
375
|
-
})
|
|
376
|
-
const workbook = new Workbook()
|
|
377
|
-
const { el } = mountViewer({
|
|
378
|
-
connector,
|
|
379
|
-
template: createSummaryTemplate(),
|
|
380
|
-
workbook,
|
|
381
|
-
resolveTemplate
|
|
382
|
-
})
|
|
383
|
-
await flushViewer()
|
|
384
|
-
|
|
385
|
-
// 主表 Filter Bar 改值为「华东」(离开时的当时值)
|
|
386
|
-
const rootInput = el.querySelector<HTMLInputElement>('.u-report-filter-bar .u-input input')!
|
|
387
|
-
rootInput.value = '华东'
|
|
388
|
-
rootInput.dispatchEvent(
|
|
389
|
-
new InputEvent('input', { bubbles: true, data: '华东', inputType: 'insertText' })
|
|
390
|
-
)
|
|
391
|
-
await flushViewer()
|
|
392
|
-
expect(calls).toHaveLength(2)
|
|
393
|
-
expect(calls[1]).toMatchObject({ sql: SUMMARY_SQL, values: { keyword: '华东' } })
|
|
394
|
-
|
|
395
|
-
// 第一层:主表 → 明细表(region=华东 → p_region)
|
|
396
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
397
|
-
dispatchGridClick(el)
|
|
398
|
-
await flushViewer()
|
|
399
|
-
expect(calls[2]).toMatchObject({ sql: ORDERS_SQL, values: { p_region: '华东' } })
|
|
400
|
-
|
|
401
|
-
// 第二层:明细表 → 项目表(customer=甲公司 → p_customer)
|
|
402
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
403
|
-
dispatchGridClick(el)
|
|
404
|
-
await flushViewer()
|
|
405
|
-
expect(calls[3]).toMatchObject({ sql: ITEMS_SQL, values: { p_customer: '甲公司' } })
|
|
406
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('X 项目')
|
|
407
|
-
|
|
408
|
-
// 回退到明细表:当时值 p_region=华东,重新取数渲染
|
|
409
|
-
await clickButton(el.querySelector<HTMLElement>(`${DRILL_BAR_CLS} button`)!)
|
|
410
|
-
expect(calls[4]).toMatchObject({ sql: ORDERS_SQL, values: { p_region: '华东' } })
|
|
411
|
-
expect(el.querySelector<HTMLInputElement>('.u-report-filter-bar .u-input input')!.value).toBe(
|
|
412
|
-
'华东'
|
|
413
|
-
)
|
|
414
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('甲公司')
|
|
415
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeTruthy()
|
|
416
|
-
|
|
417
|
-
// 回退到主表:当时值 keyword=华东(离开前的改值),重新取数渲染
|
|
418
|
-
await clickButton(el.querySelector<HTMLElement>(`${DRILL_BAR_CLS} button`)!)
|
|
419
|
-
expect(calls[5]).toMatchObject({ sql: SUMMARY_SQL, values: { keyword: '华东' } })
|
|
420
|
-
expect(el.querySelector<HTMLInputElement>('.u-report-filter-bar .u-input input')!.value).toBe(
|
|
421
|
-
'华东'
|
|
422
|
-
)
|
|
423
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
424
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
it('resolveTemplate 抛错:可读错误提示,停留当前报表,下钻栈不变', async () => {
|
|
428
|
-
const { connector, calls } = createStubConnector({ [SUMMARY_SQL]: SUMMARY_ROWS })
|
|
429
|
-
const resolveTemplate = vi.fn(() => Promise.reject(new Error('模板服务不可用')))
|
|
430
|
-
const workbook = new Workbook()
|
|
431
|
-
const { el } = mountViewer({
|
|
432
|
-
connector,
|
|
433
|
-
template: createSummaryTemplate(),
|
|
434
|
-
workbook,
|
|
435
|
-
resolveTemplate
|
|
436
|
-
})
|
|
437
|
-
await flushViewer()
|
|
438
|
-
expect(calls).toHaveLength(1)
|
|
439
|
-
|
|
440
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
441
|
-
dispatchGridClick(el)
|
|
442
|
-
await flushViewer()
|
|
443
|
-
|
|
444
|
-
const errorBanner = el.querySelector('.u-report-viewer__error')!
|
|
445
|
-
expect(errorBanner.textContent).toContain('模板服务不可用')
|
|
446
|
-
// 停留当前报:填充内容不变,不再取数,无回退入口
|
|
447
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
448
|
-
expect(calls).toHaveLength(1)
|
|
449
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
450
|
-
})
|
|
451
|
-
|
|
452
|
-
it('resolveTemplate 返回空结果:可读错误提示,停留当前报表', async () => {
|
|
453
|
-
const { connector, calls } = createStubConnector({ [SUMMARY_SQL]: SUMMARY_ROWS })
|
|
454
|
-
const resolveTemplate = createTemplateResolver({})
|
|
455
|
-
const workbook = new Workbook()
|
|
456
|
-
const { el } = mountViewer({
|
|
457
|
-
connector,
|
|
458
|
-
template: createSummaryTemplate(),
|
|
459
|
-
workbook,
|
|
460
|
-
resolveTemplate
|
|
461
|
-
})
|
|
462
|
-
await flushViewer()
|
|
463
|
-
|
|
464
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
465
|
-
dispatchGridClick(el)
|
|
466
|
-
await flushViewer()
|
|
467
|
-
|
|
468
|
-
expect(resolveTemplate).toHaveBeenCalledWith('tpl-detail')
|
|
469
|
-
const errorBanner = el.querySelector('.u-report-viewer__error')!
|
|
470
|
-
expect(errorBanner.textContent).toContain('tpl-detail')
|
|
471
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
472
|
-
expect(calls).toHaveLength(1)
|
|
473
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
474
|
-
})
|
|
475
|
-
|
|
476
|
-
it('下钻指向自身:正常压栈并逐级回退', async () => {
|
|
477
|
-
const { connector, calls } = createStubConnector({ [SELF_SQL]: SUMMARY_ROWS })
|
|
478
|
-
const selfTemplate = createSelfTemplate()
|
|
479
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-self': selfTemplate })
|
|
480
|
-
const { el } = mountViewer({
|
|
481
|
-
connector,
|
|
482
|
-
template: selfTemplate,
|
|
483
|
-
workbook: new Workbook(),
|
|
484
|
-
resolveTemplate
|
|
485
|
-
})
|
|
486
|
-
await flushViewer()
|
|
487
|
-
expect(calls[0]).toMatchObject({ sql: SELF_SQL, values: { p_region: '' } })
|
|
488
|
-
|
|
489
|
-
// 第一次自指:(1,0) 华东 → p_region=华东
|
|
490
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
491
|
-
dispatchGridClick(el)
|
|
492
|
-
await flushViewer()
|
|
493
|
-
expect(calls[1]).toMatchObject({ sql: SELF_SQL, values: { p_region: '华东' } })
|
|
494
|
-
|
|
495
|
-
// 第二次自指:(2,0) 华南 → p_region=华南
|
|
496
|
-
mockHitAddr({ row: 2, col: 0 })
|
|
497
|
-
dispatchGridClick(el)
|
|
498
|
-
await flushViewer()
|
|
499
|
-
expect(calls[2]).toMatchObject({ sql: SELF_SQL, values: { p_region: '华南' } })
|
|
500
|
-
|
|
501
|
-
// 逐级回退:恢复各层当时参数并重新取数
|
|
502
|
-
await clickButton(el.querySelector<HTMLElement>(`${DRILL_BAR_CLS} button`)!)
|
|
503
|
-
expect(calls[3]).toMatchObject({ sql: SELF_SQL, values: { p_region: '华东' } })
|
|
504
|
-
await clickButton(el.querySelector<HTMLElement>(`${DRILL_BAR_CLS} button`)!)
|
|
505
|
-
expect(calls[4]).toMatchObject({ sql: SELF_SQL, values: { p_region: '' } })
|
|
506
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
507
|
-
})
|
|
508
|
-
|
|
509
|
-
it('悬停配了下钻的格子时出现可点光标提示,移出后消失', async () => {
|
|
510
|
-
const { connector } = createStubConnector({ [SUMMARY_SQL]: SUMMARY_ROWS })
|
|
511
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-detail': createDetailTemplate() })
|
|
512
|
-
const { el } = mountViewer({
|
|
513
|
-
connector,
|
|
514
|
-
template: createSummaryTemplate(),
|
|
515
|
-
workbook: new Workbook(),
|
|
516
|
-
resolveTemplate
|
|
517
|
-
})
|
|
518
|
-
await flushViewer()
|
|
519
|
-
|
|
520
|
-
const sheetEl = el.querySelector(`.${SHEET_CLS}`)!
|
|
521
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
522
|
-
dispatchGridPointerMove(el)
|
|
523
|
-
await nextTick()
|
|
524
|
-
expect(sheetEl.classList.contains(DRILL_HOVER_CLS)).toBe(true)
|
|
525
|
-
|
|
526
|
-
mockHitAddr({ row: 0, col: 0 })
|
|
527
|
-
dispatchGridPointerMove(el)
|
|
528
|
-
await nextTick()
|
|
529
|
-
expect(sheetEl.classList.contains(DRILL_HOVER_CLS)).toBe(false)
|
|
530
|
-
})
|
|
531
|
-
|
|
532
|
-
it('查看态自动为配了下钻的单元格应用超链接样式(蓝色字体与下划线)', async () => {
|
|
533
|
-
const { connector } = createStubConnector({ [SUMMARY_SQL]: SUMMARY_ROWS })
|
|
534
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-detail': createDetailTemplate() })
|
|
535
|
-
const { el } = mountViewer({
|
|
536
|
-
connector,
|
|
537
|
-
template: createSummaryTemplate(),
|
|
538
|
-
workbook: new Workbook(),
|
|
539
|
-
resolveTemplate
|
|
540
|
-
})
|
|
541
|
-
await flushViewer()
|
|
542
|
-
|
|
543
|
-
const sheetComp = (el.querySelector('.u-sheet') as any)?.__vueParentComponent
|
|
544
|
-
const sheetProps = sheetComp?.props
|
|
545
|
-
expect(typeof sheetProps?.resolveCellStyle).toBe('function')
|
|
546
|
-
|
|
547
|
-
// (1,0) 华东分组格配了下钻 -> 带有超链接样式
|
|
548
|
-
const drillStyle = sheetProps.resolveCellStyle({ row: 1, col: 0 }, undefined)
|
|
549
|
-
expect(drillStyle?.font?.color).toBe('#2f54eb')
|
|
550
|
-
expect(drillStyle?.font?.underline).toBe(true)
|
|
551
|
-
|
|
552
|
-
// (0,0) 静态表头未配下钻 -> 不附加超链接样式
|
|
553
|
-
const staticStyle = sheetProps.resolveCellStyle({ row: 0, col: 0 }, undefined)
|
|
554
|
-
expect(staticStyle).toBeUndefined()
|
|
555
|
-
})
|
|
556
|
-
})
|
|
557
|
-
|
|
558
|
-
describe('UReportViewer 下钻(UDialog 弹框)', () => {
|
|
559
|
-
it('dialog 方式打开完整查看器:映射参数带入、Filter Bar 可改值,外层不受影响', async () => {
|
|
560
|
-
const { connector, calls } = createStubConnector({
|
|
561
|
-
[SUMMARY_SQL]: SUMMARY_ROWS,
|
|
562
|
-
[ORDERS_SQL]: ORDER_ROWS
|
|
563
|
-
})
|
|
564
|
-
const resolveTemplate = createTemplateResolver({ 'tpl-detail': createDetailTemplate() })
|
|
565
|
-
const workbook = new Workbook()
|
|
566
|
-
const { el } = mountViewer({
|
|
567
|
-
connector,
|
|
568
|
-
template: createSummaryTemplate('dialog'),
|
|
569
|
-
workbook,
|
|
570
|
-
resolveTemplate
|
|
571
|
-
})
|
|
572
|
-
await flushViewer()
|
|
573
|
-
expect(calls).toHaveLength(1)
|
|
574
|
-
|
|
575
|
-
const dialog = await openDrillDialog(el)
|
|
576
|
-
expect(resolveTemplate).toHaveBeenCalledWith('tpl-detail')
|
|
577
|
-
expect(calls).toHaveLength(2)
|
|
578
|
-
expect(calls[1]).toMatchObject({ sql: ORDERS_SQL, values: { p_region: '华东' } })
|
|
579
|
-
|
|
580
|
-
const innerInput = dialog.querySelector<HTMLInputElement>(
|
|
581
|
-
'.u-report-filter-bar .u-input input'
|
|
582
|
-
)!
|
|
583
|
-
expect(innerInput.value).toBe('华东')
|
|
584
|
-
expect(nestedActiveSheet(dialog)?.getDisplayValue({ row: 1, col: 0 })).toBe('甲公司')
|
|
585
|
-
|
|
586
|
-
// 外层仍是主表:无回退条、填充不变
|
|
587
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
588
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
589
|
-
|
|
590
|
-
innerInput.value = '华南'
|
|
591
|
-
innerInput.dispatchEvent(
|
|
592
|
-
new InputEvent('input', { bubbles: true, data: '华南', inputType: 'insertText' })
|
|
593
|
-
)
|
|
594
|
-
await flushViewer()
|
|
595
|
-
expect(calls[2]).toMatchObject({ sql: ORDERS_SQL, values: { p_region: '华南' } })
|
|
596
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
597
|
-
})
|
|
598
|
-
|
|
599
|
-
it('弹框内可继续下钻与逐级回退,外层栈不变', async () => {
|
|
600
|
-
const { connector, calls } = createStubConnector({
|
|
601
|
-
[SUMMARY_SQL]: SUMMARY_ROWS,
|
|
602
|
-
[ORDERS_SQL]: ORDER_ROWS,
|
|
603
|
-
[ITEMS_SQL]: ITEM_ROWS
|
|
604
|
-
})
|
|
605
|
-
const resolveTemplate = createTemplateResolver({
|
|
606
|
-
'tpl-detail': createDetailTemplate(),
|
|
607
|
-
'tpl-third': createThirdTemplate()
|
|
608
|
-
})
|
|
609
|
-
const workbook = new Workbook()
|
|
610
|
-
const { el } = mountViewer({
|
|
611
|
-
connector,
|
|
612
|
-
template: createSummaryTemplate('dialog'),
|
|
613
|
-
workbook,
|
|
614
|
-
resolveTemplate
|
|
615
|
-
})
|
|
616
|
-
await flushViewer()
|
|
617
|
-
|
|
618
|
-
const dialog = await openDrillDialog(el)
|
|
619
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
620
|
-
dispatchGridClick(dialog)
|
|
621
|
-
await flushViewer()
|
|
622
|
-
|
|
623
|
-
expect(calls[2]).toMatchObject({ sql: ITEMS_SQL, values: { p_customer: '甲公司' } })
|
|
624
|
-
expect(nestedActiveSheet(dialog)?.getDisplayValue({ row: 1, col: 0 })).toBe('X 项目')
|
|
625
|
-
expect(dialog.querySelector(DRILL_BAR_CLS)).toBeTruthy()
|
|
626
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
627
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
628
|
-
|
|
629
|
-
await clickButton(dialog.querySelector<HTMLElement>(`${DRILL_BAR_CLS} button`)!)
|
|
630
|
-
expect(calls[3]).toMatchObject({ sql: ORDERS_SQL, values: { p_region: '华东' } })
|
|
631
|
-
expect(nestedActiveSheet(dialog)?.getDisplayValue({ row: 1, col: 0 })).toBe('甲公司')
|
|
632
|
-
expect(dialog.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
633
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
634
|
-
})
|
|
635
|
-
|
|
636
|
-
it('关闭弹框(按钮 / 遮罩 / Esc)丢弃框内栈,回到打开前', async () => {
|
|
637
|
-
const { connector, calls } = createStubConnector({
|
|
638
|
-
[SUMMARY_SQL]: SUMMARY_ROWS,
|
|
639
|
-
[ORDERS_SQL]: ORDER_ROWS,
|
|
640
|
-
[ITEMS_SQL]: ITEM_ROWS
|
|
641
|
-
})
|
|
642
|
-
const resolveTemplate = createTemplateResolver({
|
|
643
|
-
'tpl-detail': createDetailTemplate(),
|
|
644
|
-
'tpl-third': createThirdTemplate()
|
|
645
|
-
})
|
|
646
|
-
const workbook = new Workbook()
|
|
647
|
-
const { el } = mountViewer({
|
|
648
|
-
connector,
|
|
649
|
-
template: createSummaryTemplate('dialog'),
|
|
650
|
-
workbook,
|
|
651
|
-
resolveTemplate
|
|
652
|
-
})
|
|
653
|
-
await flushViewer()
|
|
654
|
-
|
|
655
|
-
async function drillInside(dialog: HTMLElement): Promise<void> {
|
|
656
|
-
mockHitAddr({ row: 1, col: 0 })
|
|
657
|
-
dispatchGridClick(dialog)
|
|
658
|
-
await flushViewer()
|
|
659
|
-
expect(nestedActiveSheet(dialog)?.getDisplayValue({ row: 1, col: 0 })).toBe('X 项目')
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
function assertOuterUnchanged(): void {
|
|
663
|
-
expect(drillDialogEl()).toBeNull()
|
|
664
|
-
expect(el.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
665
|
-
expect(workbook.activeSheet.getDisplayValue({ row: 1, col: 0 })).toBe('华东')
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
const byButton = await openDrillDialog(el)
|
|
669
|
-
await drillInside(byButton)
|
|
670
|
-
byButton.querySelector<HTMLElement>('.u-dialog__btn-close')!.click()
|
|
671
|
-
await flushViewer()
|
|
672
|
-
assertOuterUnchanged()
|
|
673
|
-
|
|
674
|
-
// 再打开应是新的框内栈(明细层),而不是关闭前的第三层
|
|
675
|
-
const again = await openDrillDialog(el)
|
|
676
|
-
expect(nestedActiveSheet(again)?.getDisplayValue({ row: 1, col: 0 })).toBe('甲公司')
|
|
677
|
-
expect(again.querySelector(DRILL_BAR_CLS)).toBeNull()
|
|
678
|
-
await drillInside(again)
|
|
679
|
-
again.parentElement!.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))
|
|
680
|
-
await flushViewer()
|
|
681
|
-
assertOuterUnchanged()
|
|
682
|
-
|
|
683
|
-
const byEsc = await openDrillDialog(el)
|
|
684
|
-
await drillInside(byEsc)
|
|
685
|
-
byEsc.parentElement!.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape', bubbles: true }))
|
|
686
|
-
await flushViewer()
|
|
687
|
-
assertOuterUnchanged()
|
|
688
|
-
|
|
689
|
-
// 关闭不触发外层重新取数(calls[0] 为主表,其余为弹框内)
|
|
690
|
-
expect(calls.filter((call) => call.sql === SUMMARY_SQL)).toHaveLength(1)
|
|
691
|
-
})
|
|
692
|
-
})
|