| | |
| | | :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" /> |
| | |
| | | <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> |
| | |
| | | :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> |
| | |
| | | getDeviceListByType, |
| | | getDeviceDetailCheckListByType |
| | | } from './service.js' |
| | | import { |
| | | getFuzzyReportWord, |
| | | getScoreReportWord, |
| | | getFuzzyReportPdfUrl, |
| | | getScoreReportPdfUrl, |
| | | } from "../planOfAudit/service"; |
| | | export default { |
| | | components: { HeaderBox }, |
| | | props: {}, |
| | |
| | | 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: [],//数据列表 |
| | | // 详情弹窗相关数据 |
| | |
| | | detailPageSize: 10, |
| | | detailTotal: 0, |
| | | currentDeviceId: null,//当前查看详情的设备ID |
| | | currentRow: null, // 当前选中的行数据 |
| | | // 委托方相关 |
| | | projectList: [], // 项目列表(委托方使用) |
| | | isClient: false, // 是否委托方端 |
| | |
| | | |
| | | // 使用统一方法,根据用户类型调用对应接口 |
| | | getDeviceListByType({ ...params }, this.isClient).then(res => { |
| | | |
| | | |
| | | // 处理 properties 字段 |
| | | this.tableList = res.records.map(item => { |
| | | return { |
| | |
| | | }, |
| | | |
| | | handleSizeChange(val) { |
| | | |
| | | |
| | | this.pageSize = val; |
| | | this.currentPage = 1; // 改变每页条数时重置到第一页 |
| | | this.getList(); |
| | | }, |
| | | |
| | | handleCurrentChange(val) { |
| | | |
| | | |
| | | this.currentPage = val; |
| | | this.getList(); |
| | | }, |
| | |
| | | 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(); |
| | |
| | | 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 => { |
| | |
| | | |
| | | // 详情弹窗分页 - 每页条数改变 |
| | | handleDetailSizeChange(val) { |
| | | |
| | | |
| | | this.detailPageSize = val; |
| | | this.detailCurrentPage = 1; |
| | | this.getDetailCheckList(); |
| | |
| | | |
| | | // 详情弹窗分页 - 当前页改变 |
| | | handleDetailCurrentChange(val) { |
| | | |
| | | |
| | | this.detailCurrentPage = val; |
| | | this.getDetailCheckList(); |
| | | }, |
| | |
| | | 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; |