Compare commits
2 Commits
264501ee01
...
82e10762a4
| Author | SHA1 | Date | |
|---|---|---|---|
| 82e10762a4 | |||
| 9ec6f708ca |
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<base-dialog
|
||||
v-model:visible="props.visible"
|
||||
title="涉灾隐患点情况"
|
||||
:title="props.title"
|
||||
:table-data="tableData"
|
||||
:table-columns="tableColumns"
|
||||
:table-height="450"
|
||||
@ -32,17 +32,26 @@
|
||||
</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 class="info-block">
|
||||
<div class="block-title">风险描述</div>
|
||||
@ -55,8 +64,14 @@
|
||||
<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">
|
||||
<div class="info-block display jc_sb">
|
||||
<div class="block-title">三级包保责任人</div>
|
||||
<div class="responsibility-list">
|
||||
<div class="responsibility-item">
|
||||
@ -64,59 +79,122 @@
|
||||
<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-row simple-row">
|
||||
<span class="row-label">护路员</span>
|
||||
<span class="row-value name">{{ hazardData.roadKeeper.name }}</span>
|
||||
<span class="row-value phone">{{ hazardData.roadKeeper.phone }}</span>
|
||||
<span class="row-value frequency">{{ hazardData.roadKeeper.frequency }}</span>
|
||||
</div>
|
||||
<div class="info-block display jc_sb">
|
||||
<div class="block-title">护路员:</div>
|
||||
|
||||
<!-- 预警预报关 -->
|
||||
<div class="info-row simple-row">
|
||||
<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>
|
||||
<!-- <span class="row-value">{{ hazardData.earlyWarning }}</span> -->
|
||||
</div>
|
||||
|
||||
<!-- 线下巡查关 -->
|
||||
<div class="info-row simple-row">
|
||||
<!-- 线下巡查关 - 仅涉灾隐患点显示 -->
|
||||
<div v-if="!isRoadData" class="info-row simple-row">
|
||||
<span class="row-label">线下巡查关</span>
|
||||
<span class="row-value">{{ hazardData.offlinePatrol }}</span>
|
||||
<!-- <span class="row-value">{{ hazardData.offlinePatrol }}</span> -->
|
||||
</div>
|
||||
|
||||
<!-- 交通管控关 -->
|
||||
<div class="info-row simple-row">
|
||||
<!-- 交通管控关 - 仅涉灾隐患点显示 -->
|
||||
<div v-if="!isRoadData" class="info-row simple-row">
|
||||
<span class="row-label">交通管控关</span>
|
||||
<span class="row-value">{{ hazardData.trafficControl }}</span>
|
||||
<!-- <span class="row-value">{{ hazardData.trafficControl }}</span> -->
|
||||
</div>
|
||||
|
||||
<!-- 力量预置关 -->
|
||||
<div class="info-row simple-row">
|
||||
<!-- 力量预置关 - 仅涉灾隐患点显示 -->
|
||||
<div v-if="!isRoadData" class="info-row simple-row">
|
||||
<span class="row-label">力量预置关</span>
|
||||
<span class="row-value">{{ hazardData.forcePreposition }}</span>
|
||||
<!-- <span class="row-value">{{ hazardData.forcePreposition }}</span> -->
|
||||
<el-icon class="location-icon"><Location /></el-icon>
|
||||
</div>
|
||||
|
||||
<!-- 告警阻拦关 -->
|
||||
<div class="info-row simple-row">
|
||||
<!-- 告警阻拦关 - 仅涉灾隐患点显示 -->
|
||||
<div v-if="!isRoadData" class="info-row simple-row">
|
||||
<span class="row-label">告警阻拦关</span>
|
||||
<span class="row-value">{{ hazardData.alarmBlocking }}</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 v-if="isRoadData && hazardData.photos" class="info-block display jc_sb">
|
||||
<div class="block-title">照片</div>
|
||||
<div class="photo-list">
|
||||
<img v-for="(photo, index) in hazardData.photos" :key="index" :src="photo" class="photo-item" @click="previewPhoto(photo)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -124,9 +202,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { Location } from '@element-plus/icons-vue';
|
||||
import baseDialog from '../component/baseDialog.vue';
|
||||
import { ref, watch, computed } from 'vue'
|
||||
import { Location, VideoCamera, Microphone, Phone } from '@element-plus/icons-vue'
|
||||
import baseDialog from '../component/baseDialog.vue'
|
||||
import { openVideoConference } from '../component/index.js'
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
@ -137,16 +216,25 @@ const props = defineProps({
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
title: {
|
||||
type: String,
|
||||
default: '涉灾隐患点情况',
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:visible', 'close']);
|
||||
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 tableColumns = ref([])
|
||||
const tableData = ref([])
|
||||
const total = ref(0)
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
|
||||
// 隐患点数据(根据数据库字段映射)
|
||||
const hazardData = ref({
|
||||
@ -204,44 +292,73 @@ const hazardData = ref({
|
||||
// 坐标信息
|
||||
longitude: '', // GL1_LON 经度
|
||||
latitude: '', // GL1_LAT 纬度
|
||||
});
|
||||
|
||||
// 照片信息(路段数据)
|
||||
photos: [], // 照片列表
|
||||
})
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
emit('close');
|
||||
};
|
||||
emit('update:visible', false)
|
||||
emit('close')
|
||||
}
|
||||
|
||||
// 分页操作
|
||||
const handleSizeChange = val => {
|
||||
pageSize.value = val;
|
||||
};
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
}
|
||||
|
||||
const handleCurrentChange = val => {
|
||||
currentPage.value = val;
|
||||
};
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val
|
||||
}
|
||||
|
||||
// 预览照片
|
||||
const previewPhoto = (photo) => {
|
||||
// 使用 Element Plus 的图片预览功能
|
||||
const { preview } = require('element-plus')
|
||||
preview(photo)
|
||||
}
|
||||
|
||||
// 视频通话
|
||||
const handleVideo = (item) => {
|
||||
console.log('视频通话:', item)
|
||||
emit('video', {
|
||||
...item,
|
||||
id: hazardData.value.id,
|
||||
})
|
||||
}
|
||||
|
||||
// 语音通话
|
||||
const handleVoice = (item) => {
|
||||
console.log('语音通话:', item)
|
||||
emit('voice', item)
|
||||
}
|
||||
|
||||
// 拨打电话
|
||||
const handleCall = (item) => {
|
||||
console.log('拨打电话:', item)
|
||||
emit('call', item)
|
||||
}
|
||||
|
||||
// 监听visible变化
|
||||
watch(
|
||||
() => props.visible,
|
||||
newVal => {
|
||||
(newVal) => {
|
||||
if (newVal && props.data) {
|
||||
// 根据数据库字段映射数据
|
||||
const data = 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 || '',
|
||||
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: {
|
||||
@ -286,17 +403,20 @@ watch(
|
||||
// 坐标信息
|
||||
longitude: data.GL1_LON || data.longitude || '',
|
||||
latitude: data.GL1_LAT || data.latitude || '',
|
||||
};
|
||||
|
||||
// 照片信息(路段数据)
|
||||
photos: data.photos || [],
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.hazard-info-panel {
|
||||
height: 500px;
|
||||
width: 600px;
|
||||
width: 650px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
overflow-y: auto;
|
||||
// 自定义滚动条样式
|
||||
@ -342,7 +462,6 @@ watch(
|
||||
}
|
||||
|
||||
.row-value {
|
||||
flex: 1;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 14px;
|
||||
|
||||
@ -399,6 +518,7 @@ watch(
|
||||
padding: 12px;
|
||||
background: rgba(64, 169, 255, 0.05);
|
||||
border-radius: 4px;
|
||||
// align-items: center;
|
||||
|
||||
.block-title {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
@ -411,6 +531,41 @@ watch(
|
||||
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 {
|
||||
@ -427,24 +582,101 @@ watch(
|
||||
width: 140px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 13px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.responsibility-name {
|
||||
color: #40a9ff;
|
||||
font-size: 14px;
|
||||
width: 60px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.responsibility-phone {
|
||||
color: #40a9ff;
|
||||
font-size: 14px;
|
||||
width: 120px;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +68,21 @@
|
||||
<el-option v-for="option in regionOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="filter-item">
|
||||
<el-select
|
||||
:teleported="false"
|
||||
v-model="filterForm.roadType"
|
||||
size="small"
|
||||
placeholder="公路类型"
|
||||
class="filter-select"
|
||||
clearable
|
||||
@change="handleFilterChange"
|
||||
>
|
||||
<el-option v-for="option in roadTypeOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="filter-item">
|
||||
<el-button type="primary" class="search-btn" @click="handleSearch">查询</el-button>
|
||||
</div>
|
||||
@ -179,7 +194,7 @@
|
||||
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
||||
import { Close, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
|
||||
import { request } from '@/utils/request'
|
||||
import { pointTypeOptions, pointLevelOptions, regionOptions } from '../component/index.js'
|
||||
import { pointTypeOptions, pointLevelOptions, regionOptions, roadTypeOptions } from '../component/index.js'
|
||||
import baseDialog from '../component/baseDialog.vue'
|
||||
|
||||
import respondedIcon from '../../../assets/xiangying/有回应@2x.png'
|
||||
@ -213,6 +228,7 @@ const filterForm = ref({
|
||||
pointType: '',
|
||||
pointLevel: '',
|
||||
region: '',
|
||||
roadType: '',
|
||||
})
|
||||
|
||||
// 统一的表格列配置(桥梁、边坡、隧道、路段使用)
|
||||
@ -481,6 +497,7 @@ const getTimeParams = () => {
|
||||
offset: (currentPage.value - 1) * pageSize.value,
|
||||
countyName: countyName || '',
|
||||
riskLevel: filterForm.value.pointLevel || '',
|
||||
roadTypes: filterForm.value.roadType || '',
|
||||
}
|
||||
}
|
||||
// 处理数据为统一格式
|
||||
@ -791,6 +808,7 @@ watch(
|
||||
district: '',
|
||||
type: '',
|
||||
roadConditionType: '',
|
||||
roadType: '',
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -103,6 +103,7 @@ const emit = defineEmits([
|
||||
'riskPointStatsChange',
|
||||
'update:roadvalArr',
|
||||
'openHazardPointSituation',
|
||||
'openRoadSectionSituation',
|
||||
]);
|
||||
|
||||
// 当前选中的区县
|
||||
@ -846,6 +847,9 @@ const addProjectMarkers = (data, iconUrl, type = 'project') => {
|
||||
if (type === 'riskPoint') {
|
||||
// 风险点类型,触发父组件打开涉灾隐患点情况弹窗
|
||||
emit('openHazardPointSituation', item);
|
||||
} else if (type === 'road') {
|
||||
// 路段类型,触发父组件打开路段情况弹窗
|
||||
emit('openRoadSectionSituation', item);
|
||||
} else {
|
||||
openMapInfoDialog(type, item);
|
||||
}
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
// 弹窗组件统一数据配置
|
||||
import { ref } from 'vue';
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
import { ref } from 'vue'
|
||||
import { request } from '@/utils/request'
|
||||
import { ElMessage } from 'element-plus'
|
||||
// 公路类型选项
|
||||
export const roadTypeOptions = ref([
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '国省道', value: 'G,S' },
|
||||
{ label: '农村公路', value: ' X, Y, C' },
|
||||
])
|
||||
// 影响区域选项
|
||||
export const regionOptions = ref([]);
|
||||
export const regionOptions = ref([])
|
||||
|
||||
// 获取影响区域选项
|
||||
export const fetchDistrictOptions = async () => {
|
||||
@ -11,25 +17,25 @@ export const fetchDistrictOptions = async () => {
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/sm-event/dashboard/district-options',
|
||||
method: 'GET',
|
||||
});
|
||||
})
|
||||
if (res && res.code === '00000' && Array.isArray(res.data)) {
|
||||
// 将接口返回的数据转换为选项格式
|
||||
const options = res.data.map(item => ({
|
||||
const options = res.data.map((item) => ({
|
||||
label: item.qxmc,
|
||||
value: item.xzdm,
|
||||
}));
|
||||
}))
|
||||
// 保留"全部"选项,并添加接口返回的数据
|
||||
regionOptions.value = [{ label: '全部', value: '' }, ...options];
|
||||
return options;
|
||||
regionOptions.value = [{ label: '全部', value: '' }, ...options]
|
||||
return options
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取影响区域选项失败:', error);
|
||||
console.error('获取影响区域选项失败:', error)
|
||||
}
|
||||
return regionOptions.value;
|
||||
};
|
||||
return regionOptions.value
|
||||
}
|
||||
|
||||
// 路况类型选项(默认数据,会被API数据替换)
|
||||
export const typeOptions = ref([]);
|
||||
export const typeOptions = ref([])
|
||||
|
||||
// 管控措施选项(默认数据,会被API数据替换)
|
||||
export const controlMeasureOptions = ref([
|
||||
@ -39,7 +45,7 @@ export const controlMeasureOptions = ref([
|
||||
// { label: "限速限车", value: "限速限车" },
|
||||
// { label: "限速", value: "限速" },
|
||||
// { label: "告警阻拦", value: "告警阻拦" },
|
||||
]);
|
||||
])
|
||||
|
||||
// 获取路况类型选项
|
||||
export const fetchRoadConditionOptions = async () => {
|
||||
@ -47,22 +53,22 @@ export const fetchRoadConditionOptions = async () => {
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/sm-event/dashboard/processing-measure-options',
|
||||
method: 'GET',
|
||||
});
|
||||
})
|
||||
if (res && res.code === '00000' && Array.isArray(res.data)) {
|
||||
// 将接口返回的字符串数组转换为选项格式
|
||||
const options = res.data.map(item => ({
|
||||
const options = res.data.map((item) => ({
|
||||
label: item,
|
||||
value: item,
|
||||
}));
|
||||
}))
|
||||
// 保留"全部"选项,并添加接口返回的数据
|
||||
typeOptions.value = [{ label: '全部', value: '' }, ...options];
|
||||
return options;
|
||||
typeOptions.value = [{ label: '全部', value: '' }, ...options]
|
||||
return options
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取路况类型选项失败:', error);
|
||||
console.error('获取路况类型选项失败:', error)
|
||||
}
|
||||
return typeOptions.value;
|
||||
};
|
||||
return typeOptions.value
|
||||
}
|
||||
|
||||
// 获取管控措施选项
|
||||
export const fetchControlMeasureOptions = async () => {
|
||||
@ -70,34 +76,34 @@ export const fetchControlMeasureOptions = async () => {
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/sm-event/dashboard/processing-measure-options',
|
||||
method: 'GET',
|
||||
});
|
||||
})
|
||||
|
||||
if (res && res.code === '00000' && Array.isArray(res.data)) {
|
||||
const options = res.data
|
||||
.map(item => {
|
||||
.map((item) => {
|
||||
if (typeof item === 'string') {
|
||||
return { label: item, value: item };
|
||||
return { label: item, value: item }
|
||||
}
|
||||
if (item && typeof item === 'object') {
|
||||
const label = item.label ?? item.name ?? item.text ?? item.value ?? item.val;
|
||||
const value = item.value ?? item.val ?? item.code ?? label;
|
||||
if (label == null || value == null) return null;
|
||||
return { label: String(label), value: String(value) };
|
||||
const label = item.label ?? item.name ?? item.text ?? item.value ?? item.val
|
||||
const value = item.value ?? item.val ?? item.code ?? label
|
||||
if (label == null || value == null) return null
|
||||
return { label: String(label), value: String(value) }
|
||||
}
|
||||
return null;
|
||||
return null
|
||||
})
|
||||
.filter(Boolean);
|
||||
.filter(Boolean)
|
||||
|
||||
if (options.length > 0) {
|
||||
controlMeasureOptions.value = options;
|
||||
return options;
|
||||
controlMeasureOptions.value = options
|
||||
return options
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取管控措施选项失败:', error);
|
||||
console.error('获取管控措施选项失败:', error)
|
||||
}
|
||||
return controlMeasureOptions.value;
|
||||
};
|
||||
return controlMeasureOptions.value
|
||||
}
|
||||
|
||||
// 风险等级选项
|
||||
export const riskLevelOptions = [
|
||||
@ -106,7 +112,7 @@ export const riskLevelOptions = [
|
||||
{ label: '二级', value: '二级' },
|
||||
{ label: '三级', value: '三级' },
|
||||
{ label: '四级', value: '四级' },
|
||||
];
|
||||
]
|
||||
|
||||
// 影响点类型选项
|
||||
export const pointTypeOptions = [
|
||||
@ -115,7 +121,7 @@ export const pointTypeOptions = [
|
||||
{ label: '桥梁', value: 'bridge' },
|
||||
{ label: '隧道', value: 'tunnel' },
|
||||
{ label: '路面', value: 'road' },
|
||||
];
|
||||
]
|
||||
|
||||
// 影响点等级选项
|
||||
export const pointLevelOptions = [
|
||||
@ -124,14 +130,14 @@ export const pointLevelOptions = [
|
||||
{ label: '中风险', value: '中风险' },
|
||||
{ label: '较高风险', value: '较高风险' },
|
||||
{ label: '高风险', value: '高风险' },
|
||||
];
|
||||
]
|
||||
|
||||
// 是否回应选项
|
||||
export const isRespondedOptions = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false },
|
||||
];
|
||||
]
|
||||
|
||||
// 预警等级选项
|
||||
export const warningLevelOptions = [
|
||||
@ -140,30 +146,277 @@ export const warningLevelOptions = [
|
||||
{ label: '橙色预警', value: '橙色预警' },
|
||||
{ label: '黄色预警', value: '黄色预警' },
|
||||
{ label: '蓝色预警', value: '蓝色预警' },
|
||||
];
|
||||
]
|
||||
|
||||
// 是否结束选项
|
||||
export const isEndedOptions = [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '是', value: true },
|
||||
{ label: '否', value: false },
|
||||
];
|
||||
]
|
||||
|
||||
// 影响区域选项(带全部)
|
||||
export const regionOptionsWithAll = ref([]);
|
||||
export const regionOptionsWithAll = ref([])
|
||||
|
||||
// 格式化日期时间为接口所需格式
|
||||
export const formatDateTime = date => {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
const hours = String(d.getHours()).padStart(2, '0');
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(d.getSeconds()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
export const formatDateTime = (date) => {
|
||||
if (!date) return ''
|
||||
const d = new Date(date)
|
||||
const year = d.getFullYear()
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
const hours = String(d.getHours()).padStart(2, '0')
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0')
|
||||
const seconds = String(d.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
// 记录用户操作日志(使用 fetch keepalive 确保页面切换后请求仍能完成)
|
||||
export const logUserOperation = (type, command) => {
|
||||
try {
|
||||
const data = { type, command }
|
||||
|
||||
// 使用 fetch 的 keepalive 选项确保页面卸载后请求仍能完成
|
||||
fetch('/snow-ops-platform/weather-warning/users/logs', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
keepalive: true, // 关键:确保页面切换后请求仍能完成
|
||||
})
|
||||
.then((response) => {
|
||||
console.log('日志请求完成:', response.status)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('日志请求失败:', error)
|
||||
})
|
||||
|
||||
console.log('日志已触发发送:', data)
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('记录操作日志失败:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 监听外部应用打开并记录日志的辅助函数
|
||||
const listenForAppLaunch = (type, command) => {
|
||||
let hasLogged = false
|
||||
let hasLostFocus = false // 是否已经失去焦点
|
||||
let focusTimer = null // 用于延迟检测的定时器
|
||||
const startTime = Date.now()
|
||||
console.log('开始监听外部应用打开...', { type, command, initialHidden: document.hidden, startTime })
|
||||
|
||||
// 确认打开外部应用
|
||||
const confirmLaunch = () => {
|
||||
if (hasLogged) return
|
||||
hasLogged = true
|
||||
console.log('确认用户点击了"打开"按钮,调用日志接口')
|
||||
logUserOperation(type, command)
|
||||
cleanup()
|
||||
}
|
||||
|
||||
// 检测打开状态
|
||||
const checkLaunchStatus = () => {
|
||||
if (hasLogged) return
|
||||
|
||||
const now = Date.now()
|
||||
const elapsed = now - startTime
|
||||
|
||||
const isHidden = document.hidden
|
||||
const currentHasFocus = document.hasFocus()
|
||||
|
||||
console.log(`检测状态 [${elapsed}ms]:`, { isHidden, hasFocus: currentHasFocus, hasLostFocus, hasLogged })
|
||||
|
||||
// 情况1: 页面被隐藏 → 用户点击了"打开"
|
||||
if (isHidden) {
|
||||
confirmLaunch()
|
||||
return
|
||||
}
|
||||
|
||||
// 情况2: 失去焦点后重新获得焦点 → 用户点击了"取消"
|
||||
if (hasLostFocus && currentHasFocus) {
|
||||
console.log('用户点击了"取消"按钮,不记录日志')
|
||||
cleanup()
|
||||
return
|
||||
}
|
||||
|
||||
// 记录当前焦点状态
|
||||
if (!currentHasFocus && !hasLostFocus) {
|
||||
hasLostFocus = true
|
||||
console.log('页面失去焦点,开始等待用户选择...')
|
||||
|
||||
// 设置延迟检测:1.5秒后如果仍未获得焦点,认为用户点击了"打开"
|
||||
focusTimer = setTimeout(() => {
|
||||
if (!hasLogged && hasLostFocus && !document.hasFocus()) {
|
||||
console.log('1.5秒未重新获得焦点,认为用户点击了"打开"')
|
||||
confirmLaunch()
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
|
||||
// 方法1: 监听 visibilitychange 事件
|
||||
const handleVisibilityChange = () => {
|
||||
console.log('visibilitychange 触发, document.hidden:', document.hidden)
|
||||
checkLaunchStatus()
|
||||
}
|
||||
|
||||
// 方法2: 监听 window blur 事件
|
||||
const handleWindowBlur = () => {
|
||||
console.log('window blur 触发')
|
||||
hasLostFocus = true
|
||||
// 设置延迟检测:1.5秒后如果仍未获得焦点,认为用户点击了"打开"
|
||||
focusTimer = setTimeout(() => {
|
||||
if (!hasLogged && hasLostFocus && !document.hasFocus()) {
|
||||
console.log('1.5秒未重新获得焦点,认为用户点击了"打开"')
|
||||
confirmLaunch()
|
||||
}
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
// 方法3: 监听 window focus 事件(判断用户是否点击取消)
|
||||
const handleWindowFocus = () => {
|
||||
console.log('window focus 触发')
|
||||
checkLaunchStatus()
|
||||
}
|
||||
|
||||
// 方法4: 定时轮询检测
|
||||
let checkInterval = setInterval(() => {
|
||||
checkLaunchStatus()
|
||||
const elapsed = Date.now() - startTime
|
||||
|
||||
// 10秒后停止轮询
|
||||
if (elapsed > 10000 || hasLogged) {
|
||||
clearInterval(checkInterval)
|
||||
}
|
||||
}, 200)
|
||||
|
||||
// 清理函数
|
||||
const cleanup = () => {
|
||||
console.log('清理监听器')
|
||||
clearInterval(checkInterval)
|
||||
clearTimeout(focusTimer)
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange)
|
||||
window.removeEventListener('blur', handleWindowBlur)
|
||||
window.removeEventListener('focus', handleWindowFocus)
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||||
window.addEventListener('blur', handleWindowBlur)
|
||||
window.addEventListener('focus', handleWindowFocus)
|
||||
|
||||
// 10秒后自动清理
|
||||
setTimeout(() => {
|
||||
if (!hasLogged) {
|
||||
console.log('10秒超时,未检测到打开操作,清理监听器')
|
||||
cleanup()
|
||||
}
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
// 打开视频会议
|
||||
export const openVideoConference = async (item) => {
|
||||
console.log('打开视频会议:', item)
|
||||
if (!item || !item.name || !item.phone) {
|
||||
console.warn('缺少姓名或电话信息')
|
||||
return
|
||||
}
|
||||
try {
|
||||
// 调用接口获取 user-id
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/weather-warning/user-id',
|
||||
method: 'GET',
|
||||
params: {
|
||||
name: item.name,
|
||||
phone: item.phone,
|
||||
},
|
||||
})
|
||||
const userId = 1279134
|
||||
if (res.code === '00000') {
|
||||
// const userId = res.data
|
||||
const url = `taurusykz://taurusclient/action/avmeeting/conferenceCreateByIds?title=重庆渝路畅行风险预警&isVideoConference=true&calleeStaffIds=${userId}`
|
||||
window.location.href = url
|
||||
// 监听用户点击"打开"按钮后记录日志
|
||||
let jsobj = {
|
||||
name: item.name,
|
||||
phone: item.phone,
|
||||
id: item.id,
|
||||
userId: userId,
|
||||
text: '打开视频会议',
|
||||
}
|
||||
logUserOperation('launch-video-conference', JSON.stringify(jsobj))
|
||||
} else {
|
||||
console.error('获取 user-id 失败:', res)
|
||||
// 非系统用户, 操作无法执行
|
||||
ElMessage.warning('非系统用户, 操作无法执行')
|
||||
logUserOperation('launch-video-conference', '非系统用户, 操作无法执行')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取 user-id 出错:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 打开语音通话
|
||||
export const openVoiceConference = async (item) => {
|
||||
console.log('打开语音通话:', item)
|
||||
if (!item || !item.name || !item.phone) {
|
||||
console.warn('缺少姓名或电话信息')
|
||||
return
|
||||
}
|
||||
try {
|
||||
// 调用接口获取 user-id
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/weather-warning/user-id',
|
||||
method: 'GET',
|
||||
params: {
|
||||
name: item.name,
|
||||
phone: item.phone,
|
||||
},
|
||||
})
|
||||
if (res.code === '00000' && res.data != null) {
|
||||
const userId = res.data
|
||||
const url = `taurusykz://taurusclient/action/avmeeting/conferenceCreateByIds?title=重庆渝路畅行风险预警&isVideoConference=false&calleeStaffIds=${userId}`
|
||||
window.location.href = url
|
||||
// 监听用户点击"打开"按钮后记录日志
|
||||
let jsobj = {
|
||||
name: item.name,
|
||||
phone: item.phone,
|
||||
id: item.id,
|
||||
userId: userId,
|
||||
text: '打开语音通话',
|
||||
}
|
||||
logUserOperation('launch-audio-conference', JSON.stringify(jsobj))
|
||||
} else {
|
||||
console.error('获取 user-id 失败:', res)
|
||||
// 非系统用户, 操作无法执行
|
||||
ElMessage.warning('非系统用户, 操作无法执行')
|
||||
logUserOperation('launch-audio-conference', '非系统用户, 操作无法执行')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取 user-id 出错:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 打开拨打电话
|
||||
export const opencallConference = async (item) => {
|
||||
console.log('打开拨打电话:', item)
|
||||
if (!item || !item.name || !item.phone) {
|
||||
console.warn('缺少姓名或电话信息')
|
||||
return
|
||||
}
|
||||
// 监听用户点击"打开"按钮后记录日志
|
||||
let jsobj = {
|
||||
name: item.name,
|
||||
phone: item.phone,
|
||||
id: item.id,
|
||||
userId: '',
|
||||
text: '拨打电话',
|
||||
}
|
||||
// listenForAppLaunch('launch-audio-conference', JSON.stringify(jsobj))
|
||||
logUserOperation('phone-based-confirmation', JSON.stringify(jsobj))
|
||||
}
|
||||
|
||||
// 默认导出所有选项
|
||||
export default {
|
||||
@ -181,4 +434,7 @@ export default {
|
||||
fetchRoadConditionOptions,
|
||||
fetchDistrictOptions,
|
||||
fetchControlMeasureOptions,
|
||||
};
|
||||
openVideoConference,
|
||||
openVoiceConference,
|
||||
opencallConference,
|
||||
}
|
||||
|
||||
@ -4,11 +4,7 @@
|
||||
<img class="title_bg" src="../../assets/RiskWarning_img/一级标题栏bg@2x.png" alt="" />
|
||||
<div class="title_img_box">
|
||||
<img class="title_img1" src="../../assets/RiskWarning_img/位图@2x.png" alt="" />
|
||||
<img
|
||||
class="title_img2"
|
||||
src="../../assets/RiskWarning_img/渝路畅行-风险预警一键响应@2x.png"
|
||||
alt=""
|
||||
/>
|
||||
<img class="title_img2" src="../../assets/RiskWarning_img/渝路畅行-风险预警一键响应@2x.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -20,12 +16,7 @@
|
||||
<div class="corner corner-bottom-left"></div>
|
||||
<div class="corner corner-bottom-right"></div>
|
||||
<!-- 中心数据展示卡片 -->
|
||||
<centerInfoCard
|
||||
:type="showCenterCard.type"
|
||||
:peopleCount="showCenterCard.value"
|
||||
roadCount="117"
|
||||
@click="handleCenterCardClick"
|
||||
/>
|
||||
<centerInfoCard :type="showCenterCard.type" :peopleCount="showCenterCard.value" roadCount="117" @click="handleCenterCardClick" />
|
||||
|
||||
<div class="left">
|
||||
<left
|
||||
@ -40,7 +31,7 @@
|
||||
@openWarningSituation="openDialog('warningSituation')"
|
||||
@openResponseStatus="openDialog('responseStatus')"
|
||||
@openDispatchDistrict="openDialog('dispatchDistrict')"
|
||||
@showCenterCard="item => handleCenterCardClick(item)"
|
||||
@showCenterCard="(item) => handleCenterCardClick(item)"
|
||||
@openOfflineHelp="openDialog('offlineHelp')"
|
||||
@openImageInspection="openDialog('imageInspection')"
|
||||
></left>
|
||||
@ -70,6 +61,7 @@
|
||||
@riskPointStatsChange="handleRiskPointStatsChange"
|
||||
@update:roadvalArr="updateRoadvalArr"
|
||||
@openHazardPointSituation="handleOpenHazardPointSituation"
|
||||
@openRoadSectionSituation="handleOpenRoadSectionSituation"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -127,15 +119,12 @@
|
||||
:message="confirmConfig.message"
|
||||
:confirm-text="confirmConfig.confirmText"
|
||||
:cancel-text="confirmConfig.cancelText"
|
||||
@confirm="closeDialog('confirm')"
|
||||
@confirm="confirmCall"
|
||||
@cancel="closeDialog('confirm')"
|
||||
/>
|
||||
|
||||
<!-- 风险点详情对话框 -->
|
||||
<riskPointDetailDialog
|
||||
v-model:visible="dialogVisible.riskPointDetail"
|
||||
@close="closeDialog('riskPointDetail')"
|
||||
/>
|
||||
<riskPointDetailDialog v-model:visible="dialogVisible.riskPointDetail" @close="closeDialog('riskPointDetail')" />
|
||||
|
||||
<!-- 影响点情况对话框 -->
|
||||
<impactPointDialog
|
||||
@ -154,16 +143,10 @@
|
||||
/>
|
||||
|
||||
<!-- 响应点详情对话框 -->
|
||||
<responsePointDetailDialog
|
||||
v-model:visible="dialogVisible.responsePointDetail"
|
||||
@close="closeDialog('responsePointDetail')"
|
||||
/>
|
||||
<responsePointDetailDialog v-model:visible="dialogVisible.responsePointDetail" @close="closeDialog('responsePointDetail')" />
|
||||
|
||||
<!-- 响应点信息对话框 -->
|
||||
<responsePointInfoDialog
|
||||
v-model:visible="dialogVisible.responsePointInfo"
|
||||
@close="closeDialog('responsePointInfo')"
|
||||
/>
|
||||
<responsePointInfoDialog v-model:visible="dialogVisible.responsePointInfo" @close="closeDialog('responsePointInfo')" />
|
||||
|
||||
<!-- 响应状态对话框 -->
|
||||
<responseStatusDialog
|
||||
@ -174,10 +157,7 @@
|
||||
/>
|
||||
|
||||
<!-- AI预警处理结果对话框 -->
|
||||
<aiWarningResultDialog
|
||||
v-model:visible="dialogVisible.aiWarningResult"
|
||||
@close="closeDialog('aiWarningResult')"
|
||||
/>
|
||||
<aiWarningResultDialog v-model:visible="dialogVisible.aiWarningResult" @close="closeDialog('aiWarningResult')" />
|
||||
|
||||
<!-- 潼南基本信息对话框 -->
|
||||
<tongnanInfoDialog
|
||||
@ -213,16 +193,10 @@
|
||||
/>
|
||||
|
||||
<!-- 管控情况对话框 -->
|
||||
<controlSituationDialog
|
||||
v-model:visible="dialogVisible.controlSituation"
|
||||
@close="closeDialog('controlSituation')"
|
||||
/>
|
||||
<controlSituationDialog v-model:visible="dialogVisible.controlSituation" @close="closeDialog('controlSituation')" />
|
||||
|
||||
<!-- 调度详情对话框 -->
|
||||
<dispatchDetailDialog
|
||||
v-model:visible="dialogVisible.dispatchDetail"
|
||||
@close="closeDialog('dispatchDetail')"
|
||||
/>
|
||||
<dispatchDetailDialog v-model:visible="dialogVisible.dispatchDetail" @close="closeDialog('dispatchDetail')" />
|
||||
|
||||
<!-- 调度区县情况对话框 -->
|
||||
<dispatchDistrictDialog
|
||||
@ -250,89 +224,81 @@
|
||||
/>
|
||||
|
||||
<!-- 隧道信息对话框 -->
|
||||
<tunnelInfoDialog
|
||||
v-model:visible="dialogVisible.tunnelInfo"
|
||||
@close="closeDialog('tunnelInfo')"
|
||||
/>
|
||||
<tunnelInfoDialog v-model:visible="dialogVisible.tunnelInfo" @close="closeDialog('tunnelInfo')" />
|
||||
|
||||
<hazardPointSituationDialog
|
||||
v-model:visible="dialogVisible.hazardPointSituation"
|
||||
:data="hazardPointData"
|
||||
:title="hazardPointDialogTitle"
|
||||
@close="closeDialog('hazardPointSituation')"
|
||||
@voice="openVoiceConference"
|
||||
@video="openVideoConference"
|
||||
@call="handleCallClick"
|
||||
/>
|
||||
|
||||
<offlineHelpDialog
|
||||
v-model:visible="dialogVisible.offlineHelp"
|
||||
@close="closeDialog('offlineHelp')"
|
||||
/>
|
||||
<offlineHelpDialog v-model:visible="dialogVisible.offlineHelp" @close="closeDialog('offlineHelp')" />
|
||||
|
||||
<!-- 抽查人次对话框 -->
|
||||
<imageInspectionDialog
|
||||
v-model:visible="dialogVisible.imageInspection"
|
||||
@close="closeDialog('imageInspection')"
|
||||
/>
|
||||
<imageInspectionDialog v-model:visible="dialogVisible.imageInspection" @close="closeDialog('imageInspection')" />
|
||||
|
||||
<!-- 巡查里程对话框 -->
|
||||
<patrolMileageDialog
|
||||
v-model:visible="dialogVisible.patrolMileage"
|
||||
@close="closeDialog('patrolMileage')"
|
||||
/>
|
||||
<patrolMileageDialog v-model:visible="dialogVisible.patrolMileage" @close="closeDialog('patrolMileage')" />
|
||||
|
||||
<!-- 巡查情况对话框 -->
|
||||
<patrolSituationDialog
|
||||
v-model:visible="dialogVisible.patrolSituation"
|
||||
@close="closeDialog('patrolSituation')"
|
||||
/>
|
||||
<patrolSituationDialog v-model:visible="dialogVisible.patrolSituation" @close="closeDialog('patrolSituation')" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, provide } from 'vue';
|
||||
import useMapStore from '@/map/stores/mapStore';
|
||||
import { useMapBase } from '../cockpit/composables/useMapBase';
|
||||
import left from './left.vue';
|
||||
import right from './right.vue';
|
||||
import bottom from './bottom.vue';
|
||||
import top from './top.vue';
|
||||
import ChongqingMap from './component/ChongqingMap.vue';
|
||||
import { ref, onMounted, provide } from 'vue'
|
||||
import useMapStore from '@/map/stores/mapStore'
|
||||
import { useMapBase } from '../cockpit/composables/useMapBase'
|
||||
import left from './left.vue'
|
||||
import right from './right.vue'
|
||||
import bottom from './bottom.vue'
|
||||
import top from './top.vue'
|
||||
import ChongqingMap from './component/ChongqingMap.vue'
|
||||
import {
|
||||
fetchRoadConditionOptions,
|
||||
fetchDistrictOptions,
|
||||
fetchControlMeasureOptions,
|
||||
} from './component/index.js';
|
||||
openVideoConference,
|
||||
openVoiceConference,
|
||||
opencallConference,
|
||||
} from './component/index.js'
|
||||
|
||||
// 引入所有弹窗组件
|
||||
import responseSituationDiaLog from './Dialog/responseSituationDiaLog.vue';
|
||||
import warningInfoDialog from './Dialog/warningInfoDialog.vue';
|
||||
import eventDetailDialog from './Dialog/eventDetailDialog.vue';
|
||||
import confirmDialog from './Dialog/confirmDialog.vue';
|
||||
import riskPointDetailDialog from './Dialog/riskPointDetailDialog.vue';
|
||||
import impactPointDialog from './Dialog/impactPointDialog.vue';
|
||||
import impactPointDetailDialog from './Dialog/impactPointDetailDialog.vue';
|
||||
import responsePointDetailDialog from './Dialog/responsePointDetailDialog.vue';
|
||||
import responsePointInfoDialog from './Dialog/responsePointInfoDialog.vue';
|
||||
import responseStatusDialog from './Dialog/responseStatusDialog.vue';
|
||||
import aiWarningResultDialog from './Dialog/aiWarningResultDialog.vue';
|
||||
import tongnanInfoDialog from './Dialog/tongnanInfoDialog.vue';
|
||||
import tongnanResponsibleDialog from './Dialog/tongnanResponsibleDialog.vue';
|
||||
import clearanceSituationDialog from './Dialog/clearanceSituationDialog.vue';
|
||||
import controlSituationDialog from './Dialog/controlSituationDialog.vue';
|
||||
import dispatchDetailDialog from './Dialog/dispatchDetailDialog.vue';
|
||||
import dispatchDistrictDialog from './Dialog/dispatchDistrictDialog.vue';
|
||||
import tongnanTeamDialog from './Dialog/tongnanTeamDialog.vue';
|
||||
import warningSituationDialog from './Dialog/warningSituationDialog.vue';
|
||||
import tunnelInfoDialog from './Dialog/tunnelInfoDialog.vue';
|
||||
import centerInfoCard from './Dialog/centerInfoCard.vue';
|
||||
import tongnanProjectPersonDialog from './Dialog/tongnanProjectPersonDialog.vue';
|
||||
import hazardPointSituationDialog from './Dialog/hazardPointSituationDialog.vue';
|
||||
import offlineHelpDialog from './Dialog/offlineHelpDialog.vue';
|
||||
import imageInspectionDialog from './Dialog/imageInspectionDialog.vue';
|
||||
import patrolMileageDialog from './Dialog/patrolMileageDialog.vue';
|
||||
import patrolSituationDialog from './Dialog/patrolSituationDialog.vue';
|
||||
import responseSituationDiaLog from './Dialog/responseSituationDiaLog.vue'
|
||||
import warningInfoDialog from './Dialog/warningInfoDialog.vue'
|
||||
import eventDetailDialog from './Dialog/eventDetailDialog.vue'
|
||||
import confirmDialog from './Dialog/confirmDialog.vue'
|
||||
import riskPointDetailDialog from './Dialog/riskPointDetailDialog.vue'
|
||||
import impactPointDialog from './Dialog/impactPointDialog.vue'
|
||||
import impactPointDetailDialog from './Dialog/impactPointDetailDialog.vue'
|
||||
import responsePointDetailDialog from './Dialog/responsePointDetailDialog.vue'
|
||||
import responsePointInfoDialog from './Dialog/responsePointInfoDialog.vue'
|
||||
import responseStatusDialog from './Dialog/responseStatusDialog.vue'
|
||||
import aiWarningResultDialog from './Dialog/aiWarningResultDialog.vue'
|
||||
import tongnanInfoDialog from './Dialog/tongnanInfoDialog.vue'
|
||||
import tongnanResponsibleDialog from './Dialog/tongnanResponsibleDialog.vue'
|
||||
import clearanceSituationDialog from './Dialog/clearanceSituationDialog.vue'
|
||||
import controlSituationDialog from './Dialog/controlSituationDialog.vue'
|
||||
import dispatchDetailDialog from './Dialog/dispatchDetailDialog.vue'
|
||||
import dispatchDistrictDialog from './Dialog/dispatchDistrictDialog.vue'
|
||||
import tongnanTeamDialog from './Dialog/tongnanTeamDialog.vue'
|
||||
import warningSituationDialog from './Dialog/warningSituationDialog.vue'
|
||||
import tunnelInfoDialog from './Dialog/tunnelInfoDialog.vue'
|
||||
import centerInfoCard from './Dialog/centerInfoCard.vue'
|
||||
import tongnanProjectPersonDialog from './Dialog/tongnanProjectPersonDialog.vue'
|
||||
import hazardPointSituationDialog from './Dialog/hazardPointSituationDialog.vue'
|
||||
import offlineHelpDialog from './Dialog/offlineHelpDialog.vue'
|
||||
import imageInspectionDialog from './Dialog/imageInspectionDialog.vue'
|
||||
import patrolMileageDialog from './Dialog/patrolMileageDialog.vue'
|
||||
import patrolSituationDialog from './Dialog/patrolSituationDialog.vue'
|
||||
|
||||
import './component/el-select.scss';
|
||||
import './component/date-picker-theme.scss';
|
||||
import './component/el-select.scss'
|
||||
import './component/date-picker-theme.scss'
|
||||
|
||||
// 弹窗显示状态
|
||||
const dialogVisible = ref({
|
||||
@ -362,8 +328,8 @@ const dialogVisible = ref({
|
||||
imageInspection: false,
|
||||
patrolMileage: false,
|
||||
patrolSituation: false,
|
||||
});
|
||||
const activeitem = ref({});
|
||||
})
|
||||
const activeitem = ref({})
|
||||
|
||||
// 风险点统计数据
|
||||
const riskPointStats = ref({
|
||||
@ -374,169 +340,186 @@ const riskPointStats = ref({
|
||||
一般路内隐患点: 0,
|
||||
一般路外隐患点: 0,
|
||||
风险点总数: 0,
|
||||
});
|
||||
})
|
||||
|
||||
// 涉灾隐患点数据
|
||||
const hazardPointData = ref({});
|
||||
const hazardPointData = ref({})
|
||||
|
||||
// 弹窗标题
|
||||
const hazardPointDialogTitle = ref('涉灾隐患点情况')
|
||||
|
||||
// 日期范围
|
||||
const getdateRange = ref([]);
|
||||
const getdateRange = ref([])
|
||||
|
||||
// 处理日期范围变化
|
||||
const handleDateRangeChange = val => {
|
||||
console.log('日期范围变化:', val);
|
||||
getdateRange.value = val;
|
||||
};
|
||||
const handleDateRangeChange = (val) => {
|
||||
console.log('日期范围变化:', val)
|
||||
getdateRange.value = val
|
||||
}
|
||||
|
||||
// 地图组件引用
|
||||
const chongqingMapRef = ref(null);
|
||||
const chongqingMapRef = ref(null)
|
||||
|
||||
// 切换导航项时触发
|
||||
const changeActiveIndex = index => {
|
||||
activeitem.value = index;
|
||||
};
|
||||
const roadItem = ref({});
|
||||
const showRoadStats = ref(false);
|
||||
const roadItemClick = item => {
|
||||
console.log('点击路段:', item);
|
||||
roadItem.value = item;
|
||||
showRoadStats.value = true;
|
||||
};
|
||||
const changeActiveIndex = (index) => {
|
||||
activeitem.value = index
|
||||
}
|
||||
const roadItem = ref({})
|
||||
const showRoadStats = ref(false)
|
||||
const roadItemClick = (item) => {
|
||||
console.log('点击路段:', item)
|
||||
roadItem.value = item
|
||||
showRoadStats.value = true
|
||||
}
|
||||
|
||||
// 处理隐藏路段统计
|
||||
const handleHideRoadStats = () => {
|
||||
console.log('隐藏路段统计');
|
||||
showRoadStats.value = false;
|
||||
};
|
||||
console.log('隐藏路段统计')
|
||||
showRoadStats.value = false
|
||||
}
|
||||
|
||||
// 处理隐患点点击
|
||||
const handleHazardItemClick = item => {
|
||||
console.log('点击隐患点:', item);
|
||||
const handleHazardItemClick = (item) => {
|
||||
console.log('点击隐患点:', item)
|
||||
// 调用地图组件的方法获取风险点数据
|
||||
if (chongqingMapRef.value) {
|
||||
chongqingMapRef.value.handleHazardItemClick(item);
|
||||
chongqingMapRef.value.handleHazardItemClick(item)
|
||||
}
|
||||
};
|
||||
const showHazardPopup = ref(false);
|
||||
const showHazardPopupfn = val => {
|
||||
showHazardPopup.value = val;
|
||||
};
|
||||
}
|
||||
const showHazardPopup = ref(false)
|
||||
const showHazardPopupfn = (val) => {
|
||||
showHazardPopup.value = val
|
||||
}
|
||||
|
||||
// 处理风险点统计数据变化
|
||||
const handleRiskPointStatsChange = stats => {
|
||||
console.log('风险点统计数据变化:', stats);
|
||||
riskPointStats.value = stats;
|
||||
};
|
||||
const handleRiskPointStatsChange = (stats) => {
|
||||
console.log('风险点统计数据变化:', stats)
|
||||
riskPointStats.value = stats
|
||||
}
|
||||
|
||||
// 路段统计数据
|
||||
const roadvalArrtrue = ref([]);
|
||||
const updateRoadvalArr = roadvalArr => {
|
||||
roadvalArrtrue.value = roadvalArr;
|
||||
const roadvalArrtrue = ref([])
|
||||
const updateRoadvalArr = (roadvalArr) => {
|
||||
roadvalArrtrue.value = roadvalArr
|
||||
// let num = 0;
|
||||
// roadvalArrtrue.value.forEach(item => {
|
||||
// num += item.value;
|
||||
// });
|
||||
// roadvalArrtrue.value.push({ label: '风险点总数', value: num });
|
||||
console.log('更新路段统计数据:', roadvalArr);
|
||||
console.log('更新路段统计数据:', roadvalArrtrue);
|
||||
};
|
||||
console.log('更新路段统计数据:', roadvalArr)
|
||||
console.log('更新路段统计数据:', roadvalArrtrue)
|
||||
}
|
||||
|
||||
// 打开资源详情(队伍、人员、装备、物资)
|
||||
const openResourceDetail = item => {
|
||||
console.log('打开资源详情:', item);
|
||||
const openResourceDetail = (item) => {
|
||||
console.log('打开资源详情:', item)
|
||||
// 判断是否为队伍或人员
|
||||
if (item.label === '全市普通公路抢险队伍' || item.label === '人员') {
|
||||
// 调用地图组件的获取应急力量方法
|
||||
if (chongqingMapRef.value) {
|
||||
chongqingMapRef.value.getEmergencyForceData();
|
||||
chongqingMapRef.value.getEmergencyForceData()
|
||||
}
|
||||
}
|
||||
// 打开对应的弹窗
|
||||
const key = item.label.toLowerCase().replace(/[^a-z]/g, '');
|
||||
const key = item.label.toLowerCase().replace(/[^a-z]/g, '')
|
||||
if (dialogVisible.value[key] !== undefined) {
|
||||
dialogVisible.value[key] = true;
|
||||
dialogVisible.value[key] = true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 清除地图标记
|
||||
const clearMapMarkers = () => {
|
||||
console.log('清除地图标记');
|
||||
console.log('清除地图标记')
|
||||
if (chongqingMapRef.value) {
|
||||
chongqingMapRef.value.clearProjectMarkers();
|
||||
chongqingMapRef.value.clearProjectMarkers()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 处理清除筛选事件
|
||||
const handleClearFilters = () => {
|
||||
console.log('index.vue 处理清除筛选事件');
|
||||
console.log('index.vue 处理清除筛选事件')
|
||||
// 清除地图标记
|
||||
clearMapMarkers();
|
||||
clearMapMarkers()
|
||||
// 重置相关状态
|
||||
activeitem.value = {};
|
||||
roadItem.value = {};
|
||||
showHazardPopup.value = false;
|
||||
};
|
||||
activeitem.value = {}
|
||||
roadItem.value = {}
|
||||
showHazardPopup.value = false
|
||||
}
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = dialogName => {
|
||||
dialogVisible.value[dialogName] = true;
|
||||
};
|
||||
const impactPointDetailItem = ref({});
|
||||
const openDialog = (dialogName) => {
|
||||
dialogVisible.value[dialogName] = true
|
||||
}
|
||||
const impactPointDetailItem = ref({})
|
||||
// 处理影响点点击
|
||||
const handleImpactPointClick = item => {
|
||||
console.log('影响点点击:', item);
|
||||
impactPointDetailItem.value = item;
|
||||
};
|
||||
const handleImpactItem = ref({});
|
||||
const handleImpactClickItem = item => {
|
||||
console.log('影响点点击详情:', item);
|
||||
handleImpactItem.value = item;
|
||||
};
|
||||
const tongnanInfoItemData = ref({});
|
||||
const tongnanInfoItemDatafn = item => {
|
||||
console.log('点击详情:', item);
|
||||
tongnanInfoItemData.value = item;
|
||||
};
|
||||
const handleImpactPointClick = (item) => {
|
||||
console.log('影响点点击:', item)
|
||||
impactPointDetailItem.value = item
|
||||
}
|
||||
const handleImpactItem = ref({})
|
||||
const handleImpactClickItem = (item) => {
|
||||
console.log('影响点点击详情:', item)
|
||||
handleImpactItem.value = item
|
||||
}
|
||||
const tongnanInfoItemData = ref({})
|
||||
const tongnanInfoItemDatafn = (item) => {
|
||||
console.log('点击详情:', item)
|
||||
tongnanInfoItemData.value = item
|
||||
}
|
||||
// 关闭弹窗
|
||||
const closeDialog = dialogName => {
|
||||
const closeDialog = (dialogName) => {
|
||||
// 关闭弹窗时,重置弹窗数据
|
||||
console.log('关闭弹窗', dialogName);
|
||||
dialogVisible.value[dialogName] = false;
|
||||
};
|
||||
console.log('关闭弹窗', dialogName)
|
||||
dialogVisible.value[dialogName] = false
|
||||
}
|
||||
|
||||
// 处理打开涉灾隐患点情况弹窗
|
||||
const handleOpenHazardPointSituation = item => {
|
||||
console.log('打开涉灾隐患点情况弹窗:', item);
|
||||
hazardPointData.value = item;
|
||||
dialogVisible.value.hazardPointSituation = true;
|
||||
};
|
||||
const handleOpenHazardPointSituation = (item) => {
|
||||
console.log('打开涉灾隐患点情况弹窗:', item)
|
||||
hazardPointDialogTitle.value = '涉灾隐患点情况'
|
||||
hazardPointData.value = item
|
||||
dialogVisible.value.hazardPointSituation = true
|
||||
}
|
||||
|
||||
// 处理打开路段情况弹窗
|
||||
const handleOpenRoadSectionSituation = (item) => {
|
||||
console.log('打开路段情况弹窗:', item)
|
||||
hazardPointDialogTitle.value = '路段情况'
|
||||
// 添加数据类型标识
|
||||
hazardPointData.value = {
|
||||
...item,
|
||||
dataType: 'road',
|
||||
}
|
||||
dialogVisible.value.hazardPointSituation = true
|
||||
}
|
||||
|
||||
// 处理气象预警点击
|
||||
const warningitem = ref({});
|
||||
const handleWarningClick = item => {
|
||||
console.log('气象预警点击:', item);
|
||||
warningitem.value = item;
|
||||
};
|
||||
const warningitem = ref({})
|
||||
const handleWarningClick = (item) => {
|
||||
console.log('气象预警点击:', item)
|
||||
warningitem.value = item
|
||||
}
|
||||
|
||||
const clearanceSituationDialogItemData = ref({});
|
||||
const handleItemData = item => {
|
||||
console.log('点击详情:', item);
|
||||
clearanceSituationDialogItemData.value = item;
|
||||
};
|
||||
const clearanceSituationDialogItemData = ref({})
|
||||
const handleItemData = (item) => {
|
||||
console.log('点击详情:', item)
|
||||
clearanceSituationDialogItemData.value = item
|
||||
}
|
||||
|
||||
const dispatchDateRange = ref([]);
|
||||
const handleDispatchDateRange = range => {
|
||||
dispatchDateRange.value = range;
|
||||
};
|
||||
const rightDateRange = ref([]);
|
||||
const updateDateRange = range => {
|
||||
console.log('更新日期范围:', range);
|
||||
rightDateRange.value = range;
|
||||
};
|
||||
const filterForm = ref({});
|
||||
const updateFilterForm = item => {
|
||||
console.log('更新筛选表单:', item);
|
||||
filterForm.value = item;
|
||||
};
|
||||
const dispatchDateRange = ref([])
|
||||
const handleDispatchDateRange = (range) => {
|
||||
dispatchDateRange.value = range
|
||||
}
|
||||
const rightDateRange = ref([])
|
||||
const updateDateRange = (range) => {
|
||||
console.log('更新日期范围:', range)
|
||||
rightDateRange.value = range
|
||||
}
|
||||
const filterForm = ref({})
|
||||
const updateFilterForm = (item) => {
|
||||
console.log('更新筛选表单:', item)
|
||||
filterForm.value = item
|
||||
}
|
||||
|
||||
// 确认对话框配置
|
||||
const confirmConfig = ref({
|
||||
@ -544,63 +527,82 @@ const confirmConfig = ref({
|
||||
message: '是否拨打电话?',
|
||||
confirmText: '确定',
|
||||
cancelText: '取消',
|
||||
});
|
||||
|
||||
})
|
||||
// 当前要拨打的电话信息
|
||||
const currentCallItem = ref(null)
|
||||
// 处理电话按钮点击
|
||||
const handleCallClick = (item) => {
|
||||
console.log('准备拨打电话:', item)
|
||||
currentCallItem.value = item
|
||||
openConfirm({
|
||||
title: '拨打电话',
|
||||
message: `是否拨打电话: ${item.phone || item.name || ''}?`,
|
||||
})
|
||||
}
|
||||
// 打开确认对话框
|
||||
const openConfirm = config => {
|
||||
confirmConfig.value = { ...confirmConfig.value, ...config };
|
||||
dialogVisible.value.confirm = true;
|
||||
};
|
||||
const openConfirm = (config) => {
|
||||
confirmConfig.value = { ...confirmConfig.value, ...config }
|
||||
dialogVisible.value.confirm = true
|
||||
}
|
||||
|
||||
// 确认拨打电话
|
||||
const confirmCall = () => {
|
||||
if (currentCallItem.value) {
|
||||
opencallConference(currentCallItem.value)
|
||||
currentCallItem.value = null
|
||||
}
|
||||
closeDialog('confirm')
|
||||
}
|
||||
// 中心信息卡片显示状态
|
||||
const showCenterCard = ref(false);
|
||||
const allCountyData = ref({});
|
||||
const showCenterCard = ref(false)
|
||||
const allCountyData = ref({})
|
||||
// 处理区县点击
|
||||
const handleDistrictClick = item => {
|
||||
console.log('区县点击:', item);
|
||||
allCountyData.value = item;
|
||||
const handleDistrictClick = (item) => {
|
||||
console.log('区县点击:', item)
|
||||
allCountyData.value = item
|
||||
if (item.data.roadType == 'national') {
|
||||
// 国省道
|
||||
openDialog('tongnanTeam');
|
||||
openDialog('tongnanTeam')
|
||||
} else if (item.data.roadType == 'rural') {
|
||||
openDialog('responseSituation');
|
||||
openDialog('responseSituation')
|
||||
} else if (item.data.type == 'project' && item.data.roadType == '-') {
|
||||
// 项目
|
||||
openDialog('tongnanResponsible');
|
||||
openDialog('tongnanResponsible')
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 处理中心卡片点击
|
||||
const handleCenterCardClick = item => {
|
||||
console.log('中心卡片点击:', item);
|
||||
const handleCenterCardClick = (item) => {
|
||||
console.log('中心卡片点击:', item)
|
||||
|
||||
// 调用地图组件的方法打开中心信息卡片弹窗
|
||||
if (chongqingMapRef.value && item.data) {
|
||||
const cardData = {
|
||||
title: getCardTitleByType(item.type),
|
||||
dataList: item.data,
|
||||
};
|
||||
chongqingMapRef.value.openCenterCard(cardData);
|
||||
}
|
||||
chongqingMapRef.value.openCenterCard(cardData)
|
||||
|
||||
// 如果数据中包含区县信息,定位到第一个区县
|
||||
if (item.data.length > 0 && (item.data[0].countyName || item.data[0].name)) {
|
||||
const firstCounty = item.data[0].countyName || item.data[0].name;
|
||||
chongqingMapRef.value.locateToDistrict(firstCounty);
|
||||
const firstCounty = item.data[0].countyName || item.data[0].name
|
||||
chongqingMapRef.value.locateToDistrict(firstCounty)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 根据类型获取卡片标题
|
||||
const getCardTitleByType = type => {
|
||||
const getCardTitleByType = (type) => {
|
||||
const titleMap = {
|
||||
first: '国省道调度',
|
||||
second: '农村公路调度',
|
||||
third: '建设工程调度',
|
||||
};
|
||||
return titleMap[type] || '调度统计';
|
||||
};
|
||||
const handleCenterCardClickType = item => {
|
||||
console.log(item.data);
|
||||
showCenterCard.value = true;
|
||||
}
|
||||
return titleMap[type] || '调度统计'
|
||||
}
|
||||
const handleCenterCardClickType = (item) => {
|
||||
console.log(item.data)
|
||||
showCenterCard.value = true
|
||||
// if (item.type === "second") {
|
||||
// openDialog("tongnanTeam");
|
||||
// } else if (item.type === "third") {
|
||||
@ -608,47 +610,47 @@ const handleCenterCardClickType = item => {
|
||||
// } else if (item.type === "first") {
|
||||
// openDialog("warningSituation");
|
||||
// }
|
||||
};
|
||||
}
|
||||
|
||||
// 兄弟组件通信机制
|
||||
const refreshLeftData = ref(null);
|
||||
const refreshRightData = ref(null);
|
||||
const refreshLeftData = ref(null)
|
||||
const refreshRightData = ref(null)
|
||||
|
||||
// 提供刷新函数给子组件
|
||||
const setRefreshLeftData = callback => {
|
||||
refreshLeftData.value = callback;
|
||||
};
|
||||
const setRefreshLeftData = (callback) => {
|
||||
refreshLeftData.value = callback
|
||||
}
|
||||
|
||||
// 提供刷新函数给 right.vue
|
||||
const setRefreshRightData = callback => {
|
||||
refreshRightData.value = callback;
|
||||
};
|
||||
const setRefreshRightData = (callback) => {
|
||||
refreshRightData.value = callback
|
||||
}
|
||||
|
||||
// 触发刷新函数
|
||||
const triggerRefreshLeftData = () => {
|
||||
if (refreshLeftData.value) {
|
||||
refreshLeftData.value();
|
||||
refreshLeftData.value()
|
||||
}
|
||||
// 同时触发 right.vue 刷新
|
||||
if (refreshRightData.value) {
|
||||
refreshRightData.value();
|
||||
refreshRightData.value()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 提供通信机制给子组件
|
||||
provide('setRefreshLeftData', setRefreshLeftData);
|
||||
provide('triggerRefreshLeftData', triggerRefreshLeftData);
|
||||
provide('setRefreshRightData', setRefreshRightData);
|
||||
provide('getdateRange', getdateRange);
|
||||
provide('setRefreshLeftData', setRefreshLeftData)
|
||||
provide('triggerRefreshLeftData', triggerRefreshLeftData)
|
||||
provide('setRefreshRightData', setRefreshRightData)
|
||||
provide('getdateRange', getdateRange)
|
||||
|
||||
// ==================== 地图状态管理 ====================
|
||||
|
||||
const mapStore = useMapStore();
|
||||
const mapStore = useMapStore()
|
||||
|
||||
/**
|
||||
* 加载地图的业务底图与聚焦中心点
|
||||
*/
|
||||
const mapBase = useMapBase(mapStore);
|
||||
const mapBase = useMapBase(mapStore)
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
|
||||
@ -657,11 +659,11 @@ const mapBase = useMapBase(mapStore);
|
||||
*/
|
||||
onMounted(() => {
|
||||
// 加载地图业务底图 并 聚焦中心点
|
||||
mapBase.loadBaseData();
|
||||
fetchRoadConditionOptions(); // 获取路况类型选项
|
||||
fetchDistrictOptions(); // 获取区县选项
|
||||
fetchControlMeasureOptions(); // 获取管控措施选项
|
||||
});
|
||||
mapBase.loadBaseData()
|
||||
fetchRoadConditionOptions() // 获取路况类型选项
|
||||
fetchDistrictOptions() // 获取区县选项
|
||||
fetchControlMeasureOptions() // 获取管控措施选项
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<div class="filter-header">
|
||||
<div class="filter-container">
|
||||
<span class="filter-item active" @click="handleDateRangeClick()">本轮</span>
|
||||
<!-- <span class="filter-item active" @click="handleDateRangeClick()">本轮</span> -->
|
||||
<span class="filter-item active" @click="handleDateRangeClick('total')">累计</span>
|
||||
<span class="filter-item active" @click="handleDateRangeClick('today')">今日</span>
|
||||
<div class="date-range-wrapper">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
@ -17,12 +19,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="hazard-stats" v-if="showHazardPopup">
|
||||
<div
|
||||
v-for="(item, index) in hazardStatsShowArr"
|
||||
:key="index"
|
||||
class="stat-item"
|
||||
:class="item.class"
|
||||
>
|
||||
<div v-for="(item, index) in hazardStatsShowArr" :key="index" class="stat-item" :class="item.class">
|
||||
<span class="stat-label">{{ item.label }}</span>
|
||||
<span class="stat-value-container display ai_center">
|
||||
<span class="stat-value">{{ item.value }}</span>
|
||||
@ -43,9 +40,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, inject, defineProps, nextTick, provide, onMounted } from 'vue';
|
||||
import { Calendar } from '@element-plus/icons-vue';
|
||||
import { request } from '@/utils/request';
|
||||
import { ref, watch, inject, defineProps, nextTick, provide, onMounted } from 'vue'
|
||||
import { Calendar } from '@element-plus/icons-vue'
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
const props = defineProps({
|
||||
riskPointStats: {
|
||||
@ -68,26 +65,26 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
})
|
||||
watch(
|
||||
() => props.showHazardPopup,
|
||||
newShow => {
|
||||
hazardStatsShowArr.value = JSON.parse(JSON.stringify([]));
|
||||
hazardStats.value.forEach(item => {
|
||||
item.value = 0;
|
||||
item.show = false;
|
||||
});
|
||||
}
|
||||
);
|
||||
(newShow) => {
|
||||
hazardStatsShowArr.value = JSON.parse(JSON.stringify([]))
|
||||
hazardStats.value.forEach((item) => {
|
||||
item.value = 0
|
||||
item.show = false
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
const emit = defineEmits(['openAIResult', 'dateRangeChange']);
|
||||
const emit = defineEmits(['openAIResult', 'dateRangeChange'])
|
||||
|
||||
// 注入兄弟组件通信机制
|
||||
const triggerRefreshLeftData = inject('triggerRefreshLeftData');
|
||||
const dateRange = ref([]);
|
||||
const triggerRefreshLeftData = inject('triggerRefreshLeftData')
|
||||
const dateRange = ref([])
|
||||
|
||||
// 隐患点统计数据
|
||||
const hazardStatsShowArr = ref([]);
|
||||
const hazardStatsShowArr = ref([])
|
||||
const hazardStats = ref([
|
||||
{ label: '重大路内隐患点', value: 0, show: false, type: '重大路内隐患点', isWithinRedLine: '是' },
|
||||
{ label: '重大路外隐患点', value: 0, show: false, type: '重大路外隐患点', isWithinRedLine: '否' },
|
||||
@ -96,7 +93,7 @@ const hazardStats = ref([
|
||||
{ label: '一般路内隐患点', value: 0, show: false, type: '一般路内隐患点', isWithinRedLine: '是' },
|
||||
{ label: '一般路外隐患点', value: 0, show: false, type: '一般路外隐患点', isWithinRedLine: '否' },
|
||||
{ label: '风险点总数', value: 0, show: false, type: '风险点总数', isWithinRedLine: '' },
|
||||
]);
|
||||
])
|
||||
|
||||
// 路段统计数据
|
||||
const roadStats = ref([
|
||||
@ -105,28 +102,24 @@ const roadStats = ref([
|
||||
{ label: '中风险路段', value: 0, type: '中风险路段' },
|
||||
{ label: '低风险路段', value: 0, type: '低风险路段' },
|
||||
{ label: '风险点总数', value: 0, type: '风险点总数' },
|
||||
]);
|
||||
])
|
||||
|
||||
watch(
|
||||
() => props.riskPointStats,
|
||||
newStats => {
|
||||
console.log('top.vue 收到风险点统计数据:', newStats);
|
||||
(newStats) => {
|
||||
console.log('top.vue 收到风险点统计数据:', newStats)
|
||||
if (newStats) {
|
||||
hazardStatsShowArr.value = [];
|
||||
hazardStats.value.forEach(item => {
|
||||
if (
|
||||
item.label.includes(newStats.riskLevel) &&
|
||||
newStats.isWithinRedLine == item.isWithinRedLine &&
|
||||
newStats.value >= 0
|
||||
) {
|
||||
item.value = newStats.value;
|
||||
item.show = true;
|
||||
hazardStatsShowArr.value = []
|
||||
hazardStats.value.forEach((item) => {
|
||||
if (item.label.includes(newStats.riskLevel) && newStats.isWithinRedLine == item.isWithinRedLine && newStats.value >= 0) {
|
||||
item.value = newStats.value
|
||||
item.show = true
|
||||
}
|
||||
if (item.show) {
|
||||
hazardStatsShowArr.value.push(item);
|
||||
hazardStats.value[6].show = true;
|
||||
hazardStatsShowArr.value.push(item)
|
||||
hazardStats.value[6].show = true
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
hazardStats.value[6].value =
|
||||
hazardStats.value[0].value +
|
||||
@ -134,51 +127,64 @@ watch(
|
||||
hazardStats.value[2].value +
|
||||
hazardStats.value[3].value +
|
||||
hazardStats.value[4].value +
|
||||
hazardStats.value[5].value;
|
||||
hazardStats.value[5].value
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
{ immediate: true, deep: true },
|
||||
)
|
||||
|
||||
// 设置日期时间为当天的23:59:59
|
||||
const setEndOfDay = date => {
|
||||
if (!date) return date;
|
||||
const d = new Date(date);
|
||||
d.setHours(23, 59, 59, 999);
|
||||
return d;
|
||||
};
|
||||
const setEndOfDay = (date) => {
|
||||
if (!date) return date
|
||||
const d = new Date(date)
|
||||
d.setHours(23, 59, 59, 999)
|
||||
return d
|
||||
}
|
||||
// 点击本轮
|
||||
const handleDateRangeClick = () => {
|
||||
dateRange.value = [];
|
||||
const handleDateRangeClick = (type) => {
|
||||
const now = new Date()
|
||||
if (type === 'total') {
|
||||
// 今年1月1号 00:00:00 到今年年底 23:59:59
|
||||
const startOfYear = new Date(now.getFullYear(), 0, 1, 0, 0, 0, 0)
|
||||
const endOfYear = new Date(now.getFullYear(), 11, 31, 23, 59, 59, 999)
|
||||
dateRange.value = [startOfYear, endOfYear]
|
||||
} else if (type === 'today') {
|
||||
// 今天 00:00:00 到 23:59:59
|
||||
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0)
|
||||
const endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999)
|
||||
dateRange.value = [startOfDay, endOfDay]
|
||||
} else {
|
||||
dateRange.value = []
|
||||
}
|
||||
// triggerRefreshLeftData();
|
||||
// 不需要手动 emit,watch 会监听 dateRange 变化并自动 emit
|
||||
};
|
||||
}
|
||||
// 监听 dateRange 变化
|
||||
watch(
|
||||
dateRange,
|
||||
(newVal, oldVal) => {
|
||||
// 只有当值真正发生变化时才触发
|
||||
console.log('dateRange 变化:', newVal, oldVal);
|
||||
console.log('dateRange 变化:', newVal, oldVal)
|
||||
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
||||
console.log('dateRange 发生变化:', newVal);
|
||||
console.log('dateRange 发生变化:', newVal)
|
||||
// 如果有结束日期,将其设置为当天的23:59:59
|
||||
if (newVal && newVal.length === 2 && newVal[1]) {
|
||||
newVal[1] = setEndOfDay(newVal[1]);
|
||||
newVal[1] = setEndOfDay(newVal[1])
|
||||
}
|
||||
// 触发兄弟组件刷新
|
||||
// if (triggerRefreshLeftData) {
|
||||
// triggerRefreshLeftData();
|
||||
// }
|
||||
// 向父组件传递时间范围
|
||||
emit('dateRangeChange', newVal);
|
||||
emit('dateRangeChange', newVal)
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
const handleAIClick = () => {
|
||||
emit('openAIResult');
|
||||
};
|
||||
emit('openAIResult')
|
||||
}
|
||||
|
||||
// 获取风险等级统计数据
|
||||
const fetchRiskLevelCount = async () => {
|
||||
@ -186,35 +192,35 @@ const fetchRiskLevelCount = async () => {
|
||||
const res = await request({
|
||||
url: '/snow-ops-platform/risk-point/risk-level-count',
|
||||
method: 'GET',
|
||||
});
|
||||
console.log('风险等级统计数据:', res);
|
||||
})
|
||||
console.log('风险等级统计数据:', res)
|
||||
if (res.code === '00000' && res.data) {
|
||||
// 更新路段统计数据
|
||||
const data = res.data;
|
||||
let roadTotal = 0;
|
||||
roadStats.value.forEach(item => {
|
||||
const data = res.data
|
||||
let roadTotal = 0
|
||||
roadStats.value.forEach((item) => {
|
||||
// 重置值为0
|
||||
item.value = 0;
|
||||
item.value = 0
|
||||
// 查找匹配的数据
|
||||
const matchedData = data.find(d => item.label.includes(d.level));
|
||||
const matchedData = data.find((d) => item.label.includes(d.level))
|
||||
if (matchedData) {
|
||||
item.value = Number(matchedData.count);
|
||||
roadTotal += Number(matchedData.count);
|
||||
item.value = Number(matchedData.count)
|
||||
roadTotal += Number(matchedData.count)
|
||||
}
|
||||
});
|
||||
})
|
||||
// 更新风险点总数
|
||||
roadStats.value[4].value = roadTotal;
|
||||
console.log('更新后的roadStats:', roadStats.value);
|
||||
roadStats.value[4].value = roadTotal
|
||||
console.log('更新后的roadStats:', roadStats.value)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取风险等级统计数据失败:', error);
|
||||
console.error('获取风险等级统计数据失败:', error)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 组件挂载时获取数据
|
||||
onMounted(() => {
|
||||
fetchRiskLevelCount();
|
||||
});
|
||||
fetchRiskLevelCount()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user