From 19453ccbf5f0cd89450768fbcc29f7437ca8b282 Mon Sep 17 00:00:00 2001
From: 祖安之光 <11848914+light-of-zuan@user.noreply.gitee.com>
Date: 星期四, 07 八月 2025 09:16:39 +0800
Subject: [PATCH] 修改新增

---
 public/maintainRecord.docx                                                                    |    0 
 public/repairRecord.docx                                                                      |    0 
 src/views/work/qualityInfo/infrastructureMng/maintainPlan/index.vue                           |  549 ++++++++
 src/views/work/qualityInfo/infrastructureMng/repairRecord/index.vue                           |  235 +++
 src/views/work/qualityInfo/infrastructureMng/repairRecord/components/editDialog.vue           |  463 +++++++
 public/reviewRecordStatistic.docx                                                             |    0 
 src/views/work/qualityInfo/infrastructureMng/ledger/index.vue                                 |  214 +++
 src/views/work/qualityInfo/infrastructureMng/maintainRecord/components/editDialog.vue         |  553 ++++++++
 src/api/infrastructureMng/ledger.js                                                           |  163 ++
 src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/index.vue                 |  207 +++
 src/views/work/qualityInfo/infrastructureMng/ledger/components/editDialog.vue                 |  262 ++++
 src/views/work/qualityInfo/infrastructureMng/maintainPlan/components/editDialog.vue           |  541 ++++++++
 src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityManual/index.vue      |    1 
 package.json                                                                                  |    4 
 src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/components/editDialog.vue |  426 ++++++
 src/views/work/qualityInfo/infrastructureMng/maintainRecord/index.vue                         |  234 +++
 16 files changed, 3,850 insertions(+), 2 deletions(-)

diff --git a/package.json b/package.json
index 2f30671..fcb5339 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,9 @@
     "vue-router": "4.1.4",
     "vue3-json-excel": "^1.0.10-alpha",
     "vue3-tree-org": "^4.2.2",
-    "wangeditor5-for-vue3": "^0.1.0"
+    "wangeditor5-for-vue3": "^0.1.0",
+    "xlsx": "^0.18.5",
+    "xlsx-js-style": "^1.2.0"
   },
   "devDependencies": {
     "@vitejs/plugin-vue": "3.1.0",
diff --git a/public/maintainRecord.docx b/public/maintainRecord.docx
new file mode 100644
index 0000000..463f778
--- /dev/null
+++ b/public/maintainRecord.docx
Binary files differ
diff --git a/public/repairRecord.docx b/public/repairRecord.docx
new file mode 100644
index 0000000..7b806d8
--- /dev/null
+++ b/public/repairRecord.docx
Binary files differ
diff --git a/public/reviewRecordStatistic.docx b/public/reviewRecordStatistic.docx
new file mode 100644
index 0000000..213e5b4
--- /dev/null
+++ b/public/reviewRecordStatistic.docx
Binary files differ
diff --git a/src/api/infrastructureMng/ledger.js b/src/api/infrastructureMng/ledger.js
new file mode 100644
index 0000000..45a1b11
--- /dev/null
+++ b/src/api/infrastructureMng/ledger.js
@@ -0,0 +1,163 @@
+import request from '@/utils/request'
+
+export function getStandingBookList(query) {
+  return request({
+    url: '/system/standingBook/selectStandingBookList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function delStandingBook(query) {
+  return request({
+    url: '/system/standingBook/delStandingBook',
+    method: 'get',
+    params: query
+  })
+}
+
+export function addStandingBook(data) {
+  return request({
+    url: '/system/standingBook/saveStandingBook',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateStandingBook(data) {
+  return request({
+    url: '/system/standingBook/updateStandingBook',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getMaintenanceRecordList(query) {
+  return request({
+    url: '/system/annualMaintenanceRecord/selectAnnualMaintenanceRecordList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function delMaintenanceRecord(query) {
+  return request({
+    url: '/system/annualMaintenanceRecord/deletedAnnualMaintenanceRecord',
+    method: 'get',
+    params: query
+  })
+}
+
+export function updateMaintenanceRecord(data) {
+  return request({
+    url: '/system/annualMaintenanceRecord/saveAnnualMaintenanceRecord',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getMaintenanceRecordDetail(query) {
+  return request({
+    url: '/system/annualMaintenanceRecord/getAnnualMaintenanceRecord',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getMaintenanceServiceList(query) {
+  return request({
+    url: '/system/annualMaintenanceService/selectAnnualMaintenanceServiceList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function delMaintenanceService(query) {
+  return request({
+    url: '/system/annualMaintenanceService/deletedAnnualMaintenanceService',
+    method: 'get',
+    params: query
+  })
+}
+
+export function updateMaintenanceService(data) {
+  return request({
+    url: '/system/annualMaintenanceService/saveAnnualMaintenanceService',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getMaintenanceServiceDetail(query) {
+  return request({
+    url: '/system/annualMaintenanceService/getAnnualMaintenanceService',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getMaintenanceEvaluateList(query) {
+  return request({
+    url: '/system/annualMaintenanceEvaluate/selectAnnualMaintenanceEvaluateList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function delMaintenanceEvaluate(query) {
+  return request({
+    url: '/system/annualMaintenanceEvaluate/deletedAnnualMaintenanceEvaluate',
+    method: 'get',
+    params: query
+  })
+}
+
+export function updateMaintenanceEvaluate(data) {
+  return request({
+    url: '/system/annualMaintenanceEvaluate/saveAnnualMaintenanceEvaluate',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getMaintenanceEvaluateDetail(query) {
+  return request({
+    url: '/system/annualMaintenanceEvaluate/getAnnualMaintenanceEvaluate',
+    method: 'get',
+    params: query
+  })
+}
+
+
+
+export function getMaintenancePlanList(query) {
+  return request({
+    url: '/system/annualMaintenance/selectAnnualMaintenanceList',
+    method: 'get',
+    params: query
+  })
+}
+
+export function delMaintenancePlan(query) {
+  return request({
+    url: '/system/annualMaintenance/deletedAnnualMaintenance',
+    method: 'get',
+    params: query
+  })
+}
+
+export function updateMaintenancePlan(data) {
+  return request({
+    url: '/system/annualMaintenance/saveAnnualMaintenance',
+    method: 'post',
+    data: data
+  })
+}
+
+export function getMaintenancePlanDetail(query) {
+  return request({
+    url: '/system/annualMaintenance/getAnnualMaintenance',
+    method: 'get',
+    params: query
+  })
+}
diff --git a/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityManual/index.vue b/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityManual/index.vue
index 53f2ae7..ea3f499 100644
--- a/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityManual/index.vue
+++ b/src/views/build/conpanyFunctionConsult/digitalFileDep/manageType/qualityManual/index.vue
@@ -236,7 +236,6 @@
     data.companyInfo.policies = res.data.companyQualityPolicies ? res.data.companyQualityPolicies[0]?.policy : []
     const duties = transToTableData(res.data.sysFunctionalDistributions,data.originDeptList)
     data.companyInfo.allDepts = duties.allDepts
-    console.log(data.companyInfo.allDepts,'all')
     data.companyInfo.clauses = duties.clauses
     data.companyInfo.temps = res.data.companyIndustryTemplates?.map((item,index)=>{
       return {
diff --git a/src/views/work/qualityInfo/infrastructureMng/ledger/components/editDialog.vue b/src/views/work/qualityInfo/infrastructureMng/ledger/components/editDialog.vue
new file mode 100644
index 0000000..720804b
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/ledger/components/editDialog.vue
@@ -0,0 +1,262 @@
+<template>
+  <div class="notice">
+    <el-dialog
+        v-model="dialogVisible"
+        :title="state.title"
+        width="50%"
+        :before-close="handleClose"
+        :close-on-press-escape="false"
+        :close-on-click-modal="false"
+    >
+      <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" >
+        <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+          <el-select v-model="state.form.companyId" placeholder="请选择" clearable @change="getDeptList" :disabled="state.title =='查看'">
+            <el-option
+                v-for="item in state.companyList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="名称型号:" prop="model">
+          <el-input v-model.trim="state.form.model"></el-input>
+        </el-form-item>
+        <el-form-item label="部门:" prop="deptId">
+          <el-select
+              clearable
+              v-model="state.form.deptId"
+              :disabled="state.title =='查看'"
+              filterable
+              placeholder="选择部门"
+              style="width: 100%"
+          >
+            <el-option
+                v-for="item in state.deptList"
+                :key="item.deptId"
+                :label="item.deptName"
+                :value="item.deptId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="责任人/使用人:" prop="personResponsible">
+          <el-select clearable v-model="state.form.personResponsible" :disabled="state.title =='查看'" filterable placeholder="责任人/使用人" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="设备类型:" prop="deviceType">
+          <el-select v-model="state.form.deviceType" :disabled="state.title =='查看'" placeholder="请选择" clearable>
+            <el-option key="1" label="生产设备" :value="1"></el-option>
+            <el-option key="2" label="办公自动化设备" :value="2"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="编号:" prop="number">
+          <el-input v-model.trim="state.form.number" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="品牌:" prop="brand">
+          <el-input v-model.trim="state.form.brand" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="密级/类型:" prop="confidentiality">
+          <el-input v-model.trim="state.form.confidentiality" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="状态:" prop="status">
+          <el-select v-model="state.form.status" :disabled="state.title =='查看'" placeholder="请选择" clearable>
+            <el-option key="1" label="完好" :value="1"></el-option>
+            <el-option key="2" label="损坏" :value="2"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="用途:" prop="purpose">
+          <el-input v-model.trim="state.form.purpose" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="使用地点:" prop="location">
+          <el-input v-model.trim="state.form.location" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="使用情况:" prop="used">
+          <el-input v-model.trim="state.form.used" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="备注:" prop="remark">
+          <el-input v-model.trim="state.form.remark" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+      </el-form>
+      <template #footer v-if="state.title !='查看'">
+        <span class="dialog-footer">
+            <el-button @click="handleClose" size="default">取 消</el-button>
+            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {Base64} from "js-base64"
+import {getToken} from "@/utils/auth";
+import {
+  addInternalAuditCheck, getInternalAuditCheckInfo,
+  updateInternalAuditCheck
+} from "@/api/innerReview/meetingReview";
+import {getDepart} from "@/api/orgStructure/depart";
+import {listUser} from "@/api/system/user";
+import {addStandingBook, updateStandingBook} from "@/api/infrastructureMng/ledger";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+
+const state = reactive({
+  title: '',
+  form: {
+    id: null,
+    model: '',
+    deptId: null,
+    personResponsible: null,
+    deviceType: null,
+    number: '',
+    brand: '',
+    confidentiality: '',
+    status: null,
+    purpose: '',
+    location: '',
+    used: '',
+    remark: '',
+    companyId: null
+  },
+  formRules:{
+    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+    deptId: [{ required: true, message: '请选择受部门', trigger: 'blur' }],
+    model: [{ required: true, message: '请填写名称型号', trigger: 'blur' }],
+    personResponsible: [{ required: true, message: '请选择责任人/使用人',  trigger: 'blur' }],
+    deviceType: [{ required: true, message: '请选择设备类型',  trigger: 'blur' }],
+    number: [{ required: true, message: '请填写编号',  trigger: 'blur' }]
+  },
+  isAdmin: false,
+  companyList: [],
+  deptList: [],
+  userList: []
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+  state.isAdmin = isAdmin
+  if(isAdmin){
+    state.companyList = companyList
+  }
+  await getUserList(companyId)
+  await getDepartList(companyId)
+  state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+  state.form.companyId = companyId
+  if(state.title == '编辑'||state.title == '查看'){
+    Object.keys(state.form).forEach(key => {
+      if (key in value) {
+        state.form[key] = value[key]
+      }
+    })
+  }
+  dialogVisible.value = true
+}
+
+
+const onSubmit = async () => {
+  const valid = await superRef.value.validate();
+  if(valid){
+    if(state.title == '新增'){
+      const {id,...data} = state.form
+      const res = await addStandingBook(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }else{
+      const res = await updateStandingBook(state.form)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }
+  }
+}
+
+const getDeptList = async ()=>{
+  state.form.deptId = null
+  state.form.personResponsible = null
+  await getDepartList(state.form.companyId)
+  await getUserList(state.form.companyId)
+}
+
+const getDepartList = async (companyId)=> {
+  const params = {
+    companyId: companyId
+  }
+  const res = await getDepart(params)
+  if(res.code == 200){
+    state.deptList = res.data
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const getUserList = async (companyId)=> {
+  const res = await listUser({pageIndex: 1,pageSize: 999, companyId: companyId})
+  if(res.code == 200){
+    state.userList = res.data.list?res.data.list:[]
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const handleClose = () => {
+  state.form = {
+    id: null,
+    model: '',
+    deptId: null,
+    personResponsible: null,
+    deviceType: null,
+    number: '',
+    brand: '',
+    confidentiality: '',
+    status: null,
+    purpose: '',
+    location: '',
+    used: '',
+    remark: '',
+    companyId: null
+  }
+  superRef.value.clearValidate();
+  superRef.value.resetFields()
+  dialogVisible.value = false;
+}
+
+defineExpose({
+  openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+  :deep(.el-form .el-form-item__label) {
+    font-size: 15px;
+  }
+  .file {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+}
+</style>
diff --git a/src/views/work/qualityInfo/infrastructureMng/ledger/index.vue b/src/views/work/qualityInfo/infrastructureMng/ledger/index.vue
new file mode 100644
index 0000000..8ed0b5c
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/ledger/index.vue
@@ -0,0 +1,214 @@
+<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 >
+          <el-button v-if="isAdmin" type="primary" @click="getList">查询</el-button>
+          <el-button v-if="isAdmin" type="primary" plain @click="reset">重置</el-button>
+          <vue3-json-excel
+              :json-data="expertData"
+              :fields="fields"
+              name="用户花名册.xls"
+              style="margin-left: 12px"
+          >
+            <el-button type="primary">导出</el-button>
+          </vue3-json-excel>
+        </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="model" align="center" label="名称型号"></el-table-column>
+      <el-table-column prop="deptName" align="center" label="部门"></el-table-column>
+      <el-table-column prop="personResponsible" align="center" label="责任人/使用人"></el-table-column>
+      <el-table-column prop="number" align="center" label="编号"></el-table-column>
+      <el-table-column prop="location" align="center" label="使用地点"></el-table-column>
+      <el-table-column prop="used" align="center" label="使用情况"></el-table-column>
+<!--      <el-table-column label="检查表" align="center">-->
+<!--        <template #default="scope">-->
+<!--          {{scope.row.deptName }}内审检查表-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+      <el-table-column label="操作" align="center">
+        <template #default="scope">
+          <el-button link type="primary" @click="openDialog('edit',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 {getStandardTemp,delStandardTemp} from "@/api/standardSys/standardSys";
+import { renderAsync } from "docx-preview";
+import {
+  delInternalAuditCheck,
+  delMeetingsList,
+  getInternalAuditCheck, getInternalAuditCheckInfo,
+  getMeetingsList
+} from "@/api/innerReview/meetingReview";
+import {generateWordDocument} from "@/utils/exportWord";
+import {delStandingBook, getStandingBookList} 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',
+  '名称型号':'model',
+  '部门':'deptName',
+  '责任人/使用人':'personResponsible',
+  '编号':'number',
+  '使用地点':'location',
+  '使用情况':'used'
+});
+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 getStandingBookList(data.queryParams)
+  if(res.code == 200){
+    data.dataList = res.data.list || []
+    data.total = res.data.total
+  }else{
+    ElMessage.warning(res.message)
+  }
+  loading.value = false
+  await getAllList()
+}
+
+const getAllList = async () => {
+  let query = {
+    pageNum: data.queryParams.pageNum,
+    pageSize: 9999,
+    companyId: data.queryParams.companyId
+  }
+  const res = await getStandingBookList(query)
+  if(res.code == 200){
+    data.expertData = res.data.list?.map((item,index) => {
+      return {
+        ...item,
+        index: index + 1
+      }
+    })
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+
+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 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 delStandingBook({id: val.id})
+        if(res.code == 200){
+          ElMessage.success('数据删除成功')
+          await getList()
+        }else{
+          ElMessage.warning(res.message)
+        }
+      })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/infrastructureMng/maintainPlan/components/editDialog.vue b/src/views/work/qualityInfo/infrastructureMng/maintainPlan/components/editDialog.vue
new file mode 100644
index 0000000..4f67770
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/maintainPlan/components/editDialog.vue
@@ -0,0 +1,541 @@
+<template>
+  <div class="notice">
+    <el-dialog
+        v-model="dialogVisible"
+        :title="state.title"
+        width="75%"
+        :before-close="handleClose"
+        :close-on-press-escape="false"
+        :close-on-click-modal="false"
+    >
+      <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="180px">
+        <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+          <el-select v-model="state.form.companyId" placeholder="请选择" :disabled="state.title =='查看'" clearable @change="getDeptList">
+            <el-option
+                v-for="item in state.companyList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="年份:" prop="year">
+              <el-date-picker
+                  v-model="state.form.year"
+                  type="year"
+                  value-format="YYYY"
+                  placeholder="请选择年份"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="编号:" prop="number">
+              <el-input v-model.trim="state.form.number" :readonly="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="年度基础设施维护计划:" prop="annualMaintenanceDeviceSaveDTOReqs">
+          <el-button
+              type="primary"
+              plain
+              icon="Plus"
+              @click="addLine"
+              style="margin-bottom: 10px"
+              v-if="state.title !=='查看'"
+          >新增</el-button>
+        </el-form-item>
+<!--        <el-table :data="state.form.annualMaintenanceDeviceSaveDTOReqs" class="customedTable" :border="true">-->
+<!--          <el-table-column label="序号" type="index" width="80" align="center">-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="设备名称" prop="deviceName" align="center">-->
+<!--            <template #default="scope">-->
+<!--              <el-input-->
+<!--                  v-model.trim="scope.row.deviceName"-->
+<!--                  size="large"-->
+<!--                  type="textarea"-->
+<!--                  style="width: 100%;"-->
+<!--                  clearable-->
+<!--              >-->
+<!--              </el-input>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="型号" prop="model" align="center">-->
+<!--            <template #default="scope">-->
+<!--              <el-input-->
+<!--                  v-model.trim="scope.row.model"-->
+<!--                  size="large"-->
+<!--                  type="textarea"-->
+<!--                  style="width: 100%;"-->
+<!--                  clearable-->
+<!--              >-->
+<!--              </el-input>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="厂内编号" prop="factoryNumber" align="center">-->
+<!--            <template #default="scope">-->
+<!--              <el-input-->
+<!--                  v-model.trim="scope.row.factoryNumber"-->
+<!--                  size="large"-->
+<!--                  type="textarea"-->
+<!--                  style="width: 100%;"-->
+<!--                  clearable-->
+<!--              >-->
+<!--              </el-input>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="用途" prop="purpose" align="center">-->
+<!--            <template #default="scope">-->
+<!--              <el-input-->
+<!--                  v-model.trim="scope.row.purpose"-->
+<!--                  size="large"-->
+<!--                  type="textarea"-->
+<!--                  style="width: 100%;"-->
+<!--                  clearable-->
+<!--              >-->
+<!--              </el-input>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="使用部门" prop="deptName" align="center">-->
+<!--            <template #default="scope">-->
+<!--              <el-input-->
+<!--                  v-model.trim="scope.row.deptName"-->
+<!--                  size="large"-->
+<!--                  type="textarea"-->
+<!--                  style="width: 100%;"-->
+<!--                  clearable-->
+<!--              >-->
+<!--              </el-input>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
+<!--          <el-table-column label="操作" align="center" width="70">-->
+<!--            <template #default="scope">-->
+<!--              <el-button link type="danger" @click="handleDelete(scope.$index)">删除</el-button>-->
+<!--            </template>-->
+<!--          </el-table-column>-->
+<!--        </el-table>-->
+        <div v-for="(device,deviceIndex) in state.form.annualMaintenanceDeviceSaveDTOReqs" :key="deviceIndex" class="device-table">
+          <table class="seven-col-table">
+            <thead>
+              <tr>
+                <th>序号</th>
+                <th>设备名称</th>
+                <th>型号</th>
+                <th>厂内编号</th>
+                <th>用途</th>
+                <th>使用部门</th>
+                <th v-if="state.title !=='查看'">操作</th>
+              </tr>
+            </thead>
+            <tbody>
+            <tr>
+              <td>{{deviceIndex + 1}}</td>
+              <td>
+                <el-input v-model.trim="device.deviceName" type="textarea" style="width: 100%;" clearable :readonly="state.title =='查看'"></el-input>
+              </td>
+              <td>
+                <el-input v-model.trim="device.model" type="textarea" style="width: 100%;" clearable :readonly="state.title =='查看'"></el-input>
+              </td>
+              <td>
+                <el-input v-model.trim="device.factoryNumber" type="textarea" style="width: 100%;" clearable :readonly="state.title =='查看'"></el-input>
+              </td>
+              <td>
+                <el-input v-model.trim="device.purpose" type="textarea" style="width: 100%;" clearable :readonly="state.title =='查看'"></el-input>
+              </td>
+              <td>
+                <el-input v-model.trim="device.deptName" type="textarea" style="width: 100%;" clearable :readonly="state.title =='查看'"></el-input>
+              </td>
+              <td v-if="state.title !=='查看'">
+                <el-button link type="danger" @click="handleDelete(deviceIndex)">删除</el-button>
+              </td>
+            </tr>
+            </tbody>
+          </table>
+          <table class="maintain-table">
+            <thead>
+            <tr>
+              <th style="width: 120px;">项目</th>
+              <th style="width: 80px;">频度</th>
+              <th v-for="(month,monthIndex) in state.monthList" :key="monthIndex">{{month.label}}</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr v-for="(line,lineIndex) in state.form.annualMaintenanceDeviceSaveDTOReqs[deviceIndex].annualMaintenanceDeviceTypes" :key="lineIndex">
+              <td>{{line.projectType == 1?'日常例行点检':line.projectType == 2?'一级保养':'二级保养'}}</td>
+              <td>{{line.frequency == 1?'工作日':line.frequency == 2?'1次/3个月':'1次/6个月'}}</td>
+              <td v-for="(month,monthIndex2) in state.monthList" :key="monthIndex2">
+                <el-input v-model.trim="line[month.value]" style="width: 100%;" clearable :readonly="state.title =='查看'"></el-input>
+              </td>
+            </tr>
+            </tbody>
+          </table>
+        </div>
+        <el-form-item label="核准:" prop="approvalId">
+          <el-select clearable v-model="state.form.approvalId" :disabled="state.title =='查看'" filterable placeholder="核准" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="审核:" prop="processId">
+          <el-select clearable v-model="state.form.processId" :disabled="state.title =='查看'" filterable placeholder="审核" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="做成:" prop="finishId">
+          <el-select clearable v-model="state.form.finishId" :disabled="state.title =='查看'" filterable placeholder="做成" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer v-if="state.title !='查看'">
+        <span class="dialog-footer">
+            <el-button @click="handleClose" size="default">取 消</el-button>
+            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {Base64} from "js-base64"
+import {getToken} from "@/utils/auth";
+import {
+  addInternalAuditCheck, getInternalAuditCheckInfo,
+  updateInternalAuditCheck
+} from "@/api/innerReview/meetingReview";
+import {getDepart} from "@/api/orgStructure/depart";
+import {listUser} from "@/api/system/user";
+import {getMaintenancePlanDetail, updateMaintenancePlan} from "@/api/infrastructureMng/ledger";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const checkList = (rule, value, callback) => {
+  if (state.form.annualMaintenanceDeviceSaveDTOReqs.length == 0) {
+    callback(new Error('维护计划不可为空'))
+  } else {
+    callback()
+  }
+}
+const state = reactive({
+  title: '',
+  form: {
+    id: null,
+    companyId: null,
+    name: '',
+    year: '',
+    number: '',
+    annualMaintenanceDeviceSaveDTOReqs: [],
+    approvalId: null,
+    approvalName: '',
+    processId: null,
+    processName: '',
+    finishId: null,
+    finishName: '',
+    delDeviceIds: []
+  },
+  oldDeviceList: [],
+  formRules:{
+    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+    year: [{ required: true, message: '请选择年份', trigger: 'blur' }],
+    number: [{ required: true, message: '请填写编号', trigger: 'blur' }],
+    approvalId: [{ required: true, message: '请选择核准人',  trigger: 'blur' }],
+    processId: [{ required: true, message: '请选择审核人',  trigger: 'blur' }],
+    finishId: [{ required: true, message: '请选择做成人',  trigger: 'blur' }],
+    annualMaintenanceDeviceSaveDTOReqs: [{ required: true, validator: checkList, trigger: 'blur' }],
+  },
+  isAdmin: false,
+  companyList: [],
+  userList: [],
+  monthList: [
+    {label: '一月',value: 'jan'},
+    {label: '二月',value: 'feb'},
+    {label: '三月',value: 'mar'},
+    {label: '四月',value: 'apr'},
+    {label: '五月',value: 'may'},
+    {label: '六月',value: 'jun'},
+    {label: '七月',value: 'jul'},
+    {label: '八月',value: 'aug'},
+    {label: '九月',value: 'sep'},
+    {label: '十月',value: 'oct'},
+    {label: '十一月',value: 'nov'},
+    {label: '十二月',value: 'decm'}
+  ]
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+  state.isAdmin = isAdmin
+  if(isAdmin){
+    state.companyList = companyList
+  }
+  await getUserList(companyId)
+  state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+  state.form.companyId = companyId
+  if(state.title == '编辑'||state.title == '查看'){
+    await getInfo(value.id)
+  }
+  dialogVisible.value = true
+}
+
+const addLine = () => {
+  const obj = {
+    id: null,
+    annualMaintenanceId: null,
+    annualMaintenanceDeviceTypes: [
+      {
+        id: null,
+        annualMaintenanceDeviceId: null,
+        projectType: 1,
+        frequency: 1,
+        jan: '',
+        feb: '',
+        mar: '',
+        apr: '',
+        may: '',
+        jun: '',
+        jul: '',
+        aug: '',
+        sep: '',
+        oct: '',
+        nov: '',
+        decm: ''
+      },
+      {
+        id: null,
+        annualMaintenanceDeviceId: null,
+        projectType: 2,
+        frequency: 2,
+        jan: '',
+        feb: '',
+        mar: '',
+        apr: '',
+        may: '',
+        jun: '',
+        jul: '',
+        aug: '',
+        sep: '',
+        oct: '',
+        nov: '',
+        decm: ''
+      },
+      {
+        id: null,
+        annualMaintenanceDeviceId: null,
+        projectType: 3,
+        frequency: 3,
+        jan: '',
+        feb: '',
+        mar: '',
+        apr: '',
+        may: '',
+        jun: '',
+        jul: '',
+        aug: '',
+        sep: '',
+        oct: '',
+        nov: '',
+        decm: ''
+      }
+    ],
+    delDeviceTypeIds: [],
+    deviceName: '',
+    model: '',
+    factoryNumber: '',
+    purpose: '',
+    deptName: ''
+  }
+  state.form.annualMaintenanceDeviceSaveDTOReqs.push(obj);
+}
+
+const handleDelete = (i) =>{
+  state.form.annualMaintenanceDeviceSaveDTOReqs = state.form.annualMaintenanceDeviceSaveDTOReqs.filter((item,index) => index != i)
+}
+
+const onSubmit = async () => {
+  const valid = await superRef.value.validate();
+  console.log(state.form,'form')
+  // return
+  if(valid){
+    const data = JSON.parse(JSON.stringify(state.form))
+    data.delDeviceIds = state.oldDeviceList.filter(i =>!data.annualMaintenanceDeviceSaveDTOReqs.some(item=>item.id == i.id)).map(i=>i.id)
+    data.approvalName = state.userList.find(i=>i.userId == data.approvalId)?.name
+    data.processName = state.userList.find(i=>i.userId == data.processId)?.name
+    data.finishName = state.userList.find(i=>i.userId == data.finishId)?.name
+    data.name = data.year + '年度基础设施维护计划'
+    if(state.title == '新增'){
+      delete data.id
+      const res = await updateMaintenancePlan(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }else{
+      const res = await updateMaintenancePlan(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }
+  }
+}
+
+const getInfo = async (id)=> {
+  const res = await getMaintenancePlanDetail({id: id})
+  if(res.code == 200){
+    Object.keys(state.form).forEach(key => {
+      if (key in res.data) {
+        state.form[key] = res.data[key]
+      }
+    })
+    state.form.annualMaintenanceDeviceSaveDTOReqs = res.data.annualMaintenanceDeviceList.map(item=>{
+      return {
+        ...item,
+        annualMaintenanceDeviceTypes: [...item.annualMaintenanceDeviceTypeList].sort((a, b) => a.projectType - b.projectType)
+      }
+    })
+    state.oldDeviceList = res.data.annualMaintenanceDeviceList
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const getDeptList = async ()=>{
+  state.form.approvalId = null
+  state.form.processId = null
+  state.form.finishId = null
+  await getUserList(state.form.companyId)
+}
+
+const getUserList = async (companyId)=> {
+  const res = await listUser({pageIndex: 1,pageSize: 999,companyId: companyId})
+  if(res.code == 200){
+    state.userList = res.data.list?res.data.list.map(item=>{
+      const user = item.id
+      const {id, ...data} = item
+      return {
+        ...data,
+        userId: user
+      }
+    }):[]
+    if(state.form.deptId){
+      state.interUserList = state.userList.filter(i=>i.deptId !== state.form.deptId)
+    }else{
+      state.interUserList = state.userList
+    }
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const handleClose = () => {
+  state.form = {
+    id: null,
+    companyId: null,
+    name: '',
+    year: '',
+    number: '',
+    annualMaintenanceDeviceSaveDTOReqs: [],
+    approvalId: null,
+    approvalName: '',
+    processId: null,
+    processName: '',
+    finishId: null,
+    finishName: '',
+    delDeviceIds: []
+  }
+  superRef.value.clearValidate();
+  superRef.value.resetFields()
+  dialogVisible.value = false;
+}
+
+defineExpose({
+  openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+  :deep(.el-form .el-form-item__label) {
+    font-size: 15px;
+  }
+  .file {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+  .device-table {
+    width: calc(100% - 170px);
+    margin-left: 170px;
+    margin-bottom: 30px;
+    padding: 5px;
+    border: 1px solid #2563eb;
+    border-radius: 5px;
+    background: #fff;
+    box-shadow: 8px 8px 15px rgba(0, 21, 41, 0.08), -8px -8px 15px #fff;
+  }
+
+  table {
+    width: 100%;
+    border-collapse: collapse;
+    margin-bottom: 4px;
+  }
+
+  th, td {
+    border: 1px solid #ebeef5;
+    padding: 0;
+    text-align: center;
+  }
+
+  th {
+    padding: 4px 0;
+    background-color: #f8f8f9;
+  }
+  .maintain-table{
+    margin-bottom: 0;
+  }
+}
+</style>
+<style lang="scss">
+.device-table {
+  .el-textarea__inner{
+    border: none !important;
+    border-color: rgba(0,0,0,0);
+    border-radius: 0;
+  }
+  .el-input__wrapper{
+    border: none !important;
+    border-color: rgba(0,0,0,0);
+    border-radius: 0;
+  }
+}
+</style>
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>
diff --git a/src/views/work/qualityInfo/infrastructureMng/maintainRecord/components/editDialog.vue b/src/views/work/qualityInfo/infrastructureMng/maintainRecord/components/editDialog.vue
new file mode 100644
index 0000000..a5e1985
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/maintainRecord/components/editDialog.vue
@@ -0,0 +1,553 @@
+<template>
+  <div class="notice">
+    <el-dialog
+        v-model="dialogVisible"
+        :title="state.title"
+        width="75%"
+        :before-close="handleClose"
+        :close-on-press-escape="false"
+        :close-on-click-modal="false"
+    >
+      <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px">
+        <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+          <el-select v-model="state.form.companyId" placeholder="请选择" :disabled="state.title =='查看'" clearable @change="getDeptList">
+            <el-option
+                v-for="item in state.companyList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-row>
+          <el-col :span="8">
+            <el-form-item label="设备名称:" prop="deviceName">
+              <el-input v-model.trim="state.form.deviceName" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="设备编号:" prop="deviceNumber">
+              <el-input v-model.trim="state.form.deviceNumber" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="表单编号:" prop="number">
+              <el-input v-model.trim="state.form.number" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-table :data="state.maintainList" :border="true" class="customedTable" :span-method="objectSpanMethod" style="margin-bottom: 30px">
+          <el-table-column label="保养内容" align="center" width="100">
+            <template #default="scope">
+              保养内容
+            </template>
+          </el-table-column>
+          <el-table-column label="标准" prop="standard" align="center">
+            <template #default="scope">
+              <p style="margin: 0;text-align: left">{{scope.row.standard}}</p>
+            </template>
+          </el-table-column>
+          <el-table-column label="保养等级" prop="level" align="center"/>
+          <el-table-column label="结论" prop="conclusion" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.conclusion"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%"
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="整改措施" prop="rectificationMeasures" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.rectificationMeasures"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%"
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-form-item label="设备保养验收结论:" prop="conclusion">
+          <el-input v-model.trim="state.form.conclusion" type="textarea" :autosize="{ minRows: 2 }" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        一级保养
+        <el-row>
+          <el-col :span="6">
+            <el-form-item label="操作工:" prop="operatorsOne">
+              <el-select clearable v-model="state.form.operatorsOne" :disabled="state.title =='查看'" value-key="userId" filterable multiple placeholder="操作工" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="日期:" prop="operateDateOne">
+              <el-date-picker
+                  v-model="state.form.operateDateOne"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择日期"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="检查:" prop="checkersOne">
+              <el-select clearable v-model="state.form.checkersOne" :disabled="state.title =='查看'" value-key="userId" filterable multiple placeholder="检查" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="日期:" prop="checkDateOne">
+              <el-date-picker
+                  v-model="state.form.checkDateOne"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择日期"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        二级保养
+        <el-row>
+          <el-col :span="6">
+            <el-form-item label="操作工:" prop="operatorsTwo">
+              <el-select clearable v-model="state.form.operatorsTwo" :disabled="state.title =='查看'" value-key="userId" filterable multiple placeholder="操作工" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="日期:" prop="operateDateTwo">
+              <el-date-picker
+                  v-model="state.form.operateDateTwo"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择日期"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="检查:" prop="checkersTwo">
+              <el-select clearable v-model="state.form.checkersTwo" :disabled="state.title =='查看'" value-key="userId" filterable multiple placeholder="检查" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="日期:" prop="checkDateTwo">
+              <el-date-picker
+                  v-model="state.form.checkDateTwo"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择日期"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+      </el-form>
+      <template #footer v-if="state.title !='查看'">
+        <span class="dialog-footer">
+            <el-button @click="handleClose" size="default">取 消</el-button>
+            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {Base64} from "js-base64"
+import {getToken} from "@/utils/auth";
+import {
+  addInternalAuditCheck, getInternalAuditCheckInfo,
+  updateInternalAuditCheck
+} from "@/api/innerReview/meetingReview";
+import {getDepart} from "@/api/orgStructure/depart";
+import {listUser} from "@/api/system/user";
+import {getMaintenanceServiceDetail, updateMaintenanceService} from "@/api/infrastructureMng/ledger";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const checkFiles = (rule, value, callback) => {
+  if (state.fileList.length == 0) {
+    callback(new Error('请上传文件'))
+  } else {
+    callback()
+  }
+}
+const state = reactive({
+  title: '',
+  form: {
+    id: null,
+    companyId: null,
+    deviceName: '',
+    deviceNumber: '',
+    number: '',
+    annualMaintenanceServiceContentList: [],
+    annualMaintenanceServiceUserList: [],
+    conclusion: '',
+    operatorsOne: [],
+    operateDateOne: '',
+    checkersOne: [],
+    checkDateOne: '',
+    operatorsTwo: [],
+    operateDateTwo: '',
+    checkersTwo: [],
+    checkDateTwo: '',
+    delServiceUserIds: []
+  },
+  oldServiceUsers: [],
+  maintainList: [
+    {
+      id: null,
+      serviceType: 1,
+      standard: '1、设备内外清洁,无黄油、油垢、锈蚀,油质符合要求。',
+      level: '一、二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 2,
+      standard: '2、根据设备情况、进行部分零件拆解、清洗、修复。对各紧固零件进行检查、修复,各部配合间隙进行适当调整。',
+      level: '一、二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 3,
+      standard: '3、清洗毛毡、油线、滤油器;清理油路、管道、加足润滑油和润滑脂,补齐各种缺欠,保持无黄袍。',
+      level: '一、二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 4,
+      standard: '4、对设备所有二操纵机构,各种挡铁、限位开关调修至灵敏可靠,将各种防尘、防屑、装置清洗修复至完整好用。',
+      level: '一、二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 5,
+      standard: '5、各润滑部位进行全部清洗,结合换油周期进行换油,油质油量符合要求。',
+      level: '二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 6,
+      standard: '6、检查设备的技术状况,调整安装水平,根据设备的使用情况进行全部或部分解体检查、清洗,调整各部分的配合精度。',
+      level: '二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 7,
+      standard: '7、修复或更换磨损部件、零件,并为下一次二保或大修做好备件资料准备。',
+      level: '二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    },{
+      id: null,
+      serviceType: 8,
+      standard: '8、零部件完整,随机附件基本齐全并保管好。',
+      level: '二级',
+      conclusion: '',
+      rectificationMeasures: ''
+    }
+  ],
+  formRules:{
+    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+    deviceName: [{ required: true, message: '请填写设备名称', trigger: 'blur' }],
+    deviceNumber: [{ required: true, message: '请填写设备编号', trigger: 'blur' }],
+    number: [{ required: true, message: '请填写表单编号', trigger: 'blur' }]
+  },
+  isAdmin: false,
+  companyList: [],
+  userList: []
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+  state.isAdmin = isAdmin
+  if(isAdmin){
+    state.companyList = companyList
+  }
+  await getUserList(companyId)
+  state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+  state.form.companyId = companyId
+  if(state.title == '编辑'||state.title == '查看'){
+    await getInfo(value.id)
+  }
+  dialogVisible.value = true
+}
+
+const objectSpanMethod = ({row, column, rowIndex, columnIndex,}) => {
+  if (columnIndex === 0) {
+    if (rowIndex === 0) {
+      return {
+        rowspan: state.maintainList.length,
+        colspan: 1
+      }
+    } else {
+      return {
+        rowspan: 0,
+        colspan: 0
+      }
+    }
+  }
+}
+
+const onSubmit = async () => {
+  const valid = await superRef.value.validate();
+  if(valid){
+    const data = JSON.parse(JSON.stringify(state.form))
+    data.operatorsOne = data.operatorsOne.map(i=>{
+      return {
+        id: i.id || null,
+        annualMaintenanceServiceId: i.annualMaintenanceServiceId || null,
+        userId: i.userId,
+        userName: i.name,
+        userType: 1,
+        checkDate: data.operateDateOne
+      }
+    })
+    data.checkersOne = data.checkersOne.map(i=>{
+      return {
+        id: i.id || null,
+        annualMaintenanceServiceId: i.annualMaintenanceServiceId || null,
+        userId: i.userId,
+        userName: i.name,
+        userType: 2,
+        checkDate: data.checkDateOne
+      }
+    })
+    data.operatorsTwo = data.operatorsTwo.map(i=>{
+      return {
+        id: i.id || null,
+        annualMaintenanceServiceId: i.annualMaintenanceServiceId || null,
+        userId: i.userId,
+        userName: i.name,
+        userType: 3,
+        checkDate: data.operateDateTwo
+      }
+    })
+    data.checkersTwo = data.checkersTwo.map(i=>{
+      return {
+        id: i.id || null,
+        annualMaintenanceServiceId: i.annualMaintenanceServiceId || null,
+        userId: i.userId,
+        userName: i.name,
+        userType: 4,
+        checkDate: data.checkDateTwo
+      }
+    })
+    data.annualMaintenanceServiceUserList = [...data.operatorsOne,...data.checkersOne,...data.operatorsTwo,...data.checkersTwo]
+    data.delServiceUserIds = state.oldServiceUsers.filter(i =>!data.annualMaintenanceServiceUserList.some(item=>item.id == i.id)).map(i=>i.id)
+    data.annualMaintenanceServiceContentList = state.maintainList.map(item=>{
+      return {
+        id: item.id,
+        serviceType: item.serviceType,
+        conclusion: item.conclusion,
+        rectificationMeasures: item.rectificationMeasures
+      }
+    })
+    delete data.operatorsOne
+    delete data.checkersOne
+    delete data.operatorsTwo
+    delete data.checkersTwo
+    delete data.operateDateOne
+    delete data.checkDateOne
+    delete data.operateDateTwo
+    delete data.checkDateTwo
+    if(state.title == '新增'){
+      delete data.id
+      const res = await updateMaintenanceService(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }else{
+      const res = await updateMaintenanceService(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }
+  }
+}
+
+const getInfo = async (id)=> {
+  const res = await getMaintenanceServiceDetail({id: id})
+  if(res.code == 200){
+    Object.keys(state.form).forEach(key => {
+      if (key in res.data) {
+        state.form[key] = res.data[key]
+      }
+    })
+    state.oldServiceUsers = state.form.annualMaintenanceServiceUserList?.map(item=>{
+      return {
+        id: item.id,
+        annualMaintenanceServiceId: item.annualMaintenanceServiceId,
+        userId: item.userId,
+        name: item.userName,
+        userType: item.userType,
+        checkDate: item.checkDate.substring(0,10)
+      }
+    })
+    state.form.operatorsOne = state.oldServiceUsers.filter(i=>i.userType == 1)
+    state.form.checkersOne = state.oldServiceUsers.filter(i=>i.userType == 2)
+    state.form.operatorsTwo = state.oldServiceUsers.filter(i=>i.userType == 3)
+    state.form.checkersTwo = state.oldServiceUsers.filter(i=>i.userType == 4)
+    state.form.operateDateOne = state.form.operatorsOne[0].checkDate || ''
+    state.form.checkDateOne = state.form.checkersOne[0].checkDate || ''
+    state.form.operateDateTwo = state.form.operatorsTwo[0].checkDate || ''
+    state.form.checkDateTwo = state.form.checkersTwo[0].checkDate || ''
+    state.maintainList = state.maintainList.map(item=>{
+      return {
+        id: state.form.annualMaintenanceServiceContentList.find(i=>i.serviceType == item.serviceType)?.id,
+        serviceType: item.serviceType,
+        standard: item.standard,
+        level: item.level,
+        conclusion: state.form.annualMaintenanceServiceContentList.find(i=>i.serviceType == item.serviceType)?.conclusion,
+        rectificationMeasures: state.form.annualMaintenanceServiceContentList.find(i=>i.serviceType == item.serviceType)?.rectificationMeasures,
+      }
+    })
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const getDeptList = async ()=>{
+  state.form.operatorsOne = []
+  state.form.checkersOne = []
+  state.form.operatorsTwo = []
+  state.form.checkersTwo = []
+  await getUserList(state.form.companyId)
+}
+
+
+const getUserList = async (companyId)=> {
+  const res = await listUser({pageIndex: 1,pageSize: 999,companyId: companyId})
+  if(res.code == 200){
+    state.userList = res.data.list?res.data.list.map(item=>{
+      const user = item.id
+      const {id, ...data} = item
+      return {
+        ...data,
+        userId: user
+      }
+    }):[]
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const handleClose = () => {
+  state.form = {
+    id: null,
+    companyId: null,
+    deviceName: '',
+    deviceNumber: '',
+    number: '',
+    annualMaintenanceServiceContentList: [],
+    annualMaintenanceServiceUserList: [],
+    conclusion: '',
+    operatorsOne: [],
+    operateDateOne: '',
+    checkersOne: [],
+    checkDateOne: '',
+    operatorsTwo: [],
+    operateDateTwo: '',
+    checkersTwo: [],
+    checkDateTwo: '',
+    delServiceUserIds: []
+  }
+  state.maintainList = state.maintainList.map(i=>{
+    return {
+      serviceType: i.serviceType,
+      standard: i.standard,
+      level: i.level,
+      conclusion: '',
+      rectificationMeasures: ''
+    }
+  })
+  superRef.value.clearValidate();
+  superRef.value.resetFields()
+  dialogVisible.value = false;
+}
+
+defineExpose({
+  openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+  :deep(.el-form .el-form-item__label) {
+    font-size: 15px;
+  }
+  .file {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+}
+</style>
+<style lang="scss">
+.customedTable{
+  .el-table__cell{
+    padding: 2px 0 !important;
+    font-size: 14px !important;
+  }
+  .cell{
+    padding: 0 2px !important;
+    font-size: 14px !important;
+  }
+}
+</style>
diff --git a/src/views/work/qualityInfo/infrastructureMng/maintainRecord/index.vue b/src/views/work/qualityInfo/infrastructureMng/maintainRecord/index.vue
new file mode 100644
index 0000000..6d70635
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/maintainRecord/index.vue
@@ -0,0 +1,234 @@
+<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 >
+          <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="deviceName" align="center" label="设备名称"></el-table-column>
+      <el-table-column prop="deviceNumber" 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 {getStandardTemp,delStandardTemp} from "@/api/standardSys/standardSys";
+import { renderAsync } from "docx-preview";
+import {
+  delInternalAuditCheck,
+  delMeetingsList,
+  getInternalAuditCheck, getInternalAuditCheckInfo,
+  getMeetingsList
+} from "@/api/innerReview/meetingReview";
+import {generateWordDocument} from "@/utils/exportWord";
+import {
+  delMaintenanceService,
+  getMaintenanceRecordDetail, getMaintenanceServiceDetail,
+  getMaintenanceServiceList
+} 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: [],
+  isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = 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 getMaintenanceServiceList(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 getMaintenanceServiceDetail({id: val.id})
+  if(res.code == 200){
+    if(res.data){
+      let tableData = res.data
+      if(Array.isArray(tableData.annualMaintenanceServiceUserList) && tableData.annualMaintenanceServiceUserList.length>0){
+        const serviceUsers = tableData.annualMaintenanceServiceUserList?.map(item=>{
+          return {
+            ...item,
+            checkDate: item.checkDate.substring(0,10)
+          }
+        })
+        tableData.operatorsOneNames = serviceUsers.filter(i=>i.userType == 1).map(i=>i.userName).join(',')
+        tableData.checkersOneNames = serviceUsers.filter(i=>i.userType == 2).map(i=>i.userName).join(',')
+        tableData.operatorsTwoNames = serviceUsers.filter(i=>i.userType == 3).map(i=>i.userName).join(',')
+        tableData.checkersTwoNames = serviceUsers.filter(i=>i.userType == 4).map(i=>i.userName).join(',')
+        tableData.operateDateOne = serviceUsers.find(i=>i.userType == 1).checkDate || ''
+        tableData.checkDateOne = serviceUsers.find(i=>i.userType == 2).checkDate || ''
+        tableData.operateDateTwo = serviceUsers.find(i=>i.userType == 3).checkDate || ''
+        tableData.checkDateTwo = serviceUsers.find(i=>i.userType == 4).checkDate || ''
+      }else{
+        tableData.operatorsOneNames = ''
+        tableData.checkersOneNames = ''
+        tableData.operatorsTwoNames = ''
+        tableData.checkersTwoNames = ''
+        tableData.operateDateOne = ''
+        tableData.checkDateOne = ''
+        tableData.operateDateTwo = ''
+        tableData.checkDateTwo = ''
+      }
+      if(data.isAdmin){
+        tableData.companyName = data.companyList.find(i=>i.id == val.companyId)?.name
+      }else{
+        tableData.companyName = userStore.companyName
+      }
+      for(let i = 0; i < 8; i++){
+        const num = Number(i) + 1
+        if(tableData.annualMaintenanceServiceContentList.find(i=>i.serviceType == num)){
+          tableData['col' + num] = tableData.annualMaintenanceServiceContentList.find(i=>i.serviceType == num).conclusion
+          tableData['act' + num] = tableData.annualMaintenanceServiceContentList.find(i=>i.serviceType == num).rectificationMeasures
+        }else{
+          tableData['col' + num] = ''
+          tableData['act' + num] = ''
+        }
+      }
+      try {
+        generateWordDocument('/maintainRecord.docx', tableData, tableData.companyName + '保养记录表.docx');
+      } catch (error){
+        ElMessage({
+          type: 'warning',
+          message: '导出失败'
+        });
+      }
+    }else{
+      ElMessage.warning('暂无数据')
+    }
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+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 delMaintenanceService({id: val.id})
+        if(res.code == 200){
+          ElMessage.success('数据删除成功')
+          await getList()
+        }else{
+          ElMessage.warning(res.message)
+        }
+      })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/infrastructureMng/repairRecord/components/editDialog.vue b/src/views/work/qualityInfo/infrastructureMng/repairRecord/components/editDialog.vue
new file mode 100644
index 0000000..b1ce2ca
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/repairRecord/components/editDialog.vue
@@ -0,0 +1,463 @@
+<template>
+  <div class="notice">
+    <el-dialog
+        v-model="dialogVisible"
+        :title="state.title"
+        width="50%"
+        :before-close="handleClose"
+        :close-on-press-escape="false"
+        :close-on-click-modal="false"
+    >
+      <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" >
+        <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+          <el-select v-model="state.form.companyId" placeholder="请选择" :disabled="state.title =='查看'" clearable @change="getDeptList">
+            <el-option
+                v-for="item in state.companyList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-row>
+          <el-col :span="8">
+            <el-form-item label="设备名称:" prop="deviceName">
+              <el-input v-model.trim="state.form.deviceName" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="设备编号:" prop="number">
+              <el-input v-model.trim="state.form.number" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="表单编号:" prop="formNumber">
+              <el-input v-model.trim="state.form.formNumber" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="故障发生日期:" prop="faultDate">
+              <el-date-picker
+                  v-model="state.form.faultDate"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择故障发生日期"
+                  :disabled="state.title =='查看'"
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="要求维修日期:" prop="repairDate">
+              <el-date-picker
+                  v-model="state.form.repairDate"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择要求维修日期"
+                  :disabled="state.title =='查看'"
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="故障现象:" prop="failurePhenomenon">
+          <el-input v-model.trim="state.form.failurePhenomenon" type="textarea" :autosize="{ minRows: 2 }" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="设施操作/管理员:" prop="maintainUsers">
+              <el-select clearable v-model="state.form.maintainUsers" :disabled="state.title =='查看'" value-key="userId" filterable multiple placeholder="设施操作/管理员" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="主管:" prop="managerId">
+              <el-select clearable v-model="state.form.managerId" :disabled="state.title =='查看'" filterable placeholder="主管" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item.userId"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="故障原因及排除方法:" prop="faultCause">
+          <el-input v-model.trim="state.form.faultCause" type="textarea" :autosize="{ minRows: 2 }" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="维修方式:" prop="maintenanceMethod">
+              <el-radio-group v-model="state.form.maintenanceMethod" :disabled="state.title =='查看'">
+                <el-radio :label="1">内部维修</el-radio>
+                <el-radio :label="2">委外维修</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="委外地点:" prop="outsourcingLocation">
+              <el-input v-model.trim="state.form.outsourcingLocation" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="维修工时:" prop="repairTime">
+              <el-input v-model.trim="state.form.repairTime" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="停机时间:" prop="downTime">
+              <el-date-picker
+                  v-model="state.form.downTime"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择停机时间"
+                  :disabled="state.title =='查看'"
+                  style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="更换材料:" prop="replaceMaterials">
+              <el-input v-model.trim="state.form.replaceMaterials" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="金额(元):" prop="money">
+              <el-input v-model.trim="state.form.money" :disabled="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="维修员:" prop="repairUsers">
+              <el-select clearable v-model="state.form.repairUsers" :disabled="state.title =='查看'" value-key="userId" filterable multiple placeholder="维修员" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="设备科主管:" prop="deviceManagerId">
+              <el-select clearable v-model="state.form.deviceManagerId" :disabled="state.title =='查看'" filterableplaceholder="设备科主管" style="width: 100%">
+                <el-option
+                    v-for="item in state.userList"
+                    :key="item.userId"
+                    :label="item.name"
+                    :value="item.userId"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="备注:" prop="remark">
+          <el-input v-model.trim="state.form.remark" type="textarea" :autosize="{ minRows: 2 }" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="设施管理部门验收确认:" prop="acceptanceConfirmation">
+          <el-input v-model.trim="state.form.acceptanceConfirmation" type="textarea" :autosize="{ minRows: 2 }" :readonly="state.title =='查看'"></el-input>
+        </el-form-item>
+        <el-form-item label="编制:" prop="establishmentId">
+          <el-select clearable v-model="state.form.establishmentId" :disabled="state.title =='查看'" filterable placeholder="编制人" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="审核:" prop="processId">
+          <el-select clearable v-model="state.form.processId" :disabled="state.title =='查看'" filterable placeholder="审核人" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="批准:" prop="approvalId">
+          <el-select clearable v-model="state.form.approvalId" :disabled="state.title =='查看'" filterable placeholder="批准人" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer v-if="state.title !='查看'">
+        <span class="dialog-footer">
+            <el-button @click="handleClose" size="default">取 消</el-button>
+            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {Base64} from "js-base64"
+import {getToken} from "@/utils/auth";
+import {
+  addInternalAuditCheck, getInternalAuditCheckInfo,
+  updateInternalAuditCheck
+} from "@/api/innerReview/meetingReview";
+import {getDepart} from "@/api/orgStructure/depart";
+import {listUser} from "@/api/system/user";
+import {getMaintenanceRecordDetail, updateMaintenanceRecord} from "@/api/infrastructureMng/ledger";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+
+const state = reactive({
+  title: '',
+  form: {
+    id: null,
+    deviceName: '',
+    number: '',
+    formNumber: '',
+    faultDate: '',
+    repairDate: '',
+    failurePhenomenon: '',
+    maintainUsers: [],
+    managerId: null,
+    managerName: '',
+    faultCause: '',
+    maintenanceMethod: null,
+    outsourcingLocation: '',
+    repairTime: '',
+    downTime: '',
+    replaceMaterials: '',
+    money: '',
+    repairUsers: [],
+    annualMaintenanceRecordUsers: [],
+    deviceManagerId: null,
+    deviceManagerName: '',
+    remark: '',
+    acceptanceConfirmation: '',
+    establishmentId: null,
+    processId: null,
+    approvalId: null,
+    companyId: null
+  },
+  formRules:{
+    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+    deviceName: [{ required: true, message: '请填写设备名称', trigger: 'blur' }],
+    number: [{ required: true, message: '请填写编号',  trigger: 'blur' }],
+    formNumber: [{ required: true, message: '请填写表单编号',  trigger: 'blur' }],
+    faultDate: [{ required: true, message: '请选择故障发生日期',  trigger: 'blur' }],
+    repairDate: [{ required: true, message: '请选择要求维修日期',  trigger: 'blur' }],
+    failurePhenomenon: [{ required: true, message: '请填写故障现象',  trigger: 'blur' }],
+    maintainUsers: [{ required: true, message: '请选择设施操作/管理员',  trigger: 'blur' }],
+    managerId: [{ required: true, message: '请选择主管',  trigger: 'blur' }],
+    faultCause: [{ required: true, message: '请填写故障原因及排除方法',  trigger: 'blur' }],
+    maintenanceMethod: [{ required: true, message: '请选择维修方式',  trigger: 'blur' }],
+    establishmentId: [{ required: true, message: '请选择编制人',  trigger: 'blur' }],
+    processId: [{ required: true, message: '请选择审核人',  trigger: 'blur' }],
+    approvalId: [{ required: true, message: '请选择批准人',  trigger: 'blur' }]
+  },
+  isAdmin: false,
+  companyList: [],
+  oldRecordUsers: [],
+  userList: []
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+  state.isAdmin = isAdmin
+  if(isAdmin){
+    state.companyList = companyList
+  }
+  await getUserList(companyId)
+  state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+  state.form.companyId = companyId
+  if(state.title == '编辑'||state.title == '查看'){
+    await getInfo(value.id)
+  }
+  dialogVisible.value = true
+}
+
+
+const onSubmit = async () => {
+  const valid = await superRef.value.validate()
+  if(valid){
+    const data = JSON.parse(JSON.stringify(state.form))
+    data.maintainUsers = data.maintainUsers.map(i=>{
+      return {
+        id: i.id || null,
+        annualMaintenanceRecordId: i.annualMaintenanceRecordId || null,
+        userId: i.userId,
+        userName: i.name,
+        userType: 1
+      }
+    })
+    data.repairUsers = data.repairUsers.map(i=>{
+      return {
+        id: i.id || null,
+        annualMaintenanceRecordId: i.annualMaintenanceRecordId || null,
+        userId: i.userId,
+        userName: i.name,
+        userType: 2
+      }
+    })
+    data.annualMaintenanceRecordUsers = data.maintainUsers.concat(data.repairUsers)
+    data.managerName = state.userList.find(i=>i.userId == data.managerId)?.name
+    data.deviceManagerName = state.userList.find(i=>i.userId == data.deviceManagerId)?.name
+    data.establishmentName = state.userList.find(i=>i.userId == data.establishmentId)?.name
+    data.processName = state.userList.find(i=>i.userId == data.processId)?.name
+    data.approvalName = state.userList.find(i=>i.userId == data.approvalId)?.name
+    data.delRecordUserIds = state.oldRecordUsers.filter(oldItem => !data.annualMaintenanceRecordUsers.some(newItem => newItem.id === oldItem.id)).map(item => item.id)
+    delete data.maintainUsers
+    delete data.repairUsers
+    if(state.title == '新增'){
+      delete data.id
+      const res = await updateMaintenanceRecord(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }else{
+      const res = await updateMaintenanceRecord(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }
+  }
+}
+
+const getInfo = async (id)=> {
+  const res = await getMaintenanceRecordDetail({id: id})
+  if(res.code == 200){
+    Object.keys(state.form).forEach(key => {
+      if (key in res.data) {
+        state.form[key] = res.data[key]
+      }
+    })
+    state.oldRecordUsers = state.form.annualMaintenanceRecordUsers?.map(item=>{
+      return {
+        id: item.id,
+        annualMaintenanceRecordId: item.annualMaintenanceRecordId,
+        userId: item.userId,
+        name: item.userName,
+        userType: item.userType
+      }
+    })
+    state.form.maintainUsers = state.oldRecordUsers.filter(i=>i.userType == 1)
+    state.form.repairUsers = state.oldRecordUsers.filter(i=>i.userType == 2)
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const getDeptList = async ()=>{
+  state.form.maintainUsers = []
+  state.form.managerId = null
+  state.form.repairUsers = []
+  state.form.annualMaintenanceRecordUsers = []
+  state.form.deviceManagerId = null
+  state.form.establishmentId = null
+  state.form.processId = null
+  state.form.approvalId = null
+  await getUserList(state.form.companyId)
+}
+
+const getUserList = async (companyId)=> {
+  const res = await listUser({pageIndex: 1,pageSize: 999, companyId: companyId})
+  if(res.code == 200){
+    state.userList = res.data.list?res.data.list.map(item=>{
+      const user = item.id
+      const {id, ...data} = item
+      return {
+        ...data,
+        userId: user
+      }
+    }):[]
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const handleClose = () => {
+  state.form = {
+    id: null,
+    deviceName: '',
+    number: '',
+    formNumber: '',
+    faultDate: '',
+    repairDate: '',
+    failurePhenomenon: '',
+    maintainUsers: [],
+    managerId: null,
+    faultCause: '',
+    maintenanceMethod: null,
+    outsourcingLocation: '',
+    repairTime: '',
+    downTime: '',
+    replaceMaterials: '',
+    money: '',
+    repairUsers: [],
+    annualMaintenanceRecordUsers: [],
+    deviceManagerId: null,
+    deviceManagerName: '',
+    remark: '',
+    acceptanceConfirmation: '',
+    establishmentId: null,
+    processId: null,
+    approvalId: null,
+    companyId: null
+  }
+  state.fileList = []
+  superRef.value.clearValidate();
+  superRef.value.resetFields()
+  dialogVisible.value = false;
+}
+
+defineExpose({
+  openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+  :deep(.el-form .el-form-item__label) {
+    font-size: 15px;
+  }
+  .file {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+}
+</style>
diff --git a/src/views/work/qualityInfo/infrastructureMng/repairRecord/index.vue b/src/views/work/qualityInfo/infrastructureMng/repairRecord/index.vue
new file mode 100644
index 0000000..49740a3
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/repairRecord/index.vue
@@ -0,0 +1,235 @@
+<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 >
+          <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="deviceName" align="center" label="设备名称"></el-table-column>
+      <el-table-column prop="failurePhenomenon" align="center" label="故障现象"></el-table-column>
+      <el-table-column prop="faultCause" align="center" label="故障原因及排除方法"></el-table-column>
+      <el-table-column prop="faultDate" align="center" label="故障发生日期">
+        <template #default="scope">
+          {{scope.row.faultDate.substring(0,10)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="repairDate" align="center" label="要求维修日期">
+        <template #default="scope">
+          {{scope.row.repairDate.substring(0,10)}}
+        </template>
+      </el-table-column>
+      <el-table-column prop="manageName" align="center" label="设施操作/管理员"></el-table-column>
+      <el-table-column prop="managerName" align="center" label="主管"></el-table-column>
+<!--      <el-table-column label="检查表" align="center">-->
+<!--        <template #default="scope">-->
+<!--          {{scope.row.deptName }}内审检查表-->
+<!--        </template>-->
+<!--      </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 {generateWordDocument} from "@/utils/exportWord";
+import {
+  delMaintenanceRecord,
+  getMaintenanceRecordDetail,
+  getMaintenanceRecordList
+} from "@/api/infrastructureMng/ledger";
+import {getInternalAuditCheckInfo} from "@/api/innerReview/meetingReview";
+
+
+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 getMaintenanceRecordList(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 openDialog = (type, value) => {
+  dialogRef.value.openDialog(type, value, data.queryParams.companyId, data.isAdmin, data.companyList);
+}
+
+const downloadFile = async (val)=>{
+  const res = await getMaintenanceRecordDetail({id: val.id})
+  if(res.code == 200){
+    if(res.data){
+      let tableData = res.data
+      tableData.maintainUsers = tableData.annualMaintenanceRecordUsers.filter(i=>i.userType == 1)?.map(i=>i.userName).join('、')
+      tableData.repairUsers = tableData.annualMaintenanceRecordUsers.filter(i=>i.userType == 2)?.map(i=>i.userName).join('、')
+      tableData.faultDate = tableData.faultDate.substring(0,10)
+      tableData.repairDate = tableData.repairDate.substring(0,10)
+      tableData.downTime = tableData.downTime.substring(0,10)
+      tableData.typeList = [
+        {
+          id: 1,
+          label: '内部维修',
+          checked: tableData.maintenanceMethod == 1 ? false : true
+        },
+        {
+          id: 2,
+          label: '委外维修',
+          checked: tableData.maintenanceMethod == 2 ? false : true
+        }
+      ]
+      if(data.isAdmin){
+        tableData.companyName = data.companyList.find(i=>i.id == val.companyId)?.name
+      }else{
+        tableData.companyName = userStore.companyName
+      }
+      try {
+        generateWordDocument('/repairRecord.docx', tableData, tableData.companyName + '基础设施维修记录.docx');
+      } catch (error){
+        ElMessage({
+          type: 'warning',
+          message: '导出失败'
+        });
+      }
+    }else{
+      ElMessage.warning('暂无数据')
+    }
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+/** 重置新增的表单以及其他数据  */
+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 delMaintenanceRecord({id: val.id})
+        if(res.code == 200){
+          ElMessage.success('数据删除成功')
+          await getList()
+        }else{
+          ElMessage.warning(res.message)
+        }
+      })
+}
+
+</script>
diff --git a/src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/components/editDialog.vue b/src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/components/editDialog.vue
new file mode 100644
index 0000000..9c9a18e
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/components/editDialog.vue
@@ -0,0 +1,426 @@
+<template>
+  <div class="notice">
+    <el-dialog
+        v-model="dialogVisible"
+        :title="state.title"
+        width="75%"
+        :before-close="handleClose"
+        :close-on-press-escape="false"
+        :close-on-click-modal="false"
+    >
+      <el-form :model="state.form" size="default" ref="superRef" :rules="state.formRules" label-width="150px" >
+        <el-form-item v-if="state.isAdmin" label="企业:" prop="companyId">
+          <el-select v-model="state.form.companyId" placeholder="请选择" :disabled="state.title =='查看'" clearable @change="getDeptList">
+            <el-option
+                v-for="item in state.companyList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-row>
+          <el-col :span="8">
+            <el-form-item label="制定日期:" prop="enactmentDate">
+              <el-date-picker
+                  v-model="state.form.enactmentDate"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择日期"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="修订日期:" prop="revisionDate">
+              <el-date-picker
+                  v-model="state.form.revisionDate"
+                  type="date"
+                  value-format="YYYY-MM-DD"
+                  placeholder="请选择日期"
+                  :disabled="state.title =='查看'"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="表单编号:" prop="number">
+              <el-input v-model.trim="state.form.number" :readonly="state.title =='查看'"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-form-item label="设备属性:" prop="annualMaintenanceEvaluateDeviceList">
+          <el-button
+              type="primary"
+              plain
+              icon="Plus"
+              @click="addLine"
+              style="margin-bottom: 10px"
+          >新增</el-button>
+        </el-form-item>
+        <el-table :data="state.form.annualMaintenanceEvaluateDeviceList" class="customedTable" :border="true">
+          <el-table-column label="序号" type="index" width="80" align="center">
+          </el-table-column>
+          <el-table-column label="设备编号" prop="deviceNumber" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.deviceNumber"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%;"
+                  clearable
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="设备名称" prop="deviceName" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.deviceName"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%;"
+                  clearable
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="型号" prop="model" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.model"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%;"
+                  clearable
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="地点" prop="location" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.location"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%;"
+                  clearable
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="使用人" prop="useUser" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.useUser"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%;"
+                  clearable
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="设备使用部门" prop="deptName" align="center">
+            <template #default="scope">
+              <el-input
+                  v-model.trim="scope.row.deptName"
+                  size="large"
+                  type="textarea"
+                  style="width: 100%;"
+                  clearable
+                  :readonly="state.title =='查看'"
+              >
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="抽查结果" prop="resultType" align="center">
+            <template #default="scope">
+              <el-select v-model="scope.row.resultType" :disabled="state.title =='查看'" placeholder="请选择" clearable>
+                <el-option key="1" label="完好" :value="1"></el-option>
+                <el-option key="2" label="需整改" :value="2"></el-option>
+                <el-option key="3" label="报废" :value="3"></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="70">
+            <template #default="scope">
+              <el-button link type="danger" @click="handleDelete(scope.$index)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-form-item label="编制:" prop="establishmentId">
+          <el-select clearable v-model="state.form.establishmentId" :disabled="state.title =='查看'" filterable placeholder="编制" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="审核:" prop="processId">
+          <el-select clearable v-model="state.form.processId" :disabled="state.title =='查看'" filterable placeholder="审核" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="批准:" prop="approvalId">
+          <el-select clearable v-model="state.form.approvalId" :disabled="state.title =='查看'" filterable placeholder="批准" style="width: 100%">
+            <el-option
+                v-for="item in state.userList"
+                :key="item.userId"
+                :label="item.name"
+                :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer v-if="state.title !='查看'">
+        <span class="dialog-footer">
+            <el-button @click="handleClose" size="default">取 消</el-button>
+            <el-button type="primary"  @click="onSubmit" size="default" v-preReClick>确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup>
+import {reactive, ref, toRefs, defineEmits, nextTick, onMounted} from 'vue'
+import {ElMessage} from "element-plus";
+import {getToken} from "@/utils/auth";
+import {
+  updateMaintenanceEvaluate,
+  getMaintenanceEvaluateDetail
+} from "@/api/infrastructureMng/ledger";
+
+import {listUser} from "@/api/system/user";
+
+const emit = defineEmits(["getList"]);
+const dialogVisible = ref(false)
+const superRef = ref()
+const checkList = (rule, value, callback) => {
+  if (state.form.annualMaintenanceEvaluateDeviceList.length == 0) {
+    callback(new Error('设备属性不可为空'))
+  } else {
+    callback()
+  }
+}
+const state = reactive({
+  title: '',
+  form: {
+    id: null,
+    companyId: null,
+    enactmentDate: '',
+    revisionDate: '',
+    number: '',
+    annualMaintenanceEvaluateDeviceList: [],
+    establishmentId: null,
+    establishmentName: '',
+    processId: null,
+    processName: '',
+    approvalId: null,
+    approvalName: '',
+    evaluateDeviceIds: [],
+    name: ''
+  },
+  oldDeviceList: [],
+  formRules:{
+    companyId: [{ required: true, message: '请选择企业', trigger: 'blur' }],
+    enactmentDate: [{ required: true, message: '请选择指定日期', trigger: 'blur' }],
+    revisionDate: [{ required: true, message: '请选择修订日期', trigger: 'blur' }],
+    number: [{ required: true, message: '请填写编号',  trigger: 'blur' }],
+    annualMaintenanceEvaluateDeviceList: [{ required: true, validator: checkList, trigger: 'blur' }],
+    establishmentId: [{ required: true, message: '请选择编制人', trigger: 'blur' }],
+    processId: [{ required: true, message: '请选择审核人', trigger: 'blur' }],
+    approvalId: [{ required: true, message: '请选择批准人', trigger: 'blur' }]
+  },
+  isAdmin: false,
+  companyList: [],
+  userList: []
+})
+onMounted(() => {
+
+});
+
+const openDialog = async (type, value,companyId, isAdmin, companyList) => {
+  state.isAdmin = isAdmin
+  if(isAdmin){
+    state.companyList = companyList
+  }
+  await getUserList(companyId)
+  state.title = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看'
+  state.form.companyId = companyId
+  if(state.title == '编辑'||state.title == '查看'){
+    await getInfo(value.id)
+  }
+  dialogVisible.value = true
+}
+
+const addLine = () => {
+  const obj = {
+    id: null,
+    annualMaintenanceEvaluateId: null,
+    deviceNumber: '',
+    deviceName: '',
+    model: '',
+    location: '',
+    useUser: '',
+    deptName: '',
+    resultType: null
+  }
+  state.form.annualMaintenanceEvaluateDeviceList.push(obj);
+}
+
+const handleDelete = (i) =>{
+  state.form.annualMaintenanceEvaluateDeviceList = state.form.annualMaintenanceEvaluateDeviceList.filter((item,index) => index != i)
+}
+
+const onSubmit = async () => {
+  const valid = await superRef.value.validate();
+  if(valid){
+    const data = JSON.parse(JSON.stringify(state.form))
+    data.evaluateDeviceIds = state.oldDeviceList.filter(i =>!data.annualMaintenanceEvaluateDeviceList.some(item=>item.id == i.id)).map(i=>i.id)
+    data.establishmentName = state.userList.find(i=>i.userId == data.establishmentId)?.name
+    data.processName = state.userList.find(i=>i.userId == data.processId)?.name
+    data.approvalName = state.userList.find(i=>i.userId == data.approvalId)?.name
+    data.name = data.enactmentDate + '设备完好性评价记录及完好率统计表'
+    if(state.title == '新增'){
+      delete data.id
+      const res = await updateMaintenanceEvaluate(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }else{
+      const res = await updateMaintenanceEvaluate(data)
+      if(res.code == 200){
+        ElMessage.success(res.message)
+        emit('getList')
+        handleClose()
+        dialogVisible.value = false;
+      }else{
+        ElMessage.warning(res.message)
+      }
+    }
+  }
+}
+
+const getInfo = async (id)=> {
+  const res = await getMaintenanceEvaluateDetail({id: id})
+  if(res.code == 200){
+    Object.keys(state.form).forEach(key => {
+      if (key in res.data) {
+        state.form[key] = res.data[key]
+      }
+    })
+    state.form.annualMaintenanceEvaluateDeviceList = res.data.annualMaintenanceEvaluateDeviceList?.map(item=>{
+      return {
+        id: item.id,
+        annualMaintenanceEvaluateId: item.annualMaintenanceEvaluateId,
+        deviceNumber: item.deviceNumber,
+        deviceName: item.deviceName,
+        model: item.model,
+        location: item.location,
+        useUser: item.useUser,
+        deptName: item.deptName,
+        resultType: item.resultType
+      }
+    })
+    state.oldDeviceList = state.form.annualMaintenanceEvaluateDeviceList
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const getDeptList = async ()=>{
+  state.form.establishmentId = null
+  state.form.processId = null
+  state.form.approvalId = null
+  await getUserList(state.form.companyId)
+}
+
+const getUserList = async (companyId)=> {
+  const res = await listUser({pageIndex: 1,pageSize: 999,companyId: companyId})
+  if(res.code == 200){
+    state.userList = res.data.list?res.data.list.map(item=>{
+      const user = item.id
+      const {id, ...data} = item
+      return {
+        ...data,
+        userId: user
+      }
+    }):[]
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+const handleClose = () => {
+  state.form = {
+    id: null,
+    companyId: null,
+    enactmentDate: '',
+    revisionDate: '',
+    number: '',
+    annualMaintenanceEvaluateDeviceList: [],
+    establishmentId: null,
+    establishmentName: '',
+    processId: null,
+    processName: '',
+    approvalId: null,
+    approvalName: '',
+    evaluateDeviceIds: [],
+    name: ''
+  }
+  superRef.value.clearValidate();
+  superRef.value.resetFields()
+  dialogVisible.value = false;
+}
+
+defineExpose({
+  openDialog
+});
+
+</script>
+
+<style scoped lang="scss">
+.notice{
+  :deep(.el-form .el-form-item__label) {
+    font-size: 15px;
+  }
+  .file {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+  }
+}
+</style>
+<style lang="scss">
+.customedTable{
+  width: calc(100% - 150px);
+  margin-left: 150px;
+  margin-bottom: 30px;
+  .el-table__cell{
+    padding: 2px 0 !important;
+    font-size: 14px !important;
+  }
+  .cell{
+    padding: 0 2px !important;
+    font-size: 14px !important;
+  }
+}
+</style>
diff --git a/src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/index.vue b/src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/index.vue
new file mode 100644
index 0000000..7b62bc1
--- /dev/null
+++ b/src/views/work/qualityInfo/infrastructureMng/reviewRecordStatistics/index.vue
@@ -0,0 +1,207 @@
+<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 >
+          <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="companyName" align="center" label="公司名称" v-if="isAdmin"></el-table-column>
+      <el-table-column prop="enactmentDate" align="center" label="名称">
+        <template #default="scope">
+          {{scope.row.enactmentDate.substring(0,10) + '设备完好性评价记录及完好率统计表'}}
+        </template>
+      </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 {generateWordDocument} from "@/utils/exportWord";
+import {
+  delMaintenanceEvaluate,
+  getMaintenanceEvaluateDetail,
+  getMaintenanceEvaluateList
+} 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: [],
+  isAdmin: false
+});
+
+const { queryParams, total, dataList,companyList, isAdmin } = 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 getMaintenanceEvaluateList(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 getMaintenanceEvaluateDetail({id: val.id})
+  if(res.code == 200){
+    if(res.data){
+      let tableData = res.data
+      tableData.table = res.data.annualMaintenanceEvaluateDeviceList.map((item,index)=>{
+        return {
+          ...item,
+          index: index + 1,
+          isWell: item.resultType == 1 ? '√' : '',
+          isFix: item.resultType == 2 ? '√' : '',
+          isCrap: item.resultType == 3 ? '√' : ''
+        }
+      })
+      tableData.deviceCount = tableData.table.length
+      tableData.enactmentDate = tableData.enactmentDate.substring(0,10)
+      tableData.revisionDate = tableData.revisionDate.substring(0,10)
+      if(data.isAdmin){
+        tableData.companyName = data.companyList.find(i=>i.id == val.companyId)?.name
+      }else{
+        tableData.companyName = userStore.companyName
+      }
+      try {
+        generateWordDocument('/reviewRecordStatistic.docx', tableData, tableData.enactmentDate +'设备完好性评价记录及完好率统计表.docx');
+      } catch (error){
+        ElMessage({
+          type: 'warning',
+          message: '导出失败'
+        });
+      }
+    }else{
+      ElMessage.warning('暂无数据')
+    }
+  }else{
+    ElMessage.warning(res.message)
+  }
+}
+
+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 delMaintenanceEvaluate({id: val.id})
+        if(res.code == 200){
+          ElMessage.success('数据删除成功')
+          await getList()
+        }else{
+          ElMessage.warning(res.message)
+        }
+      })
+}
+
+</script>

--
Gitblit v1.9.2