<template>
|
|
<CardBox
|
|
class="card-page report-bg"
|
|
:showTitle="false"
|
|
>
|
|
<div class="report-toolbar">
|
|
<el-button
|
|
class="report-back-btn"
|
|
type="primary"
|
|
icon="el-icon-back"
|
|
size="mini"
|
|
@click="backPage"
|
|
>返回</el-button>
|
|
</div>
|
|
<el-table
|
|
class="report-table"
|
|
border
|
|
:data="pointInfo.headerInfoList"
|
|
:show-header="false"
|
|
:span-method="headerSpan"
|
|
>
|
|
<el-table-column prop="title1" label="">
|
|
<template slot-scope="scope">
|
|
<span class="header-title">{{ scope.row.title1 }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="info1" label=""> </el-table-column>
|
|
<el-table-column prop="title2" label="">
|
|
<template slot-scope="scope">
|
|
<span class="header-title">{{ scope.row.title2 }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="info2" label=""> </el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 缺陷点位汇总 - 按任务分组 -->
|
|
<div
|
|
style="margin-top: 10px"
|
|
v-if="
|
|
pointInfo.errorPointsByTask &&
|
|
Object.keys(pointInfo.errorPointsByTask).length > 0
|
|
"
|
|
>
|
|
<div class="point-info-title">缺陷结果数量汇总</div>
|
|
<div
|
|
v-for="(taskPoints, taskName) in pointInfo.errorPointsByTask"
|
|
:key="'error_' + taskName"
|
|
class="task-group"
|
|
>
|
|
<div
|
|
class="task-group-title"
|
|
v-if="shouldShowTaskName(taskName, 'error')"
|
|
>
|
|
任务名称:{{ taskName }}
|
|
</div>
|
|
<el-table class="report-table" border stripe :data="getPaginatedData('error', taskName)">
|
|
<el-table-column
|
|
prop="code"
|
|
label="编号"
|
|
align="center"
|
|
width="80"
|
|
></el-table-column>
|
|
<el-table-column
|
|
prop="area"
|
|
label="区域"
|
|
align="center"
|
|
></el-table-column>
|
|
<el-table-column
|
|
prop="pointName"
|
|
label="点位"
|
|
align="center"
|
|
></el-table-column>
|
|
<el-table-column
|
|
prop="inspectionResults"
|
|
label="巡视结果"
|
|
align="center"
|
|
></el-table-column>
|
|
<el-table-column prop="inspectionImg" label="巡视图像" align="center">
|
|
<template slot-scope="scope">
|
|
<div class="inspection-img-wrap">
|
|
<!-- 直接使用原来的 inspectionImg,让 AsyncImage 自己处理 -->
|
|
<AsyncImage
|
|
class="inspection-img"
|
|
fit="contain"
|
|
:src="scope.row.inspectionImg"
|
|
@click="lookImageDetail(scope.row.inspectionImg)"
|
|
></AsyncImage>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页组件 -->
|
|
<div
|
|
class="pagination-wrap"
|
|
v-if="getTotalCount('error', taskName) > pageSize"
|
|
>
|
|
<el-pagination
|
|
background
|
|
small
|
|
layout="total, prev, pager, next"
|
|
:total="getTotalCount('error', taskName)"
|
|
:page-size="pageSize"
|
|
:current-page.sync="currentPageMap[`error_${taskName}`]"
|
|
@current-change="() => $forceUpdate()"
|
|
>
|
|
</el-pagination>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 正常点位汇总 - 按任务分组 -->
|
|
<div
|
|
style="margin-top: 10px"
|
|
v-if="
|
|
pointInfo.normalPointsByTask &&
|
|
Object.keys(pointInfo.normalPointsByTask).length > 0
|
|
"
|
|
>
|
|
<div class="point-info-title">正常结果数量汇总</div>
|
|
<div
|
|
v-for="(taskPoints, taskName) in pointInfo.normalPointsByTask"
|
|
:key="'normal_' + taskName"
|
|
class="task-group"
|
|
>
|
|
<div
|
|
class="task-group-title"
|
|
v-if="shouldShowTaskName(taskName, 'normal')"
|
|
>
|
|
任务名称:{{ taskName }}
|
|
</div>
|
|
<el-table class="report-table" border stripe :data="getPaginatedData('normal', taskName)">
|
|
<el-table-column
|
|
prop="code"
|
|
label="编号"
|
|
align="center"
|
|
width="80"
|
|
></el-table-column>
|
|
<el-table-column
|
|
prop="area"
|
|
label="区域"
|
|
align="center"
|
|
></el-table-column>
|
|
<el-table-column
|
|
prop="pointName"
|
|
label="点位"
|
|
align="center"
|
|
></el-table-column>
|
|
<el-table-column
|
|
prop="inspectionResults"
|
|
label="巡视结果"
|
|
align="center"
|
|
></el-table-column>
|
|
<el-table-column prop="inspectionImg" label="巡视图像" align="center">
|
|
<template slot-scope="scope">
|
|
<div class="inspection-img-wrap">
|
|
<!-- 直接使用原来的 inspectionImg,让 AsyncImage 自己处理 -->
|
|
<AsyncImage
|
|
class="inspection-img"
|
|
fit="contain"
|
|
:src="scope.row.inspectionImg"
|
|
@click="lookImageDetail(scope.row.inspectionImg)"
|
|
></AsyncImage>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页组件 -->
|
|
<div
|
|
class="pagination-wrap"
|
|
v-if="getTotalCount('normal', taskName) > pageSize"
|
|
>
|
|
<el-pagination
|
|
background
|
|
small
|
|
layout="total, prev, pager, next"
|
|
:total="getTotalCount('normal', taskName)"
|
|
:page-size="pageSize"
|
|
:current-page.sync="currentPageMap[`normal_${taskName}`]"
|
|
@current-change="() => $forceUpdate()"
|
|
>
|
|
</el-pagination>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<el-dialog
|
|
title="图片预览"
|
|
:visible.sync="showPreviewImages"
|
|
:close-on-click-modal="false"
|
|
:close-on-press-escape="false"
|
|
:destroy-on-close="true"
|
|
custom-class="card-dialog card-page"
|
|
width="70%"
|
|
append-to-body
|
|
>
|
|
<ImagePreview
|
|
v-if="showPreviewImages"
|
|
:imageUrls="showImgesUrls"
|
|
:selectImgPosition="previewImagePos"
|
|
:showTemperatureTool="false"
|
|
/>
|
|
</el-dialog>
|
|
</CardBox>
|
|
</template>
|
|
|
|
<script>
|
|
import ImagePreview from "@/views/cards/components/ImagePreview/index.vue";
|
|
import AsyncImage from "@/components/AsyncImage/index.vue";
|
|
import { getPatrolReportShaoxing } from "@/api/inspectionDataManage/inspectionReporter";
|
|
import CardBox from "../components/cardBox.vue";
|
|
|
|
export default {
|
|
name: "PatrolReportDetail",
|
|
components: { AsyncImage, ImagePreview, CardBox },
|
|
|
|
data() {
|
|
return {
|
|
lineId: null,
|
|
reportType: 0,
|
|
showPreviewImages: false,
|
|
showImgesUrls: [],
|
|
previewImagePos: 0,
|
|
reportInfo: {},
|
|
pointInfo: {},
|
|
code: "",
|
|
returnState: {},
|
|
urlFrom: "",
|
|
|
|
// 分页配置
|
|
pageSize: 20,
|
|
currentPageMap: {},
|
|
|
|
// 原始数据缓存
|
|
originalDataCache: {
|
|
error: {},
|
|
normal: {},
|
|
},
|
|
};
|
|
},
|
|
|
|
created() {
|
|
this.lineId = this.$route.query.lineId;
|
|
this.urlFrom =
|
|
this.$route.query.fromComponent || this.$route.query.fromPage;
|
|
this.reportType =
|
|
this.$route.query.reportType ?? this.$route.query.filter;
|
|
if (!this.lineId) {
|
|
this.lineId = JSON.parse(sessionStorage.getItem("reportLineId"));
|
|
}
|
|
if (
|
|
this.reportType === undefined ||
|
|
this.reportType === null ||
|
|
this.reportType === ""
|
|
) {
|
|
const savedReportType = sessionStorage.getItem("reportType");
|
|
this.reportType = savedReportType ? JSON.parse(savedReportType) : 0;
|
|
}
|
|
this.getDetail();
|
|
|
|
if (
|
|
this.urlFrom === "InspectionTask" ||
|
|
this.urlFrom === "inspectionTask"
|
|
) {
|
|
const savedState = sessionStorage.getItem("inspectionTaskState");
|
|
if (savedState) {
|
|
console.log("已保存巡检任务页面状态,返回时会自动恢复");
|
|
}
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
getDetail() {
|
|
if (!this.lineId) {
|
|
return;
|
|
}
|
|
let url = "";
|
|
if (this.urlFrom == "InspectionTask") {
|
|
url = `taskStatus`;
|
|
} else {
|
|
url = `report`;
|
|
}
|
|
getPatrolReportShaoxing(url, this.lineId, this.reportType || 0).then((res) => {
|
|
// Some deployments return detail as a JSON string; normalize it before grouping.
|
|
const report = res && res.data ? res.data : res;
|
|
if (report && typeof report.detail === "string") {
|
|
try {
|
|
report.detail = JSON.parse(report.detail);
|
|
} catch (error) {
|
|
console.warn("巡视报告详情解析失败", error);
|
|
}
|
|
}
|
|
this.reportInfo = report || {};
|
|
this.pointInfo = this.getPointInfo();
|
|
this.code = res.code;
|
|
|
|
// 初始化分页
|
|
this.initPagination();
|
|
}).catch((error) => {
|
|
this.reportInfo = {};
|
|
this.pointInfo = {};
|
|
console.error("获取巡视报告详情失败", error);
|
|
this.$modal && this.$modal.msgError("巡视报告详情加载失败");
|
|
});
|
|
},
|
|
|
|
getPointInfo() {
|
|
const headerInfoList = [
|
|
{
|
|
title1: "换流站",
|
|
info1: this.reportInfo.stationName,
|
|
title2: "",
|
|
info2: "",
|
|
},
|
|
{
|
|
title1: "审核人",
|
|
info1: this.reportInfo.checkPerson,
|
|
title2: "审核时间",
|
|
info2: this.reportInfo.checkTime,
|
|
},
|
|
{
|
|
title1: "巡视开始时间",
|
|
info1: this.reportInfo.inspectionStartTime,
|
|
title2: "巡视结束时间",
|
|
info2: this.reportInfo.inspectionEndTime,
|
|
},
|
|
{
|
|
title1: "巡视任务",
|
|
info1: this.reportInfo.inspectionTaskName,
|
|
title2: "巡视统计",
|
|
info2: this.reportInfo.patrolStatistics,
|
|
},
|
|
{
|
|
title1: "巡视结论",
|
|
info1: this.reportInfo.description,
|
|
title2: "",
|
|
info2: "",
|
|
},
|
|
];
|
|
|
|
const errorPointsByTask = {};
|
|
const normalPointsByTask = {};
|
|
|
|
if (this.reportInfo.detail) {
|
|
// 处理缺陷点位
|
|
if (this.reportInfo.detail.缺陷) {
|
|
this.reportInfo.detail.缺陷.forEach((taskGroup) => {
|
|
Object.keys(taskGroup).forEach((taskName) => {
|
|
const points = taskGroup[taskName];
|
|
if (points && points.length > 0) {
|
|
if (!errorPointsByTask[taskName]) {
|
|
errorPointsByTask[taskName] = [];
|
|
}
|
|
points.forEach((point) => {
|
|
if (point.inspectionImg) {
|
|
point.inspectionImgList = [point.inspectionImg];
|
|
} else {
|
|
point.inspectionImgList = [];
|
|
}
|
|
errorPointsByTask[taskName].push(point);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// 处理正常点位
|
|
if (this.reportInfo.detail.正常) {
|
|
this.reportInfo.detail.正常.forEach((taskGroup) => {
|
|
Object.keys(taskGroup).forEach((taskName) => {
|
|
const points = taskGroup[taskName];
|
|
if (points && points.length > 0) {
|
|
if (!normalPointsByTask[taskName]) {
|
|
normalPointsByTask[taskName] = [];
|
|
}
|
|
points.forEach((point) => {
|
|
if (point.inspectionImg) {
|
|
point.inspectionImgList = point.inspectionImg.split(",");
|
|
} else {
|
|
point.inspectionImgList = [];
|
|
}
|
|
normalPointsByTask[taskName].push(point);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
} else {
|
|
// 兼容旧数据结构
|
|
const errorPointsList = [];
|
|
const normalPointsList = [];
|
|
|
|
if (this.reportInfo.info) {
|
|
this.reportInfo.info.forEach((element) => {
|
|
element.inspectionImgList = [];
|
|
if (element.inspectionImg) {
|
|
element.inspectionImgList = element.inspectionImg.split(",");
|
|
}
|
|
|
|
if (element.pointStatus == "正常") {
|
|
normalPointsList.push(element);
|
|
} else if (element.pointStatus == "缺陷") {
|
|
errorPointsList.push(element);
|
|
}
|
|
});
|
|
}
|
|
|
|
const groupByTask = (list) => {
|
|
const grouped = {};
|
|
list.forEach((item) => {
|
|
const taskName = item.taskName || "未分类任务";
|
|
if (!grouped[taskName]) {
|
|
grouped[taskName] = [];
|
|
}
|
|
grouped[taskName].push(item);
|
|
});
|
|
return grouped;
|
|
};
|
|
|
|
Object.assign(errorPointsByTask, groupByTask(errorPointsList));
|
|
Object.assign(normalPointsByTask, groupByTask(normalPointsList));
|
|
}
|
|
|
|
// 缓存原始数据用于分页
|
|
Object.keys(errorPointsByTask).forEach((taskName) => {
|
|
this.originalDataCache.error[taskName] = [
|
|
...errorPointsByTask[taskName],
|
|
];
|
|
});
|
|
Object.keys(normalPointsByTask).forEach((taskName) => {
|
|
this.originalDataCache.normal[taskName] = [
|
|
...normalPointsByTask[taskName],
|
|
];
|
|
});
|
|
|
|
return {
|
|
headerInfoList,
|
|
errorPointsByTask,
|
|
normalPointsByTask,
|
|
errorPointsList: Object.values(errorPointsByTask).flat(),
|
|
normalPointsList: Object.values(normalPointsByTask).flat(),
|
|
};
|
|
},
|
|
|
|
initPagination() {
|
|
const errorTasks = Object.keys(this.pointInfo.errorPointsByTask || {});
|
|
const normalTasks = Object.keys(this.pointInfo.normalPointsByTask || {});
|
|
|
|
[...errorTasks, ...normalTasks].forEach((task) => {
|
|
const type = errorTasks.includes(task) ? "error" : "normal";
|
|
const key = `${type}_${task}`;
|
|
if (!this.currentPageMap[key]) {
|
|
this.currentPageMap[key] = 1;
|
|
}
|
|
});
|
|
},
|
|
|
|
getTotalCount(type, taskName) {
|
|
return this.originalDataCache[type][taskName]?.length || 0;
|
|
},
|
|
|
|
getPaginatedData(type, taskName) {
|
|
const key = `${type}_${taskName}`;
|
|
const currentPage = this.currentPageMap[key] || 1;
|
|
const allData = this.originalDataCache[type][taskName] || [];
|
|
const start = (currentPage - 1) * this.pageSize;
|
|
const end = start + this.pageSize;
|
|
return allData.slice(start, end);
|
|
},
|
|
|
|
shouldShowTaskName(taskName, type) {
|
|
let taskCount = 0;
|
|
if (type === "error") {
|
|
taskCount = Object.keys(this.pointInfo.errorPointsByTask || {}).length;
|
|
} else if (type === "normal") {
|
|
taskCount = Object.keys(this.pointInfo.normalPointsByTask || {}).length;
|
|
}
|
|
|
|
if (taskCount === 1 && taskName === this.reportInfo.inspectionTaskName) {
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
handleClose(done) {
|
|
this.$emit("update:visible", false);
|
|
},
|
|
|
|
headerSpan({ row, column, rowIndex, columnIndex }) {
|
|
if (rowIndex === 0) {
|
|
if (columnIndex === 1) {
|
|
return [1, 3];
|
|
}
|
|
}
|
|
},
|
|
|
|
lookImageDetail(imgUrl) {
|
|
this.previewImagePos = 0;
|
|
this.showImgesUrls = [imgUrl];
|
|
this.showPreviewImages = true;
|
|
},
|
|
|
|
backPage() {
|
|
const fromComponent =
|
|
this.$route.query.fromComponent || this.urlFrom || "inspectionTask";
|
|
|
|
let targetRoute = {};
|
|
|
|
if (fromComponent === "InspectionReporter") {
|
|
targetRoute = {
|
|
name: this.$route.meta.patrolWorkspace
|
|
? "InspectionWorkspaceReport"
|
|
: "PatrolReport",
|
|
};
|
|
} else {
|
|
targetRoute = {
|
|
name: this.$route.meta.patrolWorkspace
|
|
? "InspectionWorkspaceTask"
|
|
: "InspectionTaskSummary",
|
|
};
|
|
}
|
|
|
|
this.$router.replace({
|
|
...targetRoute,
|
|
query: {
|
|
from: "back",
|
|
},
|
|
});
|
|
|
|
sessionStorage.removeItem("reportLineId");
|
|
sessionStorage.removeItem("reportType");
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
::v-deep .content {
|
|
overflow: scroll;
|
|
}
|
|
::v-deep .el-table__body-wrapper {
|
|
max-height: 450px;
|
|
overflow-y: scroll;
|
|
}
|
|
.report-bg {
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.report-toolbar {
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.report-back-btn {
|
|
border: 1px solid transparent !important;
|
|
background:
|
|
linear-gradient(#01016b, #01016b) padding-box,
|
|
linear-gradient(135deg, #3988ff, #0351c6) border-box !important;
|
|
color: #43c0ff !important;
|
|
}
|
|
.header-title {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.point-info-title {
|
|
font-size: 20px;
|
|
text-align: center;
|
|
padding: 10px;
|
|
}
|
|
|
|
.task-group {
|
|
margin-top: 20px;
|
|
&:first-of-type {
|
|
margin-top: 0;
|
|
}
|
|
.task-group-title {
|
|
font-size: 14px;
|
|
padding: 8px 0;
|
|
margin-bottom: 10px;
|
|
}
|
|
}
|
|
|
|
.inspection-img-wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
.inspection-img {
|
|
width: 60px;
|
|
height: 60px;
|
|
cursor: pointer;
|
|
}
|
|
.inspection-btn {
|
|
cursor: pointer;
|
|
display: block;
|
|
padding-bottom: 20px;
|
|
}
|
|
}
|
|
|
|
.pagination-wrap {
|
|
margin-top: 15px;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
// 分页组件样式覆盖 - 正常页码白色,当前页蓝色
|
|
::v-deep .el-pagination {
|
|
.btn-prev,
|
|
.btn-next,
|
|
.el-pager li {
|
|
background-color: transparent;
|
|
color: #ffffff;
|
|
font-weight: normal;
|
|
&:not(.disabled):hover {
|
|
color: #40e5f0;
|
|
}
|
|
}
|
|
|
|
.el-pager li.active {
|
|
color: #40e5f0;
|
|
background-color: transparent;
|
|
cursor: default;
|
|
&:hover {
|
|
color: #40e5f0;
|
|
}
|
|
}
|
|
|
|
.el-pager li.disabled,
|
|
.btn-prev.disabled,
|
|
.btn-next.disabled {
|
|
color: #7f8c9a;
|
|
}
|
|
}
|
|
|
|
::v-deep .el-table {
|
|
width: 100% !important;
|
|
background: #edf4ff !important;
|
|
color: #17345f;
|
|
border-color: #6f9ed8 !important;
|
|
}
|
|
|
|
::v-deep .el-table::before,
|
|
::v-deep .el-table::after,
|
|
::v-deep .el-table--border::after,
|
|
::v-deep .el-table--group::after {
|
|
background-color: #6f9ed8 !important;
|
|
}
|
|
|
|
::v-deep .el-table__header-wrapper,
|
|
::v-deep .el-table__body-wrapper,
|
|
::v-deep .el-table__empty-block {
|
|
background: transparent !important;
|
|
background-color: transparent !important;
|
|
}
|
|
|
|
::v-deep .el-table th.el-table__cell {
|
|
background: #0b3d89 !important;
|
|
border-color: #6f9ed8 !important;
|
|
}
|
|
|
|
::v-deep .el-table th.el-table__cell .cell {
|
|
color: #ffffff !important;
|
|
}
|
|
|
|
::v-deep .el-table td.el-table__cell {
|
|
background: #edf4ff !important;
|
|
border-color: #a9c4e8 !important;
|
|
color: #17345f !important;
|
|
}
|
|
|
|
::v-deep .el-table td.el-table__cell .cell {
|
|
color: #17345f !important;
|
|
}
|
|
|
|
.card-page.report-bg ::v-deep .el-table__body .el-table__row,
|
|
.card-page.report-bg ::v-deep .el-table__body .el-table__row td.el-table__cell {
|
|
background: #edf4ff !important;
|
|
}
|
|
|
|
.card-page.report-bg ::v-deep .el-table__body .el-table__row--striped,
|
|
.card-page.report-bg ::v-deep .el-table__body .el-table__row--striped td.el-table__cell {
|
|
background: #dce9fa !important;
|
|
}
|
|
|
|
.card-page.report-bg ::v-deep .el-table__body tr:hover > td.el-table__cell {
|
|
background: #c8dcf5 !important;
|
|
}
|
|
|
|
::v-deep .el-table__body-wrapper,
|
|
::v-deep .content {
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
}
|
|
|
|
::v-deep .el-table__body-wrapper::-webkit-scrollbar,
|
|
::v-deep .content::-webkit-scrollbar {
|
|
width: 0;
|
|
height: 0;
|
|
display: none;
|
|
}
|
|
</style>
|