| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682 |
- import XEUtils from 'xe-utils'
- import { VxeUI } from '../../../ui'
- import { isColumnInfo, getCellValue, createHandleGetRowId } from '../../src/util'
- import { parseFile, formatText, eqEmptyValue } from '../../../ui/src/utils'
- import { hasClass } from '../../../ui/src/dom'
- import { createHtmlPage, getExportBlobByContent } from './util'
- import { warnLog, errLog } from '../../../ui/src/log'
- import type { VxeTablePropTypes, VxeTableDefines, TableReactData, VxeTablePrivateMethods, TableInternalData, GridReactData, VxeColumnPropTypes, VxeTableConstructor } from '../../../../types'
- const { getI18n, renderer } = VxeUI
- let htmlCellElem: any
- const csvBOM = '\ufeff'
- const enterSymbol = '\r\n'
- function hasTreeChildren ($xeTable: VxeTableConstructor, row: any) {
- const treeOpts = $xeTable.computeTreeOpts
- const childrenField = treeOpts.children || treeOpts.childrenField
- return row[childrenField] && row[childrenField].length
- }
- function getSeq ($xeTable: VxeTableConstructor, cellValue: any, row: any, $rowIndex: number, column: VxeTableDefines.ColumnInfo, $columnIndex: number) {
- const seqOpts = $xeTable.computeSeqOpts
- const seqMethod = seqOpts.seqMethod || (column as any).seqMethod
- if (seqMethod) {
- return seqMethod({
- $table: $xeTable,
- row,
- rowIndex: $xeTable.getRowIndex(row),
- $rowIndex,
- column,
- columnIndex: $xeTable.getColumnIndex(column),
- $columnIndex
- })
- }
- return cellValue
- }
- function defaultFilterExportColumn (column: VxeTableDefines.ColumnInfo) {
- return !!column.field || ['seq', 'checkbox', 'radio'].indexOf(column.type || '') === -1
- }
- function toTableBorder (border: VxeTablePropTypes.Border | undefined) {
- if (border === true) {
- return 'full'
- }
- if (border) {
- return border
- }
- return 'default'
- }
- function toBooleanValue (cellValue: any) {
- return XEUtils.isBoolean(cellValue) ? (cellValue ? 'TRUE' : 'FALSE') : cellValue
- }
- const toStringValue = (cellValue: any) => {
- return eqEmptyValue(cellValue) ? '' : `${cellValue}`
- }
- function getBodyLabelData ($xeTable: VxeTableConstructor, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
- const props = $xeTable
- const { isAllExpand, mode } = opts
- const { treeConfig } = props
- const radioOpts = $xeTable.computeRadioOpts
- const checkboxOpts = $xeTable.computeCheckboxOpts
- const treeOpts = $xeTable.computeTreeOpts
- const columnOpts = $xeTable.computeColumnOpts
- if (!htmlCellElem) {
- htmlCellElem = document.createElement('div')
- }
- if (treeConfig) {
- const childrenField = treeOpts.children || treeOpts.childrenField
- // 如果是树表格只允许导出数据源
- const rest: any[] = []
- const expandMaps: Record<string, boolean> = {}
- const useMaps: Record<string, boolean> = {}
- const { handleGetRowId } = createHandleGetRowId($xeTable)
- XEUtils.eachTree(datas, (item, $rowIndex, items, path, parent, nodes) => {
- const row = item._row || item
- const rowid = handleGetRowId(row)
- if (useMaps[rowid]) {
- return
- }
- const parentRow = parent && parent._row ? parent._row : parent
- const pRowid = parentRow ? handleGetRowId(parentRow) : ''
- if ((isAllExpand || !parentRow || (expandMaps[pRowid] && $xeTable.isTreeExpandByRow(parentRow)))) {
- const hasRowChild = hasTreeChildren($xeTable, row)
- const item: any = {
- _row: row,
- _level: nodes.length - 1,
- _hasChild: hasRowChild,
- _expand: hasRowChild && $xeTable.isTreeExpandByRow(row)
- }
- columns.forEach((column, $columnIndex) => {
- let cellValue: string | number | boolean | null = ''
- const renderOpts = column.editRender || column.cellRender
- let bodyExportMethod: VxeColumnPropTypes.ExportMethod | undefined = column.exportMethod || columnOpts.exportMethod
- if (!bodyExportMethod && renderOpts && renderOpts.name) {
- const compConf = renderer.get(renderOpts.name)
- if (compConf) {
- bodyExportMethod = compConf.tableExportMethod || compConf.exportMethod
- }
- }
- if (!bodyExportMethod) {
- bodyExportMethod = columnOpts.exportMethod
- }
- if (bodyExportMethod) {
- cellValue = bodyExportMethod({ $table: $xeTable, row, column, options: opts })
- } else {
- switch (column.type) {
- case 'seq': {
- const seqVal = path.map((num, i) => i % 2 === 0 ? (Number(num) + 1) : '.').join('')
- cellValue = mode === 'all' ? seqVal : getSeq($xeTable, seqVal, row, $rowIndex, column, $columnIndex)
- break
- }
- case 'checkbox':
- cellValue = toBooleanValue($xeTable.isCheckedByCheckboxRow(row))
- item._checkboxLabel = checkboxOpts.labelField ? XEUtils.get(row, checkboxOpts.labelField) : ''
- item._checkboxDisabled = checkboxOpts.checkMethod && !checkboxOpts.checkMethod({ $table: $xeTable, row })
- break
- case 'radio':
- cellValue = toBooleanValue($xeTable.isCheckedByRadioRow(row))
- item._radioLabel = radioOpts.labelField ? XEUtils.get(row, radioOpts.labelField) : ''
- item._radioDisabled = radioOpts.checkMethod && !radioOpts.checkMethod({ $table: $xeTable, row })
- break
- default:
- if (opts.original) {
- cellValue = getCellValue(row, column)
- } else {
- cellValue = $xeTable.getCellLabel(row, column)
- if (column.type === 'html') {
- htmlCellElem.innerHTML = cellValue
- cellValue = htmlCellElem.innerText.trim()
- } else {
- const cell = $xeTable.getCellElement(row, column)
- if (cell && !hasClass(cell, 'is--progress')) {
- cellValue = cell.innerText.trim()
- }
- }
- }
- }
- }
- item[column.id] = toStringValue(cellValue)
- })
- useMaps[rowid] = true
- if (pRowid) {
- expandMaps[pRowid] = true
- }
- rest.push(Object.assign(item, row))
- }
- }, { children: childrenField })
- return rest
- }
- return datas.map((row, $rowIndex) => {
- const item: any = {
- _row: row
- }
- columns.forEach((column, $columnIndex) => {
- let cellValue: string | number | boolean | null = ''
- const renderOpts = column.editRender || column.cellRender
- let bodyExportMethod: VxeColumnPropTypes.ExportMethod | undefined = column.exportMethod || columnOpts.exportMethod
- if (!bodyExportMethod && renderOpts && renderOpts.name) {
- const compConf = renderer.get(renderOpts.name)
- if (compConf) {
- bodyExportMethod = compConf.tableExportMethod || compConf.exportMethod
- }
- }
- if (bodyExportMethod) {
- cellValue = bodyExportMethod({ $table: $xeTable, row, column, options: opts })
- } else {
- switch (column.type) {
- case 'seq': {
- const seqValue = $rowIndex + 1
- cellValue = mode === 'all' ? seqValue : getSeq($xeTable, seqValue, row, $rowIndex, column, $columnIndex)
- break
- }
- case 'checkbox':
- cellValue = toBooleanValue($xeTable.isCheckedByCheckboxRow(row))
- item._checkboxLabel = checkboxOpts.labelField ? XEUtils.get(row, checkboxOpts.labelField) : ''
- item._checkboxDisabled = checkboxOpts.checkMethod && !checkboxOpts.checkMethod({ $table: $xeTable, row })
- break
- case 'radio':
- cellValue = toBooleanValue($xeTable.isCheckedByRadioRow(row))
- item._radioLabel = radioOpts.labelField ? XEUtils.get(row, radioOpts.labelField) : ''
- item._radioDisabled = radioOpts.checkMethod && !radioOpts.checkMethod({ $table: $xeTable, row })
- break
- default:
- if (opts.original) {
- cellValue = getCellValue(row, column)
- } else {
- cellValue = $xeTable.getCellLabel(row, column)
- if (column.type === 'html') {
- htmlCellElem.innerHTML = cellValue
- cellValue = htmlCellElem.innerText.trim()
- } else {
- const cell = $xeTable.getCellElement(row, column)
- if (cell && !hasClass(cell, 'is--progress')) {
- cellValue = cell.innerText.trim()
- }
- }
- }
- }
- }
- item[column.id] = toStringValue(cellValue)
- })
- return item
- })
- }
- function getExportData ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions) {
- const $xeGrid = $xeTable.$xeGrid
- const $xeGantt = $xeTable.$xeGantt
- const { columns, dataFilterMethod } = opts
- let datas = opts.data
- if (dataFilterMethod) {
- datas = datas.filter((row, index) => dataFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, row, $rowIndex: index }))
- }
- return getBodyLabelData($xeTable, opts, columns, datas)
- }
- function getBooleanValue (cellValue: any) {
- return cellValue === 'TRUE' || cellValue === 'true' || cellValue === true
- }
- function getHeaderTitle ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, column: VxeTableDefines.ColumnInfo) {
- const columnOpts = $xeTable.computeColumnOpts
- const headExportMethod = column.headerExportMethod || columnOpts.headerExportMethod
- return headExportMethod ? headExportMethod({ column, options: opts, $table: $xeTable }) : ((opts.isTitle ? column.getTitle() : column.field) || '')
- }
- function getFooterCellValue ($xeTable: any, opts: VxeTablePropTypes.ExportHandleOptions, row: any, column: VxeTableDefines.ColumnInfo) {
- const columnOpts = $xeTable.computeColumnOpts
- const renderOpts = column.editRender || column.cellRender
- let footLabelMethod: VxeColumnPropTypes.FooterExportMethod | undefined = column.footerExportMethod
- if (!footLabelMethod && renderOpts && renderOpts.name) {
- const compConf = renderer.get(renderOpts.name)
- if (compConf) {
- footLabelMethod = compConf.tableFooterExportMethod || compConf.footerExportMethod || (compConf as any).footerCellExportMethod
- }
- }
- if (!footLabelMethod) {
- footLabelMethod = columnOpts.footerExportMethod
- }
- const _columnIndex = $xeTable.getVTColumnIndex(column)
- if (footLabelMethod) {
- return footLabelMethod({ $table: $xeTable, items: row, itemIndex: _columnIndex, row, _columnIndex, column, options: opts })
- }
- // 兼容老模式
- if (XEUtils.isArray(row)) {
- return XEUtils.toValueString(row[_columnIndex])
- }
- return XEUtils.get(row, column.field)
- }
- function getFooterData ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, footerTableData: any[]) {
- const $xeGrid = $xeTable.$xeGrid
- const $xeGantt = $xeTable.$xeGantt
- const { footerFilterMethod } = opts
- return footerFilterMethod ? footerTableData.filter((items: any, index: any) => footerFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, items, $rowIndex: index })) : footerTableData
- }
- function getCsvCellTypeLabel (column: any, cellValue: any) {
- if (cellValue) {
- if (column.type === 'seq') {
- return `\t${cellValue}`
- }
- switch (column.cellType) {
- case 'string':
- if (!isNaN(cellValue)) {
- return `\t${cellValue}`
- }
- break
- case 'number':
- break
- default:
- if (cellValue.length >= 12 && !isNaN(cellValue)) {
- return `\t${cellValue}`
- }
- break
- }
- }
- return cellValue
- }
- function toTxtCellLabel (val: any) {
- if (/[",\s\n]/.test(val)) {
- return `"${val.replace(/"/g, '""')}"`
- }
- return val
- }
- function toCsv ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
- const reactData = $xeTable as unknown as TableReactData
- let content = csvBOM
- if (opts.isHeader) {
- content += columns.map(column => toTxtCellLabel(getHeaderTitle($xeTable, opts, column))).join(',') + enterSymbol
- }
- datas.forEach(row => {
- content += columns.map(column => toTxtCellLabel(getCsvCellTypeLabel(column, row[column.id]))).join(',') + enterSymbol
- })
- if (opts.isFooter) {
- const { footerTableData } = reactData
- const footers = getFooterData($xeTable, opts, footerTableData)
- footers.forEach((row) => {
- content += columns.map(column => toTxtCellLabel(getFooterCellValue($xeTable, opts, row, column))).join(',') + enterSymbol
- })
- }
- return content
- }
- function toTxt ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
- const reactData = $xeTable as unknown as TableReactData
- let content = ''
- if (opts.isHeader) {
- content += columns.map(column => toTxtCellLabel(getHeaderTitle($xeTable, opts, column))).join('\t') + enterSymbol
- }
- datas.forEach(row => {
- content += columns.map(column => toTxtCellLabel(row[column.id])).join('\t') + enterSymbol
- })
- if (opts.isFooter) {
- const { footerTableData } = reactData
- const footers = getFooterData($xeTable, opts, footerTableData)
- footers.forEach((row) => {
- content += columns.map(column => toTxtCellLabel(getFooterCellValue($xeTable, opts, row, column))).join('\t') + enterSymbol
- })
- }
- return content
- }
- function hasEllipsis ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, column: VxeTableDefines.ColumnInfo, property: 'showOverflow' | 'showHeaderOverflow', allColumnOverflow: VxeTablePropTypes.ShowOverflow | undefined) {
- const reactData = $xeTable as unknown as TableReactData
- const columnOverflow = column[property]
- const headOverflow = XEUtils.isUndefined(columnOverflow) || XEUtils.isNull(columnOverflow) ? allColumnOverflow : columnOverflow
- const showEllipsis = headOverflow === 'ellipsis'
- const showTitle = headOverflow === 'title'
- const showTooltip = headOverflow === true || headOverflow === 'tooltip'
- let isEllipsis = showTitle || showTooltip || showEllipsis
- // 虚拟滚动不支持动态高度
- const { scrollXLoad, scrollYLoad } = reactData
- if ((scrollXLoad || scrollYLoad) && !isEllipsis) {
- isEllipsis = true
- }
- return isEllipsis
- }
- function toHtml ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
- const props = $xeTable
- const reactData = $xeTable as unknown as TableReactData
- const internalData = $xeTable as unknown as TableInternalData
- const { id, border, treeConfig, headerAlign: allHeaderAlign, align: allAlign, footerAlign: allFooterAlign, showOverflow: allColumnOverflow, showHeaderOverflow: allColumnHeaderOverflow } = props
- const { isAllSelected, isIndeterminate } = reactData
- const { mergeBodyCellMaps } = internalData
- const treeOpts = $xeTable.computeTreeOpts
- const { print: isPrint, isHeader, isFooter, isColgroup, isMerge, colgroups, original } = opts
- const allCls = 'check-all'
- const clss = [
- 'vxe-table',
- `border--${toTableBorder(border)}`,
- isPrint ? 'is--print' : '',
- isHeader ? 'is--header' : ''
- ].filter(cls => cls)
- const tables = [
- `<table class="${clss.join(' ')}" border="0" cellspacing="0" cellpadding="0">`,
- `<colgroup>${columns.map(column => `<col style="width:${column.renderWidth}px">`).join('')}</colgroup>`
- ]
- if (isHeader) {
- tables.push('<thead>')
- if (isColgroup && !original) {
- colgroups.forEach((cols: any[]) => {
- tables.push(
- `<tr>${cols.map(column => {
- const headAlign = column.headerAlign || column.align || allHeaderAlign || allAlign
- const classNames = hasEllipsis($xeTable, column, 'showHeaderOverflow', allColumnHeaderOverflow) ? ['col--ellipsis'] : []
- const cellTitle = getHeaderTitle($xeTable, opts, column)
- let childWidth = 0
- let countChild = 0
- XEUtils.eachTree([column], item => {
- if (!item.childNodes || !column.childNodes.length) {
- countChild++
- }
- childWidth += item.renderWidth
- }, { children: 'childNodes' })
- const cellWidth = childWidth - countChild
- if (headAlign) {
- classNames.push(`col--${headAlign}`)
- }
- if (column.type === 'checkbox') {
- 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>`
- }
- 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>`
- }).join('')}</tr>`
- )
- })
- } else {
- tables.push(
- `<tr>${columns.map(column => {
- const headAlign = column.headerAlign || column.align || allHeaderAlign || allAlign
- const classNames = hasEllipsis($xeTable, column, 'showHeaderOverflow', allColumnHeaderOverflow) ? ['col--ellipsis'] : []
- const cellTitle = getHeaderTitle($xeTable, opts, column)
- if (headAlign) {
- classNames.push(`col--${headAlign}`)
- }
- if (column.type === 'checkbox') {
- return `<th class="${classNames.join(' ')}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><input type="checkbox" class="${allCls}" ${isAllSelected ? 'checked' : ''}><span>${cellTitle}</span></div></th>`
- }
- return `<th class="${classNames.join(' ')}" title="${cellTitle}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}><span>${formatText(cellTitle, true)}</span></div></th>`
- }).join('')}</tr>`
- )
- }
- tables.push('</thead>')
- }
- if (datas.length) {
- tables.push('<tbody>')
- if (treeConfig) {
- datas.forEach(item => {
- tables.push(
- '<tr>' + columns.map(column => {
- const cellAlign = column.align || allAlign
- const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
- const cellValue = item[column.id]
- if (cellAlign) {
- classNames.push(`col--${cellAlign}`)
- }
- if (column.treeNode) {
- let treeIcon = ''
- if (item._hasChild) {
- treeIcon = `<i class="${item._expand ? 'vxe-table--tree-fold-icon' : 'vxe-table--tree-unfold-icon'}"></i>`
- }
- classNames.push('vxe-table--tree-node')
- if (column.type === 'radio') {
- 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>`
- } else if (column.type === 'checkbox') {
- 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>`
- }
- 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>`
- }
- if (column.type === 'radio') {
- 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>`
- } else if (column.type === 'checkbox') {
- 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>`
- }
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
- }).join('') + '</tr>'
- )
- })
- } else {
- datas.forEach(item => {
- tables.push(
- '<tr>' + columns.map(column => {
- const colid = column.id
- const cellAlign = column.align || allAlign
- const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
- const cellValue = item[colid]
- let rowSpan = 1
- let colSpan = 1
- if (isMerge) {
- const _rowIndex = $xeTable.getVTRowIndex(item._row)
- const _columnIndex = $xeTable.getVTColumnIndex(column)
- const spanRest = mergeBodyCellMaps[`${_rowIndex}:${_columnIndex}`]
- if (spanRest) {
- const { rowspan, colspan } = spanRest
- if (!rowspan || !colspan) {
- return ''
- }
- if (rowspan > 1) {
- rowSpan = rowspan
- }
- if (colspan > 1) {
- colSpan = colspan
- }
- }
- }
- if (cellAlign) {
- classNames.push(`col--${cellAlign}`)
- }
- if (column.type === 'radio') {
- 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>`
- } else if (column.type === 'checkbox') {
- 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>`
- }
- return `<td class="${classNames.join(' ')}" rowspan="${rowSpan}" colspan="${colSpan}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
- }).join('') + '</tr>'
- )
- })
- }
- tables.push('</tbody>')
- }
- if (isFooter) {
- const { footerTableData } = reactData
- const footers = getFooterData($xeTable, opts, footerTableData)
- if (footers.length) {
- tables.push('<tfoot>')
- footers.forEach((row: any) => {
- tables.push(
- `<tr>${columns.map(column => {
- const footAlign = column.footerAlign || column.align || allFooterAlign || allAlign
- const classNames = hasEllipsis($xeTable, column, 'showOverflow', allColumnOverflow) ? ['col--ellipsis'] : []
- const cellValue = getFooterCellValue($xeTable, opts, row, column)
- if (footAlign) {
- classNames.push(`col--${footAlign}`)
- }
- return `<td class="${classNames.join(' ')}" title="${cellValue}"><div ${isPrint ? '' : `style="width: ${column.renderWidth}px"`}>${formatText(cellValue, true)}</div></td>`
- }).join('')}</tr>`
- )
- })
- tables.push('</tfoot>')
- }
- }
- // 是否半选状态
- const script = !isAllSelected && isIndeterminate ? `<script>(function(){var a=document.querySelector(".${allCls}");if(a){a.indeterminate=true}})()</script>` : ''
- tables.push('</table>', script)
- return isPrint ? tables.join('') : createHtmlPage(opts, tables.join(''))
- }
- function toXML ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: any, columns: any[], datas: any[]) {
- const reactData = $xeTable as unknown as TableReactData
- let xml = [
- '<?xml version="1.0"?>',
- '<?mso-application progid="Excel.Sheet"?>',
- '<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">',
- '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">',
- '<Version>16.00</Version>',
- '</DocumentProperties>',
- '<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">',
- '<WindowHeight>7920</WindowHeight>',
- '<WindowWidth>21570</WindowWidth>',
- '<WindowTopX>32767</WindowTopX>',
- '<WindowTopY>32767</WindowTopY>',
- '<ProtectStructure>False</ProtectStructure>',
- '<ProtectWindows>False</ProtectWindows>',
- '</ExcelWorkbook>',
- `<Worksheet ss:Name="${opts.sheetName}">`,
- '<Table>',
- columns.map(column => `<Column ss:Width="${column.renderWidth}"/>`).join('')
- ].join('')
- if (opts.isHeader) {
- xml += `<Row>${columns.map(column => `<Cell><Data ss:Type="String">${getHeaderTitle($xeTable, opts, column)}</Data></Cell>`).join('')}</Row>`
- }
- datas.forEach(row => {
- xml += '<Row>' + columns.map(column => `<Cell><Data ss:Type="String">${row[column.id]}</Data></Cell>`).join('') + '</Row>'
- })
- if (opts.isFooter) {
- const { footerTableData } = reactData
- const footers = getFooterData($xeTable, opts, footerTableData)
- footers.forEach((row: any) => {
- xml += `<Row>${columns.map(column => `<Cell><Data ss:Type="String">${getFooterCellValue($xeTable, opts, row, column)}</Data></Cell>`).join('')}</Row>`
- })
- }
- return `${xml}</Table></Worksheet></Workbook>`
- }
- function getContent ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions, columns: VxeTableDefines.ColumnInfo[], datas: any[]) {
- if (columns.length) {
- switch (opts.type) {
- case 'csv':
- return toCsv($xeTable, opts, columns, datas)
- case 'txt':
- return toTxt($xeTable, opts, columns, datas)
- case 'html':
- return toHtml($xeTable, opts, columns, datas)
- case 'xml':
- return toXML($xeTable, opts, columns, datas)
- }
- }
- return ''
- }
- function downloadFile ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: any, content: any) {
- const { filename, type, download } = opts
- if (!download) {
- const blob = getExportBlobByContent(content, opts)
- return Promise.resolve({ type, content, blob })
- }
- if (VxeUI.saveFile) {
- VxeUI.saveFile({ filename, type, content }).then(() => {
- if (opts.message !== false) {
- if (VxeUI.modal) {
- VxeUI.modal.message({ content: getI18n('vxe.table.expSuccess'), status: 'success' })
- }
- }
- })
- }
- }
- function clearColumnConvert (columns: any) {
- XEUtils.eachTree(columns, column => {
- delete column._level
- delete column._colSpan
- delete column._rowSpan
- delete column._children
- delete column.childNodes
- }, { children: 'children' })
- }
- function handleExport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, opts: VxeTablePropTypes.ExportHandleOptions) {
- const $xeGrid = $xeTable.$xeGrid
- const $xeGantt = $xeTable.$xeGantt
- const { remote, columns, colgroups, exportMethod, afterExportMethod } = opts
- return new Promise(resolve => {
- if (remote) {
- const params = { options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }
- resolve(exportMethod ? exportMethod(params) : params)
- } else {
- const datas = getExportData($xeTable, opts)
- resolve(
- $xeTable.preventEvent(null, 'event.export', { options: opts, columns, colgroups, datas }, () => {
- return downloadFile($xeTable, opts, getContent($xeTable, opts, columns, datas))
- })
- )
- }
- }).then((params) => {
- clearColumnConvert(columns)
- if (!opts.print) {
- if (afterExportMethod) {
- afterExportMethod({ status: true, options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
- }
- }
- return Object.assign({ status: true }, params)
- }).catch(() => {
- clearColumnConvert(columns)
- if (!opts.print) {
- if (afterExportMethod) {
- afterExportMethod({ status: false, options: opts, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
- }
- }
- const params = { status: false }
- return Promise.reject(params)
- })
- }
- function getElementsByTagName (elem: any, qualifiedName: any) {
- return elem.getElementsByTagName(qualifiedName) as HTMLElement[]
- }
- function getTxtCellKey (now: any) {
- return `#${now}@${XEUtils.uniqueId()}`
- }
- function replaceTxtCell (cell: any, vMaps: any) {
- return cell.replace(/#\d+@\d+/g, (key: any) => XEUtils.hasOwnProp(vMaps, key) ? vMaps[key] : key)
- }
- function getTxtCellValue (val: any, vMaps: any) {
- const rest = replaceTxtCell(val, vMaps)
- return rest.replace(/^"+$/g, (qVal: any) => '"'.repeat(Math.ceil(qVal.length / 2)))
- }
- function toExportField (tableConf: {
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
- }, field: string) {
- const { fieldMaps, titleMaps } = tableConf
- // title 转 field
- if (!fieldMaps[field]) {
- const teCol = titleMaps[field]
- if (teCol && teCol.field) {
- field = teCol.field
- }
- }
- return field
- }
- function parseCsvAndTxt (tableConf: {
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
- }, content: string, cellSeparator: string) {
- const list = content.split(enterSymbol)
- const rows: any[] = []
- let fields: string[] = []
- if (list.length) {
- const vMaps: any = {}
- const now = Date.now()
- list.forEach((rVal) => {
- if (rVal) {
- const item: any = {}
- rVal = rVal.replace(/("")|(\n)/g, (text: string, dVal: string) => {
- const key = getTxtCellKey(now)
- vMaps[key] = dVal ? '"' : '\n'
- return key
- }).replace(/"(.*?)"/g, (text: string, cVal: string) => {
- const key = getTxtCellKey(now)
- vMaps[key] = replaceTxtCell(cVal, vMaps)
- return key
- })
- const cells: string[] = rVal.split(cellSeparator)
- if (!fields.length) {
- fields = cells.map((val: string) => toExportField(tableConf, getTxtCellValue(val.trim(), vMaps)))
- } else {
- cells.forEach((val, colIndex) => {
- if (colIndex < fields.length) {
- item[fields[colIndex]] = getTxtCellValue(val.trim(), vMaps)
- }
- })
- rows.push(item)
- }
- }
- })
- }
- return { fields, rows }
- }
- function parseCsv (tableConf: {
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
- }, content: string) {
- return parseCsvAndTxt(tableConf, content, ',')
- }
- function parseTxt (tableConf: {
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
- }, content: string) {
- return parseCsvAndTxt(tableConf, content, '\t')
- }
- function parseHTML (tableConf: {
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
- }, content: string) {
- const domParser = new DOMParser()
- const xmlDoc = domParser.parseFromString(content, 'text/html')
- const bodyNodes = getElementsByTagName(xmlDoc, 'body')
- const rows: any[] = []
- const fields: string[] = []
- if (bodyNodes.length) {
- const tableNodes = getElementsByTagName(bodyNodes[0], 'table')
- if (tableNodes.length) {
- const theadNodes = getElementsByTagName(tableNodes[0], 'thead')
- if (theadNodes.length) {
- XEUtils.arrayEach(getElementsByTagName(theadNodes[0], 'tr'), rowNode => {
- XEUtils.arrayEach(getElementsByTagName(rowNode, 'th'), cellNode => {
- fields.push(toExportField(tableConf, cellNode.textContent || ''))
- })
- })
- const tbodyNodes = getElementsByTagName(tableNodes[0], 'tbody')
- if (tbodyNodes.length) {
- XEUtils.arrayEach(getElementsByTagName(tbodyNodes[0], 'tr'), rowNode => {
- const item: any = {}
- XEUtils.arrayEach(getElementsByTagName(rowNode, 'td'), (cellNode, colIndex) => {
- if (fields[colIndex]) {
- item[fields[colIndex]] = cellNode.textContent || ''
- }
- })
- rows.push(item)
- })
- }
- }
- }
- }
- return { fields, rows }
- }
- function parseXML (tableConf: {
- fieldMaps: Record<string, VxeTableDefines.ColumnInfo>
- titleMaps: Record<string, VxeTableDefines.ColumnInfo>
- }, content: string) {
- const domParser = new DOMParser()
- const xmlDoc = domParser.parseFromString(content, 'application/xml')
- const sheetNodes = getElementsByTagName(xmlDoc, 'Worksheet')
- const rows: any[] = []
- const fields: string[] = []
- if (sheetNodes.length) {
- const tableNodes = getElementsByTagName(sheetNodes[0], 'Table')
- if (tableNodes.length) {
- const rowNodes = getElementsByTagName(tableNodes[0], 'Row')
- if (rowNodes.length) {
- XEUtils.arrayEach(getElementsByTagName(rowNodes[0], 'Cell'), cellNode => {
- fields.push(toExportField(tableConf, cellNode.textContent || ''))
- })
- XEUtils.arrayEach(rowNodes, (rowNode, index) => {
- if (index) {
- const item: any = {}
- const cellNodes = getElementsByTagName(rowNode, 'Cell')
- XEUtils.arrayEach(cellNodes, (cellNode, colIndex) => {
- if (fields[colIndex]) {
- item[fields[colIndex]] = cellNode.textContent
- }
- })
- rows.push(item)
- }
- })
- }
- }
- }
- return { fields, rows }
- }
- function handleImport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, content: any, opts: any) {
- const internalData = $xeTable as unknown as TableInternalData
- const { tableFullColumn, _importResolve, _importReject } = internalData
- let rest: {
- fields: string[];
- rows: any[];
- } = { fields: [], rows: [] }
- const tableFieldMaps: Record<string, VxeTableDefines.ColumnInfo> = {}
- const tableTitleMaps: Record<string, VxeTableDefines.ColumnInfo> = {}
- tableFullColumn.forEach((column) => {
- const field = column.field
- const title = column.getTitle()
- if (field) {
- tableFieldMaps[field] = column
- }
- if (title) {
- tableTitleMaps[column.getTitle()] = column
- }
- })
- const tableConf = {
- fieldMaps: tableFieldMaps,
- titleMaps: tableTitleMaps
- }
- switch (opts.type) {
- case 'csv':
- rest = parseCsv(tableConf, content)
- break
- case 'txt':
- rest = parseTxt(tableConf, content)
- break
- case 'html':
- rest = parseHTML(tableConf, content)
- break
- case 'xml':
- rest = parseXML(tableConf, content)
- break
- }
- const { fields, rows } = rest
- const status = fields.some(field => tableFieldMaps[field] || tableTitleMaps[field])
- if (status) {
- $xeTable.createData(rows)
- .then((data: any) => {
- let loadRest
- if (opts.mode === 'insert' || opts.mode === 'insertBottom') {
- loadRest = $xeTable.insertAt(data, -1)
- } if (opts.mode === 'insertTop') {
- loadRest = $xeTable.insert(data)
- } else {
- loadRest = $xeTable.reloadData(data)
- }
- if (opts.message !== false) {
- // 检测弹窗模块
- if (!VxeUI.modal) {
- errLog('vxe.error.reqModule', ['Modal'])
- }
- VxeUI.modal.message({ content: getI18n('vxe.table.impSuccess', [rows.length]), status: 'success' })
- }
- return loadRest.then(() => {
- if (_importResolve) {
- _importResolve({ status: true })
- }
- })
- })
- } else if (opts.message !== false) {
- // 检测弹窗模块
- if (!VxeUI.modal) {
- errLog('vxe.error.reqModule', ['Modal'])
- }
- VxeUI.modal.message({ content: getI18n('vxe.error.impFields'), status: 'error' })
- if (_importReject) {
- _importReject({ status: false })
- }
- }
- }
- function handleFileImport ($xeTable: VxeTableConstructor & VxeTablePrivateMethods, file: any, opts: any) {
- const internalData = $xeTable as unknown as TableInternalData
- const importOpts = $xeTable.computeImportOpts
- const { importMethod, afterImportMethod } = opts
- const { type, filename } = parseFile(file)
- // 检查类型,如果为自定义导出,则不需要校验类型
- if (!importMethod && !XEUtils.includes(XEUtils.keys(importOpts._typeMaps), type)) {
- if (opts.message !== false) {
- // 检测弹窗模块
- if (!VxeUI.modal) {
- errLog('vxe.error.reqModule', ['Modal'])
- }
- VxeUI.modal.message({ content: getI18n('vxe.error.notType', [type]), status: 'error' })
- }
- const params = { status: false }
- return Promise.reject(params)
- }
- const rest = new Promise((resolve, reject) => {
- const _importResolve = (params: any) => {
- resolve(params)
- ;($xeTable as any)._importResolve = null
- ;($xeTable as any)._importReject = null
- }
- const _importReject = (params: any) => {
- reject(params)
- ;($xeTable as any)._importResolve = null
- ;($xeTable as any)._importReject = null
- }
- ;($xeTable as any)._importResolve = _importResolve
- ;($xeTable as any)._importReject = _importReject
- if (window.FileReader) {
- const options = Object.assign({ mode: 'insertTop' }, opts, { type, filename })
- if (options.remote) {
- if (importMethod) {
- Promise.resolve(importMethod({ file, options, $table: $xeTable })).then(() => {
- _importResolve({ status: true })
- }).catch(() => {
- _importResolve({ status: true })
- })
- } else {
- _importResolve({ status: true })
- }
- } else {
- const { tableFullColumn } = internalData
- $xeTable.preventEvent(null, 'event.import', { file, options, columns: tableFullColumn }, () => {
- const reader = new FileReader()
- reader.onerror = () => {
- errLog('vxe.error.notType', [type])
- _importReject({ status: false })
- }
- reader.onload = (e: any) => {
- handleImport($xeTable, e.target.result, options)
- }
- reader.readAsText(file, options.encoding || 'UTF-8')
- })
- }
- } else {
- // 不支持的浏览器
- errLog('vxe.error.notExp')
- _importResolve({ status: true })
- }
- })
- return rest.then(() => {
- if (afterImportMethod) {
- afterImportMethod({ status: true, options: opts, $table: $xeTable })
- }
- }).catch((e) => {
- if (afterImportMethod) {
- afterImportMethod({ status: false, options: opts, $table: $xeTable })
- }
- return Promise.reject(e)
- })
- }
- function handleCloseExport () {
- if (VxeUI.modal) {
- return VxeUI.modal.close('VXE_EXPORT_MODAL')
- }
- return Promise.resolve()
- }
- function handleFilterColumns (exportOpts: VxeTablePropTypes.ExportConfig, column: VxeTableDefines.ColumnInfo, columns: VxeTableDefines.ColumnInfo[] | VxeTablePropTypes.ExportOrPrintColumnOption[]) {
- return columns.some((item: any) => {
- if (isColumnInfo(item)) {
- return column.id === (item as any).id
- } else if (XEUtils.isString(item)) {
- return column.field === item
- } else {
- const colid = item.id || item.colId
- const type = item.type
- const field = item.field
- if (colid) {
- return column.id === colid
- } else if (field && type) {
- return column.field === field && column.type === type
- } else if (field) {
- return column.field === field
- } else if (type) {
- return column.type === type
- }
- }
- return false
- })
- }
- function handleFilterFields (exportOpts: VxeTablePropTypes.ExportConfig, column: VxeTableDefines.ColumnInfo, includeFields: string[] | undefined, excludeFields: string[] | undefined) {
- if (excludeFields) {
- if (XEUtils.includes(excludeFields, column.field)) {
- return false
- }
- }
- if (includeFields) {
- if (XEUtils.includes(includeFields, column.field)) {
- return true
- }
- return false
- }
- return exportOpts.original ? !!column.field : defaultFilterExportColumn(column)
- }
- function handleExportAndPrint ($xeTable: VxeTableConstructor, options: VxeTablePropTypes.ExportOpts | VxeTablePropTypes.ExportConfig, isPrint?: any) {
- const props = $xeTable
- const reactData = $xeTable as unknown as TableReactData
- const internalData = $xeTable as unknown as TableInternalData
- const $xeGrid = $xeTable.$xeGrid
- const $xeGantt = $xeTable.$xeGantt
- const $xeGGWrapper = $xeGrid || $xeGantt
- const { treeConfig, showHeader, showFooter } = props
- const { initStore, isGroup, footerTableData, exportStore, exportParams } = reactData
- const { collectColumn, mergeBodyList, mergeFooterList } = internalData
- const exportOpts = $xeTable.computeExportOpts
- const hasTree = treeConfig
- const customOpts = $xeTable.computeCustomOpts
- const selectRecords = $xeTable.getCheckboxRecords()
- const proxyOpts = $xeGGWrapper ? $xeGGWrapper.computeProxyOpts : {}
- const hasFooter = !!footerTableData.length
- const hasMerge = !!(mergeBodyList.length || mergeFooterList.length)
- const defOpts = Object.assign({
- message: true,
- isHeader: showHeader,
- isTitle: showHeader,
- isFooter: showFooter,
- isColgroup: isGroup,
- isMerge: hasMerge,
- useStyle: true,
- current: 'current',
- modes: (proxyOpts.ajax && proxyOpts.ajax.queryAll ? ['all'] : []).concat(['current', 'selected', 'empty'])
- }, options)
- const types = defOpts.types || XEUtils.keys(exportOpts._typeMaps)
- const modes = defOpts.modes || []
- const checkMethod = customOpts.checkMethod
- const exportColumns = collectColumn.slice(0)
- const { columns, excludeFields, includeFields } = defOpts
- // 处理类型
- const typeList = types.map((value) => {
- return {
- value,
- label: getI18n(`vxe.export.types.${value}`)
- }
- })
- const modeList = modes.map((item: any) => {
- if (item && item.value) {
- return {
- value: item.value,
- label: item.label || item.value
- }
- }
- return {
- value: item,
- label: getI18n(`vxe.export.modes.${item}`)
- }
- })
- // 默认选中
- XEUtils.eachTree(exportColumns, (column, index, items, path, parent) => {
- const isColGroup = column.children && column.children.length > 0
- let isChecked = false
- if (columns && columns.length) {
- isChecked = handleFilterColumns(defOpts, column, columns)
- } else if (excludeFields || includeFields) {
- isChecked = handleFilterFields(defOpts, column, includeFields, excludeFields)
- } else {
- isChecked = column.visible && (isColGroup || defaultFilterExportColumn(column))
- }
- column.checked = isChecked
- column.halfChecked = false
- column.disabled = (parent && parent.disabled) || (checkMethod ? !checkMethod({ $table: $xeTable, column }) : false)
- })
- // 更新条件
- Object.assign(exportStore, {
- columns: exportColumns,
- typeList,
- modeList,
- hasFooter,
- hasMerge,
- hasTree,
- isPrint,
- hasColgroup: isGroup,
- visible: true
- })
- // 默认参数
- Object.assign(exportParams, {
- mode: selectRecords.length ? 'selected' : 'current'
- }, defOpts)
- const { filename, sheetName, mode, type } = exportParams
- if (filename) {
- if (XEUtils.isFunction(filename)) {
- exportParams.filename = filename({
- options: defOpts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- } else {
- exportParams.filename = `${filename}`
- }
- }
- if (sheetName) {
- if (XEUtils.isFunction(sheetName)) {
- exportParams.sheetName = sheetName({
- options: defOpts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- } else {
- exportParams.sheetName = `${sheetName}`
- }
- }
- if (!modeList.some(item => item.value === mode)) {
- exportParams.mode = modeList[0].value
- }
- if (!typeList.some(item => item.value === type)) {
- exportParams.type = typeList[0].value
- }
- initStore.export = true
- return $xeTable.$nextTick()
- }
- const getConvertColumns = (columns: any[]) => {
- const result: any[] = []
- columns.forEach((column) => {
- if (column.childNodes && column.childNodes.length) {
- result.push(column)
- result.push(...getConvertColumns(column.childNodes))
- } else {
- result.push(column)
- }
- })
- return result
- }
- const convertToRows = (originColumns: any[]) => {
- let maxLevel = 1
- const traverse = (column: any, parent?: any) => {
- if (parent) {
- column._level = parent._level + 1
- if (maxLevel < column._level) {
- maxLevel = column._level
- }
- }
- if (column.childNodes && column.childNodes.length) {
- let colSpan = 0
- column.childNodes.forEach((subColumn: any) => {
- traverse(subColumn, column)
- colSpan += subColumn._colSpan
- })
- column._colSpan = colSpan
- } else {
- column._colSpan = 1
- }
- }
- originColumns.forEach((column) => {
- column._level = 1
- traverse(column)
- })
- const rows: any[] = []
- for (let i = 0; i < maxLevel; i++) {
- rows.push([])
- }
- const allColumns = getConvertColumns(originColumns)
- allColumns.forEach((column) => {
- if (column.childNodes && column.childNodes.length) {
- column._rowSpan = 1
- } else {
- column._rowSpan = maxLevel - column._level + 1
- }
- rows[column._level - 1].push(column)
- })
- return rows
- }
- export default {
- methods: {
- /**
- * 导出文件,支持 csv/html/xml/txt
- * 如果是树表格,则默认是导出所有节点
- * 如果是启用了虚拟滚动,则只能导出数据源,可以配合 dataFilterMethod 函数转换数据
- * @param {Object} options 参数
- */
- _exportData (options?: VxeTablePropTypes.ExportConfig) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const props = $xeTable
- const reactData = $xeTable as unknown as TableReactData
- const internalData = $xeTable as unknown as TableInternalData
- const $xeGrid = $xeTable.$xeGrid
- const $xeGantt = $xeTable.$xeGantt
- const $xeGGWrapper = $xeGrid || $xeGantt
- const { treeConfig, showHeader, showFooter } = props
- const { isGroup } = reactData
- const { tableFullColumn, afterFullData, afterTreeFullData, collectColumn, mergeBodyList, mergeFooterList } = internalData
- const exportOpts = $xeTable.computeExportOpts
- const treeOpts = $xeTable.computeTreeOpts
- const proxyOpts = $xeGGWrapper ? $xeGGWrapper.computeProxyOpts : {}
- const hasMerge = !!(mergeBodyList.length || mergeFooterList.length)
- const opts = Object.assign({
- message: true,
- isHeader: showHeader,
- isTitle: showHeader,
- isFooter: showFooter,
- isColgroup: isGroup,
- isMerge: hasMerge,
- useStyle: true,
- current: 'current',
- modes: (proxyOpts.ajax && proxyOpts.ajax.queryAll ? ['all'] : []).concat(['current', 'selected', 'empty']),
- download: true,
- type: 'csv'
- // filename: '',
- // sheetName: '',
- // original: false,
- // isAllExpand: false,
- // data: null,
- // remote: false,
- // dataFilterMethod: null,
- // footerFilterMethod: null,
- // exportMethod: null,
- // columnFilterMethod: null,
- // beforeExportMethod: null,
- // afterExportMethod: null
- }, exportOpts, options)
- let { filename, sheetName, type, mode, columns, original, columnFilterMethod, beforeExportMethod, includeFields, excludeFields } = opts
- let groups: any[] = []
- const selectRecords = $xeTable.getCheckboxRecords()
- if (!mode) {
- mode = selectRecords.length ? 'selected' : 'current'
- }
- let isCustomCol = false
- let customCols = []
- if (columns && columns.length) {
- isCustomCol = true
- customCols = columns
- } else {
- customCols = XEUtils.searchTree(collectColumn, column => {
- const isColGroup = column.children && column.children.length > 0
- let isChecked = false
- if (columns && columns.length) {
- isChecked = handleFilterColumns(opts, column, columns)
- } else if (excludeFields || includeFields) {
- isChecked = handleFilterFields(opts, column, includeFields, excludeFields)
- } else {
- isChecked = column.visible && (isColGroup || defaultFilterExportColumn(column))
- }
- return isChecked
- }, { children: 'children', mapChildren: 'childNodes', original: true })
- }
- const handleOptions: VxeTablePropTypes.ExportHandleOptions = Object.assign({ } as { data: any[], colgroups: any[], columns: any[] }, opts, { filename: '', sheetName: '' })
- // 如果设置源数据,则默认导出设置了字段的列
- if (!isCustomCol && !columnFilterMethod) {
- columnFilterMethod = ({ column }) => {
- if (excludeFields) {
- if (XEUtils.includes(excludeFields, column.field)) {
- return false
- }
- }
- if (includeFields) {
- if (XEUtils.includes(includeFields, column.field)) {
- return true
- }
- return false
- }
- return original ? !!column.field : defaultFilterExportColumn(column)
- }
- handleOptions.columnFilterMethod = columnFilterMethod
- }
- if (customCols) {
- handleOptions._isCustomColumn = true
- groups = XEUtils.searchTree(
- XEUtils.mapTree(customCols, (item) => {
- let targetColumn
- if (item) {
- if (isColumnInfo(item)) {
- targetColumn = item
- } else if (XEUtils.isString(item)) {
- targetColumn = $xeTable.getColumnByField(item)
- } else {
- const colid = item.id || item.colId
- const type = item.type
- const field = item.field
- if (colid) {
- targetColumn = $xeTable.getColumnById(colid)
- } else if (field && type) {
- targetColumn = tableFullColumn.find((column: VxeTableDefines.ColumnInfo) => column.field === field && column.type === type)
- } else if (field) {
- targetColumn = $xeTable.getColumnByField(field)
- } else if (type) {
- targetColumn = tableFullColumn.find((column: VxeTableDefines.ColumnInfo) => column.type === type)
- }
- }
- return targetColumn || {}
- }
- }, {
- children: 'childNodes',
- mapChildren: '_children'
- }),
- (column, index) => isColumnInfo(column) && (!columnFilterMethod || columnFilterMethod({ $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt, column: column as any, $columnIndex: index })),
- {
- children: '_children',
- mapChildren: 'childNodes',
- original: true
- }
- )
- } else {
- 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 })
- }
- // 获取所有列
- const cols: VxeTableDefines.ColumnInfo[] = []
- XEUtils.eachTree(groups, column => {
- const isColGroup = column.children && column.children.length
- if (!isColGroup) {
- cols.push(column)
- }
- }, { children: 'childNodes' })
- // 构建分组层级
- handleOptions.columns = cols
- handleOptions.colgroups = convertToRows(groups)
- if (filename) {
- if (XEUtils.isFunction(filename)) {
- handleOptions.filename = filename({
- options: opts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- } else {
- handleOptions.filename = `${filename}`
- }
- }
- if (!handleOptions.filename) {
- handleOptions.filename = getI18n(handleOptions.original ? 'vxe.table.expOriginFilename' : 'vxe.table.expFilename', [XEUtils.toDateString(Date.now(), 'yyyyMMddHHmmss')])
- }
- if (sheetName) {
- if (XEUtils.isFunction(sheetName)) {
- handleOptions.sheetName = sheetName({
- options: opts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- } else {
- handleOptions.sheetName = `${sheetName}`
- }
- }
- if (!handleOptions.sheetName) {
- handleOptions.sheetName = document.title || ''
- }
- // 检查类型,如果为自定义导出,则不需要校验类型
- if (!handleOptions.exportMethod && !XEUtils.includes(XEUtils.keys(exportOpts._typeMaps), type)) {
- errLog('vxe.error.notType', [type])
- if (['xlsx', 'pdf'].includes(type)) {
- warnLog('vxe.error.reqPlugin', [4, 'plugin-export-xlsx'])
- }
- const params = { status: false }
- return Promise.reject(params)
- }
- if (!handleOptions.print) {
- if (beforeExportMethod) {
- beforeExportMethod({ options: handleOptions, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt })
- }
- }
- if (!handleOptions.data) {
- handleOptions.data = []
- if (mode === 'selected') {
- if (['html', 'pdf'].indexOf(type) > -1 && treeConfig) {
- handleOptions.data = XEUtils.searchTree($xeTable.getTableData().fullData, item => $xeTable.findRowIndexOf(selectRecords, item) > -1, Object.assign({}, treeOpts, { data: '_row' }))
- } else {
- handleOptions.data = selectRecords
- }
- } else if (mode === 'all') {
- if (!$xeGGWrapper) {
- errLog('vxe.error.errProp', ['all', 'mode=current,selected'])
- }
- if ($xeGGWrapper && !handleOptions.remote) {
- const gridReactData = $xeGGWrapper as unknown as GridReactData
- const proxyOpts = $xeGGWrapper.computeProxyOpts
- const { sortData } = gridReactData
- const { beforeQueryAll, afterQueryAll, ajax = {} } = proxyOpts
- const resConfigs = proxyOpts.response || proxyOpts.props || {}
- const ajaxMethods = ajax.queryAll
- const queryAllSuccessMethods = ajax.queryAllSuccess
- const queryAllErrorMethods = ajax.queryAllError
- if (!ajaxMethods) {
- errLog('vxe.error.notFunc', ['proxy-config.ajax.queryAll'])
- }
- if (ajaxMethods) {
- const params = {
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt,
- sort: sortData.length ? sortData[0] : {} as any,
- sorts: sortData as any[],
- filters: gridReactData.filterData,
- form: gridReactData.formData,
- options: handleOptions
- }
- return Promise.resolve((beforeQueryAll || ajaxMethods)(params))
- .then(rest => {
- const listProp = resConfigs.list
- handleOptions.data = (listProp ? (XEUtils.isFunction(listProp) ? listProp({ data: rest, $table: $xeTable, $grid: $xeGrid, $gantt: $xeGantt }) : XEUtils.get(rest, listProp)) : rest) || []
- if (afterQueryAll) {
- afterQueryAll(params)
- }
- if (queryAllSuccessMethods) {
- queryAllSuccessMethods({ ...params, response: rest })
- }
- return handleExport($xeTable, handleOptions)
- })
- .catch((rest) => {
- if (queryAllErrorMethods) {
- queryAllErrorMethods({ ...params, response: rest })
- }
- })
- }
- }
- } else if (mode === 'current') {
- handleOptions.data = treeConfig ? afterTreeFullData : afterFullData
- }
- } else {
- handleOptions._isCustomData = true
- }
- return handleExport($xeTable, handleOptions)
- },
- _importByFile (file: File, options: VxeTablePropTypes.ImportConfig) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const opts = Object.assign({}, options)
- const { beforeImportMethod } = opts
- if (beforeImportMethod) {
- beforeImportMethod({ options: opts, $table: $xeTable })
- }
- return handleFileImport($xeTable, file, opts)
- },
- _importData (options?: VxeTablePropTypes.ImportConfig) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const { importOpts } = this
- const opts = Object.assign({
- types: XEUtils.keys(importOpts._typeMaps)
- // beforeImportMethod: null,
- // afterImportMethod: null
- }, importOpts, options)
- const { beforeImportMethod, afterImportMethod } = opts
- if (beforeImportMethod) {
- beforeImportMethod({ options: opts, $table: this })
- }
- return VxeUI.readFile(opts).catch(e => {
- if (afterImportMethod) {
- afterImportMethod({ status: false, options: opts, $table: $xeTable })
- }
- return Promise.reject(e)
- }).then((params) => {
- const { file } = params
- return handleFileImport($xeTable, file, opts)
- })
- },
- _saveFile (options: {
- filename: string
- type: string
- content: string | Blob
- }) {
- return VxeUI.saveFile(options)
- },
- _readFile (options?: {
- multiple?: boolean
- types?: string[]
- message?: boolean
- }) {
- return VxeUI.readFile(options)
- },
- _print (options?: VxeTablePropTypes.PrintConfig) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const $xeGrid = $xeTable.$xeGrid
- const $xeGantt = $xeTable.$xeGantt
- const printOpts = $xeTable.computePrintOpts
- const opts = Object.assign({
- original: false
- // beforePrintMethod
- }, printOpts, options, {
- type: 'html',
- download: false,
- remote: false,
- print: true
- })
- const { sheetName } = opts
- let printTitle = ''
- if (sheetName) {
- if (XEUtils.isFunction(sheetName)) {
- printTitle = sheetName({
- options: opts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- } else {
- printTitle = `${sheetName}`
- }
- }
- if (!printTitle) {
- printTitle = document.title || ''
- }
- const beforePrintMethod = opts.beforePrintMethod
- const tableHtml = opts.html || opts.content
- return new Promise((resolve, reject) => {
- if (VxeUI.print) {
- if (tableHtml) {
- resolve(
- VxeUI.print({
- title: printTitle,
- html: tableHtml,
- customStyle: opts.style,
- beforeMethod: beforePrintMethod
- ? ({ html }) => {
- return beforePrintMethod({
- html,
- content: html,
- options: opts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- }
- : undefined
- })
- )
- } else {
- resolve(
- $xeTable.exportData(opts).then(({ content }: any) => {
- return VxeUI.print({
- title: printTitle,
- html: content,
- customStyle: opts.style,
- beforeMethod: beforePrintMethod
- ? ({ html }) => {
- return beforePrintMethod({
- html,
- content: html,
- options: opts,
- $table: $xeTable,
- $grid: $xeGrid,
- $gantt: $xeGantt
- })
- }
- : undefined
- })
- })
- )
- }
- } else {
- const e = { status: false }
- reject(e)
- }
- })
- },
- _getPrintHtml (options: VxeTablePropTypes.PrintConfig) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const printOpts = $xeTable.computePrintOpts
- const opts = Object.assign({
- original: false
- // beforePrintMethod
- }, printOpts, options, {
- type: 'html',
- download: false,
- remote: false,
- print: true
- })
- return $xeTable.exportData(opts).then(({ content }: any) => {
- return {
- html: content
- }
- })
- },
- _closeImport () {
- if (VxeUI.modal) {
- return VxeUI.modal.close('VXE_IMPORT_MODAL')
- }
- return Promise.resolve()
- },
- _openImport (options?: VxeTablePropTypes.ImportConfig) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const props = $xeTable
- const reactData = $xeTable as unknown as TableReactData
- const { treeConfig, importConfig } = props
- const { initStore, importStore, importParams } = reactData
- const importOpts = $xeTable.computeImportOpts
- const defOpts = Object.assign({
- mode: 'insertTop',
- message: true,
- types: XEUtils.keys(importOpts._typeMaps),
- modes: ['insertTop', 'covering']
- }, importOpts, options)
- const types = defOpts.types || []
- const modes = defOpts.modes || []
- const isTree = !!treeConfig
- if (isTree) {
- if (defOpts.message) {
- VxeUI.modal.message({ content: getI18n('vxe.error.treeNotImp'), status: 'error' })
- }
- return
- }
- if (!importConfig) {
- errLog('vxe.error.reqProp', ['import-config'])
- }
- // 处理类型
- const typeList = types.map((value: any) => {
- return {
- value,
- label: getI18n(`vxe.export.types.${value}`)
- }
- })
- const modeList = modes.map((item: any) => {
- if (item && item.value) {
- return {
- value: item.value,
- label: item.label || item.value
- }
- }
- return {
- value: item,
- label: getI18n(`vxe.import.modes.${item}`)
- }
- })
- Object.assign(importStore, {
- file: null,
- type: '',
- filename: '',
- modeList,
- typeList,
- visible: true
- })
- Object.assign(importParams, defOpts)
- if (!modeList.some(item => item.value === importParams.mode)) {
- importParams.mode = modeList[0].value
- }
- initStore.import = true
- },
- _closeExport: handleCloseExport,
- _openExport (options: any) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const props = $xeTable
- const exportOpts = $xeTable.computeExportOpts
- const defOpts = Object.assign({
- message: true,
- types: XEUtils.keys(exportOpts._typeMaps)
- }, exportOpts, options)
- if (!props.exportConfig) {
- errLog('vxe.error.reqProp', ['export-config'])
- }
- return handleExportAndPrint($xeTable, defOpts)
- },
- _closePrint: handleCloseExport,
- _openPrint (options: any) {
- const $xeTable = this as VxeTableConstructor & VxeTablePrivateMethods
- const props = $xeTable
- const printOpts = $xeTable.computePrintOpts
- const defOpts = Object.assign({
- message: true
- }, printOpts, options)
- if (!props.printConfig) {
- errLog('vxe.error.reqProp', ['print-config'])
- }
- return handleExportAndPrint($xeTable, defOpts, true)
- }
- } as any
- } as any
|