vxe-table 3.20.7 → 3.20.9

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 (144) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +106 -106
  3. package/es/index.esm.js +2 -1
  4. package/es/style.css +1 -1
  5. package/es/table/src/methods.js +81 -84
  6. package/es/table/src/table.js +20 -1
  7. package/es/table/src/util.js +6 -0
  8. package/es/table/style.css +18 -48
  9. package/es/ui/index.js +1 -1
  10. package/es/ui/src/dom.js +19 -20
  11. package/es/ui/src/log.js +1 -1
  12. package/es/vxe-table/style.css +18 -48
  13. package/lib/index.common.js +2 -1
  14. package/lib/index.umd.js +1985 -3291
  15. package/lib/index.umd.min.js +1 -1
  16. package/lib/style.css +1 -1
  17. package/lib/table/src/methods.js +17 -15
  18. package/lib/table/src/methods.min.js +1 -1
  19. package/lib/table/src/table.js +19 -1
  20. package/lib/table/src/table.min.js +1 -1
  21. package/lib/table/src/util.js +6 -0
  22. package/lib/table/src/util.min.js +1 -1
  23. package/lib/table/style/style.css +18 -48
  24. package/lib/ui/index.js +1 -1
  25. package/lib/ui/index.min.js +1 -1
  26. package/lib/ui/src/dom.js +21 -20
  27. package/lib/ui/src/dom.min.js +1 -1
  28. package/lib/ui/src/log.js +1 -1
  29. package/lib/ui/src/log.min.js +1 -1
  30. package/lib/v-x-e-table/index.js +2 -1
  31. package/lib/v-x-e-table/index.min.js +1 -1
  32. package/lib/vxe-colgroup/index.js +2 -1
  33. package/lib/vxe-colgroup/index.min.js +1 -1
  34. package/lib/vxe-column/index.js +2 -1
  35. package/lib/vxe-column/index.min.js +1 -1
  36. package/lib/vxe-grid/index.js +2 -1
  37. package/lib/vxe-grid/index.min.js +1 -1
  38. package/lib/vxe-table/index.js +2 -1
  39. package/lib/vxe-table/index.min.js +1 -1
  40. package/lib/vxe-table/style/style.css +18 -48
  41. package/lib/vxe-toolbar/index.js +2 -1
  42. package/lib/vxe-toolbar/index.min.js +1 -1
  43. package/lib/vxe-ui/index.js +2 -1
  44. package/lib/vxe-ui/index.min.js +1 -1
  45. package/lib/vxe-v-x-e-table/index.js +2 -1
  46. package/lib/vxe-v-x-e-table/index.min.js +1 -1
  47. package/package.json +93 -93
  48. package/packages/colgroup/index.ts +22 -22
  49. package/packages/column/index.ts +22 -22
  50. package/packages/components.ts +42 -42
  51. package/packages/grid/index.ts +22 -22
  52. package/packages/grid/src/grid.ts +1935 -1935
  53. package/packages/index.ts +4 -4
  54. package/packages/locale/lang/ar-EG.ts +832 -832
  55. package/packages/locale/lang/de-DE.ts +832 -832
  56. package/packages/locale/lang/en-US.ts +832 -832
  57. package/packages/locale/lang/es-ES.ts +832 -832
  58. package/packages/locale/lang/fr-FR.ts +832 -832
  59. package/packages/locale/lang/hu-HU.ts +832 -832
  60. package/packages/locale/lang/hy-AM.ts +832 -832
  61. package/packages/locale/lang/id-ID.ts +832 -832
  62. package/packages/locale/lang/it-IT.ts +832 -832
  63. package/packages/locale/lang/ja-JP.ts +832 -832
  64. package/packages/locale/lang/ko-KR.ts +832 -832
  65. package/packages/locale/lang/ms-MY.ts +832 -832
  66. package/packages/locale/lang/nb-NO.ts +832 -832
  67. package/packages/locale/lang/pt-BR.ts +832 -832
  68. package/packages/locale/lang/ru-RU.ts +832 -832
  69. package/packages/locale/lang/th-TH.ts +832 -832
  70. package/packages/locale/lang/ug-CN.ts +832 -832
  71. package/packages/locale/lang/uk-UA.ts +832 -832
  72. package/packages/locale/lang/uz-UZ.ts +832 -832
  73. package/packages/locale/lang/vi-VN.ts +832 -832
  74. package/packages/locale/lang/zh-CHT.ts +832 -832
  75. package/packages/locale/lang/zh-CN.ts +832 -832
  76. package/packages/locale/lang/zh-HK.ts +3 -3
  77. package/packages/locale/lang/zh-MO.ts +3 -3
  78. package/packages/locale/lang/zh-TC.ts +3 -3
  79. package/packages/locale/lang/zh-TW.ts +3 -3
  80. package/packages/table/index.ts +49 -49
  81. package/packages/table/module/custom/mixin.ts +369 -369
  82. package/packages/table/module/custom/panel.ts +1461 -1461
  83. package/packages/table/module/edit/mixin.ts +1123 -1123
  84. package/packages/table/module/export/export-panel.ts +658 -658
  85. package/packages/table/module/export/import-panel.ts +319 -319
  86. package/packages/table/module/export/mixin.ts +1693 -1693
  87. package/packages/table/module/export/util.ts +24 -24
  88. package/packages/table/module/filter/mixin.ts +507 -507
  89. package/packages/table/module/filter/panel.ts +329 -329
  90. package/packages/table/module/keyboard/mixin.ts +513 -513
  91. package/packages/table/module/menu/mixin.ts +329 -329
  92. package/packages/table/module/menu/panel.ts +212 -212
  93. package/packages/table/module/validator/mixin.ts +626 -626
  94. package/packages/table/render/index.ts +1456 -1456
  95. package/packages/table/src/body.ts +969 -969
  96. package/packages/table/src/cell.ts +1285 -1285
  97. package/packages/table/src/column.ts +205 -205
  98. package/packages/table/src/columnInfo.ts +228 -228
  99. package/packages/table/src/footer.ts +388 -388
  100. package/packages/table/src/group.ts +51 -51
  101. package/packages/table/src/header.ts +602 -602
  102. package/packages/table/src/methods.ts +12936 -12939
  103. package/packages/table/src/props.ts +311 -311
  104. package/packages/table/src/store.ts +15 -15
  105. package/packages/table/src/table.ts +2523 -2505
  106. package/packages/table/src/util.ts +1018 -1012
  107. package/packages/toolbar/index.ts +18 -18
  108. package/packages/toolbar/src/toolbar.ts +856 -856
  109. package/packages/ui/index.ts +530 -530
  110. package/packages/ui/src/anime.ts +52 -52
  111. package/packages/ui/src/comp.ts +3 -3
  112. package/packages/ui/src/dom.ts +237 -236
  113. package/packages/ui/src/log.ts +8 -8
  114. package/packages/ui/src/utils.ts +56 -56
  115. package/packages/ui/src/vn.ts +65 -65
  116. package/packages/v-x-e-table/index.ts +4 -4
  117. package/styles/all.scss +7 -7
  118. package/styles/base.scss +16 -16
  119. package/styles/components/grid.scss +89 -89
  120. package/styles/components/icon.scss +225 -225
  121. package/styles/components/old-icon.scss +715 -715
  122. package/styles/components/table-module/all.scss +6 -6
  123. package/styles/components/table-module/custom.scss +527 -527
  124. package/styles/components/table-module/export.scss +130 -130
  125. package/styles/components/table-module/filter.scss +130 -130
  126. package/styles/components/table-module/menu.scss +81 -81
  127. package/styles/components/table.scss +2679 -2679
  128. package/styles/components/toolbar.scss +119 -119
  129. package/styles/default.scss +2 -2
  130. package/styles/helpers/baseMixin.scss +95 -95
  131. package/styles/index.scss +3 -3
  132. package/styles/modules.scss +5 -5
  133. package/styles/theme/base.scss +93 -93
  134. package/styles/theme/dark.scss +49 -49
  135. package/styles/theme/light.scss +44 -44
  136. package/styles/variable.scss +43 -43
  137. package/types/all.d.ts +53 -53
  138. package/types/index.d.ts +4 -4
  139. /package/es/{iconfont.1773991883171.ttf → iconfont.1774420912543.ttf} +0 -0
  140. /package/es/{iconfont.1773991883171.woff → iconfont.1774420912543.woff} +0 -0
  141. /package/es/{iconfont.1773991883171.woff2 → iconfont.1774420912543.woff2} +0 -0
  142. /package/lib/{iconfont.1773991883171.ttf → iconfont.1774420912543.ttf} +0 -0
  143. /package/lib/{iconfont.1773991883171.woff → iconfont.1774420912543.woff} +0 -0
  144. /package/lib/{iconfont.1773991883171.woff2 → iconfont.1774420912543.woff2} +0 -0
@@ -1,1693 +1,1693 @@
1
- import XEUtils from 'xe-utils'
2
- import { VxeUI } from '../../../ui'
3
- import { isColumnInfo, getCellValue, createHandleGetRowId } from '../../src/util'
4
- import { parseFile, formatText, eqEmptyValue } from '../../../ui/src/utils'
5
- import { hasClass } from '../../../ui/src/dom'
6
- import { createHtmlPage, getExportBlobByContent } from './util'
7
- import { warnLog, errLog } from '../../../ui/src/log'
8
-
9
- import type { VxeTablePropTypes, VxeTableDefines, TableReactData, VxeTablePrivateMethods, TableInternalData, VxeColumnPropTypes, VxeTableConstructor } from '../../../../types'
10
-
11
- const { getI18n, renderer } = VxeUI
12
-
13
- let htmlCellElem: any
14
-
15
- const csvBOM = '\ufeff'
16
- const enterSymbol = '\r\n'
17
-
18
- function hasTreeChildren ($xeTable: VxeTableConstructor, row: any) {
19
- const treeOpts = $xeTable.computeTreeOpts
20
- const childrenField = treeOpts.children || treeOpts.childrenField
21
- return row[childrenField] && row[childrenField].length
22
- }
23
-
24
- function getSeq ($xeTable: VxeTableConstructor, cellValue: any, row: any, $rowIndex: number, column: VxeTableDefines.ColumnInfo, $columnIndex: number) {
25
- const seqOpts = $xeTable.computeSeqOpts
26
- const seqMd = seqOpts.seqMethod || (column as any).seqMethod
27
- if (seqMd) {
28
- return seqMd({
29
- $table: $xeTable,
30
- row,
31
- rowIndex: $xeTable.getRowIndex(row),
32
- _rowIndex: $xeTable.getVTRowIndex(row),
33
- $rowIndex,
34
- column,
35
- columnIndex: $xeTable.getColumnIndex(column),
36
- _columnIndex: $xeTable.getVTColumnIndex(column),
37
- $columnIndex
38
- })
39
- }
40
- return cellValue
41
- }
42
-
43
- function defaultFilterExportColumn (column: VxeTableDefines.ColumnInfo) {
44
- return !!column.field || ['seq', 'checkbox', 'radio'].indexOf(column.type || '') === -1
45
- }
46
-
47
- function toTableBorder (border: VxeTablePropTypes.Border | undefined) {
48
- if (border === true) {
49
- return 'full'
50
- }
51
- if (border) {
52
- return border
53
- }
54
- return 'default'
55
- }
56
-
57
- function toBooleanValue (cellValue: any) {
58
- return XEUtils.isBoolean(cellValue) ? (cellValue ? 'TRUE' : 'FALSE') : cellValue
59
- }
60
-
61
- const toStringValue = (cellValue: any) => {
62
- return eqEmptyValue(cellValue) ? '' : `${cellValue}`
63
- }
64
-
65
- function getBodyLabelData ($xeTable: VxeTableConstructor, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
66
- const props = $xeTable
67
-
68
- const { isAllExpand, mode } = opts
69
- const { treeConfig } = props
70
- const radioOpts = $xeTable.computeRadioOpts
71
- const checkboxOpts = $xeTable.computeCheckboxOpts
72
- const treeOpts = $xeTable.computeTreeOpts
73
- const columnOpts = $xeTable.computeColumnOpts
74
- if (!htmlCellElem) {
75
- htmlCellElem = document.createElement('div')
76
- }
77
- if (treeConfig) {
78
- const childrenField = treeOpts.children || treeOpts.childrenField
79
- // 如果是树表格只允许导出数据源
80
- const rest: any[] = []
81
- const expandMaps: Record<string, boolean> = {}
82
- const useMaps: Record<string, boolean> = {}
83
- const { handleGetRowId } = createHandleGetRowId($xeTable)
84
- XEUtils.eachTree(datas, (item, $rowIndex, items, path, parent, nodes) => {
85
- const row = item._row || item
86
- const rowid = handleGetRowId(row)
87
- if (useMaps[rowid]) {
88
- return
89
- }
90
- const parentRow = parent && parent._row ? parent._row : parent
91
- const pRowid = parentRow ? handleGetRowId(parentRow) : ''
92
- if ((isAllExpand || !parentRow || (expandMaps[pRowid] && $xeTable.isTreeExpandByRow(parentRow)))) {
93
- const hasRowChild = hasTreeChildren($xeTable, row)
94
- const item: any = {
95
- _row: row,
96
- _level: nodes.length - 1,
97
- _hasChild: hasRowChild,
98
- _expand: hasRowChild && $xeTable.isTreeExpandByRow(row)
99
- }
100
- columns.forEach((column, $columnIndex) => {
101
- let cellValue: string | number | boolean | null = ''
102
- const renderOpts = column.editRender || column.cellRender
103
- let bodyExportMethod: VxeColumnPropTypes.ExportMethod | undefined = column.exportMethod || columnOpts.exportMethod
104
- if (!bodyExportMethod && renderOpts && renderOpts.name) {
105
- const compConf = renderer.get(renderOpts.name)
106
- if (compConf) {
107
- bodyExportMethod = compConf.tableExportMethod || compConf.exportMethod
108
- }
109
- }
110
- if (!bodyExportMethod) {
111
- bodyExportMethod = columnOpts.exportMethod
112
- }
113
- if (bodyExportMethod) {
114
- cellValue = bodyExportMethod({ $table: $xeTable, row, column, options: opts })
115
- } else {
116
- switch (column.type) {
117
- case 'seq': {
118
- const seqVal = path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('')
119
- cellValue = mode === 'all' ? seqVal : getSeq($xeTable, seqVal, row, $rowIndex, column, $columnIndex)
120
- break
121
- }
122
- case 'checkbox':
123
- cellValue = toBooleanValue($xeTable.isCheckedByCheckboxRow(row))
124
- item._checkboxLabel = checkboxOpts.labelField ? XEUtils.get(row, checkboxOpts.labelField) : ''
125
- item._checkboxDisabled = checkboxOpts.checkMethod && !checkboxOpts.checkMethod({ $table: $xeTable, row })
126
- break
127
- case 'radio':
128
- cellValue = toBooleanValue($xeTable.isCheckedByRadioRow(row))
129
- item._radioLabel = radioOpts.labelField ? XEUtils.get(row, radioOpts.labelField) : ''
130
- item._radioDisabled = radioOpts.checkMethod && !radioOpts.checkMethod({ $table: $xeTable, row })
131
- break
132
- default:
133
- if (opts.original) {
134
- cellValue = getCellValue(row, column)
135
- } else {
136
- cellValue = $xeTable.getCellLabel(row, column)
137
- if (column.type === 'html') {
138
- htmlCellElem.innerHTML = cellValue
139
- cellValue = htmlCellElem.innerText.trim()
140
- } else {
141
- const cell = $xeTable.getCellElement(row, column)
142
- if (cell && !hasClass(cell, 'is--progress')) {
143
- cellValue = cell.innerText.trim()
144
- }
145
- }
146
- }
147
- }
148
- }
149
- item[column.id] = toStringValue(cellValue)
150
- })
151
- useMaps[rowid] = true
152
- if (pRowid) {
153
- expandMaps[pRowid] = true
154
- }
155
- rest.push(Object.assign(item, row))
156
- }
157
- }, { children: childrenField })
158
- return rest
159
- }
160
- return datas.map((row, $rowIndex) => {
161
- const item: any = {
162
- _row: row
163
- }
164
- columns.forEach((column, $columnIndex) => {
165
- let cellValue: string | number | boolean | null = ''
166
- const renderOpts = column.editRender || column.cellRender
167
- let bodyExportMethod: VxeColumnPropTypes.ExportMethod | undefined = column.exportMethod || columnOpts.exportMethod
168
- if (!bodyExportMethod && renderOpts && renderOpts.name) {
169
- const compConf = renderer.get(renderOpts.name)
170
- if (compConf) {
171
- bodyExportMethod = compConf.tableExportMethod || compConf.exportMethod
172
- }
173
- }
174
- if (bodyExportMethod) {
175
- cellValue = bodyExportMethod({ $table: $xeTable, row, column, options: opts })
176
- } else {
177
- switch (column.type) {
178
- case 'seq': {
179
- const seqValue = $rowIndex + 1
180
- cellValue = mode === 'all' ? seqValue : getSeq($xeTable, seqValue, row, $rowIndex, column, $columnIndex)
181
- break
182
- }
183
- case 'checkbox':
184
- cellValue = toBooleanValue($xeTable.isCheckedByCheckboxRow(row))
185
- item._checkboxLabel = checkboxOpts.labelField ? XEUtils.get(row, checkboxOpts.labelField) : ''
186
- item._checkboxDisabled = checkboxOpts.checkMethod && !checkboxOpts.checkMethod({ $table: $xeTable, row })
187
- break
188
- case 'radio':
189
- cellValue = toBooleanValue($xeTable.isCheckedByRadioRow(row))
190
- item._radioLabel = radioOpts.labelField ? XEUtils.get(row, radioOpts.labelField) : ''
191
- item._radioDisabled = radioOpts.checkMethod && !radioOpts.checkMethod({ $table: $xeTable, row })
192
- break
193
- default:
194
- if (opts.original) {
195
- cellValue = getCellValue(row, column)
196
- } else {
197
- cellValue = $xeTable.getCellLabel(row, column)
198
- if (column.type === 'html') {
199
- htmlCellElem.innerHTML = cellValue
200
- cellValue = htmlCellElem.innerText.trim()
201
- } else {
202
- const cell = $xeTable.getCellElement(row, column)
203
- if (cell && !hasClass(cell, 'is--progress')) {
204
- cellValue = cell.innerText.trim()
205
- }
206
- }
207
- }
208
- }
209
- }
210
- item[column.id] = toStringValue(cellValue)
211
- })
212
- return item
213
- })
214
- }
215
-
216
- function getExportData ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions) {
217
- const $xeGrid = $xeTable.$xeGrid
218
- const $xeGantt = $xeTable.$xeGantt
219
-
220
- const { columns, dataFilterMethod } = opts
221
- let datas = opts.data
222
- if (dataFilterMethod) {
223
- datas = datas.filter((row, index) => dataFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, row, $rowIndex: index }))
224
- }
225
- return getBodyLabelData($xeTable, opts, columns, datas)
226
- }
227
-
228
- function getBooleanValue (cellValue: any) {
229
- return cellValue === 'TRUE' || cellValue === 'true' || cellValue === true
230
- }
231
-
232
- function getHeaderTitle ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, column: VxeTableDefines.ColumnInfo) {
233
- const columnOpts = $xeTable.computeColumnOpts
234
- const headExportMethod = column.headerExportMethod || columnOpts.headerExportMethod
235
- return headExportMethod ? headExportMethod({ column, options: opts, $table: $xeTable }) : ((opts.isTitle ? column.getTitle() : column.field) || '')
236
- }
237
-
238
- function getFooterCellValue ($xeTable: any, opts: VxeTablePropTypes.ExportHandleOptions, row: any, column: VxeTableDefines.ColumnInfo) {
239
- const columnOpts = $xeTable.computeColumnOpts
240
- const renderOpts = column.editRender || column.cellRender
241
- let footLabelMethod: VxeColumnPropTypes.FooterExportMethod | undefined = column.footerExportMethod
242
- if (!footLabelMethod && renderOpts && renderOpts.name) {
243
- const compConf = renderer.get(renderOpts.name)
244
- if (compConf) {
245
- footLabelMethod = compConf.tableFooterExportMethod || compConf.footerExportMethod || (compConf as any).footerCellExportMethod
246
- }
247
- }
248
- if (!footLabelMethod) {
249
- footLabelMethod = columnOpts.footerExportMethod
250
- }
251
- if (footLabelMethod) {
252
- const _columnIndex = $xeTable.getVTColumnIndex(column)
253
- return footLabelMethod({ $table: $xeTable, items: row, itemIndex: _columnIndex, row, _columnIndex, column, options: opts })
254
- }
255
- const cellValue = $xeTable.getFooterCellLabel(row, column)
256
- return cellValue
257
- }
258
-
259
- function getFooterData ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, footerTableData: any[]) {
260
- const $xeGrid = $xeTable.$xeGrid
261
- const $xeGantt = $xeTable.$xeGantt
262
-
263
- const { footerFilterMethod } = opts
264
- return footerFilterMethod ? footerTableData.filter((items: any, index: any) => footerFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, items, $rowIndex: index })) : footerTableData
265
- }
266
-
267
- function getCsvCellTypeLabel (column: any, cellValue: any) {
268
- if (cellValue) {
269
- if (column.type === 'seq') {
270
- return `\t${cellValue}`
271
- }
272
- switch (column.cellType) {
273
- case 'string':
274
- if (!isNaN(cellValue)) {
275
- return `\t${cellValue}`
276
- }
277
- break
278
- case 'number':
279
- break
280
- default:
281
- if (cellValue.length >= 12 && !isNaN(cellValue)) {
282
- return `\t${cellValue}`
283
- }
284
- break
285
- }
286
- }
287
- return cellValue
288
- }
289
-
290
- function toTxtCellLabel (val: any) {
291
- if (/[",\s\n]/.test(val)) {
292
- return `"${val.replace(/"/g, '""')}"`
293
- }
294
- return val
295
- }
296
-
297
- function toCsv ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
298
- const reactData = $xeTable as unknown as TableReactData
299
-
300
- let content = csvBOM
301
- if (opts.isHeader) {
302
- content += columns.map(column => toTxtCellLabel(getHeaderTitle($xeTable, opts, column))).join(',') + enterSymbol
303
- }
304
- datas.forEach(row => {
305
- content += columns.map(column => toTxtCellLabel(getCsvCellTypeLabel(column, row[column.id]))).join(',') + enterSymbol
306
- })
307
- if (opts.isFooter) {
308
- const { footerTableData } = reactData
309
- const footers = getFooterData($xeTable, opts, footerTableData)
310
- footers.forEach((row) => {
311
- content += columns.map(column => toTxtCellLabel(getFooterCellValue($xeTable, opts, row, column))).join(',') + enterSymbol
312
- })
313
- }
314
- return content
315
- }
316
-
317
- function toTxt ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
318
- const reactData = $xeTable as unknown as TableReactData
319
-
320
- let content = ''
321
- if (opts.isHeader) {
322
- content += columns.map(column => toTxtCellLabel(getHeaderTitle($xeTable, opts, column))).join('\t') + enterSymbol
323
- }
324
- datas.forEach(row => {
325
- content += columns.map(column => toTxtCellLabel(row[column.id])).join('\t') + enterSymbol
326
- })
327
- if (opts.isFooter) {
328
- const { footerTableData } = reactData
329
- const footers = getFooterData($xeTable, opts, footerTableData)
330
- footers.forEach((row) => {
331
- content += columns.map(column => toTxtCellLabel(getFooterCellValue($xeTable, opts, row, column))).join('\t') + enterSymbol
332
- })
333
- }
334
- return content
335
- }
336
-
337
- function hasEllipsis ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: VxeTableDefines.ColumnInfo, property: 'showOverflow' | 'showHeaderOverflow', allColumnOverflow: VxeTablePropTypes.ShowOverflow | undefined) {
338
- const reactData = $xeTable as unknown as TableReactData
339
-
340
- const columnOverflow = column[property]
341
- const headOverflow = XEUtils.isUndefined(columnOverflow) || XEUtils.isNull(columnOverflow) ? allColumnOverflow : columnOverflow
342
- const showEllipsis = headOverflow === 'ellipsis'
343
- const showTitle = headOverflow === 'title'
344
- const showTooltip = headOverflow === true || headOverflow === 'tooltip'
345
- let isEllipsis = showTitle || showTooltip || showEllipsis
346
- // 虚拟滚动不支持动态高度
347
- const { scrollXLoad, scrollYLoad } = reactData
348
- if ((scrollXLoad || scrollYLoad) && !isEllipsis) {
349
- isEllipsis = true
350
- }
351
- return isEllipsis
352
- }
353
-
354
- function toHtml ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
355
- const props = $xeTable
356
- const reactData = $xeTable as unknown as TableReactData
357
- const internalData = $xeTable as unknown as TableInternalData
358
-
359
- const { id, border, treeConfig, headerAlign: allHeaderAlign, align: allAlign, footerAlign: allFooterAlign, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow } = props
360
- const { isAllSelected, isIndeterminate } = reactData
361
- const { mergeBodyCellMaps } = internalData
362
- const treeOpts = $xeTable.computeTreeOpts
363
- const { print: isPrint, isHeader, isFooter, isColgroup, isMerge, colgroups, original } = opts
364
- const allCls = 'check-all'
365
- const clss = [
366
- 'vxe-table',
367
- `border--${toTableBorder(border)}`,
368
- isPrint ? 'is--print' : '',
369
- isHeader ? 'is--header' : ''
370
- ].filter(cls => cls)
371
- const tables = [
372
- `<table class="${clss.join(' ')}" border="0" cellspacing="0" cellpadding="0">`,
373
- `<colgroup>${columns.map(column => `<col style="width:${column.renderWidth}px">`).join('')}</colgroup>`
374
- ]
375
- if (isHeader) {
376
- tables.push('<thead>')
377
- if (isColgroup && !original) {
378
- colgroups.forEach((cols: any[]) => {
379
- tables.push(
380
- `<tr>${cols.map(column => {
381
- const headAlign = column.headerAlign || column.align || allHeaderAlign || allAlign
382
- const classNames = hasEllipsis($xeTable, column, 'showHeaderOverflow', allColumnHeaderOverflow) ? ['col--ellipsis'] : []
383
- const cellTitle = getHeaderTitle($xeTable, opts, column)
384
- let childWidth = 0
385
- let countChild = 0
386
- XEUtils.eachTree([column], item => {
387
- if (!item.childNodes || !column.childNodes.length) {
388
- countChild++
389
- }
390
- childWidth += item.renderWidth
391
- }, { children: 'childNodes' })
392
- const cellWidth = childWidth - countChild
393
- if (headAlign) {
394
- classNames.push(`col--${headAlign}`)
395
- }
396
- if (column.type === 'checkbox') {
397
- return `<th class="${classNames.join(' ')}" colspan="${column._colSpan}" rowspan="${column._rowSpan}"><div ${isPrint ? '' : `style="width: ${cellWidth}px"`}><input type="checkbox" class="${allCls}" ${isAllSelected ? 'checked' : ''}><span>${cellTitle}</span></div></th>`
398
- }
399
- return `<th class="${classNames.join(' ')}" colspan="${column._colSpan}" rowspan="${column._rowSpan}" title="${cellTitle}"><div ${isPrint ? '' : `style="width: ${cellWidth}px"`}><span>${formatText(cellTitle, true)}</span></div></th>`
400
- }).join('')}</tr>`
401
- )
402
- })
403
- } else {
404
- tables.push(
405
- `<tr>${columns.map(column => {
406
- const headAlign = column.headerAlign || column.align || allHeaderAlign || allAlign
407
- const classNames = hasEllipsis($xeTable, column, 'showHeaderOverflow', allColumnHeaderOverflow) ? ['col--ellipsis'] : []
408
- const cellTitle = getHeaderTitle($xeTable, opts, column)
409
- if (headAlign) {
410
- classNames.push(`col--${headAlign}`)
411
- }
412
- if (column.type === 'checkbox') {
413
- return `<th class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" class="${allCls}" ${isAllSelected ? 'checked' : ''}><span>${cellTitle}</span></div></th>`
414
- }
415
- return `<th class="${classNames.join(' ')}" title="${cellTitle}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><span>${formatText(cellTitle, true)}</span></div></th>`
416
- }).join('')}</tr>`
417
- )
418
- }
419
- tables.push('</thead>')
420
- }
421
- if (datas.length) {
422
- tables.push('<tbody>')
423
- if (treeConfig) {
424
- datas.forEach(item => {
425
- tables.push(
426
- '<tr>' + columns.map(column => {
427
- const cellAlign = column.align || allAlign
428
- const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
429
- const cellValue = item[column.id]
430
- if (cellAlign) {
431
- classNames.push(`col--${cellAlign}`)
432
- }
433
- if (column.treeNode) {
434
- let treeIcon = ''
435
- if (item._hasChild) {
436
- treeIcon = `<i class="${item._expand ? 'vxe-table--tree-fold-icon' : 'vxe-table--tree-unfold-icon'}"></i>`
437
- }
438
- classNames.push('vxe-table--tree-node')
439
- if (column.type === 'radio') {
440
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><div class="vxe-table--tree-node-wrapper" style="padding-left: ${item._level * treeOpts.indent}px"><div class="vxe-table--tree-icon-wrapper">${treeIcon}</div><div class="vxe-table--tree-cell"><input type="radio" name="radio_${id}" ${item._radioDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._radioLabel}</span></div></div></div></td>`
441
- } else if (column.type === 'checkbox') {
442
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><div class="vxe-table--tree-node-wrapper" style="padding-left: ${item._level * treeOpts.indent}px"><div class="vxe-table--tree-icon-wrapper">${treeIcon}</div><div class="vxe-table--tree-cell"><input type="checkbox" ${item._checkboxDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._checkboxLabel}</span></div></div></div></td>`
443
- }
444
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><div class="vxe-table--tree-node-wrapper" style="padding-left: ${item._level * treeOpts.indent}px"><div class="vxe-table--tree-icon-wrapper">${treeIcon}</div><div class="vxe-table--tree-cell">${cellValue}</div></div></div></td>`
445
- }
446
- if (column.type === 'radio') {
447
- return `<td class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="radio" name="radio_${id}" ${item._radioDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._radioLabel}</span></div></td>`
448
- } else if (column.type === 'checkbox') {
449
- return `<td class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" ${item._checkboxDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._checkboxLabel}</span></div></td>`
450
- }
451
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
452
- }).join('') + '</tr>'
453
- )
454
- })
455
- } else {
456
- datas.forEach(item => {
457
- tables.push(
458
- '<tr>' + columns.map(column => {
459
- const colid = column.id
460
- const cellAlign = column.align || allAlign
461
- const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
462
- const cellValue = item[colid]
463
- let rowSpan = 1
464
- let colSpan = 1
465
- if (isMerge) {
466
- const _rowIndex = $xeTable.getVTRowIndex(item._row)
467
- const _columnIndex = $xeTable.getVTColumnIndex(column)
468
- const spanRest = mergeBodyCellMaps[`${_rowIndex}:${_columnIndex}`]
469
- if (spanRest) {
470
- const { rowspan, colspan } = spanRest
471
- if (!rowspan || !colspan) {
472
- return ''
473
- }
474
- if (rowspan > 1) {
475
- rowSpan = rowspan
476
- }
477
- if (colspan > 1) {
478
- colSpan = colspan
479
- }
480
- }
481
- }
482
- if (cellAlign) {
483
- classNames.push(`col--${cellAlign}`)
484
- }
485
- if (column.type === 'radio') {
486
- return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="radio" name="radio_${id}" ${item._radioDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._radioLabel}</span></div></td>`
487
- } else if (column.type === 'checkbox') {
488
- return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" ${item._checkboxDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._checkboxLabel}</span></div></td>`
489
- }
490
- return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
491
- }).join('') + '</tr>'
492
- )
493
- })
494
- }
495
- tables.push('</tbody>')
496
- }
497
- if (isFooter) {
498
- const { footerTableData } = reactData
499
- const footers = getFooterData($xeTable, opts, footerTableData)
500
- if (footers.length) {
501
- tables.push('<tfoot>')
502
- footers.forEach((row: any) => {
503
- tables.push(
504
- `<tr>${columns.map(column => {
505
- const footAlign = column.footerAlign || column.align || allFooterAlign || allAlign
506
- const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
507
- const cellValue = getFooterCellValue($xeTable, opts, row, column)
508
- if (footAlign) {
509
- classNames.push(`col--${footAlign}`)
510
- }
511
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
512
- }).join('')}</tr>`
513
- )
514
- })
515
- tables.push('</tfoot>')
516
- }
517
- }
518
- // 是否半选状态
519
- const script = !isAllSelected && isIndeterminate ? `<script>(function(){var a=document.querySelector(".${allCls}");if(a){a.indeterminate=true}})()</script>` : ''
520
- tables.push('</table>', script)
521
- return isPrint ? tables.join('') : createHtmlPage(opts, tables.join(''))
522
- }
523
-
524
- function toXML ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: any, columns: any[], datas: any[]) {
525
- const reactData = $xeTable as unknown as TableReactData
526
-
527
- let xml = [
528
- '<?xml version="1.0"?>',
529
- '<?mso-application progid="Excel.Sheet"?>',
530
- '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">',
531
- '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">',
532
- '<Version>16.00</Version>',
533
- '</DocumentProperties>',
534
- '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">',
535
- '<WindowHeight>7920</WindowHeight>',
536
- '<WindowWidth>21570</WindowWidth>',
537
- '<WindowTopX>32767</WindowTopX>',
538
- '<WindowTopY>32767</WindowTopY>',
539
- '<ProtectStructure>False</ProtectStructure>',
540
- '<ProtectWindows>False</ProtectWindows>',
541
- '</ExcelWorkbook>',
542
- `<Worksheet ss:Name="${opts.sheetName}">`,
543
- '<Table>',
544
- columns.map(column => `<Column ss:Width="${column.renderWidth}"/>`).join('')
545
- ].join('')
546
- if (opts.isHeader) {
547
- xml += `<Row>${columns.map(column => `<Cell><Data ss:Type="String">${getHeaderTitle($xeTable, opts, column)}</Data></Cell>`).join('')}</Row>`
548
- }
549
- datas.forEach(row => {
550
- xml += '<Row>' + columns.map(column => `<Cell><Data ss:Type="String">${row[column.id]}</Data></Cell>`).join('') + '</Row>'
551
- })
552
- if (opts.isFooter) {
553
- const { footerTableData } = reactData
554
- const footers = getFooterData($xeTable, opts, footerTableData)
555
- footers.forEach((row: any) => {
556
- xml += `<Row>${columns.map(column => `<Cell><Data ss:Type="String">${getFooterCellValue($xeTable, opts, row, column)}</Data></Cell>`).join('')}</Row>`
557
- })
558
- }
559
- return `${xml}</Table></Worksheet></Workbook>`
560
- }
561
-
562
- function getContent ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
563
- if (columns.length) {
564
- switch (opts.type) {
565
- case 'csv':
566
- return toCsv($xeTable, opts, columns, datas)
567
- case 'txt':
568
- return toTxt($xeTable, opts, columns, datas)
569
- case 'html':
570
- return toHtml($xeTable, opts, columns, datas)
571
- case 'xml':
572
- return toXML($xeTable, opts, columns, datas)
573
- }
574
- }
575
- return ''
576
- }
577
-
578
- function downloadFile ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: any, content: any) {
579
- const { filename, type, download } = opts
580
- if (!download) {
581
- const blob = getExportBlobByContent(content, opts)
582
- return Promise.resolve({ type, content, blob })
583
- }
584
- if (VxeUI.saveFile) {
585
- VxeUI.saveFile({ filename, type, content }).then(() => {
586
- if (opts.message !== false) {
587
- if (VxeUI.modal) {
588
- VxeUI.modal.message({ content: getI18n('vxe.table.expSuccess'), status: 'success' })
589
- }
590
- }
591
- })
592
- }
593
- }
594
-
595
- function clearColumnConvert (columns: any) {
596
- XEUtils.eachTree(columns, column => {
597
- delete column._level
598
- delete column._colSpan
599
- delete column._rowSpan
600
- delete column._children
601
- delete column.childNodes
602
- }, { children: 'children' })
603
- }
604
-
605
- function handleExport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions) {
606
- const $xeGrid = $xeTable.$xeGrid
607
- const $xeGantt = $xeTable.$xeGantt
608
-
609
- const { remote, columns, colgroups, exportMethod, afterExportMethod } = opts
610
- return new Promise(resolve => {
611
- if (remote) {
612
- const params = { options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }
613
- resolve(exportMethod ? exportMethod(params) : params)
614
- } else {
615
- const datas = getExportData($xeTable, opts)
616
- resolve(
617
- $xeTable.preventEvent(null, 'event.export', { options: opts, columns, colgroups, datas }, () => {
618
- return downloadFile($xeTable, opts, getContent($xeTable, opts, columns, datas))
619
- })
620
- )
621
- }
622
- }).then((params) => {
623
- clearColumnConvert(columns)
624
- if (!opts.print) {
625
- if (afterExportMethod) {
626
- afterExportMethod({ status: true, options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
627
- }
628
- }
629
- return Object.assign({ status: true }, params)
630
- }).catch(() => {
631
- clearColumnConvert(columns)
632
- if (!opts.print) {
633
- if (afterExportMethod) {
634
- afterExportMethod({ status: false, options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
635
- }
636
- }
637
- const params = { status: false }
638
- return Promise.reject(params)
639
- })
640
- }
641
-
642
- function getElementsByTagName (elem: any, qualifiedName: any) {
643
- return elem.getElementsByTagName(qualifiedName) as HTMLElement[]
644
- }
645
-
646
- function getTxtCellKey (now: any) {
647
- return `#${now}@${XEUtils.uniqueId()}`
648
- }
649
-
650
- function replaceTxtCell (cell: any, vMaps: any) {
651
- return cell.replace(/#\d+@\d+/g, (key: any) => XEUtils.hasOwnProp(vMaps, key) ? vMaps[key] : key)
652
- }
653
-
654
- function getTxtCellValue (val: any, vMaps: any) {
655
- const rest = replaceTxtCell(val, vMaps)
656
- return rest.replace(/^"+$/g, (qVal: any) => '"'.repeat(Math.ceil(qVal.length / 2)))
657
- }
658
-
659
- function toExportField (tableConf: {
660
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
661
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
662
- }, field: string) {
663
- const { fieldMaps, titleMaps } = tableConf
664
- // title 转 field
665
- if (!fieldMaps[field]) {
666
- const teCol = titleMaps[field]
667
- if (teCol && teCol.field) {
668
- field = teCol.field
669
- }
670
- }
671
- return field
672
- }
673
-
674
- function parseCsvAndTxt (tableConf: {
675
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
676
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
677
- }, content: string, cellSeparator: string) {
678
- const list = content.split(enterSymbol)
679
- const rows: any[] = []
680
- let fields: string[] = []
681
- if (list.length) {
682
- const vMaps: any = {}
683
- const now = Date.now()
684
- list.forEach((rVal) => {
685
- if (rVal) {
686
- const item: any = {}
687
- rVal = rVal.replace(/("")|(\n)/g, (text: string, dVal: string) => {
688
- const key = getTxtCellKey(now)
689
- vMaps[key] = dVal ? '"' : '\n'
690
- return key
691
- }).replace(/"(.*?)"/g, (text: string, cVal: string) => {
692
- const key = getTxtCellKey(now)
693
- vMaps[key] = replaceTxtCell(cVal, vMaps)
694
- return key
695
- })
696
- const cells: string[] = rVal.split(cellSeparator)
697
- if (!fields.length) {
698
- fields = cells.map((val: string) => toExportField(tableConf, getTxtCellValue(val.trim(), vMaps)))
699
- } else {
700
- cells.forEach((val, colIndex) => {
701
- if (colIndex < fields.length) {
702
- item[fields[colIndex]] = getTxtCellValue(val.trim(), vMaps)
703
- }
704
- })
705
- rows.push(item)
706
- }
707
- }
708
- })
709
- }
710
- return { fields, rows }
711
- }
712
-
713
- function parseCsv (tableConf: {
714
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
715
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
716
- }, content: string) {
717
- return parseCsvAndTxt(tableConf, content, ',')
718
- }
719
-
720
- function parseTxt (tableConf: {
721
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
722
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
723
- }, content: string) {
724
- return parseCsvAndTxt(tableConf, content, '\t')
725
- }
726
-
727
- function parseHTML (tableConf: {
728
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
729
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
730
- }, content: string) {
731
- const domParser = new DOMParser()
732
- const xmlDoc = domParser.parseFromString(content, 'text/html')
733
- const bodyNodes = getElementsByTagName(xmlDoc, 'body')
734
- const rows: any[] = []
735
- const fields: string[] = []
736
- if (bodyNodes.length) {
737
- const tableNodes = getElementsByTagName(bodyNodes[0], 'table')
738
- if (tableNodes.length) {
739
- const theadNodes = getElementsByTagName(tableNodes[0], 'thead')
740
- if (theadNodes.length) {
741
- XEUtils.arrayEach(getElementsByTagName(theadNodes[0], 'tr'), rowNode => {
742
- XEUtils.arrayEach(getElementsByTagName(rowNode, 'th'), cellNode => {
743
- fields.push(toExportField(tableConf, cellNode.textContent || ''))
744
- })
745
- })
746
- const tbodyNodes = getElementsByTagName(tableNodes[0], 'tbody')
747
- if (tbodyNodes.length) {
748
- XEUtils.arrayEach(getElementsByTagName(tbodyNodes[0], 'tr'), rowNode => {
749
- const item: any = {}
750
- XEUtils.arrayEach(getElementsByTagName(rowNode, 'td'), (cellNode, colIndex) => {
751
- if (fields[colIndex]) {
752
- item[fields[colIndex]] = cellNode.textContent || ''
753
- }
754
- })
755
- rows.push(item)
756
- })
757
- }
758
- }
759
- }
760
- }
761
- return { fields, rows }
762
- }
763
-
764
- function parseXML (tableConf: {
765
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
766
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
767
- }, content: string) {
768
- const domParser = new DOMParser()
769
- const xmlDoc = domParser.parseFromString(content, 'application/xml')
770
- const sheetNodes = getElementsByTagName(xmlDoc, 'Worksheet')
771
- const rows: any[] = []
772
- const fields: string[] = []
773
- if (sheetNodes.length) {
774
- const tableNodes = getElementsByTagName(sheetNodes[0], 'Table')
775
- if (tableNodes.length) {
776
- const rowNodes = getElementsByTagName(tableNodes[0], 'Row')
777
- if (rowNodes.length) {
778
- XEUtils.arrayEach(getElementsByTagName(rowNodes[0], 'Cell'), cellNode => {
779
- fields.push(toExportField(tableConf, cellNode.textContent || ''))
780
- })
781
- XEUtils.arrayEach(rowNodes, (rowNode, index) => {
782
- if (index) {
783
- const item: any = {}
784
- const cellNodes = getElementsByTagName(rowNode, 'Cell')
785
- XEUtils.arrayEach(cellNodes, (cellNode, colIndex) => {
786
- if (fields[colIndex]) {
787
- item[fields[colIndex]] = cellNode.textContent
788
- }
789
- })
790
- rows.push(item)
791
- }
792
- })
793
- }
794
- }
795
- }
796
- return { fields, rows }
797
- }
798
-
799
- function handleImport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, content: any, opts: any) {
800
- const internalData = $xeTable as unknown as TableInternalData
801
-
802
- const { tableFullColumn, _importResolve, _importReject } = internalData
803
- let rest: {
804
- fields: string[];
805
- rows: any[];
806
- } = { fields: [], rows: [] }
807
- const tableFieldMaps: Record<string, VxeTableDefines.ColumnInfo> = {}
808
- const tableTitleMaps: Record<string, VxeTableDefines.ColumnInfo> = {}
809
- tableFullColumn.forEach((column) => {
810
- const field = column.field
811
- const title = column.getTitle()
812
- if (field) {
813
- tableFieldMaps[field] = column
814
- }
815
- if (title) {
816
- tableTitleMaps[column.getTitle()] = column
817
- }
818
- })
819
- const tableConf = {
820
- fieldMaps: tableFieldMaps,
821
- titleMaps: tableTitleMaps
822
- }
823
- switch (opts.type) {
824
- case 'csv':
825
- rest = parseCsv(tableConf, content)
826
- break
827
- case 'txt':
828
- rest = parseTxt(tableConf, content)
829
- break
830
- case 'html':
831
- rest = parseHTML(tableConf, content)
832
- break
833
- case 'xml':
834
- rest = parseXML(tableConf, content)
835
- break
836
- }
837
- const { fields, rows } = rest
838
- const status = fields.some(field => tableFieldMaps[field] || tableTitleMaps[field])
839
- if (status) {
840
- $xeTable.createData(rows)
841
- .then((data: any) => {
842
- let loadRest
843
- if (opts.mode === 'insert' || opts.mode === 'insertBottom') {
844
- loadRest = $xeTable.insertAt(data, -1)
845
- } else if (opts.mode === 'insertTop') {
846
- loadRest = $xeTable.insert(data)
847
- } else {
848
- loadRest = $xeTable.reloadData(data)
849
- }
850
- if (opts.message !== false) {
851
- // 检测弹窗模块
852
- if (!VxeUI.modal) {
853
- errLog('vxe.error.reqModule', ['Modal'])
854
- }
855
- VxeUI.modal.message({ content: getI18n('vxe.table.impSuccess', [rows.length]), status: 'success' })
856
- }
857
- return loadRest.then(() => {
858
- if (_importResolve) {
859
- _importResolve({ status: true })
860
- }
861
- })
862
- })
863
- } else if (opts.message !== false) {
864
- // 检测弹窗模块
865
- if (!VxeUI.modal) {
866
- errLog('vxe.error.reqModule', ['Modal'])
867
- }
868
- VxeUI.modal.message({ content: getI18n('vxe.error.impFields'), status: 'error' })
869
- if (_importReject) {
870
- _importReject({ status: false })
871
- }
872
- }
873
- }
874
-
875
- function handleFileImport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, file: any, opts: any) {
876
- const internalData = $xeTable as unknown as TableInternalData
877
-
878
- const importOpts = $xeTable.computeImportOpts
879
- const { importMethod, afterImportMethod } = opts
880
- const { type, filename } = parseFile(file)
881
-
882
- // 检查类型,如果为自定义导出,则不需要校验类型
883
- if (!importMethod && !XEUtils.includes(XEUtils.keys(importOpts._typeMaps), type)) {
884
- if (opts.message !== false) {
885
- // 检测弹窗模块
886
- if (!VxeUI.modal) {
887
- errLog('vxe.error.reqModule', ['Modal'])
888
- }
889
- VxeUI.modal.message({ content: getI18n('vxe.error.notType', [type]), status: 'error' })
890
- }
891
- const params = { status: false }
892
- return Promise.reject(params)
893
- }
894
-
895
- const rest = new Promise((resolve, reject) => {
896
- const _importResolve = (params: any) => {
897
- resolve(params)
898
- ;($xeTable as any)._importResolve = null
899
- ;($xeTable as any)._importReject = null
900
- }
901
- const _importReject = (params: any) => {
902
- reject(params)
903
- ;($xeTable as any)._importResolve = null
904
- ;($xeTable as any)._importReject = null
905
- }
906
- ;($xeTable as any)._importResolve = _importResolve
907
- ;($xeTable as any)._importReject = _importReject
908
- if (window.FileReader) {
909
- const options = Object.assign({ mode: 'insertTop' }, opts, { type, filename })
910
- if (options.remote) {
911
- if (importMethod) {
912
- Promise.resolve(importMethod({ file, options, $table: $xeTable })).then(() => {
913
- _importResolve({ status: true })
914
- }).catch(() => {
915
- _importResolve({ status: true })
916
- })
917
- } else {
918
- _importResolve({ status: true })
919
- }
920
- } else {
921
- const { tableFullColumn } = internalData
922
- $xeTable.preventEvent(null, 'event.import', { file, options, columns: tableFullColumn }, () => {
923
- const reader = new FileReader()
924
- reader.onerror = () => {
925
- errLog('vxe.error.notType', [type])
926
- _importReject({ status: false })
927
- }
928
- reader.onload = (e: any) => {
929
- handleImport($xeTable, e.target.result, options)
930
- }
931
- reader.readAsText(file, options.encoding || 'UTF-8')
932
- })
933
- }
934
- } else {
935
- // 不支持的浏览器
936
- errLog('vxe.error.notExp')
937
- _importResolve({ status: true })
938
- }
939
- })
940
-
941
- return rest.then(() => {
942
- if (afterImportMethod) {
943
- afterImportMethod({ status: true, options: opts, $table: $xeTable })
944
- }
945
- }).catch((e) => {
946
- if (afterImportMethod) {
947
- afterImportMethod({ status: false, options: opts, $table: $xeTable })
948
- }
949
- return Promise.reject(e)
950
- })
951
- }
952
-
953
- function handleCloseExport () {
954
- if (VxeUI.modal) {
955
- return VxeUI.modal.close('VXE_EXPORT_MODAL')
956
- }
957
- return Promise.resolve()
958
- }
959
-
960
- function handleFilterColumns (exportOpts: VxeTablePropTypes.ExportConfig, column: VxeTableDefines.ColumnInfo, columns: VxeTableDefines.ColumnInfo[] | VxeTablePropTypes.ExportOrPrintColumnOption[]) {
961
- return columns.some((item: any) => {
962
- if (isColumnInfo(item)) {
963
- return column.id === (item as any).id
964
- } else if (XEUtils.isString(item)) {
965
- return column.field === item
966
- } else {
967
- const colid = item.id || item.colId
968
- const type = item.type
969
- const field = item.field
970
- if (colid) {
971
- return column.id === colid
972
- } else if (field && type) {
973
- return column.field === field && column.type === type
974
- } else if (field) {
975
- return column.field === field
976
- } else if (type) {
977
- return column.type === type
978
- }
979
- }
980
- return false
981
- })
982
- }
983
-
984
- function handleFilterFields (exportOpts: VxeTablePropTypes.ExportConfig, column: VxeTableDefines.ColumnInfo, includeFields: string[] | undefined, excludeFields: string[] | undefined) {
985
- if (excludeFields) {
986
- if (XEUtils.includes(excludeFields, column.field)) {
987
- return false
988
- }
989
- }
990
- if (includeFields) {
991
- if (XEUtils.includes(includeFields, column.field)) {
992
- return true
993
- }
994
- return false
995
- }
996
- return exportOpts.original ? !!column.field : defaultFilterExportColumn(column)
997
- }
998
-
999
- function handleExportAndPrint ($xeTable: VxeTableConstructor, options: VxeTablePropTypes.ExportOpts | VxeTablePropTypes.ExportConfig, isPrint?: any) {
1000
- const props = $xeTable
1001
- const reactData = $xeTable as unknown as TableReactData
1002
- const internalData = $xeTable as unknown as TableInternalData
1003
- const $xeGrid = $xeTable.$xeGrid
1004
- const $xeGantt = $xeTable.$xeGantt
1005
- const $xeGGWrapper = $xeGrid || $xeGantt
1006
-
1007
- const { treeConfig, showHeader, showFooter } = props
1008
- const { initStore, isGroup, footerTableData, exportStore, exportParams } = reactData
1009
- const { collectColumn, mergeBodyList, mergeFooterList } = internalData
1010
- const exportOpts = $xeTable.computeExportOpts
1011
- const hasTree = treeConfig
1012
- const customOpts = $xeTable.computeCustomOpts
1013
- const selectRecords = $xeTable.getCheckboxRecords()
1014
- const proxyOpts = $xeGGWrapper ? $xeGGWrapper.computeProxyOpts : {}
1015
- const hasFooter = !!footerTableData.length
1016
- const hasMerge = !!(mergeBodyList.length || mergeFooterList.length)
1017
- const defOpts = Object.assign({
1018
- message: true,
1019
- isHeader: showHeader,
1020
- isTitle: showHeader,
1021
- isFooter: showFooter,
1022
- isColgroup: isGroup,
1023
- isMerge: hasMerge,
1024
- useStyle: true,
1025
- current: 'current',
1026
- modes: (proxyOpts.ajax && proxyOpts.ajax.queryAll ? ['all'] : []).concat(['current', 'selected', 'empty'])
1027
- }, options)
1028
- const types = defOpts.types || XEUtils.keys(exportOpts._typeMaps)
1029
- const modes = defOpts.modes || []
1030
- const checkMethod = customOpts.checkMethod
1031
- const exportColumns = collectColumn.slice(0)
1032
- const { columns, excludeFields, includeFields } = defOpts
1033
- // 处理类型
1034
- const typeList = types.map((value) => {
1035
- return {
1036
- value,
1037
- label: getI18n(`vxe.export.types.${value}`)
1038
- }
1039
- })
1040
- const modeList = modes.map((item: any) => {
1041
- if (item && item.value) {
1042
- return {
1043
- value: item.value,
1044
- label: item.label || item.value
1045
- }
1046
- }
1047
- return {
1048
- value: item,
1049
- label: getI18n(`vxe.export.modes.${item}`)
1050
- }
1051
- })
1052
- // 默认选中
1053
- XEUtils.eachTree(exportColumns, (column, index, items, path, parent) => {
1054
- const isColGroup = column.children && column.children.length > 0
1055
- let isChecked = false
1056
- if (columns && columns.length) {
1057
- isChecked = handleFilterColumns(defOpts, column, columns)
1058
- } else if (excludeFields || includeFields) {
1059
- isChecked = handleFilterFields(defOpts, column, includeFields, excludeFields)
1060
- } else {
1061
- isChecked = column.visible && (isColGroup || defaultFilterExportColumn(column))
1062
- }
1063
- column.checked = isChecked
1064
- column.halfChecked = false
1065
- column.disabled = (parent && parent.disabled) || (checkMethod ? !checkMethod({ $table: $xeTable, column }) : false)
1066
- })
1067
- // 更新条件
1068
- Object.assign(exportStore, {
1069
- columns: exportColumns,
1070
- typeList,
1071
- modeList,
1072
- hasFooter,
1073
- hasMerge,
1074
- hasTree,
1075
- isPrint,
1076
- hasColgroup: isGroup,
1077
- visible: true
1078
- })
1079
- // 默认参数
1080
- Object.assign(exportParams, {
1081
- mode: selectRecords.length ? 'selected' : 'current'
1082
- }, defOpts)
1083
- const { filename, sheetName, mode, type } = exportParams
1084
- if (filename) {
1085
- if (XEUtils.isFunction(filename)) {
1086
- exportParams.filename = filename({
1087
- options: defOpts,
1088
- $table: $xeTable,
1089
- $grid: $xeGrid,
1090
- $gantt: $xeGantt
1091
- })
1092
- } else {
1093
- exportParams.filename = `${filename}`
1094
- }
1095
- }
1096
- if (sheetName) {
1097
- if (XEUtils.isFunction(sheetName)) {
1098
- exportParams.sheetName = sheetName({
1099
- options: defOpts,
1100
- $table: $xeTable,
1101
- $grid: $xeGrid,
1102
- $gantt: $xeGantt
1103
- })
1104
- } else {
1105
- exportParams.sheetName = `${sheetName}`
1106
- }
1107
- }
1108
- if (!modeList.some(item => item.value === mode)) {
1109
- exportParams.mode = modeList[0].value
1110
- }
1111
- if (!typeList.some(item => item.value === type)) {
1112
- exportParams.type = typeList[0].value
1113
- }
1114
- initStore.export = true
1115
- return $xeTable.$nextTick()
1116
- }
1117
-
1118
- const getConvertColumns = (columns: any[]) => {
1119
- const result: any[] = []
1120
- columns.forEach((column) => {
1121
- if (column.childNodes && column.childNodes.length) {
1122
- result.push(column)
1123
- result.push(...getConvertColumns(column.childNodes))
1124
- } else {
1125
- result.push(column)
1126
- }
1127
- })
1128
- return result
1129
- }
1130
-
1131
- const convertToRows = (originColumns: any[]) => {
1132
- let maxLevel = 1
1133
- const traverse = (column: any, parent?: any) => {
1134
- if (parent) {
1135
- column._level = parent._level + 1
1136
- if (maxLevel < column._level) {
1137
- maxLevel = column._level
1138
- }
1139
- }
1140
- if (column.childNodes && column.childNodes.length) {
1141
- let colSpan = 0
1142
- column.childNodes.forEach((subColumn: any) => {
1143
- traverse(subColumn, column)
1144
- colSpan += subColumn._colSpan
1145
- })
1146
- column._colSpan = colSpan
1147
- } else {
1148
- column._colSpan = 1
1149
- }
1150
- }
1151
-
1152
- originColumns.forEach((column) => {
1153
- column._level = 1
1154
- traverse(column)
1155
- })
1156
-
1157
- const rows: any[] = []
1158
- for (let i = 0; i < maxLevel; i++) {
1159
- rows.push([])
1160
- }
1161
-
1162
- const allColumns = getConvertColumns(originColumns)
1163
-
1164
- allColumns.forEach((column) => {
1165
- if (column.childNodes && column.childNodes.length) {
1166
- column._rowSpan = 1
1167
- } else {
1168
- column._rowSpan = maxLevel - column._level + 1
1169
- }
1170
- rows[column._level - 1].push(column)
1171
- })
1172
-
1173
- return rows
1174
- }
1175
-
1176
- export default {
1177
- methods: {
1178
- /**
1179
- * 导出文件,支持 csv/html/xml/txt
1180
- * 如果是树表格,则默认是导出所有节点
1181
- * 如果是启用了虚拟滚动,则只能导出数据源,可以配合 dataFilterMethod 函数转换数据
1182
- * @param {Object} options 参数
1183
- */
1184
- _exportData (options?: VxeTablePropTypes.ExportConfig) {
1185
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1186
- const props = $xeTable
1187
- const reactData = $xeTable as unknown as TableReactData
1188
- const internalData = $xeTable as unknown as TableInternalData
1189
- const $xeGrid = $xeTable.$xeGrid
1190
- const $xeGantt = $xeTable.$xeGantt
1191
- const $xeGGWrapper = $xeGrid || $xeGantt
1192
-
1193
- const { treeConfig, showHeader, showFooter } = props
1194
- const { isGroup } = reactData
1195
- const { tableFullColumn, afterFullData, afterTreeFullData, collectColumn, mergeBodyList, mergeFooterList } = internalData
1196
- const exportOpts = $xeTable.computeExportOpts
1197
- const treeOpts = $xeTable.computeTreeOpts
1198
- const proxyOpts = $xeGGWrapper ? $xeGGWrapper.computeProxyOpts : {}
1199
- const hasMerge = !!(mergeBodyList.length || mergeFooterList.length)
1200
- const opts = Object.assign({
1201
- message: true,
1202
- isHeader: showHeader,
1203
- isTitle: showHeader,
1204
- isFooter: showFooter,
1205
- isColgroup: isGroup,
1206
- isMerge: hasMerge,
1207
- useStyle: true,
1208
- current: 'current',
1209
- modes: (proxyOpts.ajax && proxyOpts.ajax.queryAll ? ['all'] : []).concat(['current', 'selected', 'empty']),
1210
- download: true,
1211
- type: 'csv'
1212
- // filename: '',
1213
- // sheetName: '',
1214
- // original: false,
1215
- // isAllExpand: false,
1216
- // data: null,
1217
- // remote: false,
1218
- // dataFilterMethod: null,
1219
- // footerFilterMethod: null,
1220
- // exportMethod: null,
1221
- // columnFilterMethod: null,
1222
- // beforeExportMethod: null,
1223
- // afterExportMethod: null
1224
- }, exportOpts, options)
1225
- let { filename, sheetName, type, mode, columns, original, columnFilterMethod, beforeExportMethod, includeFields, excludeFields } = opts
1226
- let groups: any[] = []
1227
- const selectRecords = $xeTable.getCheckboxRecords()
1228
- if (!mode) {
1229
- mode = selectRecords.length ? 'selected' : 'current'
1230
- }
1231
- let isCustomCol = false
1232
- let customCols = []
1233
- if (columns && columns.length) {
1234
- isCustomCol = true
1235
- customCols = columns
1236
- } else {
1237
- customCols = XEUtils.searchTree(collectColumn, column => {
1238
- const isColGroup = column.children && column.children.length > 0
1239
- let isChecked = false
1240
- if (columns && columns.length) {
1241
- isChecked = handleFilterColumns(opts, column, columns)
1242
- } else if (excludeFields || includeFields) {
1243
- isChecked = handleFilterFields(opts, column, includeFields, excludeFields)
1244
- } else {
1245
- isChecked = column.visible && (isColGroup || defaultFilterExportColumn(column))
1246
- }
1247
- return isChecked
1248
- }, { children: 'children', mapChildren: 'childNodes', original: true })
1249
- }
1250
- const handleOptions: VxeTablePropTypes.ExportHandleOptions = Object.assign({ } as { data: any[], colgroups: any[], columns: any[] }, opts, { filename: '', sheetName: '' })
1251
- // 如果设置源数据,则默认导出设置了字段的列
1252
- if (!isCustomCol && !columnFilterMethod) {
1253
- columnFilterMethod = ({ column }) => {
1254
- if (excludeFields) {
1255
- if (XEUtils.includes(excludeFields, column.field)) {
1256
- return false
1257
- }
1258
- }
1259
- if (includeFields) {
1260
- if (XEUtils.includes(includeFields, column.field)) {
1261
- return true
1262
- }
1263
- return false
1264
- }
1265
- return original ? !!column.field : defaultFilterExportColumn(column)
1266
- }
1267
- handleOptions.columnFilterMethod = columnFilterMethod
1268
- }
1269
- if (customCols) {
1270
- handleOptions._isCustomColumn = true
1271
- groups = XEUtils.searchTree(
1272
- XEUtils.mapTree(customCols, (item) => {
1273
- let targetColumn
1274
- if (item) {
1275
- if (isColumnInfo(item)) {
1276
- targetColumn = item
1277
- } else if (XEUtils.isString(item)) {
1278
- targetColumn = $xeTable.getColumnByField(item)
1279
- } else {
1280
- const colid = item.id || item.colId
1281
- const type = item.type
1282
- const field = item.field
1283
- if (colid) {
1284
- targetColumn = $xeTable.getColumnById(colid)
1285
- } else if (field && type) {
1286
- targetColumn = tableFullColumn.find((column: VxeTableDefines.ColumnInfo) => column.field === field && column.type === type)
1287
- } else if (field) {
1288
- targetColumn = $xeTable.getColumnByField(field)
1289
- } else if (type) {
1290
- targetColumn = tableFullColumn.find((column: VxeTableDefines.ColumnInfo) => column.type === type)
1291
- }
1292
- }
1293
- return targetColumn || {}
1294
- }
1295
- }, {
1296
- children: 'childNodes',
1297
- mapChildren: '_children'
1298
- }),
1299
- (column, index) => isColumnInfo(column) && (!columnFilterMethod || columnFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, column: column as any, $columnIndex: index })),
1300
- {
1301
- children: '_children',
1302
- mapChildren: 'childNodes',
1303
- original: true
1304
- }
1305
- )
1306
- } else {
1307
- groups = XEUtils.searchTree(isGroup ? collectColumn : tableFullColumn, (column, index) => column.visible && (!columnFilterMethod || columnFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, column, $columnIndex: index })), { children: 'children', mapChildren: 'childNodes', original: true })
1308
- }
1309
- // 获取所有列
1310
- const cols: VxeTableDefines.ColumnInfo[] = []
1311
- XEUtils.eachTree(groups, column => {
1312
- const isColGroup = column.children && column.children.length
1313
- if (!isColGroup) {
1314
- cols.push(column)
1315
- }
1316
- }, { children: 'childNodes' })
1317
- // 构建分组层级
1318
- handleOptions.columns = cols
1319
- handleOptions.colgroups = convertToRows(groups)
1320
- if (filename) {
1321
- if (XEUtils.isFunction(filename)) {
1322
- handleOptions.filename = filename({
1323
- options: opts,
1324
- $table: $xeTable,
1325
- $grid: $xeGrid,
1326
- $gantt: $xeGantt
1327
- })
1328
- } else {
1329
- handleOptions.filename = `${filename}`
1330
- }
1331
- }
1332
- if (!handleOptions.filename) {
1333
- handleOptions.filename = getI18n(handleOptions.original ? 'vxe.table.expOriginFilename' : 'vxe.table.expFilename', [XEUtils.toDateString(Date.now(), 'yyyyMMddHHmmss')])
1334
- }
1335
-
1336
- if (sheetName) {
1337
- if (XEUtils.isFunction(sheetName)) {
1338
- handleOptions.sheetName = sheetName({
1339
- options: opts,
1340
- $table: $xeTable,
1341
- $grid: $xeGrid,
1342
- $gantt: $xeGantt
1343
- })
1344
- } else {
1345
- handleOptions.sheetName = `${sheetName}`
1346
- }
1347
- }
1348
- if (!handleOptions.sheetName) {
1349
- handleOptions.sheetName = document.title || ''
1350
- }
1351
-
1352
- // 检查类型,如果为自定义导出,则不需要校验类型
1353
- if (!handleOptions.exportMethod && !XEUtils.includes(XEUtils.keys(exportOpts._typeMaps), type)) {
1354
- errLog('vxe.error.notType', [type])
1355
- if (['xlsx', 'pdf'].includes(type)) {
1356
- warnLog('vxe.error.reqPlugin', [4, 'plugin-export-xlsx'])
1357
- }
1358
- const params = { status: false }
1359
- return Promise.reject(params)
1360
- }
1361
-
1362
- if (!handleOptions.print) {
1363
- if (beforeExportMethod) {
1364
- beforeExportMethod({ options: handleOptions, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
1365
- }
1366
- }
1367
-
1368
- if (!handleOptions.data) {
1369
- handleOptions.data = []
1370
- if (mode === 'selected') {
1371
- if (['html', 'pdf'].indexOf(type) > -1 && treeConfig) {
1372
- handleOptions.data = XEUtils.searchTree($xeTable.getTableData().fullData, item => $xeTable.findRowIndexOf(selectRecords, item) > -1, Object.assign({}, treeOpts, { data: '_row' }))
1373
- } else {
1374
- handleOptions.data = selectRecords
1375
- }
1376
- } else if (mode === 'all') {
1377
- if (!$xeGGWrapper) {
1378
- errLog('vxe.error.errProp', ['all', 'mode=current,selected'])
1379
- }
1380
-
1381
- if ($xeGGWrapper && !handleOptions.remote) {
1382
- const gridReactData = $xeGGWrapper.reactData
1383
- const proxyOpts = $xeGGWrapper.computeProxyOpts
1384
- const { sortData } = gridReactData
1385
- const { beforeQueryAll, afterQueryAll, ajax = {} } = proxyOpts
1386
- const resConfigs = proxyOpts.response || proxyOpts.props || {}
1387
- const ajaxMethods = ajax.queryAll
1388
- const queryAllSuccessMethods = ajax.queryAllSuccess
1389
- const queryAllErrorMethods = ajax.queryAllError
1390
-
1391
- if (!ajaxMethods) {
1392
- errLog('vxe.error.notFunc', ['proxy-config.ajax.queryAll'])
1393
- }
1394
-
1395
- if (ajaxMethods) {
1396
- const params = {
1397
- $table: $xeTable,
1398
- $grid: $xeGrid,
1399
- $gantt: $xeGantt,
1400
- sort: sortData.length ? sortData[0] : {} as any,
1401
- sorts: sortData as any[],
1402
- filters: gridReactData.filterData,
1403
- form: gridReactData.formData,
1404
- options: handleOptions
1405
- }
1406
- return Promise.resolve((beforeQueryAll || ajaxMethods)(params))
1407
- .then(rest => {
1408
- const listProp = resConfigs.list
1409
- let tdData: any[] = []
1410
- if (listProp) {
1411
- if (XEUtils.isFunction(listProp)) {
1412
- tdData = listProp({ data: rest, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
1413
- } else {
1414
- tdData = XEUtils.isArray(rest) ? rest : XEUtils.get(rest, listProp)
1415
- }
1416
- } else {
1417
- if (XEUtils.isArray(rest)) {
1418
- tdData = rest
1419
- }
1420
- }
1421
- handleOptions.data = tdData
1422
- if (afterQueryAll) {
1423
- afterQueryAll(params)
1424
- }
1425
- if (queryAllSuccessMethods) {
1426
- queryAllSuccessMethods({ ...params, response: rest })
1427
- }
1428
- return handleExport($xeTable, handleOptions)
1429
- })
1430
- .catch((rest) => {
1431
- if (queryAllErrorMethods) {
1432
- queryAllErrorMethods({ ...params, response: rest })
1433
- }
1434
- })
1435
- }
1436
- }
1437
- } else if (mode === 'current') {
1438
- handleOptions.data = treeConfig ? afterTreeFullData : afterFullData
1439
- }
1440
- } else {
1441
- handleOptions._isCustomData = true
1442
- }
1443
- return handleExport($xeTable, handleOptions)
1444
- },
1445
- _importByFile (file: File, options: VxeTablePropTypes.ImportConfig) {
1446
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1447
-
1448
- const opts = Object.assign({}, options)
1449
- const { beforeImportMethod } = opts
1450
- if (beforeImportMethod) {
1451
- beforeImportMethod({ options: opts, $table: $xeTable })
1452
- }
1453
- return handleFileImport($xeTable, file, opts)
1454
- },
1455
- _importData (options?: VxeTablePropTypes.ImportConfig) {
1456
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1457
-
1458
- const { importOpts } = this
1459
- const opts = Object.assign({
1460
- types: XEUtils.keys(importOpts._typeMaps)
1461
- // beforeImportMethod: null,
1462
- // afterImportMethod: null
1463
- }, importOpts, options)
1464
- const { beforeImportMethod, afterImportMethod } = opts
1465
- if (beforeImportMethod) {
1466
- beforeImportMethod({ options: opts, $table: this })
1467
- }
1468
- return VxeUI.readFile(opts).catch(e => {
1469
- if (afterImportMethod) {
1470
- afterImportMethod({ status: false, options: opts, $table: $xeTable })
1471
- }
1472
- return Promise.reject(e)
1473
- }).then((params) => {
1474
- const { file } = params
1475
- return handleFileImport($xeTable, file, opts)
1476
- })
1477
- },
1478
- _saveFile (options: {
1479
- filename: string
1480
- type: string
1481
- content: string | Blob
1482
- }) {
1483
- return VxeUI.saveFile(options)
1484
- },
1485
- _readFile (options?: {
1486
- multiple?: boolean
1487
- types?: string[]
1488
- message?: boolean
1489
- }) {
1490
- return VxeUI.readFile(options)
1491
- },
1492
- _print (options?: VxeTablePropTypes.PrintConfig) {
1493
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1494
- const $xeGrid = $xeTable.$xeGrid
1495
- const $xeGantt = $xeTable.$xeGantt
1496
-
1497
- const printOpts = $xeTable.computePrintOpts
1498
- const opts = Object.assign({
1499
- original: false
1500
- // beforePrintMethod
1501
- }, printOpts, options, {
1502
- type: 'html',
1503
- download: false,
1504
- remote: false,
1505
- print: true
1506
- })
1507
- const { sheetName } = opts
1508
- let printTitle = ''
1509
-
1510
- if (sheetName) {
1511
- if (XEUtils.isFunction(sheetName)) {
1512
- printTitle = sheetName({
1513
- options: opts,
1514
- $table: $xeTable,
1515
- $grid: $xeGrid,
1516
- $gantt: $xeGantt
1517
- })
1518
- } else {
1519
- printTitle = `${sheetName}`
1520
- }
1521
- }
1522
- if (!printTitle) {
1523
- printTitle = document.title || ''
1524
- }
1525
-
1526
- const beforePrintMethod = opts.beforePrintMethod
1527
- const tableHtml = opts.html || opts.content
1528
- return new Promise((resolve, reject) => {
1529
- if (VxeUI.print) {
1530
- if (tableHtml) {
1531
- resolve(
1532
- VxeUI.print({
1533
- title: printTitle,
1534
- html: tableHtml,
1535
- customStyle: opts.style,
1536
- beforeMethod: beforePrintMethod
1537
- ? ({ html }) => {
1538
- return beforePrintMethod({
1539
- html,
1540
- content: html,
1541
- options: opts,
1542
- $table: $xeTable,
1543
- $grid: $xeGrid,
1544
- $gantt: $xeGantt
1545
- })
1546
- }
1547
- : undefined
1548
- })
1549
- )
1550
- } else {
1551
- resolve(
1552
- $xeTable.exportData(opts).then(({ content }: any) => {
1553
- return VxeUI.print({
1554
- title: printTitle,
1555
- html: content,
1556
- customStyle: opts.style,
1557
- beforeMethod: beforePrintMethod
1558
- ? ({ html }) => {
1559
- return beforePrintMethod({
1560
- html,
1561
- content: html,
1562
- options: opts,
1563
- $table: $xeTable,
1564
- $grid: $xeGrid,
1565
- $gantt: $xeGantt
1566
- })
1567
- }
1568
- : undefined
1569
- })
1570
- })
1571
- )
1572
- }
1573
- } else {
1574
- const e = { status: false }
1575
- reject(e)
1576
- }
1577
- })
1578
- },
1579
- _getPrintHtml (options: VxeTablePropTypes.PrintConfig) {
1580
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1581
-
1582
- const printOpts = $xeTable.computePrintOpts
1583
- const opts = Object.assign({
1584
- original: false
1585
- // beforePrintMethod
1586
- }, printOpts, options, {
1587
- type: 'html',
1588
- download: false,
1589
- remote: false,
1590
- print: true
1591
- })
1592
- return $xeTable.exportData(opts).then(({ content }: any) => {
1593
- return {
1594
- html: content
1595
- }
1596
- })
1597
- },
1598
- _closeImport () {
1599
- if (VxeUI.modal) {
1600
- return VxeUI.modal.close('VXE_IMPORT_MODAL')
1601
- }
1602
- return Promise.resolve()
1603
- },
1604
- _openImport (options?: VxeTablePropTypes.ImportConfig) {
1605
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1606
- const props = $xeTable
1607
- const reactData = $xeTable as unknown as TableReactData
1608
-
1609
- const { treeConfig, importConfig } = props
1610
- const { initStore, importStore, importParams } = reactData
1611
- const importOpts = $xeTable.computeImportOpts
1612
- const defOpts = Object.assign({
1613
- mode: 'insertTop',
1614
- message: true,
1615
- types: XEUtils.keys(importOpts._typeMaps),
1616
- modes: ['insertTop', 'covering']
1617
- }, importOpts, options)
1618
- const types = defOpts.types || []
1619
- const modes = defOpts.modes || []
1620
- const isTree = !!treeConfig
1621
- if (isTree) {
1622
- if (defOpts.message) {
1623
- VxeUI.modal.message({ content: getI18n('vxe.error.treeNotImp'), status: 'error' })
1624
- }
1625
- return
1626
- }
1627
- if (!importConfig) {
1628
- errLog('vxe.error.reqProp', ['import-config'])
1629
- }
1630
- // 处理类型
1631
- const typeList = types.map((value: any) => {
1632
- return {
1633
- value,
1634
- label: getI18n(`vxe.export.types.${value}`)
1635
- }
1636
- })
1637
- const modeList = modes.map((item: any) => {
1638
- if (item && item.value) {
1639
- return {
1640
- value: item.value,
1641
- label: item.label || item.value
1642
- }
1643
- }
1644
- return {
1645
- value: item,
1646
- label: getI18n(`vxe.import.modes.${item}`)
1647
- }
1648
- })
1649
- Object.assign(importStore, {
1650
- file: null,
1651
- type: '',
1652
- filename: '',
1653
- modeList,
1654
- typeList,
1655
- visible: true
1656
- })
1657
- Object.assign(importParams, defOpts)
1658
- if (!modeList.some(item => item.value === importParams.mode)) {
1659
- importParams.mode = modeList[0].value
1660
- }
1661
- initStore.import = true
1662
- },
1663
- _closeExport: handleCloseExport,
1664
- _openExport (options: any) {
1665
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1666
- const props = $xeTable
1667
-
1668
- const exportOpts = $xeTable.computeExportOpts
1669
- const defOpts = Object.assign({
1670
- message: true,
1671
- types: XEUtils.keys(exportOpts._typeMaps)
1672
- }, exportOpts, options)
1673
- if (!props.exportConfig) {
1674
- errLog('vxe.error.reqProp', ['export-config'])
1675
- }
1676
- return handleExportAndPrint($xeTable, defOpts)
1677
- },
1678
- _closePrint: handleCloseExport,
1679
- _openPrint (options: any) {
1680
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1681
- const props = $xeTable
1682
-
1683
- const printOpts = $xeTable.computePrintOpts
1684
- const defOpts = Object.assign({
1685
- message: true
1686
- }, printOpts, options)
1687
- if (!props.printConfig) {
1688
- errLog('vxe.error.reqProp', ['print-config'])
1689
- }
1690
- return handleExportAndPrint($xeTable, defOpts, true)
1691
- }
1692
- } as any
1693
- } as any
1
+ import XEUtils from 'xe-utils'
2
+ import { VxeUI } from '../../../ui'
3
+ import { isColumnInfo, getCellValue, createHandleGetRowId } from '../../src/util'
4
+ import { parseFile, formatText, eqEmptyValue } from '../../../ui/src/utils'
5
+ import { hasClass } from '../../../ui/src/dom'
6
+ import { createHtmlPage, getExportBlobByContent } from './util'
7
+ import { warnLog, errLog } from '../../../ui/src/log'
8
+
9
+ import type { VxeTablePropTypes, VxeTableDefines, TableReactData, VxeTablePrivateMethods, TableInternalData, VxeColumnPropTypes, VxeTableConstructor } from '../../../../types'
10
+
11
+ const { getI18n, renderer } = VxeUI
12
+
13
+ let htmlCellElem: any
14
+
15
+ const csvBOM = '\ufeff'
16
+ const enterSymbol = '\r\n'
17
+
18
+ function hasTreeChildren ($xeTable: VxeTableConstructor, row: any) {
19
+ const treeOpts = $xeTable.computeTreeOpts
20
+ const childrenField = treeOpts.children || treeOpts.childrenField
21
+ return row[childrenField] && row[childrenField].length
22
+ }
23
+
24
+ function getSeq ($xeTable: VxeTableConstructor, cellValue: any, row: any, $rowIndex: number, column: VxeTableDefines.ColumnInfo, $columnIndex: number) {
25
+ const seqOpts = $xeTable.computeSeqOpts
26
+ const seqMd = seqOpts.seqMethod || (column as any).seqMethod
27
+ if (seqMd) {
28
+ return seqMd({
29
+ $table: $xeTable,
30
+ row,
31
+ rowIndex: $xeTable.getRowIndex(row),
32
+ _rowIndex: $xeTable.getVTRowIndex(row),
33
+ $rowIndex,
34
+ column,
35
+ columnIndex: $xeTable.getColumnIndex(column),
36
+ _columnIndex: $xeTable.getVTColumnIndex(column),
37
+ $columnIndex
38
+ })
39
+ }
40
+ return cellValue
41
+ }
42
+
43
+ function defaultFilterExportColumn (column: VxeTableDefines.ColumnInfo) {
44
+ return !!column.field || ['seq', 'checkbox', 'radio'].indexOf(column.type || '') === -1
45
+ }
46
+
47
+ function toTableBorder (border: VxeTablePropTypes.Border | undefined) {
48
+ if (border === true) {
49
+ return 'full'
50
+ }
51
+ if (border) {
52
+ return border
53
+ }
54
+ return 'default'
55
+ }
56
+
57
+ function toBooleanValue (cellValue: any) {
58
+ return XEUtils.isBoolean(cellValue) ? (cellValue ? 'TRUE' : 'FALSE') : cellValue
59
+ }
60
+
61
+ const toStringValue = (cellValue: any) => {
62
+ return eqEmptyValue(cellValue) ? '' : `${cellValue}`
63
+ }
64
+
65
+ function getBodyLabelData ($xeTable: VxeTableConstructor, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
66
+ const props = $xeTable
67
+
68
+ const { isAllExpand, mode } = opts
69
+ const { treeConfig } = props
70
+ const radioOpts = $xeTable.computeRadioOpts
71
+ const checkboxOpts = $xeTable.computeCheckboxOpts
72
+ const treeOpts = $xeTable.computeTreeOpts
73
+ const columnOpts = $xeTable.computeColumnOpts
74
+ if (!htmlCellElem) {
75
+ htmlCellElem = document.createElement('div')
76
+ }
77
+ if (treeConfig) {
78
+ const childrenField = treeOpts.children || treeOpts.childrenField
79
+ // 如果是树表格只允许导出数据源
80
+ const rest: any[] = []
81
+ const expandMaps: Record<string, boolean> = {}
82
+ const useMaps: Record<string, boolean> = {}
83
+ const { handleGetRowId } = createHandleGetRowId($xeTable)
84
+ XEUtils.eachTree(datas, (item, $rowIndex, items, path, parent, nodes) => {
85
+ const row = item._row || item
86
+ const rowid = handleGetRowId(row)
87
+ if (useMaps[rowid]) {
88
+ return
89
+ }
90
+ const parentRow = parent && parent._row ? parent._row : parent
91
+ const pRowid = parentRow ? handleGetRowId(parentRow) : ''
92
+ if ((isAllExpand || !parentRow || (expandMaps[pRowid] && $xeTable.isTreeExpandByRow(parentRow)))) {
93
+ const hasRowChild = hasTreeChildren($xeTable, row)
94
+ const item: any = {
95
+ _row: row,
96
+ _level: nodes.length - 1,
97
+ _hasChild: hasRowChild,
98
+ _expand: hasRowChild && $xeTable.isTreeExpandByRow(row)
99
+ }
100
+ columns.forEach((column, $columnIndex) => {
101
+ let cellValue: string | number | boolean | null = ''
102
+ const renderOpts = column.editRender || column.cellRender
103
+ let bodyExportMethod: VxeColumnPropTypes.ExportMethod | undefined = column.exportMethod || columnOpts.exportMethod
104
+ if (!bodyExportMethod && renderOpts && renderOpts.name) {
105
+ const compConf = renderer.get(renderOpts.name)
106
+ if (compConf) {
107
+ bodyExportMethod = compConf.tableExportMethod || compConf.exportMethod
108
+ }
109
+ }
110
+ if (!bodyExportMethod) {
111
+ bodyExportMethod = columnOpts.exportMethod
112
+ }
113
+ if (bodyExportMethod) {
114
+ cellValue = bodyExportMethod({ $table: $xeTable, row, column, options: opts })
115
+ } else {
116
+ switch (column.type) {
117
+ case 'seq': {
118
+ const seqVal = path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('')
119
+ cellValue = mode === 'all' ? seqVal : getSeq($xeTable, seqVal, row, $rowIndex, column, $columnIndex)
120
+ break
121
+ }
122
+ case 'checkbox':
123
+ cellValue = toBooleanValue($xeTable.isCheckedByCheckboxRow(row))
124
+ item._checkboxLabel = checkboxOpts.labelField ? XEUtils.get(row, checkboxOpts.labelField) : ''
125
+ item._checkboxDisabled = checkboxOpts.checkMethod && !checkboxOpts.checkMethod({ $table: $xeTable, row })
126
+ break
127
+ case 'radio':
128
+ cellValue = toBooleanValue($xeTable.isCheckedByRadioRow(row))
129
+ item._radioLabel = radioOpts.labelField ? XEUtils.get(row, radioOpts.labelField) : ''
130
+ item._radioDisabled = radioOpts.checkMethod && !radioOpts.checkMethod({ $table: $xeTable, row })
131
+ break
132
+ default:
133
+ if (opts.original) {
134
+ cellValue = getCellValue(row, column)
135
+ } else {
136
+ cellValue = $xeTable.getCellLabel(row, column)
137
+ if (column.type === 'html') {
138
+ htmlCellElem.innerHTML = cellValue
139
+ cellValue = htmlCellElem.innerText.trim()
140
+ } else {
141
+ const cell = $xeTable.getCellElement(row, column)
142
+ if (cell && !hasClass(cell, 'is--progress')) {
143
+ cellValue = cell.innerText.trim()
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }
149
+ item[column.id] = toStringValue(cellValue)
150
+ })
151
+ useMaps[rowid] = true
152
+ if (pRowid) {
153
+ expandMaps[pRowid] = true
154
+ }
155
+ rest.push(Object.assign(item, row))
156
+ }
157
+ }, { children: childrenField })
158
+ return rest
159
+ }
160
+ return datas.map((row, $rowIndex) => {
161
+ const item: any = {
162
+ _row: row
163
+ }
164
+ columns.forEach((column, $columnIndex) => {
165
+ let cellValue: string | number | boolean | null = ''
166
+ const renderOpts = column.editRender || column.cellRender
167
+ let bodyExportMethod: VxeColumnPropTypes.ExportMethod | undefined = column.exportMethod || columnOpts.exportMethod
168
+ if (!bodyExportMethod && renderOpts && renderOpts.name) {
169
+ const compConf = renderer.get(renderOpts.name)
170
+ if (compConf) {
171
+ bodyExportMethod = compConf.tableExportMethod || compConf.exportMethod
172
+ }
173
+ }
174
+ if (bodyExportMethod) {
175
+ cellValue = bodyExportMethod({ $table: $xeTable, row, column, options: opts })
176
+ } else {
177
+ switch (column.type) {
178
+ case 'seq': {
179
+ const seqValue = $rowIndex + 1
180
+ cellValue = mode === 'all' ? seqValue : getSeq($xeTable, seqValue, row, $rowIndex, column, $columnIndex)
181
+ break
182
+ }
183
+ case 'checkbox':
184
+ cellValue = toBooleanValue($xeTable.isCheckedByCheckboxRow(row))
185
+ item._checkboxLabel = checkboxOpts.labelField ? XEUtils.get(row, checkboxOpts.labelField) : ''
186
+ item._checkboxDisabled = checkboxOpts.checkMethod && !checkboxOpts.checkMethod({ $table: $xeTable, row })
187
+ break
188
+ case 'radio':
189
+ cellValue = toBooleanValue($xeTable.isCheckedByRadioRow(row))
190
+ item._radioLabel = radioOpts.labelField ? XEUtils.get(row, radioOpts.labelField) : ''
191
+ item._radioDisabled = radioOpts.checkMethod && !radioOpts.checkMethod({ $table: $xeTable, row })
192
+ break
193
+ default:
194
+ if (opts.original) {
195
+ cellValue = getCellValue(row, column)
196
+ } else {
197
+ cellValue = $xeTable.getCellLabel(row, column)
198
+ if (column.type === 'html') {
199
+ htmlCellElem.innerHTML = cellValue
200
+ cellValue = htmlCellElem.innerText.trim()
201
+ } else {
202
+ const cell = $xeTable.getCellElement(row, column)
203
+ if (cell && !hasClass(cell, 'is--progress')) {
204
+ cellValue = cell.innerText.trim()
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ item[column.id] = toStringValue(cellValue)
211
+ })
212
+ return item
213
+ })
214
+ }
215
+
216
+ function getExportData ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions) {
217
+ const $xeGrid = $xeTable.$xeGrid
218
+ const $xeGantt = $xeTable.$xeGantt
219
+
220
+ const { columns, dataFilterMethod } = opts
221
+ let datas = opts.data
222
+ if (dataFilterMethod) {
223
+ datas = datas.filter((row, index) => dataFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, row, $rowIndex: index }))
224
+ }
225
+ return getBodyLabelData($xeTable, opts, columns, datas)
226
+ }
227
+
228
+ function getBooleanValue (cellValue: any) {
229
+ return cellValue === 'TRUE' || cellValue === 'true' || cellValue === true
230
+ }
231
+
232
+ function getHeaderTitle ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, column: VxeTableDefines.ColumnInfo) {
233
+ const columnOpts = $xeTable.computeColumnOpts
234
+ const headExportMethod = column.headerExportMethod || columnOpts.headerExportMethod
235
+ return headExportMethod ? headExportMethod({ column, options: opts, $table: $xeTable }) : ((opts.isTitle ? column.getTitle() : column.field) || '')
236
+ }
237
+
238
+ function getFooterCellValue ($xeTable: any, opts: VxeTablePropTypes.ExportHandleOptions, row: any, column: VxeTableDefines.ColumnInfo) {
239
+ const columnOpts = $xeTable.computeColumnOpts
240
+ const renderOpts = column.editRender || column.cellRender
241
+ let footLabelMethod: VxeColumnPropTypes.FooterExportMethod | undefined = column.footerExportMethod
242
+ if (!footLabelMethod && renderOpts && renderOpts.name) {
243
+ const compConf = renderer.get(renderOpts.name)
244
+ if (compConf) {
245
+ footLabelMethod = compConf.tableFooterExportMethod || compConf.footerExportMethod || (compConf as any).footerCellExportMethod
246
+ }
247
+ }
248
+ if (!footLabelMethod) {
249
+ footLabelMethod = columnOpts.footerExportMethod
250
+ }
251
+ if (footLabelMethod) {
252
+ const _columnIndex = $xeTable.getVTColumnIndex(column)
253
+ return footLabelMethod({ $table: $xeTable, items: row, itemIndex: _columnIndex, row, _columnIndex, column, options: opts })
254
+ }
255
+ const cellValue = $xeTable.getFooterCellLabel(row, column)
256
+ return cellValue
257
+ }
258
+
259
+ function getFooterData ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, footerTableData: any[]) {
260
+ const $xeGrid = $xeTable.$xeGrid
261
+ const $xeGantt = $xeTable.$xeGantt
262
+
263
+ const { footerFilterMethod } = opts
264
+ return footerFilterMethod ? footerTableData.filter((items: any, index: any) => footerFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, items, $rowIndex: index })) : footerTableData
265
+ }
266
+
267
+ function getCsvCellTypeLabel (column: any, cellValue: any) {
268
+ if (cellValue) {
269
+ if (column.type === 'seq') {
270
+ return `\t${cellValue}`
271
+ }
272
+ switch (column.cellType) {
273
+ case 'string':
274
+ if (!isNaN(cellValue)) {
275
+ return `\t${cellValue}`
276
+ }
277
+ break
278
+ case 'number':
279
+ break
280
+ default:
281
+ if (cellValue.length >= 12 && !isNaN(cellValue)) {
282
+ return `\t${cellValue}`
283
+ }
284
+ break
285
+ }
286
+ }
287
+ return cellValue
288
+ }
289
+
290
+ function toTxtCellLabel (val: any) {
291
+ if (/[",\s\n]/.test(val)) {
292
+ return `"${val.replace(/"/g, '""')}"`
293
+ }
294
+ return val
295
+ }
296
+
297
+ function toCsv ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
298
+ const reactData = $xeTable as unknown as TableReactData
299
+
300
+ let content = csvBOM
301
+ if (opts.isHeader) {
302
+ content += columns.map(column => toTxtCellLabel(getHeaderTitle($xeTable, opts, column))).join(',') + enterSymbol
303
+ }
304
+ datas.forEach(row => {
305
+ content += columns.map(column => toTxtCellLabel(getCsvCellTypeLabel(column, row[column.id]))).join(',') + enterSymbol
306
+ })
307
+ if (opts.isFooter) {
308
+ const { footerTableData } = reactData
309
+ const footers = getFooterData($xeTable, opts, footerTableData)
310
+ footers.forEach((row) => {
311
+ content += columns.map(column => toTxtCellLabel(getFooterCellValue($xeTable, opts, row, column))).join(',') + enterSymbol
312
+ })
313
+ }
314
+ return content
315
+ }
316
+
317
+ function toTxt ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
318
+ const reactData = $xeTable as unknown as TableReactData
319
+
320
+ let content = ''
321
+ if (opts.isHeader) {
322
+ content += columns.map(column => toTxtCellLabel(getHeaderTitle($xeTable, opts, column))).join('\t') + enterSymbol
323
+ }
324
+ datas.forEach(row => {
325
+ content += columns.map(column => toTxtCellLabel(row[column.id])).join('\t') + enterSymbol
326
+ })
327
+ if (opts.isFooter) {
328
+ const { footerTableData } = reactData
329
+ const footers = getFooterData($xeTable, opts, footerTableData)
330
+ footers.forEach((row) => {
331
+ content += columns.map(column => toTxtCellLabel(getFooterCellValue($xeTable, opts, row, column))).join('\t') + enterSymbol
332
+ })
333
+ }
334
+ return content
335
+ }
336
+
337
+ function hasEllipsis ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: VxeTableDefines.ColumnInfo, property: 'showOverflow' | 'showHeaderOverflow', allColumnOverflow: VxeTablePropTypes.ShowOverflow | undefined) {
338
+ const reactData = $xeTable as unknown as TableReactData
339
+
340
+ const columnOverflow = column[property]
341
+ const headOverflow = XEUtils.isUndefined(columnOverflow) || XEUtils.isNull(columnOverflow) ? allColumnOverflow : columnOverflow
342
+ const showEllipsis = headOverflow === 'ellipsis'
343
+ const showTitle = headOverflow === 'title'
344
+ const showTooltip = headOverflow === true || headOverflow === 'tooltip'
345
+ let isEllipsis = showTitle || showTooltip || showEllipsis
346
+ // 虚拟滚动不支持动态高度
347
+ const { scrollXLoad, scrollYLoad } = reactData
348
+ if ((scrollXLoad || scrollYLoad) && !isEllipsis) {
349
+ isEllipsis = true
350
+ }
351
+ return isEllipsis
352
+ }
353
+
354
+ function toHtml ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
355
+ const props = $xeTable
356
+ const reactData = $xeTable as unknown as TableReactData
357
+ const internalData = $xeTable as unknown as TableInternalData
358
+
359
+ const { id, border, treeConfig, headerAlign: allHeaderAlign, align: allAlign, footerAlign: allFooterAlign, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow } = props
360
+ const { isAllSelected, isIndeterminate } = reactData
361
+ const { mergeBodyCellMaps } = internalData
362
+ const treeOpts = $xeTable.computeTreeOpts
363
+ const { print: isPrint, isHeader, isFooter, isColgroup, isMerge, colgroups, original } = opts
364
+ const allCls = 'check-all'
365
+ const clss = [
366
+ 'vxe-table',
367
+ `border--${toTableBorder(border)}`,
368
+ isPrint ? 'is--print' : '',
369
+ isHeader ? 'is--header' : ''
370
+ ].filter(cls => cls)
371
+ const tables = [
372
+ `<table class="${clss.join(' ')}" border="0" cellspacing="0" cellpadding="0">`,
373
+ `<colgroup>${columns.map(column => `<col style="width:${column.renderWidth}px">`).join('')}</colgroup>`
374
+ ]
375
+ if (isHeader) {
376
+ tables.push('<thead>')
377
+ if (isColgroup && !original) {
378
+ colgroups.forEach((cols: any[]) => {
379
+ tables.push(
380
+ `<tr>${cols.map(column => {
381
+ const headAlign = column.headerAlign || column.align || allHeaderAlign || allAlign
382
+ const classNames = hasEllipsis($xeTable, column, 'showHeaderOverflow', allColumnHeaderOverflow) ? ['col--ellipsis'] : []
383
+ const cellTitle = getHeaderTitle($xeTable, opts, column)
384
+ let childWidth = 0
385
+ let countChild = 0
386
+ XEUtils.eachTree([column], item => {
387
+ if (!item.childNodes || !column.childNodes.length) {
388
+ countChild++
389
+ }
390
+ childWidth += item.renderWidth
391
+ }, { children: 'childNodes' })
392
+ const cellWidth = childWidth - countChild
393
+ if (headAlign) {
394
+ classNames.push(`col--${headAlign}`)
395
+ }
396
+ if (column.type === 'checkbox') {
397
+ return `<th class="${classNames.join(' ')}" colspan="${column._colSpan}" rowspan="${column._rowSpan}"><div ${isPrint ? '' : `style="width: ${cellWidth}px"`}><input type="checkbox" class="${allCls}" ${isAllSelected ? 'checked' : ''}><span>${cellTitle}</span></div></th>`
398
+ }
399
+ return `<th class="${classNames.join(' ')}" colspan="${column._colSpan}" rowspan="${column._rowSpan}" title="${cellTitle}"><div ${isPrint ? '' : `style="width: ${cellWidth}px"`}><span>${formatText(cellTitle, true)}</span></div></th>`
400
+ }).join('')}</tr>`
401
+ )
402
+ })
403
+ } else {
404
+ tables.push(
405
+ `<tr>${columns.map(column => {
406
+ const headAlign = column.headerAlign || column.align || allHeaderAlign || allAlign
407
+ const classNames = hasEllipsis($xeTable, column, 'showHeaderOverflow', allColumnHeaderOverflow) ? ['col--ellipsis'] : []
408
+ const cellTitle = getHeaderTitle($xeTable, opts, column)
409
+ if (headAlign) {
410
+ classNames.push(`col--${headAlign}`)
411
+ }
412
+ if (column.type === 'checkbox') {
413
+ return `<th class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" class="${allCls}" ${isAllSelected ? 'checked' : ''}><span>${cellTitle}</span></div></th>`
414
+ }
415
+ return `<th class="${classNames.join(' ')}" title="${cellTitle}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><span>${formatText(cellTitle, true)}</span></div></th>`
416
+ }).join('')}</tr>`
417
+ )
418
+ }
419
+ tables.push('</thead>')
420
+ }
421
+ if (datas.length) {
422
+ tables.push('<tbody>')
423
+ if (treeConfig) {
424
+ datas.forEach(item => {
425
+ tables.push(
426
+ '<tr>' + columns.map(column => {
427
+ const cellAlign = column.align || allAlign
428
+ const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
429
+ const cellValue = item[column.id]
430
+ if (cellAlign) {
431
+ classNames.push(`col--${cellAlign}`)
432
+ }
433
+ if (column.treeNode) {
434
+ let treeIcon = ''
435
+ if (item._hasChild) {
436
+ treeIcon = `<i class="${item._expand ? 'vxe-table--tree-fold-icon' : 'vxe-table--tree-unfold-icon'}"></i>`
437
+ }
438
+ classNames.push('vxe-table--tree-node')
439
+ if (column.type === 'radio') {
440
+ return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><div class="vxe-table--tree-node-wrapper" style="padding-left: ${item._level * treeOpts.indent}px"><div class="vxe-table--tree-icon-wrapper">${treeIcon}</div><div class="vxe-table--tree-cell"><input type="radio" name="radio_${id}" ${item._radioDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._radioLabel}</span></div></div></div></td>`
441
+ } else if (column.type === 'checkbox') {
442
+ return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><div class="vxe-table--tree-node-wrapper" style="padding-left: ${item._level * treeOpts.indent}px"><div class="vxe-table--tree-icon-wrapper">${treeIcon}</div><div class="vxe-table--tree-cell"><input type="checkbox" ${item._checkboxDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._checkboxLabel}</span></div></div></div></td>`
443
+ }
444
+ return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><div class="vxe-table--tree-node-wrapper" style="padding-left: ${item._level * treeOpts.indent}px"><div class="vxe-table--tree-icon-wrapper">${treeIcon}</div><div class="vxe-table--tree-cell">${cellValue}</div></div></div></td>`
445
+ }
446
+ if (column.type === 'radio') {
447
+ return `<td class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="radio" name="radio_${id}" ${item._radioDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._radioLabel}</span></div></td>`
448
+ } else if (column.type === 'checkbox') {
449
+ return `<td class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" ${item._checkboxDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._checkboxLabel}</span></div></td>`
450
+ }
451
+ return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
452
+ }).join('') + '</tr>'
453
+ )
454
+ })
455
+ } else {
456
+ datas.forEach(item => {
457
+ tables.push(
458
+ '<tr>' + columns.map(column => {
459
+ const colid = column.id
460
+ const cellAlign = column.align || allAlign
461
+ const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
462
+ const cellValue = item[colid]
463
+ let rowSpan = 1
464
+ let colSpan = 1
465
+ if (isMerge) {
466
+ const _rowIndex = $xeTable.getVTRowIndex(item._row)
467
+ const _columnIndex = $xeTable.getVTColumnIndex(column)
468
+ const spanRest = mergeBodyCellMaps[`${_rowIndex}:${_columnIndex}`]
469
+ if (spanRest) {
470
+ const { rowspan, colspan } = spanRest
471
+ if (!rowspan || !colspan) {
472
+ return ''
473
+ }
474
+ if (rowspan > 1) {
475
+ rowSpan = rowspan
476
+ }
477
+ if (colspan > 1) {
478
+ colSpan = colspan
479
+ }
480
+ }
481
+ }
482
+ if (cellAlign) {
483
+ classNames.push(`col--${cellAlign}`)
484
+ }
485
+ if (column.type === 'radio') {
486
+ return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="radio" name="radio_${id}" ${item._radioDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._radioLabel}</span></div></td>`
487
+ } else if (column.type === 'checkbox') {
488
+ return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" ${item._checkboxDisabled ? 'disabled ' : ''}${getBooleanValue(cellValue) ? 'checked' : ''}><span>${item._checkboxLabel}</span></div></td>`
489
+ }
490
+ return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
491
+ }).join('') + '</tr>'
492
+ )
493
+ })
494
+ }
495
+ tables.push('</tbody>')
496
+ }
497
+ if (isFooter) {
498
+ const { footerTableData } = reactData
499
+ const footers = getFooterData($xeTable, opts, footerTableData)
500
+ if (footers.length) {
501
+ tables.push('<tfoot>')
502
+ footers.forEach((row: any) => {
503
+ tables.push(
504
+ `<tr>${columns.map(column => {
505
+ const footAlign = column.footerAlign || column.align || allFooterAlign || allAlign
506
+ const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
507
+ const cellValue = getFooterCellValue($xeTable, opts, row, column)
508
+ if (footAlign) {
509
+ classNames.push(`col--${footAlign}`)
510
+ }
511
+ return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
512
+ }).join('')}</tr>`
513
+ )
514
+ })
515
+ tables.push('</tfoot>')
516
+ }
517
+ }
518
+ // 是否半选状态
519
+ const script = !isAllSelected && isIndeterminate ? `<script>(function(){var a=document.querySelector(".${allCls}");if(a){a.indeterminate=true}})()</script>` : ''
520
+ tables.push('</table>', script)
521
+ return isPrint ? tables.join('') : createHtmlPage(opts, tables.join(''))
522
+ }
523
+
524
+ function toXML ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: any, columns: any[], datas: any[]) {
525
+ const reactData = $xeTable as unknown as TableReactData
526
+
527
+ let xml = [
528
+ '<?xml version="1.0"?>',
529
+ '<?mso-application progid="Excel.Sheet"?>',
530
+ '<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">',
531
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">',
532
+ '<Version>16.00</Version>',
533
+ '</DocumentProperties>',
534
+ '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">',
535
+ '<WindowHeight>7920</WindowHeight>',
536
+ '<WindowWidth>21570</WindowWidth>',
537
+ '<WindowTopX>32767</WindowTopX>',
538
+ '<WindowTopY>32767</WindowTopY>',
539
+ '<ProtectStructure>False</ProtectStructure>',
540
+ '<ProtectWindows>False</ProtectWindows>',
541
+ '</ExcelWorkbook>',
542
+ `<Worksheet ss:Name="${opts.sheetName}">`,
543
+ '<Table>',
544
+ columns.map(column => `<Column ss:Width="${column.renderWidth}"/>`).join('')
545
+ ].join('')
546
+ if (opts.isHeader) {
547
+ xml += `<Row>${columns.map(column => `<Cell><Data ss:Type="String">${getHeaderTitle($xeTable, opts, column)}</Data></Cell>`).join('')}</Row>`
548
+ }
549
+ datas.forEach(row => {
550
+ xml += '<Row>' + columns.map(column => `<Cell><Data ss:Type="String">${row[column.id]}</Data></Cell>`).join('') + '</Row>'
551
+ })
552
+ if (opts.isFooter) {
553
+ const { footerTableData } = reactData
554
+ const footers = getFooterData($xeTable, opts, footerTableData)
555
+ footers.forEach((row: any) => {
556
+ xml += `<Row>${columns.map(column => `<Cell><Data ss:Type="String">${getFooterCellValue($xeTable, opts, row, column)}</Data></Cell>`).join('')}</Row>`
557
+ })
558
+ }
559
+ return `${xml}</Table></Worksheet></Workbook>`
560
+ }
561
+
562
+ function getContent ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
563
+ if (columns.length) {
564
+ switch (opts.type) {
565
+ case 'csv':
566
+ return toCsv($xeTable, opts, columns, datas)
567
+ case 'txt':
568
+ return toTxt($xeTable, opts, columns, datas)
569
+ case 'html':
570
+ return toHtml($xeTable, opts, columns, datas)
571
+ case 'xml':
572
+ return toXML($xeTable, opts, columns, datas)
573
+ }
574
+ }
575
+ return ''
576
+ }
577
+
578
+ function downloadFile ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: any, content: any) {
579
+ const { filename, type, download } = opts
580
+ if (!download) {
581
+ const blob = getExportBlobByContent(content, opts)
582
+ return Promise.resolve({ type, content, blob })
583
+ }
584
+ if (VxeUI.saveFile) {
585
+ VxeUI.saveFile({ filename, type, content }).then(() => {
586
+ if (opts.message !== false) {
587
+ if (VxeUI.modal) {
588
+ VxeUI.modal.message({ content: getI18n('vxe.table.expSuccess'), status: 'success' })
589
+ }
590
+ }
591
+ })
592
+ }
593
+ }
594
+
595
+ function clearColumnConvert (columns: any) {
596
+ XEUtils.eachTree(columns, column => {
597
+ delete column._level
598
+ delete column._colSpan
599
+ delete column._rowSpan
600
+ delete column._children
601
+ delete column.childNodes
602
+ }, { children: 'children' })
603
+ }
604
+
605
+ function handleExport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions) {
606
+ const $xeGrid = $xeTable.$xeGrid
607
+ const $xeGantt = $xeTable.$xeGantt
608
+
609
+ const { remote, columns, colgroups, exportMethod, afterExportMethod } = opts
610
+ return new Promise(resolve => {
611
+ if (remote) {
612
+ const params = { options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }
613
+ resolve(exportMethod ? exportMethod(params) : params)
614
+ } else {
615
+ const datas = getExportData($xeTable, opts)
616
+ resolve(
617
+ $xeTable.preventEvent(null, 'event.export', { options: opts, columns, colgroups, datas }, () => {
618
+ return downloadFile($xeTable, opts, getContent($xeTable, opts, columns, datas))
619
+ })
620
+ )
621
+ }
622
+ }).then((params) => {
623
+ clearColumnConvert(columns)
624
+ if (!opts.print) {
625
+ if (afterExportMethod) {
626
+ afterExportMethod({ status: true, options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
627
+ }
628
+ }
629
+ return Object.assign({ status: true }, params)
630
+ }).catch(() => {
631
+ clearColumnConvert(columns)
632
+ if (!opts.print) {
633
+ if (afterExportMethod) {
634
+ afterExportMethod({ status: false, options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
635
+ }
636
+ }
637
+ const params = { status: false }
638
+ return Promise.reject(params)
639
+ })
640
+ }
641
+
642
+ function getElementsByTagName (elem: any, qualifiedName: any) {
643
+ return elem.getElementsByTagName(qualifiedName) as HTMLElement[]
644
+ }
645
+
646
+ function getTxtCellKey (now: any) {
647
+ return `#${now}@${XEUtils.uniqueId()}`
648
+ }
649
+
650
+ function replaceTxtCell (cell: any, vMaps: any) {
651
+ return cell.replace(/#\d+@\d+/g, (key: any) => XEUtils.hasOwnProp(vMaps, key) ? vMaps[key] : key)
652
+ }
653
+
654
+ function getTxtCellValue (val: any, vMaps: any) {
655
+ const rest = replaceTxtCell(val, vMaps)
656
+ return rest.replace(/^"+$/g, (qVal: any) => '"'.repeat(Math.ceil(qVal.length / 2)))
657
+ }
658
+
659
+ function toExportField (tableConf: {
660
+ fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
661
+ titleMaps: Record<string, VxeTableDefines.ColumnInfo>
662
+ }, field: string) {
663
+ const { fieldMaps, titleMaps } = tableConf
664
+ // title 转 field
665
+ if (!fieldMaps[field]) {
666
+ const teCol = titleMaps[field]
667
+ if (teCol && teCol.field) {
668
+ field = teCol.field
669
+ }
670
+ }
671
+ return field
672
+ }
673
+
674
+ function parseCsvAndTxt (tableConf: {
675
+ fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
676
+ titleMaps: Record<string, VxeTableDefines.ColumnInfo>
677
+ }, content: string, cellSeparator: string) {
678
+ const list = content.split(enterSymbol)
679
+ const rows: any[] = []
680
+ let fields: string[] = []
681
+ if (list.length) {
682
+ const vMaps: any = {}
683
+ const now = Date.now()
684
+ list.forEach((rVal) => {
685
+ if (rVal) {
686
+ const item: any = {}
687
+ rVal = rVal.replace(/("")|(\n)/g, (text: string, dVal: string) => {
688
+ const key = getTxtCellKey(now)
689
+ vMaps[key] = dVal ? '"' : '\n'
690
+ return key
691
+ }).replace(/"(.*?)"/g, (text: string, cVal: string) => {
692
+ const key = getTxtCellKey(now)
693
+ vMaps[key] = replaceTxtCell(cVal, vMaps)
694
+ return key
695
+ })
696
+ const cells: string[] = rVal.split(cellSeparator)
697
+ if (!fields.length) {
698
+ fields = cells.map((val: string) => toExportField(tableConf, getTxtCellValue(val.trim(), vMaps)))
699
+ } else {
700
+ cells.forEach((val, colIndex) => {
701
+ if (colIndex < fields.length) {
702
+ item[fields[colIndex]] = getTxtCellValue(val.trim(), vMaps)
703
+ }
704
+ })
705
+ rows.push(item)
706
+ }
707
+ }
708
+ })
709
+ }
710
+ return { fields, rows }
711
+ }
712
+
713
+ function parseCsv (tableConf: {
714
+ fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
715
+ titleMaps: Record<string, VxeTableDefines.ColumnInfo>
716
+ }, content: string) {
717
+ return parseCsvAndTxt(tableConf, content, ',')
718
+ }
719
+
720
+ function parseTxt (tableConf: {
721
+ fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
722
+ titleMaps: Record<string, VxeTableDefines.ColumnInfo>
723
+ }, content: string) {
724
+ return parseCsvAndTxt(tableConf, content, '\t')
725
+ }
726
+
727
+ function parseHTML (tableConf: {
728
+ fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
729
+ titleMaps: Record<string, VxeTableDefines.ColumnInfo>
730
+ }, content: string) {
731
+ const domParser = new DOMParser()
732
+ const xmlDoc = domParser.parseFromString(content, 'text/html')
733
+ const bodyNodes = getElementsByTagName(xmlDoc, 'body')
734
+ const rows: any[] = []
735
+ const fields: string[] = []
736
+ if (bodyNodes.length) {
737
+ const tableNodes = getElementsByTagName(bodyNodes[0], 'table')
738
+ if (tableNodes.length) {
739
+ const theadNodes = getElementsByTagName(tableNodes[0], 'thead')
740
+ if (theadNodes.length) {
741
+ XEUtils.arrayEach(getElementsByTagName(theadNodes[0], 'tr'), rowNode => {
742
+ XEUtils.arrayEach(getElementsByTagName(rowNode, 'th'), cellNode => {
743
+ fields.push(toExportField(tableConf, cellNode.textContent || ''))
744
+ })
745
+ })
746
+ const tbodyNodes = getElementsByTagName(tableNodes[0], 'tbody')
747
+ if (tbodyNodes.length) {
748
+ XEUtils.arrayEach(getElementsByTagName(tbodyNodes[0], 'tr'), rowNode => {
749
+ const item: any = {}
750
+ XEUtils.arrayEach(getElementsByTagName(rowNode, 'td'), (cellNode, colIndex) => {
751
+ if (fields[colIndex]) {
752
+ item[fields[colIndex]] = cellNode.textContent || ''
753
+ }
754
+ })
755
+ rows.push(item)
756
+ })
757
+ }
758
+ }
759
+ }
760
+ }
761
+ return { fields, rows }
762
+ }
763
+
764
+ function parseXML (tableConf: {
765
+ fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
766
+ titleMaps: Record<string, VxeTableDefines.ColumnInfo>
767
+ }, content: string) {
768
+ const domParser = new DOMParser()
769
+ const xmlDoc = domParser.parseFromString(content, 'application/xml')
770
+ const sheetNodes = getElementsByTagName(xmlDoc, 'Worksheet')
771
+ const rows: any[] = []
772
+ const fields: string[] = []
773
+ if (sheetNodes.length) {
774
+ const tableNodes = getElementsByTagName(sheetNodes[0], 'Table')
775
+ if (tableNodes.length) {
776
+ const rowNodes = getElementsByTagName(tableNodes[0], 'Row')
777
+ if (rowNodes.length) {
778
+ XEUtils.arrayEach(getElementsByTagName(rowNodes[0], 'Cell'), cellNode => {
779
+ fields.push(toExportField(tableConf, cellNode.textContent || ''))
780
+ })
781
+ XEUtils.arrayEach(rowNodes, (rowNode, index) => {
782
+ if (index) {
783
+ const item: any = {}
784
+ const cellNodes = getElementsByTagName(rowNode, 'Cell')
785
+ XEUtils.arrayEach(cellNodes, (cellNode, colIndex) => {
786
+ if (fields[colIndex]) {
787
+ item[fields[colIndex]] = cellNode.textContent
788
+ }
789
+ })
790
+ rows.push(item)
791
+ }
792
+ })
793
+ }
794
+ }
795
+ }
796
+ return { fields, rows }
797
+ }
798
+
799
+ function handleImport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, content: any, opts: any) {
800
+ const internalData = $xeTable as unknown as TableInternalData
801
+
802
+ const { tableFullColumn, _importResolve, _importReject } = internalData
803
+ let rest: {
804
+ fields: string[];
805
+ rows: any[];
806
+ } = { fields: [], rows: [] }
807
+ const tableFieldMaps: Record<string, VxeTableDefines.ColumnInfo> = {}
808
+ const tableTitleMaps: Record<string, VxeTableDefines.ColumnInfo> = {}
809
+ tableFullColumn.forEach((column) => {
810
+ const field = column.field
811
+ const title = column.getTitle()
812
+ if (field) {
813
+ tableFieldMaps[field] = column
814
+ }
815
+ if (title) {
816
+ tableTitleMaps[column.getTitle()] = column
817
+ }
818
+ })
819
+ const tableConf = {
820
+ fieldMaps: tableFieldMaps,
821
+ titleMaps: tableTitleMaps
822
+ }
823
+ switch (opts.type) {
824
+ case 'csv':
825
+ rest = parseCsv(tableConf, content)
826
+ break
827
+ case 'txt':
828
+ rest = parseTxt(tableConf, content)
829
+ break
830
+ case 'html':
831
+ rest = parseHTML(tableConf, content)
832
+ break
833
+ case 'xml':
834
+ rest = parseXML(tableConf, content)
835
+ break
836
+ }
837
+ const { fields, rows } = rest
838
+ const status = fields.some(field => tableFieldMaps[field] || tableTitleMaps[field])
839
+ if (status) {
840
+ $xeTable.createData(rows)
841
+ .then((data: any) => {
842
+ let loadRest
843
+ if (opts.mode === 'insert' || opts.mode === 'insertBottom') {
844
+ loadRest = $xeTable.insertAt(data, -1)
845
+ } else if (opts.mode === 'insertTop') {
846
+ loadRest = $xeTable.insert(data)
847
+ } else {
848
+ loadRest = $xeTable.reloadData(data)
849
+ }
850
+ if (opts.message !== false) {
851
+ // 检测弹窗模块
852
+ if (!VxeUI.modal) {
853
+ errLog('vxe.error.reqModule', ['Modal'])
854
+ }
855
+ VxeUI.modal.message({ content: getI18n('vxe.table.impSuccess', [rows.length]), status: 'success' })
856
+ }
857
+ return loadRest.then(() => {
858
+ if (_importResolve) {
859
+ _importResolve({ status: true })
860
+ }
861
+ })
862
+ })
863
+ } else if (opts.message !== false) {
864
+ // 检测弹窗模块
865
+ if (!VxeUI.modal) {
866
+ errLog('vxe.error.reqModule', ['Modal'])
867
+ }
868
+ VxeUI.modal.message({ content: getI18n('vxe.error.impFields'), status: 'error' })
869
+ if (_importReject) {
870
+ _importReject({ status: false })
871
+ }
872
+ }
873
+ }
874
+
875
+ function handleFileImport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, file: any, opts: any) {
876
+ const internalData = $xeTable as unknown as TableInternalData
877
+
878
+ const importOpts = $xeTable.computeImportOpts
879
+ const { importMethod, afterImportMethod } = opts
880
+ const { type, filename } = parseFile(file)
881
+
882
+ // 检查类型,如果为自定义导出,则不需要校验类型
883
+ if (!importMethod && !XEUtils.includes(XEUtils.keys(importOpts._typeMaps), type)) {
884
+ if (opts.message !== false) {
885
+ // 检测弹窗模块
886
+ if (!VxeUI.modal) {
887
+ errLog('vxe.error.reqModule', ['Modal'])
888
+ }
889
+ VxeUI.modal.message({ content: getI18n('vxe.error.notType', [type]), status: 'error' })
890
+ }
891
+ const params = { status: false }
892
+ return Promise.reject(params)
893
+ }
894
+
895
+ const rest = new Promise((resolve, reject) => {
896
+ const _importResolve = (params: any) => {
897
+ resolve(params)
898
+ ;($xeTable as any)._importResolve = null
899
+ ;($xeTable as any)._importReject = null
900
+ }
901
+ const _importReject = (params: any) => {
902
+ reject(params)
903
+ ;($xeTable as any)._importResolve = null
904
+ ;($xeTable as any)._importReject = null
905
+ }
906
+ ;($xeTable as any)._importResolve = _importResolve
907
+ ;($xeTable as any)._importReject = _importReject
908
+ if (window.FileReader) {
909
+ const options = Object.assign({ mode: 'insertTop' }, opts, { type, filename })
910
+ if (options.remote) {
911
+ if (importMethod) {
912
+ Promise.resolve(importMethod({ file, options, $table: $xeTable })).then(() => {
913
+ _importResolve({ status: true })
914
+ }).catch(() => {
915
+ _importResolve({ status: true })
916
+ })
917
+ } else {
918
+ _importResolve({ status: true })
919
+ }
920
+ } else {
921
+ const { tableFullColumn } = internalData
922
+ $xeTable.preventEvent(null, 'event.import', { file, options, columns: tableFullColumn }, () => {
923
+ const reader = new FileReader()
924
+ reader.onerror = () => {
925
+ errLog('vxe.error.notType', [type])
926
+ _importReject({ status: false })
927
+ }
928
+ reader.onload = (e: any) => {
929
+ handleImport($xeTable, e.target.result, options)
930
+ }
931
+ reader.readAsText(file, options.encoding || 'UTF-8')
932
+ })
933
+ }
934
+ } else {
935
+ // 不支持的浏览器
936
+ errLog('vxe.error.notExp')
937
+ _importResolve({ status: true })
938
+ }
939
+ })
940
+
941
+ return rest.then(() => {
942
+ if (afterImportMethod) {
943
+ afterImportMethod({ status: true, options: opts, $table: $xeTable })
944
+ }
945
+ }).catch((e) => {
946
+ if (afterImportMethod) {
947
+ afterImportMethod({ status: false, options: opts, $table: $xeTable })
948
+ }
949
+ return Promise.reject(e)
950
+ })
951
+ }
952
+
953
+ function handleCloseExport () {
954
+ if (VxeUI.modal) {
955
+ return VxeUI.modal.close('VXE_EXPORT_MODAL')
956
+ }
957
+ return Promise.resolve()
958
+ }
959
+
960
+ function handleFilterColumns (exportOpts: VxeTablePropTypes.ExportConfig, column: VxeTableDefines.ColumnInfo, columns: VxeTableDefines.ColumnInfo[] | VxeTablePropTypes.ExportOrPrintColumnOption[]) {
961
+ return columns.some((item: any) => {
962
+ if (isColumnInfo(item)) {
963
+ return column.id === (item as any).id
964
+ } else if (XEUtils.isString(item)) {
965
+ return column.field === item
966
+ } else {
967
+ const colid = item.id || item.colId
968
+ const type = item.type
969
+ const field = item.field
970
+ if (colid) {
971
+ return column.id === colid
972
+ } else if (field && type) {
973
+ return column.field === field && column.type === type
974
+ } else if (field) {
975
+ return column.field === field
976
+ } else if (type) {
977
+ return column.type === type
978
+ }
979
+ }
980
+ return false
981
+ })
982
+ }
983
+
984
+ function handleFilterFields (exportOpts: VxeTablePropTypes.ExportConfig, column: VxeTableDefines.ColumnInfo, includeFields: string[] | undefined, excludeFields: string[] | undefined) {
985
+ if (excludeFields) {
986
+ if (XEUtils.includes(excludeFields, column.field)) {
987
+ return false
988
+ }
989
+ }
990
+ if (includeFields) {
991
+ if (XEUtils.includes(includeFields, column.field)) {
992
+ return true
993
+ }
994
+ return false
995
+ }
996
+ return exportOpts.original ? !!column.field : defaultFilterExportColumn(column)
997
+ }
998
+
999
+ function handleExportAndPrint ($xeTable: VxeTableConstructor, options: VxeTablePropTypes.ExportOpts | VxeTablePropTypes.ExportConfig, isPrint?: any) {
1000
+ const props = $xeTable
1001
+ const reactData = $xeTable as unknown as TableReactData
1002
+ const internalData = $xeTable as unknown as TableInternalData
1003
+ const $xeGrid = $xeTable.$xeGrid
1004
+ const $xeGantt = $xeTable.$xeGantt
1005
+ const $xeGGWrapper = $xeGrid || $xeGantt
1006
+
1007
+ const { treeConfig, showHeader, showFooter } = props
1008
+ const { initStore, isGroup, footerTableData, exportStore, exportParams } = reactData
1009
+ const { collectColumn, mergeBodyList, mergeFooterList } = internalData
1010
+ const exportOpts = $xeTable.computeExportOpts
1011
+ const hasTree = treeConfig
1012
+ const customOpts = $xeTable.computeCustomOpts
1013
+ const selectRecords = $xeTable.getCheckboxRecords()
1014
+ const proxyOpts = $xeGGWrapper ? $xeGGWrapper.computeProxyOpts : {}
1015
+ const hasFooter = !!footerTableData.length
1016
+ const hasMerge = !!(mergeBodyList.length || mergeFooterList.length)
1017
+ const defOpts = Object.assign({
1018
+ message: true,
1019
+ isHeader: showHeader,
1020
+ isTitle: showHeader,
1021
+ isFooter: showFooter,
1022
+ isColgroup: isGroup,
1023
+ isMerge: hasMerge,
1024
+ useStyle: true,
1025
+ current: 'current',
1026
+ modes: (proxyOpts.ajax && proxyOpts.ajax.queryAll ? ['all'] : []).concat(['current', 'selected', 'empty'])
1027
+ }, options)
1028
+ const types = defOpts.types || XEUtils.keys(exportOpts._typeMaps)
1029
+ const modes = defOpts.modes || []
1030
+ const checkMethod = customOpts.checkMethod
1031
+ const exportColumns = collectColumn.slice(0)
1032
+ const { columns, excludeFields, includeFields } = defOpts
1033
+ // 处理类型
1034
+ const typeList = types.map((value) => {
1035
+ return {
1036
+ value,
1037
+ label: getI18n(`vxe.export.types.${value}`)
1038
+ }
1039
+ })
1040
+ const modeList = modes.map((item: any) => {
1041
+ if (item && item.value) {
1042
+ return {
1043
+ value: item.value,
1044
+ label: item.label || item.value
1045
+ }
1046
+ }
1047
+ return {
1048
+ value: item,
1049
+ label: getI18n(`vxe.export.modes.${item}`)
1050
+ }
1051
+ })
1052
+ // 默认选中
1053
+ XEUtils.eachTree(exportColumns, (column, index, items, path, parent) => {
1054
+ const isColGroup = column.children && column.children.length > 0
1055
+ let isChecked = false
1056
+ if (columns && columns.length) {
1057
+ isChecked = handleFilterColumns(defOpts, column, columns)
1058
+ } else if (excludeFields || includeFields) {
1059
+ isChecked = handleFilterFields(defOpts, column, includeFields, excludeFields)
1060
+ } else {
1061
+ isChecked = column.visible && (isColGroup || defaultFilterExportColumn(column))
1062
+ }
1063
+ column.checked = isChecked
1064
+ column.halfChecked = false
1065
+ column.disabled = (parent && parent.disabled) || (checkMethod ? !checkMethod({ $table: $xeTable, column }) : false)
1066
+ })
1067
+ // 更新条件
1068
+ Object.assign(exportStore, {
1069
+ columns: exportColumns,
1070
+ typeList,
1071
+ modeList,
1072
+ hasFooter,
1073
+ hasMerge,
1074
+ hasTree,
1075
+ isPrint,
1076
+ hasColgroup: isGroup,
1077
+ visible: true
1078
+ })
1079
+ // 默认参数
1080
+ Object.assign(exportParams, {
1081
+ mode: selectRecords.length ? 'selected' : 'current'
1082
+ }, defOpts)
1083
+ const { filename, sheetName, mode, type } = exportParams
1084
+ if (filename) {
1085
+ if (XEUtils.isFunction(filename)) {
1086
+ exportParams.filename = filename({
1087
+ options: defOpts,
1088
+ $table: $xeTable,
1089
+ $grid: $xeGrid,
1090
+ $gantt: $xeGantt
1091
+ })
1092
+ } else {
1093
+ exportParams.filename = `${filename}`
1094
+ }
1095
+ }
1096
+ if (sheetName) {
1097
+ if (XEUtils.isFunction(sheetName)) {
1098
+ exportParams.sheetName = sheetName({
1099
+ options: defOpts,
1100
+ $table: $xeTable,
1101
+ $grid: $xeGrid,
1102
+ $gantt: $xeGantt
1103
+ })
1104
+ } else {
1105
+ exportParams.sheetName = `${sheetName}`
1106
+ }
1107
+ }
1108
+ if (!modeList.some(item => item.value === mode)) {
1109
+ exportParams.mode = modeList[0].value
1110
+ }
1111
+ if (!typeList.some(item => item.value === type)) {
1112
+ exportParams.type = typeList[0].value
1113
+ }
1114
+ initStore.export = true
1115
+ return $xeTable.$nextTick()
1116
+ }
1117
+
1118
+ const getConvertColumns = (columns: any[]) => {
1119
+ const result: any[] = []
1120
+ columns.forEach((column) => {
1121
+ if (column.childNodes && column.childNodes.length) {
1122
+ result.push(column)
1123
+ result.push(...getConvertColumns(column.childNodes))
1124
+ } else {
1125
+ result.push(column)
1126
+ }
1127
+ })
1128
+ return result
1129
+ }
1130
+
1131
+ const convertToRows = (originColumns: any[]) => {
1132
+ let maxLevel = 1
1133
+ const traverse = (column: any, parent?: any) => {
1134
+ if (parent) {
1135
+ column._level = parent._level + 1
1136
+ if (maxLevel < column._level) {
1137
+ maxLevel = column._level
1138
+ }
1139
+ }
1140
+ if (column.childNodes && column.childNodes.length) {
1141
+ let colSpan = 0
1142
+ column.childNodes.forEach((subColumn: any) => {
1143
+ traverse(subColumn, column)
1144
+ colSpan += subColumn._colSpan
1145
+ })
1146
+ column._colSpan = colSpan
1147
+ } else {
1148
+ column._colSpan = 1
1149
+ }
1150
+ }
1151
+
1152
+ originColumns.forEach((column) => {
1153
+ column._level = 1
1154
+ traverse(column)
1155
+ })
1156
+
1157
+ const rows: any[] = []
1158
+ for (let i = 0; i < maxLevel; i++) {
1159
+ rows.push([])
1160
+ }
1161
+
1162
+ const allColumns = getConvertColumns(originColumns)
1163
+
1164
+ allColumns.forEach((column) => {
1165
+ if (column.childNodes && column.childNodes.length) {
1166
+ column._rowSpan = 1
1167
+ } else {
1168
+ column._rowSpan = maxLevel - column._level + 1
1169
+ }
1170
+ rows[column._level - 1].push(column)
1171
+ })
1172
+
1173
+ return rows
1174
+ }
1175
+
1176
+ export default {
1177
+ methods: {
1178
+ /**
1179
+ * 导出文件,支持 csv/html/xml/txt
1180
+ * 如果是树表格,则默认是导出所有节点
1181
+ * 如果是启用了虚拟滚动,则只能导出数据源,可以配合 dataFilterMethod 函数转换数据
1182
+ * @param {Object} options 参数
1183
+ */
1184
+ _exportData (options?: VxeTablePropTypes.ExportConfig) {
1185
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1186
+ const props = $xeTable
1187
+ const reactData = $xeTable as unknown as TableReactData
1188
+ const internalData = $xeTable as unknown as TableInternalData
1189
+ const $xeGrid = $xeTable.$xeGrid
1190
+ const $xeGantt = $xeTable.$xeGantt
1191
+ const $xeGGWrapper = $xeGrid || $xeGantt
1192
+
1193
+ const { treeConfig, showHeader, showFooter } = props
1194
+ const { isGroup } = reactData
1195
+ const { tableFullColumn, afterFullData, afterTreeFullData, collectColumn, mergeBodyList, mergeFooterList } = internalData
1196
+ const exportOpts = $xeTable.computeExportOpts
1197
+ const treeOpts = $xeTable.computeTreeOpts
1198
+ const proxyOpts = $xeGGWrapper ? $xeGGWrapper.computeProxyOpts : {}
1199
+ const hasMerge = !!(mergeBodyList.length || mergeFooterList.length)
1200
+ const opts = Object.assign({
1201
+ message: true,
1202
+ isHeader: showHeader,
1203
+ isTitle: showHeader,
1204
+ isFooter: showFooter,
1205
+ isColgroup: isGroup,
1206
+ isMerge: hasMerge,
1207
+ useStyle: true,
1208
+ current: 'current',
1209
+ modes: (proxyOpts.ajax && proxyOpts.ajax.queryAll ? ['all'] : []).concat(['current', 'selected', 'empty']),
1210
+ download: true,
1211
+ type: 'csv'
1212
+ // filename: '',
1213
+ // sheetName: '',
1214
+ // original: false,
1215
+ // isAllExpand: false,
1216
+ // data: null,
1217
+ // remote: false,
1218
+ // dataFilterMethod: null,
1219
+ // footerFilterMethod: null,
1220
+ // exportMethod: null,
1221
+ // columnFilterMethod: null,
1222
+ // beforeExportMethod: null,
1223
+ // afterExportMethod: null
1224
+ }, exportOpts, options)
1225
+ let { filename, sheetName, type, mode, columns, original, columnFilterMethod, beforeExportMethod, includeFields, excludeFields } = opts
1226
+ let groups: any[] = []
1227
+ const selectRecords = $xeTable.getCheckboxRecords()
1228
+ if (!mode) {
1229
+ mode = selectRecords.length ? 'selected' : 'current'
1230
+ }
1231
+ let isCustomCol = false
1232
+ let customCols = []
1233
+ if (columns && columns.length) {
1234
+ isCustomCol = true
1235
+ customCols = columns
1236
+ } else {
1237
+ customCols = XEUtils.searchTree(collectColumn, column => {
1238
+ const isColGroup = column.children && column.children.length > 0
1239
+ let isChecked = false
1240
+ if (columns && columns.length) {
1241
+ isChecked = handleFilterColumns(opts, column, columns)
1242
+ } else if (excludeFields || includeFields) {
1243
+ isChecked = handleFilterFields(opts, column, includeFields, excludeFields)
1244
+ } else {
1245
+ isChecked = column.visible && (isColGroup || defaultFilterExportColumn(column))
1246
+ }
1247
+ return isChecked
1248
+ }, { children: 'children', mapChildren: 'childNodes', original: true })
1249
+ }
1250
+ const handleOptions: VxeTablePropTypes.ExportHandleOptions = Object.assign({ } as { data: any[], colgroups: any[], columns: any[] }, opts, { filename: '', sheetName: '' })
1251
+ // 如果设置源数据,则默认导出设置了字段的列
1252
+ if (!isCustomCol && !columnFilterMethod) {
1253
+ columnFilterMethod = ({ column }) => {
1254
+ if (excludeFields) {
1255
+ if (XEUtils.includes(excludeFields, column.field)) {
1256
+ return false
1257
+ }
1258
+ }
1259
+ if (includeFields) {
1260
+ if (XEUtils.includes(includeFields, column.field)) {
1261
+ return true
1262
+ }
1263
+ return false
1264
+ }
1265
+ return original ? !!column.field : defaultFilterExportColumn(column)
1266
+ }
1267
+ handleOptions.columnFilterMethod = columnFilterMethod
1268
+ }
1269
+ if (customCols) {
1270
+ handleOptions._isCustomColumn = true
1271
+ groups = XEUtils.searchTree(
1272
+ XEUtils.mapTree(customCols, (item) => {
1273
+ let targetColumn
1274
+ if (item) {
1275
+ if (isColumnInfo(item)) {
1276
+ targetColumn = item
1277
+ } else if (XEUtils.isString(item)) {
1278
+ targetColumn = $xeTable.getColumnByField(item)
1279
+ } else {
1280
+ const colid = item.id || item.colId
1281
+ const type = item.type
1282
+ const field = item.field
1283
+ if (colid) {
1284
+ targetColumn = $xeTable.getColumnById(colid)
1285
+ } else if (field && type) {
1286
+ targetColumn = tableFullColumn.find((column: VxeTableDefines.ColumnInfo) => column.field === field && column.type === type)
1287
+ } else if (field) {
1288
+ targetColumn = $xeTable.getColumnByField(field)
1289
+ } else if (type) {
1290
+ targetColumn = tableFullColumn.find((column: VxeTableDefines.ColumnInfo) => column.type === type)
1291
+ }
1292
+ }
1293
+ return targetColumn || {}
1294
+ }
1295
+ }, {
1296
+ children: 'childNodes',
1297
+ mapChildren: '_children'
1298
+ }),
1299
+ (column, index) => isColumnInfo(column) && (!columnFilterMethod || columnFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, column: column as any, $columnIndex: index })),
1300
+ {
1301
+ children: '_children',
1302
+ mapChildren: 'childNodes',
1303
+ original: true
1304
+ }
1305
+ )
1306
+ } else {
1307
+ groups = XEUtils.searchTree(isGroup ? collectColumn : tableFullColumn, (column, index) => column.visible && (!columnFilterMethod || columnFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, column, $columnIndex: index })), { children: 'children', mapChildren: 'childNodes', original: true })
1308
+ }
1309
+ // 获取所有列
1310
+ const cols: VxeTableDefines.ColumnInfo[] = []
1311
+ XEUtils.eachTree(groups, column => {
1312
+ const isColGroup = column.children && column.children.length
1313
+ if (!isColGroup) {
1314
+ cols.push(column)
1315
+ }
1316
+ }, { children: 'childNodes' })
1317
+ // 构建分组层级
1318
+ handleOptions.columns = cols
1319
+ handleOptions.colgroups = convertToRows(groups)
1320
+ if (filename) {
1321
+ if (XEUtils.isFunction(filename)) {
1322
+ handleOptions.filename = filename({
1323
+ options: opts,
1324
+ $table: $xeTable,
1325
+ $grid: $xeGrid,
1326
+ $gantt: $xeGantt
1327
+ })
1328
+ } else {
1329
+ handleOptions.filename = `${filename}`
1330
+ }
1331
+ }
1332
+ if (!handleOptions.filename) {
1333
+ handleOptions.filename = getI18n(handleOptions.original ? 'vxe.table.expOriginFilename' : 'vxe.table.expFilename', [XEUtils.toDateString(Date.now(), 'yyyyMMddHHmmss')])
1334
+ }
1335
+
1336
+ if (sheetName) {
1337
+ if (XEUtils.isFunction(sheetName)) {
1338
+ handleOptions.sheetName = sheetName({
1339
+ options: opts,
1340
+ $table: $xeTable,
1341
+ $grid: $xeGrid,
1342
+ $gantt: $xeGantt
1343
+ })
1344
+ } else {
1345
+ handleOptions.sheetName = `${sheetName}`
1346
+ }
1347
+ }
1348
+ if (!handleOptions.sheetName) {
1349
+ handleOptions.sheetName = document.title || ''
1350
+ }
1351
+
1352
+ // 检查类型,如果为自定义导出,则不需要校验类型
1353
+ if (!handleOptions.exportMethod && !XEUtils.includes(XEUtils.keys(exportOpts._typeMaps), type)) {
1354
+ errLog('vxe.error.notType', [type])
1355
+ if (['xlsx', 'pdf'].includes(type)) {
1356
+ warnLog('vxe.error.reqPlugin', [4, 'plugin-export-xlsx'])
1357
+ }
1358
+ const params = { status: false }
1359
+ return Promise.reject(params)
1360
+ }
1361
+
1362
+ if (!handleOptions.print) {
1363
+ if (beforeExportMethod) {
1364
+ beforeExportMethod({ options: handleOptions, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
1365
+ }
1366
+ }
1367
+
1368
+ if (!handleOptions.data) {
1369
+ handleOptions.data = []
1370
+ if (mode === 'selected') {
1371
+ if (['html', 'pdf'].indexOf(type) > -1 && treeConfig) {
1372
+ handleOptions.data = XEUtils.searchTree($xeTable.getTableData().fullData, item => $xeTable.findRowIndexOf(selectRecords, item) > -1, Object.assign({}, treeOpts, { data: '_row' }))
1373
+ } else {
1374
+ handleOptions.data = selectRecords
1375
+ }
1376
+ } else if (mode === 'all') {
1377
+ if (!$xeGGWrapper) {
1378
+ errLog('vxe.error.errProp', ['all', 'mode=current,selected'])
1379
+ }
1380
+
1381
+ if ($xeGGWrapper && !handleOptions.remote) {
1382
+ const gridReactData = $xeGGWrapper.reactData
1383
+ const proxyOpts = $xeGGWrapper.computeProxyOpts
1384
+ const { sortData } = gridReactData
1385
+ const { beforeQueryAll, afterQueryAll, ajax = {} } = proxyOpts
1386
+ const resConfigs = proxyOpts.response || proxyOpts.props || {}
1387
+ const ajaxMethods = ajax.queryAll
1388
+ const queryAllSuccessMethods = ajax.queryAllSuccess
1389
+ const queryAllErrorMethods = ajax.queryAllError
1390
+
1391
+ if (!ajaxMethods) {
1392
+ errLog('vxe.error.notFunc', ['proxy-config.ajax.queryAll'])
1393
+ }
1394
+
1395
+ if (ajaxMethods) {
1396
+ const params = {
1397
+ $table: $xeTable,
1398
+ $grid: $xeGrid,
1399
+ $gantt: $xeGantt,
1400
+ sort: sortData.length ? sortData[0] : {} as any,
1401
+ sorts: sortData as any[],
1402
+ filters: gridReactData.filterData,
1403
+ form: gridReactData.formData,
1404
+ options: handleOptions
1405
+ }
1406
+ return Promise.resolve((beforeQueryAll || ajaxMethods)(params))
1407
+ .then(rest => {
1408
+ const listProp = resConfigs.list
1409
+ let tdData: any[] = []
1410
+ if (listProp) {
1411
+ if (XEUtils.isFunction(listProp)) {
1412
+ tdData = listProp({ data: rest, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
1413
+ } else {
1414
+ tdData = XEUtils.isArray(rest) ? rest : XEUtils.get(rest, listProp)
1415
+ }
1416
+ } else {
1417
+ if (XEUtils.isArray(rest)) {
1418
+ tdData = rest
1419
+ }
1420
+ }
1421
+ handleOptions.data = tdData
1422
+ if (afterQueryAll) {
1423
+ afterQueryAll(params)
1424
+ }
1425
+ if (queryAllSuccessMethods) {
1426
+ queryAllSuccessMethods({ ...params, response: rest })
1427
+ }
1428
+ return handleExport($xeTable, handleOptions)
1429
+ })
1430
+ .catch((rest) => {
1431
+ if (queryAllErrorMethods) {
1432
+ queryAllErrorMethods({ ...params, response: rest })
1433
+ }
1434
+ })
1435
+ }
1436
+ }
1437
+ } else if (mode === 'current') {
1438
+ handleOptions.data = treeConfig ? afterTreeFullData : afterFullData
1439
+ }
1440
+ } else {
1441
+ handleOptions._isCustomData = true
1442
+ }
1443
+ return handleExport($xeTable, handleOptions)
1444
+ },
1445
+ _importByFile (file: File, options: VxeTablePropTypes.ImportConfig) {
1446
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1447
+
1448
+ const opts = Object.assign({}, options)
1449
+ const { beforeImportMethod } = opts
1450
+ if (beforeImportMethod) {
1451
+ beforeImportMethod({ options: opts, $table: $xeTable })
1452
+ }
1453
+ return handleFileImport($xeTable, file, opts)
1454
+ },
1455
+ _importData (options?: VxeTablePropTypes.ImportConfig) {
1456
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1457
+
1458
+ const { importOpts } = this
1459
+ const opts = Object.assign({
1460
+ types: XEUtils.keys(importOpts._typeMaps)
1461
+ // beforeImportMethod: null,
1462
+ // afterImportMethod: null
1463
+ }, importOpts, options)
1464
+ const { beforeImportMethod, afterImportMethod } = opts
1465
+ if (beforeImportMethod) {
1466
+ beforeImportMethod({ options: opts, $table: this })
1467
+ }
1468
+ return VxeUI.readFile(opts).catch(e => {
1469
+ if (afterImportMethod) {
1470
+ afterImportMethod({ status: false, options: opts, $table: $xeTable })
1471
+ }
1472
+ return Promise.reject(e)
1473
+ }).then((params) => {
1474
+ const { file } = params
1475
+ return handleFileImport($xeTable, file, opts)
1476
+ })
1477
+ },
1478
+ _saveFile (options: {
1479
+ filename: string
1480
+ type: string
1481
+ content: string | Blob
1482
+ }) {
1483
+ return VxeUI.saveFile(options)
1484
+ },
1485
+ _readFile (options?: {
1486
+ multiple?: boolean
1487
+ types?: string[]
1488
+ message?: boolean
1489
+ }) {
1490
+ return VxeUI.readFile(options)
1491
+ },
1492
+ _print (options?: VxeTablePropTypes.PrintConfig) {
1493
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1494
+ const $xeGrid = $xeTable.$xeGrid
1495
+ const $xeGantt = $xeTable.$xeGantt
1496
+
1497
+ const printOpts = $xeTable.computePrintOpts
1498
+ const opts = Object.assign({
1499
+ original: false
1500
+ // beforePrintMethod
1501
+ }, printOpts, options, {
1502
+ type: 'html',
1503
+ download: false,
1504
+ remote: false,
1505
+ print: true
1506
+ })
1507
+ const { sheetName } = opts
1508
+ let printTitle = ''
1509
+
1510
+ if (sheetName) {
1511
+ if (XEUtils.isFunction(sheetName)) {
1512
+ printTitle = sheetName({
1513
+ options: opts,
1514
+ $table: $xeTable,
1515
+ $grid: $xeGrid,
1516
+ $gantt: $xeGantt
1517
+ })
1518
+ } else {
1519
+ printTitle = `${sheetName}`
1520
+ }
1521
+ }
1522
+ if (!printTitle) {
1523
+ printTitle = document.title || ''
1524
+ }
1525
+
1526
+ const beforePrintMethod = opts.beforePrintMethod
1527
+ const tableHtml = opts.html || opts.content
1528
+ return new Promise((resolve, reject) => {
1529
+ if (VxeUI.print) {
1530
+ if (tableHtml) {
1531
+ resolve(
1532
+ VxeUI.print({
1533
+ title: printTitle,
1534
+ html: tableHtml,
1535
+ customStyle: opts.style,
1536
+ beforeMethod: beforePrintMethod
1537
+ ? ({ html }) => {
1538
+ return beforePrintMethod({
1539
+ html,
1540
+ content: html,
1541
+ options: opts,
1542
+ $table: $xeTable,
1543
+ $grid: $xeGrid,
1544
+ $gantt: $xeGantt
1545
+ })
1546
+ }
1547
+ : undefined
1548
+ })
1549
+ )
1550
+ } else {
1551
+ resolve(
1552
+ $xeTable.exportData(opts).then(({ content }: any) => {
1553
+ return VxeUI.print({
1554
+ title: printTitle,
1555
+ html: content,
1556
+ customStyle: opts.style,
1557
+ beforeMethod: beforePrintMethod
1558
+ ? ({ html }) => {
1559
+ return beforePrintMethod({
1560
+ html,
1561
+ content: html,
1562
+ options: opts,
1563
+ $table: $xeTable,
1564
+ $grid: $xeGrid,
1565
+ $gantt: $xeGantt
1566
+ })
1567
+ }
1568
+ : undefined
1569
+ })
1570
+ })
1571
+ )
1572
+ }
1573
+ } else {
1574
+ const e = { status: false }
1575
+ reject(e)
1576
+ }
1577
+ })
1578
+ },
1579
+ _getPrintHtml (options: VxeTablePropTypes.PrintConfig) {
1580
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1581
+
1582
+ const printOpts = $xeTable.computePrintOpts
1583
+ const opts = Object.assign({
1584
+ original: false
1585
+ // beforePrintMethod
1586
+ }, printOpts, options, {
1587
+ type: 'html',
1588
+ download: false,
1589
+ remote: false,
1590
+ print: true
1591
+ })
1592
+ return $xeTable.exportData(opts).then(({ content }: any) => {
1593
+ return {
1594
+ html: content
1595
+ }
1596
+ })
1597
+ },
1598
+ _closeImport () {
1599
+ if (VxeUI.modal) {
1600
+ return VxeUI.modal.close('VXE_IMPORT_MODAL')
1601
+ }
1602
+ return Promise.resolve()
1603
+ },
1604
+ _openImport (options?: VxeTablePropTypes.ImportConfig) {
1605
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1606
+ const props = $xeTable
1607
+ const reactData = $xeTable as unknown as TableReactData
1608
+
1609
+ const { treeConfig, importConfig } = props
1610
+ const { initStore, importStore, importParams } = reactData
1611
+ const importOpts = $xeTable.computeImportOpts
1612
+ const defOpts = Object.assign({
1613
+ mode: 'insertTop',
1614
+ message: true,
1615
+ types: XEUtils.keys(importOpts._typeMaps),
1616
+ modes: ['insertTop', 'covering']
1617
+ }, importOpts, options)
1618
+ const types = defOpts.types || []
1619
+ const modes = defOpts.modes || []
1620
+ const isTree = !!treeConfig
1621
+ if (isTree) {
1622
+ if (defOpts.message) {
1623
+ VxeUI.modal.message({ content: getI18n('vxe.error.treeNotImp'), status: 'error' })
1624
+ }
1625
+ return
1626
+ }
1627
+ if (!importConfig) {
1628
+ errLog('vxe.error.reqProp', ['import-config'])
1629
+ }
1630
+ // 处理类型
1631
+ const typeList = types.map((value: any) => {
1632
+ return {
1633
+ value,
1634
+ label: getI18n(`vxe.export.types.${value}`)
1635
+ }
1636
+ })
1637
+ const modeList = modes.map((item: any) => {
1638
+ if (item && item.value) {
1639
+ return {
1640
+ value: item.value,
1641
+ label: item.label || item.value
1642
+ }
1643
+ }
1644
+ return {
1645
+ value: item,
1646
+ label: getI18n(`vxe.import.modes.${item}`)
1647
+ }
1648
+ })
1649
+ Object.assign(importStore, {
1650
+ file: null,
1651
+ type: '',
1652
+ filename: '',
1653
+ modeList,
1654
+ typeList,
1655
+ visible: true
1656
+ })
1657
+ Object.assign(importParams, defOpts)
1658
+ if (!modeList.some(item => item.value === importParams.mode)) {
1659
+ importParams.mode = modeList[0].value
1660
+ }
1661
+ initStore.import = true
1662
+ },
1663
+ _closeExport: handleCloseExport,
1664
+ _openExport (options: any) {
1665
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1666
+ const props = $xeTable
1667
+
1668
+ const exportOpts = $xeTable.computeExportOpts
1669
+ const defOpts = Object.assign({
1670
+ message: true,
1671
+ types: XEUtils.keys(exportOpts._typeMaps)
1672
+ }, exportOpts, options)
1673
+ if (!props.exportConfig) {
1674
+ errLog('vxe.error.reqProp', ['export-config'])
1675
+ }
1676
+ return handleExportAndPrint($xeTable, defOpts)
1677
+ },
1678
+ _closePrint: handleCloseExport,
1679
+ _openPrint (options: any) {
1680
+ const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
1681
+ const props = $xeTable
1682
+
1683
+ const printOpts = $xeTable.computePrintOpts
1684
+ const defOpts = Object.assign({
1685
+ message: true
1686
+ }, printOpts, options)
1687
+ if (!props.printConfig) {
1688
+ errLog('vxe.error.reqProp', ['print-config'])
1689
+ }
1690
+ return handleExportAndPrint($xeTable, defOpts, true)
1691
+ }
1692
+ } as any
1693
+ } as any