1343 lines
36 KiB
Vue
Raw Normal View History

2026-03-27 17:47:09 +08:00
<template>
<div class="right-panel">
<SectionHeader title="防范应对" />
<!-- 防范应对 -->
2026-03-31 18:10:34 +08:00
<div class="control-section">
<div class="control-title">应急力量</div>
</div>
2026-03-27 17:47:09 +08:00
<div class="prevention-section">
<!-- 第一行队伍人员装备物资 -->
<div class="resource-grid">
2026-03-31 18:10:34 +08:00
<div
v-for="(item, index) in resourceData"
:key="index"
class="resource-item"
@click="handleResourceClick(item)"
2026-03-31 18:10:34 +08:00
>
2026-03-27 17:47:09 +08:00
<!-- <div class="resource-icon" :class="item.iconClass"></div> -->
<img class="resource-icon" :src="item.img" alt="" />
<div class="resource-info">
<div class="resource-label">{{ item.label }}</div>
<div class="resource-value">
{{ item.value }}
<span class="unit">{{ item.unit }}</span>
2026-03-27 17:47:09 +08:00
</div>
</div>
</div>
</div>
<!-- 管控路段数 -->
<div class="control-section">
2026-04-02 16:35:45 +08:00
<div class="control-title display jc_sb ai_center">
<div class="f1">管控路段数</div>
<div class="f1">管控项目</div>
2026-03-31 18:10:34 +08:00
</div>
<div style="display: flex; justify-content: space-between">
<div class="control-grid">
<div
v-for="(item, index) in controlData1"
:key="index"
class="control-item"
:class="{
clickable: true,
2026-03-31 18:10:34 +08:00
}"
@click="handleControlClick(item)"
>
<!-- item.label === '封闭管控数' -->
2026-03-31 18:10:34 +08:00
<div class="control-value">{{ item.value }}</div>
<div class="control-label">{{ item.label }}</div>
</div>
</div>
2026-03-31 18:10:34 +08:00
<div style="width: 10px"></div>
<div class="control-grid">
<div
v-for="(item, index) in controlData2"
:key="index"
class="control-item"
:class="{
clickable: item.label == '停工项目数' || item.label == '关闭驻地数',
2026-03-31 18:10:34 +08:00
}"
@click="handleControlClick(item)"
>
<div class="control-value">{{ item.value }}</div>
<div class="control-label">{{ item.label }}</div>
</div>
2026-03-27 17:47:09 +08:00
</div>
</div>
</div>
<!-- 巡查公路里程 -->
<div class="patrol-section clickable">
2026-04-02 16:35:45 +08:00
<div class="patrol-header display jc_sb ai_center">
2026-04-28 09:20:54 +08:00
<div @click="handlePatrolClick" style="cursor: pointer">
2026-04-02 16:35:45 +08:00
<span class="patrol-title">巡查公路里程</span>
<span class="patrol-mileage ml_10">{{ roadInspectionMileage }}km</span>
2026-04-02 16:35:45 +08:00
</div>
<div>
<span class="patrol-title">巡查项目数</span>
<span class="patrol-mileage ml_10">0</span>
2026-04-02 16:35:45 +08:00
</div>
2026-03-27 17:47:09 +08:00
</div>
2026-04-28 09:20:54 +08:00
<div class="patrol-grid" style="cursor: pointer" @click="handlePatrolSituationClick">
<div v-for="(item, index) in patrolData" :key="index" class="patrol-item">
2026-03-27 17:47:09 +08:00
<div class="patrol-value">{{ item.value }}</div>
<div class="patrol-label">{{ item.label }}</div>
</div>
</div>
</div>
<!-- 抢险投入情况 -->
<div class="rescue-section">
<div class="rescue-title">抢险投入情况</div>
<div class="rescue-grid">
<div v-for="(item, index) in rescueData" :key="index" class="rescue-item">
2026-03-27 17:47:09 +08:00
<!-- <div class="rescue-icon" :class="item.iconClass"></div> -->
<img class="rescue-icon" :src="item.img" alt="" />
<div class="rescue-info">
<div class="rescue-value">
{{ item.value }}
<span class="unit">{{ item.unit }}</span>
2026-03-27 17:47:09 +08:00
</div>
<div class="rescue-label">{{ item.label }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- 受灾情况 -->
<div class="disaster-section">
<SectionHeader title="受灾情况">
<template #right>
<div class="header-filters">
<span class="filter-item active" @click="handleDateRangeClick()">本轮</span>
2026-03-27 17:47:09 +08:00
<div class="date-range-wrapper">
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间"
size="small"
popper-class="custom-date-picker"
:teleported="false"
2026-03-27 17:47:09 +08:00
:prefix-icon="Calendar"
@change="handleDateChange"
2026-03-27 17:47:09 +08:00
/>
</div>
</div>
</template>
</SectionHeader>
<!-- 阻断情况 -->
<div class="block-section clickable" @click="handleBlockClick">
2026-03-27 17:47:09 +08:00
<div class="block-title">阻断情况(已抢通/阻断数)</div>
<div class="block-grid">
<div class="block-item">
<div class="block-num">
<span class="current">{{ blockData[0].current }}</span>
<span class="separator">/</span>
<span class="total">{{ blockData[0].total }}</span>
</div>
<div class="block-label">{{ blockData[0].label }}</div>
</div>
<div class="divider-line"></div>
<div class="block-item">
<div class="block-num">
<span class="current">{{ blockData[1].current }}</span>
<span class="separator">/</span>
<span class="total">{{ blockData[1].total }}</span>
</div>
<div class="block-label">{{ blockData[1].label }}</div>
</div>
<div class="divider-line"></div>
<div class="block-item death-item">
<div class="death-num">{{ deathData.value }}</div>
<div class="death-label">{{ deathData.label }}</div>
</div>
</div>
</div>
<!-- 灾害情况 -->
<div class="damage-section">
<div class="damage-title">灾害情况</div>
<div class="damage-grid">
<div
v-for="(item, index) in damageData"
:key="index"
class="damage-item"
:class="item.class"
>
<div class="damage-value">
{{ item.value }}
<span class="unit">{{ item.unit }}</span>
2026-03-27 17:47:09 +08:00
</div>
<div class="damage-label">{{ item.label }}</div>
</div>
</div>
</div>
<!-- 重大事件 -->
<div class="event-section">
<span class="event-title">重大事件</span>
<span class="event-num">{{ majorEvent }}</span>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, inject, watch } from 'vue';
import { request } from '@/utils/request';
2026-03-27 17:47:09 +08:00
import SectionHeader from './component/sectionHeader.vue';
import { Calendar } from '@element-plus/icons-vue';
2026-03-27 17:47:09 +08:00
import icon1 from '../../assets/RiskWarning_img/icon1@2x.png';
import icon2 from '../../assets/RiskWarning_img/icon2@2x.png';
import icon3 from '../../assets/RiskWarning_img/icon3@2x.png';
import icon4 from '../../assets/RiskWarning_img/icon4@2x.png';
2026-03-27 17:47:09 +08:00
import icon11 from '../../assets/RiskWarning_img/icon-1@2x.png';
import icon12 from '../../assets/RiskWarning_img/icon-2@2x.png';
import icon13 from '../../assets/RiskWarning_img/icon-3@2x.png';
2026-03-27 17:47:09 +08:00
import icon51 from '../../assets/RiskWarning_img/编组5@2x.png';
import icon52 from '../../assets/RiskWarning_img/编组22@2x.png';
import icon55 from '../../assets/RiskWarning_img/路径55@2x.png';
2026-03-27 17:47:09 +08:00
import icon62 from '../../assets/RiskWarning_img/路径62@2x.png';
import icon621 from '../../assets/RiskWarning_img/路径62@2x (1).png';
import icon622 from '../../assets/RiskWarning_img/路径62@2x (2).png';
import { formatDateTime } from './component/index.js';
2026-03-27 17:47:09 +08:00
const emit = defineEmits([
'openClearanceSituation',
'openControlSituation',
'openResourceDetail',
'update:dateRange',
'openPatrolMileage',
'openPatrolSituation',
'update:filterForm',
]);
// 注入兄弟组件通信机制
const setRefreshRightData = inject('setRefreshRightData');
const getdateRange = inject('getdateRange', ref([]));
const props = defineProps({});
// 日期选择器变化事件
const handleDateChange = val => {
dateRange.value = val;
getDisasterStats();
};
// 点击日期范围器
const handleDateRangeClick = val => {
dateRange.value = [];
getDisasterStats();
};
// 获取应急力量列表数据
const getYhYjllList = async () => {
try {
const res = await request({
url: '/snow-ops-platform/yhYjll/list',
method: 'GET',
params: {
// longitude: 114.305556,
// latitude: 22.624722,
// maxDistance: 10 // 1000km
},
});
console.log(res);
if (res.code == '00000') {
let gl1Rysls = 0; // 人员数
let gl1Yjllmcs = 0; // 队伍数
res.data.forEach(item => {
2026-04-09 14:53:44 +08:00
if (item.gl1Lx == 1 || item.gl1Lx == 2) {
gl1Yjllmcs = gl1Yjllmcs + 1;
}
gl1Rysls = Number(item.gl1Rysl) + gl1Rysls;
});
if (gl1Rysls > 10000) {
gl1Rysls = (gl1Rysls / 10000).toFixed(2);
resourceData.value[1].unit = '万人';
} else {
resourceData.value[1].value = gl1Rysls;
resourceData.value[1].unit = '人';
}
resourceData.value[0].value = gl1Yjllmcs;
}
} catch (error) {
console.error('获取应急力量列表失败:', error);
}
};
// 根据类型获取图标
const getIconByType = type => {
const iconMap = {
1: icon1, // 队伍
2: icon2, // 人员
3: icon3, // 装备
4: icon4, // 物资
};
return iconMap[type] || icon1;
};
// 获取物资列表数据
const getYhYjllListMaterials = async () => {
try {
const res = await request({
url: '/snow-ops-platform/yhYjll/listMaterials',
method: 'GET',
params: {},
});
console.log('物资列表:', res);
if (res.code == '00000' && res.data) {
let equipment = 0; // 装备数
let materials = 0; // 物资数
res.data.forEach(item => {
if (item.gl1Wzlx == 1) {
equipment = equipment + extractAndSumNumbers(item.gl1Wzsl);
} else if (item.gl1Wzlx == 2) {
materials = materials + extractAndSumNumbers(item.gl1Wzsl);
}
});
if (materials > 10000) {
resourceData.value[3].value = (materials / 10000).toFixed(2);
resourceData.value[3].unit = '万件';
} else {
resourceData.value[3].value = materials;
resourceData.value[3].unit = '件';
}
console.log(equipment, materials);
// 更新物资数据
resourceData.value[2].value = equipment || '0';
}
} catch (error) {
console.error('获取物资列表失败:', error);
}
};
// 获取管控统计数据
const getControlStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/control-stats',
method: 'GET',
params: params,
});
console.log('管控统计数据:', res);
if (res.code == '00000' && res.data) {
const data = res.data;
// 更新controlData1数组的value值
controlData1.value.forEach(item => {
if (item.label === '封闭管控数') {
item.value = data.fullClosureCount || '0';
} else if (item.label === '半幅通行数') {
item.value = data.halfClosureCount || '0';
} else if (item.label === '限速(限车型)数') {
item.value = data.speedLimitCount || '0';
} else if (item.label === '告警阻拦处数') {
item.value = data.warningBlockCount || '0';
}
});
}
} catch (error) {
console.error('获取管控统计数据失败:', error);
}
};
// 获取抢险投入统计数据
const getRescueInputStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/rescue-input-stats',
method: 'GET',
params: params,
});
console.log('抢险投入统计数据:', res);
if (res.code == '00000' && res.data) {
const data = res.data;
// 更新rescueData数组的value值
rescueData.value.forEach(item => {
if (item.label === '本轮出动人次') {
item.value = data.investedManpower || '0';
item.unit = '人';
if (item.value > 10000) {
item.value = (item.value / 10000).toFixed(2);
item.unit = '万人';
}
} else if (item.label === '本轮出动设备') {
item.value = data.investedMachinery || '0';
item.unit = '台';
if (item.value > 10000) {
item.value = (item.value / 10000).toFixed(2);
item.unit = '万台';
}
} else if (item.label === '清理塌方') {
// 将立方米转换为万立方米
item.value = data.clearedLandslide.toFixed(2) || 0;
item.unit = '立方米';
if (item.value > 10000) {
item.value = (item.value / 10000).toFixed(2);
item.unit = '万立方米';
}
}
});
}
} catch (error) {
console.error('获取抢险投入统计数据失败:', error);
}
};
// 获取灾害统计数据
const getDisasterStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (dateRange.value && dateRange.value.length === 2) {
params.start = formatDateTime(dateRange.value[0]);
params.end = formatDateTime(dateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/disaster-stats',
method: 'GET',
params: params,
});
console.log('灾害统计数据:', res);
if (res.code == '00000' && res.data) {
const data = res.data;
// 更新blockData数组的value值
blockData.value.forEach(item => {
if (item.label === '今日新增阻断数') {
item.current = data.todayNormalCount || '0';
item.total = data.todayTotalCount || '0';
} else if (item.label === '本轮累计阻断数') {
item.current = data.roundNormalCount || '0';
item.total = data.roundTotalCount || '0';
}
});
// 更新deathData的value值
deathData.value.value = data.roundDeadCount || '0';
// 更新damageData数组的value值
damageData.value.forEach(item => {
if (item.label === '本轮塌方量') {
data.roundLandslideVolume = data.roundLandslideVolume.toFixed(2);
if (data.roundLandslideVolume > 10000) {
item.value = (data.roundLandslideVolume / 10000).toFixed(2) || '0';
item.unit = '万立方米';
} else {
item.value = data.roundLandslideVolume || '0';
item.unit = '立方米';
}
} else if (item.label === '汛期塌方量') {
data.floodSeasonLandslideVolume = data.floodSeasonLandslideVolume.toFixed(2);
if (data.floodSeasonLandslideVolume > 10000) {
item.value = (data.floodSeasonLandslideVolume / 10000).toFixed(2) || '0';
item.unit = '万立方米';
} else {
item.value = data.floodSeasonLandslideVolume || '0';
item.unit = '立方米';
}
} else if (item.label === '当年塌方量') {
data.yearLandslideVolume = data.yearLandslideVolume.toFixed(2);
if (data.yearLandslideVolume > 10000) {
item.value = (data.yearLandslideVolume / 10000).toFixed(2) || '0';
item.unit = '万立方米';
} else {
item.value = data.yearLandslideVolume || '0';
item.unit = '立方米';
}
} else if (item.label === '本轮已损失') {
data.roundTotalLossAmount = data.roundTotalLossAmount.toFixed(2);
if (data.roundTotalLossAmount > 10000) {
item.value = (data.roundTotalLossAmount / 10000).toFixed(2) || '0';
item.unit = '亿元';
} else {
item.value = data.roundTotalLossAmount || '0';
item.unit = '万元';
}
} else if (item.label === '汛期已损失') {
data.floodSeasonTotalLossAmount = data.floodSeasonTotalLossAmount.toFixed(2);
if (data.floodSeasonTotalLossAmount > 10000) {
item.value = (data.floodSeasonTotalLossAmount / 10000).toFixed(2) || '0';
item.unit = '亿元';
} else {
item.value = data.floodSeasonTotalLossAmount || '0';
item.unit = '万元';
}
} else if (item.label === '当年已损失') {
data.yearTotalLossAmount = data.yearTotalLossAmount.toFixed(2);
if (data.yearTotalLossAmount > 10000) {
item.value = (data.yearTotalLossAmount / 10000).toFixed(2) || '0';
item.unit = '亿元';
} else {
item.value = data.yearTotalLossAmount || '0';
item.unit = '万元';
}
}
});
}
} catch (error) {
console.error('获取灾害统计数据失败:', error);
}
};
// 从字符串中提取数字并相加
const extractAndSumNumbers = value => {
// 如果是数字,直接返回
if (typeof value === 'number') {
return value;
}
// 如果不是字符串,返回 0
if (!value || typeof value !== 'string') return 0;
// 匹配所有数字(包括小数)
const numbers = value.match(/\d+\.?\d*/g);
if (!numbers) return 0;
// 将提取的数字相加
return numbers.reduce((sum, num) => sum + Number(num), 0);
};
// 点击管控项
const handleControlClick = item => {
if (
item.label === '封闭管控数' ||
item.label === '半幅通行数' ||
item.label === '限速(限车型)数' ||
item.label === '告警阻拦处数'
) {
emit('openClearanceSituation');
emit('update:dateRange', getdateRange.value || []);
emit('update:filterForm', item || {});
} else if (item.label === '停工项目数' || item.label === '关闭驻地数') {
emit('openControlSituation');
}
};
// 点击阻断情况
const handleBlockClick = () => {
emit('openClearanceSituation');
2026-04-28 09:20:54 +08:00
emit('update:filterForm', {});
};
// 点击巡查公路里程
const handlePatrolClick = () => {
emit('openPatrolMileage');
};
// 点击巡查情况
const handlePatrolSituationClick = () => {
emit('openPatrolSituation');
};
2026-03-27 17:47:09 +08:00
// 日期范围选择器
const dateRange = ref([]);
// 资源数据(队伍、人员、装备、物资)
const resourceData = ref([
2026-03-27 17:47:09 +08:00
{
label: '全市普通公路抢险队伍',
value: '',
unit: '支',
iconClass: 'icon-team',
2026-03-27 17:47:09 +08:00
img: icon1,
},
2026-03-31 18:10:34 +08:00
{
label: '人员',
value: '',
unit: '人',
iconClass: 'icon-person',
2026-03-31 18:10:34 +08:00
img: icon2,
},
{
label: '储备装备',
value: '',
unit: '台',
iconClass: 'icon-equip',
2026-03-31 18:10:34 +08:00
img: icon3,
},
{
label: '物资',
value: '',
unit: '件',
iconClass: 'icon-material',
2026-03-31 18:10:34 +08:00
img: icon4,
},
]);
2026-03-27 17:47:09 +08:00
// 点击资源项
const handleResourceClick = item => {
emit('openResourceDetail', item);
};
2026-03-27 17:47:09 +08:00
// 管控路段数据
const controlData1 = ref([
{ label: '封闭管控数', value: '40' },
{ label: '半幅通行数', value: '40' },
{ label: '限速(限车型)数', value: '24' },
{ label: '告警阻拦处数', value: '32' },
]);
2026-04-17 17:23:51 +08:00
const controlData2 = ref([
{ label: '停工项目数', value: '0', key: 'stoped_project_count' },
{ label: '关闭驻地数', value: '0', key: 'closed_site_count' },
{ label: '转移撤离人员数', value: '0', key: 'displaced_population' },
]);
// 获取气象预警受影响统计(按项目)
const getAffectedCountByProject = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
2026-04-17 17:23:51 +08:00
const res = await request({
url: '/snow-ops-platform/weather-warning/affected-count/_by_project',
method: 'GET',
params: params,
2026-04-17 17:23:51 +08:00
});
console.log('气象预警受影响统计:', res);
if (res.code === '00000' && res.data) {
const data = res.data;
// 更新 controlData2 数组的值
controlData2.value.forEach(item => {
const matchedData = data.find(d => d.name === item.key);
if (matchedData) {
item.value = String(matchedData.count);
}
});
}
} catch (error) {
console.error('获取气象预警受影响统计失败:', error);
}
};
2026-03-27 17:47:09 +08:00
// 巡查数据
const patrolData = ref([
{ label: '巡查路段数', value: '0', key: 'roadSectionInspectionCount' },
{ label: '巡查桥梁数', value: '0', key: 'bridgeInspectionCount' },
{ label: '巡查边坡数', value: '0', key: 'slopeInspectionCount' },
{ label: '巡查隧道数', value: '0', key: 'tunnelInspectionCount' },
{ label: '发现隐患数', value: '0', key: 'hiddenDangerCount' },
]);
// 巡查公路里程
const roadInspectionMileage = ref('0');
// 获取巡查统计数据
const getInspectionStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/yhWgxc/weather-warning/inspection-stats',
method: 'GET',
params: params,
});
console.log('巡查统计数据:', res);
if (res.code == '00000' && res.data) {
const data = res.data;
// 更新巡查公路里程
roadInspectionMileage.value = data.roadInspectionMileage || '0';
// 更新patrolData数组的value值
patrolData.value.forEach(item => {
if (item.key === 'roadSectionInspectionCount') {
item.value = data.roadSectionInspectionCount || '0';
} else if (item.key === 'bridgeInspectionCount') {
item.value = data.bridgeInspectionCount || '0';
} else if (item.key === 'slopeInspectionCount') {
item.value = data.slopeInspectionCount || '0';
} else if (item.key === 'tunnelInspectionCount') {
item.value = data.tunnelInspectionCount || '0';
} else if (item.key === 'hiddenDangerCount') {
item.value = data.hiddenDangerCount || '0';
}
});
}
} catch (error) {
console.error('获取巡查统计数据失败:', error);
}
};
2026-03-27 17:47:09 +08:00
// 抢险投入数据
const rescueData = ref([
2026-03-27 17:47:09 +08:00
{
label: '本轮出动人次',
value: '22341',
unit: '人次',
iconClass: 'icon-rescue-person',
2026-03-27 17:47:09 +08:00
img: icon11,
},
{
label: '本轮出动设备',
value: '341',
unit: '台次',
iconClass: 'icon-rescue-equip',
2026-03-27 17:47:09 +08:00
img: icon12,
},
{
label: '清理塌方',
value: '1367',
unit: '立方米',
iconClass: 'icon-rescue-clear',
2026-03-27 17:47:09 +08:00
img: icon13,
},
]);
2026-03-27 17:47:09 +08:00
// 受灾情况 - 阻断数据
const blockData = ref([
{ label: '今日新增阻断数', current: '19', total: '23' },
{ label: '本轮累计阻断数', current: '10', total: '23' },
]);
2026-03-27 17:47:09 +08:00
// 伤亡人数
const deathData = ref({ label: '本轮因灾伤亡人数', value: '5' });
2026-03-27 17:47:09 +08:00
// 灾害情况数据
const damageData = ref([
{ label: '本轮塌方量', value: '23', unit: '万立方米', class: 'blue' },
{ label: '汛期塌方量', value: '23', unit: '万立方米', class: 'blue' },
{ label: '当年塌方量', value: '23', unit: '万立方米', class: 'blue' },
{ label: '本轮已损失', value: '80', unit: '万元', class: 'red' },
{ label: '汛期已损失', value: '18', unit: '万元', class: 'red' },
{ label: '当年已损失', value: '350', unit: '万元', class: 'red' },
]);
2026-03-27 17:47:09 +08:00
// 重大事件数
const majorEvent = '0';
// 刷新数据的函数提前定义避免watch中调用时未初始化
const init = () => {
console.log('right.vue 刷新数据');
getYhYjllList(); // 获取应急力量列表数据
getYhYjllListMaterials(); // 获取物资列表数据
getControlStats(); // 获取管控统计数据
getAffectedCountByProject(); // 获取气象预警受影响统计数据
getRescueInputStats(); // 获取抢险投入统计数据
getDisasterStats(); // 获取灾害统计数据
getInspectionStats(); // 获取巡查统计数据
};
// 组件挂载时获取数据并注册刷新函数
onMounted(() => {
init();
// 注册刷新函数到父组件
if (setRefreshRightData) {
setRefreshRightData(init);
}
});
watch(
() => getdateRange.value,
newVal => {
console.log('right.vue 日期范围变化:', newVal);
if (newVal && newVal.length === 2) {
init();
}
},
{ deep: true, immediate: true }
);
2026-03-27 17:47:09 +08:00
</script>
<style lang="scss" scoped>
// 视频屏幕自适应 - 基于视口宽度动态调整
// 基准宽度 1920px使用 vw 单位实现自适应
@function vw($px) {
@return calc($px / 1920 * 100vw);
}
2026-03-27 17:47:09 +08:00
.right-panel {
width: 100%;
height: 100%;
padding: vw(20);
2026-03-27 17:47:09 +08:00
box-sizing: border-box;
overflow-y: auto;
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
// 小屏幕适配
@media (max-width: 1366px) {
padding: 12px;
}
@media (max-width: 1024px) {
padding: 8px;
}
2026-03-27 17:47:09 +08:00
}
.prevention-section {
// background: linear-gradient(
// 180deg,
// rgba(21, 41, 59, 0.95) 0%,
// rgba(13, 28, 42, 0.95) 100%
// );
// border: 1px solid rgba(64, 169, 255, 0.3);
border-radius: 8px;
}
.section-header {
display: flex;
justify-content: space-between;
background-image: url('../../assets/RiskWarning_img/标题bg@2x.png');
2026-03-27 17:47:09 +08:00
align-items: center;
2026-04-02 16:35:45 +08:00
margin-bottom: vw(8);
height: vw(50);
2026-03-27 17:47:09 +08:00
.header-left {
display: flex;
align-items: center;
2026-04-02 16:35:45 +08:00
gap: vw(6);
2026-03-27 17:47:09 +08:00
.icon-back {
2026-04-02 16:35:45 +08:00
width: vw(16);
height: vw(16);
min-width: 14px;
min-height: 14px;
background: linear-gradient(135deg, #18f2f9 0%, #1890ff 100%);
2026-03-27 17:47:09 +08:00
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
&::before {
content: '←';
2026-03-27 17:47:09 +08:00
color: #fff;
2026-04-02 16:35:45 +08:00
font-size: vw(10);
2026-03-27 17:47:09 +08:00
}
}
.title {
2026-04-02 16:35:45 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
font-weight: bold;
color: #fff;
}
}
}
// 资源网格(队伍、人员、装备、物资)
.resource-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
2026-04-02 16:35:45 +08:00
gap: vw(6);
margin-bottom: vw(6);
2026-03-27 17:47:09 +08:00
.resource-item {
display: flex;
align-items: center;
box-sizing: border-box;
height: 42px;
2026-04-02 16:35:45 +08:00
gap: vw(6);
padding: vw(4) vw(8);
background: linear-gradient(270deg, rgba(18, 52, 97, 0) 0%, #203555 100%);
2026-03-27 17:47:09 +08:00
border: 2px solid transparent;
border-image: linear-gradient(270deg, rgba(80, 145, 201, 0), rgba(39, 77, 153, 1)) 2 2;
2026-03-27 17:47:09 +08:00
border-radius: 6px;
border-right: 0px;
.resource-icon {
2026-04-02 16:35:45 +08:00
width: vw(24);
height: vw(24);
min-width: 16px;
min-height: 16px;
2026-03-27 17:47:09 +08:00
display: flex;
align-items: center;
justify-content: center;
2026-04-02 16:35:45 +08:00
font-size: vw(18);
2026-03-27 17:47:09 +08:00
&.icon-team::before {
content: '👷';
2026-03-27 17:47:09 +08:00
}
&.icon-person::before {
content: '👤';
2026-03-27 17:47:09 +08:00
}
&.icon-equip::before {
content: '🚛';
2026-03-27 17:47:09 +08:00
}
&.icon-material::before {
content: '📦';
2026-03-27 17:47:09 +08:00
}
}
.resource-info {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
.resource-label {
width: 48%;
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
2026-04-02 16:35:45 +08:00
margin-bottom: vw(2);
2026-03-27 17:47:09 +08:00
}
.resource-value {
2026-04-02 16:35:45 +08:00
font-size: vw(16);
2026-03-27 17:47:09 +08:00
font-weight: bold;
color: #18f2f9;
2026-03-27 17:47:09 +08:00
.unit {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
font-weight: normal;
margin-left: 2px;
}
}
}
}
}
// 管控路段
.control-section {
margin-bottom: vw(10);
2026-03-27 17:47:09 +08:00
.control-title {
2026-04-02 16:35:45 +08:00
font-size: vw(16);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.9);
margin-bottom: vw(10);
2026-04-02 16:35:45 +08:00
font-weight: 600;
2026-03-27 17:47:09 +08:00
.control-num {
font-size: vw(16);
2026-03-27 17:47:09 +08:00
color: #18f2f9;
2026-03-27 17:47:09 +08:00
font-weight: bold;
margin-left: vw(5);
2026-03-27 17:47:09 +08:00
}
}
.control-grid {
2026-03-31 18:10:34 +08:00
flex: 1;
2026-03-27 17:47:09 +08:00
display: grid;
2026-03-31 18:10:34 +08:00
grid-template-columns: repeat(2, 1fr);
2026-04-03 18:08:42 +08:00
// background: rgba(62, 106, 172, 0.36);
// box-shadow: inset 0px 0px 8px 0px #379bff;
background-image: url('../../assets/RiskWarning_img/路径 62@2x.png');
2026-04-03 18:08:42 +08:00
background-size: 100% 100%;
background-position: right;
gap: vw(8);
2026-03-27 17:47:09 +08:00
.control-item {
text-align: center;
2026-04-02 16:35:45 +08:00
padding: vw(5) vw(5);
2026-03-27 17:47:09 +08:00
// background: rgba(64, 169, 255, 0.1);
border-radius: 4px;
&.clickable {
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: rgba(64, 169, 255, 0.15);
}
}
2026-03-27 17:47:09 +08:00
.control-value {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
color: #18f2f9;
2026-04-02 16:35:45 +08:00
// margin-bottom: vw(4);
2026-03-27 17:47:09 +08:00
}
.control-label {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
}
}
}
}
// 巡查公路里程
.patrol-section {
margin-bottom: vw(10);
2026-03-27 17:47:09 +08:00
.patrol-header {
display: flex;
align-items: center;
gap: vw(10);
margin-bottom: vw(10);
2026-03-27 17:47:09 +08:00
.patrol-title {
2026-04-02 16:35:45 +08:00
font-size: vw(16);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.9);
}
.patrol-mileage {
font-size: vw(16);
2026-03-27 17:47:09 +08:00
font-weight: bold;
color: #4fecff;
2026-03-27 17:47:09 +08:00
}
}
.patrol-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: vw(8);
2026-03-27 17:47:09 +08:00
.patrol-item {
text-align: center;
padding: vw(6) vw(5);
2026-03-27 17:47:09 +08:00
// background: rgba(64, 169, 255, 0.1);
// border-radius: 4px;
background-image: url('../../assets/RiskWarning_img/路径62@2x (1).png');
2026-03-27 17:47:09 +08:00
background-size: 100% 100%;
background-position: right;
.patrol-value {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
color: #4fecff;
margin-bottom: vw(4);
2026-03-27 17:47:09 +08:00
text-align: left;
margin-left: vw(5);
2026-03-27 17:47:09 +08:00
}
.patrol-label {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
}
}
}
}
// 抢险投入情况
.rescue-section {
.rescue-title {
2026-04-02 16:35:45 +08:00
font-size: vw(16);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.9);
margin-bottom: vw(10);
2026-03-27 17:47:09 +08:00
}
.rescue-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: vw(10);
2026-03-27 17:47:09 +08:00
.rescue-item {
display: flex;
align-items: center;
gap: vw(4);
padding: vw(8) 0;
2026-03-27 17:47:09 +08:00
// background: rgba(64, 169, 255, 0.1);
// border: 1px solid rgba(64, 169, 255, 0.2);
// border-radius: 6px;
background-image: url('../../assets/RiskWarning_img/路径62@2x (1).png');
2026-03-27 17:47:09 +08:00
background-size: 100% 100%;
background-position: right;
.rescue-icon {
2026-04-02 16:35:45 +08:00
width: vw(40);
height: vw(40);
2026-03-27 17:47:09 +08:00
display: flex;
align-items: center;
justify-content: center;
font-size: vw(22);
margin-left: vw(5);
2026-03-27 17:47:09 +08:00
&.icon-rescue-person::before {
content: '👷';
2026-03-27 17:47:09 +08:00
}
&.icon-rescue-equip::before {
content: '🚜';
2026-03-27 17:47:09 +08:00
}
&.icon-rescue-clear::before {
content: '🏔️';
2026-03-27 17:47:09 +08:00
}
}
.rescue-info {
.rescue-value {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
2026-04-02 16:35:45 +08:00
color: #fff;
margin-bottom: vw(4);
2026-03-27 17:47:09 +08:00
display: flex;
align-items: center;
.unit {
font-size: vw(10);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
font-weight: normal;
margin-left: 2px;
}
}
.rescue-label {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
}
}
}
}
}
// 受灾情况样式
.disaster-section {
2026-04-02 16:35:45 +08:00
margin-top: vw(10);
2026-03-27 17:47:09 +08:00
.block-section {
margin-bottom: vw(10);
&.clickable {
cursor: pointer;
transition: all 0.3s;
&:hover {
opacity: 0.9;
.block-title {
color: #69c0ff;
}
}
}
2026-03-27 17:47:09 +08:00
.block-title {
2026-04-02 16:35:45 +08:00
font-size: vw(16);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.8);
margin-bottom: vw(10);
2026-03-27 17:47:09 +08:00
}
.block-grid {
display: flex;
justify-content: space-between;
height: 100%;
padding: 0 vw(20);
2026-03-27 17:47:09 +08:00
// display: grid;
// grid-template-columns: repeat(5, 1fr);
// gap: 10px;
background-image: url('../../assets/RiskWarning_img/编组22@2x.png');
2026-03-27 17:47:09 +08:00
background-size: 100% 100%;
background-position: center;
.divider-line {
width: 2px;
height: vw(40);
2026-03-27 17:47:09 +08:00
margin: auto 0;
background: linear-gradient(180deg, transparent 0%, #18f2f9 50%, transparent 100%);
2026-03-27 17:47:09 +08:00
// margin: 0 auto;
}
.block-item {
text-align: center;
padding: vw(8);
2026-03-27 17:47:09 +08:00
// background: rgba(64, 169, 255, 0.1);
// border-radius: 6px;
// background-image: url("../../assets/RiskWarning_img/路径62@2x (1).png");
// background-size: 100% 100%;
// background-position: left;
.block-num {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
margin-bottom: vw(6);
2026-03-27 17:47:09 +08:00
.current {
color: #18f2f9;
2026-03-27 17:47:09 +08:00
}
.separator {
color: rgba(255, 255, 255, 0.5);
margin: 0 2px;
}
.total {
color: #ff4d4f;
}
}
.block-label {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
}
&.death-item {
.death-num {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
2026-04-02 16:35:45 +08:00
color: #fff;
margin-bottom: vw(6);
2026-03-27 17:47:09 +08:00
}
.death-label {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
}
}
}
}
}
.damage-section {
2026-04-02 16:35:45 +08:00
margin-bottom: vw(5);
2026-03-27 17:47:09 +08:00
.damage-title {
2026-04-02 16:35:45 +08:00
font-size: vw(16);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.8);
margin-bottom: vw(10);
2026-03-27 17:47:09 +08:00
}
.damage-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
2026-04-02 16:35:45 +08:00
gap: vw(5);
2026-03-27 17:47:09 +08:00
.damage-item {
text-align: center;
padding: vw(4) 0;
2026-03-27 17:47:09 +08:00
// background: rgba(64, 169, 255, 0.1);
// border-radius: 6px;
background-image: url('../../assets/RiskWarning_img/路径62@2x.png');
2026-03-27 17:47:09 +08:00
background-size: 100% 100%;
background-position: left;
.damage-value {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
margin-bottom: vw(6);
2026-03-27 17:47:09 +08:00
.unit {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
font-weight: normal;
margin-left: 2px;
}
}
.damage-label {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.7);
}
&.blue .damage-value {
color: #18f2f9;
2026-03-27 17:47:09 +08:00
.unit {
color: rgba(255, 255, 255, 0.7);
}
}
&.red .damage-value {
color: #ff4d4f;
.unit {
color: rgba(255, 255, 255, 0.7);
}
}
}
}
}
.event-section {
text-align: center;
padding: vw(12);
2026-03-27 17:47:09 +08:00
// background: rgba(64, 169, 255, 0.1);
// border-radius: 6px;
background-image: url('../../assets/RiskWarning_img/编组5@2x.png');
2026-03-27 17:47:09 +08:00
background-size: 100% 100%;
background-position: left;
.event-title {
2026-04-03 18:08:42 +08:00
font-size: vw(14);
2026-03-27 17:47:09 +08:00
color: rgba(255, 255, 255, 0.9);
}
.event-num {
font-size: vw(18);
2026-03-27 17:47:09 +08:00
font-weight: bold;
color: #ff4d4f;
}
}
}
.header-filters {
display: flex;
align-items: center;
gap: vw(6);
font-size: vw(10);
2026-03-27 17:47:09 +08:00
.filter-item {
2026-04-02 16:35:45 +08:00
color: #fff;
padding: vw(8) vw(8);
background: #183c67;
box-shadow: inset 0px 0px 8px 0px #4fecff;
2026-03-27 17:47:09 +08:00
cursor: pointer;
}
.filter-separator {
color: rgba(255, 255, 255, 0.4);
}
}
.date-range-wrapper {
:deep(.el-date-editor) {
2026-04-02 16:35:45 +08:00
border-radius: 0px !important;
height: 3.1em !important;
}
:deep(.el-date-editor) {
width: vw(200);
max-width: vw(200);
2026-03-27 17:47:09 +08:00
background: #183c67;
box-shadow: inset 0px 0px 8px 0px #4fecff;
.el-range-input {
background: transparent;
color: rgba(255, 255, 255, 0.8);
&::placeholder {
color: rgba(255, 255, 255, 0.5);
}
}
.el-range-separator {
color: rgba(255, 255, 255, 0.4);
}
.el-icon {
color: rgba(255, 255, 255, 0.5);
}
// &:hover {
// border-color: rgba(64, 169, 255, 0.5);
// }
}
}
</style>