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