2023-09-06 19:08:55 +08:00

623 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="overview">
<el-dialog :show-close="false" v-model="visible1" :style="dialogStyle" @close="closeMain">
<template #title>
<div class="title-detail">
<img src="@/assets/images/tableIcon/look.png" alt="" />
<span>查看隐患整改信息</span>
<el-icon>
<close @click="closeMain" />
</el-icon>
</div>
</template>
<div class="detail-content">
<div class="content-title">隐患记录</div>
<div class="row">
<el-row :gutter="20">
<el-col :span="8">
<span class="row-span"
>检查情况:
<span>{{
basicData?.state == 0
? "待检查"
: basicData?.state == 1
? "执法中"
: basicData?.state == 2
? "待整改"
: basicData?.state == 3
? "待审核"
: basicData?.state == 4
? "已闭合"
: basicData?.state == 5
? "已驳回"
: ""
}}</span>
</span>
</el-col>
<el-col :span="8">
<span class="row-span">工程名称:{{ basicData?.engineeringName }}</span></el-col
>
<el-col :span="8">
<span class="row-span">检查人员:{{ basicData?.inspectUserName }}</span></el-col
>
</el-row>
</div>
<div class="row">
<el-row :gutter="20">
<el-col :span="8">
<span class="row-span">检查时间:{{ basicData?.createTime }}</span>
</el-col>
<el-col :span="8">
<span class="row-span">建设单位:{{ basicData?.buildEnt }}</span></el-col
>
<el-col :span="8">
<span class="row-span">监理单位:{{ basicData?.supervisorEnt }}</span></el-col
>
</el-row>
</div>
<div class="row">
<el-row :gutter="20">
<el-col :span="8">
<span class="row-span">施工单位:{{ basicData?.opEnt }}</span>
</el-col>
<el-col :span="8">
<span class="row-span">勘察单位:{{ basicData?.surveyEnt }}</span></el-col
>
<el-col :span="8">
<span class="row-span">设计单位:{{ basicData?.designEnt }}</span></el-col
>
</el-row>
</div>
<div class="row">
<el-row :gutter="20">
<el-col :span="8">
<span class="row-span">责任区域:{{ basicData?.address }}</span>
</el-col>
<el-col :span="8">
<span class="row-span">整改类型:{{ basicData?.requireType == 1 ? "限期整改" : "停工整改" }}</span></el-col
>
<el-col :span="8">
<span class="row-span">整改期限:{{ basicData?.deadline }}</span></el-col
>
</el-row>
</div>
</div>
<div class="detail-table">
<div class="content-title">整改/复查记录</div>
<div class="table">
<el-table
:data="recordData"
class="el-table"
:row-style="{ height: '40px' }"
:header-cell-style="{ backgroundColor: '#F5F7FA', textAlign: 'center', height: '40px' }"
:cell-style="{ textAlign: 'center', height: '40px' }"
@row-click="rowClick"
>
<el-table-column prop="createByName" label="创建人" />
<el-table-column prop="questionDesc" label="隐患问题" :show-overflow-tooltip="true" />
<el-table-column label="隐患照片">
<template #default="scope">
<el-image
v-if="scope.row.image && scope.row.image.length > 0"
style="width: 38px; height: 28px"
:src="scope.row.image[0].url"
fit="fill"
></el-image>
</template>
</el-table-column>
<el-table-column prop="state" label="整改状态">
<template #default="scope">
<span>{{
scope.row.state == 1
? "待整改"
: scope.row.state == 2
? "待审核"
: scope.row.state == 3
? "已闭合"
: scope.row.state == 4
? "已驳回"
: ""
}}</span>
</template>
</el-table-column>
</el-table>
</div>
<!-- <div class="operation-btn" v-if="basicData?.state != 4">
<el-button type="info" style="margin-right: 98px">驳回,请尽快整改</el-button>
<el-button type="primary">整改完成,全部合格</el-button>
<el-button type="primary" @click="allSubmit">全部整改完成,提交审核</el-button>
</div> -->
</div>
<div class="transform-record" v-if="transformDialog">
<div class="title-detail">
<img src="@/assets/images/tableIcon/look.png" alt="" />
<span>整改记录</span>
<el-icon>
<close @click="closeSecondary" />
</el-icon>
</div>
<div class="content-title">隐患问题</div>
<div class="row">
<span>创建人:</span>
<span>{{ recordRowData.createByName }}</span>
</div>
<div class="row">
<span>创建时间:</span>
<span>{{ recordRowData.createTime }}</span>
</div>
<div class="row">
<span>隐患问题:</span>
<span>{{ recordRowData.questionDesc }}</span>
</div>
<div class="row">
<span>备注:</span>
<span>{{ recordRowData.remark }}</span>
</div>
<div class="row">
<span>隐患照片:</span>
<div class="imgList" v-if="recordRowData.image">
<el-image
:src="item.url"
fit="fill"
v-for="(item, index) in recordRowData.image"
:key="index"
:preview-src-list="[item.url]"
>
</el-image>
</div>
</div>
<div class="situation">
<span>整改情况</span>
<el-button type="success" @click="addSituation" v-if="recordRowData.state === 1 || recordRowData.state === 4"
>新增整改记录</el-button
>
</div>
<div class="situation-step">
<el-timeline>
<el-timeline-item :timestamp="item.createTime" placement="top" v-for="(item, index) in timelineList" :key="index">
<div class="row">
<span>整改人:</span>
<template v-if="item.type && item.type == 'insert'">
<el-input v-model="reformInfo.solveBy" placeholder="请输入" />
</template>
<span v-else>{{ item.solveBy }}</span>
</div>
<div class="row">
<span>整改日期:</span>
<template v-if="item.type && item.type == 'insert'">
<el-date-picker
v-model="reformInfo.solveTime"
type="datetime"
style="width: 100%"
placeholder="请选择日期"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</template>
<span v-else>{{ item.solveTime }}</span>
</div>
<div class="row">
<span>整改回复:</span>
<template v-if="item.type && item.type == 'insert'">
<el-input v-model="reformInfo.solveDesc" type="textarea" :rows="2" placeholder="请输入" />
</template>
<span v-else>{{ item.solveDesc }}</span>
</div>
<div class="row">
<span>整改照片:</span>
<div class="face-img" v-if="item.type && item.type == 'insert'">
<div class="imgList" v-if="reformInfo.solveImage.length > 0">
<img :src="item.url" class="face-avatar" v-for="(item, index) in reformInfo.solveImage" :key="index" />
</div>
<el-upload
class="face-uploader"
:action="`${baseUrl}` + '/xmgl/file/upload'"
:show-file-list="false"
:on-success="handleAvatarSuccess"
accept="image/jpg, image/jpeg, image/png"
>
<el-icon><plus /></el-icon>
</el-upload>
</div>
<div class="imgList" v-else-if="Array.isArray(item.solveImage)">
<img :src="item.url" alt="" v-for="(item, index) in item.solveImage" :key="index" />
</div>
</div>
<div class="row" v-if="item.suggest">
<span>审核意见:</span>
<span>{{ item.suggest }}</span>
</div>
<div
class="status-name"
:style="{ color: item.examineState === 0 ? '#008BFF' : item.examineState === 1 ? '#30AC7C' : '#F64D31' }"
v-if="!item.type"
>
{{ item.examineState == 0 ? "待审核" : item.examineState == 1 ? "已通过" : "已驳回" }}
</div>
<!-- <div class="status-operate" v-if="item.examineState === 0">
<el-button type="primary" @click="auditVisible = true">审核</el-button>
</div> -->
<div class="status-operate" v-if="item.type">
<el-button type="primary" @click="submitForm">提交</el-button>
</div>
</el-timeline-item>
</el-timeline>
</div>
</div>
</el-dialog>
<el-dialog v-model="auditVisible" :append-to-body="true">
<template #title>
<div style="border-left: 2px solid #0f81ff; font-size: 20px; color: #333333">
<span style="margin-left: 5px">审核意见</span>
</div>
</template>
<el-input type="textarea" :rows="2" placeholder="请输入内容" />
<template #footer>
<span class="dialog-footer">
<el-button @click="auditVisible = false"> </el-button>
<el-button type="primary" @click="auditVisible = false"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, watch, reactive } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { FormInstance, UploadProps } from "element-plus";
import { locationCheckDetails, locationUpdateDetails, locationSubmitReform, locationSubmitAll } from "@/api/modules/project";
const baseUrl = import.meta.env.VITE_API_URL;
const props = defineProps({
detailsDialog: Boolean,
relativeId: String
});
const emits = defineEmits(["update:detailsDialog", "confirm"]);
const visible1 = ref(false);
const transformDialog = ref(false); // 整改记录对话框
const recordData = ref([]); // 整改记录表格数据
const recordRowData = ref(); // 整改记录表格行数据
const basicData = ref(); // 基础信息
const dialogStyle = ref({
"min-width": "824px"
});
const reformInfo = ref({
solveBy: "",
solveTime: "",
solveDesc: "",
solveImage: []
});
// 全部整改完成,提交
const allSubmit = async () => {
const res = await locationSubmitAll({ id: basicData.value.id });
closeMain();
ElMessage.success("提交成功");
};
// 关闭两个对话框
const closeMain = () => {
visible1.value = false;
transformDialog.value = false;
dialogStyle.value = {
"min-width": "824px",
transform: "translateX(0px)"
};
};
// 关闭整改记录辅弹框
const closeSecondary = () => {
transformDialog.value = false;
dialogStyle.value = {
"min-width": "824px",
transform: "translateX(0px)"
};
};
// 提交整改情况
const submitForm = async () => {
reformInfo.value.solveImage = JSON.stringify(reformInfo.value.solveImage);
let requestData = {
...reformInfo.value,
inspectQuestionId: recordRowData.value.id
};
const res = await locationSubmitReform(requestData);
timelineList.value.shift();
getInfo();
getTimeLineList();
closeSecondary();
ElMessage.success("提交成功");
};
// 图片上传成功后的钩子
const handleAvatarSuccess: UploadProps["onSuccess"] = (response, uploadFile) => {
console.log(response.result.url);
reformInfo.value.solveImage.push({
url: response.result.url
});
};
// 点击表格任意一行时
const rowClick = row => {
recordRowData.value = row;
transformDialog.value = true;
dialogStyle.value = {
"min-width": "824px",
transform: "translateX(-170px)"
};
reformInfo.value = reactive({
solveBy: "",
solveTime: "",
solveDesc: "",
solveImage: []
});
// 全部
getTimeLineList();
};
// 相关信息接口调用
const getInfo = async () => {
const res = await locationCheckDetails({ id: props.relativeId });
basicData.value = res.result;
recordData.value = res.result.acceptInspectQuestionList;
recordData.value.map(item => {
item.image = eval(item.image);
});
console.log(recordData);
};
const timelineList = ref([{ name: 1 }]);
// 获取整改情况时间轴列表
const getTimeLineList = async () => {
const res = await locationUpdateDetails({ inspectQuestionId: recordRowData.value.id });
res.result.map(item => {
item.solveImage = eval(item.solveImage);
});
timelineList.value = res.result;
};
const addSituation = () => {
let findItem = timelineList.value.find(item => {
return item.type == "insert";
});
if (!findItem) {
timelineList.value.unshift({
type: "insert"
});
}
};
const auditVisible = ref(false);
// 监听父组件的visible用来简介控制el-dialog的弹框开关一般是用于开
watch(
() => props.detailsDialog,
(n, o) => {
visible1.value = n;
if (n) {
getInfo();
} else {
emits("confirm");
}
}
);
// 监听el-dialog显示状态再通过@update:visible 通知父组件,一般是用于关
watch(visible1, (n, o) => {
emits("update:detailsDialog", n);
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
@mixin fullwidth {
width: -webkit-fill-available;
width: -moz-available;
width: stretch;
}
@mixin flex {
display: flex;
align-items: center;
}
@mixin title {
font-size: 14px;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
color: #333333;
border-left: 2px solid #008bff;
padding-left: 5px;
}
.overview {
// background-color: #fff;
flex: 1;
:deep(.el-dialog) {
position: relative;
}
.title-detail {
@include flex;
> img {
width: 16px;
height: 18px;
}
> span {
font-size: 18px;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
color: #333333;
margin-left: 5px;
margin-right: auto;
}
:deep(.el-icon) {
cursor: pointer;
color: #a8abb2;
}
}
.detail-content {
.content-title {
@include title;
}
.row {
margin-top: 14px;
.row-span {
font-size: 12px;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
> span {
font-weight: 400;
color: #008bff;
}
}
}
}
.detail-table {
height: 391px;
margin-top: 20px;
.content-title {
@include title;
}
.table {
height: 300px;
margin-top: 20px;
:deep(.el-table) {
height: 100%;
}
}
.operation-btn {
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
}
}
.transform-record {
position: absolute;
top: 0;
right: -460px;
width: 380px;
height: calc(100% - 31px);
min-width: 420px;
background: #ffffff;
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;
margin-bottom: 24px;
}
.row {
display: flex;
margin-bottom: 12px;
span:nth-child(1) {
width: 56px;
text-align: right;
font-size: 12px;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #333333;
white-space: nowrap;
margin-right: 10px;
}
span:nth-child(2) {
font-size: 12px;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
color: #333333;
overflow-wrap: anywhere;
}
.imgList {
display: flex;
flex-wrap: wrap;
img {
width: 95px;
height: 53px;
margin-bottom: 10px;
margin-right: 15px;
}
:deep(.el-image) {
width: 95px;
height: 53px;
margin-bottom: 10px;
margin-right: 15px;
}
}
.face-img {
width: 100%;
align-self: flex-start;
@include flex;
flex-wrap: wrap;
:deep(.face-uploader .el-upload) {
border: 1px dashed #d9d9d9 !important;
border-radius: 6px !important;
cursor: pointer !important;
position: relative !important;
overflow: hidden !important;
}
.face-uploader .el-upload:hover {
border-color: #409eff !important;
}
:deep(.el-icon) {
font-size: 28px;
color: #8c939d;
width: 53px;
height: 53px;
line-height: 53px;
text-align: center;
}
.face-avatar {
width: 53px;
height: 53px;
display: block;
}
}
}
.situation {
@include flex;
border-left: 2px solid #008bff;
margin-top: 20px;
span {
margin-right: auto;
margin-left: 5px;
}
}
.situation-step {
margin-top: 20px;
overflow-y: scroll;
height: 210px;
.row {
span:nth-child(1) {
text-align: left;
}
}
:deep(.el-timeline-item) {
position: relative;
padding-bottom: 14px !important;
}
:deep(.el-timeline) {
padding: 0;
}
.status-name {
position: absolute;
right: 0;
top: 0;
font-size: 12px;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
}
.status-operate {
position: absolute;
right: 0;
bottom: -10px;
}
}
}
.audit-title {
border-left: 2px solid #0f81ff !important;
}
}
.test :deep(.el-input__wrapper) {
box-shadow: 0 0 0 0;
}
.test :deep(.el-input__inner) {
text-align: center;
}
:deep(.el-table__empty-text) {
min-height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
</style>