vxe-table 4.18.7 → 4.18.8

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