hejianhao
2026-02-02 ab6de8cd9a83e9c921d321cbcf23433bda33c833
Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/smartBuilding
2个文件已修改
329 ■■■■■ 已修改文件
screen/src/view/equipmentList/index.vue 323 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/hiddenDanger/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/equipmentList/index.vue
@@ -166,7 +166,7 @@
        :current-page="currentPage" :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">
      <CustomTable :data="detailCheckList" height="630">
        <el-table-column label="检查计划" prop="planName" />
        <el-table-column label="计划类型" prop="planType" />
@@ -179,16 +179,45 @@
        <el-table-column label="风险类型" prop="riskLevel" />
        <el-table-column label="操作">
          <template #default="{ row }">
            <el-popover trigger="click" popper-class="custom-popper">
            <el-popover
              trigger="click"
              popper-class="custom-popper"
              :disabled="!hasAnyReport(row)"
            >
              <template #reference>
                <el-button type="text" class="btnColor">查看报告</el-button>
                <el-button
                  type="text"
                  :class="hasAnyReport(row) ? 'btnColor' : 'btnDisabled'"
                  :disabled="!hasAnyReport(row)"
                  @click="checkReportAvailability(row)"
                >
                  查看报告
                </el-button>
              </template>
              <div class="h100 flex flex-column a-center j-between c-fff fs--16 SHSBold">
                <div @click="openReport('safe')" class="py--12 w100 txt-center br--10 bgcolor6 cursor-pointer">
                  综合报告
              <div
                class="h100 flex flex-column a-center j-between c-fff fs--16 SHSBold"
              >
                <div
                  @click="openReport('safe', row)"
                  class="py--12 w100 txt-center br--10 bgcolor6 report-btn"
                  :class="{
                    'report-disabled': row.containSystemRes !== 1,
                    'report-enabled': row.containSystemRes === 1
                  }"
                >
                  <span>安全报告</span>
                  <span v-if="row.containSystemRes !== 1" class="no-report-tag">(暂无)</span>
                </div>
                <div @click="openReport('device')" class="py--12 w100 txt-center br--10 bgcolor7 cursor-pointer">
                  设备报告
                <div
                  @click="openReport('device', row)"
                  class="py--12 w100 txt-center br--10 bgcolor7 report-btn"
                  :class="{
                    'report-disabled': row.containDeviceRes !== 1,
                    'report-enabled': row.containDeviceRes === 1
                  }"
                >
                  <span>设备报告</span>
                  <span v-if="row.containDeviceRes !== 1" class="no-report-tag">(暂无)</span>
                </div>
              </div>
            </el-popover>
@@ -204,9 +233,33 @@
        :total="detailTotal" />
    </CustomDialog>
    <!-- 检查报告弹窗 -->
    <CustomDialog title="检查报告" :visible.sync="reportVisible" width="1420px">
      <div style="height: 691px" class="oa">
        <iframe v-if="reportUrl" :src="reportUrl" width="100%" height="100%" frameborder="0"></iframe>
    <CustomDialog
      title="检查报告"
      :visible.sync="reportVisible"
      width="1420px"
      @close="closeReportDialog"
    >
      <div style="height: 691px;" class="flex flex-column" v-loading="loading">
        <!-- PDF预览容器 -->
        <div
          v-if="showPreview && pdfUrl"
          style="width: 100%; height: 100%; overflow: auto; background: #525659;"
        >
          <iframe
            :src="pdfUrl"
            style="width: 100%; height: 100%; border: none;"
            frameborder="0"
          ></iframe>
        </div>
        <!-- 加载提示 -->
        <div v-else class="flex flex-column a-center j-center h100">
          <div class="c-fff fs--18 mb--20">正在加载报告...</div>
        </div>
        <!-- 底部操作按钮 -->
        <div class="flex j-center gap--20 mt--20">
          <el-button type="primary" @click="downloadReport" :disabled="!reportBlobUrl">下载报告</el-button>
          <el-button @click="closeReportDialog">关闭</el-button>
        </div>
      </div>
    </CustomDialog>
  </div>
@@ -221,6 +274,12 @@
  getDeviceListByType,
  getDeviceDetailCheckListByType
} from './service.js'
import {
  getFuzzyReportWord,
  getScoreReportWord,
  getFuzzyReportPdfUrl,
  getScoreReportPdfUrl,
} from "../planOfAudit/service";
export default {
  components: { HeaderBox },
  props: {},
@@ -240,11 +299,11 @@
      total: 0,
      projectVisible: false,
      reportVisible: false,
      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",
      reportUrl: "", // 已废弃,保留兼容性
      reportBlobUrl: "", // Blob URL用于下载
      pdfUrl: "", // PDF预览URL
      loading: false,
      showPreview: false, // 是否显示预览
      deviceTypeList: [],//设备类型列表
      tableList: [],//数据列表
      // 详情弹窗相关数据
@@ -253,6 +312,7 @@
      detailPageSize: 10,
      detailTotal: 0,
      currentDeviceId: null,//当前查看详情的设备ID
      currentRow: null, // 当前选中的行数据
      // 委托方相关
      projectList: [], // 项目列表(委托方使用)
      isClient: false, // 是否委托方端
@@ -429,7 +489,7 @@
      // 使用统一方法,根据用户类型调用对应接口
      getDeviceListByType({ ...params }, this.isClient).then(res => {
        // 处理 properties 字段
        this.tableList = res.records.map(item => {
          return {
@@ -476,14 +536,14 @@
    },
    handleSizeChange(val) {
      this.pageSize = val;
      this.currentPage = 1; // 改变每页条数时重置到第一页
      this.getList();
    },
    handleCurrentChange(val) {
      this.currentPage = val;
      this.getList();
    },
@@ -514,20 +574,189 @@
      this.$router.go(-1);
    },
    openReport(type) {
      if (type === "safe") {
        this.reportUrl = this.safeReportUrl;
      } else if (type === "device") {
        this.reportUrl = this.deviceReportUrl;
      } else {
        this.reportUrl = "";
    // 检查是否有任何报告
    hasAnyReport(row) {
      return row.containSystemRes === 1 || row.containDeviceRes === 1;
    },
    // 检查报告可用性(当按钮被禁用时点击)
    checkReportAvailability(row) {
      if (!this.hasAnyReport(row)) {
        this.$message.warning("该设备暂无可查看的报告");
      }
      this.reportVisible = !!this.reportUrl;
    },
    // 打开报告
    async openReport(type, row) {
      // 根据类型检查是否有对应报告
      const hasReport = type === "safe"
        ? row.containSystemRes === 1
        : row.containDeviceRes === 1;
      if (!hasReport) {
        this.$message.warning(`暂无${type === "safe" ? "安全" : "设备"}报告`);
        return;
      }
      this.currentRow = row;
      this.reportVisible = true;
      this.showPreview = false;
      this.loading = true;
      try {
        // 从 localStorage 获取模板 ID
        const deviceTemplateId = localStorage.getItem("deviceTemplateId");
        const safetyId = localStorage.getItem("safetyId");
        // 检查任务 ID
        const checkTaskId = row.id;
        if (!checkTaskId) {
          this.$message.error("缺少检查任务ID");
          this.loading = false;
          this.reportVisible = false;
          return;
        }
        // 使用当前时间戳作为 uuid
        const uuid = Date.now().toString();
        // 第一步:调用接口生成Word文档(返回Word文档流)
        let wordBlob;
        try {
          if (type === "safe") {
            // 安全报告(模糊评价)
            if (!safetyId) {
              this.$message.error("缺少安全报告模板ID");
              this.loading = false;
              this.reportVisible = false;
              return;
            }
            wordBlob = await getFuzzyReportWord({
              checkTaskId: checkTaskId,
              templateId: safetyId,
              uuid: uuid
            });
          } else {
            // 设备报告(打分评价)
            if (!deviceTemplateId) {
              this.$message.error("缺少设备报告模板ID");
              this.loading = false;
              this.reportVisible = false;
              return;
            }
            wordBlob = await getScoreReportWord({
              checkTaskId: checkTaskId,
              templateId: deviceTemplateId,
              uuid: uuid
            });
          }
        } catch (error) {
          // 捕获生成Word文档时的错误
          console.error("生成Word文档失败:", error);
          this.$message.error(error.message || "生成报告失败");
          this.loading = false;
          this.reportVisible = false;
          return;
        }
        // 检查 Word 文档是否生成成功
        if (!wordBlob || wordBlob.size === 0) {
          this.$message.error("报告生成失败");
          this.loading = false;
          this.reportVisible = false;
          return;
        }
        // 第二步:使用uuid获取PDF链接
        let pdfUrlResponse;
        try {
          if (type === "safe") {
            pdfUrlResponse = await getFuzzyReportPdfUrl({ uuid: uuid });
          } else {
            pdfUrlResponse = await getScoreReportPdfUrl({ uuid: uuid });
          }
        } catch (error) {
          // 捕获获取PDF链接时的错误
          console.error("获取PDF链接失败:", error);
          this.$message.error(error.message || "获取PDF链接失败");
          this.loading = false;
          this.reportVisible = false;
          return;
        }
        // 根据后端返回的数据结构获取PDF链接
        // 假设后端返回格式为 { data: "http://xxx.pdf" } 或直接返回字符串
        const pdfUrl = pdfUrlResponse.data || pdfUrlResponse;
        if (!pdfUrl) {
          this.$message.error("获取PDF链接失败");
          this.loading = false;
          this.reportVisible = false;
          return;
        }
        // 保存PDF链接用于预览和下载
        this.pdfUrl = pdfUrl;
        this.reportBlobUrl = pdfUrl; // 用于下载
        this.showPreview = true;
        this.$message.success("报告加载成功");
      } catch (error) {
        console.error("获取报告失败:", error);
        // 优先显示错误对象中的 message
        if (error.message) {
          this.$message.error(error.message);
        } else if (error.response) {
          const status = error.response.status;
          if (status === 404) {
            this.$message.error("报告不存在");
          } else if (status === 500) {
            this.$message.error("服务器错误,请稍后重试");
          } else {
            this.$message.error(`获取报告失败: ${error.response.statusText || '未知错误'}`);
          }
        } else {
          this.$message.error("获取报告失败,请检查网络连接");
        }
        this.showPreview = false;
        this.reportVisible = false;
      } finally {
        this.loading = false;
      }
    },
    // 下载报告
    downloadReport() {
      if (!this.reportBlobUrl) {
        this.$message.warning("报告未加载");
        return;
      }
      try {
        // 直接打开PDF链接进行下载
        window.open(this.reportBlobUrl, '_blank');
        this.$message.success("报告下载成功");
      } catch (error) {
        console.error("下载报告失败:", error);
        this.$message.error("下载报告失败");
      }
    },
    // 关闭报告弹窗
    closeReportDialog() {
      this.reportVisible = false;
      this.showPreview = false;
      // 清空PDF链接(不需要释放URL,因为是服务器链接)
      this.reportBlobUrl = "";
      this.pdfUrl = "";
      this.reportUrl = ""; // 保留兼容性
    },
    // 打开详情弹窗
    openDetailDialog(row) {
      this.currentDeviceId = row.id;
      this.currentDeviceId = row.projectId;
      this.detailCurrentPage = 1;
      this.projectVisible = true;
      this.getDetailCheckList();
@@ -538,14 +767,14 @@
      if (!this.currentDeviceId) return;
      let params = {
        projectId: this.projectId,
        projectId: this.currentDeviceId,
        pageNum: this.detailCurrentPage,
        pageSize: this.detailPageSize
      };
      // 使用统一方法,根据用户类型调用对应接口
      getDeviceDetailCheckListByType(params, this.isClient).then(res => {
        this.detailCheckList = res.records || [];
        this.detailTotal = res.total || 0;
      }).catch(err => {
@@ -557,7 +786,7 @@
    // 详情弹窗分页 - 每页条数改变
    handleDetailSizeChange(val) {
      this.detailPageSize = val;
      this.detailCurrentPage = 1;
      this.getDetailCheckList();
@@ -565,7 +794,7 @@
    // 详情弹窗分页 - 当前页改变
    handleDetailCurrentChange(val) {
      this.detailCurrentPage = val;
      this.getDetailCheckList();
    },
@@ -711,6 +940,36 @@
  color: #00ebfc;
}
.btnDisabled {
  color: #666666 !important;
  cursor: not-allowed !important;
}
.report-btn {
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
}
.report-enabled {
  &:hover {
    opacity: 0.8;
    transform: translateY(-2px);
  }
}
.report-disabled {
  opacity: 0.4;
  cursor: not-allowed !important;
  pointer-events: none;
}
.no-report-tag {
  font-size: 12px;
  margin-left: 4px;
  opacity: 0.7;
}
::v-deep .el-descriptions {
  .el-descriptions__body {
    background-color: transparent;
screen/src/view/hiddenDanger/index.vue
@@ -494,10 +494,10 @@
      // bigHiddenDangerConfig: 1开启 2关闭
      // generalHiddenDangerConfig: 1开启 2关闭
      if (this.bigHiddenDangerConfig === 1) {
      if (this.bigHiddenDangerConfig === 2) {
        return false
      } else if (this.generalHiddenDangerConfig === 1) {
        return this.activeTab === 1
      } else if (this.generalHiddenDangerConfig === 2) {
        return this.activeTab == 1
      } else {
        return true
      }