bxztApp/packages/screen/src/views/RiskWarning/Dialog/hazardPointSituationDialog.vue

747 lines
22 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>
<base-dialog
:visible="props.visible"
:title="props.title"
:table-data="tableData"
:table-columns="tableColumns"
:table-height="450"
:total="total"
:current-page="currentPage"
:page-size="pageSize"
:z-index="2000"
:max-width="900"
:show-filter="false"
:table-show="false"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
@close="handleClose"
>
<!-- 自定义内容区域 -->
<template #header>
<div class="hazard-info-panel">
<!-- 基本信息 -->
<div class="info-section">
<div class="info-row">
<div class="info-item">
<span class="info-label">区县名称</span>
<span class="info-value">{{ hazardData.district }}</span>
</div>
<div class="info-item">
<span class="info-label">风险等级</span>
<span class="info-value">{{ hazardData.riskLevel }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">路线名称</span>
<span class="info-value">{{ hazardData.roadName }}</span>
</div>
<div class="info-item">
<span class="info-label">公路编号</span>
<span class="info-value">{{ hazardData.roadCode }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">位置</span>
<span class="info-value">{{ hazardData.location }}</span>
</div>
<div class="info-item">
<span class="info-label">风险类型</span>
<span class="info-value">{{ hazardData.riskType }}</span>
</div>
</div>
</div>
<!-- 照片 - 路段数据展示 -->
<div v-if="hazardData.photos" class="info-block display">
<div class="block-title mr_10">照片</div>
<div class="photo-list">
<img v-for="(photo, index) in hazardData.photos" :key="index" :src="photo" class="photo-item" @click="previewPhoto(index)" />
</div>
</div>
<!-- 图片预览组件 -->
<el-image-viewer v-if="previewVisible" :url-list="hazardData.photos" :initial-index="previewIndex" @close="previewVisible = false" />
<!-- 风险描述 -->
<div class="info-block">
<div class="block-title">风险描述</div>
<div class="block-content">{{ hazardData.riskDescription }}</div>
</div>
<!-- 采取措施 -->
<div class="info-block">
<div class="block-title">采取措施</div>
<div class="block-content">{{ hazardData.measures }}</div>
</div>
<!-- 专家意见 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData && hazardData.expertOpinion" class="info-block">
<div class="block-title">专家意见</div>
<div class="block-content">{{ hazardData.expertOpinion }}</div>
</div>
<!-- 三级包保责任人 -->
<div class="info-block display jc_sb">
<div class="block-title">三级包保责任人</div>
<div class="responsibility-list">
<div class="responsibility-item">
<span class="responsibility-label">交通主管部门责任人</span>
<span class="responsibility-name">{{ hazardData.trafficDept.name }}</span>
<span class="responsibility-phone">{{ hazardData.trafficDept.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.trafficDept.frequency }}</span>
<div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.trafficDept, '交通主管部门责任人')" title="视频">
<el-icon><VideoCamera /></el-icon>
</div>
<div class="action-btn" @click="handleVoice(hazardData.trafficDept, '交通主管部门责任人')" title="语音">
<el-icon><Microphone /></el-icon>
</div>
<div class="action-btn" @click="handleCall(hazardData.trafficDept, '交通主管部门责任人')" title="电话">
<el-icon><Phone /></el-icon>
</div>
</div>
<span class="fs_12">半年巡查一次</span>
</div>
<div class="responsibility-item">
<span class="responsibility-label">公路机构责任人</span>
<span class="responsibility-name">{{ hazardData.roadOrg.name }}</span>
<span class="responsibility-phone">{{ hazardData.roadOrg.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.roadOrg.frequency }}</span>
<div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.roadOrg, '公路机构责任人')" title="视频">
<el-icon><VideoCamera /></el-icon>
</div>
<div class="action-btn" @click="handleVoice(hazardData.roadOrg, '公路机构责任人')" title="语音">
<el-icon><Microphone /></el-icon>
</div>
<div class="action-btn" @click="handleCall(hazardData.roadOrg, '公路机构责任人')" title="电话">
<el-icon><Phone /></el-icon>
</div>
</div>
<span class="fs_12">每月巡查一次</span>
</div>
<div class="responsibility-item">
<span class="responsibility-label">养护站责任人</span>
<span class="responsibility-name">{{ hazardData.maintenance.name }}</span>
<span class="responsibility-phone">{{ hazardData.maintenance.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.maintenance.frequency }}</span>
<div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.maintenance, '养护站责任人')" title="视频">
<el-icon><VideoCamera /></el-icon>
</div>
<div class="action-btn" @click="handleVoice(hazardData.maintenance, '养护站责任人')" title="语音">
<el-icon><Microphone /></el-icon>
</div>
<div class="action-btn" @click="handleCall(hazardData.maintenance, '养护站责任人')" title="电话">
<el-icon><Phone /></el-icon>
</div>
</div>
<span class="fs_12">每周巡查一次</span>
</div>
</div>
</div>
<!-- 护路员 -->
<div class="info-block display jc_sb">
<div class="block-title">护路员:</div>
<div class="f1 display ai_center jc_end" style="gap: 8px">
<span class="responsibility-name">{{ hazardData.roadKeeper.name }}</span>
<span class="responsibility-name" style="width: 100px">{{ hazardData.roadKeeper.phone }}</span>
<span class="responsibility-frequency">{{ hazardData.roadKeeper.frequency }}</span>
<div class="action-btns">
<div class="action-btn" @click="handleVideo(hazardData.roadKeeper, '护路员')" title="视频">
<el-icon><VideoCamera /></el-icon>
</div>
<div class="action-btn" @click="handleVoice(hazardData.roadKeeper, '护路员')" title="语音">
<el-icon><Microphone /></el-icon>
</div>
<div class="action-btn" @click="handleCall(hazardData.roadKeeper, '护路员')" title="电话">
<el-icon><Phone /></el-icon>
</div>
</div>
<span class="fs_12">一周巡查两次</span>
</div>
</div>
<!-- 预警预报关 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData" class="info-row simple-row">
<span class="row-label">预警预报关</span>
<!-- <span class="row-value">{{ hazardData.earlyWarning }}</span> -->
</div>
<!-- 线下巡查关 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData" class="info-row simple-row">
<span class="row-label">线下巡查关</span>
<!-- <span class="row-value">{{ hazardData.offlinePatrol }}</span> -->
</div>
<!-- 交通管控关 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData" class="info-row simple-row">
<span class="row-label">交通管控关</span>
<!-- <span class="row-value">{{ hazardData.trafficControl }}</span> -->
</div>
<!-- 力量预置关 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData" class="info-row simple-row">
<span class="row-label">力量预置关</span>
<!-- <span class="row-value">{{ hazardData.forcePreposition }}</span> -->
<el-icon class="location-icon"><Location /></el-icon>
</div>
<!-- 告警阻拦关 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData" class="info-row simple-row">
<span class="row-label">告警阻拦关</span>
<!-- <span class="row-value">{{ hazardData.alarmBlocking }}</span> -->
</div>
<!-- 备注 - 仅涉灾隐患点显示 -->
<div v-if="!isRoadData && hazardData.remark" class="info-block display jc_sb">
<div class="block-title">备注</div>
<!-- <div class="block-content">{{ hazardData.remark }}</div> -->
</div>
</div>
</template>
</base-dialog>
</template>
<script setup>
import { ref, watch, computed } from 'vue'
import { Location, VideoCamera, Microphone, Phone } from '@element-plus/icons-vue'
import baseDialog from '../component/baseDialog.vue'
import { openVideoConference, openVoiceConference, opencallConference, getImageUrlList } from '../component/index.js'
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
data: {
type: Object,
default: () => ({}),
},
title: {
type: String,
default: '涉灾隐患点情况',
},
})
const emit = defineEmits(['update:visible', 'close', 'video', 'voice', 'call'])
// 判断是否为路段数据
const isRoadData = computed(() => {
return props.data?.dataType === 'road'
})
// 表格列配置(为空,因为使用自定义内容)
const tableColumns = ref([])
const tableData = ref([])
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
// 隐患点数据(根据数据库字段映射)
const hazardData = ref({
// 基本信息
district: '', // GL1_QXMC 区县名称
riskLevel: '', // GL1_FXDJ 风险等级
roadCode: '', // GL1_GLBH 路线编号
roadName: '', // GL1_GLMC 路线名称
location: '', // GL1_QDZH 起点桩号 + GL1_ZDZH 止点桩号
riskDescription: '', // GL1_FXMS 风险描述
riskType: '', // GL1_FXLX 风险类型
measures: '', // GL1_CQCS 采取措施
isWithinRedLine: '', // GL1_SFHXN 是否红线内
// 三级包保责任人
trafficDept: {
name: '', // GL1_JTXM 交通主管责任人姓名
phone: '', // GL1_JTDH 交通主管责任人电话
frequency: '',
},
roadOrg: {
name: '', // GL1_JGXM 公路机构责任人姓名
phone: '', // GL1_JGDH 公路机构责任人电话
frequency: '',
},
maintenance: {
name: '', // GL1_YHXM 养护站责任人姓名
phone: '', // GL1_YHDH 养护站责任人电话
frequency: '',
},
roadKeeper: {
name: '', // GL1_HLXM 护路员姓名
phone: '', // GL1_HLDH 护路员电话
frequency: '',
},
// 六关信息
earlyWarning: '', // GL1_YJDJ 预警等级
offlinePatrol: '', // GL1_SFJCD 是否是监测点
trafficControl: '', // GL1_SFZCQS 是否采取措施
forcePreposition: '', // GL1_ZT 显示状态
alarmBlocking: '', // GL1_SFZZWC 是否完成整治
// 其他信息
isMeasureTaken: '', // GL1_SFCQCS 是否采取措施
completeDeadline: '', // GL1_WCSX 完成时限
expertOpinion: '', // GL1_ZJYJ 专家意见
isTransferred: '', // GL1_SFGZYJ 是否规治移交
auditStatus: '', // GL1_SHZT 审核状态
auditUnit: '', // GL1_SHDW 审核单位
reporter: '', // GL1_SBR 上报人姓名
reportTime: '', // GL1_SBSJ 上报时间
remark: '', // GL1_BZ 备注
// 坐标信息
longitude: '', // GL1_LON 经度
latitude: '', // GL1_LAT 纬度
// 照片信息(路段数据)
photos: [], // 照片列表
})
// 关闭弹窗
const handleClose = () => {
emit('update:visible', false)
emit('close')
}
// 分页操作
const handleSizeChange = (val) => {
pageSize.value = val
}
const handleCurrentChange = (val) => {
currentPage.value = val
}
// 图片预览状态
const previewVisible = ref(false)
const previewIndex = ref(0)
// 预览照片
const previewPhoto = (index) => {
previewIndex.value = index
previewVisible.value = true
}
// 视频通话
const handleVideo = (item, type) => {
console.log('视频通话:', item)
let textType = ''
if (props.title.includes('涉灾隐患点')) {
textType = '涉灾隐患点'
} else if (props.title.includes('路段')) {
textType = '路段'
}
let videoParams = {
...item,
id: hazardData.value.id,
type: type,
role: getRolefn(type),
textType: textType,
}
openVideoConference(videoParams)
// emit('video', {
// ...item,
// id: hazardData.value.id,
// })
}
// 语音通话
const handleVoice = (item, type) => {
console.log('语音通话:', item)
let textType = ''
if (props.title.includes('涉灾隐患点')) {
textType = '涉灾隐患点'
} else if (props.title.includes('路段')) {
textType = '路段'
}
let voiceParams = {
...item,
id: hazardData.value.id,
type: type,
role: getRolefn(type),
textType: textType,
}
openVoiceConference(voiceParams)
// emit('voice', {
// ...item,
// id: hazardData.value.id,
// })
}
// 拨打电话
const handleCall = (item, type) => {
console.log('拨打电话:', item)
let textType = ''
if (props.title.includes('涉灾隐患点')) {
textType = '涉灾隐患点'
} else if (props.title.includes('路段')) {
textType = '路段'
}
emit('call', {
...item,
id: hazardData.value.id,
type: type,
role: getRolefn(type),
textType: textType,
})
}
const getRolefn = (item) => {
if (item == '交通主管部门责任人') {
return '责任人'
} else if (item == '公路机构责任人') {
return '责任人'
} else if (item == '养护站责任人') {
return '站长'
} else if (item == '护路员') {
return '一般人员'
} else {
return '-'
}
}
// 监听visible变化
watch(
() => props.visible,
(newVal) => {
if (newVal && props.data) {
// 根据数据库字段映射数据
const data = props.data
hazardData.value = {
// 基本信息
district: data.GL1_QXMC || data.district || '',
riskLevel: data.GL1_FXDJ || data.riskLevel || '',
roadCode: data.GL1_GLBH || data.roadCode || '',
roadName: data.GL1_GLMC || data.roadName || '',
location: data.GL1_QDZH && data.GL1_ZDZH ? `${data.GL1_QDZH}${data.GL1_ZDZH}` : data.location || '',
riskDescription: data.GL1_FXMS || data.riskDescription || '',
riskType: data.GL1_FXLX || data.riskType || '',
measures: data.GL1_CQCS || data.measures || '',
isWithinRedLine: data.GL1_SFHXN || data.isWithinRedLine || '',
id: data.GL1_ID || '',
// 三级包保责任人
trafficDept: {
name: data.GL1_JTXM || data.trafficDept?.name || '',
phone: data.GL1_JTDH || data.trafficDept?.phone || '',
frequency: data.trafficDept?.frequency || '',
},
roadOrg: {
name: data.GL1_JGXM || data.roadOrg?.name || '',
phone: data.GL1_JGDH || data.roadOrg?.phone || '',
frequency: data.roadOrg?.frequency || '',
},
maintenance: {
name: data.GL1_YHXM || data.maintenance?.name || '',
phone: data.GL1_YHDH || data.maintenance?.phone || '',
frequency: data.maintenance?.frequency || '',
},
roadKeeper: {
name: data.GL1_HLXM || data.roadKeeper?.name || '',
phone: data.GL1_HLDH || data.roadKeeper?.phone || '',
frequency: data.roadKeeper?.frequency || '',
},
// 六关信息
earlyWarning: data.GL1_YJDJ || data.earlyWarning || '',
offlinePatrol: data.GL1_SFJCD || data.offlinePatrol || '',
trafficControl: data.GL1_SFZCQS || data.trafficControl || '',
forcePreposition: data.GL1_ZT || data.forcePreposition || '',
alarmBlocking: data.GL1_SFZZWC || data.alarmBlocking || '',
// 其他信息
isMeasureTaken: data.GL1_SFCQCS || data.isMeasureTaken || '',
completeDeadline: data.GL1_WCSX || data.completeDeadline || '',
expertOpinion: data.GL1_ZJYJ || data.expertOpinion || '',
isTransferred: data.GL1_SFGZYJ || data.isTransferred || '',
auditStatus: data.GL1_SHZT || data.auditStatus || '',
auditUnit: data.GL1_SHDW || data.auditUnit || '',
reporter: data.GL1_SBR || data.reporter || '',
reportTime: data.GL1_SBSJ || data.reportTime || '',
remark: data.GL1_BZ || data.remark || '',
// 坐标信息
longitude: data.GL1_LON || data.longitude || '',
latitude: data.GL1_LAT || data.latitude || '',
// 照片信息(优先使用 GL1_TP 生成图片地址)
photos: data.GL1_TP ? getImageUrlList(data.GL1_TP) : data.photos || [],
}
}
},
{ immediate: true },
)
</script>
<style lang="scss" scoped>
.hazard-info-panel {
height: 500px;
width: 650px;
color: rgba(255, 255, 255, 0.9);
overflow-y: auto;
// 自定义滚动条样式
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: rgba(20, 46, 73, 0.3);
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #142e49;
border-radius: 3px;
&:hover {
background: #1a3a5c;
}
}
// Firefox 滚动条样式
scrollbar-width: thin;
scrollbar-color: #142e49 rgba(20, 46, 73, 0.3);
.info-section {
margin-bottom: 16px;
}
.info-row {
display: flex;
margin-bottom: 12px;
&.simple-row {
align-items: center;
padding: 8px 0;
border-bottom: 1px solid rgba(64, 169, 255, 0.1);
.row-label {
width: 100px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
}
.row-value {
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
&.name {
color: #40a9ff;
width: auto;
flex: none;
margin-right: 8px;
}
&.phone {
color: #40a9ff;
width: auto;
flex: none;
margin-right: 16px;
}
&.frequency {
color: rgba(255, 255, 255, 0.6);
width: auto;
flex: none;
}
}
.location-icon {
color: #40a9ff;
font-size: 16px;
cursor: pointer;
margin-left: 8px;
}
}
}
.info-item {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
.info-label {
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
}
.info-value {
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
font-weight: 500;
}
}
.info-block {
margin-bottom: 16px;
padding: 12px;
background: rgba(64, 169, 255, 0.05);
border-radius: 4px;
// align-items: center;
.block-title {
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
margin-bottom: 8px;
}
.block-content {
color: rgba(255, 255, 255, 0.9);
font-size: 14px;
line-height: 1.6;
}
.responsibility-label {
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
flex-shrink: 0;
}
.responsibility-name {
color: #40a9ff;
font-size: 14px;
flex-shrink: 0;
}
// 按钮组
.action-btns {
display: flex;
flex-shrink: 0;
display: flex;
align-items: center;
.action-btn {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
color: #40a9ff;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
border-radius: 4px;
&:hover {
color: #40a9ff;
background: rgba(64, 169, 255, 0.1);
}
}
}
}
.responsibility-list {
display: flex;
flex-direction: column;
gap: 8px;
.responsibility-item {
display: flex;
align-items: center;
gap: 8px;
.responsibility-label {
width: 140px;
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
flex-shrink: 0;
}
.responsibility-name {
color: #40a9ff;
font-size: 14px;
flex-shrink: 0;
}
.responsibility-phone {
color: #40a9ff;
font-size: 14px;
width: 100px;
flex-shrink: 0;
}
.responsibility-frequency {
color: rgba(255, 255, 255, 0.6);
font-size: 13px;
flex: 1;
min-width: 0;
}
// 按钮组
.action-btns {
display: flex;
flex-shrink: 0;
display: flex;
align-items: center;
.action-btn {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
color: #40a9ff;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
border-radius: 4px;
&:hover {
color: #40a9ff;
background: rgba(64, 169, 255, 0.1);
}
}
}
}
}
// 护路员行的按钮样式
.simple-row {
.action-btns {
display: flex;
margin-left: auto;
.action-btn {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
color: #40a9ff;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
border-radius: 4px;
&:hover {
color: #40a9ff;
background: rgba(64, 169, 255, 0.1);
}
}
}
}
// 照片列表样式
.photo-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
.photo-item {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 4px;
cursor: pointer;
border: 1px solid rgba(64, 169, 255, 0.3);
transition: all 0.3s ease;
&:hover {
border-color: #40a9ff;
transform: scale(1.05);
}
}
}
}
</style>