增加重大事情弹窗,修改3d大屏的页面数据,修改ai弹窗数据,

This commit is contained in:
fanjia 2026-05-13 14:53:10 +08:00
parent 1b08e596a0
commit 57fa628844
11 changed files with 449 additions and 224 deletions

View File

@ -1,17 +1,17 @@
<template>
<div class="map-viewer">
<!-- Cesium 地图容器 -->
<MapViewport />
<!-- <MapViewport /> -->
<!-- 地图控制工具 - 使用 Teleport 传送到更高层级 -->
<!-- 延迟渲染确保目标元素已存在 -->
<Teleport to="#sa-controls" v-if="isMounted">
<!-- <Teleport to="#sa-controls" v-if="isMounted">
<MapControls
:active-tool-key="activeToolKey"
@tool-change="handleToolChange"
@device-watch="handleDeviceWatch"
/>
</Teleport>
</Teleport> -->
</div>
</template>

View File

@ -45,11 +45,7 @@
<div class="hierarchy-left">
<div v-for="(level, index) in hierarchyLevels" :key="level.key" class="level-item">
<!-- 层级节点 -->
<div
class="level-node"
:class="[level.key, { active: activeLevel === level.key }]"
@click="activeLevel = level.key"
>
<div class="level-node" :class="[level.key, { active: activeLevel === level.key }]" @click="activeLevel = level.key">
<img :src="level.icon" class="level-icon" alt="" />
<span class="level-name">{{ level.name }}</span>
</div>
@ -69,14 +65,7 @@
:key="tab.key"
class="hierarchy-tab"
:class="{ active: activeHierarchyTab === tab.key }"
@click="
activeHierarchyTab = tab.key;
if (tab.key == 'city-dept') {
activeImpactTab = 'point';
} else {
activeImpactTab = 'aiiType';
}
"
@click="handleHierarchyTabClick(tab.key)"
>
{{ tab.label }}
</div>
@ -89,10 +78,7 @@
:key="tab.key"
class="hierarchy-tab"
:class="{ active: activeHierarchyTab === tab.key }"
@click="
activeHierarchyTab = tab.key;
activeImpactTab = 'point';
"
@click="handleDistrictTabClick(tab.key)"
>
{{ tab.label }}
</div>
@ -105,12 +91,7 @@
:key="tab.key"
class="hierarchy-tab"
:class="{ active: activeHierarchyTab === tab.key }"
@click="
activeHierarchyTab = tab.key;
if (tab.key == 'frontline-whistle' || tab.key == 'frontline-guard') {
activeImpactTab = 'project';
}
"
@click="handleFrontlineTabClick(tab.key)"
>
{{ tab.label }}
</div>
@ -145,7 +126,7 @@
{{ currentWarningInfo.emergency }}
</div>
<div class="suggestion-content" v-else-if="'district-leader' == activeHierarchyTab">
{{ currentWarningInfo.leader }}
{{ currentWarningInfo.districtLeader }}
</div>
<div class="suggestion-content" v-else-if="'district-person' == activeHierarchyTab">
{{ currentWarningInfo.person }}
@ -154,23 +135,14 @@
<div class="suggestion-content" v-else-if="'frontline-guard' == activeHierarchyTab">
{{ currentWarningInfo.guard }}
</div>
<div
class="suggestion-content"
v-else-if="'frontline-whistle' == activeHierarchyTab"
>
<div class="suggestion-content" v-else-if="'frontline-whistle' == activeHierarchyTab">
{{ currentWarningInfo.whistle }}
</div>
<div
class="suggestion-content"
v-else-if="'frontline-contractor' == activeHierarchyTab"
>
<div class="suggestion-content" v-else-if="'frontline-contractor' == activeHierarchyTab">
{{ currentWarningInfo.contractor }}
</div>
<div
class="suggestion-content"
v-else-if="'frontline-person' == activeHierarchyTab"
>
{{ currentWarningInfo.person }}
<div class="suggestion-content" v-else-if="'frontline-person' == activeHierarchyTab">
{{ currentWarningInfo.frontlinePerson }}
</div>
</div>
@ -188,14 +160,8 @@
"
>
<div class="display jc_sb ai_center">
<div class="section-label">影响范围</div>
<div
class="impact-tabs"
v-if="
'district-leader' == activeHierarchyTab ||
'district-person' == activeHierarchyTab
"
>
<div class="section-label">重点影响范围:</div>
<div class="impact-tabs" v-if="'district-leader' == activeHierarchyTab || 'district-person' == activeHierarchyTab">
<div
v-for="tab in impactTabs"
:key="tab.key"
@ -228,58 +194,38 @@
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
size="small"
height="150"
>
<el-table-column prop="label" label="类型" width="" align="center" />
<el-table-column prop="number" label="数量" width="" align="center" />
<el-table-column prop="label" label="类型" align="center" />
<el-table-column prop="number" label="数量" align="center" />
</el-table>
<el-table
v-if="activeImpactTab === 'point'"
:data="currentImpactData"
style="background: transparent"
style="background: transparent; width: 368px"
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
size="small"
height="150"
>
<el-table-column type="index" label="序号" width="" align="center" />
<el-table-column prop="area" label="影响区域" width="" align="center" />
<el-table-column prop="roadCode" label="线路编号" width="" align="center" />
<el-table-column prop="type" label="类型" width="" align="center" />
<el-table-column
prop="stake"
label="桩号"
width=""
align="center"
show-overflow-tooltip
/>
<el-table-column type="index" label="序号" align="center" />
<el-table-column prop="area" label="影响区域" align="center" />
<el-table-column prop="roadCode" label="线路编号" align="center" />
<el-table-column prop="type" label="类型" align="center" />
<el-table-column prop="stake" label="桩号" align="center" show-overflow-tooltip />
</el-table>
<el-table
v-if="activeImpactTab === 'project'"
:data="impactProjectDataTable"
style="background: transparent"
style="background: transparent; width: 368px"
:header-cell-style="headerCellStyle"
:cell-style="cellStyle"
size="small"
height="150"
>
<el-table-column type="index" label="序号" width="" align="center" />
<el-table-column prop="area" label="影响区域" width="" align="center" />
<el-table-column prop="projectName" label="项目名称" width="70" align="center" />
<el-table-column
prop="projectAddress"
label="项目地址"
width=""
align="center"
/>
<el-table-column
prop="lineNumber"
label="线路编号"
width=""
align="center"
show-overflow-tooltip
/>
<el-table-column type="index" label="序号" align="center" />
<el-table-column prop="area" label="影响区域" align="center" />
<el-table-column prop="projectName" label="项目名称" align="center" />
<el-table-column prop="projectAddress" label="驻地地址" align="center" />
<el-table-column prop="lineNumber" label="线路编号" align="center" show-overflow-tooltip />
</el-table>
</div>
</div>
@ -291,13 +237,13 @@
</template>
<script setup>
import { ref, computed, watch } from 'vue';
import { DArrowRight, Folder } from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
import cityIcon from '../../../assets/RiskWarning_img/市级icon.png';
import districtIcon from '../../../assets/RiskWarning_img/区县icon.png';
import frontlineIcon from '../../../assets/RiskWarning_img/一线icon.png';
import AIIcon from '../../../assets/RiskWarning_img/AI.png';
import { ref, computed, watch } from 'vue'
import { DArrowRight, Folder } from '@element-plus/icons-vue'
import baseDialog from '../component/baseDialog.vue'
import cityIcon from '../../../assets/RiskWarning_img/市级icon.png'
import districtIcon from '../../../assets/RiskWarning_img/区县icon.png'
import frontlineIcon from '../../../assets/RiskWarning_img/一线icon.png'
import AIIcon from '../../../assets/RiskWarning_img/AI.png'
const props = defineProps({
visible: {
type: Boolean,
@ -307,9 +253,9 @@ const props = defineProps({
type: Object,
default: () => ({}),
},
});
})
const emit = defineEmits(['update:visible', 'close']);
const emit = defineEmits(['update:visible', 'close'])
// ==================== ====================
@ -320,7 +266,7 @@ const warningData = ref({
'黔江区气象台2026年4月16日01时00分发布“暴雨红色预警信号”过去1小时双槐雨量已达90毫米预计6日1:00-7:00濯水镇街强降水仍将持续未来6小时累计雨量将达90160毫米最大小时雨强将达80100毫米局地伴有雷电、阵性大风地质灾害、中小河流洪水、山洪、城乡积涝等灾害风险高请注意防范。',
effectiveTime: '',
expireTime: '',
});
})
//
const hierarchyLevels = ref([
@ -342,27 +288,27 @@ const hierarchyLevels = ref([
name: '一线',
icon: frontlineIcon,
},
]);
])
//
const hierarchyTabs = ref([
{ key: 'city-leader', label: '中心领导', parentKey: 'city' },
{ key: 'city-dept', label: '处室负责人', parentKey: 'city' },
{ key: 'city-emergency', label: '中心应急办', parentKey: 'city' },
]);
])
const districtTabsMap = ref([
{ key: 'district-leader', label: '公路交通部门领导', parentKey: 'district' },
{ key: 'district-person', label: '养护站长/路长办', parentKey: 'district' },
]);
])
const frontlineTabsMap = ref([
{ key: 'frontline-guard', label: '护路员', parentKey: 'frontline' },
{ key: 'frontline-whistle', label: '建设单位包保责任人', parentKey: 'frontline' },
{ key: 'frontline-contractor', label: '施工单位包保责任人', parentKey: 'frontline' },
{ key: 'frontline-person', label: '吹哨人', parentKey: 'frontline' },
]);
])
const activeHierarchyTab = ref('city-leader');
const activeLevel = ref('city');
const activeHierarchyTab = ref('city-leader')
const activeLevel = ref('city')
//
const warningTabs = ref([
@ -371,15 +317,15 @@ const warningTabs = ref([
label: '公路中心领导',
content:
'黔江区气象台2026年4月16日01时00分发布"暴雨红色预警信号"过去1小时双槐雨量已达90毫米预计6日1:00-7:00濯水镇街强降水仍将持续未来6小时累计雨量将达90~160毫米最大小时雨强将达80~100毫米局地伴有雷电、阵性大风地质灾害、中小河流洪水、山洪、城乡积涝等灾害风险高请注意防范。',
leader:
'按照相关指南启动I级防御响应请领导在岗值班主持召开或参加部署调度会及时跟踪、研究、部署灾害防范和应急保通工作安排开展督导帮扶。',
dept: '按照相关指南启动I级防御响应请处室负责人和相关人员在岗值班参加部署调度会分析研判影响区县、重点路段和项目部署本领域调度核查工作督促本领域落实5个关口防御应对措施参加工作组开展指导帮扶及时收集分析、研究部署本领域防范应对、受灾和抢险救援保通工作。',
leader: '按照相关指南启动I级防御响应请领导在岗值班主持召开或参加部署调度会及时跟踪、研究、部署灾害防范和应急保通工作安排开展督导帮扶。',
dept: '照相关指南启动I级防御响应请处室负责人和相关人员在岗值班参加部署调度会分析研判影响区县、重点路段和项目部署本领域调度核查工作督促本领域落实5个关口防御应对措施参加工作组开展指导帮扶及时收集分析、研究部署本领域防范应对、受灾和抢险救援保通工作。',
emergency:
'按照相关指南启动I级防御响应请相关人员在岗值班准备并参加部署调度会开展预警叫应组织分析研判影响区县、重点路段和项目等风险要素部署市级公路应急中心全员做好应急抢险准备及时跟踪分析、研究部署防范应对、受灾和抢险救援保通工作。',
leader:
districtLeader:
'按照相关指南,请根据暴雨预警级别启动相应等级防御响应,视情召开部署调度会,请及时关注地质、水文等风险提示信息,做好会商研判,严格值班值守,落实预警叫应、部署调度、督导帮扶、力量预置、巡查排危、告警阻拦、交通管控和“关停撤转”等措施,及时跟踪分析、研究部署防范应对、受灾和抢险救援保通工作。',
person:
'按照相关指南,请根据暴雨预警级别启动相应等级防御响应,视情召开部署调度会,请及时关注地质、水文等风险提示信息,做好会商研判,严格值班值守,落实预警叫应、部署调度、督导帮扶、力量预置、巡查排危、告警阻拦、交通管控和“关停撤转”等措施,及时跟踪分析、研究部署防范应对、受灾和抢险救援保通工作。',
'按照相关指南,请根据暴雨预警级别启动相应等级防御响应,请及时关注地质、水文等风险提示信息,做好会商研判,严格值班值守,落实预警叫应、部署调度、督导帮扶、力量预置、巡查排危、告警阻拦、交通管控等措施,及时跟踪分析、研究部署防范应对、受灾和抢险救援保通工作。',
guard:
'按照相关要求启动I级防御响应并请及时关注地质、水文等风险提示信息落实主动封闭管控措施请立即按照2小时一次频率对你管养的重点路段进行巡查重点巡查较高及以上风险路段、涉灾隐患点、地质条件复杂路段、临河临崖路段重点关注涉水桥梁基础及墩台、不良地质隧道、隧道洞口边仰坡及侧切结构、高陡边坡支挡防护以及防排水设施发现异常情况立即向上报告采取紧急排危、告警阻拦、交通管控等措施并及时报送工作开展情况。',
@ -387,30 +333,55 @@ const warningTabs = ref([
'按照相关指南,请根据暴雨预警级别启动相应等级防御响应,请及时关注地质、水文等风险提示信息,做好会商研判,严格值班值守,落实预警叫应、部署调度、督导帮扶、力量预置、巡查排危和“关停撤转”等措施,及时跟踪分析、研究部署防范应对、受灾和抢险救援保通工作。',
contractor:
'按照相关指南,请根据暴雨预警级别启动相应等级防御响应,请及时关注地质、水文等风险提示信息,做好会商研判,严格值班值守,落实预警叫应、部署调度、督导帮扶、力量预置、巡查排危和“关停撤转”等措施,及时跟踪分析、研究部署防范应对、受灾和抢险救援保通工作。',
},
{ key: 'dept', label: '处室负责人', content: '', suggestion: '' },
{ key: 'emergency', label: '中心应急办', content: '', suggestion: '' },
]);
const activeWarningTab = ref('leader');
frontlinePerson:
'按照相关要求启动I级防御响应并请及时关注地质、水文等风险提示信息落实主动“关停撤转”措施应急抢险人员和吹哨人全员在岗值班做好应急装备物资检修并请立即对你项目的重点部位进行巡查重点巡查两区三厂、大型设施设备、取弃土场、砂石料场、涉水桥梁、富水隧道、围堰、支架脚手架、高切坡、深基坑、滑坡处置等部位发现异常情况立即向上报告采取紧急排危、吹哨撤转等措施并及时报送工作开展情况。',
},
])
const activeWarningTab = ref('leader')
//
const currentWarningInfo = computed(() => {
const tab = warningTabs.value.find(t => t.key === activeWarningTab.value);
return tab || warningTabs.value[0];
});
// const tab = warningTabs.value.find((t) => t.key === activeWarningTab.value)
// console.log(tab)
return warningTabs.value[0]
})
//
const impactTabs = ref([
{ key: 'point', label: '影响点' },
{ key: 'project', label: '影响驻地' },
]);
const activeImpactTab = ref('project');
])
const activeImpactTab = ref('project')
//
const impactPointData = ref([]);
const impactPointData = ref([])
//
const impactProjectData = ref([]);
const impactProjectData = ref([])
//
const handleHierarchyTabClick = (key) => {
activeHierarchyTab.value = key
if (key == 'city-dept') {
activeImpactTab.value = 'point'
} else {
activeImpactTab.value = 'aiiType'
}
}
//
const handleDistrictTabClick = (key) => {
activeHierarchyTab.value = key
activeImpactTab.value = 'point'
}
// 线
const handleFrontlineTabClick = (key) => {
activeHierarchyTab.value = key
if (key == 'frontline-whistle' || key == 'frontline-guard') {
activeImpactTab.value = 'project'
}
}
const aiiTypeArr = ref([
{ number: '2', label: '影响区县' },
@ -418,7 +389,7 @@ const aiiTypeArr = ref([
{ number: '21', label: '桥梁' },
{ number: '21', label: '隧道' },
{ number: '21', label: '驻地' },
]);
])
//
const impactProjectDataTable = ref([
{
@ -435,7 +406,7 @@ const impactProjectDataTable = ref([
projectAddress: '',
lineNumber: 'G318',
},
]);
])
//
const currentImpactData = computed(() => {
@ -454,8 +425,8 @@ const currentImpactData = computed(() => {
type: '隧道',
stake: '336.850-336.900',
},
];
});
]
})
//
const headerCellStyle = () => ({
@ -464,7 +435,8 @@ const headerCellStyle = () => ({
fontSize: '12px',
fontWeight: 'bold',
borderBottom: '1px solid rgba(24, 242, 249, 0.2)',
});
padding: '0',
})
const cellStyle = () => ({
background: '#1C659E',
@ -472,19 +444,19 @@ const cellStyle = () => ({
fontSize: '12px',
borderBottom: '1px solid #175E91',
textAlign: 'center',
});
})
// ==================== ====================
//
const handleClose = () => {
emit('update:visible', false);
emit('close');
};
emit('update:visible', false)
emit('close')
}
//
const initData = data => {
if (!data) return;
const initData = (data) => {
if (!data) return
//
if (data.warning) {
@ -493,56 +465,56 @@ const initData = data => {
publishContent: data.warning.publishContent || '',
effectiveTime: data.warning.effectiveTime || '',
expireTime: data.warning.expireTime || '',
};
}
}
//
if (data.hierarchyLevels) {
hierarchyLevels.value = data.hierarchyLevels;
hierarchyLevels.value = data.hierarchyLevels
}
//
if (data.hierarchyTabs) {
hierarchyTabs.value = data.hierarchyTabs;
hierarchyTabs.value = data.hierarchyTabs
}
if (data.districtTabsMap) {
districtTabsMap.value = data.districtTabsMap;
districtTabsMap.value = data.districtTabsMap
}
if (data.frontlineTabsMap) {
frontlineTabsMap.value = data.frontlineTabsMap;
frontlineTabsMap.value = data.frontlineTabsMap
}
if (data.activeHierarchyTab) {
activeHierarchyTab.value = data.activeHierarchyTab;
activeHierarchyTab.value = data.activeHierarchyTab
}
if (data.activeLevel) {
activeLevel.value = data.activeLevel;
activeLevel.value = data.activeLevel
}
//
if (data.warningTabs) {
warningTabs.value = data.warningTabs;
warningTabs.value = data.warningTabs
}
//
if (data.impactPointData) {
impactPointData.value = data.impactPointData;
impactPointData.value = data.impactPointData
}
if (data.impactProjectData) {
impactProjectData.value = data.impactProjectData;
impactProjectData.value = data.impactProjectData
}
};
}
// ==================== ====================
watch(
() => props.visible,
newVal => {
(newVal) => {
if (newVal && props.aiData) {
initData(props.aiData);
initData(props.aiData)
}
},
{ immediate: true }
);
{ immediate: true },
)
</script>
<style lang="scss" scoped>
@ -895,11 +867,7 @@ watch(
padding: 6px 16px;
font-size: 12px;
color: rgba(255, 255, 255, 0.8);
background: linear-gradient(
180deg,
rgba(102, 105, 255, 0.26) 0%,
rgba(31, 201, 255, 0.23) 100%
);
background: linear-gradient(180deg, rgba(102, 105, 255, 0.26) 0%, rgba(31, 201, 255, 0.23) 100%);
cursor: pointer;
transition: all 0.3s;

View File

@ -180,8 +180,8 @@ const fetchData = async () => {
district: district,
name: commandData.userName || '-',
phone: commandData.userPhone || '-',
type: commandData.type || '-',
role: commandData.role || '一般人员',
type: commandData.x_type || '-',
role: commandData.x_role || '一般人员',
dispatchTime: item.createdAt || '-',
}
})

View File

@ -179,24 +179,7 @@ watch(
const photoList = ref([])
//
const dynamicRecords = ref([
// {
// type: '',
// patrolTime: '2026-03-28 14:30:00',
// patrolPerson: '',
// description: '',
// hasProblem: true,
// image: 'https://via.placeholder.com/80x60/40a9ff/ffffff?text=',
// },
// {
// type: '',
// patrolTime: '2026-03-28 14:30:00',
// patrolPerson: '',
// description: '',
// hasProblem: false,
// image: null,
// },
])
const dynamicRecords = ref([])
//
const getStatusClass = (status) => {
@ -244,6 +227,7 @@ const getPatrolRecord = async (riskPointId) => {
url: '/snow-ops-platform/risk-point/patrol-record',
method: 'GET',
params: {
// riskPointId: '32be3f9caa034b37a174f0bd56ef6b11',
riskPointId,
},
})
@ -285,14 +269,15 @@ const getPatrolRecord = async (riskPointId) => {
// base-dialog
//
const getAffectedObjectTypeId = (data) => {
let pointType = props.item.pointType
let poinTypeText = props.item.poinTypeText
basicInfo.value = {}
photoList.value = []
dynamicRecords.value = []
if (!data) {
return
}
if (pointType === '桥梁') {
console.log('data:', data, poinTypeText)
if (poinTypeText === '桥梁') {
// -
basicInfo.value = {
district: data.GL1_QXMC || '-', //
@ -330,7 +315,7 @@ const getAffectedObjectTypeId = (data) => {
// image: null,
// },
// ];
} else if (pointType === '边坡') {
} else if (poinTypeText === '边坡') {
// -
basicInfo.value = {
district: data.GL1_QXMC || '-', //
@ -360,7 +345,7 @@ const getAffectedObjectTypeId = (data) => {
// image: null,
// },
// ];
} else if (pointType === '隧道') {
} else if (poinTypeText === '隧道') {
// -
basicInfo.value = {
district: data.GL1_QXMC || '-', //
@ -399,29 +384,30 @@ const getAffectedObjectTypeId = (data) => {
// image: null,
// },
// ];
} else if (pointType === '路段') {
} else if (poinTypeText === '路段') {
console.log('路段数据:', props.item?.rawData)
// -
basicInfo.value = {
district: data.rawData.COUNTY_NAME || '-', //
level: data.rawData.GL1_FXDJ || '未评定', //
levelClass: data.rawData.GL1_FXDJ, //
roadCode: data.rawData.GL1_LXBH || '-', // 线
location: data.pointLocation, //
riskDesc: data.rawData.GL1_FXMS || '-', //
discoverTime: data.rawData.GL1_SBSJ || '-', //
district: data?.rawData?.countyName || '-', //
level: data?.rawData?.riskLevel || '未评定', //
levelClass: data?.rawData?.riskLevel, //
roadCode: data?.rawData?.roadId || '-', // 线
location: data?.rawData?.stationStart + '至' + data?.rawData?.stationEnd, //
riskDesc: data?.rawData?.riskDescription || '-', //
discoverTime: data?.rawData?.riskFoundAt || '-', //
}
const photos = []
// -
if (getImageUrlList(data.item?.RISK_POINT?.GL1_TP).length > 0) {
photos.push(...getImageUrlList(data.item?.RISK_POINT?.GL1_TP || '')) //
if (getImageUrlList(data?.rawData?.roadImages || '').length > 0) {
photos.push(...getImageUrlList(data?.rawData?.roadImages || '')) //
}
photoList.value = photos.length > 0 ? photos : []
console.log('照片列表:', photos)
//
const riskPointId = data.item?.RISK_POINT?.GL1_ID
if (riskPointId) {
const riskPointId = data.rawData?.id
if (riskPointId && data.rawData.type == 'risk-section') {
getPatrolRecord(riskPointId)
}
@ -444,18 +430,18 @@ const getAffectedObjectDetail = async () => {
try {
let id = ''
let apiUrl = ''
const pointType = props.item?.pointType
const poinTypeText = props.item?.poinTypeText
if (pointType === '桥梁') {
if (poinTypeText === '桥梁') {
id = props.item?.rawData?.GL1_ZJ || ''
apiUrl = `/snow-ops-platform/weather-warning/affected-object/bridge/${id}`
} else if (pointType === '边坡') {
} else if (poinTypeText === '边坡') {
id = props.item?.rawData?.GL1_ID || ''
apiUrl = `/snow-ops-platform/weather-warning/affected-object/slope/${id}`
} else if (pointType === '隧道') {
} else if (poinTypeText === '隧道') {
id = props.item?.rawData?.GL1_ZJ || ''
apiUrl = `/snow-ops-platform/weather-warning/affected-object/tunnel/${id}`
} else if (pointType === '路段') {
} else if (poinTypeText === '路段') {
id = props.item?.rawData?.GL1ZJ || ''
apiUrl = `/snow-ops-platform/weather-warning/affected-object/road-section/${id}`
}

View File

@ -52,7 +52,7 @@
clearable
@change="handleFilterChange"
>
<el-option v-for="option in pointLevelOptions" :key="option.value" :label="option.label" :value="option.value" />
<el-option v-for="option in pointLevelOptionsAll" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</div>
<div class="filter-item">
@ -194,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, roadTypeOptions } from '../component/index.js'
import { pointTypeOptions, pointLevelOptionsAll, regionOptions, roadTypeOptions, pointLevelOptions } from '../component/index.js'
import baseDialog from '../component/baseDialog.vue'
import respondedIcon from '../../../assets/xiangying/有回应@2x.png'
@ -414,7 +414,7 @@ const getApiUrlByType = (type) => {
}
//
const handleClick = (index, item) => {
const handleClick = async (index, item) => {
tableData.value = []
cardType.value = index + ''
cardTypeVal.value = item.type
@ -422,7 +422,7 @@ const handleClick = (index, item) => {
tableColumns.value = getColumnsByType(item.type)
//
currentPage.value = 1
fetchData()
await fetchData()
}
//
@ -540,7 +540,7 @@ const processUnifiedData = (item, type) => {
//
region: item.GL1_QXMC || item.COUNTY || item.county || item.region || item.ADMINISTRATIVE_REGION || item.COUNTY_NAME || '-',
//
pointType: impactData.value[type].type || '-',
poinTypeText: impactData.value[type].type || '-',
//
pointLocation: item.GL1_QLMC || item.NAME || item.GL1_SDMC || item.PROJECT_NAME || item.GL1_LXBH || item.name || '-',
//
@ -668,39 +668,44 @@ const processUnifiedData = (item, type) => {
return {
...baseData,
// - 使
region: item.COUNTY_NAME || '-',
region: item.countyName || '-',
pointType:
item.type == 'controlled-section'
? '国省道-管控路段'
: item.type == 'risk-section'
? '国省道-风险路段'
: item.type == 'controlled-rural-section' || item.type == 'rural-section'
? '农村路段'
: '-',
// - 使线+
pointLocation:
item.GL1_QDZH && item.GL1_ZDZH
? item.GL1_LXMC + '(k' + (item.GL1_QDZH + '').replace('.', '+') + '至k' + (item.GL1_ZDZH + '').replace('.', '+') + ')'
: item.GL1_LXMC,
pointLocation: (item.roadName || '') + '' + item.stationStart + '至' + item.stationEnd + '',
// - 使
pointLevel: item.GL1_FXDJ || '',
levelClass: getLevelClass(item.GL1_FXDJ),
pointLevel: item.riskLevel || '-',
levelClass: getLevelClass(item.riskLevel),
// - 使GL1_JTXMGL1_JTDH
trafficDept: {
name: item.GL1_JTXM || '-',
phone: item.GL1_JTDH || '-',
name: item.transChiefName || '-',
phone: item.transChiefPhone || '-',
},
// - 使GL1_JGXMGL1_JGDH
roadOrg: {
name: item.GL1_JGXM || '-',
phone: item.GL1_JGDH || '-',
name: item.roadChiefName || '-',
phone: item.roadChiefPhone || '-',
},
// - 使GL1_YHXMGL1_YHDH
maintenance: {
name: item.GL1_YHXM || '-',
phone: item.GL1_YHDH || '-',
name: item.maintStationChiefName || '-',
phone: item.maintStationChiefPhone || '-',
},
// - 使GL1_HLXMGL1_HLDH
roadKeeper: {
name: item.GL1_HLXM || item.ROAD_PATROL_WORKER_NAME || '-',
phone: item.GL1_HLDH || item.ROAD_PATROL_WORKER_PHONE || '-',
name: item.roadPatrolWorkerName || '-',
phone: item.roadPatrolWorkerPhone || '-',
},
//
generalStaff: {
name: item.ROAD_CAPTAIN_NAME || '-',
phone: item.ROAD_CAPTAIN_PHONE || '-',
name: item.roadCaptainName || '-',
phone: item.roadCaptainPhone || '-',
},
}
}
@ -822,7 +827,7 @@ watch(
cardTypeVal.value = '路段'
console.log('影响点情况=========newVal:', newVal)
if (newVal) {
filterForm.value.region = newVal.countyName
// filterForm.value.region = newVal.countyName
currentPage.value = 1
} else {
filterForm.value = {

View File

@ -0,0 +1,250 @@
<template>
<base-dialog
:visible="props.visible"
title="重大事件"
:table-data="tableData"
:table-columns="tableColumns"
:table-height="300"
:total="total"
:current-page="currentPage"
:page-size="pageSize"
:max-width="1000"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
@close="handleClose"
>
<!-- 筛选区域 -->
<template #filter>
<div class="filter-row">
<div class="filter-item">
<span class="filter-label">影响区域</span>
<el-select
:teleported="false"
v-model="filterForm.district"
placeholder="请选择"
class="filter-select"
clearable
@change="handleFilterChange"
>
<el-option v-for="item in regionOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="filter-item">
<span class="filter-label">类型</span>
<el-select :teleported="false" v-model="filterForm.type" placeholder="请选择" class="filter-select" clearable @change="handleFilterChange">
<el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="filter-item">
<span class="filter-label">管控措施</span>
<el-select
:teleported="false"
v-model="filterForm.controlMeasure"
placeholder="请选择"
class="filter-select"
clearable
@change="handleFilterChange"
>
<el-option v-for="item in controlMeasureOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
</template>
<!-- 操作列插槽 -->
<template #operation="{ row }">
<div class="operation-btn" @click="handleRescue(row)">抢险</div>
</template>
</base-dialog>
</template>
<script setup>
import { ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import BaseDialog from '../component/baseDialog.vue'
import { controlMeasureOptions, regionOptions, typeOptions } from '../component/index.js'
const router = useRouter()
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:visible', 'close'])
//
const filterForm = ref({
district: '',
type: '',
controlMeasure: '',
})
//
const tableColumns = ref([
{ prop: 'id', label: '序号', width: '60' },
{ prop: 'district', label: '影响区域', width: '' },
{ prop: 'location', label: '阻断小地名', width: '' },
{ prop: 'roadCode', label: '线路编号', width: '' },
{ prop: 'milepost', label: '起止桩号', width: '' },
{ prop: 'occurTime', label: '发生时间', width: '' },
{ prop: 'type', label: '类型', width: '' },
{ prop: 'controlMeasure', label: '管控措施', width: '' },
{ prop: 'operation', label: '操作', width: '', slot: 'operation' },
])
//
const tableData = ref([
{
id: 1,
district: '巫溪县',
location: 'XXX拐弯处',
roadCode: 'G242',
milepost: '336.800-336.850',
occurTime: '2025-08-11 04:53:42',
type: '边坡坍塌',
controlMeasure: '全幅封闭',
},
{
id: 2,
district: '万州区',
location: 'XXX路段',
roadCode: 'G242',
milepost: '336.800-336.850',
occurTime: '2025-08-11 04:53:42',
type: '边坡坍塌',
controlMeasure: '全幅封闭',
},
])
//
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(tableData.value.length)
//
const handleClose = () => {
emit('update:visible', false)
emit('close')
}
//
const handleSizeChange = (val) => {
pageSize.value = val
fetchData()
}
const handleCurrentChange = (val) => {
currentPage.value = val
fetchData()
}
//
const handleFilterChange = () => {
currentPage.value = 1
fetchData()
}
//
const fetchData = () => {
// API
console.log('获取重大事件数据,筛选条件:', filterForm.value)
//
let filteredData = [...tableData.value]
if (filterForm.value.district) {
filteredData = filteredData.filter((item) => item.district === filterForm.value.district)
}
if (filterForm.value.type) {
filteredData = filteredData.filter((item) => item.type === filterForm.value.type)
}
if (filterForm.value.controlMeasure) {
filteredData = filteredData.filter((item) => item.controlMeasure === filterForm.value.controlMeasure)
}
total.value = filteredData.length
}
//
const handleRescue = (row) => {
console.log('抢险操作:', row)
// 3D
window.location.href = '/3DSituationalAwareness?id=1'
}
// visible
watch(
() => props.visible,
(newVal) => {
if (newVal) {
currentPage.value = 1
fetchData()
}
},
)
</script>
<style lang="scss" scoped>
//
.filter-row {
width: 900px;
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.filter-item {
display: flex;
align-items: center;
gap: 8px;
.filter-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.8);
white-space: nowrap;
}
.filter-select {
width: 160px;
:deep(.el-input__wrapper) {
background-color: rgba(30, 70, 120, 0.4);
border: 1px solid rgba(64, 169, 255, 0.3);
box-shadow: none;
border-radius: 4px;
.el-input__inner {
color: #fff;
font-size: 13px;
&::placeholder {
color: rgba(255, 255, 255, 0.4);
}
}
.el-input__suffix {
.el-icon {
color: rgba(255, 255, 255, 0.6);
}
}
}
}
}
//
.operation-btn {
color: #ff6b6b;
cursor: pointer;
transition: all 0.3s;
&:hover {
color: #ff8787;
text-decoration: underline;
}
}
</style>

View File

@ -51,14 +51,14 @@
class="filter-select"
@change="handleFilterChange"
>
<el-option v-for="option in pointLevelOptions" :key="option.value" :label="option.label" :value="option.value" />
<el-option v-for="option in pointLevelOptionsAll" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</div>
<div class="filter-item">
<span class="filter-label">是否回应</span>
<el-select
:teleported="false"
v-model="filterForm.isResponded"
v-model="filterForm.isReply"
placeholder="是否回应"
clearable
class="filter-select"
@ -83,7 +83,7 @@
<div class="person-info">
<div class="person-name center" v-if="row.trafficDept.name != '-'">
<span style="margin-right: 5px">{{ row.trafficDept.name }}</span>
<img class="response-icon" :src="row.trafficDept.isResponded ? row.trafficDept.img : row.trafficDept.img" alt />
<img class="response-icon" :src="row.trafficDept.isReply ? row.trafficDept.img : row.trafficDept.img" alt />
</div>
<span class="person-phone">{{ row.trafficDept.phone }}</span>
</div>
@ -158,7 +158,7 @@
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { Close, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import { pointTypeOptions, pointLevelOptions, isRespondedOptions, formatDateTime } from '../component/index.js'
import { pointTypeOptions, pointLevelOptionsAll, isRespondedOptions, formatDateTime } from '../component/index.js'
import baseDialog from '../component/baseDialog.vue'
import { request } from '@/utils/request.js'
@ -194,7 +194,7 @@ const emit = defineEmits(['update:visible', 'close', 'detail'])
const filterForm = ref({
pointType: '',
pointLevel: '',
isResponded: '',
isReply: '',
})
const cardType = ref('路段')
@ -331,7 +331,7 @@ const fetchData = async () => {
limit: pageSize.value,
warningId: props.responseStatusData.warningId || '',
riskLevel: filterForm.value.pointLevel || '',
isResponded: filterForm.value.isResponded,
isReply: filterForm.value.isReply,
}
if (props.dispatchDateRange && props.dispatchDateRange.length > 0) {
params.start = formatDateTime(props.dispatchDateRange[0]) || ''
@ -368,31 +368,31 @@ const fetchData = async () => {
name: trafficDeptEvent.noticeName || '-',
phone: trafficDeptEvent.noticePhone || '-',
img: trafficDeptEvent.replyState === 'read' ? respondedIcon : notRespondedIcon,
isResponded: trafficDeptEvent.replyState === 'read',
isReply: trafficDeptEvent.replyState === 'read',
},
roadOrg: {
name: roadOrgEvent.noticeName || '-',
phone: roadOrgEvent.noticePhone || '-',
img: roadOrgEvent.replyState === 'read' ? respondedIcon : notRespondedIcon,
isResponded: roadOrgEvent.replyState === 'read',
isReply: roadOrgEvent.replyState === 'read',
},
maintenance: {
name: maintenanceEvent.noticeName || '-',
phone: maintenanceEvent.noticePhone || '-',
img: maintenanceEvent.replyState === 'read' ? respondedIcon : notRespondedIcon,
isResponded: maintenanceEvent.replyState === 'read',
isReply: maintenanceEvent.replyState === 'read',
},
roadKeeper: {
name: roadKeeperEvent.noticeName || '-',
phone: roadKeeperEvent.noticePhone || '-',
img: roadKeeperEvent.replyState === 'read' ? respondedIcon : notRespondedIcon,
isResponded: roadKeeperEvent.replyState === 'read',
isReply: roadKeeperEvent.replyState === 'read',
},
generalStaff: {
name: generalStaffEvent.noticeName || '-',
phone: generalStaffEvent.noticePhone || '-',
img: generalStaffEvent.replyState === 'read' ? respondedIcon : notRespondedIcon,
isResponded: generalStaffEvent.replyState === 'read',
isReply: generalStaffEvent.replyState === 'read',
},
urgeTime: {
@ -441,7 +441,7 @@ const handleFilterChange = () => {
console.log(filterForm.value)
filterForm.value.pointLevel = filterForm.value.pointLevel || ''
filterForm.value.isResponded = filterForm.value.isResponded
filterForm.value.isReply = filterForm.value.isReply
currentPage.value = 1
fetchData()
}

View File

@ -132,6 +132,15 @@ export const pointLevelOptions = [
{ label: '较高风险', value: '较高风险' },
{ label: '高风险', value: '高风险' },
]
export const pointLevelOptionsAll = [
{ label: '全部', value: '' },
{ label: '低风险', value: '低风险' },
{ label: '中风险', value: '中风险' },
{ label: '高风险', value: '高风险' },
{ label: '一般隐患', value: '一般隐患' },
{ label: '较大隐患', value: '较大隐患' },
{ label: '较高风险', value: '较高风险' },
]
// 是否回应选项
export const isRespondedOptions = [

View File

@ -46,6 +46,7 @@
@openPatrolMileage="openDialog('patrolMileage')"
@openPatrolSituation="openDialog('patrolSituation')"
@update:filterForm="updateFilterForm"
@open-major-event="() => (dialogVisible.majorEvent = true)"
></right>
</div>
<!-- 地图中心 -->
@ -258,6 +259,9 @@
<!-- 巡查情况对话框 -->
<patrolSituationDialog v-model:visible="dialogVisible.patrolSituation" @close="closeDialog('patrolSituation')" />
<!-- 重大事件对话框 -->
<majorEventDialog v-model:visible="dialogVisible.majorEvent" @close="closeDialog('majorEvent')" />
</div>
</div>
</template>
@ -308,6 +312,7 @@ 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 majorEventDialog from './Dialog/majorEventDialog.vue'
import './component/el-select.scss'
import './component/date-picker-theme.scss'
@ -340,6 +345,7 @@ const dialogVisible = ref({
imageInspection: false,
patrolMileage: false,
patrolSituation: false,
majorEvent: false,
})
const activeitem = ref({})

View File

@ -659,7 +659,7 @@ const getBarHeight = (value) => {
const actualValue = value.count || value.value
if (!actualValue || actualValue == 0) return '0'
// 10%100%
const height = (actualValue / totalValue.value) * 300
const height = (actualValue / totalValue.value) * 100
// 3%
// 100% 3%
console.log(height)

View File

@ -173,7 +173,7 @@
</div>
<!-- 重大事件 -->
<div class="event-section">
<div class="event-section" @click="$emit('open-major-event')">
<span class="event-title">重大事件</span>
<span class="event-num">{{ majorEvent }}</span>
</div>
@ -1256,6 +1256,7 @@ watch(
}
.event-section {
cursor: pointer;
text-align: center;
padding: vw(12);
// background: rgba(64, 169, 255, 0.1);