From 7e810cf016d1b637b693eeca4a4d8447083c68e2 Mon Sep 17 00:00:00 2001 From: zhouwx <1175765986@qq.com> Date: 星期四, 07 八月 2025 14:59:34 +0800 Subject: [PATCH] 修改 --- src/views/work/qualityInfo/infrastructureMng/maintainPlan/index.vue | 549 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 549 insertions(+), 0 deletions(-) diff --git a/src/views/work/qualityInfo/infrastructureMng/maintainPlan/index.vue b/src/views/work/qualityInfo/infrastructureMng/maintainPlan/index.vue new file mode 100644 index 0000000..674d657 --- /dev/null +++ b/src/views/work/qualityInfo/infrastructureMng/maintainPlan/index.vue @@ -0,0 +1,549 @@ +<template> + <div class="app-container"> + <div style="display: flex;justify-content: space-between"> + <el-form :inline="true" style="display: flex;align-items: center;flex-wrap: wrap;" > + <el-form-item> + <el-button + type="primary" + plain + icon="Plus" + @click="openDialog('add',{})" + >新增</el-button> + </el-form-item> + <el-form-item v-if="isAdmin" label="企业:" > + <el-select v-model="data.queryParams.companyId" placeholder="请选择" clearable> + <el-option + v-for="item in companyList" + :key="item.id" + :label="item.name" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> + <el-form-item v-if="isAdmin" label="年份:"> + <el-date-picker + v-model="data.queryParams.year" + type="year" + value-format="YYYY" + placeholder="请选择年份" + /> + </el-form-item> + <el-form-item > + <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button> + <el-button v-if="isAdmin" type="primary" plain @click="reset">重置</el-button> +<!-- <el-button type="primary">导出</el-button>--> + </el-form-item> + </el-form> + </div> + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true"> + <el-table-column type="index" label="序号"></el-table-column> + <el-table-column prop="name" align="center" label="名称"></el-table-column> + <el-table-column prop="year" align="center" label="年份"></el-table-column> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button link type="primary" @click="openDialog('view',scope.row)">查看</el-button> + <el-button link type="primary" @click="openDialog('edit',scope.row)">编辑</el-button> + <el-button link type="primary" @click="downloadFile(scope.row)">导出</el-button> + <el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + + <edit-dialog ref="dialogRef" @getList=getList></edit-dialog> + </div> +</template> + +<script setup> +import {getCurrentInstance, onMounted, onUnmounted, reactive, ref, toRefs} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {delCompany, getCompany} from "@/api/onlineEducation/company"; +import Cookies from "js-cookie"; +import editDialog from './components/editDialog.vue' +import useUserStore from "@/store/modules/user"; +import { utils, writeFile } from 'xlsx-js-style'; +import {generateWordDocument} from "@/utils/exportWord"; +import { + delMaintenancePlan, + getMaintenanceEvaluateDetail, + getMaintenancePlanDetail, + getMaintenancePlanList +} from "@/api/infrastructureMng/ledger"; + + +const userStore = useUserStore() +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const dialogRef = ref(); +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + companyId: null + }, + total: 0, + dataList: [], + companyList: [], + expertData: [], + isAdmin: false +}); +const fields = ref({ + '序号':'index', + '名称型号':'username', + '部门':'idCard', + '责任人/使用人':'entryTime', + '编号':'deptName', + '使用地点':'duty', + '使用情况':'phone' +}); +const { queryParams, total, dataList,companyList, isAdmin, expertData } = toRefs(data); +const userInfo = ref() +onMounted(async ()=>{ + if(userStore.roles.includes('admin')){ + data.isAdmin = true + await getCompanyList() + }else{ + data.isAdmin = false + data.queryParams.companyId = userStore.companyId + } + await getList() +}) + +onUnmounted(()=>{ + +}) + +const getList = async () => { + loading.value = true + const res = await getMaintenancePlanList(data.queryParams) + if(res.code == 200){ + data.dataList = res.data.list || [] + data.total = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false +} + +const getCompanyList = async ()=>{ + const queryParams = { + pageNum: 1, + pageSize: 999 + } + const res = await getCompany(queryParams) + if (res.code == 200) { + data.companyList = res.data.list?res.data.list:[] + // data.queryParams.companyId = data.companyList[0].id + } else { + ElMessage.warning(res.message) + } +} + +// const downloadFile = async (val)=>{ +// const res = await getMaintenancePlanDetail({id: val.id}) +// if(res.code == 200){ +// if(res.data){ +// let tableData = res.data +// tableData.content = res.data.caluseNum.split('、').map((i,index)=>i + res.data.caluseContent.split(';\n')[index]).join('\n') +// tableData.interPeople = res.data.internalAuditCheckPeople.map(i=>i.auditUserName) +// try { +// generateWordDocument('/interCheck.docx', tableData, tableData.deptName +'内审检查表.docx'); +// } catch (error){ +// ElMessage({ +// type: 'warning', +// message: '导出失败' +// }); +// } +// }else{ +// ElMessage.warning('暂无数据') +// } +// }else{ +// ElMessage.warning(res.message) +// } +// } + + + +const downloadFile = async (val)=>{ + const res = await getMaintenancePlanDetail({id: val.id}) + if(res.code == 200){ + if(res.data){ + let tableData = res.data + if(data.isAdmin){ + tableData.companyName = data.companyList.find(i=>i.id == val.companyId)?.name + }else{ + tableData.companyName = userStore.companyName + } + const wb = utils.book_new(); + const wsData = []; + + // 第一行:企业名称(合并A1-T1) + wsData.push([{ v: tableData.companyName, t: 's', s: { font: { bold: true, sz: 16 }, alignment: { horizontal: 'center' } } }]); + + // 第二行:标题(合并A2-T2) + wsData.push([{ v: tableData.name || '年度基础设施维护计划', t: 's', s: { font: { bold: true, sz: 14 }, alignment: { horizontal: 'center' } } }]); + + // 第三行:表头上半部分 + const row3 = [ + // A-F列(将在下方与row4合并) + { v: '序号', t: 's', s: headerStyle }, + { v: '设备名称', t: 's', s: headerStyle }, + { v: '型号', t: 's', s: headerStyle }, + { v: '厂内编号', t: 's', s: headerStyle }, + { v: '用途', t: 's', s: headerStyle }, + { v: '使用部门', t: 's', s: headerStyle }, + // G-H列合并(维修保养) + { v: '维修保养', t: 's', s: mergedHeaderStyle }, + null, // 合并单元格占位 + // I-T列合并(年度) + { v: `${tableData.year}年度`, t: 's', s: mergedHeaderStyle }, + ...Array(11).fill(null) // 合并单元格占位 + ]; + + // 第四行:表头下半部分 + const row4 = [ + // A-F列留空(与row3合并) + ...Array(6).fill(null), + // G列:项目 + { v: '项目', t: 's', s: subHeaderStyle }, + // H列:频度 + { v: '频度', t: 's', s: subHeaderStyle }, + // I-T列:月份 + { v: '一月', t: 's', s: subHeaderStyle }, + { v: '二月', t: 's', s: subHeaderStyle }, + { v: '三月', t: 's', s: subHeaderStyle }, + { v: '四月', t: 's', s: subHeaderStyle }, + { v: '五月', t: 's', s: subHeaderStyle }, + { v: '六月', t: 's', s: subHeaderStyle }, + { v: '七月', t: 's', s: subHeaderStyle }, + { v: '八月', t: 's', s: subHeaderStyle }, + { v: '九月', t: 's', s: subHeaderStyle }, + { v: '十月', t: 's', s: subHeaderStyle }, + { v: '十一月', t: 's', s: subHeaderStyle }, + { v: '十二月', t: 's', s: subHeaderStyle } + ]; + + // 添加表头行 + wsData.push(row3); + wsData.push(row4); + + // 添加数据行 + tableData.annualMaintenanceDeviceList.forEach((device, deviceIndex) => { + const rowBase = 4 + deviceIndex * 3; // 计算起始行号 + + // 获取三种类型的维护数据 + const maintenanceTypes = device.annualMaintenanceDeviceTypeList || []; + const dailyData = maintenanceTypes.find(item => item.projectType === 1) || {}; + const level1Data = maintenanceTypes.find(item => item.projectType === 2) || {}; + const level2Data = maintenanceTypes.find(item => item.projectType === 3) || {}; + + // 主数据行(日常例行点检) + const mainRow = [ + { v: deviceIndex + 1, t: 'n', s: dataStyle }, // A列:序号 + { v: device.deviceName || '', t: 's', s: dataStyle }, // B列:设备名称 + { v: device.model || '', t: 's', s: dataStyle }, // C列:型号 + { v: device.factoryNumber || '', t: 's', s: dataStyle }, // D列:厂内编号 + { v: device.purpose || '', t: 's', s: dataStyle }, // E列:用途 + { v: device.deptName || '', t: 's', s: dataStyle }, // F列:使用部门 + { v: '日常例行点检', t: 's', s: subDataStyle }, // G列 + { v: getFrequencyText(dailyData.frequency), t: 's', s: subDataStyle }, // H列 + // I-T列:月份数据(日常例行点检) + { v: dailyData.jan || '', t: 's', s: monthStyle }, + { v: dailyData.feb || '', t: 's', s: monthStyle }, + { v: dailyData.mar || '', t: 's', s: monthStyle }, + { v: dailyData.apr || '', t: 's', s: monthStyle }, + { v: dailyData.may || '', t: 's', s: monthStyle }, + { v: dailyData.jun || '', t: 's', s: monthStyle }, + { v: dailyData.jul || '', t: 's', s: monthStyle }, + { v: dailyData.aug || '', t: 's', s: monthStyle }, + { v: dailyData.sep || '', t: 's', s: monthStyle }, + { v: dailyData.oct || '', t: 's', s: monthStyle }, + { v: dailyData.nov || '', t: 's', s: monthStyle }, + { v: dailyData.decm || '', t: 's', s: monthStyle } + ]; + + // 一级保养行 + const subRow1 = [ + ...Array(6).fill(null), // A-F列留空(与主行合并) + { v: '一级保养', t: 's', s: subDataStyle }, // G列 + { v: getFrequencyText(level1Data.frequency), t: 's', s: subDataStyle }, // H列 + // I-T列:月份数据(一级保养) + { v: level1Data.jan || '', t: 's', s: monthStyle }, + { v: level1Data.feb || '', t: 's', s: monthStyle }, + { v: level1Data.mar || '', t: 's', s: monthStyle }, + { v: level1Data.apr || '', t: 's', s: monthStyle }, + { v: level1Data.may || '', t: 's', s: monthStyle }, + { v: level1Data.jun || '', t: 's', s: monthStyle }, + { v: level1Data.jul || '', t: 's', s: monthStyle }, + { v: level1Data.aug || '', t: 's', s: monthStyle }, + { v: level1Data.sep || '', t: 's', s: monthStyle }, + { v: level1Data.oct || '', t: 's', s: monthStyle }, + { v: level1Data.nov || '', t: 's', s: monthStyle }, + { v: level1Data.decm || '', t: 's', s: monthStyle } + ]; + // 二级保养行 + const subRow2 = [ + ...Array(6).fill(null), // A-F列留空(与主行合并) + { v: '二级保养', t: 's', s: subDataStyle }, // G列 + { v: getFrequencyText(level2Data.frequency), t: 's', s: subDataStyle }, // H列 + // I-T列:月份数据(二级保养) + { v: level2Data.jan || '', t: 's', s: monthStyle }, + { v: level2Data.feb || '', t: 's', s: monthStyle }, + { v: level2Data.mar || '', t: 's', s: monthStyle }, + { v: level2Data.apr || '', t: 's', s: monthStyle }, + { v: level2Data.may || '', t: 's', s: monthStyle }, + { v: level2Data.jun || '', t: 's', s: monthStyle }, + { v: level2Data.jul || '', t: 's', s: monthStyle }, + { v: level2Data.aug || '', t: 's', s: monthStyle }, + { v: level2Data.sep || '', t: 's', s: monthStyle }, + { v: level2Data.oct || '', t: 's', s: monthStyle }, + { v: level2Data.nov || '', t: 's', s: monthStyle }, + { v: level2Data.decm || '', t: 's', s: monthStyle } + ]; + wsData.push(mainRow); + wsData.push(subRow1); + wsData.push(subRow2); + }); + // 6. 说明行(合并A-T) + const noteRowIndex = wsData.length; + wsData.push([{ + v: "说明:" + '\n' + "1、日常例行点检项目依设备日常点检表项目进行。" + '\n' + "2、一级保养:以操作工为主,维修工辅导,按计划对设备进行检查,清洗规定部位,疏通油管,更换和清洗油管、油毡、滤油器。调整设备各配合间隙,紧固设备各固定螺,对传动件进行润滑加油。频度为每季度/次。" + '\n' + "3、二级保养:以维修工为主,对设备进行部分解体检查修理。更换或修复磨损件、清洗、换油,检查修理电器部分。频度为半年/次。" + '\n' + "4、以上计划为设备在正常使用状态进行的计划,如设备处于暂停使用时不需做相关保养。", + t: 's', + s: noteStyle + }]); + // 7. 核准/审核/做成标题行 + const approvalTitleRow = Array(20).fill({ v: '', t: 's', s: dataStyle }); + approvalTitleRow[0] = { v: '核准', t: 's', s: footerHeaderStyle }; + approvalTitleRow[7] = { v: '审核', t: 's', s: footerHeaderStyle }; + approvalTitleRow[14] = { v: '做成', t: 's', s: footerHeaderStyle }; + wsData.push(approvalTitleRow); + // 8. 人员信息行 + const approvalDataRow = Array(20).fill({ v: '', t: 's', s: dataStyle }); + approvalDataRow[0] = { v: tableData.approvalName || '', t: 's', s: footerDataStyle }; + approvalDataRow[7] = { v: tableData.processName || '', t: 's', s: footerDataStyle }; + approvalDataRow[14] = { v: tableData.finishName || '', t: 's', s: footerDataStyle }; + wsData.push(approvalDataRow); + // 9. 表单编号行 + const lastRow = wsData.length; + const noteText = "表单编号:" + tableData.number; + wsData.push([{ + v: noteText, + t: 's', + s: { + font: { sz: 11 }, + alignment: { horizontal: 'right', vertical: 'center', wrapText: true }, + + } + }]); + + const ws = utils.aoa_to_sheet(wsData); + + // 设置合并单元格 + + const merges = [ + // 第一行合并(A1-T1) + { s: { r: 0, c: 0 }, e: { r: 0, c: 19 } }, + // 第二行合并(A2-T2) + { s: { r: 1, c: 0 }, e: { r: 1, c: 19 } }, + + // A-F列在第三行和第四行合并 + ...Array.from({ length: 6 }, (_, c) => ({ + s: { r: 2, c }, e: { r: 3, c } + })), + + // 第三行的维修保养合并(G3-H3) + { s: { r: 2, c: 6 }, e: { r: 2, c: 7 } }, + // 第三行的年度合并(I3-T3) + { s: { r: 2, c: 8 }, e: { r: 2, c: 19 } }, + // 说明行合并 + { s: { r: noteRowIndex, c: 0 }, e: { r: noteRowIndex, c: 19 } }, + + // 核准/审核/做成标题合并 + { s: { r: noteRowIndex + 1, c: 0 }, e: { r: noteRowIndex + 1, c: 6 } }, + { s: { r: noteRowIndex + 1, c: 7 }, e: { r: noteRowIndex + 1, c: 13 } }, + { s: { r: noteRowIndex + 1, c: 14 }, e: { r: noteRowIndex + 1, c: 19 } }, + + // 人员信息合并 + { s: { r: noteRowIndex + 2, c: 0 }, e: { r: noteRowIndex + 2, c: 6 } }, + { s: { r: noteRowIndex + 2, c: 7 }, e: { r: noteRowIndex + 2, c: 13 } }, + { s: { r: noteRowIndex + 2, c: 14 }, e: { r: noteRowIndex + 2, c: 19 } }, + + { s: { r: lastRow, c: 0 }, e: { r: lastRow, c: 19 } } + ]; + + // 添加每个设备的三行合并 + tableData.annualMaintenanceDeviceList.forEach((_, index) => { + const rowBase = 4 + index * 3; + // A-F列在三行中合并 + for (let c = 0; c < 6; c++) { + merges.push({ s: { r: rowBase, c }, e: { r: rowBase + 2, c } }); + } + }); + + ws['!merges'] = merges; + + merges.forEach(merge => { + const { s, e } = merge; // 合并区域的起止位置 + // 设置合并区域四个边的边框 + for (let r = s.r; r <= e.r; r++) { + for (let c = s.c; c <= e.c; c++) { + const cellRef = utils.encode_cell({ r, c }); + // 保留原有样式,只覆盖边框 + ws[cellRef] = ws[cellRef] || { t: 's', v: '' }; + ws[cellRef].s = { + ...(ws[cellRef].s || {}), + border: { + top: { style: 'thin', color: { rgb: '000000' } }, + left: { style: 'thin', color: { rgb: '000000' } }, + bottom: { style: 'thin', color: { rgb: '000000' } }, + right: { style: 'thin', color: { rgb: '000000' } } + } + }; + } + } + }); + + const totalRows = wsData.length; + if (!ws['!rows']) { + ws['!rows'] = Array(totalRows).fill(null); + } + ws['!rows'][noteRowIndex] = { hpx: 100 }; + // 设置列宽 + ws['!cols'] = [ + { wch: 8 }, { wch: 15 }, { wch: 12 }, { wch: 12 }, + { wch: 12 }, { wch: 12 }, { wch: 12 }, { wch: 10 }, + ...Array(12).fill({ wch: 8 }) + ]; + + // 添加工作表到工作簿 + utils.book_append_sheet(wb, ws, '维护计划'); + + // 导出Excel文件 + writeFile(wb, `${tableData.companyName}${tableData.year}年度基础设施维护计划.xlsx`); + + + }else{ + ElMessage.warning('暂无数据') + } + }else{ + ElMessage.warning(res.message) + } +} + +// 频度文本转换 +function getFrequencyText(frequency) { + switch(frequency) { + case 1: return '工作日'; + case 2: return '1次/3月'; + case 3: return '1次/6月'; + default: return ''; + } +} + +// 样式定义 +const headerStyle = { + font: { bold: true, color: { rgb: 'FFFFFF' } }, + fill: { fgColor: { rgb: '4472C4' } }, + alignment: { horizontal: 'center', vertical: 'center' }, + border: { + top: { style: 'thin', color: { rgb: '000000' } }, + bottom: { style: 'thin', color: { rgb: '000000' } }, + left: { style: 'thin', color: { rgb: '000000' } }, + right: { style: 'thin', color: { rgb: '000000' } } + } +}; + +const mergedHeaderStyle = { + ...headerStyle, + fill: { fgColor: { rgb: '70AD47' } } +}; + +const subHeaderStyle = { + font: { bold: true }, + fill: { fgColor: { rgb: 'B4C6E7' } }, + alignment: { horizontal: 'center', vertical: 'center' }, + border: headerStyle.border +}; + +const dataStyle = { + alignment: { horizontal: 'center', vertical: 'center' }, + border: headerStyle.border +}; + +const subDataStyle = { + font: { bold: true }, + fill: { fgColor: { rgb: 'E2EFDA' } }, + alignment: { horizontal: 'center', vertical: 'center' }, + border: headerStyle.border +}; + +const monthStyle = { + alignment: { horizontal: 'center', vertical: 'center' }, + border: headerStyle.border +}; + +const noteStyle = { + font: { italic: true, sz: 11 }, + alignment: { horizontal: 'left', vertical: 'center', wrapText: true }, + border: { + top: { style: 'thin', color: { rgb: '000000' } }, + bottom: { style: 'thin', color: { rgb: '000000' } } + } +}; + +const footerHeaderStyle = { + ...headerStyle, + fill: { fgColor: { rgb: 'D9D9D9' } }, + font: { bold: true, color: { rgb: '000000' } } +}; + +const footerDataStyle = { + ...dataStyle, + font: { bold: true }, + alignment: { horizontal: 'center' } +}; + + +const openDialog = (type, value) => { + dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList); +} + +/** 重置新增的表单以及其他数据 */ +const reset= async()=> { + data.queryParams = { + pageNum: 1, + pageSize: 10, + companyId: null + } + await getCompanyList() + await getList() +} +const handleDelete = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delMaintenancePlan({id: val.id}) + if(res.code == 200){ + ElMessage.success('数据删除成功') + await getList() + }else{ + ElMessage.warning(res.message) + } + }) +} + +</script> -- Gitblit v1.9.2