董国庆
2026-01-22 076029d3ef36904be57a2caa4d2a45cf31b04018
检查计划列表
1个文件已删除
2个文件已添加
3个文件已修改
723 ■■■■■ 已修改文件
screen/src/utils/riskSourceMap.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/majorRisk/api.txt 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/planOfAudit/api.txt 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/planOfAudit/index.vue 568 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/planOfAudit/service.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/projectHome/index.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/utils/riskSourceMap.js
@@ -83,6 +83,25 @@
  ENERGY_STATION: '能源站',
  MULTI_FUNCTION_COMPLEX: '综合体'
}
export const planTypeMap = {
  SECURITY_CHECK: '安全检查',
  QUALITY_CHECK: '质量检查',
  COMPREHENSIVE_CHECK: '综合检查',
  EQUIPMENT_CHECK: '设备检查',
  OPERATION_CHECK: '运营检查'
}
export const errorLevelMap = {
  P1: '一级隐患',
  P2: '二级隐患',
  P3: '三级隐患',
  P4: '四级隐患'
}
export const errorReviewStateMap = {
  NOT_REFORMED: '未整改',
  PARTIAL_REFORMED: '部分整改',
  REFORMED: '已整改'
}
/**
 * 根据类型和 code 获取对应的中文名称
@@ -120,4 +139,3 @@
    }
  })
}
screen/src/view/majorRisk/api.txt
File was deleted
screen/src/view/planOfAudit/api.txt
New file
@@ -0,0 +1,45 @@
1、计划下拉框信息 是get 无传参  响应:name 名称; id
2、获取检查列表  post  json传参
    请求参数:pageNum    分页参数,当前页码;pageSize    分页参数,每页数量,默认为10;projectId    项目id
    响应参数: checkTime    检查时间    string
              commentType    1模糊评价 2打分评价    integer
              containDeviceRes    设备报告 1有 0无    integer
              containSystemRes    安全报告 1有 0无    integer
              fuzzyScore    模糊分数    string
              id        integer
              planName    检查计划名称    string
              planType    计划类型    integer
              riskLevel    风险类型    integer
              score    打分分数    string
3、获取检查资料列表 get params传参  请求参数:planId    planId
    响应参数: checkUserImg    检查人员照片    string
              clientId        integer(int32)
              createTime        string(date-time)
              creatorId    创建人id    integer(int32)
              deleted    是否删除 false正常true删除    boolean
              id        integer(int32)
              integrityNotification    廉政告知单    string
              planId        integer(int32)
              planName    计划名称    string
              projectId        integer(int32)
              projectName    项目名称    string
              safetySlip    安全告知单    string
              time    检查时间    string(date-time)
              title    检查标题    string
4、获取检查资料详情 get params传参  请求参数:id    检查资料id
    响应参数:checkUserImg    检查人员照片    string
              clientId        integer(int32)
              createTime        string(date-time)
              creatorId    创建人id    integer(int32)
              deleted    是否删除 false正常true删除    boolean
              id        integer(int32)
              integrityNotification    廉政告知单    string
              planId        integer(int32)
              planName    计划名称    string
              projectId        integer(int32)
              projectName    项目名称    string
              safetySlip    安全告知单    string
              time    检查时间    string(date-time)
              title    检查标题    string
screen/src/view/planOfAudit/index.vue
@@ -17,15 +17,16 @@
        >
          <el-select
            filterable
            v-model="projectId"
            v-model="planType"
            placeholder="请选择计划类型"
            class="flex1"
            clearable
          >
            <el-option
              v-for="item in [1, 2]"
              :key="item"
              :label="item"
              :value="item"
              v-for="item in planOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            >
            </el-option>
          </el-select>
@@ -39,7 +40,7 @@
          class="flex a-center j-between px--20 w--300 h--40 relative bgcolor1 picker"
        >
          <el-date-picker
            v-model="dateTime"
            v-model="startTime"
            ref="datetime1"
            type="datetime"
            placeholder=""
@@ -48,15 +49,15 @@
          <div
            class="absolute w100 h100 flex a-center c-fff fs--14 SHS"
            style="width: calc(100% - 20px)"
            v-if="dateTxt"
            v-if="startTimeTxt"
          >
            {{ dateTxt }}
            {{ startTimeTxt }}
          </div>
          <div
            v-else
            class="absolute w100 h100 flex a-center c-fff fs--14 SHSR"
          >
            请选择日期
            请选择开始日期
          </div>
          <img
            src="../../assets/img/home/Shape@2x (6).png"
@@ -68,7 +69,7 @@
          class="flex a-center j-between px--20 w--300 h--40 relative bgcolor1 picker"
        >
          <el-date-picker
            v-model="dateTime"
            v-model="endTime"
            ref="datetime2"
            type="datetime"
            placeholder=""
@@ -77,15 +78,15 @@
          <div
            class="absolute w100 h100 flex a-center c-fff fs--14 SHS"
            style="width: calc(100% - 20px)"
            v-if="dateTxt"
            v-if="endTimeTxt"
          >
            {{ dateTxt }}
            {{ endTimeTxt }}
          </div>
          <div
            v-else
            class="absolute w100 h100 flex a-center c-fff fs--14 SHSR"
          >
            请选择日期
            请选择结束日期
          </div>
          <img
            src="../../assets/img/home/Shape@2x (6).png"
@@ -95,37 +96,54 @@
        <div
          class="flex a-center j-between w--300 pl--20 h--40 relative bgcolor1 searchBox"
        >
          <el-select
            filterable
            v-model="projectId"
          <el-input
            v-model="searchKeyword"
            placeholder="请输入搜索内容"
            class="flex1"
          >
            <el-option
              v-for="item in [1, 2]"
              :key="item"
              :label="item"
              :value="item"
            >
            </el-option>
          </el-select>
          <div class="btn SHSR">搜索</div>
            clearable
            @keyup.enter.native="handleSearch"
          />
          <div @click="handleSearch" class="btn SHSR">搜索</div>
        </div>
      </div>
      <!-- 表格 -->
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        :data="checkList"
        height="800"
        style="border: 2px solid #3d7fff"
        v-loading="loading"
      >
        <el-table-column label="检查计划" prop="projectName" />
        <el-table-column label="计划类型" prop="projectName" />
        <el-table-column label="检查时间" prop="projectName" />
        <el-table-column label="本月检查风险" prop="projectName" />
        <el-table-column label="操作">
        <el-table-column label="检查计划" prop="planName" min-width="150" />
        <el-table-column label="计划类型" min-width="120">
          <template #default="{ row }">
            {{ formatPlanType(row.planType) }}
          </template>
        </el-table-column>
        <el-table-column label="检查时间" min-width="180">
          <template #default="{ row }">
            {{ formatTime(row.checkTime) }}
          </template>
        </el-table-column>
        <!-- 以下列仅在非项目端(type != 2)时显示 -->
        <el-table-column v-if="type != 2" label="风险等级" min-width="120">
          <template #default="{ row }">
            {{ formatRiskLevel(row.riskLevel) }}
          </template>
        </el-table-column>
        <el-table-column v-if="type != 2" label="评价方式" min-width="120">
          <template #default="{ row }">
            {{ formatCommentType(row.commentType) }}
          </template>
        </el-table-column>
        <el-table-column v-if="type != 2" label="评分" min-width="100">
          <template #default="{ row }">
            {{ getScoreDisplay(row) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="{ row }">
            <el-button
              @click="projectVisible = true"
              @click="openCheckMaterialDialog(row)"
              type="text"
              class="btnColor"
              >检查资料</el-button
@@ -138,14 +156,16 @@
                class="h100 flex flex-column a-center j-between c-fff fs--16 SHSBold"
              >
                <div
                  @click="openReport('safe')"
                  @click="openReport('safe', row)"
                  class="py--12 w100 txt-center br--10 bgcolor6 cursor-pointer"
                  :class="{ disabled: row.containSystemRes !== 1 }"
                >
                  安全报告
                </div>
                <div
                  @click="openReport('device')"
                  @click="openReport('device', row)"
                  class="py--12 w100 txt-center br--10 bgcolor7 cursor-pointer"
                  :class="{ disabled: row.containDeviceRes !== 1 }"
                >
                  设备报告
                </div>
@@ -158,26 +178,51 @@
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-sizes="[100, 200, 300, 400]"
        :page-size="10"
        :total="400"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="pageSize"
        :total="total"
      />
    </div>
    <!-- 检查资料列表弹窗 -->
    <CustomDialog title="项目" :visible.sync="projectVisible" width="1420px">
    <CustomDialog
      title="检查资料列表"
      :visible.sync="projectVisible"
      width="1420px"
      @close="closeProjectDialog"
    >
      <CustomTable
        :data="[{ projectName: '项目777' }, { projectName: '项目2' }]"
        :data="checkMaterialList"
        height="630"
        v-loading="loading"
      >
        <el-table-column label="检查标题" prop="projectName" />
        <el-table-column label="检查时间" prop="projectName" />
        <el-table-column label="安全告知单" prop="projectName" />
        <el-table-column label="检查人员照片" prop="projectName" />
        <el-table-column label="廉政告知单" prop="projectName" />
        <el-table-column label="操作">
        <el-table-column label="检查标题" prop="title" min-width="150" />
        <!-- 以下列仅在非项目端(type != 2)时显示 -->
        <el-table-column v-if="type != 2" label="计划名称" prop="planName" min-width="150" />
        <el-table-column v-if="type != 2" label="项目名称" prop="projectName" min-width="150" />
        <el-table-column label="检查时间" min-width="180">
          <template #default="{ row }">
            {{ formatTime(row.time) }}
          </template>
        </el-table-column>
        <el-table-column label="安全告知单" min-width="100">
          <template #default="{ row }">
            {{ row.safetySlip ? "有" : "无" }}
          </template>
        </el-table-column>
        <el-table-column label="检查人员照片" min-width="120">
          <template #default="{ row }">
            {{ row.checkUserImg ? "有" : "无" }}
          </template>
        </el-table-column>
        <el-table-column label="廉政告知单" min-width="100">
          <template #default="{ row }">
            {{ row.integrityNotification ? "有" : "无" }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="100" fixed="right">
          <template #default="{ row }">
            <el-button
              @click="detailVisible = true"
              @click="openDetailDialog(row)"
              type="text"
              class="btnColor"
              >详情</el-button
@@ -187,7 +232,12 @@
      </CustomTable>
    </CustomDialog>
    <!-- 检查报告弹窗 -->
    <CustomDialog title="检查报告" :visible.sync="reportVisible" width="1420px">
    <CustomDialog
      title="检查报告"
      :visible.sync="reportVisible"
      width="1420px"
      @close="closeReportDialog"
    >
      <div style="height: 691px" class="oa">
        <iframe
          v-if="reportUrl"
@@ -196,6 +246,9 @@
          height="100%"
          frameborder="0"
        ></iframe>
        <div v-else class="flex a-center j-center h100 c-fff fs--16">
          暂无报告数据
        </div>
      </div>
    </CustomDialog>
    <!-- 检查资料详情弹窗 -->
@@ -203,73 +256,98 @@
      title="检查资料详情"
      :visible.sync="detailVisible"
      width="1420px"
      @close="closeDetailDialog"
    >
      <div class="oa" style="height: 700px">
      <div class="oa" style="height: 700px" v-loading="loading">
        <div class="flex j-between gap--30 mt--30">
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">计划名称:</div>
            <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor8">
              计划名称计划名称计划名称
              {{ checkMaterialDetail.planName || "-" }}
            </div>
          </div>
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">项目名称:</div>
            <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor8">
              计划名称计划名称计划名称
              {{ checkMaterialDetail.projectName || "-" }}
            </div>
          </div>
        </div>
        <div class="flex j-between gap--30 mt--30">
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">检测标题:</div>
            <div class="SHSR fs--16 lh--16 mb--17 color1">检查标题:</div>
            <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor8">
              计划名称计划名称计划名称
              {{ checkMaterialDetail.title || "-" }}
            </div>
          </div>
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">检测时间:</div>
            <div class="SHSR fs--16 lh--16 mb--17 color1">检查时间:</div>
            <div class="lh--60 px--19 c-fff SHSBold fs--18 w100 bgcolor8">
              计划名称计划名称计划名称
              {{ formatTime(checkMaterialDetail.time) }}
            </div>
          </div>
        </div>
        <div class="mt--30">
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">安全告知单:</div>
            <div class="flex a-center oa gap--14">
            <div
              class="flex a-center oa gap--14"
              v-if="parseImages(checkMaterialDetail.safetySlip).length > 0"
            >
              <img
                v-for="item in 6"
                :key="item"
                src="../../assets/img/home/@3x@2x.png"
                class="w--150 h--120"
                v-for="(item, index) in parseImages(
                  checkMaterialDetail.safetySlip
                )"
                :key="index"
                :src="item"
                class="w--150 h--120 cursor-pointer"
                @click="previewImage(item)"
              />
            </div>
            <div v-else class="c-fff fs--14 SHSR">暂无图片</div>
          </div>
        </div>
        <div class="mt--30">
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">检查人员照片:</div>
            <div class="flex a-center oa gap--14">
            <div
              class="flex a-center oa gap--14"
              v-if="parseImages(checkMaterialDetail.checkUserImg).length > 0"
            >
              <img
                v-for="item in 6"
                :key="item"
                src="../../assets/img/home/@3x@2x.png"
                class="w--150 h--120"
                v-for="(item, index) in parseImages(
                  checkMaterialDetail.checkUserImg
                )"
                :key="index"
                :src="item"
                class="w--150 h--120 cursor-pointer"
                @click="previewImage(item)"
              />
            </div>
            <div v-else class="c-fff fs--14 SHSR">暂无图片</div>
          </div>
        </div>
        <div class="mt--30">
          <div class="flex1">
            <div class="SHSR fs--16 lh--16 mb--17 color1">廉政告知单:</div>
            <div class="flex a-center oa gap--14">
            <div
              class="flex a-center oa gap--14"
              v-if="
                parseImages(checkMaterialDetail.integrityNotification).length >
                0
              "
            >
              <img
                v-for="item in 6"
                :key="item"
                src="../../assets/img/home/@3x@2x.png"
                class="w--150 h--120"
                v-for="(item, index) in parseImages(
                  checkMaterialDetail.integrityNotification
                )"
                :key="index"
                :src="item"
                class="w--150 h--120 cursor-pointer"
                @click="previewImage(item)"
              />
            </div>
            <div v-else class="c-fff fs--14 SHSR">暂无图片</div>
          </div>
        </div>
      </div>
@@ -280,32 +358,90 @@
<script>
import HeaderBox from "../header/index.vue";
import moment from "moment";
import {
  getPlanList,
  getDeviceDetailCheckList,
  getDeviceDetailCheckPlanList,
  getDeviceDetailCheckPlanDetail,
} from "./service";
import { planTypeMap } from "@/utils/riskSourceMap";
export default {
  components: { HeaderBox },
  props: {},
  data() {
    return {
      dateTime: null,
      // 搜索条件
      planType: "", // 计划类型
      startTime: null, // 开始时间
      endTime: null, // 结束时间
      searchKeyword: "", // 搜索关键词
      startTimeTxt: "",
      endTimeTxt: "",
      // 项目信息
      projectId: null,
      projectName: null,
      dateTxt: "",
      type: null, // 路由参数 type,用于判断是否为项目端
      // 分页
      currentPage: 1,
      pageSize: 10,
      total: 0,
      // 列表数据
      planOptions: [], // 计划类型下拉选项
      checkList: [], // 检查列表
      checkMaterialList: [], // 检查资料列表
      checkMaterialDetail: {}, // 检查资料详情
      // 弹窗控制
      projectVisible: false,
      reportVisible: false,
      detailVisible: false,
      // 当前选中的数据
      currentPlanId: null, // 当前选中的计划ID
      currentCheckId: null, // 当前选中的检查资料ID
      currentRow: null, // 当前选中的行数据
      // 报告相关
      reportUrl: "",
      safeReportUrl:
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
      deviceReportUrl:
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
      loading: false,
      // 枚举映射
      planTypeMap: planTypeMap, // 计划类型映射
      riskLevelMap: {
        0: "拒绝接受风险",
        1: "不可接受风险",
        2: "可接受风险",
        3: "可容忍风险",
        4: "可忽略风险",
      },
      commentTypeMap: {
        1: "模糊评价",
        2: "打分评价",
      },
    };
  },
  computed: {},
  watch: {
    dateTime: {
      handler(newVal, oldVal) {
    startTime: {
      handler(newVal) {
        if (newVal) {
          this.dateTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
          this.startTimeTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
        } else {
          this.startTimeTxt = "";
        }
      },
      immediate: true,
    },
    endTime: {
      handler(newVal) {
        if (newVal) {
          this.endTimeTxt = moment(newVal).format("YYYY年MM月DD日 HH:mm:ss");
        } else {
          this.endTimeTxt = "";
        }
      },
      immediate: true,
@@ -314,33 +450,273 @@
  created() {
    this.projectId = this.$route.query.projectId;
    this.projectName = this.$route.query.projectName;
    this.type = this.$route.query.type; // 获取路由参数 type
  },
  mounted() {},
  mounted() {
    this.initData();
  },
  methods: {
    // 初始化数据
    async initData() {
      await this.getPlanOptions();
      await this.getCheckList();
    },
    // 获取计划类型下拉选项
    async getPlanOptions() {
      try {
        // 将 planTypeMap 转换为下拉选项格式
        // 下标作为 value 传给后端,中文名称作为 label 显示
        this.planOptions = Object.keys(this.planTypeMap).map((code, index) => ({
          id: index, // 下标用于传给后端
          name: this.planTypeMap[code], // 中文名称用于显示
          code: code, // 保存 code 用于参考
        }));
      } catch (error) {
        console.error("获取计划类型失败:", error);
        this.$message.error("获取计划类型失败");
      }
    },
    // 获取检查列表
    async getCheckList() {
      this.loading = true;
      try {
        const params = {
          pageNum: this.currentPage,
          pageSize: this.pageSize,
          projectId: this.projectId,
        };
        // 添加可选搜索条件
        if (this.planType !== "" && this.planType !== null && this.planType !== undefined) {
          params.planType = this.planType; // 传下标给后端(0, 1, 2...)
        }
        if (this.startTime) {
          params.startTime = moment(this.startTime).format(
            "YYYY-MM-DD HH:mm:ss"
          );
        }
        if (this.endTime) {
          params.endTime = moment(this.endTime).format("YYYY-MM-DD HH:mm:ss");
        }
        if (this.searchKeyword) {
          params.planName = this.searchKeyword; // 计划名称
        }
        const res = await getDeviceDetailCheckList(params);
        if (res && res) {
          this.checkList = res.records || res.list || [];
          this.total = res.total || 0;
        }
      } catch (error) {
        console.error("获取检查列表失败:", error);
        this.$message.error("获取检查列表失败");
      } finally {
        this.loading = false;
      }
    },
    // 搜索
    handleSearch() {
      this.currentPage = 1;
      this.getCheckList();
    },
    // 重置搜索条件
    handleReset() {
      this.planType = "";
      this.startTime = null;
      this.endTime = null;
      this.searchKeyword = "";
      this.currentPage = 1;
      this.getCheckList();
    },
    // 分页 - 每页条数改变
    handleSizeChange(val) {
      console.log(`每页 ${val} 条`);
      this.pageSize = val;
      this.currentPage = 1;
      this.getCheckList();
    },
    // 分页 - 当前页改变
    handleCurrentChange(val) {
      console.log(`当前页: ${val}`);
      this.currentPage = val;
      this.getCheckList();
    },
    // 打开检查资料列表弹窗
    async openCheckMaterialDialog(row) {
      this.currentRow = row;
      this.currentPlanId = row.id;
      this.projectVisible = true;
      await this.getCheckMaterialList();
    },
    // 获取检查资料列表
    async getCheckMaterialList() {
      if (!this.currentPlanId) {
        this.$message.warning("缺少计划ID");
        return;
      }
      this.loading = true;
      try {
        const res = await getDeviceDetailCheckPlanList({
          planId: this.currentPlanId,
        });
        if (res ) {
          this.checkMaterialList = res;
        }
      } catch (error) {
        console.error("获取检查资料列表失败:", error);
        this.$message.error("获取检查资料列表失败");
      } finally {
        this.loading = false;
      }
    },
    // 打开检查资料详情弹窗
    async openDetailDialog(row) {
      this.currentCheckId = row.id;
      this.detailVisible = true;
      await this.getCheckMaterialDetail();
    },
    // 获取检查资料详情
    async getCheckMaterialDetail() {
      if (!this.currentCheckId) {
        this.$message.warning("缺少检查资料ID");
        return;
      }
      this.loading = true;
      try {
        const res = await getDeviceDetailCheckPlanDetail({
          id: this.currentCheckId,
        });
        if (res ) {
          this.checkMaterialDetail = res;
        }
      } catch (error) {
        console.error("获取检查资料详情失败:", error);
        this.$message.error("获取检查资料详情失败");
      } finally {
        this.loading = false;
      }
    },
    // 打开报告
    openReport(type, row) {
      this.currentRow = row;
      if (type === "safe") {
        // 安全报告
        if (row.containSystemRes === 1) {
          this.reportUrl = row.systemReportUrl || "";
        } else {
          this.$message.warning("暂无安全报告");
          return;
        }
      } else if (type === "device") {
        // 设备报告
        if (row.containDeviceRes === 1) {
          this.reportUrl = row.deviceReportUrl || "";
        } else {
          this.$message.warning("暂无设备报告");
          return;
        }
      }
      if (this.reportUrl) {
        this.reportVisible = true;
      } else {
        this.$message.warning("报告地址不存在");
      }
    },
    // 关闭检查资料列表弹窗
    closeProjectDialog() {
      this.projectVisible = false;
      this.checkMaterialList = [];
      this.currentPlanId = null;
      this.currentRow = null;
    },
    // 关闭检查资料详情弹窗
    closeDetailDialog() {
      this.detailVisible = false;
      this.checkMaterialDetail = {};
      this.currentCheckId = null;
    },
    // 关闭报告弹窗
    closeReportDialog() {
      this.reportVisible = false;
      this.reportUrl = "";
    },
    // 日期选择器点击
    handleClick(type) {
      this.$refs[`datetime${type}`].focus();
    },
    // 返回
    backFun() {
      this.$router.go(-1);
    },
    openReport(type) {
      if (type === "safe") {
        this.reportUrl = this.safeReportUrl;
      } else if (type === "device") {
        this.reportUrl = this.deviceReportUrl;
      } else {
        this.reportUrl = "";
    // 格式化时间
    formatTime(time) {
      return time ? moment(time).format("YYYY-MM-DD HH:mm:ss") : "-";
    },
    // 格式化风险等级
    formatRiskLevel(level) {
      return this.riskLevelMap[level] || "-";
    },
    // 格式化计划类型(后端返回的是下标,需要转换为中文名称)
    formatPlanType(type) {
      // 后端返回的是下标,需要根据下标找到对应的 code,再找到中文名称
      const planTypeCodes = Object.keys(this.planTypeMap);
      if (type >= 0 && type < planTypeCodes.length) {
        const code = planTypeCodes[type];
        return this.planTypeMap[code] || "-";
      }
      this.reportVisible = !!this.reportUrl;
      return "-";
    },
    // 格式化评价类型
    formatCommentType(type) {
      return this.commentTypeMap[type] || "-";
    },
    // 获取分数显示
    getScoreDisplay(row) {
      if (row.commentType === 1) {
        return row.fuzzyScore || "-";
      } else if (row.commentType === 2) {
        return row.score || "-";
      }
      return "-";
    },
    // 处理图片数组(字符串转数组)
    parseImages(imgStr) {
      if (!imgStr) return [];
      if (Array.isArray(imgStr)) return imgStr;
      try {
        return imgStr.split(",").filter((item) => item);
      } catch (error) {
        return [];
      }
    },
    // 预览图片
    previewImage(url) {
      // 可以使用 el-image-viewer 或其他图片预览组件
      window.open(url, "_blank");
    },
  },
};
@@ -435,6 +811,13 @@
    display: none;
  }
  ::v-deep .el-input__inner {
    background: transparent;
    border: none;
    color: #fff;
    padding: 0;
  }
  .btn {
    position: absolute;
    top: -2px;
@@ -461,6 +844,11 @@
  color: #00ebfc;
}
.disabled {
  opacity: 0.5;
  cursor: not-allowed !important;
}
::v-deep .el-descriptions {
  .el-descriptions__body {
    background-color: transparent;
screen/src/view/planOfAudit/service.js
New file
@@ -0,0 +1,26 @@
import request from '@/utils/request'
// 获取计划下拉框信息
export const getPlanList = async (id) => {
  return request(`/project/getPlanList`, {
    method: 'get'
  })
}
// 获取检查列表
export const getDeviceDetailCheckList = async (data) => {
  return request(`/project/getDeviceDetailCheckList`, {
    method: 'post', data
  })
}
// 获取检查资料列表
export const getDeviceDetailCheckPlanList = async (params) => {
  return request(`/project/getDeviceDetailCheckPlanList`, {
    method: 'get', params
  })
}
// 获取设备详情检查资料详情
export const getDeviceDetailCheckPlanDetail = async (params) => {
  return request(`/project/getDeviceDetailCheckPlanDetail`, {
    method: 'get', params
  })
}
screen/src/view/projectHome/index.vue
@@ -207,21 +207,10 @@
          <template #content>
            <div class="people-info">
              <div class="people-card">
                <div
                  class="people-item"
                  v-for="(item, index) in peopleList.slice(0, 3)"
                  :key="index"
                >
                <div class="people-item" v-for="(item, index) in peopleList.slice(0, 3)" :key="index">
                  <div class="people-chart">
                    <el-progress
                      :width="74"
                      type="circle"
                      :show-text="false"
                      :percentage="parseFloat(item.rate) || 0"
                      define-back-color="#000"
                      color="#32C5FF"
                      stroke-linecap="square"
                    ></el-progress>
                    <el-progress :width="74" type="circle" :show-text="false" :percentage="parseFloat(item.rate) || 0"
                      define-back-color="#000" color="#32C5FF" stroke-linecap="square"></el-progress>
                    <div class="progress-card">
                      <div class="progress-num">{{ item.rate }}</div>
                      <div class="progress-unit">%</div>
@@ -231,22 +220,11 @@
                </div>
              </div>
              <div class="people-card2">
                <div
                  class="people-item"
                  :class="{ 'mr--67': index === 0 }"
                  v-for="(item, index) in peopleList.slice(3, 5)"
                  :key="index + 3"
                >
                <div class="people-item" :class="{ 'mr--67': index === 0 }"
                  v-for="(item, index) in peopleList.slice(3, 5)" :key="index + 3">
                  <div class="people-chart">
                    <el-progress
                      :width="74"
                      type="circle"
                      :show-text="false"
                      :percentage="parseFloat(item.rate) || 0"
                      define-back-color="#000"
                      color="#32C5FF"
                      stroke-linecap="square"
                    ></el-progress>
                    <el-progress :width="74" type="circle" :show-text="false" :percentage="parseFloat(item.rate) || 0"
                      define-back-color="#000" color="#32C5FF" stroke-linecap="square"></el-progress>
                    <div class="progress-card">
                      <div class="progress-num">{{ item.rate }}</div>
                      <div class="progress-unit">%</div>
@@ -454,6 +432,7 @@
      getLoginInfo({ id: this.projectId, type: 2 }).then(res => {
        console.log('res', res)
        this.projectName = res.name
        localStorage.setItem('commentType', res.commentType)
      })
      this.getDetail()
      this.getDangerTrendList()
@@ -629,6 +608,7 @@
        query: {
          projectId: this.projectId,
          projectName: this.projectName,
          type: 2
        },
      });
    },
@@ -1183,7 +1163,7 @@
            color: '#fff',
            fontSize: 12
          },
          formatter: function(params) {
          formatter: function (params) {
            if (params && params.length > 0) {
              const param = params[0];
              const levelText = self.valueToLevel(param.value);