@veltra/sheet 2.4.0 → 2.5.1

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 (147) hide show
  1. package/dist/components/sheet/formula-bar.js +50 -7
  2. package/dist/components/sheet/style2.css +2 -2
  3. package/dist/index.d.ts +2 -19
  4. package/dist/index.js +2 -15
  5. package/dist/types/index.d.ts +1 -3
  6. package/package.json +5 -6
  7. package/src/components/sheet/__test__/formula-bar.test.ts +29 -0
  8. package/src/components/sheet/formula-bar.vue +67 -6
  9. package/src/components/sheet/style.scss +1 -1
  10. package/src/index.ts +1 -27
  11. package/src/types/index.ts +0 -2
  12. package/dist/components/report/binding-badge.js +0 -118
  13. package/dist/components/report/designer/cell-coords.js +0 -46
  14. package/dist/components/report/designer/col-widths.js +0 -29
  15. package/dist/components/report/designer/conditional-rules/helpers.js +0 -139
  16. package/dist/components/report/designer/drill-dialog.js +0 -258
  17. package/dist/components/report/designer/drop-highlight-overlay.js +0 -76
  18. package/dist/components/report/designer/float-panel.js +0 -434
  19. package/dist/components/report/designer/role.js +0 -17
  20. package/dist/components/report/designer/rule-preview.js +0 -33
  21. package/dist/components/report/designer/rule-row.js +0 -253
  22. package/dist/components/report/designer/rules-dialog.js +0 -118
  23. package/dist/components/report/designer/topology-overlay.js +0 -122
  24. package/dist/components/report/designer/topology.js +0 -64
  25. package/dist/components/report/designer/use-grid-overlay.js +0 -75
  26. package/dist/components/report/designer-hub.js +0 -177
  27. package/dist/components/report/field-panel-helpers.js +0 -33
  28. package/dist/components/report/field-panel.js +0 -132
  29. package/dist/components/report/filter-bar.js +0 -74
  30. package/dist/components/report/hub-connection-form.js +0 -145
  31. package/dist/components/report/hub-dataset-editor.js +0 -409
  32. package/dist/components/report/preview-grid-size.js +0 -32
  33. package/dist/components/report/print.js +0 -39
  34. package/dist/components/report/report-designer.js +0 -428
  35. package/dist/components/report/report-viewer.js +0 -253
  36. package/dist/components/report/style.d.ts +0 -17
  37. package/dist/components/report/style.js +0 -18
  38. package/dist/components/report/style2.css +0 -965
  39. package/dist/components/report/use-report-designer.js +0 -387
  40. package/dist/components/report/use-report-viewer.js +0 -140
  41. package/dist/report/binding.d.ts +0 -83
  42. package/dist/report/binding.js +0 -334
  43. package/dist/report/connector.d.ts +0 -66
  44. package/dist/report/connector.js +0 -159
  45. package/dist/report/drill.d.ts +0 -48
  46. package/dist/report/drill.js +0 -78
  47. package/dist/report/export-xlsx.d.ts +0 -13
  48. package/dist/report/export-xlsx.js +0 -13
  49. package/dist/report/filter-bar.d.ts +0 -10
  50. package/dist/report/filter-bar.js +0 -31
  51. package/dist/report/index.d.ts +0 -14
  52. package/dist/report/params.d.ts +0 -13
  53. package/dist/report/params.js +0 -61
  54. package/dist/report/print.d.ts +0 -23
  55. package/dist/report/print.js +0 -197
  56. package/dist/report/render/aggregate.js +0 -193
  57. package/dist/report/render/builder.d.ts +0 -12
  58. package/dist/report/render/builder.js +0 -139
  59. package/dist/report/render/coordinate.d.ts +0 -25
  60. package/dist/report/render/coordinate.js +0 -733
  61. package/dist/report/render/index.d.ts +0 -14
  62. package/dist/report/render/index.js +0 -21
  63. package/dist/report/render/style-resolver.js +0 -50
  64. package/dist/report/render/template-index.d.ts +0 -24
  65. package/dist/report/render/template-index.js +0 -137
  66. package/dist/report/rules/evaluate.d.ts +0 -25
  67. package/dist/report/rules/evaluate.js +0 -82
  68. package/dist/report/rules/index.d.ts +0 -2
  69. package/dist/report/template.d.ts +0 -63
  70. package/dist/report/template.js +0 -83
  71. package/dist/report/types.d.ts +0 -103
  72. package/dist/types/report-designer.d.ts +0 -51
  73. package/dist/types/report-viewer.d.ts +0 -57
  74. package/src/components/report/__test__/binding-badge.test.ts +0 -92
  75. package/src/components/report/__test__/conditional-rules-helpers.test.ts +0 -88
  76. package/src/components/report/__test__/field-panel-helpers.test.ts +0 -65
  77. package/src/components/report/__test__/float-panel-position.test.ts +0 -45
  78. package/src/components/report/__test__/preview-grid-size.test.ts +0 -63
  79. package/src/components/report/__test__/report-designer.test.ts +0 -559
  80. package/src/components/report/__test__/report-drill.test.ts +0 -692
  81. package/src/components/report/__test__/report-viewer.test.ts +0 -400
  82. package/src/components/report/__test__/topology.test.ts +0 -143
  83. package/src/components/report/__test__/use-report-designer.test.ts +0 -804
  84. package/src/components/report/binding-badge.ts +0 -122
  85. package/src/components/report/designer/cell-coords.ts +0 -95
  86. package/src/components/report/designer/col-widths.ts +0 -56
  87. package/src/components/report/designer/conditional-rules/helpers.ts +0 -189
  88. package/src/components/report/designer/drill-dialog.vue +0 -245
  89. package/src/components/report/designer/drop-highlight-overlay.vue +0 -75
  90. package/src/components/report/designer/float-panel.vue +0 -444
  91. package/src/components/report/designer/role.ts +0 -32
  92. package/src/components/report/designer/rule-preview.vue +0 -40
  93. package/src/components/report/designer/rule-row.vue +0 -252
  94. package/src/components/report/designer/rules-dialog.vue +0 -110
  95. package/src/components/report/designer/topology-overlay.vue +0 -128
  96. package/src/components/report/designer/topology.ts +0 -124
  97. package/src/components/report/designer/use-grid-overlay.ts +0 -114
  98. package/src/components/report/designer-hub.vue +0 -198
  99. package/src/components/report/field-panel-helpers.ts +0 -44
  100. package/src/components/report/field-panel.vue +0 -136
  101. package/src/components/report/filter-bar.vue +0 -77
  102. package/src/components/report/hub-connection-form.vue +0 -124
  103. package/src/components/report/hub-dataset-editor.vue +0 -387
  104. package/src/components/report/index.ts +0 -2
  105. package/src/components/report/preview-grid-size.ts +0 -33
  106. package/src/components/report/print.ts +0 -44
  107. package/src/components/report/report-designer.vue +0 -454
  108. package/src/components/report/report-viewer.vue +0 -289
  109. package/src/components/report/style-designer.scss +0 -653
  110. package/src/components/report/style-hub.scss +0 -292
  111. package/src/components/report/style-viewer.scss +0 -144
  112. package/src/components/report/style.scss +0 -3
  113. package/src/components/report/style.ts +0 -20
  114. package/src/components/report/use-report-designer.ts +0 -603
  115. package/src/components/report/use-report-viewer.ts +0 -227
  116. package/src/report/__test__/binding.test.ts +0 -320
  117. package/src/report/__test__/connector.test.ts +0 -239
  118. package/src/report/__test__/drill.test.ts +0 -194
  119. package/src/report/__test__/export-xlsx.test.ts +0 -96
  120. package/src/report/__test__/filter-bar.test.ts +0 -58
  121. package/src/report/__test__/params.test.ts +0 -156
  122. package/src/report/__test__/print.test.ts +0 -170
  123. package/src/report/__test__/render.test.ts +0 -856
  124. package/src/report/__test__/rules.test.ts +0 -131
  125. package/src/report/__test__/template.test.ts +0 -366
  126. package/src/report/binding.ts +0 -474
  127. package/src/report/connector.ts +0 -206
  128. package/src/report/drill.ts +0 -112
  129. package/src/report/export-xlsx.ts +0 -15
  130. package/src/report/filter-bar.ts +0 -36
  131. package/src/report/index.ts +0 -16
  132. package/src/report/params.ts +0 -96
  133. package/src/report/print.ts +0 -234
  134. package/src/report/render/__test__/aggregate.test.ts +0 -16
  135. package/src/report/render/__test__/coordinate.test.ts +0 -405
  136. package/src/report/render/aggregate.ts +0 -289
  137. package/src/report/render/builder.ts +0 -211
  138. package/src/report/render/coordinate.ts +0 -1239
  139. package/src/report/render/index.ts +0 -30
  140. package/src/report/render/style-resolver.ts +0 -68
  141. package/src/report/render/template-index.ts +0 -200
  142. package/src/report/rules/evaluate.ts +0 -113
  143. package/src/report/rules/index.ts +0 -7
  144. package/src/report/template.ts +0 -145
  145. package/src/report/types.ts +0 -116
  146. package/src/types/report-designer.ts +0 -55
  147. package/src/types/report-viewer.ts +0 -54
@@ -1,156 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from '../params'
4
- import type { QueryParamDef } from '../types'
5
-
6
- describe('report params', () => {
7
- describe('extractParamIds', () => {
8
- it('从 SQL 提取 ${param} 占位符并去重', () => {
9
- expect(
10
- extractParamIds(
11
- 'SELECT * FROM orders WHERE order_date >= ${dateFrom} AND order_date <= ${dateTo}'
12
- )
13
- ).toEqual(['dateFrom', 'dateTo'])
14
-
15
- expect(
16
- extractParamIds("SELECT * FROM orders WHERE region = ${region} AND ${region} != ''")
17
- ).toEqual(['region'])
18
- expect(extractParamIds('SELECT * FROM orders')).toEqual([])
19
- })
20
-
21
- it('忽略空白占位符与未闭合占位符', () => {
22
- expect(extractParamIds('WHERE a = ${ } AND b = ${ x }')).toEqual(['x'])
23
- expect(extractParamIds('WHERE a = ${unclosed')).toEqual([])
24
- })
25
- })
26
-
27
- describe('buildParamDefs', () => {
28
- it('等值比较推断 number 类型(旧行为;编辑器通常覆盖为 select/text)', () => {
29
- expect(buildParamDefs('SELECT customer FROM orders WHERE region = ${region}')).toEqual([
30
- { id: 'region', label: 'region', type: 'number', defaultValue: 0 }
31
- ])
32
- })
33
-
34
- it('BETWEEN 单参数推断 date-range 类型', () => {
35
- const params = buildParamDefs(
36
- 'SELECT customer FROM orders WHERE order_date BETWEEN ${dateRange}'
37
- )
38
- expect(params).toHaveLength(1)
39
- expect(params[0]?.id).toBe('dateRange')
40
- expect(params[0]?.type).toBe('date-range')
41
- expect(params[0]?.defaultValue).toEqual(['', ''])
42
- })
43
-
44
- it('BETWEEN 双参数:首参推断 date,次参无 AND 后续回落 text(旧行为)', () => {
45
- const sql = 'SELECT customer FROM orders WHERE order_date BETWEEN ${dateFrom} AND ${dateTo}'
46
- const params = buildParamDefs(sql)
47
- const types = Object.fromEntries(params.map((p) => [p.id, p.type]))
48
- expect(types).toEqual({ dateFrom: 'date', dateTo: 'text' })
49
- })
50
-
51
- it('LIKE 推断 text、数值比较推断 number', () => {
52
- expect(
53
- buildParamDefs('SELECT customer FROM orders WHERE customer LIKE ${keyword}')[0]?.type
54
- ).toBe('text')
55
- expect(
56
- buildParamDefs('SELECT customer FROM orders WHERE amount > ${minAmount}')[0]?.type
57
- ).toBe('number')
58
- })
59
-
60
- it('元数据覆盖 label / 类型 / 默认值 / 选项', () => {
61
- const params = buildParamDefs('SELECT customer FROM orders WHERE region = ${region}', {
62
- region: {
63
- label: '地区',
64
- type: 'select',
65
- defaultValue: '',
66
- options: [
67
- { label: '华东', value: '华东' },
68
- { label: '华南', value: '华南' }
69
- ]
70
- }
71
- })
72
- expect(params[0]).toEqual({
73
- id: 'region',
74
- label: '地区',
75
- type: 'select',
76
- defaultValue: '',
77
- options: [
78
- { label: '华东', value: '华东' },
79
- { label: '华南', value: '华南' }
80
- ]
81
- })
82
- })
83
- })
84
-
85
- describe('resolveBoundDatasetParams', () => {
86
- const DATE_FROM: QueryParamDef = {
87
- id: 'dateFrom',
88
- label: '开始日期',
89
- type: 'date',
90
- defaultValue: '2024-01-01'
91
- }
92
- const DATE_TO: QueryParamDef = {
93
- id: 'dateTo',
94
- label: '结束日期',
95
- type: 'date',
96
- defaultValue: '2024-12-31'
97
- }
98
- const REGION: QueryParamDef = {
99
- id: 'region',
100
- label: '地区',
101
- type: 'select',
102
- defaultValue: '',
103
- options: [{ label: '华东', value: '华东' }]
104
- }
105
- const ALERT_THRESHOLD: QueryParamDef = {
106
- id: 'alertThreshold',
107
- label: '库存预警阈值',
108
- type: 'number',
109
- defaultValue: 80
110
- }
111
-
112
- const datasetParams: Record<string, QueryParamDef[]> = {
113
- orders: [DATE_FROM, DATE_TO, REGION],
114
- customers: [REGION],
115
- 'sales-matrix': [REGION],
116
- 'inventory-alerts': [ALERT_THRESHOLD]
117
- }
118
-
119
- it('按绑定数据集合并查询参数并去重', () => {
120
- const merged = resolveBoundDatasetParams(
121
- [],
122
- ['orders', 'customers'],
123
- (id) => datasetParams[id] ?? []
124
- )
125
- expect(merged.map((item) => item.id).sort()).toEqual(['dateFrom', 'dateTo', 'region'])
126
-
127
- const matrix = resolveBoundDatasetParams(
128
- [],
129
- ['sales-matrix'],
130
- (id) => datasetParams[id] ?? []
131
- )
132
- expect(matrix.map((item) => item.id)).toEqual(['region'])
133
-
134
- const inventory = resolveBoundDatasetParams(
135
- [],
136
- ['inventory-alerts'],
137
- (id) => datasetParams[id] ?? []
138
- )
139
- expect(inventory.map((item) => item.id)).toEqual(['alertThreshold'])
140
- })
141
-
142
- it('无绑定数据集时回退全局参数', () => {
143
- const fallback = resolveBoundDatasetParams([REGION], [], () => [])
144
- expect(fallback.map((item) => item.id)).toEqual(['region'])
145
- })
146
-
147
- it('同名参数先见为准', () => {
148
- const overridden: QueryParamDef = { ...REGION, label: '覆盖地区' }
149
- const merged = resolveBoundDatasetParams([], ['orders', 'customers'], (id) =>
150
- id === 'orders' ? [REGION] : [overridden]
151
- )
152
- expect(merged).toHaveLength(1)
153
- expect(merged[0]?.label).toBe('地区')
154
- })
155
- })
156
- })
@@ -1,170 +0,0 @@
1
- import { Sheet } from '@veltra/sheet-core'
2
- import { describe, expect, it } from 'vitest'
3
-
4
- import { buildFilledReportPrintHtml } from '../print'
5
-
6
- /** 基础填充表:表头 + 两列数据 */
7
- function createFilledSheet(name = '销售报表'): Sheet {
8
- const sheet = new Sheet(name)
9
- sheet.setCells([
10
- { addr: { row: 0, col: 0 }, data: { v: '客户' } },
11
- { addr: { row: 0, col: 1 }, data: { v: '金额' } },
12
- { addr: { row: 1, col: 0 }, data: { v: '甲公司' } },
13
- { addr: { row: 1, col: 1 }, data: { v: 100 } }
14
- ])
15
- return sheet
16
- }
17
-
18
- describe('buildFilledReportPrintHtml', () => {
19
- it('输出完整打印文档:值为文本、默认 A4 纵向、缺省标题取 sheet 名', () => {
20
- const html = buildFilledReportPrintHtml(createFilledSheet())
21
-
22
- expect(html).toContain('<!doctype html>')
23
- expect(html).toContain('<title>销售报表</title>')
24
- expect(html).toContain('@page { size: A4 portrait;')
25
- expect(html).toContain('<td>客户</td>')
26
- expect(html).toContain('<td>100</td>')
27
- // 默认列宽 80 / 行高 28(对齐 grid 默认)
28
- expect(html).toContain('<col style="width:80px">')
29
- expect(html).toContain('<tr style="height:28px">')
30
- // 背景色打印保色
31
- expect(html).toContain('print-color-adjust: exact')
32
- })
33
-
34
- it('选项:title 覆盖、landscape 方向;空名 sheet 回落「报表」', () => {
35
- const html = buildFilledReportPrintHtml(createFilledSheet(), {
36
- title: '月度报表',
37
- orientation: 'landscape'
38
- })
39
- expect(html).toContain('<title>月度报表</title>')
40
- expect(html).toContain('@page { size: A4 landscape;')
41
-
42
- const fallback = buildFilledReportPrintHtml(new Sheet(''))
43
- expect(fallback).toContain('<title>报表</title>')
44
- })
45
-
46
- it('合并格映射 rowspan/colspan,被覆盖格不输出', () => {
47
- const sheet = createFilledSheet()
48
- sheet.mergeCells({ start: { row: 0, col: 0 }, end: { row: 1, col: 1 } })
49
-
50
- const html = buildFilledReportPrintHtml(sheet)
51
- expect(html).toContain('<td colspan="2" rowspan="2">客户</td>')
52
- // 2×2 合并后只剩 1 个 td(锚点),覆盖格跳过
53
- const tdCount = (html.match(/<td/g) ?? []).length
54
- expect(tdCount).toBe(1)
55
- })
56
-
57
- it('有效样式序列化为内联 CSS(fill/border/font/align/wrap)', () => {
58
- const sheet = createFilledSheet()
59
- sheet.setCellStyle(
60
- { start: { row: 0, col: 0 }, end: { row: 0, col: 0 } },
61
- {
62
- fill: { color: '#ff0000' },
63
- border: { top: { style: 'thin', width: 1, color: '#000000' } },
64
- font: {
65
- bold: true,
66
- italic: true,
67
- underline: true,
68
- strikethrough: true,
69
- size: 14,
70
- color: '#111111'
71
- },
72
- align: { horizontal: 'center', vertical: 'middle', wrap: true }
73
- }
74
- )
75
- sheet.setCellStyle(
76
- { start: { row: 1, col: 1 }, end: { row: 1, col: 1 } },
77
- { align: { horizontal: 'right' } }
78
- )
79
-
80
- const html = buildFilledReportPrintHtml(sheet)
81
- expect(html).toContain('background-color:#ff0000')
82
- expect(html).toContain('border-top:1px solid #000000')
83
- expect(html).toContain('font-weight:bold')
84
- expect(html).toContain('font-style:italic')
85
- expect(html).toContain('text-decoration:underline line-through')
86
- expect(html).toContain('font-size:14pt')
87
- expect(html).toContain('color:#111111')
88
- expect(html).toContain('text-align:center')
89
- expect(html).toContain('vertical-align:middle')
90
- expect(html).toContain('white-space:normal;word-break:break-all')
91
- expect(html).toContain('text-align:right')
92
- })
93
-
94
- it('虚线/点线边框线型映射 CSS dashed/dotted', () => {
95
- const sheet = createFilledSheet()
96
- sheet.setCellStyle(
97
- { start: { row: 0, col: 0 }, end: { row: 0, col: 0 } },
98
- {
99
- border: {
100
- left: { style: 'dashed', width: 1, color: '#000000' },
101
- right: { style: 'dotted', width: 2, color: '#00ff00' }
102
- }
103
- }
104
- )
105
- const html = buildFilledReportPrintHtml(sheet)
106
- expect(html).toContain('border-left:1px dashed #000000')
107
- expect(html).toContain('border-right:2px dotted #00ff00')
108
- })
109
-
110
- it('自定义列宽 / 行高写入 colgroup 与 tr', () => {
111
- const sheet = createFilledSheet()
112
- sheet.setColWidth(1, 160)
113
- sheet.setRowHeight(1, 40)
114
-
115
- const html = buildFilledReportPrintHtml(sheet)
116
- expect(html).toContain('<col style="width:160px">')
117
- expect(html).toContain('<tr style="height:40px">')
118
- })
119
-
120
- it('文本与标题 HTML 转义', () => {
121
- const sheet = new Sheet('报表<Q>')
122
- sheet.setCells([{ addr: { row: 0, col: 0 }, data: { v: '<b>"x"</b> & y' } }])
123
-
124
- const html = buildFilledReportPrintHtml(sheet)
125
- expect(html).toContain('<title>报表&lt;Q&gt;</title>')
126
- expect(html).toContain('<td>&lt;b&gt;"x"&lt;/b&gt; &amp; y</td>')
127
- expect(html).not.toContain('<td><b>')
128
- })
129
-
130
- it('浮动图:data URL 内嵌,锚点格左上 + 格内偏移定位,显式宽高直出', () => {
131
- const sheet = createFilledSheet()
132
- sheet.setColWidth(0, 100)
133
- sheet.insertImage({
134
- data: new Uint8Array([1, 2, 3]),
135
- type: 'png',
136
- anchor: { from: { row: 1, col: 1, offsetX: 10, offsetY: 5 } },
137
- width: 48,
138
- height: 24,
139
- altText: '图章'
140
- })
141
-
142
- const html = buildFilledReportPrintHtml(sheet)
143
- // left = col0 宽 100 + 默认列宽 80(col1 前)→ 取 col1 左缘 100... colWidths=[100,80],col1 左缘=100,+offsetX=110
144
- // top = row0 高 28,+offsetY=5 → 33
145
- expect(html).toContain(`<img src="data:image/png;base64,AQID"`)
146
- expect(html).toContain('left:110px;top:33px;width:48px;height:24px;')
147
- expect(html).toContain('alt="图章"')
148
- })
149
-
150
- it('浮动图:宽高缺失且有 to 时按 from→to 跨度兜底', () => {
151
- const sheet = createFilledSheet()
152
- sheet.insertImage({
153
- data: new Uint8Array([0]),
154
- type: 'jpeg',
155
- anchor: { from: { row: 0, col: 0 }, to: { row: 1, col: 1 } }
156
- })
157
-
158
- const html = buildFilledReportPrintHtml(sheet)
159
- // 跨度:col0+col1 = 80+80 = 160;row0+row1 = 28+28 = 56
160
- expect(html).toContain('left:0px;top:0px;width:160px;height:56px;')
161
- expect(html).toContain('data:image/jpeg;base64,')
162
- })
163
-
164
- it('空 sheet 输出合法空表文档', () => {
165
- const html = buildFilledReportPrintHtml(new Sheet('空白'))
166
- expect(html).toContain('<title>空白</title>')
167
- expect(html).toContain('<table>')
168
- expect(html).not.toContain('<tr')
169
- })
170
- })