<template>
|
<el-dialog
|
class="gd-dialog eventDialog"
|
v-model="visible"
|
title="查看"
|
@closed="visible = false"
|
width="80%"
|
destroy-on-close
|
>
|
<div class="content" style="display: flex">
|
<div class="processBox">
|
<div class="detail-title">事件记录</div>
|
<div class="process">
|
<!-- <OrderStepBar :processList="statusFlows" />-->
|
<!-- <el-steps direction="vertical" :active="1 === 1" space="100">-->
|
<!-- <el-step-->
|
<!-- v-for="(item, index) in statusFlows"-->
|
<!-- @key="item.id"-->
|
<!-- :title="item.newStatusName"-->
|
<!-- :description="item.operateUserName"-->
|
<!-- ></el-step>-->
|
<!-- </el-steps>-->
|
<el-steps direction="vertical" :active="statusFlows.length" space="100" finish-status="success">
|
<el-step v-for="(item, index) in statusFlows" :key="item.id">
|
<template #title>
|
<div class="step-title">
|
<span class="status-name">{{ item.newStatusName }}</span>
|
<span class="operator-name">{{ item.operateUserName }}</span>
|
</div>
|
</template>
|
<template #description>
|
<div class="step-desc">
|
<span>{{ item.operateTime }}</span>
|
<span v-if="item.remark" class="remark">{{ item.remark }}</span>
|
</div>
|
</template>
|
</el-step>
|
</el-steps>
|
</div>
|
</div>
|
<div class="leftBox">
|
<div>
|
<div class="detail-title">事件详情</div>
|
<el-row class="detail-row-view">
|
<el-col :span="12">
|
<div class="label">事件名称</div>
|
<div class="val">{{ eventInfo.eventName }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">事件编号</div>
|
<div class="val">{{ eventInfo.eventNum }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">事件状态</div>
|
<div class="val">{{ getStatusLabel(eventInfo.eventStatus) }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">事件时间</div>
|
<div class="val">
|
{{ dayjs(eventInfo.shootTime).format('YYYY-MM-DD') }}
|
</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">处置人员</div>
|
<div class="val">{{ eventInfo.disposeUserName }}</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="label">处置部门</div>
|
<div class="val">{{ eventInfo.disposeDeptName }}</div>
|
</el-col>
|
</el-row>
|
</div>
|
<div class="img_flow">
|
<div class="imgurl">
|
<el-image v-if="eventInfo.attachmentType === 1"
|
:src="eventInfo.eventImageUrl"
|
:preview-src-list="[eventInfo.eventImageUrl]"
|
fit="cover"
|
preview-teleported
|
/>
|
<div class="video-btn" v-if="eventInfo.attachmentType === 3" @click="videoClick(eventInfo)">
|
<el-icon :size="30" color="#fff">
|
<VideoPlay />
|
</el-icon>
|
</div>
|
</div>
|
<div class="flow">
|
<div v-if="disposeRecords.length === 0">
|
<el-empty description="暂无处置记录数据" />
|
</div>
|
<div v-else class="flow-card" v-for="item in disposeRecords" :key="item.id">
|
<div class="flow-row1">
|
<span class="flow-name">{{ item.disposeUserName }}</span>
|
<span class="flow-status card-status" :class="statusClass(item.disposeStatus)">{{ item.disposeStatusName }}</span>
|
</div>
|
<div class="flow-row2">{{ item.disposeContent }}</div>
|
<div class="flow-row3" v-if="item.attachUrl?.length">
|
<el-image
|
v-for="(url, imageIndex) in item.attachUrl"
|
:key="`${item.id || 'record'}-${imageIndex}`"
|
class="flow-img-item"
|
:src="url"
|
:preview-src-list="item.attachUrl"
|
fit="cover"
|
preview-teleported
|
/>
|
<!-- <img-->
|
<!-- v-for="(url, imageIndex) in item.attachUrl"-->
|
<!-- :key="`${item.id || 'record'}-${imageIndex}`"-->
|
<!-- class="flow-img-item"-->
|
<!-- :src="url"-->
|
<!-- alt=""-->
|
<!-- />-->
|
</div>
|
<div class="flow-row4">{{ item.operateTime }}</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-dialog>
|
<VideoPlayDialog ref="videoPlayDialogRef" v-if="VideoShow" v-model="VideoShow" :playUrl="eventInfo.eventImageUrl" />
|
</template>
|
|
<script setup>
|
import dayjs from 'dayjs'
|
import { getDetailFull } from './eventManageApi'
|
import OrderStepBar from './OrderStepBar.vue'
|
import { ref } from 'vue'
|
import { VideoPlay } from '@element-plus/icons-vue'
|
import VideoPlayDialog from '@/components/VideoPlayDialog.vue'
|
|
const visible = defineModel()
|
const eventInfo = ref({})
|
const disposeRecords = ref([])
|
const statusFlows = ref([])
|
const VideoShow = ref(false)
|
const videoPlayDialogRef = ref(null)
|
|
// 获取状态文本
|
const getStatusLabel = status => {
|
const map = {
|
0: '待确认',
|
1: '处置中',
|
2: '已退回',
|
3: '已处置',
|
4: '已完成',
|
}
|
return map[status] || '未知'
|
}
|
|
// 状态样式类名
|
const statusClass = status => {
|
if (status === 1) return 'status-processing'
|
if (status === 3) return 'status-handled'
|
if (status === 4) return 'status-completed'
|
return ''
|
}
|
|
// 兼容事件记录接口中不同版本的字段名称
|
function normalizeStatusFlow(item = {}) {
|
return {
|
...item,
|
newStatusName: item.newStatusName || item.statusName || item.eventStatusName || '-',
|
operateContent:
|
item.operateContent || item.operationContent || item.disposeContent || item.content || item.remark || '-',
|
operateUserName:
|
item.operateUserName || item.operatorName || item.operateUser || item.operator || item.userName || '-',
|
operateTime: item.operateTime || item.createTime || item.updateTime || '-',
|
}
|
}
|
|
function videoClick(eventInfo) {
|
// currentVideo.value = eventInfo
|
VideoShow.value = true
|
}
|
|
// 打开弹框
|
async function open({ row } = {}) {
|
if (!row?.id) return
|
console.log(row, '9098')
|
const res = await getDetailFull({ id: row.id })
|
const detail = res?.data?.data || {}
|
eventInfo.value = detail.eventInfo || {}
|
disposeRecords.value = detail.disposeRecords || []
|
statusFlows.value = (detail.statusFlows || []).map(normalizeStatusFlow)
|
}
|
|
defineExpose({ open })
|
</script>
|
<style lang="scss">
|
.eventDialog {
|
.el-dialog__body {
|
display: flex;
|
flex-direction: column;
|
.content {
|
height: 0;
|
flex: 1;
|
}
|
}
|
}
|
</style>
|
<style scoped lang="scss">
|
.content {
|
display: flex;
|
gap: 0 20px;
|
//height: 630px;
|
|
.leftBox {
|
width: 0;
|
flex: 1;
|
display: flex;
|
//overflow-y: hidden;
|
//overflow-x: hidden;
|
flex-direction: column;
|
overflow: hidden;
|
//scrollbar-width: none;
|
|
&::-webkit-scrollbar {
|
display: none;
|
}
|
|
//.gd-cesium {
|
// position: relative;
|
// //overflow: hidden;
|
// width: 100%;
|
// height: 390px;
|
//}
|
.img_flow {
|
//border: 1px solid red;
|
display: flex;
|
justify-content: space-between;
|
height: 440px;
|
margin-top: 20px;
|
.imgurl {
|
flex: 1;
|
height: 100%;
|
img {
|
height: 100%;
|
width: 100%;
|
}
|
}
|
.video-btn {
|
width: 100%;
|
height:100%;
|
position: relative;
|
overflow: hidden;
|
border-radius: 4px;
|
background: linear-gradient(135deg, rgba(76, 52, 255, 0.14), rgba(76, 52, 255, 0) 48%),
|
linear-gradient(180deg, #f4f5ff 0%, #e9ecff 100%);
|
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.7);
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
|
&::before {
|
content: '';
|
position: absolute;
|
inset: 0;
|
background-image: linear-gradient(
|
90deg,
|
rgba(76, 52, 255, 0.05) 0,
|
rgba(76, 52, 255, 0.05) 1px,
|
transparent 1px,
|
transparent 12px
|
);
|
opacity: 0.42;
|
}
|
|
.el-icon {
|
position: relative;
|
z-index: 1;
|
width: 42px;
|
height: 42px;
|
border-radius: 50%;
|
background: rgba(76, 52, 255, 0.72);
|
box-shadow: 0 4px 12px rgba(76, 52, 255, 0.2);
|
}
|
}
|
.flow {
|
margin-left: 10px;
|
flex: 1;
|
min-width: 0;
|
min-height: 0;
|
overflow-y: auto;
|
overflow-x: hidden;
|
scrollbar-width: none;
|
|
&::-webkit-scrollbar {
|
display: none;
|
}
|
|
.flow-card {
|
display: flex;
|
flex-direction: column;
|
gap: 8px;
|
margin-bottom: 8px;
|
padding: 12px;
|
border: 1px solid #e4e4e4;
|
border-radius: 8px;
|
background: #fff;
|
.flow-row1 {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
.flow-row2 {
|
font-size: 14px;
|
font-weight: 500;
|
}
|
.flow-row3 {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 8px;
|
.flow-img-item {
|
width: 60px;
|
height: 60px;
|
flex: 0 0 60px;
|
border: 1px solid #e4e4e4;
|
border-radius: 4px;
|
background: #f5f5f5;
|
object-fit: cover;
|
}
|
}
|
.flow-row4 {
|
font-size: 12px;
|
color: #999;
|
}
|
.card-status {
|
font-family: Source Han Sans CN, Source Han Sans CN;
|
font-weight: 400;
|
font-size: 14px;
|
padding: 2px 6px;
|
border-radius: 4px;
|
color: #ffffff;
|
background: #999;
|
|
&.status-processing {
|
background: #1d6fe9;
|
}
|
&.status-handled {
|
background: #e6a23c;
|
}
|
&.status-completed {
|
background: #00b578;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
.rightBox {
|
width: 350px;
|
display: flex;
|
flex-direction: column;
|
|
.title {
|
font-weight: 500;
|
font-size: 14px;
|
color: #272e37;
|
}
|
|
::v-deep(.el-table) {
|
tr th {
|
font-weight: normal;
|
}
|
}
|
}
|
|
.processBox {
|
display: flex;
|
flex-direction: column;
|
height: 650px;
|
overflow: auto;
|
|
.process {
|
height: 100%;
|
padding: 12px 16px 24px 16px;
|
width: 280px;
|
border: 1px solid #e4e4e4;
|
border-radius: 8px;
|
background: #fff;
|
overflow: auto;
|
}
|
}
|
|
.step-title {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
width: 100%;
|
padding-right: 10px;
|
}
|
|
.status-name {
|
font-weight: 500;
|
color: #4c34ff;
|
font-size: 14px;
|
}
|
|
.operator-name {
|
color: #909399;
|
font-size: 13px;
|
margin-left: 20px;
|
}
|
|
.step-desc {
|
color: #999999;
|
font-size: 12px;
|
}
|
|
.remark {
|
margin-left: 12px;
|
color: #e6a23c;
|
}
|
:deep(.el-step__icon.is-text) {
|
border-color: #4c34ff;
|
}
|
:deep(.el-step__head.is-success) {
|
color: #4c34ff;
|
height: 100px;
|
border-color: #4c34ff;
|
}
|
}
|
</style>
|