1 Excel 导入
1.1 插件:
import * as XLSX from 'xlsx';
1.2 Excel模板
java后端生成
模板的列名,后端国际化生成:
比如:orderDetail.skuName
-- 中文:"商品名称"
-- 英语:"Product Name"
-- 西语:"Nombre del Producto"
1.3 读取模板数据
import { useLanguageStore} from '@/store/modules/language.js';
const languageStore = useLanguageStore();
const previewData = ref([]);
const ORDER_DETAIL_COLUMN_MAPPING = {
'en': {
'Product Name': 'skuName',
'Product Barcode': 'skuCode',
},
'zh': {
'商品名称': 'skuName',
'商品条码': 'skuCode',
},
'es': {
'Nombre del Producto': 'skuName',
'Código de Barras': 'skuCode',
}
}
const columnMapping = computed(() => {
return ORDER_DETAIL_COLUMN_MAPPING[languageStore.language] || ORDER_DETAIL_COLUMN_MAPPING['zh']
})
const readExcelFile = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = (e) => {
try {
const data = new Uint8Array(e.target.result)
const workbook = XLSX.read(data, { type: 'array' })
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
const jsonData = XLSX.utils.sheet_to_json(worksheet)
const mappedData = mapAndValidateData(jsonData)
resolve(mappedData)
} catch (error) {
reject(error)
}
}
reader.onerror = () => reject(new Error('文件读取失败'))
reader.readAsArrayBuffer(file)
})
}
const mapAndValidateData = (data) => {
if (data.length > 100) {
ElMessage.error('当前行数:' + data.length + ', 一次最多只能导入100条数据!')
return []
}
return data.map((item, index) => {
const mappedItem = {}
const errors = []
Object.keys(columnMapping.value).forEach(chineseKey => {
const englishKey = columnMapping.value[chineseKey]
if (item[chineseKey] !== undefined) {
let value = item[chineseKey]
if (typeof value === 'string') {
value = value.trim()
}
switch(englishKey) {
case 'detailQuantity':
case 'detailPrice':
case 'detailAmount':
case 'detailDiscountRate':
case 'detailTaxRate':
if (value !== '' && value !== null && value !== undefined) {
const numValue = parseFloat(value)
if (!isNaN(numValue)) {
mappedItem[englishKey] = numValue
} else {
errors.push(`${chineseKey}格式错误`)
}
} else {
mappedItem[englishKey] = 0
}
break
default:
mappedItem[englishKey] = value
}
} else {
if (['skuName', 'skuCode', 'unitCode', 'detailPrice', 'detailTaxRate'].includes(englishKey)) {
errors.push(`${chineseKey}不能为空`)
}
}
})
if (!mappedItem.detailDiscountRate) mappedItem.detailDiscountRate = 0
if (!mappedItem.detailTaxRate) mappedItem.detailTaxRate = 21
if (errors.length > 0) {
mappedItem.errorMessage = errors.join(',')
mappedItem._isValid = false
} else {
mappedItem._isValid = true
}
mappedItem.rowIndex = index + 1
return mappedItem
})
}
2 Excel导出
2.1 使用插件
2.2 设置导出字段
export const orderItemExportFields = [
{ key: 'skuName', i18nKey: 'order.item.skuName', width: 20, order: 1, format: 'text' },
{ key: 'skuCode', i18nKey: 'order.item.skuCode', width: 20, order: 2, format: 'text' },
{ key: 'unitCode', i18nKey: 'order.item.unitCode', width: 10, order: 3, format: 'text' },
{ key: 'detailPrice', i18nKey: 'order.item.detailPrice', width: 12, order: 4, format: 'currency' },
{ key: 'detailQuantity', i18nKey: 'order.item.detailQuantity', width: 10, order: 5, format: 'number' },
{ key: 'detailDiscountRate', i18nKey: 'order.item.detailDiscountRate', width: 10, order: 6, format: 'number' },
{ key: 'detailSalesAmount', i18nKey: 'order.item.detailSalesAmount', width: 14, order: 7, format: 'currency' },
{ key: 'locationCode', i18nKey: 'order.item.locationCode', width: 14, order: 8, format: 'currency' },
]
2.3 导出字段设置组件
// src/components/ExportColumnSelector
主要功能:
1 选择指定导出列;
2 设置导出列顺序;
3 缓存设置记录,通过模板名称记录!
鸣谢插件:
1. 设置顺序的拖拽插件: "vuedraggable";
2. 本地存储: "localforage";
2.4 导出业务逻辑封装
鸣谢插件:
1. 保存文件:"file-saver";
2. EXcel处理:"exceljs";
使用的功能:
1. excel内容排版;
2. 自定义A4打印:
2.1 分页打印设置;
2.2 页脚页码设置;
2.5 父组件使用:
<template>
......
<!-- 导出配置组件 -->
<ExportColumnSelector v-model="showSelector"
:all-fields="allFields"
:default-selected="selectedKeys"
@confirmExport="handleConfirmExport" />
......
</template>
<script>
import { useExcelExport } from '@/hooks/useExcelExport'
const { exportExcel } = useExcelExport();
......
function handleExportExcel(){
showSelector.value = true
}
// 导出
const handleConfirmExport = (selectedFields) => {
exportExcel({
fileName: form.value.orderInitNo,
sheetName: '订单明细',
fields: selectedFields,
data: form.value.salesOrderDetailList,
order: {
orderInitNo: form.value.orderInitNo,
orderConfirmDate: form.value.orderConfirmDate,
customerName: form.value.customerName,
customerNif: form.value.customerNif,
customerPhone: form.value.customerPhone,
totalSalesAmount: form.value.totalSalesAmount,
sellerMessage: form.value.sellerMessage,
buyerMessage: form.value.buyerMessage,
customerAddress: customerAddress.value,
}
})
}
......
</script>