GP12与后道,批量导出功能实现
This commit is contained in:
@@ -40,15 +40,15 @@
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport">导出当前页</el-button>
|
||||
<el-button type="success" icon="el-icon-download" size="mini" @click="handleExportAll">导出全部数据</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" :disabled="loading" @click="handleExport">导出当前页</el-button>
|
||||
<el-button type="success" icon="el-icon-download" size="mini" :disabled="loading" @click="handleExportAll">导出全部数据</el-button>
|
||||
</el-form-item>
|
||||
<!-- 添加进度条组件 -->
|
||||
<el-row v-if="exportProgress > 0 && exportProgress < 100">
|
||||
<el-col :span="4"><span>Excel导出进度:</span></el-col>
|
||||
<el-col :span="20"><el-progress :percentage="exportProgress" show-text></el-progress></el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<!-- 添加进度条组件 -->
|
||||
<el-row v-if="exportProgress > 0 && exportProgress < 100">
|
||||
<el-col :span="4"><span>Excel导出进度:</span></el-col>
|
||||
<el-col :span="20"><el-progress :percentage="exportProgress" show-text></el-progress></el-col>
|
||||
</el-row>
|
||||
<div style="width: 100%; display: flex; justify-content: flex-end">
|
||||
<pagination class="mt10" background :pageSizes="[12, 30, 60, 300]" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
</div>
|
||||
@@ -70,6 +70,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { saveAs } from 'file-saver'
|
||||
import ExcelJS from 'exceljs'
|
||||
import {
|
||||
listQcBackEndServiceStatistics,
|
||||
addQcBackEndServiceStatistics,
|
||||
@@ -198,16 +200,6 @@ export default {
|
||||
this.getList()
|
||||
},
|
||||
// 设置表合并行
|
||||
// mergeTable(num) {
|
||||
// this.mergeCells = []
|
||||
// const count = this.mergeColunmNumber - this.hiddenCells.length
|
||||
// for (let i = 0; i < this.dataList.length; i += num) {
|
||||
// for (let j = 0; j < count; j++) {
|
||||
// this.mergeCells.push({ row: i, col: j, rowspan: num, colspan: 0 })
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// 设置表合并行
|
||||
mergeTable(num) {
|
||||
const mergedSet = new Set()
|
||||
this.mergeCells = []
|
||||
@@ -412,45 +404,117 @@ export default {
|
||||
},
|
||||
// 计算合并单元格信息的方法
|
||||
calculateMergeCells(allData) {
|
||||
// const mergedSet = new Set()
|
||||
// const mergeCells = []
|
||||
// const count = this.mergeColunmNumber - this.hiddenCells.length
|
||||
|
||||
// for (let i = 0; i < allData.length; i += 3) {
|
||||
// for (let j = 0; j < count; j++) {
|
||||
// const rowspan = Math.min(3, allData.length - i)
|
||||
// const endRow = i + rowspan - 1
|
||||
// const endCol = j
|
||||
// // 生成唯一标识
|
||||
// const mergeKey = `${i}-${j}-${endRow}-${endCol}`
|
||||
|
||||
// if (!mergedSet.has(mergeKey)) {
|
||||
// mergeCells.push({ row: i, col: j, rowspan, colspan: 0 })
|
||||
// //this.mergeCells.push({ row: i, col: j, rowspan, colspan: 0 })
|
||||
// mergedSet.add(mergeKey)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
const mergedSet = new Set()
|
||||
const mergeCells = []
|
||||
const count = this.mergeColunmNumber - this.hiddenCells.length
|
||||
// 从第 1 列合并到第 19 列
|
||||
const startCol = 1
|
||||
const endCol = 19
|
||||
|
||||
for (let i = 0; i < allData.length; i += 3) {
|
||||
for (let j = 0; j < count; j++) {
|
||||
const rowspan = Math.min(3, allData.length - i)
|
||||
const endRow = i + rowspan - 1
|
||||
const endCol = j
|
||||
const rowspan = Math.min(3, allData.length - i)
|
||||
const endRow = i + rowspan - 1
|
||||
|
||||
for (let j = startCol; j <= endCol; j++) {
|
||||
// 生成唯一标识
|
||||
const mergeKey = `${i}-${j}-${endRow}-${endCol}`
|
||||
const mergeKey = `${i}-${j}-${endRow}-${j}`
|
||||
|
||||
if (!mergedSet.has(mergeKey)) {
|
||||
mergeCells.push({ row: i, col: j, rowspan, colspan: 0 })
|
||||
// ExcelJS 行和列从 1 开始计数,表头占 1 行
|
||||
mergeCells.push({ startRow: i + 2, startCol: j, endRow: endRow + 2, endCol: j })
|
||||
mergedSet.add(mergeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergeCells
|
||||
},
|
||||
async generateExcel(allData, allMergeCells) {
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
const worksheet = workbook.addWorksheet('后道质量报告')
|
||||
|
||||
// 构建表头,需根据实际情况调整
|
||||
const header = [
|
||||
'工单号',
|
||||
'零件号',
|
||||
'零件描述',
|
||||
'规格',
|
||||
'颜色',
|
||||
'站点',
|
||||
'班组',
|
||||
'投入数',
|
||||
'合格数',
|
||||
'合格率',
|
||||
'抛光数',
|
||||
'打磨数',
|
||||
'报废数',
|
||||
'是否一次合格',
|
||||
'是否返工件',
|
||||
'是否抛光件',
|
||||
'是否其他件',
|
||||
'开始时间',
|
||||
'结束时间',
|
||||
]
|
||||
const headerRow = worksheet.addRow(header)
|
||||
headerRow.eachCell((cell) => {
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FF2D3D51' },
|
||||
}
|
||||
cell.font = { color: { argb: 'FFFFFFFF' }, size: 16 }
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
})
|
||||
|
||||
// 添加数据
|
||||
allData.forEach((rowData) => {
|
||||
const rowValues = [
|
||||
rowData.workOrder,
|
||||
rowData.partNumber,
|
||||
rowData.description,
|
||||
rowData.specification,
|
||||
rowData.color,
|
||||
rowData.siteNo,
|
||||
rowData.team,
|
||||
rowData.requireNumber,
|
||||
rowData.qualifiedNumber,
|
||||
rowData.qualifiedRate,
|
||||
rowData.polishNumber,
|
||||
rowData.totalDamoNumber,
|
||||
rowData.totalBaofeiNumber,
|
||||
rowData.isOnetime === 1 ? '是' : '否',
|
||||
rowData.isBack === 1 ? '是' : '否',
|
||||
rowData.isPolish === 1 ? '是' : '否',
|
||||
rowData.isOut === 1 ? '是' : '否',
|
||||
rowData.startTime,
|
||||
rowData.endTime,
|
||||
]
|
||||
worksheet.addRow(rowValues)
|
||||
})
|
||||
|
||||
// 应用合并单元格
|
||||
allMergeCells.forEach((merge) => {
|
||||
worksheet.mergeCells(merge.startRow, merge.startCol, merge.endRow, merge.endCol)
|
||||
})
|
||||
|
||||
// 设置单元格样式
|
||||
worksheet.eachRow((row) => {
|
||||
row.eachCell((cell) => {
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
cell.font = { size: 14, bold: true }
|
||||
})
|
||||
})
|
||||
|
||||
return workbook
|
||||
},
|
||||
async handleExportAll() {
|
||||
this.loading = true
|
||||
this.exportProgress = 0
|
||||
@@ -471,18 +535,10 @@ export default {
|
||||
// 更新进度
|
||||
this.exportProgress = Math.round((page / totalPages) * 100)
|
||||
}
|
||||
|
||||
// 计算全部数据的合并单元格信息
|
||||
const allMergeCells = this.calculateMergeCells(allData)
|
||||
//await this.calculateMergeCells(allData)
|
||||
//this.mergeCells = []
|
||||
//console.log('allMergeCells', allMergeCells)
|
||||
console.log('mergeCells', allData)
|
||||
// 调用子组件的导出方法,传递全部数据和合并单元格信息
|
||||
this.$refs.xTable.exportAllData(allData, allMergeCells)
|
||||
// 调用子组件导出全部数据方法
|
||||
this.$refs.xTable.exportAllData(allData)
|
||||
this.exportProgress = 100
|
||||
} catch (error) {
|
||||
this.loading = false
|
||||
console.error('导出全部数据失败:', error)
|
||||
} finally {
|
||||
this.loading = false
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { saveAs } from 'file-saver'
|
||||
import ExcelJS from 'exceljs'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
dataList: {
|
||||
@@ -99,44 +102,18 @@ export default {
|
||||
mode: 'current',
|
||||
message: true,
|
||||
sheetMethod({ options, worksheet }) {
|
||||
const dataLength = options.data.length
|
||||
const columnCount = options.columns.length
|
||||
const uniqueMergeCells = []
|
||||
const mergedSet = new Set()
|
||||
if (options.mergeCells && options.mergeCells.length) {
|
||||
options.mergeCells.forEach((merge) => {
|
||||
console.log('merge', merge)
|
||||
|
||||
// 重新生成每三行合并的配置
|
||||
for (let i = 0; i < dataLength; i += 3) {
|
||||
const rowspan = Math.min(3, dataLength - i)
|
||||
for (let j = 0; j < columnCount; j++) {
|
||||
const startRow = i + 1
|
||||
const startCol = j + 1
|
||||
const endRow = startRow + rowspan - 1
|
||||
const endCol = startCol
|
||||
|
||||
// 生成唯一标识
|
||||
const key = `${startRow}-${startCol}-${endRow}-${endCol}`
|
||||
|
||||
if (!mergedSet.has(key)) {
|
||||
uniqueMergeCells.push({
|
||||
startRow,
|
||||
startCol,
|
||||
endRow,
|
||||
endCol,
|
||||
})
|
||||
mergedSet.add(key)
|
||||
}
|
||||
}
|
||||
worksheet.mergeCells(
|
||||
merge.startRow, // 起始行(从1开始)
|
||||
merge.startCol, // 起始列(从1开始)
|
||||
merge.endRow, // 结束行
|
||||
merge.endCol, // 结束列
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
uniqueMergeCells.forEach((merge) => {
|
||||
console.log('worksheet:mergeCells[merge]', merge.startRow, merge.startCol, merge.endRow, merge.endCol)
|
||||
worksheet.mergeCells(
|
||||
merge.startRow, // 起始行(从 1 开始)
|
||||
merge.startCol, // 起始列(从 1 开始)
|
||||
merge.endRow, // 结束行
|
||||
merge.endCol, // 结束列
|
||||
)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -161,67 +138,28 @@ export default {
|
||||
contextMenuClickEvent({ menu, row, column }) {
|
||||
this.$emit('menu-click', { menu, row, column })
|
||||
},
|
||||
exportAllData(allData, allMergeCells) {
|
||||
try {
|
||||
const $table = this.$refs.vxeTable
|
||||
if ($table) {
|
||||
//this.setMergeCells(allMergeCells)
|
||||
this.$nextTick(() => {
|
||||
//this.setMergeCells(allMergeCells)
|
||||
$table
|
||||
.exportData({
|
||||
type: 'xlsx',
|
||||
filename: '后道质量报告_全部数据.xlsx',
|
||||
isMerge: true,
|
||||
isColgroup: true,
|
||||
useStyle: true,
|
||||
data: allData,
|
||||
mergeCells: allMergeCells,
|
||||
sheetMethod: this.exportConfig.sheetMethod,
|
||||
})
|
||||
.then(() => {
|
||||
console.log('导出全部数据成功')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('导出全部数据失败:', error)
|
||||
})
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('导出全部数据失败:', error)
|
||||
}
|
||||
},
|
||||
// allDataSheetMethod({ options, worksheet }) {
|
||||
// if (this.mergeCells && this.mergeCells.length) {
|
||||
// const uniqueMergeCells = []
|
||||
// const mergedSet = new Set()
|
||||
// this.mergeCells.forEach((merge) => {
|
||||
// const key = `${merge.row}-${merge.col}-${merge.row + merge.rowspan}-${merge.col + merge.colspan}`
|
||||
// if (!mergedSet.has(key)) {
|
||||
// uniqueMergeCells.push(merge)
|
||||
// mergedSet.add(key)
|
||||
// }
|
||||
// })
|
||||
calculateMergeCells(allData) {
|
||||
const mergedSet = new Set()
|
||||
const mergeCells = []
|
||||
// 工单信息列数,从工单号到类别共 19 列
|
||||
const workOrderColCount = 19
|
||||
|
||||
// const dataLength = options.data.length
|
||||
// const columnCount = options.columns.length
|
||||
// uniqueMergeCells.forEach((merge) => {
|
||||
// // 确保合并范围不超出数据边界
|
||||
// const endRow = Math.min(merge.row + merge.rowspan, dataLength - 1)
|
||||
// const endCol = Math.min(merge.col + merge.colspan, columnCount - 1)
|
||||
// const worksheetKey = `${merge.row + 1},${merge.col + 1},${endRow + 1},${endCol + 1}`
|
||||
// if (!mergedSet.has(worksheetKey)) {
|
||||
// worksheet.mergeCells(
|
||||
// merge.row + 1, // 起始行(从1开始)
|
||||
// merge.col + 1, // 起始列(从1开始)
|
||||
// endRow + 1, // 结束行
|
||||
// endCol + 1, // 结束列
|
||||
// )
|
||||
// mergedSet.add(worksheetKey)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
for (let i = 0; i < allData.length; i += 3) {
|
||||
const rowspan = Math.min(3, allData.length - i)
|
||||
const endRow = i + rowspan - 1
|
||||
|
||||
// 合并工单信息列
|
||||
for (let j = 1; j <= workOrderColCount; j++) {
|
||||
const mergeKey = `${i}-${j}-${endRow}-${j}`
|
||||
if (!mergedSet.has(mergeKey)) {
|
||||
// 实际数据从第 3 行开始
|
||||
mergeCells.push({ startRow: i + 3, startCol: j, endRow: endRow + 3, endCol: j })
|
||||
mergedSet.add(mergeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergeCells
|
||||
},
|
||||
handleExport() {
|
||||
const $table = this.$refs.vxeTable
|
||||
if ($table) {
|
||||
@@ -231,9 +169,8 @@ export default {
|
||||
isMerge: true,
|
||||
isColgroup: true,
|
||||
useStyle: true,
|
||||
filename: '后道质量报告.xlsx',
|
||||
// 使用已定义的合并单元格方法
|
||||
sheetMethod: this.exportConfig.sheetMethod,
|
||||
filename: '后道质量报告.xlsx', // 设置导出文件名
|
||||
//sheetMethod: this.exportConfig.sheetMethod, // 使用已定义的合并单元格方法
|
||||
})
|
||||
.then(() => {
|
||||
console.log('导出成功')
|
||||
@@ -243,6 +180,140 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
async exportAllData(allData) {
|
||||
try {
|
||||
const allMergeCells = this.calculateMergeCells(allData)
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
const worksheet = workbook.addWorksheet('后道质量报告')
|
||||
|
||||
// 生成多级表头
|
||||
// 第一级表头,根据合并规则更新内容
|
||||
const firstLevelHeader = ['工单信息', '油漆', '设备', '毛坯', '程序', '班组操作']
|
||||
const firstLevelRow = worksheet.addRow(firstLevelHeader)
|
||||
|
||||
// 定义合并区域
|
||||
const mergeRanges = [
|
||||
{ startCol: 1, endCol: 20 },
|
||||
{ startCol: 21, endCol: 26 },
|
||||
{ startCol: 27, endCol: 33 },
|
||||
{ startCol: 34, endCol: 39 },
|
||||
{ startCol: 40, endCol: 44 },
|
||||
{ startCol: 45, endCol: 50 },
|
||||
]
|
||||
|
||||
// 应用一级表头合并
|
||||
mergeRanges.forEach((range, index) => {
|
||||
worksheet.mergeCells(1, range.startCol, 1, range.endCol)
|
||||
const cell = worksheet.getCell(1, range.startCol)
|
||||
cell.value = firstLevelHeader[index]
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFE0E0E0' }, // 浅灰色背景
|
||||
}
|
||||
cell.font = { color: { argb: 'FF000000' }, size: 16, bold: true } // 黑色文字
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
})
|
||||
|
||||
// 第二级表头
|
||||
const secondLevelHeader = [
|
||||
'工单号',
|
||||
'零件号',
|
||||
'零件描述',
|
||||
'规格',
|
||||
'颜色',
|
||||
'站点',
|
||||
'班组',
|
||||
'投入数',
|
||||
'合格数',
|
||||
'合格率',
|
||||
'抛光数',
|
||||
'打磨数',
|
||||
'报废数',
|
||||
'是否一次合格',
|
||||
'是否返工件',
|
||||
'是否抛光件',
|
||||
'是否其他件',
|
||||
'开始时间',
|
||||
'结束时间',
|
||||
'类别',
|
||||
...this.groupTable.flatMap((group) => group.children.map((defect) => defect.name)),
|
||||
]
|
||||
const secondLevelRow = worksheet.addRow(secondLevelHeader)
|
||||
secondLevelRow.eachCell((cell) => {
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFE0E0E0' }, // 浅灰色背景
|
||||
}
|
||||
cell.font = { color: { argb: 'FF000000' }, size: 14, bold: true } // 黑色文字
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
})
|
||||
|
||||
// 添加数据
|
||||
allData.forEach((rowData) => {
|
||||
const rowValues = [
|
||||
rowData.workOrder,
|
||||
rowData.partNumber,
|
||||
rowData.description,
|
||||
rowData.specification,
|
||||
rowData.color,
|
||||
rowData.siteNo,
|
||||
rowData.team,
|
||||
rowData.requireNumber,
|
||||
rowData.qualifiedNumber,
|
||||
rowData.qualifiedRate,
|
||||
rowData.polishNumber,
|
||||
rowData.damoNumber,
|
||||
rowData.baofeiNumber,
|
||||
rowData.isOnetime === 1 ? '是' : '否',
|
||||
rowData.isBack === 1 ? '是' : '否',
|
||||
rowData.isPolish === 1 ? '是' : '否',
|
||||
rowData.isOut === 1 ? '是' : '否',
|
||||
rowData.startTime,
|
||||
rowData.endTime,
|
||||
rowData.groupSort === 1 ? '抛光' : rowData.groupSort === 2 ? '打磨' : '报废',
|
||||
...this.groupTable.flatMap((group) => group.children.map((defect) => rowData[defect.code])),
|
||||
]
|
||||
const row = worksheet.addRow(rowValues)
|
||||
row.eachCell((cell) => {
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
cell.font = { size: 14 }
|
||||
})
|
||||
})
|
||||
|
||||
// 应用合并单元格
|
||||
allMergeCells.forEach((merge) => {
|
||||
worksheet.mergeCells(merge.startRow, merge.startCol, merge.endRow, merge.endCol)
|
||||
const mergedCell = worksheet.getCell(merge.startRow, merge.startCol)
|
||||
mergedCell.alignment = { vertical: 'middle', horizontal: 'center' } // 合并单元格内容居中
|
||||
})
|
||||
|
||||
const buffer = await workbook.xlsx.writeBuffer()
|
||||
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||
saveAs(blob, '后道质量报告_全部数据.xlsx')
|
||||
console.log('导出全部数据成功')
|
||||
} catch (error) {
|
||||
console.error('导出全部数据失败:', error)
|
||||
}
|
||||
},
|
||||
// 从外部接收 mergeCells 数据的方法
|
||||
setMergeCells(mergeCells) {
|
||||
this.mergeCells = mergeCells
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<!-- 查询表单 -->
|
||||
<el-form :model="queryParams" size="small" label-position="right" inline ref="queryForm" :label-width="labelWidth" @submit.native.prevent>
|
||||
<el-form-item label="开始日期" prop="startTime">
|
||||
<el-date-picker v-model="queryParams.startTime" @change="selectChange" :clearable="false" type="datetime" placeholder="选择日期时间"></el-date-picker>
|
||||
<el-date-picker v-model="queryParams.startTime" :clearable="false" type="datetime" placeholder="选择日期时间"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期" prop="endTime">
|
||||
<el-date-picker v-model="queryParams.endTime" @change="selectChange" :clearable="false" type="datetime" placeholder="选择日期时间"></el-date-picker>
|
||||
<el-date-picker v-model="queryParams.endTime" :clearable="false" type="datetime" placeholder="选择日期时间"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="工单号" prop="workOrder">
|
||||
<el-input v-model="queryParams.workOrder" placeholder="请输入工单号" />
|
||||
@@ -40,10 +40,15 @@
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport">导出当前页</el-button>
|
||||
<el-button type="warning" icon="el-icon-download" size="mini" :disabled="loading" @click="handleExport">导出当前页</el-button>
|
||||
<el-button type="success" icon="el-icon-download" size="mini" :disabled="loading" @click="handleExportAll">导出全部数据</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 添加进度条组件 -->
|
||||
<el-row v-if="exportProgress > 0 && exportProgress < 100">
|
||||
<el-col :span="4"><span>Excel导出进度:</span></el-col>
|
||||
<el-col :span="20"><el-progress :percentage="exportProgress" show-text></el-progress></el-col>
|
||||
</el-row>
|
||||
<!-- 分页组件 -->
|
||||
<div style="width: 100%; display: flex; justify-content: flex-end">
|
||||
<pagination class="mt10" background :pageSizes="[12, 30, 60, 300]" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
||||
@@ -158,6 +163,7 @@ export default {
|
||||
},
|
||||
// 总记录数
|
||||
total: 0,
|
||||
exportProgress: 0, // 导出进度
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -362,6 +368,39 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
async handleExportAll() {
|
||||
this.loading = true
|
||||
this.exportProgress = 0
|
||||
try {
|
||||
// 计算总页数
|
||||
const totalPages = Math.ceil(this.total / this.queryParams.pageSize)
|
||||
const allData = []
|
||||
|
||||
// 分页获取数据
|
||||
for (let page = 1; page <= totalPages; page++) {
|
||||
const params = { ...this.queryParams, pageNum: page }
|
||||
params.startTime = this.$dayjs(this.queryParams.startTime).format()
|
||||
params.endTime = this.$dayjs(this.queryParams.endTime).format()
|
||||
const res = await GetReviseList(params)
|
||||
if (res.code === 200) {
|
||||
allData.push(...res.data.pageList)
|
||||
}
|
||||
// 更新进度
|
||||
this.exportProgress = Math.round((page / totalPages) * 100)
|
||||
}
|
||||
// 调用子组件导出全部数据方法
|
||||
this.$refs.xTable.exportAllData(allData)
|
||||
this.exportProgress = 100
|
||||
} catch (error) {
|
||||
console.error('导出全部数据失败:', error)
|
||||
} finally {
|
||||
this.loading = false
|
||||
// 导出完成或出错,隐藏进度条
|
||||
setTimeout(() => {
|
||||
this.exportProgress = 0
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { saveAs } from 'file-saver'
|
||||
import ExcelJS from 'exceljs'
|
||||
export default {
|
||||
props: {
|
||||
dataList: {
|
||||
@@ -136,6 +138,28 @@ export default {
|
||||
contextMenuClickEvent({ menu, row, column }) {
|
||||
this.$emit('menu-click', { menu, row, column })
|
||||
},
|
||||
calculateMergeCells(allData) {
|
||||
const mergedSet = new Set()
|
||||
const mergeCells = []
|
||||
// 工单信息列数,从工单号到类别共 19 列
|
||||
const workOrderColCount = 19
|
||||
|
||||
for (let i = 0; i < allData.length; i += 3) {
|
||||
const rowspan = Math.min(3, allData.length - i)
|
||||
const endRow = i + rowspan - 1
|
||||
|
||||
// 合并工单信息列
|
||||
for (let j = 1; j <= workOrderColCount; j++) {
|
||||
const mergeKey = `${i}-${j}-${endRow}-${j}`
|
||||
if (!mergedSet.has(mergeKey)) {
|
||||
// 实际数据从第 3 行开始
|
||||
mergeCells.push({ startRow: i + 3, startCol: j, endRow: endRow + 3, endCol: j })
|
||||
mergedSet.add(mergeKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergeCells
|
||||
},
|
||||
handleExport() {
|
||||
const $table = this.$refs.vxeTable
|
||||
if ($table) {
|
||||
@@ -156,6 +180,144 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
async exportAllData(allData) {
|
||||
try {
|
||||
const allMergeCells = this.calculateMergeCells(allData)
|
||||
const workbook = new ExcelJS.Workbook()
|
||||
const worksheet = workbook.addWorksheet('GP12质量报告')
|
||||
|
||||
// 生成多级表头
|
||||
// 第一级表头,根据合并规则更新内容
|
||||
const firstLevelHeader = ['工单信息', '油漆', '设备', '毛坯', '程序', '班组操作']
|
||||
const firstLevelRow = worksheet.addRow(firstLevelHeader)
|
||||
|
||||
// 定义合并区域
|
||||
const mergeRanges = [
|
||||
{ startCol: 1, endCol: 20 },
|
||||
{ startCol: 21, endCol: 26 },
|
||||
{ startCol: 27, endCol: 33 },
|
||||
{ startCol: 34, endCol: 39 },
|
||||
{ startCol: 40, endCol: 44 },
|
||||
{ startCol: 45, endCol: 51 },
|
||||
]
|
||||
|
||||
// 应用一级表头合并
|
||||
mergeRanges.forEach((range, index) => {
|
||||
worksheet.mergeCells(1, range.startCol, 1, range.endCol)
|
||||
const cell = worksheet.getCell(1, range.startCol)
|
||||
cell.value = firstLevelHeader[index]
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFE0E0E0' }, // 浅灰色背景
|
||||
}
|
||||
cell.font = { color: { argb: 'FF000000' }, size: 16, bold: true } // 黑色文字
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
})
|
||||
|
||||
// 第二级表头
|
||||
const secondLevelHeader = [
|
||||
'工单号',
|
||||
'零件号',
|
||||
'零件描述',
|
||||
'规格',
|
||||
'颜色',
|
||||
'站点',
|
||||
'班组',
|
||||
'投入数',
|
||||
'合格数',
|
||||
'合格率',
|
||||
'抛光数',
|
||||
'打磨数',
|
||||
'报废数',
|
||||
'是否一次合格',
|
||||
'是否返工件',
|
||||
'是否抛光件',
|
||||
'是否其他件',
|
||||
'开始时间',
|
||||
'结束时间',
|
||||
'类别',
|
||||
...this.groupTable.flatMap((group) => group.children.map((defect) => defect.name)),
|
||||
]
|
||||
const secondLevelRow = worksheet.addRow(secondLevelHeader)
|
||||
secondLevelRow.eachCell((cell) => {
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFE0E0E0' }, // 浅灰色背景
|
||||
}
|
||||
cell.font = { color: { argb: 'FF000000' }, size: 14, bold: true } // 黑色文字
|
||||
cell.alignment = { vertical: 'middle', horizontal: 'center' }
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
})
|
||||
|
||||
// 添加数据
|
||||
allData.forEach((rowData) => {
|
||||
const rowValues = [
|
||||
rowData.workOrder,
|
||||
rowData.partNumber,
|
||||
rowData.description,
|
||||
rowData.specification,
|
||||
rowData.color,
|
||||
rowData.siteNo,
|
||||
rowData.team,
|
||||
rowData.requireNumber,
|
||||
rowData.qualifiedNumber,
|
||||
rowData.qualifiedRate,
|
||||
rowData.polishNumber,
|
||||
rowData.damoNumber,
|
||||
rowData.baofeiNumber,
|
||||
rowData.isOnetime === 1 ? '是' : '否',
|
||||
rowData.isBack === 1 ? '是' : '否',
|
||||
rowData.isPolish === 1 ? '是' : '否',
|
||||
rowData.isOut === 1 ? '是' : '否',
|
||||
rowData.startTime,
|
||||
rowData.endTime,
|
||||
rowData.groupSort === 1 ? '抛光' : rowData.groupSort === 2 ? '打磨' : '报废',
|
||||
...this.groupTable.flatMap((group) => group.children.map((defect) => rowData[defect.code])),
|
||||
]
|
||||
const row = worksheet.addRow(rowValues)
|
||||
row.eachCell((cell) => {
|
||||
cell.border = {
|
||||
top: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
left: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
bottom: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
right: { style: 'thin', color: { argb: 'FF161823' } },
|
||||
}
|
||||
cell.font = { size: 14 }
|
||||
})
|
||||
})
|
||||
|
||||
// 应用合并单元格
|
||||
allMergeCells.forEach((merge) => {
|
||||
worksheet.mergeCells(merge.startRow, merge.startCol, merge.endRow, merge.endCol)
|
||||
const mergedCell = worksheet.getCell(merge.startRow, merge.startCol)
|
||||
mergedCell.alignment = { vertical: 'middle', horizontal: 'center' } // 合并单元格内容居中
|
||||
})
|
||||
|
||||
const buffer = await workbook.xlsx.writeBuffer()
|
||||
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
|
||||
saveAs(blob, 'GP12质量报告_全部数据.xlsx')
|
||||
console.log('导出全部数据成功')
|
||||
} catch (error) {
|
||||
console.error('导出全部数据失败:', error)
|
||||
}
|
||||
},
|
||||
// 从外部接收 mergeCells 数据的方法
|
||||
setMergeCells(mergeCells) {
|
||||
this.mergeCells = mergeCells
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user