2026-03-27 17:47:09 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="left-panel">
|
|
|
|
|
|
<!-- 智能研判头部 -->
|
2026-04-02 16:35:45 +08:00
|
|
|
|
<SectionHeader title="智能研判">
|
2026-03-31 18:10:34 +08:00
|
|
|
|
<template #left>
|
|
|
|
|
|
<div class="filter-header">
|
2026-04-02 16:35:45 +08:00
|
|
|
|
<span class="title">智能研判</span>
|
2026-03-31 18:10:34 +08:00
|
|
|
|
<img
|
|
|
|
|
|
class="filter-icon-ai"
|
|
|
|
|
|
src="../../assets/RiskWarning_img/AI1@2x.png"
|
|
|
|
|
|
alt=""
|
|
|
|
|
|
@click="handleAIClick"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</SectionHeader>
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 气象预警 -->
|
|
|
|
|
|
<div class="weather-warning-section">
|
|
|
|
|
|
<div class="section-title">气象预警</div>
|
|
|
|
|
|
<div class="warning-cards">
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-for="(item, index) in weatherWarningData"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
class="warning-card"
|
|
|
|
|
|
:class="item.class"
|
2026-03-30 10:57:32 +08:00
|
|
|
|
@click="handleWarningCardClick(item)"
|
2026-03-27 17:47:09 +08:00
|
|
|
|
>
|
2026-04-20 10:22:34 +08:00
|
|
|
|
<img class="card-icon" src="../../assets/RiskWarning_img/气象预警图标@2x.png" alt="" />
|
2026-03-27 17:47:09 +08:00
|
|
|
|
<div class="card-info">
|
2026-04-02 16:35:45 +08:00
|
|
|
|
<div class="card-num mt_5">{{ item.value }}</div>
|
|
|
|
|
|
<div class="card-label mb_5">{{ item.label }}</div>
|
2026-03-27 17:47:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 影响点概况 -->
|
|
|
|
|
|
<div class="impact-section">
|
|
|
|
|
|
<div class="impact-header">
|
|
|
|
|
|
<div class="impact-title">影响点概况</div>
|
2026-04-21 15:34:43 +08:00
|
|
|
|
<div class="impact-detail clickable" @click="handleImpactDetailClick">一张清单(影响点)</div>
|
2026-03-27 17:47:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="chart-container">
|
|
|
|
|
|
<div class="chart-y-label">数量</div>
|
|
|
|
|
|
<div class="bar-chart f1">
|
2026-04-20 10:22:34 +08:00
|
|
|
|
<div v-for="(item, index) in impactData" :key="index" class="bar-item">
|
|
|
|
|
|
<div class="bar" :style="{ height: getBarHeight(item) + '%' }"></div>
|
2026-04-03 18:08:42 +08:00
|
|
|
|
<div class="bar-value">{{ item.count }}</div>
|
|
|
|
|
|
<div class="bar-label">{{ item.name }}</div>
|
2026-03-27 17:47:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="chart-x-label">类型</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-31 18:10:34 +08:00
|
|
|
|
<!-- 影响公路类型情况 -->
|
|
|
|
|
|
<div class="road-type-section">
|
|
|
|
|
|
<div class="section-title">影响公路类型情况</div>
|
|
|
|
|
|
<div class="road-type-cards">
|
2026-04-20 10:22:34 +08:00
|
|
|
|
<div class="road-card" v-for="(item, index) in roadTypeData" :key="index">
|
2026-04-03 18:08:42 +08:00
|
|
|
|
<span class="card-label">{{ item.extension }}:</span>
|
|
|
|
|
|
<span class="card-value">{{ item.count }}</span>
|
2026-03-31 18:10:34 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
<!-- 区县统计表格 -->
|
|
|
|
|
|
<div class="district-table-section">
|
|
|
|
|
|
<el-table
|
|
|
|
|
|
:data="districtData"
|
2026-04-20 10:22:34 +08:00
|
|
|
|
style="width: 100%; background: transparent; font-size: 12px; height: 150px"
|
2026-03-27 17:47:09 +08:00
|
|
|
|
:header-cell-style="headerCellStyle"
|
|
|
|
|
|
:cell-style="cellStyle"
|
|
|
|
|
|
size="small"
|
2026-03-31 18:10:34 +08:00
|
|
|
|
:height="tableHeight"
|
|
|
|
|
|
:scroll="{ y: true }"
|
2026-03-27 17:47:09 +08:00
|
|
|
|
>
|
2026-03-31 18:10:34 +08:00
|
|
|
|
<el-table-column prop="name" label="区县名称" :min-width="vw(80)" />
|
2026-04-20 10:22:34 +08:00
|
|
|
|
<el-table-column prop="roadSectionCount" label="路段" :min-width="vw(50)" />
|
2026-04-03 18:08:42 +08:00
|
|
|
|
<el-table-column prop="bridgeCount" label="桥梁" :min-width="vw(50)" />
|
|
|
|
|
|
<el-table-column prop="tunnelCount" label="隧道" :min-width="vw(50)" />
|
|
|
|
|
|
<el-table-column prop="slopeCount" label="边坡" :min-width="vw(50)" />
|
|
|
|
|
|
<el-table-column prop="projectCount" label="项目" :min-width="vw(50)" />
|
2026-03-27 17:47:09 +08:00
|
|
|
|
</el-table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 响应调度 -->
|
|
|
|
|
|
<div class="response-section">
|
|
|
|
|
|
<SectionHeader title="响应调度">
|
|
|
|
|
|
<template #right>
|
|
|
|
|
|
<div class="header-filters">
|
2026-04-20 10:22:34 +08:00
|
|
|
|
<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"
|
2026-04-13 11:38:11 +08:00
|
|
|
|
popper-class="custom-date-picker"
|
|
|
|
|
|
:teleported="false"
|
2026-03-27 17:47:09 +08:00
|
|
|
|
:prefix-icon="Calendar"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</SectionHeader>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 6个统计项 -->
|
|
|
|
|
|
<div class="stats-grid">
|
2026-03-30 10:57:32 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-for="(item, index) in responseStats"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
class="stat-item"
|
|
|
|
|
|
:class="{
|
2026-04-22 18:05:54 +08:00
|
|
|
|
clickable: true,
|
2026-03-30 10:57:32 +08:00
|
|
|
|
}"
|
|
|
|
|
|
@click="handleStatClick(item)"
|
|
|
|
|
|
>
|
2026-03-27 17:47:09 +08:00
|
|
|
|
<!-- <div class="stat-icon" :class="item.iconClass"></div> -->
|
|
|
|
|
|
<img class="stat-icon" :src="item.img" alt="" />
|
|
|
|
|
|
<div class="stat-info">
|
|
|
|
|
|
<div class="stat-num">{{ item.value }}</div>
|
|
|
|
|
|
<div class="stat-label">{{ item.label }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 3个调度清单卡片 -->
|
|
|
|
|
|
<div class="dispatch-cards">
|
2026-03-30 10:57:32 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-for="(item, index) in dispatchList"
|
|
|
|
|
|
:key="index"
|
2026-04-03 18:08:42 +08:00
|
|
|
|
class="dispatch-card clickable"
|
2026-03-30 10:57:32 +08:00
|
|
|
|
@click="handleDispatchCardClick(item)"
|
|
|
|
|
|
>
|
2026-03-31 18:10:34 +08:00
|
|
|
|
<div class="card-num">
|
2026-04-20 10:22:34 +08:00
|
|
|
|
{{ item.value }}
|
|
|
|
|
|
<span class="unit">人</span>
|
2026-03-31 18:10:34 +08:00
|
|
|
|
</div>
|
2026-03-27 17:47:09 +08:00
|
|
|
|
<div class="card-label">{{ item.label }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2026-04-20 10:22:34 +08:00
|
|
|
|
import { ref, computed, onMounted, watch, inject } from 'vue';
|
|
|
|
|
|
import { request } from '@/utils/request';
|
|
|
|
|
|
import SectionHeader from './component/sectionHeader.vue';
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 导入图片资源
|
2026-04-20 10:22:34 +08:00
|
|
|
|
import imgCall from '../../assets/RiskWarning_img/回应icon@2x.png';
|
|
|
|
|
|
import imgReply from '../../assets/RiskWarning_img/已回应icon@2x.png';
|
|
|
|
|
|
import imgRate from '../../assets/RiskWarning_img/回应率icon@2x.png';
|
|
|
|
|
|
import imgDistrict from '../../assets/RiskWarning_img/区县icon@2x.png';
|
|
|
|
|
|
import imgHelp from '../../assets/RiskWarning_img/响应图标5@2x.png';
|
|
|
|
|
|
import imgCheck from '../../assets/RiskWarning_img/抽查人数icon@2x.png';
|
2026-04-03 18:08:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 注入兄弟组件通信机制
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const setRefreshLeftData = inject('setRefreshLeftData');
|
2026-04-15 16:40:35 +08:00
|
|
|
|
// 注入日期范围
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const getdateRange = inject('getdateRange', ref([]));
|
2026-04-03 18:08:42 +08:00
|
|
|
|
|
2026-04-15 16:40:35 +08:00
|
|
|
|
// 监听日期范围变化,当获取到数据时重新加载
|
2026-04-03 18:08:42 +08:00
|
|
|
|
watch(
|
2026-04-15 16:40:35 +08:00
|
|
|
|
() => getdateRange.value,
|
2026-04-20 10:22:34 +08:00
|
|
|
|
newVal => {
|
|
|
|
|
|
console.log('left.vue 日期范围变化:', newVal);
|
2026-04-21 15:34:43 +08:00
|
|
|
|
// init();
|
2026-04-03 18:08:42 +08:00
|
|
|
|
},
|
2026-04-20 10:22:34 +08:00
|
|
|
|
{ deep: true }
|
2026-04-03 18:08:42 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
init();
|
2026-04-08 15:34:49 +08:00
|
|
|
|
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 注册刷新函数给父组件
|
|
|
|
|
|
if (setRefreshLeftData) {
|
|
|
|
|
|
setRefreshLeftData(init);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
const init = () => {
|
|
|
|
|
|
roadTypeLoad();
|
|
|
|
|
|
districtLoadLoad();
|
|
|
|
|
|
dispatchLoadLoad();
|
2026-04-13 11:38:11 +08:00
|
|
|
|
scheduleStatisticsByCountyLoad();
|
2026-04-03 18:08:42 +08:00
|
|
|
|
loadData();
|
|
|
|
|
|
loadBarChartData();
|
|
|
|
|
|
};
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
2026-03-30 10:57:32 +08:00
|
|
|
|
const emit = defineEmits([
|
2026-04-20 10:22:34 +08:00
|
|
|
|
'openWarningInfo',
|
|
|
|
|
|
'openImpactPoint',
|
|
|
|
|
|
'openWarningSituation',
|
|
|
|
|
|
'openResponseStatus',
|
|
|
|
|
|
'openDispatchDistrict',
|
|
|
|
|
|
'openImpactDetail',
|
|
|
|
|
|
'showCenterCard',
|
|
|
|
|
|
'warningClick',
|
|
|
|
|
|
'dispatchDateRange',
|
|
|
|
|
|
'openOfflineHelp',
|
2026-04-22 18:05:54 +08:00
|
|
|
|
'openImageInspection',
|
2026-03-30 10:57:32 +08:00
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// 点击统计项
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const handleStatClick = item => {
|
|
|
|
|
|
if (item.label === '叫应总数') {
|
|
|
|
|
|
emit('openWarningInfo');
|
|
|
|
|
|
emit('dispatchDateRange', dateRange.value);
|
|
|
|
|
|
} else if (item.label === '已回应数') {
|
|
|
|
|
|
emit('openResponseStatus');
|
|
|
|
|
|
emit('dispatchDateRange', dateRange.value);
|
|
|
|
|
|
} else if (item.label === '调度区县数') {
|
|
|
|
|
|
emit('openDispatchDistrict');
|
|
|
|
|
|
} else if (item.label === '线下帮扶数') {
|
|
|
|
|
|
emit('openOfflineHelp');
|
2026-04-22 18:05:54 +08:00
|
|
|
|
} else if (item.label === '抽查人次') {
|
|
|
|
|
|
emit('openImageInspection');
|
2026-03-30 10:57:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 点击气象预警卡片
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const handleWarningCardClick = item => {
|
|
|
|
|
|
console.log('item:', item);
|
|
|
|
|
|
emit('openWarningSituation', item);
|
2026-04-16 14:03:39 +08:00
|
|
|
|
// 传递日期范围
|
2026-04-20 10:22:34 +08:00
|
|
|
|
emit('warningClick', item);
|
2026-03-30 10:57:32 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 点击影响点明细
|
|
|
|
|
|
const handleImpactDetailClick = () => {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
emit('openImpactDetail');
|
2026-03-30 10:57:32 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 点击调度清单卡片
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const handleDispatchCardClick = item => {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
if (item.label === dispatchList.value[0].label) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
emit('showCenterCard', {
|
|
|
|
|
|
type: 'second',
|
2026-03-30 10:57:32 +08:00
|
|
|
|
value: item.value,
|
2026-04-13 11:38:11 +08:00
|
|
|
|
data: nationalarr.value,
|
2026-03-30 10:57:32 +08:00
|
|
|
|
});
|
2026-04-03 18:08:42 +08:00
|
|
|
|
} else if (item.label === dispatchList.value[1].label) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
emit('showCenterCard', {
|
|
|
|
|
|
type: 'third',
|
2026-03-30 10:57:32 +08:00
|
|
|
|
value: item.value,
|
2026-04-13 11:38:11 +08:00
|
|
|
|
data: ruralarr.value,
|
2026-03-30 10:57:32 +08:00
|
|
|
|
});
|
2026-04-03 18:08:42 +08:00
|
|
|
|
} else if (item.label === dispatchList.value[2].label) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
emit('showCenterCard', {
|
|
|
|
|
|
type: 'first',
|
2026-03-30 10:57:32 +08:00
|
|
|
|
value: item.value,
|
2026-04-13 11:38:11 +08:00
|
|
|
|
data: projectarr.value,
|
2026-03-30 10:57:32 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
// 气象预警数据
|
2026-04-02 16:35:45 +08:00
|
|
|
|
const weatherWarningData = ref([
|
2026-04-20 10:22:34 +08:00
|
|
|
|
{ label: '红色预警', value: '0', class: 'red' },
|
|
|
|
|
|
{ label: '橙色预警', value: '0', class: 'orange' },
|
|
|
|
|
|
{ label: '黄色预警', value: '0', class: 'yellow' },
|
|
|
|
|
|
{ label: '蓝色预警', value: '0', class: 'blue' },
|
2026-04-02 16:35:45 +08:00
|
|
|
|
]);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 影响点数据
|
2026-04-02 16:35:45 +08:00
|
|
|
|
const impactData = ref([
|
2026-04-20 10:22:34 +08:00
|
|
|
|
{ name: '路段', count: 0 },
|
|
|
|
|
|
{ name: '桥梁', count: 0 },
|
|
|
|
|
|
{ name: '隧道', count: 0 },
|
|
|
|
|
|
{ name: '边坡', count: 0 },
|
|
|
|
|
|
{ name: '项目', count: 0 },
|
2026-04-02 16:35:45 +08:00
|
|
|
|
]);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
2026-04-15 16:40:35 +08:00
|
|
|
|
const dateRange = ref([]);
|
2026-04-13 16:38:07 +08:00
|
|
|
|
// 点击日期范围器
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const handleDateRangeClick = val => {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
dateRange.value = val;
|
2026-04-13 16:38:07 +08:00
|
|
|
|
dispatchLoadLoad();
|
|
|
|
|
|
};
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 调度清单数据
|
|
|
|
|
|
const dispatchLoadLoad = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 处理日期参数,开始时间为当天00:00:00,结束时间为当天23:59:59
|
2026-04-20 10:22:34 +08:00
|
|
|
|
let start = '';
|
|
|
|
|
|
let end = '';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
2026-04-03 18:08:42 +08:00
|
|
|
|
if (dateRange.value && dateRange.value.length === 2) {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
start = formatDateTime(dateRange.value[0]);
|
|
|
|
|
|
end = formatDateTime(dateRange.value[1]);
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const res = await request({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
url: '/snow-ops-platform/weather-warning/schedule-statistics',
|
|
|
|
|
|
method: 'GET',
|
2026-04-03 18:08:42 +08:00
|
|
|
|
params: {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
start: start,
|
|
|
|
|
|
end: end,
|
2026-04-03 18:08:42 +08:00
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log(res);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
if (res.code == '00000') {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const data = res.data;
|
|
|
|
|
|
if (data) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
responseStats.value.forEach(item => {
|
|
|
|
|
|
if (item.label == '叫应总数') {
|
|
|
|
|
|
item.value = data['noticeCount'] || 0;
|
|
|
|
|
|
} else if (item.label == '已回应数') {
|
|
|
|
|
|
item.value = data['replyCount'] || 0;
|
|
|
|
|
|
} else if (item.label == '回应率') {
|
|
|
|
|
|
item.value = data['replyPrecent'] >= 0 ? data['replyPrecent'] + '%' : 0;
|
|
|
|
|
|
} else if (item.label == '调度区县数') {
|
|
|
|
|
|
item.value = data['countyCount'] || 0;
|
|
|
|
|
|
} else if (item.label == '线下帮扶数') {
|
|
|
|
|
|
item.value = data['supportCount'] || 0;
|
|
|
|
|
|
} else if (item.label == '抽查人次') {
|
|
|
|
|
|
item.value = data['inspectionCount'] || 0;
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-04-20 10:22:34 +08:00
|
|
|
|
dispatchList.value.forEach(item => {
|
|
|
|
|
|
if (item.label == '国省道调度') {
|
|
|
|
|
|
item.value = data['nationalRoadCount'] || 0;
|
|
|
|
|
|
} else if (item.label == '农村公路调度') {
|
|
|
|
|
|
item.value = data['ruralRoadCount'] || 0;
|
|
|
|
|
|
} else if (item.label == '建设工程调度') {
|
|
|
|
|
|
item.value = data['projectCount'] || 0;
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// responseStats.value = data;
|
|
|
|
|
|
// dispatchList.value = data;
|
2026-04-15 16:40:35 +08:00
|
|
|
|
} else {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
responseStats.value.forEach(item => {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
item.value = 0;
|
|
|
|
|
|
});
|
2026-04-20 10:22:34 +08:00
|
|
|
|
dispatchList.value.forEach(item => {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
item.value = 0;
|
|
|
|
|
|
});
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.error('加载数据失败:', error);
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
2026-04-20 10:22:34 +08:00
|
|
|
|
watch(
|
|
|
|
|
|
() => dateRange.value,
|
|
|
|
|
|
newVal => {
|
|
|
|
|
|
console.log('left.vue 调度响应变化:', newVal);
|
|
|
|
|
|
dispatchLoadLoad();
|
|
|
|
|
|
},
|
|
|
|
|
|
{ deep: true }
|
|
|
|
|
|
);
|
2026-04-15 16:40:35 +08:00
|
|
|
|
// 格式化日期时间为接口所需格式
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const formatDateTime = date => {
|
|
|
|
|
|
if (!date) return '';
|
2026-04-15 16:40:35 +08:00
|
|
|
|
const d = new Date(date);
|
|
|
|
|
|
const year = d.getFullYear();
|
2026-04-20 10:22:34 +08:00
|
|
|
|
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');
|
2026-04-15 16:40:35 +08:00
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
const getdateRangeTime = () => {
|
|
|
|
|
|
// 处理日期参数,开始时间为当天00:00:00,结束时间为当天23:59:59
|
2026-04-20 10:22:34 +08:00
|
|
|
|
let start = '';
|
|
|
|
|
|
let end = '';
|
2026-04-15 16:40:35 +08:00
|
|
|
|
if (getdateRange.value && getdateRange.value.length === 2) {
|
|
|
|
|
|
start = formatDateTime(getdateRange.value[0]);
|
|
|
|
|
|
end = formatDateTime(getdateRange.value[1]);
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
start: start,
|
|
|
|
|
|
end: end,
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 区县数据
|
|
|
|
|
|
const districtLoadLoad = async () => {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.log('区县数据:', getdateRangeTime());
|
2026-04-03 18:08:42 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const res = await request({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
url: '/snow-ops-platform/weather-warning/affected-count/_by_county',
|
|
|
|
|
|
method: 'GET',
|
2026-04-15 16:40:35 +08:00
|
|
|
|
params: getdateRangeTime(),
|
2026-04-03 18:08:42 +08:00
|
|
|
|
});
|
|
|
|
|
|
console.log(res);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
if (res.code == '00000') {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const data = res.data;
|
|
|
|
|
|
if (data) {
|
2026-04-17 17:23:51 +08:00
|
|
|
|
// 简化区县名称
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const simplifyDistrictName = name => {
|
2026-04-17 17:23:51 +08:00
|
|
|
|
if (!name) return name;
|
|
|
|
|
|
return name
|
2026-04-20 10:22:34 +08:00
|
|
|
|
.replace('彭水苗族土家族自治县', '彭水县')
|
|
|
|
|
|
.replace('石柱土家族自治县', '石柱县')
|
|
|
|
|
|
.replace('秀山土家族苗族自治县', '秀山县')
|
|
|
|
|
|
.replace('酉阳土家族苗族自治县', '酉阳县');
|
2026-04-17 17:23:51 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 处理数据,简化区县名称
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const processedData = data.map(item => ({
|
2026-04-17 17:23:51 +08:00
|
|
|
|
...item,
|
|
|
|
|
|
name: simplifyDistrictName(item.name),
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
2026-04-08 15:34:49 +08:00
|
|
|
|
// 根据路段、桥梁、隧道、边坡、项目的总数进行排序(数值越大越靠前)
|
2026-04-17 17:23:51 +08:00
|
|
|
|
const sortedData = processedData.sort((a, b) => {
|
2026-04-08 15:34:49 +08:00
|
|
|
|
const totalA =
|
|
|
|
|
|
(a.roadSectionCount || 0) +
|
|
|
|
|
|
(a.bridgeCount || 0) +
|
|
|
|
|
|
(a.tunnelCount || 0) +
|
|
|
|
|
|
(a.slopeCount || 0) +
|
|
|
|
|
|
(a.projectCount || 0);
|
|
|
|
|
|
const totalB =
|
|
|
|
|
|
(b.roadSectionCount || 0) +
|
|
|
|
|
|
(b.bridgeCount || 0) +
|
|
|
|
|
|
(b.tunnelCount || 0) +
|
|
|
|
|
|
(b.slopeCount || 0) +
|
|
|
|
|
|
(b.projectCount || 0);
|
|
|
|
|
|
return totalB - totalA; // 降序排列,数值大的在前
|
|
|
|
|
|
});
|
|
|
|
|
|
districtData.value = sortedData;
|
2026-04-15 16:40:35 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
districtData.value = [];
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.error('加载数据失败:', error);
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
const roadTypeData = ref([]);
|
2026-04-13 11:38:11 +08:00
|
|
|
|
|
|
|
|
|
|
// 调度统计区县数据
|
|
|
|
|
|
const projectarr = ref([]);
|
|
|
|
|
|
const nationalarr = ref([]);
|
|
|
|
|
|
const ruralarr = ref([]);
|
|
|
|
|
|
const scheduleStatisticsByCountyLoad = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await request({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
url: '/snow-ops-platform/weather-warning/schedule-statistics/_by_county',
|
|
|
|
|
|
method: 'GET',
|
2026-04-15 16:40:35 +08:00
|
|
|
|
params: getdateRangeTime(),
|
2026-04-13 11:38:11 +08:00
|
|
|
|
});
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.log('调度统计区县数据:', res);
|
|
|
|
|
|
if (res.code == '00000') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
const data = res.data;
|
|
|
|
|
|
if (data) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
data.forEach(item => {
|
|
|
|
|
|
if (item.countyName != '测试区县') {
|
|
|
|
|
|
if (item.type == 'project') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
projectarr.value.push(item);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
} else if (item.roadType == 'national') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
nationalarr.value.push(item);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
} else if (item.roadType == 'rural') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
ruralarr.value.push(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log(projectarr.value);
|
|
|
|
|
|
console.log(nationalarr.value);
|
|
|
|
|
|
console.log(ruralarr.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 合并渝北区和江北区为两江新区
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const mergeLiangjiangNewArea = arr => {
|
|
|
|
|
|
const yubeiItems = arr.filter(item => item.countyName === '渝北区');
|
|
|
|
|
|
const jiangbeiItems = arr.filter(item => item.countyName === '江北区');
|
2026-04-13 11:38:11 +08:00
|
|
|
|
|
|
|
|
|
|
if (yubeiItems.length > 0 || jiangbeiItems.length > 0) {
|
|
|
|
|
|
// 计算合并后的数据
|
|
|
|
|
|
const mergedItem = {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
countyName: '两江新区',
|
|
|
|
|
|
countyId: yubeiItems[0]?.countyId || jiangbeiItems[0]?.countyId || '',
|
|
|
|
|
|
type: yubeiItems[0]?.type || jiangbeiItems[0]?.type || '',
|
|
|
|
|
|
roadType: yubeiItems[0]?.roadType || jiangbeiItems[0]?.roadType || '',
|
2026-04-13 11:38:11 +08:00
|
|
|
|
// 数值字段累加
|
|
|
|
|
|
noticeCount: 0,
|
|
|
|
|
|
replyCount: 0,
|
|
|
|
|
|
population: 0,
|
|
|
|
|
|
entityCount: 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 累加渝北区数据
|
2026-04-20 10:22:34 +08:00
|
|
|
|
yubeiItems.forEach(item => {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
mergedItem.noticeCount += item.noticeCount || 0;
|
|
|
|
|
|
mergedItem.replyCount += item.replyCount || 0;
|
|
|
|
|
|
mergedItem.population += item.population || 0;
|
|
|
|
|
|
mergedItem.entityCount += item.entityCount || 0;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 累加江北区数据
|
2026-04-20 10:22:34 +08:00
|
|
|
|
jiangbeiItems.forEach(item => {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
mergedItem.noticeCount += item.noticeCount || 0;
|
|
|
|
|
|
mergedItem.replyCount += item.replyCount || 0;
|
|
|
|
|
|
mergedItem.population += item.population || 0;
|
|
|
|
|
|
mergedItem.entityCount += item.entityCount || 0;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 移除渝北区和江北区的数据,添加合并后的两江新区数据
|
2026-04-13 16:38:07 +08:00
|
|
|
|
const filteredArr = arr.filter(
|
2026-04-20 10:22:34 +08:00
|
|
|
|
item => item.countyName !== '渝北区' && item.countyName !== '江北区'
|
2026-04-13 11:38:11 +08:00
|
|
|
|
);
|
|
|
|
|
|
filteredArr.push(mergedItem);
|
|
|
|
|
|
return filteredArr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return arr;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 对三个数组分别进行合并处理
|
|
|
|
|
|
projectarr.value = mergeLiangjiangNewArea(projectarr.value);
|
|
|
|
|
|
nationalarr.value = mergeLiangjiangNewArea(nationalarr.value);
|
|
|
|
|
|
ruralarr.value = mergeLiangjiangNewArea(ruralarr.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤出前15个项目、10个全国、5个农村
|
2026-04-15 16:40:35 +08:00
|
|
|
|
// projectarr.value = projectarr.value.filter((item, index) => index < 15);
|
|
|
|
|
|
// nationalarr.value = nationalarr.value.filter(
|
|
|
|
|
|
// (item, index) => index < 10,
|
|
|
|
|
|
// );
|
|
|
|
|
|
// ruralarr.value = ruralarr.value.filter((item, index) => index < 5);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
projectarr.value = [];
|
|
|
|
|
|
nationalarr.value = [];
|
|
|
|
|
|
ruralarr.value = [];
|
2026-04-13 11:38:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.error('加载调度统计区县数据失败:', error);
|
2026-04-13 11:38:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 公路类型数据
|
|
|
|
|
|
const roadTypeLoad = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await request({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
url: '/snow-ops-platform/weather-warning/affected-count/_by_road',
|
|
|
|
|
|
method: 'GET',
|
2026-04-15 16:40:35 +08:00
|
|
|
|
params: getdateRangeTime(),
|
2026-04-03 18:08:42 +08:00
|
|
|
|
});
|
|
|
|
|
|
console.log(res);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
if (res.code == '00000') {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const data = res.data;
|
|
|
|
|
|
if (data) {
|
|
|
|
|
|
roadTypeData.value = data.reverse();
|
2026-04-15 16:40:35 +08:00
|
|
|
|
} else {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
roadTypeData.value.forEach(item => {
|
2026-04-15 16:40:35 +08:00
|
|
|
|
item.count = 0;
|
|
|
|
|
|
});
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.error('加载数据失败:', error);
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
2026-04-02 16:35:45 +08:00
|
|
|
|
// 加载气象预警和影响点数据
|
|
|
|
|
|
const loadData = async () => {
|
|
|
|
|
|
try {
|
2026-04-02 17:27:59 +08:00
|
|
|
|
const res = await request({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
url: '/snow-ops-platform/weather-warning/warning-count',
|
|
|
|
|
|
method: 'GET',
|
2026-04-15 16:40:35 +08:00
|
|
|
|
params: getdateRangeTime(),
|
2026-04-02 17:27:59 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-20 10:22:34 +08:00
|
|
|
|
if (res.code == '00000') {
|
2026-04-02 17:27:59 +08:00
|
|
|
|
const data = res.data;
|
|
|
|
|
|
if (data) {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
let obj = {};
|
2026-04-20 10:22:34 +08:00
|
|
|
|
data.forEach(item => {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
obj[item.name] = item.count || 0;
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log(obj);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
weatherWarningData.value.forEach(item => {
|
|
|
|
|
|
if (item.label == '红色预警') {
|
|
|
|
|
|
item.value = obj['warning-red-count'] + '/' + obj['warning-red-total'] || '0/0';
|
|
|
|
|
|
} else if (item.label == '橙色预警') {
|
|
|
|
|
|
item.value = obj['warning-orange-count'] + '/' + obj['warning-orange-total'] || '0/0';
|
|
|
|
|
|
} else if (item.label == '黄色预警') {
|
|
|
|
|
|
item.value = obj['warning-yellow-count'] + '/' + obj['warning-yellow-total'] || '0/0';
|
|
|
|
|
|
} else if (item.label == '蓝色预警') {
|
|
|
|
|
|
item.value = obj['warning-blue-count'] + '/' + obj['warning-blue-total'] || '0/0';
|
2026-04-02 17:27:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-04-15 16:40:35 +08:00
|
|
|
|
} else {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
weatherWarningData.value.forEach(item => {
|
|
|
|
|
|
if (item.label == '红色预警') {
|
|
|
|
|
|
item.value = '0/0';
|
|
|
|
|
|
} else if (item.label == '橙色预警') {
|
|
|
|
|
|
item.value = '0/0';
|
|
|
|
|
|
} else if (item.label == '黄色预警') {
|
|
|
|
|
|
item.value = '0/0';
|
|
|
|
|
|
} else if (item.label == '蓝色预警') {
|
|
|
|
|
|
item.value = '0/0';
|
2026-04-15 16:40:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-04-02 16:35:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.error('加载数据失败:', error);
|
2026-04-02 16:35:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 加载柱状图数据
|
|
|
|
|
|
const loadBarChartData = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await request({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
url: '/snow-ops-platform/weather-warning/affected-count',
|
|
|
|
|
|
method: 'GET',
|
2026-04-15 16:40:35 +08:00
|
|
|
|
params: getdateRangeTime(),
|
2026-04-03 18:08:42 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-20 10:22:34 +08:00
|
|
|
|
if (res.code == '00000') {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const data = res.data;
|
2026-04-15 16:40:35 +08:00
|
|
|
|
if (data.length > 0) {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 英文转中文映射
|
|
|
|
|
|
const nameMap = {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
'road-section': '路段',
|
|
|
|
|
|
bridge: '桥梁',
|
|
|
|
|
|
tunnel: '隧道',
|
|
|
|
|
|
slope: '边坡',
|
|
|
|
|
|
project: '项目',
|
|
|
|
|
|
Road: '路段',
|
|
|
|
|
|
Bridge: '桥梁',
|
|
|
|
|
|
Tunnel: '隧道',
|
|
|
|
|
|
Slope: '边坡',
|
|
|
|
|
|
Project: '项目',
|
2026-04-03 18:08:42 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 转换英文name为中文
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const convertedData = data.map(item => {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const name = nameMap[item.name] || item.name;
|
|
|
|
|
|
return { ...item, name };
|
|
|
|
|
|
});
|
2026-04-20 10:22:34 +08:00
|
|
|
|
convertedData.forEach(item => {
|
|
|
|
|
|
if (item.name == '路段') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
impactData.value[0].count = item.count || 0;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
} else if (item.name == '桥梁') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
impactData.value[1].count = item.count || 0;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
} else if (item.name == '隧道') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
impactData.value[2].count = item.count || 0;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
} else if (item.name == '边坡') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
impactData.value[3].count = item.count || 0;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
} else if (item.name == '项目') {
|
2026-04-13 11:38:11 +08:00
|
|
|
|
impactData.value[4].count = item.count || 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-04-15 16:40:35 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 影响点数据
|
|
|
|
|
|
|
|
|
|
|
|
impactData.value = JSON.parse(
|
|
|
|
|
|
JSON.stringify([
|
2026-04-20 10:22:34 +08:00
|
|
|
|
{ name: '路段', count: 0 },
|
|
|
|
|
|
{ name: '桥梁', count: 0 },
|
|
|
|
|
|
{ name: '隧道', count: 0 },
|
|
|
|
|
|
{ name: '边坡', count: 0 },
|
|
|
|
|
|
{ name: '项目', count: 0 },
|
|
|
|
|
|
])
|
2026-04-15 16:40:35 +08:00
|
|
|
|
);
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
console.error('加载柱状图数据失败:', error);
|
2026-04-03 18:08:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
// 计算最大值用于动态计算高度
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 计算所有影响点的总和
|
|
|
|
|
|
const totalValue = computed(() => {
|
|
|
|
|
|
let total = 0;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
impactData.value.forEach(item => {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
total += item.count || 0;
|
|
|
|
|
|
});
|
|
|
|
|
|
return total;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
});
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 计算每个柱子的高度百分比
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const getBarHeight = value => {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const actualValue = value.count || value.value;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
if (!actualValue || actualValue == 0) return '0';
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// 确保最小高度为10%,最大高度为100%
|
|
|
|
|
|
const height = (actualValue / totalValue.value) * 200;
|
2026-04-23 17:54:16 +08:00
|
|
|
|
// 确保高度差异明显,至少有3%的最小差异
|
|
|
|
|
|
// 最大高度为100% 最新高度为3%的最小差异
|
|
|
|
|
|
return Math.min(100, Math.max(3, Math.round(height)));
|
2026-03-27 17:47:09 +08:00
|
|
|
|
};
|
2026-03-31 18:10:34 +08:00
|
|
|
|
const handleAIClick = () => {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
emit('openAIResult');
|
2026-03-31 18:10:34 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 响应式单位转换函数(基于1920px设计稿)
|
2026-04-20 10:22:34 +08:00
|
|
|
|
const vw = px => {
|
2026-03-31 18:10:34 +08:00
|
|
|
|
return Math.round((px / 1920) * window.innerWidth);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 表格高度计算
|
|
|
|
|
|
const tableHeight = computed(() => {
|
|
|
|
|
|
return vw(100);
|
|
|
|
|
|
});
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 区县数据
|
2026-04-08 15:34:49 +08:00
|
|
|
|
const districtData = ref([]);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 响应调度统计数据
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const responseStats = ref([
|
2026-03-27 17:47:09 +08:00
|
|
|
|
{
|
2026-04-20 10:22:34 +08:00
|
|
|
|
label: '叫应总数',
|
|
|
|
|
|
value: '15',
|
|
|
|
|
|
iconClass: 'icon-call',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
img: imgCall,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-20 10:22:34 +08:00
|
|
|
|
label: '已回应数',
|
|
|
|
|
|
value: '9',
|
|
|
|
|
|
iconClass: 'icon-reply',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
img: imgReply,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-20 10:22:34 +08:00
|
|
|
|
label: '回应率',
|
|
|
|
|
|
value: '100%',
|
|
|
|
|
|
iconClass: 'icon-rate',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
img: imgRate,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-20 10:22:34 +08:00
|
|
|
|
label: '调度区县数',
|
|
|
|
|
|
value: '21',
|
|
|
|
|
|
iconClass: 'icon-district',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
img: imgDistrict,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-20 10:22:34 +08:00
|
|
|
|
label: '线下帮扶数',
|
|
|
|
|
|
value: '12',
|
|
|
|
|
|
iconClass: 'icon-help',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
img: imgHelp,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-04-20 10:22:34 +08:00
|
|
|
|
label: '抽查人次',
|
|
|
|
|
|
value: '23',
|
|
|
|
|
|
iconClass: 'icon-check',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
img: imgCheck,
|
|
|
|
|
|
},
|
2026-04-03 18:08:42 +08:00
|
|
|
|
]);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 调度清单数据
|
2026-04-03 18:08:42 +08:00
|
|
|
|
const dispatchList = ref([
|
2026-04-20 10:22:34 +08:00
|
|
|
|
{ label: '国省道调度', value: '341' },
|
|
|
|
|
|
{ label: '农村公路调度', value: '210' },
|
|
|
|
|
|
{ label: '建设工程调度', value: '120' },
|
2026-04-03 18:08:42 +08:00
|
|
|
|
]);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
const headerCellStyle = () => ({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
background: 'rgba(64, 169, 255, 0.1)',
|
|
|
|
|
|
color: 'rgba(255, 255, 255, 0.9)',
|
|
|
|
|
|
fontWeight: 'normal',
|
|
|
|
|
|
borderBottom: '1px solid rgba(64, 169, 255, 0.2)',
|
|
|
|
|
|
padding: ' 2px',
|
|
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
lineHeight: '1.2',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const cellStyle = () => ({
|
2026-04-20 10:22:34 +08:00
|
|
|
|
background: 'transparent',
|
|
|
|
|
|
color: 'rgba(255, 255, 255, 0.8)',
|
|
|
|
|
|
borderBottom: '1px solid rgba(64, 169, 255, 0.1)',
|
|
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
padding: ' 2px',
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
lineHeight: '1.2',
|
2026-03-27 17:47:09 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2026-03-31 18:10:34 +08:00
|
|
|
|
.filter-header {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
margin-left: 2.667vw;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-weight: bold;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
.title {
|
|
|
|
|
|
font-size: 1vw;
|
|
|
|
|
|
}
|
2026-03-31 18:10:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
.filter-icon-ai {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
width: 1.5em;
|
|
|
|
|
|
height: 1.5em;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
margin-left: 10px;
|
|
|
|
|
|
}
|
2026-03-30 10:57:32 +08:00
|
|
|
|
// 视频屏幕自适应 - 基于视口宽度动态调整
|
|
|
|
|
|
// 基准宽度 1920px,使用 vw 单位实现自适应
|
|
|
|
|
|
@function vw($px) {
|
|
|
|
|
|
@return calc($px / 1920 * 100vw);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
.left-panel {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-30 10:57:32 +08:00
|
|
|
|
// 小屏幕适配
|
|
|
|
|
|
@media (max-width: 1366px) {
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 1024px) {
|
|
|
|
|
|
padding: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
.section-header {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
height: vw(50);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(20);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
background-image: url('../../assets/RiskWarning_img/标题bg@2x.png');
|
2026-03-27 17:47:09 +08:00
|
|
|
|
background-size: cover;
|
|
|
|
|
|
background-position: left;
|
|
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
gap: vw(8);
|
|
|
|
|
|
margin-left: vw(35);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
|
|
|
|
.icon-back {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
width: vw(20);
|
|
|
|
|
|
height: vw(20);
|
|
|
|
|
|
min-width: 16px;
|
|
|
|
|
|
min-height: 16px;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
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 {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '←';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-date {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(11);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: rgba(255, 255, 255, 0.6);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 气象预警
|
|
|
|
|
|
.weather-warning-section {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(20);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.section-title {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(16);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(12);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.warning-cards {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
|
display: flex;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
gap: vw(5);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.warning-card {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
// padding: 12px;
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.1);
|
|
|
|
|
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
|
|
|
|
|
|
|
|
|
|
.card-icon {
|
|
|
|
|
|
width: 100%;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
max-width: vw(35);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
height: auto;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(24);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
// &::before {
|
|
|
|
|
|
// content: "⛈️";
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.card-info {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
.card-num {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
font-size: vw(18);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.card-label {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
font-size: vw(16);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: rgba(255, 255, 255, 0.7);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.red .card-num {
|
|
|
|
|
|
color: #ff4d4f;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.orange .card-num {
|
|
|
|
|
|
color: #ff7a45;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.yellow .card-num {
|
|
|
|
|
|
color: #ffc53d;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.blue .card-num {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
color: #379afd;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 影响点概况
|
|
|
|
|
|
.impact-section {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(40);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.impact-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(20);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.impact-title {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(16);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.impact-detail {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(14);
|
2026-04-02 16:35:45 +08:00
|
|
|
|
color: #18f2f9;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
cursor: pointer;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
|
|
|
|
|
|
&.clickable {
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
color: #69c0ff;
|
|
|
|
|
|
text-shadow: 0 0 8px rgba(105, 192, 255, 0.6);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart-container {
|
|
|
|
|
|
position: relative;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
height: vw(100);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
// padding: 10px 0 30px 40px;
|
|
|
|
|
|
|
|
|
|
|
|
.chart-y-label {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 0;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
top: vw(-10);
|
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.6);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar-chart {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-around;
|
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border-bottom: 1px solid rgba(64, 169, 255, 0.3);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
// 背景网格线
|
|
|
|
|
|
&::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
background-image:
|
|
|
|
|
|
linear-gradient(to right, transparent 0%, transparent 100%),
|
2026-04-20 10:22:34 +08:00
|
|
|
|
linear-gradient(to bottom, rgba(64, 169, 255, 0.1) 1px, transparent 1px);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
background-size: 100% 25%;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar-item {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column-reverse;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s ease;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
padding: vw(5) 0;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.15);
|
|
|
|
|
|
|
|
|
|
|
|
.bar-value {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
color: #18f2f9;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
background: linear-gradient(180deg, #69c0ff 0%, rgba(105, 192, 255, 0.5) 100%);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
box-shadow: 0 0 15px rgba(64, 169, 255, 0.6);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar-label {
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar-value {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
font-size: vw(14);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(5);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
width: vw(30);
|
|
|
|
|
|
min-width: 16px;
|
2026-04-20 10:22:34 +08:00
|
|
|
|
background: linear-gradient(180deg, #18f2f9 0%, rgba(64, 169, 255, 0.3) 100%);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
border-radius: 2px 2px 0 0;
|
2026-04-03 18:08:42 +08:00
|
|
|
|
// min-height: 20px;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bar-label {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
bottom: vw(-20);
|
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);
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart-x-label {
|
|
|
|
|
|
position: absolute;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
right: vw(-15);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
bottom: 0;
|
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.6);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-31 18:10:34 +08:00
|
|
|
|
// 影响公路类型情况
|
|
|
|
|
|
.road-type-section {
|
|
|
|
|
|
margin-bottom: vw(20);
|
|
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
|
font-size: vw(16);
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
|
margin-bottom: vw(12);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.road-type-cards {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
|
gap: vw(10);
|
|
|
|
|
|
|
|
|
|
|
|
.road-card {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: vw(12) vw(16);
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.1);
|
2026-04-02 16:35:45 +08:00
|
|
|
|
border: 1px solid #1d4c60;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
box-shadow: inset 0px 0px 8px 0px rgba(55, 155, 255, 0.2);
|
|
|
|
|
|
|
|
|
|
|
|
.card-label {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
font-size: vw(18);
|
2026-03-31 18:10:34 +08:00
|
|
|
|
color: rgba(255, 255, 255, 0.7);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.card-value {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
font-size: vw(22);
|
2026-03-31 18:10:34 +08:00
|
|
|
|
font-weight: bold;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
color: #18f2f9;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
text-shadow: 0 0 10px rgba(64, 169, 255, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
// 区县统计表格
|
|
|
|
|
|
.district-table-section {
|
2026-04-08 15:34:49 +08:00
|
|
|
|
height: vw(150);
|
2026-03-31 18:10:34 +08:00
|
|
|
|
overflow: hidden;
|
2026-04-08 15:34:49 +08:00
|
|
|
|
:deep(.el-table__empty-block) {
|
|
|
|
|
|
max-height: 40px !important;
|
|
|
|
|
|
.el-table__empty-text {
|
|
|
|
|
|
line-height: 30px !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
:deep(.el-table__empty-block) {
|
|
|
|
|
|
min-height: 40px !important;
|
|
|
|
|
|
}
|
2026-04-02 16:35:45 +08:00
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
:deep(.el-table) {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
|
|
|
|
|
|
&::before {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-table__inner-wrapper {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.el-table__inner-wrapper:before {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-table__header-wrapper {
|
|
|
|
|
|
background: transparent;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
position: sticky;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
z-index: 1;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-table__body-wrapper {
|
|
|
|
|
|
background: transparent;
|
2026-03-31 18:10:34 +08:00
|
|
|
|
overflow-y: auto;
|
2026-04-08 15:34:49 +08:00
|
|
|
|
max-height: calc(#{vw(150)} - #{vw(0)}); /* 减去表头高度 */
|
2026-03-31 18:10:34 +08:00
|
|
|
|
scrollbar-width: none;
|
|
|
|
|
|
-ms-overflow-style: none;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
|
2026-03-31 18:10:34 +08:00
|
|
|
|
&::-webkit-scrollbar {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
tr {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.05) !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
th.el-table__cell {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
td.el-table__cell {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 响应调度
|
|
|
|
|
|
.response-section {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
padding: vw(15);
|
|
|
|
|
|
margin-top: vw(20);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.section-header {
|
2026-04-02 16:35:45 +08:00
|
|
|
|
height: vw(50);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
margin-bottom: vw(15);
|
2026-04-20 10:22:34 +08:00
|
|
|
|
background-image: url('../../assets/RiskWarning_img/标题bg@2x.png') no-repeat;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
background-size: cover;
|
|
|
|
|
|
background-position: left;
|
|
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
gap: vw(8);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.icon-back {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
width: vw(20);
|
|
|
|
|
|
height: vw(20);
|
|
|
|
|
|
min-width: 16px;
|
|
|
|
|
|
min-height: 16px;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
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 {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '←';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: #fff;
|
2026-04-03 18:08:42 +08:00
|
|
|
|
font-size: vw(14);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-filters {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 6个统计项网格
|
|
|
|
|
|
.stats-grid {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(3, 1fr);
|
2026-04-02 16:35:45 +08:00
|
|
|
|
// gap: vw(10);
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.1);
|
|
|
|
|
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
|
|
|
|
|
|
|
|
|
|
margin-bottom: vw(10);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.stat-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
// gap: vw(8);
|
2026-04-14 09:55:12 +08:00
|
|
|
|
padding: vw(12) vw(10);
|
2026-04-02 16:35:45 +08:00
|
|
|
|
// background: rgba(64, 169, 255, 0.08);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.stat-icon {
|
|
|
|
|
|
width: 100%;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
max-width: vw(40);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
height: auto;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(18);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
&.icon-call::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '💬';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
&.icon-reply::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '✉️';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
&.icon-rate::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '⏱️';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
&.icon-district::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '📍';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
&.icon-help::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '🤝';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
&.icon-check::before {
|
2026-04-20 10:22:34 +08:00
|
|
|
|
content: '👥';
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.stat-info {
|
|
|
|
|
|
.stat-num {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(24);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
font-weight: bold;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
color: #18f2f9;
|
2026-03-27 17:47:09 +08:00
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.stat-label {
|
2026-04-03 18:08:42 +08:00
|
|
|
|
font-size: vw(14);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 10:57:32 +08:00
|
|
|
|
|
|
|
|
|
|
&.clickable {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.2);
|
2026-04-02 16:35:45 +08:00
|
|
|
|
// transform: translateY(-2px);
|
2026-03-30 10:57:32 +08:00
|
|
|
|
|
|
|
|
|
|
.stat-num {
|
|
|
|
|
|
color: #69c0ff;
|
|
|
|
|
|
text-shadow: 0 0 10px rgba(105, 192, 255, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-27 17:47:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3个调度清单卡片
|
|
|
|
|
|
.dispatch-cards {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(3, 1fr);
|
2026-03-30 10:57:32 +08:00
|
|
|
|
gap: vw(10);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
|
|
|
|
|
|
.dispatch-card {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
padding: vw(12);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
background: rgba(64, 169, 255, 0.1);
|
|
|
|
|
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
2026-03-30 10:57:32 +08:00
|
|
|
|
&.clickable {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: rgba(64, 169, 255, 0.2);
|
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
|
|
|
|
|
|
|
.card-num {
|
|
|
|
|
|
color: #69c0ff;
|
|
|
|
|
|
text-shadow: 0 0 10px rgba(105, 192, 255, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 17:47:09 +08:00
|
|
|
|
.card-num {
|
2026-03-30 10:57:32 +08:00
|
|
|
|
font-size: vw(20);
|
2026-03-27 17:47:09 +08:00
|
|
|
|
font-weight: bold;
|
2026-04-02 16:35:45 +08:00
|
|
|
|
color: #18f2f9;
|
2026-03-30 10:57:32 +08:00
|
|
|
|
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
|
|
|
|
color: rgba(255, 255, 255, 0.7);
|
|
|
|
|
|
font-weight: normal;
|
|
|
|
|
|
margin-left: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.card-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.8);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.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: 200px;
|
|
|
|
|
|
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>
|