大屏左侧数据完成调试
This commit is contained in:
parent
af40f7f464
commit
e01863a8cd
BIN
packages/screen/src/assets/RiskWarning_img/AI背景@2x.png
Normal file
BIN
packages/screen/src/assets/RiskWarning_img/AI背景@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 800 KiB |
BIN
packages/screen/src/assets/RiskWarning_img/标题@2x.png
Normal file
BIN
packages/screen/src/assets/RiskWarning_img/标题@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
packages/screen/src/assets/RiskWarning_img/矩形@2x.png
Normal file
BIN
packages/screen/src/assets/RiskWarning_img/矩形@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
packages/screen/src/assets/RiskWarning_img/路径 62@2x.png
Normal file
BIN
packages/screen/src/assets/RiskWarning_img/路径 62@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,340 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="AI预警处理结果"
|
||||||
|
:table-data="[]"
|
||||||
|
:table-columns="[]"
|
||||||
|
:table-height="0"
|
||||||
|
:total="0"
|
||||||
|
:current-page="1"
|
||||||
|
:page-size="10"
|
||||||
|
:z-index="2200"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<!-- AI处理前预警 -->
|
||||||
|
<div class="panel">
|
||||||
|
<div class="center">
|
||||||
|
<div class="panel-title" style="color: #18EFF7">AI处理前预警</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-content">
|
||||||
|
<div class="info-container">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">发布单位:</span>
|
||||||
|
<span class="info-value">{{ beforeData.publishOrg }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">发布内容:</span>
|
||||||
|
<span class="info-value">{{ beforeData.publishContent }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">生效时间:</span>
|
||||||
|
<span class="info-value">{{ beforeData.effectiveTime }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">失效时间:</span>
|
||||||
|
<span class="info-value">{{ beforeData.expireTime }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 中间AI标识 -->
|
||||||
|
<div class="ai-center">
|
||||||
|
<img
|
||||||
|
class="ai-icon-img"
|
||||||
|
src="../../../assets/RiskWarning_img/AI1@2x.png"
|
||||||
|
alt="AI"
|
||||||
|
/>
|
||||||
|
<div class="ai-arrow">
|
||||||
|
<el-icon color="#4FECFF"><DArrowRight /></el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- AI处理后预警 -->
|
||||||
|
<div class="panel after-panel panel1">
|
||||||
|
<div class="center">
|
||||||
|
<div class="panel-title" style="color: #18EFF7">AI处理后预警</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-content">
|
||||||
|
<!-- 标签页 -->
|
||||||
|
<div class="tab-header">
|
||||||
|
<div
|
||||||
|
v-for="tab in tabs"
|
||||||
|
:key="tab.key"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === tab.key }"
|
||||||
|
@click="activeTab = tab.key"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-container-tab">
|
||||||
|
<!-- 标签内容 -->
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="info-item">
|
||||||
|
<div class="info-label">预警等级;</div>
|
||||||
|
<div class="info-value">{{ afterData.warningLevel }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<div class="info-label">预警信息;</div>
|
||||||
|
<div class="info-value">{{ afterData.warningInfo }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<div class="info-label">预警详情;</div>
|
||||||
|
<div class="info-value">{{ afterData.warningDetail }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { Close, DArrowRight } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
aiData: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close"]);
|
||||||
|
|
||||||
|
// 标签页
|
||||||
|
const tabs = ref([
|
||||||
|
{ key: "frontline", label: "一线人员" },
|
||||||
|
{ key: "district", label: "区县人员" },
|
||||||
|
{ key: "handler", label: "处室人员" },
|
||||||
|
{ key: "leader", label: "中心领导" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const activeTab = ref("frontline");
|
||||||
|
|
||||||
|
// AI处理前数据
|
||||||
|
const beforeData = ref({
|
||||||
|
publishOrg: "潼南区预警中心",
|
||||||
|
publishContent:
|
||||||
|
'潼南区气象台2025年11月13日0时40分发布"暴雨蓝色预警信号",预计23日0:40-6:40,龙形、宝龙、上和、大佛、桂林、玉溪、米心、花岩、双江、古溪、群力、柏梓、崇龛、梓潼、太安等15个乡镇(街道)强降水趋于减弱,未来6小时累计雨量将达50~100毫米,最大小时雨强将达20~40毫米,局地伴有雷电、阵性大风,请各地注意防范。',
|
||||||
|
effectiveTime: "2025-11-13 00:31:30.0",
|
||||||
|
expireTime: "2025-11-13 00:31:30.0",
|
||||||
|
});
|
||||||
|
|
||||||
|
// AI处理后数据
|
||||||
|
const afterData = ref({
|
||||||
|
warningLevel: "重庆市潼南气象台发布大雾黄色预警[III级/较重]",
|
||||||
|
warningInfo:
|
||||||
|
'潼南区区气象台发布暴雨红色预警,按照相关要求,启动I级防御响应,并请及时关注地质、水文等风险提示信息,落实主动封闭管控/"关停撒转"措施',
|
||||||
|
warningDetail:
|
||||||
|
"请立即按照2小时一次频率对你管养的重点路段/重点部位进行巡查,重点巡查较高及以上风险路段、涉灾隐患点、地质条件复杂路段、临河临崖路段/两区三厂、大型设施设备、取弃土(渣)场、砂石料场、涉水桥梁、富水隧道、围堰、支架脚手架、高切坡、滑坡处置等部位,重点关注涉水桥梁基础及墩台、不良地质隧道、隧道洞口边仰坡及侧切结构、高陡边坡支挡防护以及防排水设施,发现异常情况,立即向上报告,采取紧急排危、告警阻拦、吹哨撒转等措施,并及时报送工作开展情况。",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal && props.aiData) {
|
||||||
|
Object.assign(beforeData.value, props.aiData.before);
|
||||||
|
Object.assign(afterData.value, props.aiData.after);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 内容区域
|
||||||
|
.content-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 面板
|
||||||
|
.panel {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #40a9ff;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
width: 50%;
|
||||||
|
background-image: url("../../../assets/RiskWarning_img/矩形@2x.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-content {
|
||||||
|
background-image: url("../../../assets/RiskWarning_img/AI背景@2x.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
height: 85%;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
.info-container {
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.info-container-tab {
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 80%;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.info-item {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
line-height: 1.6;
|
||||||
|
|
||||||
|
&.content-text {
|
||||||
|
display: block;
|
||||||
|
margin-top: 6px;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 中间AI标识
|
||||||
|
.ai-center {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 0 10px;
|
||||||
|
.ai-icon-img {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-icon {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 4px 20px rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-arrow {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #40a9ff;
|
||||||
|
animation: pulse 1.5s infinite;
|
||||||
|
|
||||||
|
:deep(.el-icon) {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.6;
|
||||||
|
transform: translateX(5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标签页
|
||||||
|
.tab-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
padding: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #1e4f70;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
border-color: rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
// background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
||||||
|
background: #18f2f9;
|
||||||
|
border-color: #40a9ff;
|
||||||
|
color: #075948;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-content {
|
||||||
|
.info-item {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,355 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="抢通情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="tableHeight"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
@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 v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<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 v-model="filterForm.type" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<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 v-model="filterForm.controlMeasure" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in controlMeasureOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 起止桩号列插槽 -->
|
||||||
|
<template #stakeNo="{ row }">
|
||||||
|
<el-tooltip :content="row.stakeNo" placement="top" :show-after="500">
|
||||||
|
<span class="ellipsis-text">{{ row.stakeNo }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 路况位置列插槽 -->
|
||||||
|
<template #location="{ row }">
|
||||||
|
<el-tooltip :content="row.location" placement="top" :show-after="500">
|
||||||
|
<span class="ellipsis-text">{{ row.location }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 管控措施列插槽 -->
|
||||||
|
<template #controlMeasure="{ row }">
|
||||||
|
<span :class="['control-tag', getControlClass(row.controlMeasure)]">{{ row.controlMeasure }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 操作列插槽 -->
|
||||||
|
<template #operation="{ row }">
|
||||||
|
<span class="detail-link" @click="handleDetail(row)">详情</span>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import { regionOptions, typeOptions, controlMeasureOptions } from "../component/index.js";
|
||||||
|
import BaseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close", "detail"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
region: "",
|
||||||
|
type: "",
|
||||||
|
controlMeasure: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 影响区域选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 类型选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 管控措施选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 表格高度
|
||||||
|
const tableHeight = ref(300);
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: 'id', label: '序号', width: '50' },
|
||||||
|
{ prop: 'region', label: '影响区域', width: '80' },
|
||||||
|
{ prop: 'routeNo', label: '线路编号', width: '80' },
|
||||||
|
{ prop: 'stakeNo', label: '起止桩号', width: '100', slot: 'stakeNo' },
|
||||||
|
{ prop: 'location', label: '路况位置', width: '100', slot: 'location' },
|
||||||
|
{ prop: 'occurrenceTime', label: '发生时间', width: '140' },
|
||||||
|
{ prop: 'routeNo2', label: '线路编号', width: '80' },
|
||||||
|
{ prop: 'type', label: '类型', width: '80' },
|
||||||
|
{ prop: 'controlMeasure', label: '管控措施', width: '100', slot: 'controlMeasure' },
|
||||||
|
{ prop: 'operation', label: '操作', width: '80', slot: 'operation' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
region: "巫溪县",
|
||||||
|
routeNo: "G242",
|
||||||
|
stakeNo: "336.800-338.850",
|
||||||
|
location: "三星乡五斗村",
|
||||||
|
occurrenceTime: "2025-08-11 04:53:42",
|
||||||
|
routeNo2: "G242",
|
||||||
|
type: "边坡坍塌",
|
||||||
|
controlMeasure: "全幅封闭",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
region: "万州区",
|
||||||
|
routeNo: "G242",
|
||||||
|
stakeNo: "338.800-338.850",
|
||||||
|
location: "三星乡五斗村",
|
||||||
|
occurrenceTime: "2025-08-11 04:53:42",
|
||||||
|
routeNo2: "G242",
|
||||||
|
type: "边坡坍塌",
|
||||||
|
controlMeasure: "正常通行",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
region: "沙坪坝区",
|
||||||
|
routeNo: "G319",
|
||||||
|
stakeNo: "120.500-122.000",
|
||||||
|
location: "沙坪坝镇",
|
||||||
|
occurrenceTime: "2025-08-10 14:30:00",
|
||||||
|
routeNo2: "G319",
|
||||||
|
type: "路面塌陷",
|
||||||
|
controlMeasure: "半幅封闭",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
region: "渝中区",
|
||||||
|
routeNo: "G212",
|
||||||
|
stakeNo: "88.200-89.100",
|
||||||
|
location: "渝中大道",
|
||||||
|
occurrenceTime: "2025-08-09 09:15:30",
|
||||||
|
routeNo2: "G212",
|
||||||
|
type: "桥梁损坏",
|
||||||
|
controlMeasure: "限制通行",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
||||||
|
|
||||||
|
const visiblePages = computed(() => {
|
||||||
|
const pages = [];
|
||||||
|
const maxVisible = 5;
|
||||||
|
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
||||||
|
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
||||||
|
|
||||||
|
if (end - start + 1 < maxVisible) {
|
||||||
|
start = Math.max(1, end - maxVisible + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取管控措施样式类
|
||||||
|
const getControlClass = (measure) => {
|
||||||
|
const classMap = {
|
||||||
|
"全幅封闭": "control-close",
|
||||||
|
"半幅封闭": "control-half",
|
||||||
|
"正常通行": "control-normal",
|
||||||
|
"限制通行": "control-limit",
|
||||||
|
};
|
||||||
|
return classMap[measure] || "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
const handleDetail = (item) => {
|
||||||
|
emit("detail", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
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: 120px;
|
||||||
|
|
||||||
|
: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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 省略号文本
|
||||||
|
.ellipsis-text {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 管控措施标签
|
||||||
|
.control-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.control-close {
|
||||||
|
background-color: rgba(255, 77, 79, 0.2);
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 1px solid rgba(255, 77, 79, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.control-half {
|
||||||
|
background-color: rgba(255, 122, 0, 0.2);
|
||||||
|
color: #ff7a00;
|
||||||
|
border: 1px solid rgba(255, 122, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.control-normal {
|
||||||
|
background-color: rgba(82, 196, 26, 0.2);
|
||||||
|
color: #52c41a;
|
||||||
|
border: 1px solid rgba(82, 196, 26, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.control-limit {
|
||||||
|
background-color: rgba(250, 219, 20, 0.2);
|
||||||
|
color: #fadb14;
|
||||||
|
border: 1px solid rgba(250, 219, 20, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 详情链接
|
||||||
|
.detail-link {
|
||||||
|
color: #40a9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
transition: color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #69c0ff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,6 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="confirm-dialog-overlay" @click="handleOverlayClick">
|
<div
|
||||||
|
v-if="visible"
|
||||||
|
class="confirm-dialog-overlay"
|
||||||
|
@click="handleOverlayClick"
|
||||||
|
>
|
||||||
<div class="confirm-dialog" @click.stop>
|
<div class="confirm-dialog" @click.stop>
|
||||||
|
<!-- 四个角的装饰 -->
|
||||||
|
<div class="corner corner-top-left"></div>
|
||||||
|
<div class="corner corner-top-right"></div>
|
||||||
|
<div class="corner corner-bottom-left"></div>
|
||||||
|
<div class="corner corner-bottom-right"></div>
|
||||||
<!-- 标题栏 -->
|
<!-- 标题栏 -->
|
||||||
<div class="dialog-header">
|
<div class="dialog-header">
|
||||||
<div class="header-title">{{ title }}</div>
|
<div class="header-title">{{ title }}</div>
|
||||||
@ -16,7 +25,7 @@
|
|||||||
|
|
||||||
<!-- 按钮区域 -->
|
<!-- 按钮区域 -->
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button class="btn-cancel" @click="handleCancel">
|
<el-button type="primary" class="btn-confirm" @click="handleCancel">
|
||||||
{{ cancelText }}
|
{{ cancelText }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" class="btn-confirm" @click="handleConfirm">
|
<el-button type="primary" class="btn-confirm" @click="handleConfirm">
|
||||||
@ -45,11 +54,11 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
confirmText: {
|
confirmText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "确定",
|
default: "已拨打",
|
||||||
},
|
},
|
||||||
cancelText: {
|
cancelText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "取消",
|
default: "未拨打",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,18 +98,59 @@ const handleOverlayClick = () => {
|
|||||||
|
|
||||||
.confirm-dialog {
|
.confirm-dialog {
|
||||||
width: 80vw;
|
width: 80vw;
|
||||||
max-width: 400px;
|
max-width: 300px;
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(20, 50, 90, 0.95) 0%,
|
||||||
|
rgba(10, 30, 60, 0.98) 100%
|
||||||
|
);
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: dialogSlideIn 0.3s ease-out;
|
animation: dialogSlideIn 0.3s ease-out;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
width: 90vw;
|
width: 90vw;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
}
|
}
|
||||||
|
// 四个角的装饰
|
||||||
|
.corner {
|
||||||
|
position: absolute;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #40a9ff;
|
||||||
|
z-index: 100;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&.corner-top-left {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.corner-top-right {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
border-left: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.corner-bottom-left {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
border-right: none;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.corner-bottom-right {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
border-left: none;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes dialogSlideIn {
|
@keyframes dialogSlideIn {
|
||||||
@ -120,7 +170,11 @@ const handleOverlayClick = () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
background: linear-gradient(90deg, rgba(64, 169, 255, 0.15) 0%, rgba(64, 169, 255, 0.05) 100%);
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
rgba(64, 169, 255, 0.15) 0%,
|
||||||
|
rgba(64, 169, 255, 0.05) 100%
|
||||||
|
);
|
||||||
border-bottom: 1px solid rgba(64, 169, 255, 0.2);
|
border-bottom: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
|
||||||
.header-title {
|
.header-title {
|
||||||
@ -0,0 +1,302 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="管控情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="tableHeight"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:z-index="2200"
|
||||||
|
@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 v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<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 v-model="filterForm.riskLevel" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in riskLevelOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 驻地名称列插槽 -->
|
||||||
|
<template #stationName="{ row }">
|
||||||
|
<el-tooltip :content="row.stationName" placement="top" :show-after="500">
|
||||||
|
<span class="ellipsis-text">{{ row.stationName }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 所属项目列插槽 -->
|
||||||
|
<template #project="{ row }">
|
||||||
|
<el-tooltip :content="row.project" placement="top" :show-after="500">
|
||||||
|
<span class="ellipsis-text">{{ row.project }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 驻地风险等级列插槽 -->
|
||||||
|
<template #riskLevel="{ row }">
|
||||||
|
<span :class="['risk-tag', getRiskClass(row.riskLevel)]">{{ row.riskLevel }}</span>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import { regionOptions, riskLevelOptions } from "../component/index.js";
|
||||||
|
import BaseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
region: "",
|
||||||
|
riskLevel: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 影响区域选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 风险等级选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 表格高度
|
||||||
|
const tableHeight = ref(300);
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: 'id', label: '序号', width: '60' },
|
||||||
|
{ prop: 'region', label: '影响区域', width: '100' },
|
||||||
|
{ prop: 'stationName', label: '驻地名称', width: '200', slot: 'stationName' },
|
||||||
|
{ prop: 'project', label: '所属项目', width: '200', slot: 'project' },
|
||||||
|
{ prop: 'peopleCount', label: '驻地人数', width: '80' },
|
||||||
|
{ prop: 'riskLevel', label: '驻地风险等级', width: '100', slot: 'riskLevel' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
region: "沙坪坝区",
|
||||||
|
stationName: "沙坪坝区S545茅山峡公路桥新建工程(渝黔铁路扩能改造工程)项目经理部",
|
||||||
|
project: "沙坪坝区S545茅山峡公路桥新建工程(渝黔铁路扩能改造工程)",
|
||||||
|
peopleCount: 21,
|
||||||
|
riskLevel: "Ⅳ级",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
region: "万州区",
|
||||||
|
stationName: "万州区项目经理部",
|
||||||
|
project: "万州区公路改造项目",
|
||||||
|
peopleCount: 15,
|
||||||
|
riskLevel: "Ⅲ级",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
region: "渝中区",
|
||||||
|
stationName: "渝中区桥梁维护项目部",
|
||||||
|
project: "渝中区桥梁维护工程",
|
||||||
|
peopleCount: 8,
|
||||||
|
riskLevel: "Ⅱ级",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
region: "江北区",
|
||||||
|
stationName: "江北区道路施工项目部",
|
||||||
|
project: "江北区道路施工项目",
|
||||||
|
peopleCount: 32,
|
||||||
|
riskLevel: "Ⅰ级",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
||||||
|
|
||||||
|
const visiblePages = computed(() => {
|
||||||
|
const pages = [];
|
||||||
|
const maxVisible = 5;
|
||||||
|
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
||||||
|
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
||||||
|
|
||||||
|
if (end - start + 1 < maxVisible) {
|
||||||
|
start = Math.max(1, end - maxVisible + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取风险等级样式类
|
||||||
|
const getRiskClass = (level) => {
|
||||||
|
const classMap = {
|
||||||
|
"Ⅰ级": "risk-level-1",
|
||||||
|
"Ⅱ级": "risk-level-2",
|
||||||
|
"Ⅲ级": "risk-level-3",
|
||||||
|
"Ⅳ级": "risk-level-4",
|
||||||
|
};
|
||||||
|
return classMap[level] || "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
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: 140px;
|
||||||
|
|
||||||
|
: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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 省略号文本
|
||||||
|
.ellipsis-text {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 风险等级标签
|
||||||
|
.risk-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.risk-level-1 {
|
||||||
|
background-color: rgba(255, 77, 79, 0.2);
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 1px solid rgba(255, 77, 79, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.risk-level-2 {
|
||||||
|
background-color: rgba(255, 122, 0, 0.2);
|
||||||
|
color: #ff7a00;
|
||||||
|
border: 1px solid rgba(255, 122, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.risk-level-3 {
|
||||||
|
background-color: rgba(250, 219, 20, 0.2);
|
||||||
|
color: #fadb14;
|
||||||
|
border: 1px solid rgba(250, 219, 20, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.risk-level-4 {
|
||||||
|
background-color: rgba(82, 196, 26, 0.2);
|
||||||
|
color: #52c41a;
|
||||||
|
border: 1px solid rgba(82, 196, 26, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,234 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="调度区县情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="tableHeight"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:z-index="2300"
|
||||||
|
@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 v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<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 v-model="filterForm.type" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in typeOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import { regionOptions, typeOptions } from "../component/index.js";
|
||||||
|
import BaseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
region: "",
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 影响区域选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 类型选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 表格高度
|
||||||
|
const tableHeight = ref(300);
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: 'id', label: '序号', width: '50' },
|
||||||
|
{ prop: 'district', label: '区县/镇街', width: '100' },
|
||||||
|
{ prop: 'name', label: '姓名', width: '80' },
|
||||||
|
{ prop: 'phone', label: '电话', width: '120' },
|
||||||
|
{ prop: 'type', label: '类型', width: '100' },
|
||||||
|
{ prop: 'role', label: '角色', width: '140' },
|
||||||
|
{ prop: 'dispatchTime', label: '调度时间', width: '160' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
district: "柏梓镇",
|
||||||
|
name: "赵海浪",
|
||||||
|
phone: "18623520681",
|
||||||
|
type: "交通主管部门",
|
||||||
|
role: "一般人员(路长履职)",
|
||||||
|
dispatchTime: "2025-08-11 04:53:42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
district: "柏梓镇",
|
||||||
|
name: "赵海浪",
|
||||||
|
phone: "18623520681",
|
||||||
|
type: "公路机构",
|
||||||
|
role: "一般人员(路长履职)",
|
||||||
|
dispatchTime: "2025-08-11 04:53:42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
district: "万州区",
|
||||||
|
name: "王鑫",
|
||||||
|
phone: "18623520682",
|
||||||
|
type: "养护站",
|
||||||
|
role: "站长",
|
||||||
|
dispatchTime: "2025-08-10 14:30:00",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
district: "沙坪坝区",
|
||||||
|
name: "李华",
|
||||||
|
phone: "18623520683",
|
||||||
|
type: "护路员",
|
||||||
|
role: "一般人员",
|
||||||
|
dispatchTime: "2025-08-09 09:15:30",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
||||||
|
|
||||||
|
const visiblePages = computed(() => {
|
||||||
|
const pages = [];
|
||||||
|
const maxVisible = 5;
|
||||||
|
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
||||||
|
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
||||||
|
|
||||||
|
if (end - start + 1 < maxVisible) {
|
||||||
|
start = Math.max(1, end - maxVisible + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
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: 140px;
|
||||||
|
|
||||||
|
: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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,233 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="调度区县情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="tableHeight"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:z-index="2200"
|
||||||
|
@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 v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="item in regionOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 调度数列插槽 -->
|
||||||
|
<template #dispatchCount="{ row }">
|
||||||
|
<span class="dispatch-count" @click="handleDispatchClick(row)">{{ row.dispatchCount }}</span>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import { regionOptions } from "../component/index.js";
|
||||||
|
import BaseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits({
|
||||||
|
"update:visible": (value) => typeof value === "boolean",
|
||||||
|
"close": () => true,
|
||||||
|
"dispatchClick": (item) => item !== undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
region: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 影响区域选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 表格高度
|
||||||
|
const tableHeight = ref(300);
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: 'id', label: '序号', width: '60' },
|
||||||
|
{ prop: 'region', label: '影响区域', width: '120' },
|
||||||
|
{ prop: 'dispatchCount', label: '调度数', width: '100', slot: 'dispatchCount' },
|
||||||
|
{ prop: 'lastDispatchTime', label: '最近调度时间', width: '160' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
region: "重庆市",
|
||||||
|
dispatchCount: 1,
|
||||||
|
lastDispatchTime: "2025-08-11 04:53:42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
region: "万州区",
|
||||||
|
dispatchCount: 1,
|
||||||
|
lastDispatchTime: "2025-08-11 04:53:42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
region: "沙坪坝区",
|
||||||
|
dispatchCount: 3,
|
||||||
|
lastDispatchTime: "2025-08-10 16:20:15",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
region: "渝中区",
|
||||||
|
dispatchCount: 2,
|
||||||
|
lastDispatchTime: "2025-08-09 11:45:30",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
||||||
|
|
||||||
|
const visiblePages = computed(() => {
|
||||||
|
const pages = [];
|
||||||
|
const maxVisible = 5;
|
||||||
|
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
||||||
|
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
||||||
|
|
||||||
|
if (end - start + 1 < maxVisible) {
|
||||||
|
start = Math.max(1, end - maxVisible + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击调度数
|
||||||
|
const handleDispatchClick = (item) => {
|
||||||
|
emit("dispatchClick", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
// 重置筛选表单
|
||||||
|
filterForm.value.region = "";
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
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: 140px;
|
||||||
|
|
||||||
|
: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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调度数字
|
||||||
|
.dispatch-count {
|
||||||
|
color: #40a9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #69c0ff;
|
||||||
|
text-shadow: 0 0 8px rgba(105, 192, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,14 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="event-dialog-overlay" @click="handleOverlayClick">
|
<base-dialog
|
||||||
<div class="event-dialog" @click.stop>
|
v-model:visible="props.visible"
|
||||||
<!-- 标题栏 -->
|
title="详情"
|
||||||
<div class="dialog-header">
|
:table-data="[]"
|
||||||
<div class="header-title">详情</div>
|
:table-columns="[]"
|
||||||
<div class="close-btn" @click="handleClose">
|
:table-height="0"
|
||||||
<el-icon><Close /></el-icon>
|
:total="0"
|
||||||
</div>
|
:current-page="1"
|
||||||
</div>
|
:page-size="10"
|
||||||
|
:z-index="2200"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
<!-- 事件基本信息 -->
|
<!-- 事件基本信息 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@ -116,7 +120,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
|
||||||
<!-- 图片预览弹窗 -->
|
<!-- 图片预览弹窗 -->
|
||||||
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
||||||
@ -127,12 +132,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { Close } from "@element-plus/icons-vue";
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@ -211,10 +216,7 @@ const handleClose = () => {
|
|||||||
emit("close");
|
emit("close");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点击遮罩关闭
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
// 监听visible变化
|
||||||
watch(
|
watch(
|
||||||
@ -229,68 +231,6 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.event-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.event-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 700px;
|
|
||||||
max-height: 85vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 区块
|
// 区块
|
||||||
.section {
|
.section {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
@ -496,7 +436,7 @@ watch(
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 1100;
|
z-index: 2200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-preview-container {
|
.image-preview-container {
|
||||||
@ -532,7 +472,7 @@ watch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏滚动条
|
// 隐藏滚动条
|
||||||
.event-dialog {
|
:deep(.base-dialog) {
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
|
|
||||||
@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="impact-detail-dialog-overlay" @click="handleOverlayClick">
|
<base-dialog
|
||||||
<div class="impact-detail-dialog" @click.stop>
|
v-model:visible="props.visible"
|
||||||
<!-- 标题栏 -->
|
title="影响点详情"
|
||||||
<div class="dialog-header">
|
:table-data="[]"
|
||||||
<div class="header-title">影响点详情</div>
|
:table-columns="[]"
|
||||||
<div class="close-btn" @click="handleClose">
|
:table-height="0"
|
||||||
<el-icon><Close /></el-icon>
|
:total="0"
|
||||||
</div>
|
:current-page="1"
|
||||||
</div>
|
:page-size="10"
|
||||||
|
:z-index="2500"
|
||||||
|
:max-width="650"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
<!-- 隐患点基本信息 -->
|
<!-- 隐患点基本信息 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@ -109,7 +114,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
|
||||||
<!-- 图片预览弹窗 -->
|
<!-- 图片预览弹窗 -->
|
||||||
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
||||||
@ -120,12 +126,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { Close } from "@element-plus/icons-vue";
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@ -203,10 +209,7 @@ const handleClose = () => {
|
|||||||
emit("close");
|
emit("close");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点击遮罩关闭
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
// 监听visible变化
|
||||||
watch(
|
watch(
|
||||||
@ -220,67 +223,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.impact-detail-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.impact-detail-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 650px;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 区块
|
// 区块
|
||||||
.section {
|
.section {
|
||||||
@ -556,13 +499,5 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 隐藏滚动条
|
|
||||||
.impact-detail-dialog {
|
|
||||||
scrollbar-width: none;
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@ -0,0 +1,428 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="影响点情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="320"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:z-index="2000"
|
||||||
|
:max-width="1200"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
|
<!-- 统计卡片 -->
|
||||||
|
<div class="stats-cards">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响桥梁</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响边坡</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响隧道</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响项目</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<template #filter>
|
||||||
|
<div class="filter-row">
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="filterForm.pointType" size="small" placeholder="影响点类型" class="filter-select">
|
||||||
|
<el-option
|
||||||
|
v-for="option in pointTypeOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="filterForm.pointLevel" size="small" placeholder="影响点等级" class="filter-select">
|
||||||
|
<el-option
|
||||||
|
v-for="option in pointLevelOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select v-model="filterForm.region" size="small" placeholder="影响区域" class="filter-select">
|
||||||
|
<el-option
|
||||||
|
v-for="option in regionOptionsWithAll"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-button type="primary" class="search-btn" @click="handleSearch">
|
||||||
|
查询
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 影响点等级列插槽 -->
|
||||||
|
<template #pointLevel="{ row }">
|
||||||
|
<span class="level-tag" :class="row.levelClass">{{ row.pointLevel }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 交通主管部门负责人列插槽 -->
|
||||||
|
<template #trafficDept="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.trafficDept.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.trafficDept.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 公路机构责任人列插槽 -->
|
||||||
|
<template #roadOrg="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.roadOrg.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.roadOrg.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 养护站负责人列插槽 -->
|
||||||
|
<template #maintenance="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.maintenance.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.maintenance.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 护路员列插槽 -->
|
||||||
|
<template #roadKeeper="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.roadKeeper.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.roadKeeper.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 操作列插槽 -->
|
||||||
|
<template #operation="{ row }">
|
||||||
|
<span class="detail-link" @click="handleDetail(row)">详情</span>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close, ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
||||||
|
import { pointTypeOptions, pointLevelOptions, regionOptionsWithAll } from "../component/index.js";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close", "detail"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
pointType: "",
|
||||||
|
pointLevel: "",
|
||||||
|
region: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: "id", label: "序号", width: "50px" },
|
||||||
|
{ prop: "region", label: "影响区域", width: "80px" },
|
||||||
|
{ prop: "pointType", label: "影响点类型", width: "80px" },
|
||||||
|
{ prop: "pointLocation", label: "影响点位置", width: "180px" },
|
||||||
|
{ prop: "pointLevel", label: "影响点等级", width: "90px", slot: "pointLevel" },
|
||||||
|
{ prop: "trafficDept", label: "交通主管部门负责人", width: "130px", slot: "trafficDept" },
|
||||||
|
{ prop: "roadOrg", label: "公路机构责任人", width: "110px", slot: "roadOrg" },
|
||||||
|
{ prop: "maintenance", label: "养护站负责人", width: "110px", slot: "maintenance" },
|
||||||
|
{ prop: "roadKeeper", label: "护路员", width: "100px", slot: "roadKeeper" },
|
||||||
|
{ prop: "operation", label: "操作", width: "60px", slot: "operation" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
region: "重庆市",
|
||||||
|
pointType: "边坡",
|
||||||
|
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
||||||
|
pointLevel: "一般隐患",
|
||||||
|
levelClass: "level-normal",
|
||||||
|
trafficDept: { name: "罗宸", phone: "17623865172" },
|
||||||
|
roadOrg: { name: "李海平", phone: "13708320801" },
|
||||||
|
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
||||||
|
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
region: "重庆市",
|
||||||
|
pointType: "边坡",
|
||||||
|
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
||||||
|
pointLevel: "一般隐患",
|
||||||
|
levelClass: "level-normal",
|
||||||
|
trafficDept: { name: "罗宸", phone: "17623865172" },
|
||||||
|
roadOrg: { name: "李海平", phone: "13708320801" },
|
||||||
|
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
||||||
|
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
region: "重庆市",
|
||||||
|
pointType: "边坡",
|
||||||
|
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
||||||
|
pointLevel: "一般隐患",
|
||||||
|
levelClass: "level-normal",
|
||||||
|
trafficDept: { name: "罗宸", phone: "17623865172" },
|
||||||
|
roadOrg: { name: "李海平", phone: "13708320801" },
|
||||||
|
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
||||||
|
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
||||||
|
|
||||||
|
const visiblePages = computed(() => {
|
||||||
|
const pages = [];
|
||||||
|
const maxVisible = 4;
|
||||||
|
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
||||||
|
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
||||||
|
|
||||||
|
if (end - start + 1 < maxVisible) {
|
||||||
|
start = Math.max(1, end - maxVisible + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
return pages;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
console.log("查询条件:", filterForm.value);
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
const handleDetail = (item) => {
|
||||||
|
emit("detail", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 视频屏幕自适应 - 基于视口宽度动态调整
|
||||||
|
@function vw($px) {
|
||||||
|
@return calc($px / 1920 * 100vw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 统计卡片
|
||||||
|
.stats-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: vw(16);
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
background: linear-gradient(135deg, rgba(30, 70, 120, 0.6) 0%, rgba(20, 50, 90, 0.8) 100%);
|
||||||
|
border: vw(2) solid rgba(64, 169, 255, 0.4);
|
||||||
|
text-align: center;
|
||||||
|
transition: all 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: vw(14);
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: vw(28);
|
||||||
|
font-weight: bold;
|
||||||
|
color: #40a9ff;
|
||||||
|
text-shadow: 0 0 10px rgba(64, 169, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: vw(20);
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
.filter-select {
|
||||||
|
width: vw(150);
|
||||||
|
|
||||||
|
: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: vw(4);
|
||||||
|
|
||||||
|
.el-input__inner {
|
||||||
|
color: #fff;
|
||||||
|
font-size: vw(13);
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__suffix {
|
||||||
|
.el-icon {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: vw(4);
|
||||||
|
padding: 0 vw(24);
|
||||||
|
height: vw(32);
|
||||||
|
font-size: vw(13);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #69c0ff 0%, #40a9ff 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格列样式
|
||||||
|
.level-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: vw(2) vw(8);
|
||||||
|
border-radius: vw(4);
|
||||||
|
font-size: vw(11);
|
||||||
|
|
||||||
|
&.level-normal {
|
||||||
|
background-color: rgba(250, 219, 95, 0.2);
|
||||||
|
color: #fadb5f;
|
||||||
|
border: 1px solid rgba(250, 219, 95, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.level-serious {
|
||||||
|
background-color: rgba(255, 77, 79, 0.2);
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 1px solid rgba(255, 77, 79, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: vw(2);
|
||||||
|
|
||||||
|
.person-name {
|
||||||
|
font-size: vw(12);
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-phone {
|
||||||
|
font-size: vw(11);
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-link {
|
||||||
|
color: #40a9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: vw(12);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #69c0ff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉菜单样式
|
||||||
|
:deep(.el-select-dropdown) {
|
||||||
|
background-color: rgba(20, 50, 90, 0.98);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: rgba(64, 169, 255, 0.3);
|
||||||
|
color: #40a9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="response-dialog-overlay" @click="handleOverlayClick">
|
<base-dialog
|
||||||
<div class="response-dialog" @click.stop>
|
v-model:visible="props.visible"
|
||||||
<!-- 标题栏 -->
|
title="响应点详情"
|
||||||
<div class="dialog-header">
|
:table-data="[]"
|
||||||
<div class="header-title">响应点详情</div>
|
:table-columns="[]"
|
||||||
<div class="close-btn" @click="handleClose">
|
:table-height="0"
|
||||||
<el-icon><Close /></el-icon>
|
:total="0"
|
||||||
</div>
|
:current-page="1"
|
||||||
</div>
|
:page-size="10"
|
||||||
|
:z-index="1000"
|
||||||
|
:max-width="700"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
<!-- 隐患点基本信息 -->
|
<!-- 隐患点基本信息 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@ -114,7 +119,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
|
||||||
<!-- 图片预览弹窗 -->
|
<!-- 图片预览弹窗 -->
|
||||||
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
||||||
@ -125,12 +131,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { Close } from "@element-plus/icons-vue";
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@ -240,10 +246,7 @@ const handleClose = () => {
|
|||||||
emit("close");
|
emit("close");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点击遮罩关闭
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
// 监听visible变化
|
||||||
watch(
|
watch(
|
||||||
@ -257,67 +260,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.response-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 700px;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 区块
|
// 区块
|
||||||
.section {
|
.section {
|
||||||
@ -657,22 +600,5 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.response-dialog::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-dialog::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-dialog::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-dialog::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="response-info-dialog-overlay" @click="handleOverlayClick">
|
<base-dialog
|
||||||
<div class="response-info-dialog" @click.stop>
|
v-model:visible="props.visible"
|
||||||
<!-- 标题栏 -->
|
title="响应点详情"
|
||||||
<div class="dialog-header">
|
:table-data="[]"
|
||||||
<div class="header-title">响应点详情</div>
|
:table-columns="[]"
|
||||||
<div class="close-btn" @click="handleClose">
|
:table-height="0"
|
||||||
<el-icon><Close /></el-icon>
|
:total="0"
|
||||||
</div>
|
:current-page="1"
|
||||||
</div>
|
:page-size="10"
|
||||||
|
:z-index="1000"
|
||||||
|
:max-width="750"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
<!-- 基本信息 -->
|
<!-- 基本信息 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@ -137,7 +142,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
|
||||||
<!-- 图片预览弹窗 -->
|
<!-- 图片预览弹窗 -->
|
||||||
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
||||||
@ -148,12 +154,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { Close } from "@element-plus/icons-vue";
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@ -274,10 +280,7 @@ const handleClose = () => {
|
|||||||
emit("close");
|
emit("close");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点击遮罩关闭
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
// 监听visible变化
|
||||||
watch(
|
watch(
|
||||||
@ -291,67 +294,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.response-info-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-info-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 750px;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 区块
|
// 区块
|
||||||
.section {
|
.section {
|
||||||
@ -694,22 +637,5 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.response-info-dialog::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-info-dialog::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-info-dialog::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-info-dialog::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@ -0,0 +1,264 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="潼南三级路长明细"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="300"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:z-index="1000"
|
||||||
|
:max-width="700"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
|
<!-- 统计数据卡片 -->
|
||||||
|
<div class="stats-cards">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="card-icon">
|
||||||
|
<el-icon class="stat-icon"><User /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="card-info">
|
||||||
|
<div class="card-label">路长总人数</div>
|
||||||
|
<div class="card-value">
|
||||||
|
<span class="value-num">{{ stats.total }}</span>
|
||||||
|
<span class="value-unit">人</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="card-icon">
|
||||||
|
<el-icon class="stat-icon"><OfficeBuilding /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="card-info">
|
||||||
|
<div class="card-label">县级路长</div>
|
||||||
|
<div class="card-value">
|
||||||
|
<span class="value-num">{{ stats.county }}</span>
|
||||||
|
<span class="value-unit">公里</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="card-icon">
|
||||||
|
<el-icon class="stat-icon"><MapLocation /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="card-info">
|
||||||
|
<div class="card-label">乡、村路长</div>
|
||||||
|
<div class="card-value">
|
||||||
|
<span class="value-num">{{ stats.village }}</span>
|
||||||
|
<span class="value-unit">次</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 操作列插槽 -->
|
||||||
|
<template #operation="{ row }">
|
||||||
|
<div class="action-btns">
|
||||||
|
<div class="action-btn" @click="handleView(row)">
|
||||||
|
<el-icon><VideoCamera /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn" @click="handleVoice(row)">
|
||||||
|
<el-icon><Microphone /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="action-btn" @click="handleCall(row)">
|
||||||
|
<el-icon><Phone /></el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close, VideoCamera, Microphone, Phone, ArrowLeft, ArrowRight, User, OfficeBuilding, MapLocation } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close"]);
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
const stats = ref({
|
||||||
|
total: 1127,
|
||||||
|
county: 216,
|
||||||
|
village: 1099,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: "id", label: "序号", width: "60px" },
|
||||||
|
{ prop: "district", label: "区县/镇街", width: "120px" },
|
||||||
|
{ prop: "name", label: "姓名", width: "100px" },
|
||||||
|
{ prop: "phone", label: "电话", width: "120px" },
|
||||||
|
{ prop: "role", label: "角色", width: "200px" },
|
||||||
|
{ prop: "position", label: "职务", width: "100px" },
|
||||||
|
{ prop: "operation", label: "操作", width: "120px", slot: "operation" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{ id: 1, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 2, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 3, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 4, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 5, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 6, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 7, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 8, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 9, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 10, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 11, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
{ id: 12, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 操作按钮
|
||||||
|
const handleView = (item) => {
|
||||||
|
console.log("查看视频:", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVoice = (item) => {
|
||||||
|
console.log("语音通话:", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCall = (item) => {
|
||||||
|
console.log("拨打电话:", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
// 统计卡片
|
||||||
|
.stats-cards {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: linear-gradient(135deg, rgba(30, 80, 140, 0.6) 0%, rgba(20, 60, 110, 0.8) 100%);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
|
||||||
|
.card-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: rgba(64, 169, 255, 0.15);
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #40a9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-info {
|
||||||
|
.card-label {
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
.value-num {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #40a9ff;
|
||||||
|
text-shadow: 0 0 6px rgba(64, 169, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-unit {
|
||||||
|
font-size: 10px;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作按钮样式
|
||||||
|
.action-btns {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: rgba(64, 169, 255, 0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
color: #40a9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.3);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,448 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="响应情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="200"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:z-index="1000"
|
||||||
|
:max-width="1150"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
|
<!-- 统计卡片 -->
|
||||||
|
<div class="stats-cards">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响桥梁</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响边坡</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响隧道</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响项目</div>
|
||||||
|
<div class="stat-value">2933</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">影响路段</div>
|
||||||
|
<div class="stat-value">2432</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<template #filter>
|
||||||
|
<div class="filter-row">
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.pointType"
|
||||||
|
placeholder="影响点类型"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in pointTypeOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.pointLevel"
|
||||||
|
placeholder="影响点等级"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in pointLevelOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.isResponded"
|
||||||
|
placeholder="是否回应"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in isRespondedOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 影响点等级列插槽 -->
|
||||||
|
<template #pointLevel="{ row }">
|
||||||
|
<span class="level-tag" :class="row.levelClass">{{ row.pointLevel }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 交通主管部门负责人列插槽 -->
|
||||||
|
<template #trafficDept="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.trafficDept.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.trafficDept.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 公路机构责任人列插槽 -->
|
||||||
|
<template #roadOrg="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.roadOrg.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.roadOrg.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 养护站负责人列插槽 -->
|
||||||
|
<template #maintenance="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.maintenance.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.maintenance.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 护路员列插槽 -->
|
||||||
|
<template #roadKeeper="{ row }">
|
||||||
|
<div class="person-info">
|
||||||
|
<span class="person-name">{{ row.roadKeeper.name }}</span>
|
||||||
|
<span class="person-phone">{{ row.roadKeeper.phone }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 回应状态列插槽 -->
|
||||||
|
<template #responseStatus="{ row }">
|
||||||
|
<span class="response-status" :class="row.responseClass">{{ row.responseStatus }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 最新催告时间列插槽 -->
|
||||||
|
<template #urgeTime="{ row }">
|
||||||
|
<div class="time-info">
|
||||||
|
<span class="time-date">{{ row.urgeTime.date }}</span>
|
||||||
|
<span class="time-clock">{{ row.urgeTime.time }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 操作列插槽 -->
|
||||||
|
<template #operation="{ row }">
|
||||||
|
<span class="detail-link" @click="handleDetail(row)">详情</span>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close, ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
||||||
|
import { pointTypeOptions, pointLevelOptions, isRespondedOptions } from "../component/index.js";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close", "detail"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
pointType: "",
|
||||||
|
pointLevel: "",
|
||||||
|
isResponded: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: "id", label: "序号", width: "50px" },
|
||||||
|
{ prop: "pointType", label: "影响点类型", width: "80px" },
|
||||||
|
{ prop: "pointLocation", label: "影响点位置", width: "150px" },
|
||||||
|
{ prop: "pointLevel", label: "影响点等级", width: "90px", slot: "pointLevel" },
|
||||||
|
{ prop: "checkCount", label: "查次数", width: "60px" },
|
||||||
|
{ prop: "trafficDept", label: "交通主管部门负责人", width: "120px", slot: "trafficDept" },
|
||||||
|
{ prop: "roadOrg", label: "公路机构责任人", width: "110px", slot: "roadOrg" },
|
||||||
|
{ prop: "maintenance", label: "养护站负责人", width: "110px", slot: "maintenance" },
|
||||||
|
{ prop: "roadKeeper", label: "护路员", width: "80px", slot: "roadKeeper" },
|
||||||
|
{ prop: "responseStatus", label: "回应状态", width: "70px", slot: "responseStatus" },
|
||||||
|
{ prop: "urgeTime", label: "最新催告时间", width: "110px", slot: "urgeTime" },
|
||||||
|
{ prop: "operation", label: "操作", width: "50px", slot: "operation" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
pointType: "边坡",
|
||||||
|
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
||||||
|
pointLevel: "一般隐患",
|
||||||
|
levelClass: "level-normal",
|
||||||
|
checkCount: 2,
|
||||||
|
trafficDept: { name: "罗宸", phone: "17623865172" },
|
||||||
|
roadOrg: { name: "李海平", phone: "1372386532" },
|
||||||
|
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
||||||
|
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
||||||
|
responseStatus: "已回应",
|
||||||
|
responseClass: "status-responded",
|
||||||
|
urgeTime: { date: "2026-03-28", time: "12:30:00" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
pointType: "边坡",
|
||||||
|
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
||||||
|
pointLevel: "一般隐患",
|
||||||
|
levelClass: "level-normal",
|
||||||
|
checkCount: 2,
|
||||||
|
trafficDept: { name: "罗宸", phone: "17623865172" },
|
||||||
|
roadOrg: { name: "李海平", phone: "1372386532" },
|
||||||
|
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
||||||
|
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
||||||
|
responseStatus: "已回应",
|
||||||
|
responseClass: "status-responded",
|
||||||
|
urgeTime: { date: "2026-03-28", time: "12:30:00" },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
tableData.value.push(...tableData.value);
|
||||||
|
tableData.value.push(...tableData.value);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
|
|
||||||
|
// 查看详情
|
||||||
|
const handleDetail = (item) => {
|
||||||
|
emit("detail", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
.filter-select {
|
||||||
|
width: 150px;
|
||||||
|
|
||||||
|
: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.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__suffix {
|
||||||
|
.el-icon {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格单元格样式
|
||||||
|
.level-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
|
||||||
|
&.level-normal {
|
||||||
|
background-color: rgba(250, 219, 95, 0.2);
|
||||||
|
color: #fadb5f;
|
||||||
|
border: 1px solid rgba(250, 219, 95, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.level-serious {
|
||||||
|
background-color: rgba(255, 77, 79, 0.2);
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 1px solid rgba(255, 77, 79, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
.person-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-phone {
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.response-status {
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
&.status-responded {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-unresponded {
|
||||||
|
color: #ff7a45;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
.time-date {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-clock {
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-link {
|
||||||
|
color: #40a9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #69c0ff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉菜单样式
|
||||||
|
:deep(.el-select-dropdown) {
|
||||||
|
background-color: rgba(20, 50, 90, 0.98);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: rgba(64, 169, 255, 0.3);
|
||||||
|
color: #40a9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计卡片
|
||||||
|
.stats-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(30, 70, 120, 0.6) 0%,
|
||||||
|
rgba(20, 50, 90, 0.8) 100%
|
||||||
|
);
|
||||||
|
border: 2px solid rgba(64, 169, 255, 0.4);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 20px;
|
||||||
|
text-align: center;
|
||||||
|
transition: all 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(64, 169, 255, 0.8);
|
||||||
|
box-shadow: 0 0 20px rgba(64, 169, 255, 0.3);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #40a9ff;
|
||||||
|
text-shadow: 0 0 10px rgba(64, 169, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="visible" class="risk-dialog-overlay" @click="handleOverlayClick">
|
<base-dialog
|
||||||
<div class="risk-dialog" @click.stop>
|
v-model:visible="props.visible"
|
||||||
<!-- 标题栏 -->
|
title="影响点详情"
|
||||||
<div class="dialog-header">
|
:table-data="[]"
|
||||||
<div class="header-title">影响点详情</div>
|
:table-columns="[]"
|
||||||
<div class="close-btn" @click="handleClose">
|
:table-height="0"
|
||||||
<el-icon><Close /></el-icon>
|
:total="0"
|
||||||
</div>
|
:current-page="1"
|
||||||
</div>
|
:page-size="10"
|
||||||
|
:z-index="1000"
|
||||||
|
:max-width="800"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
<!-- 基本信息 -->
|
<!-- 基本信息 -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@ -166,7 +171,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
|
||||||
<!-- 图片预览弹窗 -->
|
<!-- 图片预览弹窗 -->
|
||||||
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
|
||||||
@ -177,12 +183,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { Close } from "@element-plus/icons-vue";
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
@ -319,10 +325,7 @@ const handleClose = () => {
|
|||||||
emit("close");
|
emit("close");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点击遮罩关闭
|
// 点击遮罩关闭已由base-dialog组件处理
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
// 监听visible变化
|
||||||
watch(
|
watch(
|
||||||
@ -336,67 +339,7 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.risk-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.risk-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 800px;
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 区块
|
// 区块
|
||||||
.section {
|
.section {
|
||||||
@ -776,22 +719,5 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.risk-dialog::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.risk-dialog::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.risk-dialog::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.risk-dialog::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@ -0,0 +1,614 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="visible"
|
||||||
|
class="warning-dialog-overlay"
|
||||||
|
@click="handleOverlayClick"
|
||||||
|
>
|
||||||
|
<div class="warning-dialog" @click.stop>
|
||||||
|
<!-- 标题栏 -->
|
||||||
|
<div class="dialog-header">
|
||||||
|
<div class="header-title">响应情况</div>
|
||||||
|
<div class="close-btn" @click="handleClose">
|
||||||
|
<el-icon><Close /></el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<div class="filter-section">
|
||||||
|
<div class="filter-row">
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.warningLevel"
|
||||||
|
placeholder="预警等级"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in warningLevelOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.region"
|
||||||
|
placeholder="影响区域"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in regionOptionsWithAll"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.isEnded"
|
||||||
|
placeholder="是否结束"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in isEndedOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.isResponded"
|
||||||
|
placeholder="是否回应"
|
||||||
|
class="filter-select"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in isRespondedOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<el-button type="primary" class="search-btn" @click="handleSearch">
|
||||||
|
<el-icon><Search /></el-icon>
|
||||||
|
查询
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<div class="table-section">
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
:height="tableHeight"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="headerCellStyle"
|
||||||
|
:cell-style="cellStyle"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" label="序号" width="60" />
|
||||||
|
<el-table-column prop="weatherSource" label="气象来源" width="80" />
|
||||||
|
<el-table-column prop="warningLevel" label="预警等级" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span class="warning-level" :class="row.levelClass">{{ row.warningLevel }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="region" label="影响区域" width="100" />
|
||||||
|
<el-table-column prop="warningTime" label="预警时间" width="160" />
|
||||||
|
<el-table-column prop="endTime" label="结束时间" width="160" />
|
||||||
|
<el-table-column prop="impactPoints" label="影响点数量" width="100" />
|
||||||
|
<el-table-column prop="called" label="已叫应" width="80">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span class="clickable-cell" @click="handleCalledClick(row)">{{ row.called }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="responded" label="已回应" width="80" />
|
||||||
|
<el-table-column prop="notResponded" label="未回应" width="80" />
|
||||||
|
<el-table-column prop="urged" label="已催告" width="80" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="currentPage"
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
:page-sizes="[10, 20, 30, 40]"
|
||||||
|
:total="total"
|
||||||
|
background
|
||||||
|
layout="prev, pager, next, jumper, ->, total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close, Search, ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
||||||
|
import {
|
||||||
|
warningLevelOptions,
|
||||||
|
regionOptionsWithAll,
|
||||||
|
isEndedOptions,
|
||||||
|
isRespondedOptions,
|
||||||
|
} from "../component/index.js";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close", "openImpactPoint"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
warningLevel: "",
|
||||||
|
region: "",
|
||||||
|
isEnded: "",
|
||||||
|
isResponded: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ label: "序号", width: "60px" },
|
||||||
|
{ label: "气象来源", width: "80px" },
|
||||||
|
{ label: "预警等级", width: "100px" },
|
||||||
|
{ label: "影响区域", width: "100px" },
|
||||||
|
{ label: "预警时间", width: "160px" },
|
||||||
|
{ label: "结束时间", width: "160px" },
|
||||||
|
{ label: "影响点数量", width: "100px" },
|
||||||
|
{ label: "已叫应", width: "80px" },
|
||||||
|
{ label: "已回应", width: "80px" },
|
||||||
|
{ label: "未回应", width: "80px" },
|
||||||
|
{ label: "已催告", width: "80px" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
weatherSource: "气象局",
|
||||||
|
warningLevel: "红色预警",
|
||||||
|
levelClass: "level-red",
|
||||||
|
region: "万州区",
|
||||||
|
warningTime: "2025-08-11 04:53:42",
|
||||||
|
endTime: "2025-08-11 04:53:42",
|
||||||
|
impactPoints: 4,
|
||||||
|
called: 2,
|
||||||
|
responded: 2,
|
||||||
|
notResponded: 2,
|
||||||
|
urged: 22,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
weatherSource: "气象局",
|
||||||
|
warningLevel: "橙色预警",
|
||||||
|
levelClass: "level-orange",
|
||||||
|
region: "涪陵区",
|
||||||
|
warningTime: "2025-08-11 04:53:42",
|
||||||
|
endTime: "2025-08-11 04:53:42",
|
||||||
|
impactPoints: 0,
|
||||||
|
called: 0,
|
||||||
|
responded: 0,
|
||||||
|
notResponded: 0,
|
||||||
|
urged: 18,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
tableData.value.push(...tableData.value);
|
||||||
|
tableData.value.push(...tableData.value);
|
||||||
|
tableData.value.push(...tableData.value);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
// 表格高度
|
||||||
|
const tableHeight = ref(300);
|
||||||
|
|
||||||
|
// 表格样式
|
||||||
|
const headerCellStyle = () => {
|
||||||
|
return {
|
||||||
|
backgroundColor: '#1C4979',
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: '14px',
|
||||||
|
fontWeight: '500',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: '12px 16px',
|
||||||
|
border: 'none'
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const cellStyle = () => {
|
||||||
|
return {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
color: 'rgba(255, 255, 255, 0.85)',
|
||||||
|
fontSize: '13px',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: '12px 16px',
|
||||||
|
border: 'none'
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击遮罩关闭
|
||||||
|
const handleOverlayClick = () => {
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击已叫应
|
||||||
|
const handleCalledClick = () => {
|
||||||
|
emit("responseStatus");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const handleSearch = () => {
|
||||||
|
console.log("查询条件:", filterForm.value);
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.warning-dialog-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-dialog {
|
||||||
|
width: 80vw;
|
||||||
|
max-width: 1000px;
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(20, 50, 90, 0.95) 0%,
|
||||||
|
rgba(10, 30, 60, 0.98) 100%
|
||||||
|
);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标题栏
|
||||||
|
.dialog-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
padding: 8px 40px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent 0%,
|
||||||
|
rgba(64, 169, 255, 0.2) 20%,
|
||||||
|
rgba(64, 169, 255, 0.2) 80%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
border-bottom: 2px solid #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 20px;
|
||||||
|
transition: color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
.filter-select {
|
||||||
|
width: 120px;
|
||||||
|
|
||||||
|
: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.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__suffix {
|
||||||
|
.el-icon {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0 20px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #69c0ff 0%, #40a9ff 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格区域
|
||||||
|
.table-section {
|
||||||
|
background-color: rgba(30, 70, 120, 0.3);
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
:deep(.el-table) {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.el-table__header-wrapper {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__body-wrapper {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__row {
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
background-color: rgba(30, 70, 120, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__cell {
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__header .el-table__cell {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-level {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.level-red {
|
||||||
|
background-color: rgba(255, 77, 79, 0.2);
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 1px solid rgba(255, 77, 79, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.level-orange {
|
||||||
|
background-color: rgba(255, 122, 69, 0.2);
|
||||||
|
color: #ff7a45;
|
||||||
|
border: 1px solid rgba(255, 122, 69, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.level-yellow {
|
||||||
|
background-color: rgba(250, 219, 95, 0.2);
|
||||||
|
color: #fadb5f;
|
||||||
|
border: 1px solid rgba(250, 219, 95, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.level-blue {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
color: #40a9ff;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable-cell {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #40a9ff;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #69c0ff;
|
||||||
|
text-shadow: 0 0 8px rgba(105, 192, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
.pagination {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
:deep(.el-pagination) {
|
||||||
|
.el-pagination__total {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__sizes .el-input__inner {
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(30, 70, 120, 0.4);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__btn {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
background-color: rgba(64, 169, 255, 0.1);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover:not(.is-disabled) {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
border-color: rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__item {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
background-color: rgba(64, 169, 255, 0.1);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover:not(.is-disabled) {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
border-color: rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-color: #40a9ff;
|
||||||
|
border-color: #40a9ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__jump .el-input__inner {
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(30, 70, 120, 0.4);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏滚动条
|
||||||
|
:deep(.el-table__body-wrapper::-webkit-scrollbar) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table__body-wrapper) {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉菜单样式
|
||||||
|
:deep(.el-select-dropdown) {
|
||||||
|
background-color: rgba(20, 50, 90, 0.98);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: rgba(64, 169, 255, 0.3);
|
||||||
|
color: #40a9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,577 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
title="预警情况"
|
||||||
|
:table-data="tableData"
|
||||||
|
:table-columns="tableColumns"
|
||||||
|
:table-height="tableHeight"
|
||||||
|
:total="total"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
@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
|
||||||
|
v-model="filterForm.warningLevel"
|
||||||
|
placeholder="请选择"
|
||||||
|
class="filter-select"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in warningLevelOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="filter-item">
|
||||||
|
<span class="filter-label">影响区域</span>
|
||||||
|
<el-select
|
||||||
|
v-model="filterForm.region"
|
||||||
|
placeholder="请选择"
|
||||||
|
class="filter-select"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<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
|
||||||
|
v-model="filterForm.isEnded"
|
||||||
|
placeholder="请选择"
|
||||||
|
class="filter-select"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in isEndedOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 预警等级列插槽 -->
|
||||||
|
<template #warningLevel="{ row }">
|
||||||
|
<span
|
||||||
|
:class="[
|
||||||
|
'warning-level-tag',
|
||||||
|
getWarningClass(row.warningLevel),
|
||||||
|
]"
|
||||||
|
>{{ row.warningLevel }}</span
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 影响点数量列插槽 -->
|
||||||
|
<template #impactCount="{ row }">
|
||||||
|
<span class="impact-count" @click="handleImpactClick(row)">{{
|
||||||
|
row.impactCount
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from "vue";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import {
|
||||||
|
warningLevelOptions,
|
||||||
|
regionOptions,
|
||||||
|
isEndedOptions,
|
||||||
|
} from "../component/index.js";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close", "impactClick"]);
|
||||||
|
|
||||||
|
// 筛选表单
|
||||||
|
const filterForm = ref({
|
||||||
|
warningLevel: "",
|
||||||
|
region: "",
|
||||||
|
isEnded: "",
|
||||||
|
dateRange: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 预警等级选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 影响区域选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 是否结束选项
|
||||||
|
// 已从 index.js 导入
|
||||||
|
|
||||||
|
// 表格高度
|
||||||
|
const tableHeight = ref(300);
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const tableColumns = ref([
|
||||||
|
{ prop: 'index', label: '序号', width: '60' },
|
||||||
|
{ prop: 'warningLevel', label: '预警等级', width: '100', slot: 'warningLevel' },
|
||||||
|
{ prop: 'weatherType', label: '气象类型', width: '100' },
|
||||||
|
{ prop: 'region', label: '行政区域', width: '100' },
|
||||||
|
{ prop: 'warningTime', label: '预警时间', width: '160' },
|
||||||
|
{ prop: 'endTime', label: '结束时间', width: '160' },
|
||||||
|
{ prop: 'impactCount', label: '影响点数量', width: '100', slot: 'impactCount' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableData = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
index: 1,
|
||||||
|
warningLevel: "红色预警",
|
||||||
|
weatherType: "暴雨",
|
||||||
|
region: "重庆市",
|
||||||
|
warningTime: "2025-08-11 04:53:42",
|
||||||
|
endTime: "2025-08-11 04:53:42",
|
||||||
|
impactCount: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
index: 2,
|
||||||
|
warningLevel: "橙色预警",
|
||||||
|
weatherType: "暴雨",
|
||||||
|
region: "万州区",
|
||||||
|
warningTime: "2025-08-11 04:53:42",
|
||||||
|
endTime: "2025-08-11 04:53:42",
|
||||||
|
impactCount: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
index: 3,
|
||||||
|
warningLevel: "黄色预警",
|
||||||
|
weatherType: "大风",
|
||||||
|
region: "沙坪坝区",
|
||||||
|
warningTime: "2025-08-10 16:20:15",
|
||||||
|
endTime: "2025-08-10 20:30:00",
|
||||||
|
impactCount: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
index: 4,
|
||||||
|
warningLevel: "蓝色预警",
|
||||||
|
weatherType: "雷电",
|
||||||
|
region: "渝中区",
|
||||||
|
warningTime: "2025-08-09 09:15:30",
|
||||||
|
endTime: "2025-08-09 12:00:00",
|
||||||
|
impactCount: 2,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const total = ref(36);
|
||||||
|
|
||||||
|
// 获取预警等级样式类
|
||||||
|
const getWarningClass = (level) => {
|
||||||
|
const classMap = {
|
||||||
|
红色预警: "warning-red",
|
||||||
|
橙色预警: "warning-orange",
|
||||||
|
黄色预警: "warning-yellow",
|
||||||
|
蓝色预警: "warning-blue",
|
||||||
|
};
|
||||||
|
return classMap[level] || "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击影响点数量
|
||||||
|
const handleImpactClick = (item) => {
|
||||||
|
emit("impactClick", item);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pageSize.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
currentPage.value = val;
|
||||||
|
fetchData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取数据
|
||||||
|
const fetchData = () => {
|
||||||
|
console.log("获取第", currentPage.value, "页数据");
|
||||||
|
// 实际项目中调用API获取数据
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
currentPage.value = 1;
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 0 24px;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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: 120px;
|
||||||
|
|
||||||
|
: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;
|
||||||
|
width: 210px !important;
|
||||||
|
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-range-picker {
|
||||||
|
: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;
|
||||||
|
width: 210px !important;
|
||||||
|
|
||||||
|
.el-input__inner {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__suffix {
|
||||||
|
.el-icon {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-range-input) {
|
||||||
|
background: transparent;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-range-separator) {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格区域
|
||||||
|
.table-section {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0 24px;
|
||||||
|
|
||||||
|
:deep(.el-table) {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
.el-table__header-wrapper {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__body-wrapper {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__row {
|
||||||
|
width: 100% !important;
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(64, 169, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
background-color: rgba(30, 70, 120, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__cell {
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
.el-table__header {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.el-table__header .el-table__cell {
|
||||||
|
background-color: #1c4979;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预警等级标签
|
||||||
|
.warning-level-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
&.warning-red {
|
||||||
|
background-color: rgba(255, 77, 79, 0.2);
|
||||||
|
color: #ff4d4f;
|
||||||
|
border: 1px solid rgba(255, 77, 79, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning-orange {
|
||||||
|
background-color: rgba(255, 122, 0, 0.2);
|
||||||
|
color: #ff7a00;
|
||||||
|
border: 1px solid rgba(255, 122, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning-yellow {
|
||||||
|
background-color: rgba(250, 219, 20, 0.2);
|
||||||
|
color: #fadb14;
|
||||||
|
border: 1px solid rgba(250, 219, 20, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning-blue {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
color: #40a9ff;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 影响点数量
|
||||||
|
.impact-count {
|
||||||
|
color: #ff4d4f;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #ff7875;
|
||||||
|
text-shadow: 0 0 8px rgba(255, 77, 79, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
.pagination {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
:deep(.el-pagination) {
|
||||||
|
.el-pagination__total {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__sizes .el-input__inner {
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(30, 70, 120, 0.4);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__btn {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
background-color: rgba(64, 169, 255, 0.1);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover:not(.is-disabled) {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
border-color: rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__item {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
background-color: rgba(64, 169, 255, 0.1);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.2);
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover:not(.is-disabled) {
|
||||||
|
background-color: rgba(64, 169, 255, 0.2);
|
||||||
|
border-color: rgba(64, 169, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-color: #40a9ff;
|
||||||
|
border-color: #40a9ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__jump .el-input__inner {
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(30, 70, 120, 0.4);
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.el-table__body) {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
// 隐藏滚动条
|
||||||
|
:deep(.el-table__body-wrapper::-webkit-scrollbar) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-table__body-wrapper) {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
// 日期选择器弹出面板深色主题
|
||||||
|
.el-picker-panel {
|
||||||
|
background: rgba(20, 50, 90, 0.98) !important;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3) !important;
|
||||||
|
|
||||||
|
.el-picker-panel__content {
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
.el-date-table th {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
border-bottom-color: rgba(64, 169, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-date-table td {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
|
||||||
|
&.selected .el-date-table-cell {
|
||||||
|
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.today span {
|
||||||
|
color: #40a9ff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.in-range,
|
||||||
|
&.start-date,
|
||||||
|
&.end-date {
|
||||||
|
background: rgba(64, 169, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-picker-panel__footer {
|
||||||
|
border-top: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
background: rgba(30, 70, 120, 0.4);
|
||||||
|
border-color: rgba(64, 169, 255, 0.3);
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(64, 169, 255, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button--primary {
|
||||||
|
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: linear-gradient(135deg, #69c0ff 0%, #40a9ff 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table--fit .el-table__inner-wrapper:before {
|
||||||
|
width: 0% !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -79,6 +79,7 @@
|
|||||||
"
|
"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
<span class="ml_10">{{ row.level }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -465,7 +466,7 @@ onUnmounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
@ -537,7 +538,7 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.8);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
|
||||||
&.tag-red {
|
&.tag-red {
|
||||||
@ -606,7 +607,7 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
td.el-table__cell {
|
td.el-table__cell {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
padding: vw(5) vw(5);
|
padding: vw(5) vw(5);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,19 +41,27 @@ const loadMapData = async () => {
|
|||||||
try {
|
try {
|
||||||
// 初始化地图
|
// 初始化地图
|
||||||
|
|
||||||
// 本地测试用,注释掉部署用的代码
|
// 检查URL参数中是否有Map=dev
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const isDev = urlParams.get('Map') === 'dev';
|
||||||
|
|
||||||
|
let geoJsonData;
|
||||||
|
|
||||||
|
if (isDev) {
|
||||||
|
// 本地测试用
|
||||||
const response = await fetch(GEOJSON_URL)
|
const response = await fetch(GEOJSON_URL)
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`)
|
throw new Error(`HTTP error! status: ${response.status}`)
|
||||||
}
|
}
|
||||||
const geoJsonData = await response.json()
|
geoJsonData = await response.json()
|
||||||
|
} else {
|
||||||
// 部署需要放开注释
|
// 部署用
|
||||||
// const response = await axios.get('/aliyun-geo/bound/500000_full.json');
|
const response = await axios.get('/aliyun-geo/bound/500000_full.json');
|
||||||
// const geoJsonData = response.data;
|
geoJsonData = response.data;
|
||||||
// if (!geoJsonData) {
|
if (!geoJsonData) {
|
||||||
// throw new Error('地图数据为空');
|
throw new Error('地图数据为空');
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// // 处理行政区划变更:渝北区和江北区合并为两江新区
|
// // 处理行政区划变更:渝北区和江北区合并为两江新区
|
||||||
@ -164,16 +172,16 @@ const initMap = (geoJsonData) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 添加瓦片图层 - 使用深色样式
|
// 添加瓦片图层 - 使用深色样式
|
||||||
const tileLayer = new window.L.TileLayer(
|
// const tileLayer = new window.L.TileLayer(
|
||||||
"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
|
// "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
|
||||||
{
|
// {
|
||||||
attribution:
|
// attribution:
|
||||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
// '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||||
subdomains: "abcd",
|
// subdomains: "abcd",
|
||||||
maxZoom: 19,
|
// maxZoom: 19,
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
mapInstance.addLayer(tileLayer);
|
// mapInstance.addLayer(tileLayer);
|
||||||
|
|
||||||
// 添加 GeoJSON 图层
|
// 添加 GeoJSON 图层
|
||||||
geoJsonLayer = new window.L.GeoJSON(geoJsonData, {
|
geoJsonLayer = new window.L.GeoJSON(geoJsonData, {
|
||||||
|
|||||||
@ -1,371 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="ai-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="ai-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">AI预警处理结果</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 内容区域 -->
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<!-- AI处理前预警 -->
|
|
||||||
<div class="panel before-panel" style="background: linear-gradient(135deg, rgba(30, 80, 140, 0.6) 0%, rgba(20, 60, 110, 0.8) 100%);">
|
|
||||||
<div class="panel-title">AI处理前预警</div>
|
|
||||||
<div class="panel-content">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">发布单位:</span>
|
|
||||||
<span class="info-value">{{ beforeData.publishOrg }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">发布内容:</span>
|
|
||||||
<span class="info-value content-text">{{ beforeData.publishContent }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">生效时间:</span>
|
|
||||||
<span class="info-value">{{ beforeData.effectiveTime }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">失效时间:</span>
|
|
||||||
<span class="info-value">{{ beforeData.expireTime }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 中间AI标识 -->
|
|
||||||
<div class="ai-center">
|
|
||||||
<img class="ai-icon-img" src="../../../assets/RiskWarning_img/AI1@2x.png" alt="AI" />
|
|
||||||
<div class="ai-arrow">
|
|
||||||
<el-icon><DArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- AI处理后预警 -->
|
|
||||||
<div class="panel after-panel panel1" style="background: #2699FF">
|
|
||||||
<div class="panel-title" style="color:#fff">AI处理后预警</div>
|
|
||||||
<div class="panel-content">
|
|
||||||
<!-- 标签页 -->
|
|
||||||
<div class="tab-header">
|
|
||||||
<div
|
|
||||||
v-for="tab in tabs"
|
|
||||||
:key="tab.key"
|
|
||||||
class="tab-item"
|
|
||||||
:class="{ active: activeTab === tab.key }"
|
|
||||||
@click="activeTab = tab.key"
|
|
||||||
>
|
|
||||||
{{ tab.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 标签内容 -->
|
|
||||||
<div class="tab-content">
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">预警等级:</span>
|
|
||||||
<span class="info-value">{{ afterData.warningLevel }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">预警信息:</span>
|
|
||||||
<span class="info-value content-text">{{ afterData.warningInfo }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">预警详情:</span>
|
|
||||||
<span class="info-value content-text">{{ afterData.warningDetail }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, watch } from "vue";
|
|
||||||
import { Close, DArrowRight } from "@element-plus/icons-vue";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
aiData: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close"]);
|
|
||||||
|
|
||||||
// 标签页
|
|
||||||
const tabs = ref([
|
|
||||||
{ key: "frontline", label: "一线人员" },
|
|
||||||
{ key: "district", label: "区县人员" },
|
|
||||||
{ key: "handler", label: "处室人员" },
|
|
||||||
{ key: "leader", label: "中心领导" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
const activeTab = ref("frontline");
|
|
||||||
|
|
||||||
// AI处理前数据
|
|
||||||
const beforeData = ref({
|
|
||||||
publishOrg: "潼南区预警中心",
|
|
||||||
publishContent: '潼南区气象台2025年11月13日0时40分发布"暴雨蓝色预警信号",预计23日0:40-6:40,龙形、宝龙、上和、大佛、桂林、玉溪、米心、花岩、双江、古溪、群力、柏梓、崇龛、梓潼、太安等15个乡镇(街道)强降水趋于减弱,未来6小时累计雨量将达50~100毫米,最大小时雨强将达20~40毫米,局地伴有雷电、阵性大风,请各地注意防范。',
|
|
||||||
effectiveTime: "2025-11-13 00:31:30.0",
|
|
||||||
expireTime: "2025-11-13 00:31:30.0",
|
|
||||||
});
|
|
||||||
|
|
||||||
// AI处理后数据
|
|
||||||
const afterData = ref({
|
|
||||||
warningLevel: "重庆市潼南气象台发布大雾黄色预警[III级/较重]",
|
|
||||||
warningInfo: '潼南区区气象台发布暴雨红色预警,按照相关要求,启动I级防御响应,并请及时关注地质、水文等风险提示信息,落实主动封闭管控/"关停撒转"措施',
|
|
||||||
warningDetail: "请立即按照2小时一次频率对你管养的重点路段/重点部位进行巡查,重点巡查较高及以上风险路段、涉灾隐患点、地质条件复杂路段、临河临崖路段/两区三厂、大型设施设备、取弃土(渣)场、砂石料场、涉水桥梁、富水隧道、围堰、支架脚手架、高切坡、滑坡处置等部位,重点关注涉水桥梁基础及墩台、不良地质隧道、隧道洞口边仰坡及侧切结构、高陡边坡支挡防护以及防排水设施,发现异常情况,立即向上报告,采取紧急排危、告警阻拦、吹哨撒转等措施,并及时报送工作开展情况。",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal && props.aiData) {
|
|
||||||
Object.assign(beforeData.value, props.aiData.before);
|
|
||||||
Object.assign(afterData.value, props.aiData.after);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.ai-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ai-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 1000px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 内容区域
|
|
||||||
.content-wrapper {
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
align-items: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 面板
|
|
||||||
.panel {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 20px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: -1px;
|
|
||||||
left: -1px;
|
|
||||||
right: -1px;
|
|
||||||
bottom: -1px;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 1px;
|
|
||||||
background: linear-gradient(135deg, rgba(64, 169, 255, 0.5) 0%, transparent 50%, rgba(64, 169, 255, 0.5) 100%);
|
|
||||||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
||||||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
||||||
-webkit-mask-composite: xor;
|
|
||||||
mask-composite: exclude;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #40a9ff;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
border-bottom: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-content {
|
|
||||||
.info-item {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-label {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-value {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
line-height: 1.6;
|
|
||||||
|
|
||||||
&.content-text {
|
|
||||||
display: block;
|
|
||||||
margin-top: 6px;
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 中间AI标识
|
|
||||||
.ai-center {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 16px;
|
|
||||||
padding: 0 10px;
|
|
||||||
.ai-icon-img {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ai-icon {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #fff;
|
|
||||||
box-shadow: 0 4px 20px rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ai-arrow {
|
|
||||||
font-size: 32px;
|
|
||||||
color: #40a9ff;
|
|
||||||
animation: pulse 1.5s infinite;
|
|
||||||
|
|
||||||
:deep(.el-icon) {
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0%, 100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
opacity: 0.6;
|
|
||||||
transform: translateX(5px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签页
|
|
||||||
.tab-header {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
padding-bottom: 12px;
|
|
||||||
border-bottom: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
|
|
||||||
.tab-item {
|
|
||||||
padding: 6px 14px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
// background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
background: #163B6C;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
.info-item {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
376
packages/screen/src/views/RiskWarning/component/baseDialog.vue
Normal file
376
packages/screen/src/views/RiskWarning/component/baseDialog.vue
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="props.visible"
|
||||||
|
class="base-dialog-overlay"
|
||||||
|
:style="{ zIndex: props.zIndex }"
|
||||||
|
@click="handleOverlayClick"
|
||||||
|
>
|
||||||
|
<div class="base-dialog" @click.stop :style="{ maxWidth: `${props.maxWidth}px` }">
|
||||||
|
<!-- 四个角的装饰 -->
|
||||||
|
<div class="corner corner-top-left"></div>
|
||||||
|
<div class="corner corner-top-right"></div>
|
||||||
|
<div class="corner corner-bottom-left"></div>
|
||||||
|
<div class="corner corner-bottom-right"></div>
|
||||||
|
|
||||||
|
<!-- 标题栏 -->
|
||||||
|
<div class="dialog-header">
|
||||||
|
<div class="header-title">{{ props.title }}</div>
|
||||||
|
<div class="close-btn" @click="handleClose">
|
||||||
|
<el-icon><Close /></el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<div class="header-slot">
|
||||||
|
<slot name="header"></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 筛选区域 -->
|
||||||
|
<div class="filter-section" v-if="props.showFilter">
|
||||||
|
<slot name="filter"></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<div class="table-section" v-if="props.tableData.length > 0">
|
||||||
|
<el-table
|
||||||
|
:data="props.tableData"
|
||||||
|
:height="props.tableHeight"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="headerCellStyle"
|
||||||
|
:cell-style="cellStyle"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
v-for="column in props.tableColumns"
|
||||||
|
:key="column.prop"
|
||||||
|
:prop="column.prop"
|
||||||
|
:label="column.label"
|
||||||
|
>
|
||||||
|
<template v-if="column.slot" #default="{ row }">
|
||||||
|
<slot :name="column.slot" :row="row"></slot>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="pagination" v-if="props.showPagination && props.tableData.length > 0">
|
||||||
|
<el-pagination
|
||||||
|
:current-page="props.currentPage"
|
||||||
|
:page-size="props.pageSize"
|
||||||
|
:page-sizes="props.pageSizes"
|
||||||
|
:total="props.total"
|
||||||
|
background
|
||||||
|
layout="prev, pager, next, jumper, ->, total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { Close } from "@element-plus/icons-vue";
|
||||||
|
import { ElTable, ElTableColumn, ElPagination } from "element-plus";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "弹窗标题",
|
||||||
|
},
|
||||||
|
zIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: 1000,
|
||||||
|
},
|
||||||
|
maxWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 1000,
|
||||||
|
},
|
||||||
|
showFilter: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
showPagination: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
tableColumns: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
tableHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 300,
|
||||||
|
},
|
||||||
|
currentPage: {
|
||||||
|
type: Number,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
pageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 10,
|
||||||
|
},
|
||||||
|
pageSizes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [10, 20, 30, 40],
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible", "close", "size-change", "current-change", "update:current-page", "update:page-size"]);
|
||||||
|
|
||||||
|
// 关闭对话框
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("close");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击遮罩关闭
|
||||||
|
const handleOverlayClick = () => {
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
// 弹窗打开时的逻辑
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 分页操作
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
emit("update:page-size", val);
|
||||||
|
emit("size-change", val);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
emit("update:current-page", val);
|
||||||
|
emit("current-change", val);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格样式
|
||||||
|
const headerCellStyle = () => {
|
||||||
|
return {
|
||||||
|
backgroundColor: "#1D5194",
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: "14px",
|
||||||
|
fontWeight: "500",
|
||||||
|
textAlign: "center",
|
||||||
|
padding: "5px 0px",
|
||||||
|
border: "none",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const cellStyle = () => {
|
||||||
|
return {
|
||||||
|
backgroundColor: "#16334E",
|
||||||
|
color: "rgba(255, 255, 255, 0.85)",
|
||||||
|
fontSize: "13px",
|
||||||
|
textAlign: "center",
|
||||||
|
padding: "5px 0px",
|
||||||
|
border: "none",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.base-dialog-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
:deep(.el-table--small) {
|
||||||
|
background: #16334E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-dialog {
|
||||||
|
width: 80vw;
|
||||||
|
max-height: 80vh;
|
||||||
|
position: relative;
|
||||||
|
background: #16334e;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||||
|
// 四个角的装饰
|
||||||
|
.corner {
|
||||||
|
position: absolute;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #40a9ff;
|
||||||
|
z-index: 100;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
&.corner-top-left {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.corner-top-right {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
border-left: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.corner-bottom-left {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
border-right: none;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.corner-bottom-right {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
border-left: none;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标题栏
|
||||||
|
.dialog-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
background-image: url("../../../assets/RiskWarning_img/标题@2x.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: right;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
width: 50%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 20px;
|
||||||
|
transition: color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标题栏下方自定义插槽
|
||||||
|
.header-slot {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0 24px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 70vh;
|
||||||
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选区域
|
||||||
|
.filter-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格区域
|
||||||
|
.table-section {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 24px;
|
||||||
|
background: #16334E
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
.pagination {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #16334E;
|
||||||
|
|
||||||
|
:deep(.el-pagination) {
|
||||||
|
background: #16334E;
|
||||||
|
|
||||||
|
.el-pagination__total {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__sizes .el-input__inner {
|
||||||
|
background: #16334E;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__btn {
|
||||||
|
background: #16334E;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
|
||||||
|
&:hover:not(.is-disabled) {
|
||||||
|
background: rgba(64, 169, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__item {
|
||||||
|
background: #16334E;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
|
||||||
|
&:hover:not(.is-disabled) {
|
||||||
|
background: rgba(64, 169, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background: #40a9ff;
|
||||||
|
border-color: #40a9ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-pagination__jump .el-input__inner {
|
||||||
|
background: #16334E;
|
||||||
|
border: 1px solid rgba(64, 169, 255, 0.3);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,590 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="clearance-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="clearance-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">抢通情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">行政区域</span>
|
|
||||||
<el-select v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<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 v-model="filterForm.type" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<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 v-model="filterForm.controlMeasure" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="item in controlMeasureOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 50px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.region }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.routeNo }}</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<el-tooltip :content="item.stakeNo" placement="top" :show-after="500">
|
|
||||||
<span class="ellipsis-text">{{ item.stakeNo }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<el-tooltip :content="item.location" placement="top" :show-after="500">
|
|
||||||
<span class="ellipsis-text">{{ item.location }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 140px">{{ item.occurrenceTime }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.routeNo2 }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.type }}</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<span :class="['control-tag', getControlClass(item.controlMeasure)]">{{ item.controlMeasure }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="flex: 1">
|
|
||||||
<span class="detail-link" @click="handleDetail(item)">详情</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
上一个
|
|
||||||
</div>
|
|
||||||
<div class="page-numbers">
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-num"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
下一个
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close } from "@element-plus/icons-vue";
|
|
||||||
import { regionOptions, typeOptions, controlMeasureOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close", "detail"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
region: "",
|
|
||||||
type: "",
|
|
||||||
controlMeasure: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 行政区域选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 类型选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 管控措施选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "50px" },
|
|
||||||
{ label: "行政区域", width: "80px" },
|
|
||||||
{ label: "线路编号", width: "80px" },
|
|
||||||
{ label: "起止桩号", width: "100px" },
|
|
||||||
{ label: "路况位置", width: "100px" },
|
|
||||||
{ label: "发生时间", width: "140px" },
|
|
||||||
{ label: "线路编号", width: "80px" },
|
|
||||||
{ label: "类型", width: "80px" },
|
|
||||||
{ label: "管控措施", width: "100px" },
|
|
||||||
{ label: "操作", flex: "1" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
region: "巫溪县",
|
|
||||||
routeNo: "G242",
|
|
||||||
stakeNo: "336.800-338.850",
|
|
||||||
location: "三星乡五斗村",
|
|
||||||
occurrenceTime: "2025-08-11 04:53:42",
|
|
||||||
routeNo2: "G242",
|
|
||||||
type: "边坡坍塌",
|
|
||||||
controlMeasure: "全幅封闭",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
region: "万州区",
|
|
||||||
routeNo: "G242",
|
|
||||||
stakeNo: "338.800-338.850",
|
|
||||||
location: "三星乡五斗村",
|
|
||||||
occurrenceTime: "2025-08-11 04:53:42",
|
|
||||||
routeNo2: "G242",
|
|
||||||
type: "边坡坍塌",
|
|
||||||
controlMeasure: "正常通行",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
region: "沙坪坝区",
|
|
||||||
routeNo: "G319",
|
|
||||||
stakeNo: "120.500-122.000",
|
|
||||||
location: "沙坪坝镇",
|
|
||||||
occurrenceTime: "2025-08-10 14:30:00",
|
|
||||||
routeNo2: "G319",
|
|
||||||
type: "路面塌陷",
|
|
||||||
controlMeasure: "半幅封闭",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
region: "渝中区",
|
|
||||||
routeNo: "G212",
|
|
||||||
stakeNo: "88.200-89.100",
|
|
||||||
location: "渝中大道",
|
|
||||||
occurrenceTime: "2025-08-09 09:15:30",
|
|
||||||
routeNo2: "G212",
|
|
||||||
type: "桥梁损坏",
|
|
||||||
controlMeasure: "限制通行",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 5;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取管控措施样式类
|
|
||||||
const getControlClass = (measure) => {
|
|
||||||
const classMap = {
|
|
||||||
"全幅封闭": "control-close",
|
|
||||||
"半幅封闭": "control-half",
|
|
||||||
"正常通行": "control-normal",
|
|
||||||
"限制通行": "control-limit",
|
|
||||||
};
|
|
||||||
return classMap[measure] || "";
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 查看详情
|
|
||||||
const handleDetail = (item) => {
|
|
||||||
emit("detail", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.clearance-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clearance-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 1000px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
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: 120px;
|
|
||||||
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 16px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 14px 16px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.ellipsis-text {
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 管控措施标签
|
|
||||||
.control-tag {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.control-close {
|
|
||||||
background-color: rgba(255, 77, 79, 0.2);
|
|
||||||
color: #ff4d4f;
|
|
||||||
border: 1px solid rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.control-half {
|
|
||||||
background-color: rgba(255, 122, 0, 0.2);
|
|
||||||
color: #ff7a00;
|
|
||||||
border: 1px solid rgba(255, 122, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.control-normal {
|
|
||||||
background-color: rgba(82, 196, 26, 0.2);
|
|
||||||
color: #52c41a;
|
|
||||||
border: 1px solid rgba(82, 196, 26, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.control-limit {
|
|
||||||
background-color: rgba(250, 219, 20, 0.2);
|
|
||||||
color: #fadb14;
|
|
||||||
border: 1px solid rgba(250, 219, 20, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 详情链接
|
|
||||||
.detail-link {
|
|
||||||
color: #40a9ff;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 13px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #69c0ff;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
padding: 6px 16px;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-numbers {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-num {
|
|
||||||
min-width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,535 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="control-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="control-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">管控情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">行政区域</span>
|
|
||||||
<el-select v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<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 v-model="filterForm.riskLevel" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="item in riskLevelOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 60px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.region }}</div>
|
|
||||||
<div class="td" style="width: 200px">
|
|
||||||
<el-tooltip :content="item.stationName" placement="top" :show-after="500">
|
|
||||||
<span class="ellipsis-text">{{ item.stationName }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 200px">
|
|
||||||
<el-tooltip :content="item.project" placement="top" :show-after="500">
|
|
||||||
<span class="ellipsis-text">{{ item.project }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.peopleCount }}</div>
|
|
||||||
<div class="td" style="flex: 1">
|
|
||||||
<span :class="['risk-tag', getRiskClass(item.riskLevel)]">{{ item.riskLevel }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
上一个
|
|
||||||
</div>
|
|
||||||
<div class="page-numbers">
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-num"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
下一个
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close } from "@element-plus/icons-vue";
|
|
||||||
import { regionOptions, riskLevelOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
region: "",
|
|
||||||
riskLevel: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 行政区域选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 风险等级选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "60px" },
|
|
||||||
{ label: "行政区域", width: "100px" },
|
|
||||||
{ label: "驻地名称", width: "200px" },
|
|
||||||
{ label: "所属项目", width: "200px" },
|
|
||||||
{ label: "驻地人数", width: "80px" },
|
|
||||||
{ label: "驻地风险等级", flex: "1" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
region: "沙坪坝区",
|
|
||||||
stationName: "沙坪坝区S545茅山峡公路桥新建工程(渝黔铁路扩能改造工程)项目经理部",
|
|
||||||
project: "沙坪坝区S545茅山峡公路桥新建工程(渝黔铁路扩能改造工程)",
|
|
||||||
peopleCount: 21,
|
|
||||||
riskLevel: "Ⅳ级",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
region: "万州区",
|
|
||||||
stationName: "万州区项目经理部",
|
|
||||||
project: "万州区公路改造项目",
|
|
||||||
peopleCount: 15,
|
|
||||||
riskLevel: "Ⅲ级",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
region: "渝中区",
|
|
||||||
stationName: "渝中区桥梁维护项目部",
|
|
||||||
project: "渝中区桥梁维护工程",
|
|
||||||
peopleCount: 8,
|
|
||||||
riskLevel: "Ⅱ级",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
region: "江北区",
|
|
||||||
stationName: "江北区道路施工项目部",
|
|
||||||
project: "江北区道路施工项目",
|
|
||||||
peopleCount: 32,
|
|
||||||
riskLevel: "Ⅰ级",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 5;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取风险等级样式类
|
|
||||||
const getRiskClass = (level) => {
|
|
||||||
const classMap = {
|
|
||||||
"Ⅰ级": "risk-level-1",
|
|
||||||
"Ⅱ级": "risk-level-2",
|
|
||||||
"Ⅲ级": "risk-level-3",
|
|
||||||
"Ⅳ级": "risk-level-4",
|
|
||||||
};
|
|
||||||
return classMap[level] || "";
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.control-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.control-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 900px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
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: 140px;
|
|
||||||
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 16px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 14px 16px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.ellipsis-text {
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 风险等级标签
|
|
||||||
.risk-tag {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 12px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.risk-level-1 {
|
|
||||||
background-color: rgba(255, 77, 79, 0.2);
|
|
||||||
color: #ff4d4f;
|
|
||||||
border: 1px solid rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.risk-level-2 {
|
|
||||||
background-color: rgba(255, 122, 0, 0.2);
|
|
||||||
color: #ff7a00;
|
|
||||||
border: 1px solid rgba(255, 122, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.risk-level-3 {
|
|
||||||
background-color: rgba(250, 219, 20, 0.2);
|
|
||||||
color: #fadb14;
|
|
||||||
border: 1px solid rgba(250, 219, 20, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.risk-level-4 {
|
|
||||||
background-color: rgba(82, 196, 26, 0.2);
|
|
||||||
color: #52c41a;
|
|
||||||
border: 1px solid rgba(82, 196, 26, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
padding: 6px 16px;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-numbers {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-num {
|
|
||||||
min-width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,478 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="dispatch-detail-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="dispatch-detail-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">调度区县情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">行政区域</span>
|
|
||||||
<el-select v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<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 v-model="filterForm.type" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="item in typeOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 50px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.district }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.name }}</div>
|
|
||||||
<div class="td" style="width: 120px">{{ item.phone }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.type }}</div>
|
|
||||||
<div class="td" style="width: 140px">{{ item.role }}</div>
|
|
||||||
<div class="td" style="flex: 1">{{ item.dispatchTime }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
上一个
|
|
||||||
</div>
|
|
||||||
<div class="page-numbers">
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-num"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
下一个
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close } from "@element-plus/icons-vue";
|
|
||||||
import { regionOptions, typeOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
region: "",
|
|
||||||
type: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 行政区域选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 类型选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "50px" },
|
|
||||||
{ label: "区县/镇街", width: "100px" },
|
|
||||||
{ label: "姓名", width: "80px" },
|
|
||||||
{ label: "电话", width: "120px" },
|
|
||||||
{ label: "类型", width: "100px" },
|
|
||||||
{ label: "角色", width: "140px" },
|
|
||||||
{ label: "调度时间", flex: "1" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
district: "柏梓镇",
|
|
||||||
name: "赵海浪",
|
|
||||||
phone: "18623520681",
|
|
||||||
type: "交通主管部门",
|
|
||||||
role: "一般人员(路长履职)",
|
|
||||||
dispatchTime: "2025-08-11 04:53:42",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
district: "柏梓镇",
|
|
||||||
name: "赵海浪",
|
|
||||||
phone: "18623520681",
|
|
||||||
type: "公路机构",
|
|
||||||
role: "一般人员(路长履职)",
|
|
||||||
dispatchTime: "2025-08-11 04:53:42",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
district: "万州区",
|
|
||||||
name: "王鑫",
|
|
||||||
phone: "18623520682",
|
|
||||||
type: "养护站",
|
|
||||||
role: "站长",
|
|
||||||
dispatchTime: "2025-08-10 14:30:00",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
district: "沙坪坝区",
|
|
||||||
name: "李华",
|
|
||||||
phone: "18623520683",
|
|
||||||
type: "护路员",
|
|
||||||
role: "一般人员",
|
|
||||||
dispatchTime: "2025-08-09 09:15:30",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 5;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.dispatch-detail-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2100;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dispatch-detail-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 900px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
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: 140px;
|
|
||||||
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 16px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 14px 16px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
padding: 6px 16px;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-numbers {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-num {
|
|
||||||
min-width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,465 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="dispatch-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="dispatch-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">调度区县情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">行政区域</span>
|
|
||||||
<el-select v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="item in regionOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 60px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 120px">{{ item.region }}</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<span class="dispatch-count" @click="handleDispatchClick(item)">{{ item.dispatchCount }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="flex: 1">{{ item.lastDispatchTime }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
上一个
|
|
||||||
</div>
|
|
||||||
<div class="page-numbers">
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-num"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
下一个
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close } from "@element-plus/icons-vue";
|
|
||||||
import { regionOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close", "dispatchClick"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
region: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 行政区域选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "60px" },
|
|
||||||
{ label: "行政区域", width: "120px" },
|
|
||||||
{ label: "调度数", width: "100px" },
|
|
||||||
{ label: "最近调度时间", flex: "1" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
region: "重庆市",
|
|
||||||
dispatchCount: 1,
|
|
||||||
lastDispatchTime: "2025-08-11 04:53:42",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
region: "万州区",
|
|
||||||
dispatchCount: 1,
|
|
||||||
lastDispatchTime: "2025-08-11 04:53:42",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
region: "沙坪坝区",
|
|
||||||
dispatchCount: 3,
|
|
||||||
lastDispatchTime: "2025-08-10 16:20:15",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
region: "渝中区",
|
|
||||||
dispatchCount: 2,
|
|
||||||
lastDispatchTime: "2025-08-09 11:45:30",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 5;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击调度数
|
|
||||||
const handleDispatchClick = (item) => {
|
|
||||||
emit("dispatchClick", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.dispatch-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dispatch-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 700px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
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: 140px;
|
|
||||||
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 16px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 14px 16px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
// 调度数字
|
|
||||||
.dispatch-count {
|
|
||||||
color: #40a9ff;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #69c0ff;
|
|
||||||
text-shadow: 0 0 8px rgba(105, 192, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
padding: 6px 16px;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-numbers {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-num {
|
|
||||||
min-width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,655 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="impact-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="impact-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">影响点情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div></div>
|
|
||||||
|
|
||||||
<!-- 统计卡片 -->
|
|
||||||
<div class="stats-cards">
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响桥梁</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响边坡</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响隧道</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响项目</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.pointType" placeholder="影响点类型" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in pointTypeOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.pointLevel" placeholder="影响点等级" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in pointLevelOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.region" placeholder="行政区域" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in regionOptionsWithAll"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-button type="primary" class="search-btn" @click="handleSearch">
|
|
||||||
查询
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 50px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.region }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.pointType }}</div>
|
|
||||||
<div class="td" style="width: 180px">{{ item.pointLocation }}</div>
|
|
||||||
<div class="td" style="width: 90px">
|
|
||||||
<span class="level-tag" :class="item.levelClass">{{ item.pointLevel }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 130px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.trafficDept.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.trafficDept.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 110px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.roadOrg.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.roadOrg.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 110px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.maintenance.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.maintenance.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.roadKeeper.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.roadKeeper.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 60px">
|
|
||||||
<span class="detail-link" @click="handleDetail(item)">详情</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<span class="total">共{{ total }}条数据</span>
|
|
||||||
<div class="page-btns">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-btn"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
<el-icon><ArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close, ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
|
||||||
import { pointTypeOptions, pointLevelOptions, regionOptionsWithAll } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close", "detail"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
pointType: "",
|
|
||||||
pointLevel: "",
|
|
||||||
region: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "50px" },
|
|
||||||
{ label: "行政区域", width: "80px" },
|
|
||||||
{ label: "影响点类型", width: "80px" },
|
|
||||||
{ label: "影响点位置", width: "180px" },
|
|
||||||
{ label: "影响点等级", width: "90px" },
|
|
||||||
{ label: "交通主管部门负责人", width: "130px" },
|
|
||||||
{ label: "公路机构责任人", width: "110px" },
|
|
||||||
{ label: "养护站负责人", width: "110px" },
|
|
||||||
{ label: "护路员", width: "100px" },
|
|
||||||
{ label: "操作", width: "60px" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
region: "重庆市",
|
|
||||||
pointType: "边坡",
|
|
||||||
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
|
||||||
pointLevel: "一般隐患",
|
|
||||||
levelClass: "level-normal",
|
|
||||||
trafficDept: { name: "罗宸", phone: "17623865172" },
|
|
||||||
roadOrg: { name: "李海平", phone: "13708320801" },
|
|
||||||
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
|
||||||
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
region: "重庆市",
|
|
||||||
pointType: "边坡",
|
|
||||||
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
|
||||||
pointLevel: "一般隐患",
|
|
||||||
levelClass: "level-normal",
|
|
||||||
trafficDept: { name: "罗宸", phone: "17623865172" },
|
|
||||||
roadOrg: { name: "李海平", phone: "13708320801" },
|
|
||||||
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
|
||||||
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
region: "重庆市",
|
|
||||||
pointType: "边坡",
|
|
||||||
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
|
||||||
pointLevel: "一般隐患",
|
|
||||||
levelClass: "level-normal",
|
|
||||||
trafficDept: { name: "罗宸", phone: "17623865172" },
|
|
||||||
roadOrg: { name: "李海平", phone: "13708320801" },
|
|
||||||
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
|
||||||
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 4;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 查询
|
|
||||||
const handleSearch = () => {
|
|
||||||
console.log("查询条件:", filterForm.value);
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 查看详情
|
|
||||||
const handleDetail = (item) => {
|
|
||||||
emit("detail", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
// 视频屏幕自适应 - 基于视口宽度动态调整
|
|
||||||
@function vw($px) {
|
|
||||||
@return calc($px / 1920 * 100vw);
|
|
||||||
}
|
|
||||||
|
|
||||||
.impact-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.impact-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 1200px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: vw(12);
|
|
||||||
padding: vw(24);
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: vw(20);
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: vw(20);
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: vw(8) vw(40);
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: vw(2) solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: vw(32);
|
|
||||||
height: vw(32);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: vw(20);
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 统计卡片
|
|
||||||
.stats-cards {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: vw(16);
|
|
||||||
margin-bottom: vw(20);
|
|
||||||
|
|
||||||
.stat-card {
|
|
||||||
background: linear-gradient(135deg, rgba(30, 70, 120, 0.6) 0%, rgba(20, 50, 90, 0.8) 100%);
|
|
||||||
border: vw(2) solid rgba(64, 169, 255, 0.4);
|
|
||||||
border-radius: vw(8);
|
|
||||||
padding: vw(16) vw(20);
|
|
||||||
text-align: center;
|
|
||||||
transition: all 0.3s;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: rgba(64, 169, 255, 0.8);
|
|
||||||
box-shadow: 0 0 20px rgba(64, 169, 255, 0.3);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
|
||||||
font-size: vw(14);
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
margin-bottom: vw(8);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: vw(28);
|
|
||||||
font-weight: bold;
|
|
||||||
color: #40a9ff;
|
|
||||||
text-shadow: 0 0 10px rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: vw(20);
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 12px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-item {
|
|
||||||
.filter-select {
|
|
||||||
width: vw(150);
|
|
||||||
|
|
||||||
: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: vw(4);
|
|
||||||
|
|
||||||
.el-input__inner {
|
|
||||||
color: #fff;
|
|
||||||
font-size: vw(13);
|
|
||||||
|
|
||||||
&::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__suffix {
|
|
||||||
.el-icon {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-btn {
|
|
||||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border: none;
|
|
||||||
border-radius: vw(4);
|
|
||||||
padding: 0 vw(24);
|
|
||||||
height: vw(32);
|
|
||||||
font-size: vw(13);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: linear-gradient(135deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: vw(8);
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: vw(20);
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: vw(12) vw(16);
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: vw(13);
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: vw(12) vw(16);
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
min-height: vw(60);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: vw(12);
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
word-break: break-all;
|
|
||||||
padding: 0 vw(4);
|
|
||||||
|
|
||||||
.level-tag {
|
|
||||||
display: inline-block;
|
|
||||||
padding: vw(2) vw(8);
|
|
||||||
border-radius: vw(4);
|
|
||||||
font-size: vw(11);
|
|
||||||
|
|
||||||
&.level-normal {
|
|
||||||
background-color: rgba(250, 219, 95, 0.2);
|
|
||||||
color: #fadb5f;
|
|
||||||
border: 1px solid rgba(250, 219, 95, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.level-serious {
|
|
||||||
background-color: rgba(255, 77, 79, 0.2);
|
|
||||||
color: #ff4d4f;
|
|
||||||
border: 1px solid rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: vw(2);
|
|
||||||
|
|
||||||
.person-name {
|
|
||||||
font-size: vw(12);
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-phone {
|
|
||||||
font-size: vw(11);
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-link {
|
|
||||||
color: #40a9ff;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: vw(12);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #69c0ff;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: vw(16);
|
|
||||||
|
|
||||||
.total {
|
|
||||||
font-size: vw(13);
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-btns {
|
|
||||||
display: flex;
|
|
||||||
gap: vw(8);
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
min-width: vw(28);
|
|
||||||
height: vw(28);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
border-radius: vw(4);
|
|
||||||
font-size: vw(12);
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled):not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: vw(6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: vw(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: vw(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下拉菜单样式
|
|
||||||
:deep(.el-select-dropdown) {
|
|
||||||
background-color: rgba(20, 50, 90, 0.98);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
|
|
||||||
.el-select-dropdown__item {
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: rgba(64, 169, 255, 0.3);
|
|
||||||
color: #40a9ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,516 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="response-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="response-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">潼南三级路长明细</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 统计数据卡片 -->
|
|
||||||
<div class="stats-cards">
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="card-icon">
|
|
||||||
<el-icon class="stat-icon"><User /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="card-info">
|
|
||||||
<div class="card-label">路长总人数</div>
|
|
||||||
<div class="card-value">
|
|
||||||
<span class="value-num">{{ stats.total }}</span>
|
|
||||||
<span class="value-unit">人</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="card-icon">
|
|
||||||
<el-icon class="stat-icon"><OfficeBuilding /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="card-info">
|
|
||||||
<div class="card-label">县级路长</div>
|
|
||||||
<div class="card-value">
|
|
||||||
<span class="value-num">{{ stats.county }}</span>
|
|
||||||
<span class="value-unit">公里</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="card-icon">
|
|
||||||
<el-icon class="stat-icon"><MapLocation /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="card-info">
|
|
||||||
<div class="card-label">乡、村路长</div>
|
|
||||||
<div class="card-value">
|
|
||||||
<span class="value-num">{{ stats.village }}</span>
|
|
||||||
<span class="value-unit">次</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 60px">{{ index + 1 }}</div>
|
|
||||||
<div class="td" style="width: 120px">{{ item.district }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.name }}</div>
|
|
||||||
<div class="td" style="width: 120px">{{ item.phone }}</div>
|
|
||||||
<div class="td" style="flex: 1">{{ item.role }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.position }}</div>
|
|
||||||
<div class="td" style="width: 120px">
|
|
||||||
<div class="action-btns">
|
|
||||||
<div class="action-btn" @click="handleView(item)">
|
|
||||||
<el-icon><VideoCamera /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="action-btn" @click="handleVoice(item)">
|
|
||||||
<el-icon><Microphone /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div class="action-btn" @click="handleCall(item)">
|
|
||||||
<el-icon><Phone /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<span class="total">共{{ total }}条数据</span>
|
|
||||||
<div class="page-btns">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-btn"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
<el-icon><ArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close, VideoCamera, Microphone, Phone, ArrowLeft, ArrowRight, User, OfficeBuilding, MapLocation } from "@element-plus/icons-vue";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close"]);
|
|
||||||
|
|
||||||
// 统计数据
|
|
||||||
const stats = ref({
|
|
||||||
total: 1127,
|
|
||||||
county: 216,
|
|
||||||
village: 1099,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "60px" },
|
|
||||||
{ label: "区县/镇街", width: "120px" },
|
|
||||||
{ label: "姓名", width: "100px" },
|
|
||||||
{ label: "电话", width: "120px" },
|
|
||||||
{ label: "角色", flex: "1" },
|
|
||||||
{ label: "职务", width: "100px" },
|
|
||||||
{ label: "操作", width: "120px" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{ id: 1, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 2, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 3, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 4, district: "万州区柏梓镇", name: "赵海浪", phone: "1862352068", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 5, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 6, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 7, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 8, district: "万州区李河镇", name: "王建国", phone: "1398324567", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 9, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 10, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 11, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
{ id: 12, district: "万州区分水镇", name: "刘志强", phone: "1387654321", role: "一般人员(路长履职)", position: "其他" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 4;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 操作按钮
|
|
||||||
const handleView = (item) => {
|
|
||||||
console.log("查看视频:", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleVoice = (item) => {
|
|
||||||
console.log("语音通话:", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCall = (item) => {
|
|
||||||
console.log("拨打电话:", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.response-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-dialog {
|
|
||||||
width: 70vw;
|
|
||||||
max-width: 700px;
|
|
||||||
max-height: 80vh;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 16px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 4px 24px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 16px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 统计卡片
|
|
||||||
.stats-cards {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
.stat-card {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
background: linear-gradient(135deg, rgba(30, 80, 140, 0.6) 0%, rgba(20, 60, 110, 0.8) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 10px 12px;
|
|
||||||
|
|
||||||
.card-icon {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.15);
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
.stat-icon {
|
|
||||||
font-size: 18px;
|
|
||||||
color: #40a9ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-info {
|
|
||||||
.card-label {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
margin-bottom: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-value {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: 2px;
|
|
||||||
|
|
||||||
.value-num {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #40a9ff;
|
|
||||||
text-shadow: 0 0 6px rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-unit {
|
|
||||||
font-size: 10px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 8px 12px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 30vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 10px 12px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.action-btns {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.action-btn {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.15);
|
|
||||||
border-radius: 2px;
|
|
||||||
color: #40a9ff;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.3);
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 10px;
|
|
||||||
|
|
||||||
.total {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-btns {
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
min-width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
border-radius: 2px;
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled):not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 2px;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条角落
|
|
||||||
.table-body::-webkit-scrollbar-corner {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,697 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
v-if="visible"
|
|
||||||
class="response-status-dialog-overlay"
|
|
||||||
@click="handleOverlayClick"
|
|
||||||
>
|
|
||||||
<div class="response-status-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">响应情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 统计卡片 -->
|
|
||||||
<div class="stats-cards">
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响桥梁</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响边坡</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响隧道</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
<div class="stat-card">
|
|
||||||
<div class="stat-label">影响项目</div>
|
|
||||||
<div class="stat-value">2933</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select
|
|
||||||
v-model="filterForm.pointType"
|
|
||||||
placeholder="影响点类型"
|
|
||||||
class="filter-select"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="option in pointTypeOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select
|
|
||||||
v-model="filterForm.pointLevel"
|
|
||||||
placeholder="影响点等级"
|
|
||||||
class="filter-select"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="option in pointLevelOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select
|
|
||||||
v-model="filterForm.isResponded"
|
|
||||||
placeholder="是否回应"
|
|
||||||
class="filter-select"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="option in isRespondedOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 50px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.pointType }}</div>
|
|
||||||
<div class="td" style="width: 150px">{{ item.pointLocation }}</div>
|
|
||||||
<div class="td" style="width: 90px">
|
|
||||||
<span class="level-tag" :class="item.levelClass">{{
|
|
||||||
item.pointLevel
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 60px">{{ item.checkCount }}</div>
|
|
||||||
<div class="td" style="width: 120px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.trafficDept.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.trafficDept.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 110px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.roadOrg.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.roadOrg.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 110px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.maintenance.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.maintenance.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 80px">
|
|
||||||
<div class="person-info">
|
|
||||||
<span class="person-name">{{ item.roadKeeper.name }}</span>
|
|
||||||
<span class="person-phone">{{ item.roadKeeper.phone }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 70px">
|
|
||||||
<span class="response-status" :class="item.responseClass">{{
|
|
||||||
item.responseStatus
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 110px">
|
|
||||||
<div class="time-info">
|
|
||||||
<span class="time-date">{{ item.urgeTime.date }}</span>
|
|
||||||
<span class="time-clock">{{ item.urgeTime.time }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 50px">
|
|
||||||
<span class="detail-link" @click="handleDetail(item)">详情</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<span class="total">共{{ total }}条数据</span>
|
|
||||||
<div class="page-btns">
|
|
||||||
<div
|
|
||||||
class="page-btn"
|
|
||||||
:class="{ disabled: currentPage === 1 }"
|
|
||||||
@click="prevPage"
|
|
||||||
>
|
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-btn"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="page-btn"
|
|
||||||
:class="{ disabled: currentPage === totalPages }"
|
|
||||||
@click="nextPage"
|
|
||||||
>
|
|
||||||
<el-icon><ArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close, ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
|
||||||
import { pointTypeOptions, pointLevelOptions, isRespondedOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close", "detail"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
pointType: "",
|
|
||||||
pointLevel: "",
|
|
||||||
isResponded: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "50px" },
|
|
||||||
{ label: "影响点类型", width: "80px" },
|
|
||||||
{ label: "影响点位置", width: "150px" },
|
|
||||||
{ label: "影响点等级", width: "90px" },
|
|
||||||
{ label: "查次数", width: "60px" },
|
|
||||||
{ label: "交通主管部门负责人", width: "120px" },
|
|
||||||
{ label: "公路机构责任人", width: "110px" },
|
|
||||||
{ label: "养护站负责人", width: "110px" },
|
|
||||||
{ label: "护路员", width: "80px" },
|
|
||||||
{ label: "回应状态", width: "70px" },
|
|
||||||
{ label: "最新催告时间", width: "110px" },
|
|
||||||
{ label: "操作", width: "50px" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
pointType: "边坡",
|
|
||||||
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
|
||||||
pointLevel: "一般隐患",
|
|
||||||
levelClass: "level-normal",
|
|
||||||
checkCount: 2,
|
|
||||||
trafficDept: { name: "罗宸", phone: "17623865172" },
|
|
||||||
roadOrg: { name: "李海平", phone: "1372386532" },
|
|
||||||
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
|
||||||
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
|
||||||
responseStatus: "已回应",
|
|
||||||
responseClass: "status-responded",
|
|
||||||
urgeTime: { date: "2026-03-28", time: "12:30:00" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 12,
|
|
||||||
pointType: "边坡",
|
|
||||||
pointLocation: "武汉-大理(K1452+951至K1462+209)",
|
|
||||||
pointLevel: "一般隐患",
|
|
||||||
levelClass: "level-normal",
|
|
||||||
checkCount: 2,
|
|
||||||
trafficDept: { name: "罗宸", phone: "17623865172" },
|
|
||||||
roadOrg: { name: "李海平", phone: "1372386532" },
|
|
||||||
maintenance: { name: "苏祖兵", phone: "13594331090" },
|
|
||||||
roadKeeper: { name: "凌承礼", phone: "1592393704" },
|
|
||||||
responseStatus: "已回应",
|
|
||||||
responseClass: "status-responded",
|
|
||||||
urgeTime: { date: "2026-03-28", time: "12:30:00" },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
tableData.value.push(...tableData.value);
|
|
||||||
tableData.value.push(...tableData.value);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 4;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 查看详情
|
|
||||||
const handleDetail = (item) => {
|
|
||||||
emit("detail", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.response-status-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-status-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 1150px;
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(20, 50, 90, 0.95) 0%,
|
|
||||||
rgba(10, 30, 60, 0.98) 100%
|
|
||||||
);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
transparent 0%,
|
|
||||||
rgba(64, 169, 255, 0.2) 20%,
|
|
||||||
rgba(64, 169, 255, 0.2) 80%,
|
|
||||||
transparent 100%
|
|
||||||
);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-item {
|
|
||||||
.filter-select {
|
|
||||||
width: 150px;
|
|
||||||
|
|
||||||
: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.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__suffix {
|
|
||||||
.el-icon {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 0;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 200px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 12px 0px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
.level-tag {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
|
|
||||||
&.level-normal {
|
|
||||||
background-color: rgba(250, 219, 95, 0.2);
|
|
||||||
color: #fadb5f;
|
|
||||||
border: 1px solid rgba(250, 219, 95, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.level-serious {
|
|
||||||
background-color: rgba(255, 77, 79, 0.2);
|
|
||||||
color: #ff4d4f;
|
|
||||||
border: 1px solid rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
|
|
||||||
.person-name {
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-phone {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.response-status {
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
&.status-responded {
|
|
||||||
color: #52c41a;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.status-unresponded {
|
|
||||||
color: #ff7a45;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
|
|
||||||
.time-date {
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-clock {
|
|
||||||
font-size: 11px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.detail-link {
|
|
||||||
color: #40a9ff;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #69c0ff;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 16px;
|
|
||||||
|
|
||||||
.total {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-btns {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
min-width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled):not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下拉菜单样式
|
|
||||||
:deep(.el-select-dropdown) {
|
|
||||||
background-color: rgba(20, 50, 90, 0.98);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
|
|
||||||
.el-select-dropdown__item {
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: rgba(64, 169, 255, 0.3);
|
|
||||||
color: #40a9ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 统计卡片
|
|
||||||
.stats-cards {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: 16px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.stat-card {
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(30, 70, 120, 0.6) 0%,
|
|
||||||
rgba(20, 50, 90, 0.8) 100%
|
|
||||||
);
|
|
||||||
border: 2px solid rgba(64, 169, 255, 0.4);
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 8px 20px;
|
|
||||||
text-align: center;
|
|
||||||
transition: all 0.3s;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: rgba(64, 169, 255, 0.8);
|
|
||||||
box-shadow: 0 0 20px rgba(64, 169, 255, 0.3);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
|
||||||
font-size: 14px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #40a9ff;
|
|
||||||
text-shadow: 0 0 10px rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,665 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="warning-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="warning-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">响应情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.warningLevel" placeholder="预警等级" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in warningLevelOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.region" placeholder="行政区域" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in regionOptionsWithAll"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.isEnded" placeholder="是否结束" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in isEndedOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-select v-model="filterForm.isResponded" placeholder="是否回应" class="filter-select">
|
|
||||||
<el-option
|
|
||||||
v-for="option in isRespondedOptions"
|
|
||||||
:key="option.value"
|
|
||||||
:label="option.label"
|
|
||||||
:value="option.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<el-button type="primary" class="search-btn" @click="handleSearch">
|
|
||||||
<el-icon><Search /></el-icon>
|
|
||||||
查询
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 60px">{{ index + 1 }}</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<span class="warning-level" :class="item.levelClass">{{ item.warningLevel }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.region }}</div>
|
|
||||||
<div class="td" style="width: 160px">{{ item.warningTime }}</div>
|
|
||||||
<div class="td" style="width: 160px">{{ item.endTime }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.impactPoints }}</div>
|
|
||||||
<div class="td clickable-cell" style="width: 80px" @click.stop="handleCalledClick(item)">{{ item.called }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.responded }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.notResponded }}</div>
|
|
||||||
<div class="td" style="width: 80px">{{ item.urged }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<span class="total">共{{ total }}条数据</span>
|
|
||||||
<div class="page-btns">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
<el-icon><ArrowLeft /></el-icon>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-btn"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
<el-icon><ArrowRight /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close, Search, ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
|
||||||
import { warningLevelOptions, regionOptionsWithAll, isEndedOptions, isRespondedOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close", "openImpactPoint"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
warningLevel: "",
|
|
||||||
region: "",
|
|
||||||
isEnded: "",
|
|
||||||
isResponded: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "60px" },
|
|
||||||
{ label: "预警等级", width: "100px" },
|
|
||||||
{ label: "行政区域", width: "100px" },
|
|
||||||
{ label: "预警时间", width: "160px" },
|
|
||||||
{ label: "结束时间", width: "160px" },
|
|
||||||
{ label: "影响点数量", width: "100px" },
|
|
||||||
{ label: "已叫应", width: "80px" },
|
|
||||||
{ label: "已回应", width: "80px" },
|
|
||||||
{ label: "未回应", width: "80px" },
|
|
||||||
{ label: "已催告", width: "80px" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
levelClass: "level-red",
|
|
||||||
region: "万州区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 4,
|
|
||||||
called: 2,
|
|
||||||
responded: 2,
|
|
||||||
notResponded: 2,
|
|
||||||
urged: 22,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
warningLevel: "橙色预警",
|
|
||||||
levelClass: "level-orange",
|
|
||||||
region: "涪陵区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 18,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
levelClass: "level-red",
|
|
||||||
region: "万盛区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
warningLevel: "黄色预警",
|
|
||||||
levelClass: "level-yellow",
|
|
||||||
region: "长寿区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 20,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
levelClass: "level-red",
|
|
||||||
region: "城口区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
levelClass: "level-red",
|
|
||||||
region: "城口区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
levelClass: "level-red",
|
|
||||||
region: "城口区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
levelClass: "level-red",
|
|
||||||
region: "城口区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactPoints: 0,
|
|
||||||
called: 0,
|
|
||||||
responded: 0,
|
|
||||||
notResponded: 0,
|
|
||||||
urged: 15,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 4;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击已叫应
|
|
||||||
const handleCalledClick = () => {
|
|
||||||
emit("responseStatus");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 查询
|
|
||||||
const handleSearch = () => {
|
|
||||||
console.log("查询条件:", filterForm.value);
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.warning-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 1000px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-item {
|
|
||||||
.filter-select {
|
|
||||||
width: 120px;
|
|
||||||
|
|
||||||
: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.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__suffix {
|
|
||||||
.el-icon {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-btn {
|
|
||||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 0 20px;
|
|
||||||
height: 32px;
|
|
||||||
font-size: 13px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: linear-gradient(135deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 16px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #69c0ff;
|
|
||||||
text-shadow: 0 0 8px rgba(105, 192, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 280px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 12px 16px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&.clickable-cell {
|
|
||||||
cursor: pointer;
|
|
||||||
color: #40a9ff;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #69c0ff;
|
|
||||||
text-shadow: 0 0 8px rgba(105, 192, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning-level {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.level-red {
|
|
||||||
background-color: rgba(255, 77, 79, 0.2);
|
|
||||||
color: #ff4d4f;
|
|
||||||
border: 1px solid rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.level-orange {
|
|
||||||
background-color: rgba(255, 122, 69, 0.2);
|
|
||||||
color: #ff7a45;
|
|
||||||
border: 1px solid rgba(255, 122, 69, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.level-yellow {
|
|
||||||
background-color: rgba(250, 219, 95, 0.2);
|
|
||||||
color: #fadb5f;
|
|
||||||
border: 1px solid rgba(250, 219, 95, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.level-blue {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
color: #40a9ff;
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 16px;
|
|
||||||
|
|
||||||
.total {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-btns {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
min-width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled):not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-corner {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下拉菜单样式
|
|
||||||
:deep(.el-select-dropdown) {
|
|
||||||
background-color: rgba(20, 50, 90, 0.98);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
|
|
||||||
.el-select-dropdown__item {
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
background-color: rgba(64, 169, 255, 0.3);
|
|
||||||
color: #40a9ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,676 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-if="visible" class="warning-dialog-overlay" @click="handleOverlayClick">
|
|
||||||
<div class="warning-dialog" @click.stop>
|
|
||||||
<!-- 标题栏 -->
|
|
||||||
<div class="dialog-header">
|
|
||||||
<div class="header-title">预警情况</div>
|
|
||||||
<div class="close-btn" @click="handleClose">
|
|
||||||
<el-icon><Close /></el-icon>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区域 -->
|
|
||||||
<div class="filter-section">
|
|
||||||
<div class="filter-row">
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">预警等级</span>
|
|
||||||
<el-select v-model="filterForm.warningLevel" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="item in warningLevelOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">行政区域</span>
|
|
||||||
<el-select v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<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 v-model="filterForm.isEnded" placeholder="请选择" class="filter-select" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="item in isEndedOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
<div class="filter-item">
|
|
||||||
<span class="filter-label">时间范围</span>
|
|
||||||
<el-date-picker
|
|
||||||
v-model="filterForm.dateRange"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="至"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
class="date-range-picker"
|
|
||||||
width="210px"
|
|
||||||
style="width: 210px"
|
|
||||||
clearable
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 数据表格 -->
|
|
||||||
<div class="table-section">
|
|
||||||
<div class="table-header">
|
|
||||||
<div
|
|
||||||
v-for="(column, index) in tableColumns"
|
|
||||||
:key="index"
|
|
||||||
class="th"
|
|
||||||
:style="{ width: column.width, flex: column.flex || 'none' }"
|
|
||||||
>
|
|
||||||
{{ column.label }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-body">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in tableData"
|
|
||||||
:key="item.id"
|
|
||||||
class="table-row"
|
|
||||||
:class="{ 'row-even': index % 2 === 1 }"
|
|
||||||
>
|
|
||||||
<div class="td" style="width: 50px">{{ item.id }}</div>
|
|
||||||
<div class="td" style="width: 100px">
|
|
||||||
<span :class="['warning-level-tag', getWarningClass(item.warningLevel)]">{{ item.warningLevel }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.weatherType }}</div>
|
|
||||||
<div class="td" style="width: 100px">{{ item.region }}</div>
|
|
||||||
<div class="td" style="width: 160px">{{ item.warningTime }}</div>
|
|
||||||
<div class="td" style="width: 160px">{{ item.endTime }}</div>
|
|
||||||
<div class="td" style="flex: 1">
|
|
||||||
<span class="impact-count" @click="handleImpactClick(item)">{{ item.impactCount }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 分页 -->
|
|
||||||
<div class="pagination">
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === 1 }" @click="prevPage">
|
|
||||||
上一个
|
|
||||||
</div>
|
|
||||||
<div class="page-numbers">
|
|
||||||
<div
|
|
||||||
v-for="page in visiblePages"
|
|
||||||
:key="page"
|
|
||||||
class="page-num"
|
|
||||||
:class="{ active: currentPage === page }"
|
|
||||||
@click="goToPage(page)"
|
|
||||||
>
|
|
||||||
{{ page }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="page-btn" :class="{ disabled: currentPage === totalPages }" @click="nextPage">
|
|
||||||
下一个
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watch } from "vue";
|
|
||||||
import { Close } from "@element-plus/icons-vue";
|
|
||||||
import { warningLevelOptions, regionOptions, isEndedOptions } from "./index.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "close", "impactClick"]);
|
|
||||||
|
|
||||||
// 筛选表单
|
|
||||||
const filterForm = ref({
|
|
||||||
warningLevel: "",
|
|
||||||
region: "",
|
|
||||||
isEnded: "",
|
|
||||||
dateRange: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
// 预警等级选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 行政区域选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 是否结束选项
|
|
||||||
// 已从 index.js 导入
|
|
||||||
|
|
||||||
// 表格列配置
|
|
||||||
const tableColumns = ref([
|
|
||||||
{ label: "序号", width: "50px" },
|
|
||||||
{ label: "预警等级", width: "100px" },
|
|
||||||
{ label: "气象类型", width: "100px" },
|
|
||||||
{ label: "行政区域", width: "100px" },
|
|
||||||
{ label: "预警时间", width: "160px" },
|
|
||||||
{ label: "结束时间", width: "160px" },
|
|
||||||
{ label: "影响点数量", flex: "1" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 表格数据
|
|
||||||
const tableData = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
warningLevel: "红色预警",
|
|
||||||
weatherType: "暴雨",
|
|
||||||
region: "重庆市",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactCount: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
warningLevel: "橙色预警",
|
|
||||||
weatherType: "暴雨",
|
|
||||||
region: "万州区",
|
|
||||||
warningTime: "2025-08-11 04:53:42",
|
|
||||||
endTime: "2025-08-11 04:53:42",
|
|
||||||
impactCount: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
warningLevel: "黄色预警",
|
|
||||||
weatherType: "大风",
|
|
||||||
region: "沙坪坝区",
|
|
||||||
warningTime: "2025-08-10 16:20:15",
|
|
||||||
endTime: "2025-08-10 20:30:00",
|
|
||||||
impactCount: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
warningLevel: "蓝色预警",
|
|
||||||
weatherType: "雷电",
|
|
||||||
region: "渝中区",
|
|
||||||
warningTime: "2025-08-09 09:15:30",
|
|
||||||
endTime: "2025-08-09 12:00:00",
|
|
||||||
impactCount: 2,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const pageSize = ref(10);
|
|
||||||
const total = ref(36);
|
|
||||||
|
|
||||||
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
||||||
|
|
||||||
const visiblePages = computed(() => {
|
|
||||||
const pages = [];
|
|
||||||
const maxVisible = 5;
|
|
||||||
let start = Math.max(1, currentPage.value - Math.floor(maxVisible / 2));
|
|
||||||
let end = Math.min(totalPages.value, start + maxVisible - 1);
|
|
||||||
|
|
||||||
if (end - start + 1 < maxVisible) {
|
|
||||||
start = Math.max(1, end - maxVisible + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = start; i <= end; i++) {
|
|
||||||
pages.push(i);
|
|
||||||
}
|
|
||||||
return pages;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取预警等级样式类
|
|
||||||
const getWarningClass = (level) => {
|
|
||||||
const classMap = {
|
|
||||||
"红色预警": "warning-red",
|
|
||||||
"橙色预警": "warning-orange",
|
|
||||||
"黄色预警": "warning-yellow",
|
|
||||||
"蓝色预警": "warning-blue",
|
|
||||||
};
|
|
||||||
return classMap[level] || "";
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭对话框
|
|
||||||
const handleClose = () => {
|
|
||||||
emit("update:visible", false);
|
|
||||||
emit("close");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击遮罩关闭
|
|
||||||
const handleOverlayClick = () => {
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 点击影响点数量
|
|
||||||
const handleImpactClick = (item) => {
|
|
||||||
emit("impactClick", item);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分页操作
|
|
||||||
const prevPage = () => {
|
|
||||||
if (currentPage.value > 1) {
|
|
||||||
currentPage.value--;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextPage = () => {
|
|
||||||
if (currentPage.value < totalPages.value) {
|
|
||||||
currentPage.value++;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const goToPage = (page) => {
|
|
||||||
currentPage.value = page;
|
|
||||||
fetchData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取数据
|
|
||||||
const fetchData = () => {
|
|
||||||
console.log("获取第", currentPage.value, "页数据");
|
|
||||||
// 实际项目中调用API获取数据
|
|
||||||
};
|
|
||||||
|
|
||||||
// 监听visible变化
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
currentPage.value = 1;
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.warning-dialog-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning-dialog {
|
|
||||||
width: 80vw;
|
|
||||||
max-width: 900px;
|
|
||||||
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标题栏
|
|
||||||
.dialog-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.header-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #fff;
|
|
||||||
padding: 8px 40px;
|
|
||||||
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
|
|
||||||
border-bottom: 2px solid #40a9ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 20px;
|
|
||||||
transition: color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选区域
|
|
||||||
.filter-section {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
.filter-row {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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: 120px;
|
|
||||||
|
|
||||||
: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;
|
|
||||||
width: 210px !important;
|
|
||||||
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-range-picker {
|
|
||||||
: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;
|
|
||||||
width: 210px !important;
|
|
||||||
|
|
||||||
.el-input__inner {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 13px;
|
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
&::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__suffix {
|
|
||||||
.el-icon {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-range-input) {
|
|
||||||
background: transparent;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 13px;
|
|
||||||
|
|
||||||
&::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-range-separator) {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表格区域
|
|
||||||
.table-section {
|
|
||||||
background-color: rgba(30, 70, 120, 0.3);
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: flex;
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
padding: 12px 16px;
|
|
||||||
|
|
||||||
.th {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body {
|
|
||||||
max-height: 320px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: flex;
|
|
||||||
padding: 14px 16px;
|
|
||||||
align-items: center;
|
|
||||||
transition: background-color 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row-even {
|
|
||||||
background-color: rgba(30, 70, 120, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.td {
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.85);
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
// 预警等级标签
|
|
||||||
.warning-level-tag {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.warning-red {
|
|
||||||
background-color: rgba(255, 77, 79, 0.2);
|
|
||||||
color: #ff4d4f;
|
|
||||||
border: 1px solid rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.warning-orange {
|
|
||||||
background-color: rgba(255, 122, 0, 0.2);
|
|
||||||
color: #ff7a00;
|
|
||||||
border: 1px solid rgba(255, 122, 0, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.warning-yellow {
|
|
||||||
background-color: rgba(250, 219, 20, 0.2);
|
|
||||||
color: #fadb14;
|
|
||||||
border: 1px solid rgba(250, 219, 20, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.warning-blue {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
color: #40a9ff;
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 影响点数量
|
|
||||||
.impact-count {
|
|
||||||
color: #ff4d4f;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #ff7875;
|
|
||||||
text-shadow: 0 0 8px rgba(255, 77, 79, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
.pagination {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-btn {
|
|
||||||
padding: 6px 16px;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.disabled) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-numbers {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
|
|
||||||
.page-num {
|
|
||||||
min-width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: rgba(64, 169, 255, 0.1);
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
&:hover:not(.active) {
|
|
||||||
background-color: rgba(64, 169, 255, 0.2);
|
|
||||||
border-color: rgba(64, 169, 255, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
background-color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 滚动条样式
|
|
||||||
.table-body::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-track {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb {
|
|
||||||
background: linear-gradient(180deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-body::-webkit-scrollbar-thumb:hover {
|
|
||||||
background: linear-gradient(180deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
// 日期选择器弹出面板深色主题
|
|
||||||
.el-picker-panel {
|
|
||||||
background: rgba(20, 50, 90, 0.98) !important;
|
|
||||||
border: 1px solid rgba(64, 169, 255, 0.3) !important;
|
|
||||||
|
|
||||||
.el-picker-panel__content {
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
.el-date-table th {
|
|
||||||
color: rgba(255, 255, 255, 0.6);
|
|
||||||
border-bottom-color: rgba(64, 169, 255, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-date-table td {
|
|
||||||
color: rgba(255, 255, 255, 0.8);
|
|
||||||
|
|
||||||
&.selected .el-date-table-cell {
|
|
||||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.today span {
|
|
||||||
color: #40a9ff;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.in-range,
|
|
||||||
&.start-date,
|
|
||||||
&.end-date {
|
|
||||||
background: rgba(64, 169, 255, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-picker-panel__footer {
|
|
||||||
border-top: 1px solid rgba(64, 169, 255, 0.3);
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
background: rgba(30, 70, 120, 0.4);
|
|
||||||
border-color: rgba(64, 169, 255, 0.3);
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(64, 169, 255, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button--primary {
|
|
||||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: linear-gradient(135deg, #69c0ff 0%, #40a9ff 100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -249,7 +249,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted, provide } from "vue";
|
||||||
import useMapStore from "@/map/stores/mapStore";
|
import useMapStore from "@/map/stores/mapStore";
|
||||||
import { useMapBase } from "../cockpit/composables/useMapBase";
|
import { useMapBase } from "../cockpit/composables/useMapBase";
|
||||||
import left from "./left.vue";
|
import left from "./left.vue";
|
||||||
@ -259,26 +259,26 @@ import top from "./top.vue";
|
|||||||
import ChongqingMap from "./component/ChongqingMap.vue";
|
import ChongqingMap from "./component/ChongqingMap.vue";
|
||||||
|
|
||||||
// 引入所有弹窗组件
|
// 引入所有弹窗组件
|
||||||
import responseSituationDiaLog from "./component/responseSituationDiaLog.vue";
|
import responseSituationDiaLog from "./Dialog/responseSituationDiaLog.vue";
|
||||||
import warningInfoDialog from "./component/warningInfoDialog.vue";
|
import warningInfoDialog from "./Dialog/warningInfoDialog.vue";
|
||||||
import eventDetailDialog from "./component/eventDetailDialog.vue";
|
import eventDetailDialog from "./Dialog/eventDetailDialog.vue";
|
||||||
import confirmDialog from "./component/confirmDialog.vue";
|
import confirmDialog from "./Dialog/confirmDialog.vue";
|
||||||
import riskPointDetailDialog from "./component/riskPointDetailDialog.vue";
|
import riskPointDetailDialog from "./Dialog/riskPointDetailDialog.vue";
|
||||||
import impactPointDialog from "./component/impactPointDialog.vue";
|
import impactPointDialog from "./Dialog/impactPointDialog.vue";
|
||||||
import impactPointDetailDialog from "./component/impactPointDetailDialog.vue";
|
import impactPointDetailDialog from "./Dialog/impactPointDetailDialog.vue";
|
||||||
import responsePointDetailDialog from "./component/responsePointDetailDialog.vue";
|
import responsePointDetailDialog from "./Dialog/responsePointDetailDialog.vue";
|
||||||
import responsePointInfoDialog from "./component/responsePointInfoDialog.vue";
|
import responsePointInfoDialog from "./Dialog/responsePointInfoDialog.vue";
|
||||||
import responseStatusDialog from "./component/responseStatusDialog.vue";
|
import responseStatusDialog from "./Dialog/responseStatusDialog.vue";
|
||||||
import aiWarningResultDialog from "./component/aiWarningResultDialog.vue";
|
import aiWarningResultDialog from "./Dialog/aiWarningResultDialog.vue";
|
||||||
import tongnanInfoDialog from "./component/tongnanInfoDialog.vue";
|
import tongnanInfoDialog from "./Dialog/tongnanInfoDialog.vue";
|
||||||
import tongnanResponsibleDialog from "./component/tongnanResponsibleDialog.vue";
|
import tongnanResponsibleDialog from "./Dialog/tongnanResponsibleDialog.vue";
|
||||||
import clearanceSituationDialog from "./component/clearanceSituationDialog.vue";
|
import clearanceSituationDialog from "./Dialog/clearanceSituationDialog.vue";
|
||||||
import controlSituationDialog from "./component/controlSituationDialog.vue";
|
import controlSituationDialog from "./Dialog/controlSituationDialog.vue";
|
||||||
import dispatchDetailDialog from "./component/dispatchDetailDialog.vue";
|
import dispatchDetailDialog from "./Dialog/dispatchDetailDialog.vue";
|
||||||
import dispatchDistrictDialog from "./component/dispatchDistrictDialog.vue";
|
import dispatchDistrictDialog from "./Dialog/dispatchDistrictDialog.vue";
|
||||||
import tongnanTeamDialog from "./component/tongnanTeamDialog.vue";
|
import tongnanTeamDialog from "./Dialog/tongnanTeamDialog.vue";
|
||||||
import warningSituationDialog from "./component/warningSituationDialog.vue";
|
import warningSituationDialog from "./Dialog/warningSituationDialog.vue";
|
||||||
import tunnelInfoDialog from "./component/tunnelInfoDialog.vue";
|
import tunnelInfoDialog from "./Dialog/tunnelInfoDialog.vue";
|
||||||
|
|
||||||
// 弹窗显示状态
|
// 弹窗显示状态
|
||||||
const dialogVisible = ref({
|
const dialogVisible = ref({
|
||||||
@ -301,7 +301,7 @@ const dialogVisible = ref({
|
|||||||
dispatchDistrict: false,
|
dispatchDistrict: false,
|
||||||
tongnanTeam: false,
|
tongnanTeam: false,
|
||||||
warningSituation: false,
|
warningSituation: false,
|
||||||
tunnelInfo: false,
|
tunnelInfo: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
@ -333,6 +333,25 @@ const openConfirm = (config) => {
|
|||||||
// 中心信息卡片显示状态
|
// 中心信息卡片显示状态
|
||||||
const showCenterCard = ref(false);
|
const showCenterCard = ref(false);
|
||||||
|
|
||||||
|
// 兄弟组件通信机制
|
||||||
|
const refreshLeftData = ref(null);
|
||||||
|
|
||||||
|
// 提供刷新函数给子组件
|
||||||
|
const setRefreshLeftData = (callback) => {
|
||||||
|
refreshLeftData.value = callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 触发刷新函数
|
||||||
|
const triggerRefreshLeftData = () => {
|
||||||
|
if (refreshLeftData.value) {
|
||||||
|
refreshLeftData.value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提供通信机制给子组件
|
||||||
|
provide('setRefreshLeftData', setRefreshLeftData);
|
||||||
|
provide('triggerRefreshLeftData', triggerRefreshLeftData);
|
||||||
|
|
||||||
// ==================== 地图状态管理 ====================
|
// ==================== 地图状态管理 ====================
|
||||||
|
|
||||||
const mapStore = useMapStore();
|
const mapStore = useMapStore();
|
||||||
@ -405,27 +424,27 @@ onMounted(() => {
|
|||||||
|
|
||||||
.title_img2 {
|
.title_img2 {
|
||||||
height: vw(40);
|
height: vw(40);
|
||||||
min-height: 28px;
|
min-height: 40px;
|
||||||
width: auto;
|
width: auto;
|
||||||
max-width: vw(300);
|
width: vw(550);
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.left {
|
.left {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: vw(90);
|
top: vw(60);
|
||||||
width: 25%;
|
width: 25%;
|
||||||
height: calc(100% - #{vw(90)});
|
height: calc(100% - #{vw(60)});
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: vw(90);
|
top: vw(60);
|
||||||
width: 25%;
|
width: 25%;
|
||||||
height: calc(100% - #{vw(90)});
|
height: calc(100% - #{vw(60)});
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,14 +504,14 @@ onMounted(() => {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
&.corner-top-left {
|
&.corner-top-left {
|
||||||
top: vw(110);
|
top: vw(60);
|
||||||
left: vw(10);
|
left: vw(10);
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.corner-top-right {
|
&.corner-top-right {
|
||||||
top: vw(110);
|
top: vw(60);
|
||||||
right: vw(10);
|
right: vw(10);
|
||||||
border-left: none;
|
border-left: none;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
@ -574,7 +593,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.info-unit {
|
.info-unit {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.6);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,10 +57,10 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="bar"
|
class="bar"
|
||||||
:style="{ height: getBarHeight(item.value) + '%' }"
|
:style="{ height: getBarHeight(item) + '%' }"
|
||||||
></div>
|
></div>
|
||||||
<div class="bar-value">{{ item.value }}</div>
|
<div class="bar-value">{{ item.count }}</div>
|
||||||
<div class="bar-label">{{ item.label }}</div>
|
<div class="bar-label">{{ item.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-x-label">类型</div>
|
<div class="chart-x-label">类型</div>
|
||||||
@ -71,13 +71,13 @@
|
|||||||
<div class="road-type-section">
|
<div class="road-type-section">
|
||||||
<div class="section-title">影响公路类型情况</div>
|
<div class="section-title">影响公路类型情况</div>
|
||||||
<div class="road-type-cards">
|
<div class="road-type-cards">
|
||||||
<div class="road-card">
|
<div
|
||||||
<span class="card-label">国省道:</span>
|
class="road-card"
|
||||||
<span class="card-value">100</span>
|
v-for="(item, index) in roadTypeData"
|
||||||
</div>
|
:key="index"
|
||||||
<div class="road-card">
|
>
|
||||||
<span class="card-label">农村公路:</span>
|
<span class="card-label">{{ item.extension }}:</span>
|
||||||
<span class="card-value">300</span>
|
<span class="card-value">{{ item.count }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -99,11 +99,15 @@
|
|||||||
:scroll="{ y: true }"
|
:scroll="{ y: true }"
|
||||||
>
|
>
|
||||||
<el-table-column prop="name" label="区县名称" :min-width="vw(80)" />
|
<el-table-column prop="name" label="区县名称" :min-width="vw(80)" />
|
||||||
<el-table-column prop="road" label="路段" :min-width="vw(50)" />
|
<el-table-column
|
||||||
<el-table-column prop="bridge" label="桥梁" :min-width="vw(50)" />
|
prop="roadSectionCount"
|
||||||
<el-table-column prop="tunnel" label="隧道" :min-width="vw(50)" />
|
label="路段"
|
||||||
<el-table-column prop="slope" label="边坡" :min-width="vw(50)" />
|
:min-width="vw(50)"
|
||||||
<el-table-column prop="project" label="项目" :min-width="vw(50)" />
|
/>
|
||||||
|
<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)" />
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -123,6 +127,7 @@
|
|||||||
size="small"
|
size="small"
|
||||||
popper-class="dark-date-picker"
|
popper-class="dark-date-picker"
|
||||||
:prefix-icon="Calendar"
|
:prefix-icon="Calendar"
|
||||||
|
@change="handleDateChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -157,13 +162,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(item, index) in dispatchList"
|
v-for="(item, index) in dispatchList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="dispatch-card"
|
class="dispatch-card clickable"
|
||||||
:class="{
|
|
||||||
clickable:
|
|
||||||
item.label === '国省道调度清单' ||
|
|
||||||
item.label === '农村公路调度清单' ||
|
|
||||||
item.label === '建设工程调度清单',
|
|
||||||
}"
|
|
||||||
@click="handleDispatchCardClick(item)"
|
@click="handleDispatchCardClick(item)"
|
||||||
>
|
>
|
||||||
<div class="card-num">
|
<div class="card-num">
|
||||||
@ -177,10 +176,55 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { ref, computed, onMounted, watch, inject } from "vue";
|
||||||
import { request } from "@/utils/request";
|
import { request } from "@/utils/request";
|
||||||
|
|
||||||
import SectionHeader from "./component/sectionHeader.vue";
|
import SectionHeader from "./component/sectionHeader.vue";
|
||||||
|
// 导入图片资源
|
||||||
|
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";
|
||||||
|
|
||||||
|
// 注入兄弟组件通信机制
|
||||||
|
const setRefreshLeftData = inject('setRefreshLeftData');
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听visible变化
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
// loadData();
|
||||||
|
// loadBarChartData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.visible) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册刷新函数给父组件
|
||||||
|
if (setRefreshLeftData) {
|
||||||
|
setRefreshLeftData(init);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const init = () => {
|
||||||
|
roadTypeLoad();
|
||||||
|
districtLoadLoad();
|
||||||
|
dispatchLoadLoad();
|
||||||
|
loadData();
|
||||||
|
loadBarChartData();
|
||||||
|
};
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
"openWarningInfo",
|
"openWarningInfo",
|
||||||
@ -215,94 +259,248 @@ const handleImpactDetailClick = () => {
|
|||||||
|
|
||||||
// 点击调度清单卡片
|
// 点击调度清单卡片
|
||||||
const handleDispatchCardClick = (item) => {
|
const handleDispatchCardClick = (item) => {
|
||||||
if (item.label === "建设工程调度清单") {
|
if (item.label === dispatchList.value[0].label) {
|
||||||
emit("showCenterCard", {
|
|
||||||
type: "first",
|
|
||||||
value: item.value,
|
|
||||||
});
|
|
||||||
} else if (item.label === "国省道调度清单") {
|
|
||||||
emit("showCenterCard", {
|
emit("showCenterCard", {
|
||||||
type: "second",
|
type: "second",
|
||||||
value: item.value,
|
value: item.value,
|
||||||
});
|
});
|
||||||
} else if (item.label === "农村公路调度清单") {
|
} else if (item.label === dispatchList.value[1].label) {
|
||||||
emit("showCenterCard", {
|
emit("showCenterCard", {
|
||||||
type: "third",
|
type: "third",
|
||||||
value: item.value,
|
value: item.value,
|
||||||
});
|
});
|
||||||
|
} else if (item.label === dispatchList.value[2].label) {
|
||||||
|
emit("showCenterCard", {
|
||||||
|
type: "first",
|
||||||
|
value: item.value,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导入图片资源
|
|
||||||
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";
|
|
||||||
|
|
||||||
// 气象预警数据
|
// 气象预警数据
|
||||||
const weatherWarningData = ref([
|
const weatherWarningData = ref([
|
||||||
{ label: "红色预警", value: "", class: "red" },
|
{ label: "红色预警", value: "0", class: "red" },
|
||||||
{ label: "橙色预警", value: "", class: "orange" },
|
{ label: "橙色预警", value: "0", class: "orange" },
|
||||||
{ label: "黄色预警", value: "", class: "yellow" },
|
{ label: "黄色预警", value: "0", class: "yellow" },
|
||||||
{ label: "蓝色预警", value: "", class: "blue" },
|
{ label: "蓝色预警", value: "0", class: "blue" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 影响点数据
|
// 影响点数据
|
||||||
const impactData = ref([
|
const impactData = ref([
|
||||||
{ label: "路段", value: 830 },
|
{ name: "路段", count: 830 },
|
||||||
{ label: "桥梁", value: 312 },
|
{ name: "桥梁", count: 312 },
|
||||||
{ label: "隧道", value: 405 },
|
{ name: "隧道", count: 405 },
|
||||||
{ label: "边坡", value: 634 },
|
{ name: "边坡", count: 634 },
|
||||||
{ label: "项目", value: 523 },
|
{ name: "项目", count: 523 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 日期范围选择器
|
// 日期选择器变化事件
|
||||||
|
const handleDateChange = (val) => {
|
||||||
|
dateRange.value = val;
|
||||||
|
dispatchLoadLoad();
|
||||||
|
};
|
||||||
|
// 日期选择器数据
|
||||||
const dateRange = ref([]);
|
const dateRange = ref([]);
|
||||||
|
// 调度清单数据
|
||||||
|
const dispatchLoadLoad = async () => {
|
||||||
|
try {
|
||||||
|
// 处理日期参数,开始时间为当天00:00:00,结束时间为当天23:59:59
|
||||||
|
let startTime = "";
|
||||||
|
let endTime = "";
|
||||||
|
|
||||||
|
if (dateRange.value && dateRange.value.length === 2) {
|
||||||
|
const startDate = new Date(dateRange.value[0]);
|
||||||
|
const endDate = new Date(dateRange.value[1]);
|
||||||
|
|
||||||
|
// 开始时间设置为当天00:00:00
|
||||||
|
startDate.setHours(0, 0, 0, 0);
|
||||||
|
startTime = startDate.getTime();
|
||||||
|
|
||||||
|
// 结束时间设置为当天23:59:59
|
||||||
|
endDate.setHours(23, 59, 59, 999);
|
||||||
|
endTime = endDate.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await request({
|
||||||
|
url: "/snow-ops-platform/weather-warning/schedule-statistics",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
start: startTime,
|
||||||
|
end: endTime,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(res);
|
||||||
|
if (res.code == "00000") {
|
||||||
|
const data = res.data;
|
||||||
|
if (data) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// responseStats.value = data;
|
||||||
|
// dispatchList.value = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载数据失败:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 区县数据
|
||||||
|
const districtLoadLoad = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "/snow-ops-platform/weather-warning/affected-count/_by_county",
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
console.log(res);
|
||||||
|
if (res.code == "00000") {
|
||||||
|
const data = res.data;
|
||||||
|
if (data) {
|
||||||
|
districtData.value = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载数据失败:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const roadTypeData = ref([]);
|
||||||
|
// 公路类型数据
|
||||||
|
const roadTypeLoad = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "/snow-ops-platform/weather-warning/affected-count/_by_road",
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
console.log(res);
|
||||||
|
if (res.code == "00000") {
|
||||||
|
const data = res.data;
|
||||||
|
if (data) {
|
||||||
|
roadTypeData.value = data.reverse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载数据失败:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
// 加载气象预警和影响点数据
|
// 加载气象预警和影响点数据
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: "/snow-ops-platform/weatherWarning/statistics",
|
url: "/snow-ops-platform/weather-warning/warning-count",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.code == "00000") {
|
if (res.code == "00000") {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
if (data) {
|
if (data) {
|
||||||
|
let obj = {};
|
||||||
|
data.forEach((item) => {
|
||||||
|
obj[item.name] = item.count || 0;
|
||||||
|
});
|
||||||
|
console.log(obj);
|
||||||
weatherWarningData.value.forEach((item) => {
|
weatherWarningData.value.forEach((item) => {
|
||||||
if (item.label == "红色预警") {
|
if (item.label == "红色预警") {
|
||||||
item.value = data.redWarningCount || 0;
|
item.value =
|
||||||
|
obj["warning-red-count"] + "/" + obj["warning-red-total"] ||
|
||||||
|
"0/0";
|
||||||
} else if (item.label == "橙色预警") {
|
} else if (item.label == "橙色预警") {
|
||||||
item.value = data.orangeWarningCount || 0;
|
item.value =
|
||||||
|
obj["warning-orange-count"] + "/" + obj["warning-orange-total"] ||
|
||||||
|
"0/0";
|
||||||
} else if (item.label == "黄色预警") {
|
} else if (item.label == "黄色预警") {
|
||||||
item.value = data.yellowWarningCount || 0;
|
item.value =
|
||||||
|
obj["warning-yellow-count"] + "/" + obj["warning-yellow-total"] ||
|
||||||
|
"0/0";
|
||||||
} else if (item.label == "蓝色预警") {
|
} else if (item.label == "蓝色预警") {
|
||||||
item.value = data.blueWarningCount || 0;
|
item.value =
|
||||||
|
obj["warning-blue-count"] + "/" + obj["warning-blue-total"] ||
|
||||||
|
"0/0";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (data.impactData) {
|
|
||||||
impactData.value = data.impactData;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("加载数据失败:", error);
|
console.error("加载数据失败:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 加载柱状图数据
|
||||||
|
const loadBarChartData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "/snow-ops-platform/weather-warning/affected-count",
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.code == "00000") {
|
||||||
|
const data = res.data;
|
||||||
|
if (data && Array.isArray(data)) {
|
||||||
|
// 英文转中文映射
|
||||||
|
const nameMap = {
|
||||||
|
"road-section": "路段",
|
||||||
|
bridge: "桥梁",
|
||||||
|
tunnel: "隧道",
|
||||||
|
slope: "边坡",
|
||||||
|
project: "项目",
|
||||||
|
Road: "路段",
|
||||||
|
Bridge: "桥梁",
|
||||||
|
Tunnel: "隧道",
|
||||||
|
Slope: "边坡",
|
||||||
|
Project: "项目",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 转换英文name为中文
|
||||||
|
const convertedData = data.map((item) => {
|
||||||
|
const name = nameMap[item.name] || item.name;
|
||||||
|
return { ...item, name };
|
||||||
|
});
|
||||||
|
|
||||||
|
impactData.value = convertedData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载柱状图数据失败:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 计算最大值用于动态计算高度
|
// 计算最大值用于动态计算高度
|
||||||
const maxValue = computed(() => {
|
// 计算所有影响点的总和
|
||||||
return Math.max(...impactData.value.map((item) => item.value));
|
const totalValue = computed(() => {
|
||||||
|
let total = 0;
|
||||||
|
impactData.value.forEach((item) => {
|
||||||
|
total += item.count || 0;
|
||||||
|
});
|
||||||
|
return total;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 计算每个柱子的高度百分比
|
// 计算每个柱子的高度百分比
|
||||||
const getBarHeight = (value) => {
|
const getBarHeight = (value) => {
|
||||||
// 确保最小高度为20%,最大高度为100%
|
const actualValue = value.count || value.value;
|
||||||
const height = (value / maxValue) * 100;
|
// 确保最小高度为10%,最大高度为100%
|
||||||
return Math.min(100, Math.max(20, Math.round(height)));
|
const height = (actualValue / totalValue.value) * 200;
|
||||||
|
// 确保高度差异明显,至少有5%的差异
|
||||||
|
return Math.min(100, Math.max(10, Math.round(height)));
|
||||||
};
|
};
|
||||||
const handleAIClick = () => {
|
const handleAIClick = () => {
|
||||||
emit("openAIResult");
|
emit("openAIResult");
|
||||||
@ -319,17 +517,22 @@ const tableHeight = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 区县数据
|
// 区县数据
|
||||||
const districtData = [
|
const districtData = ref([
|
||||||
{ name: "江北区", road: 1, bridge: 1, tunnel: 1, slope: 8, project: 11 },
|
{ extension: "江北区", road: 1, bridge: 1, tunnel: 1, slope: 8, project: 11 },
|
||||||
{ name: "江北区", road: 1, bridge: 1, tunnel: 1, slope: 8, project: 11 },
|
{ extension: "南岸区", road: 1, bridge: 2, tunnel: 2, slope: 6, project: 12 },
|
||||||
{ name: "南岸区", road: 1, bridge: 2, tunnel: 2, slope: 6, project: 12 },
|
{
|
||||||
{ name: "九龙坡区", road: 2, bridge: 1, tunnel: 1, slope: 9, project: 9 },
|
extension: "九龙坡区",
|
||||||
{ name: "九龙坡区", road: 2, bridge: 1, tunnel: 1, slope: 9, project: 9 },
|
road: 2,
|
||||||
{ name: "万州区", road: 1, bridge: 2, tunnel: 2, slope: 11, project: 7 },
|
bridge: 1,
|
||||||
];
|
tunnel: 1,
|
||||||
|
slope: 9,
|
||||||
|
project: 9,
|
||||||
|
},
|
||||||
|
{ extension: "万州区", road: 1, bridge: 2, tunnel: 2, slope: 11, project: 7 },
|
||||||
|
]);
|
||||||
|
|
||||||
// 响应调度统计数据
|
// 响应调度统计数据
|
||||||
const responseStats = [
|
const responseStats = ref([
|
||||||
{
|
{
|
||||||
label: "叫应总数",
|
label: "叫应总数",
|
||||||
value: "15",
|
value: "15",
|
||||||
@ -366,14 +569,14 @@ const responseStats = [
|
|||||||
iconClass: "icon-check",
|
iconClass: "icon-check",
|
||||||
img: imgCheck,
|
img: imgCheck,
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
// 调度清单数据
|
// 调度清单数据
|
||||||
const dispatchList = [
|
const dispatchList = ref([
|
||||||
{ label: "国省道调度清单", value: "341" },
|
{ label: "国省道调度", value: "341" },
|
||||||
{ label: "农村公路调度清单", value: "210" },
|
{ label: "农村公路调度", value: "210" },
|
||||||
{ label: "建设工程调度清单", value: "120" },
|
{ label: "建设工程调度", value: "120" },
|
||||||
];
|
]);
|
||||||
|
|
||||||
const headerCellStyle = () => ({
|
const headerCellStyle = () => ({
|
||||||
background: "rgba(64, 169, 255, 0.1)",
|
background: "rgba(64, 169, 255, 0.1)",
|
||||||
@ -393,10 +596,6 @@ const cellStyle = () => ({
|
|||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
lineHeight: "1.2",
|
lineHeight: "1.2",
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
loadData();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -534,7 +733,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-label {
|
.card-label {
|
||||||
font-size: vw(12);
|
font-size: vw(16);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,7 +795,7 @@ onMounted(() => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: vw(-10);
|
top: vw(-10);
|
||||||
font-size: vw(11);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.6);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,7 +860,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bar-value {
|
.bar-value {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
margin-bottom: vw(5);
|
margin-bottom: vw(5);
|
||||||
@ -677,13 +876,13 @@ onMounted(() => {
|
|||||||
rgba(64, 169, 255, 0.3) 100%
|
rgba(64, 169, 255, 0.3) 100%
|
||||||
);
|
);
|
||||||
border-radius: 2px 2px 0 0;
|
border-radius: 2px 2px 0 0;
|
||||||
min-height: 20px;
|
// min-height: 20px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bar-label {
|
.bar-label {
|
||||||
bottom: vw(-20);
|
bottom: vw(-20);
|
||||||
font-size: vw(10);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -695,7 +894,7 @@ onMounted(() => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
right: vw(-15);
|
right: vw(-15);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
font-size: vw(10);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.6);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -831,7 +1030,7 @@ onMounted(() => {
|
|||||||
&::before {
|
&::before {
|
||||||
content: "←";
|
content: "←";
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -911,7 +1110,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.stat-label {
|
.stat-label {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -967,7 +1166,7 @@ onMounted(() => {
|
|||||||
margin-bottom: vw(6);
|
margin-bottom: vw(6);
|
||||||
|
|
||||||
.unit {
|
.unit {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
@ -975,7 +1174,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.card-label {
|
.card-label {
|
||||||
font-size: vw(10);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.8);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -472,7 +472,7 @@ const majorEvent = "0";
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
.resource-label {
|
.resource-label {
|
||||||
width: 48%;
|
width: 48%;
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
margin-bottom: vw(2);
|
margin-bottom: vw(2);
|
||||||
}
|
}
|
||||||
@ -483,7 +483,7 @@ const majorEvent = "0";
|
|||||||
color: #18F2F9;
|
color: #18F2F9;
|
||||||
|
|
||||||
.unit {
|
.unit {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
@ -516,8 +516,11 @@ const majorEvent = "0";
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
background: rgba(62, 106, 172, 0.36);
|
// background: rgba(62, 106, 172, 0.36);
|
||||||
box-shadow: inset 0px 0px 8px 0px #379bff;
|
// box-shadow: inset 0px 0px 8px 0px #379bff;
|
||||||
|
background-image: url("../../assets/RiskWarning_img/路径 62@2x.png");
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: right;
|
||||||
gap: vw(8);
|
gap: vw(8);
|
||||||
|
|
||||||
.control-item {
|
.control-item {
|
||||||
@ -544,7 +547,7 @@ const majorEvent = "0";
|
|||||||
}
|
}
|
||||||
|
|
||||||
.control-label {
|
.control-label {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -597,7 +600,7 @@ const majorEvent = "0";
|
|||||||
}
|
}
|
||||||
|
|
||||||
.patrol-label {
|
.patrol-label {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -667,7 +670,7 @@ const majorEvent = "0";
|
|||||||
}
|
}
|
||||||
|
|
||||||
.rescue-label {
|
.rescue-label {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,7 +758,7 @@ const majorEvent = "0";
|
|||||||
}
|
}
|
||||||
|
|
||||||
.block-label {
|
.block-label {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,7 +771,7 @@ const majorEvent = "0";
|
|||||||
}
|
}
|
||||||
|
|
||||||
.death-label {
|
.death-label {
|
||||||
font-size: vw(10);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -805,14 +808,14 @@ const majorEvent = "0";
|
|||||||
margin-bottom: vw(6);
|
margin-bottom: vw(6);
|
||||||
|
|
||||||
.unit {
|
.unit {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.damage-label {
|
.damage-label {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,7 +846,7 @@ const majorEvent = "0";
|
|||||||
background-position: left;
|
background-position: left;
|
||||||
|
|
||||||
.event-title {
|
.event-title {
|
||||||
font-size: vw(12);
|
font-size: vw(14);
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,13 +20,28 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref, watch, inject } from "vue";
|
||||||
import { Calendar } from "@element-plus/icons-vue";
|
import { Calendar } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
const emit = defineEmits(["openAIResult"]);
|
const emit = defineEmits(["openAIResult"]);
|
||||||
|
|
||||||
|
// 注入兄弟组件通信机制
|
||||||
|
const triggerRefreshLeftData = inject('triggerRefreshLeftData');
|
||||||
|
|
||||||
const dateRange = ref([]);
|
const dateRange = ref([]);
|
||||||
|
|
||||||
|
// 监听 dateRange 变化
|
||||||
|
watch(dateRange, (newVal, oldVal) => {
|
||||||
|
// 只有当值真正发生变化时才触发
|
||||||
|
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
|
||||||
|
console.log('dateRange 发生变化:', newVal);
|
||||||
|
// 触发兄弟组件刷新
|
||||||
|
if (triggerRefreshLeftData) {
|
||||||
|
triggerRefreshLeftData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, { deep: true });
|
||||||
|
|
||||||
const handleAIClick = () => {
|
const handleAIClick = () => {
|
||||||
emit("openAIResult");
|
emit("openAIResult");
|
||||||
};
|
};
|
||||||
@ -88,8 +103,8 @@ const handleAIClick = () => {
|
|||||||
height: 2.6em !important;
|
height: 2.6em !important;
|
||||||
}
|
}
|
||||||
:deep(.el-date-editor) {
|
:deep(.el-date-editor) {
|
||||||
width: vw(200);
|
width: 180px;
|
||||||
max-width: vw(200);
|
max-width: vw(350);
|
||||||
background: #183c67;
|
background: #183c67;
|
||||||
box-shadow: inset 0px 0px 8px 0px #4fecff;
|
box-shadow: inset 0px 0px 8px 0px #4fecff;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user