You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.8 KiB
143 lines
4.8 KiB
import {isEmpty} from "@/utils"
|
|
import request from "@/config/request"
|
|
import {elError} from "@/utils/message"
|
|
import {download} from "@/utils/file"
|
|
|
|
/**
|
|
* 搜索表格页导出excel
|
|
* 响应头为json时进行前端导出,否则直接下载文件
|
|
*
|
|
* @param url 搜索的请求地址
|
|
* @param searchForm 搜索参数
|
|
* @param options 合并选项{column, merge},只有前端导出时才需要
|
|
* @param json2workbook
|
|
* @param exportExcelByJs
|
|
*/
|
|
export function abstractExportExcel(url, searchForm, options, json2workbook, exportExcelByJs) {
|
|
request({url, method: 'post', responseType: 'blob', data: searchForm})
|
|
.then(({headers, data}) => {
|
|
const contentType = headers['content-type']
|
|
const contentDisposition = headers['content-disposition']
|
|
const filename = window.decodeURI(contentDisposition.split('=')[1])
|
|
|
|
if (contentType.includes('json')) {
|
|
const reader = new FileReader()
|
|
reader.onload = () => {
|
|
const response = JSON.parse(reader.result)
|
|
if (response.status !== 200) return elError(response.msg)
|
|
const {column, merge} = options
|
|
const workbook = json2workbook(column, response.data, merge)
|
|
exportExcelByJs(workbook, filename)
|
|
}
|
|
reader.readAsText(data)
|
|
}
|
|
else download(data, filename)
|
|
})
|
|
.catch(e => elError(e))
|
|
}
|
|
|
|
/**
|
|
* 合并excel
|
|
* 此方法会修改原始json数据(重写序号)
|
|
*
|
|
* @param props 需要合并的字段数组,用于映射json
|
|
* @param data json数组
|
|
* @param primaryKey 该行json的唯一标识字段名
|
|
* @param orderKey 该行json的序号字段名
|
|
* @param ignoreRows 忽略的行数,默认为1(忽略表头)
|
|
* @return 包含合并信息的数组,形如['A1:A10',...]
|
|
*/
|
|
export function mergeExcel(props, data, primaryKey, orderKey, ignoreRows = 1) {
|
|
const result = [], merge = [], temp = []
|
|
|
|
props.forEach((prop, index) => {
|
|
merge[index] = prop ? [1] : undefined
|
|
temp[index] = prop ? 1 : undefined
|
|
})
|
|
|
|
//序号从1开始
|
|
let indexAfterMerge = data[0][orderKey] = 1
|
|
|
|
function compare(currentRow, lastRow, nextRow, colIndex) {
|
|
const attr = props[colIndex]
|
|
|
|
//若与上一行的primaryKey相同且属性相同,则temp对应项+1
|
|
if (currentRow[primaryKey] === lastRow[primaryKey]
|
|
&& currentRow[attr] === lastRow[attr]) {
|
|
temp[colIndex]++
|
|
//最后一行特殊处理
|
|
if (!nextRow) return merge[colIndex].push(temp[colIndex])
|
|
|
|
//若与下一行相同
|
|
if (currentRow[primaryKey] === nextRow[primaryKey]
|
|
&& currentRow[attr] === nextRow[attr]) {
|
|
merge[colIndex].push(1)
|
|
}
|
|
//否则存入
|
|
else merge[colIndex].push(temp[colIndex])
|
|
}
|
|
//否则清零
|
|
else {
|
|
temp[colIndex] = 1
|
|
merge[colIndex].push(1)
|
|
}
|
|
}
|
|
|
|
for (let i = 1; i < data.length; i++) {
|
|
const currentRow = data[i]
|
|
const lastRow = data[i - 1]
|
|
const nextRow = data[i + 1]
|
|
|
|
//重写序号
|
|
if (currentRow[primaryKey] === lastRow[primaryKey]) {
|
|
currentRow[orderKey] = lastRow[orderKey]
|
|
}
|
|
else currentRow[orderKey] = ++indexAfterMerge
|
|
if (nextRow && nextRow[primaryKey] === currentRow[primaryKey]) {
|
|
nextRow[orderKey] = currentRow[orderKey]
|
|
}
|
|
|
|
props.forEach((_, colIndex) => !isEmpty(_) && compare(currentRow, lastRow, nextRow, colIndex))
|
|
}
|
|
|
|
function mergeResultConstructor(arr, colIndex) {
|
|
const colHeader = number2excelColumnHeader(colIndex)
|
|
const startRows = ignoreRows + 1
|
|
|
|
arr.forEach((rowspan, rowIndex) => {
|
|
if (rowspan > 1) {
|
|
const start = colHeader + (startRows + rowIndex - (rowspan - 1))
|
|
const end = colHeader + (startRows + rowIndex)
|
|
result.push(`${start}:${end}`)
|
|
}
|
|
})
|
|
}
|
|
|
|
merge.forEach((arr, index) => arr && mergeResultConstructor(arr, index))
|
|
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* 生成二维数组,例如json为[{id:1,name:'x'}],结果为[[1,'x']]
|
|
*
|
|
* @param data json数组
|
|
* @param propMap 表头和字段名的映射表
|
|
*/
|
|
export function jsonArray2rowArray(data, propMap) {
|
|
return data.map(i => Object.keys(i)
|
|
.reduce((arr, key) => {
|
|
arr[propMap[key]] = i[key]
|
|
return arr
|
|
}, []))
|
|
}
|
|
|
|
//数字转excel列名
|
|
export function number2excelColumnHeader(n) {
|
|
let s = ""
|
|
while (n >= 0) {
|
|
s = String.fromCharCode(n % 26 + 65) + s
|
|
n = Math.floor(n / 26) - 1
|
|
}
|
|
return s
|
|
}
|
|
|