抢通情况详情弹窗接口调用,地图图标层级提高,修改页面细节,线下帮扶数弹窗,涉灾隐患点情况弹窗

This commit is contained in:
fanjia 2026-04-21 15:34:43 +08:00
parent d2722b0824
commit 07b5f24adf
33 changed files with 2270 additions and 1307 deletions

View File

@ -1,22 +0,0 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended'
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['vue'],
rules: {
'vue/multi-word-component-names': 'off',
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'vue/no-v-html': 'off'
}
}

View File

@ -141,6 +141,18 @@
>
{{ currentWarningInfo.whistle }}
</div>
<div
class="suggestion-content"
v-else-if="'frontline-contractor' == activeHierarchyTab"
>
{{ currentWarningInfo.contractor }}
</div>
<div
class="suggestion-content"
v-else-if="'frontline-person' == activeHierarchyTab"
>
{{ currentWarningInfo.person }}
</div>
</div>
<!-- 影响范围 -->
@ -268,7 +280,7 @@ const emit = defineEmits(['update:visible', 'close']);
const warningData = ref({
publishOrg: '',
warningContent:
'潼南区气象台2025年11月13日0时40分发布“暴雨蓝色预警tt信号”预计23日0:40-6:40龙形、宝龙、上和、大佛、桂林、玉溪、米心、花岩、双江、古溪、群力、柏梓、崇龛、梓潼、太安等15个乡镇街道强降水趋于减弱未来6小时累计雨量将达50100毫米最大小时雨强将达2040毫米局地伴有雷电、阵性大风请各地注意防范。',
'黔江区气象台2026年4月16日01时00分发布“暴雨红色预警信号”过去1小时双槐雨量已达90毫米预计6日1:00-7:00濯水镇街强降水仍将持续未来6小时累计雨量将达90160毫米最大小时雨强将达80100毫米局地伴有雷电、阵性大风地质灾害、中小河流洪水、山洪、城乡积涝等灾害风险高注意防范。',
effectiveTime: '',
expireTime: '',
});
@ -297,17 +309,19 @@ const hierarchyLevels = ref([
//
const hierarchyTabs = ref([
{ key: 'city-leader', label: '公路中心领导', parentKey: 'city' },
{ key: 'city-leader', label: '中心领导', parentKey: 'city' },
{ key: 'city-dept', label: '处室负责人', parentKey: 'city' },
{ key: 'city-emergency', label: '中心应急办', parentKey: 'city' },
]);
const districtTabsMap = ref([
{ key: 'district-leader', label: '公路交通部门领导', parentKey: 'district' },
{ key: 'district-person', label: '公路交通部门包保人', parentKey: 'district' },
{ key: 'district-person', label: '养护站长/路长办', parentKey: 'district' },
]);
const frontlineTabsMap = ref([
{ key: 'frontline-guard', label: '护路员', parentKey: 'frontline' },
{ key: 'frontline-whistle', label: '项目吹哨人', parentKey: 'frontline' },
{ key: 'frontline-whistle', label: '建设单位包保责任人', parentKey: 'frontline' },
{ key: 'frontline-contractor', label: '施工单位包保责任人', parentKey: 'frontline' },
{ key: 'frontline-person', label: '吹哨人', parentKey: 'frontline' },
]);
const activeHierarchyTab = ref('city-leader');
@ -584,7 +598,7 @@ watch(
display: flex;
align-items: center;
justify-content: center;
margin-top: 50px;
// margin-top: -40px;
gap: 8px;
.ai-icon-img {
width: 80px;
@ -606,7 +620,7 @@ watch(
gap: 20px;
align-items: center;
margin-left: 20px;
margin-top: 50px;
// margin-top: -40px;
margin-right: 10px;
.hierarchy-left {

View File

@ -1,9 +1,6 @@
<template>
<div class="center-info-card-container" v-if="visible" @click="handleClick">
<div
class="center-info-card"
:style="{ backgroundImage: `url(${districtIcon})` }"
>
<div class="center-info-card" :style="{ backgroundImage: `url(${districtIcon})` }">
<!-- 标题栏 -->
<div class="card-header">
<div class="header-left">
@ -17,11 +14,11 @@
<!-- 内容区域 -->
<div class="card-content">
<div class="info-row">
<span class="info-text">人数{{ item?.population || "-" }}</span>
<span class="info-text">人数{{ item?.population || '-' }}</span>
<span class="info-text">
<span v-if="item?.type == 'project'">项目</span>
<span v-else>路段</span>
<span>{{ item?.entityCount || "-" }}</span>
<span>{{ item?.entityCount || '-' }}</span>
<span v-if="item?.type == 'project'"></span>
<span v-else></span>
</span>
@ -32,10 +29,10 @@
</template>
<script setup>
import { computed } from "vue";
import { ArrowRight, Close } from "@element-plus/icons-vue";
import districtIcon from "../../../assets/MaMap_img/区县弹窗背景@2x.png";
import locationIcon from "../../../assets/MaMap_img/区县icon@2x.png";
import { computed } from 'vue';
import { ArrowRight, Close } from '@element-plus/icons-vue';
import districtIcon from '../../../assets/MaMap_img/区县弹窗背景@2x.png';
import locationIcon from '../../../assets/MaMap_img/区县icon@2x.png';
const props = defineProps({
//
@ -51,7 +48,7 @@ const props = defineProps({
//
title: {
type: String,
default: "",
default: '',
},
//
dataList: {
@ -80,7 +77,7 @@ const props = defineProps({
},
});
const emit = defineEmits(["click", "close", "itemClick", "onClick"]);
const emit = defineEmits(['click', 'close', 'itemClick', 'onClick']);
//
const showCard = computed(() => {
@ -89,35 +86,35 @@ const showCard = computed(() => {
return props.visible;
}
// 使
return props.type === "second" || props.type === "third";
return props.type === 'second' || props.type === 'third';
});
//
const getRoadTypeText = (roadType) => {
const getRoadTypeText = roadType => {
const roadTypeMap = {
national: "国省道",
rural: "农村公路",
national: '国省道',
rural: '农村公路',
};
return roadTypeMap[roadType] || roadType;
};
//
const handleClick = () => {
console.log("centerInfoCard clicked, type:", props.type);
console.log('centerInfoCard clicked, type:', props.type);
// onClick
emit("onClick");
emit('onClick');
// click
emit("click", props.type);
emit('click', props.type);
};
//
const handleClose = () => {
emit("close");
emit('close');
};
//
const handleItemClick = (item) => {
emit("itemClick", item);
const handleItemClick = item => {
emit('itemClick', item);
};
</script>

View File

@ -23,6 +23,7 @@
placeholder="请选择"
class="filter-select"
clearable
@change="handleFilterChange"
>
<el-option
v-for="item in regionOptions"
@ -40,6 +41,7 @@
placeholder="请选择"
class="filter-select"
clearable
@change="handleFilterChange"
>
<el-option
v-for="item in typeOptions"
@ -99,17 +101,24 @@
</template>
<script setup>
import { ref, computed, watch } from 'vue';
import { ref, computed, watch, inject } from 'vue';
import { Close } from '@element-plus/icons-vue';
import { regionOptions, typeOptions, controlMeasureOptions } from '../component/index.js';
import BaseDialog from '../component/baseDialog.vue';
import { request } from '@/utils/request';
import { formatDateTime } from '../component/index.js';
0;
//
// const dateRange = inject('dateRange', ref([]));
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
dateRange: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(['update:visible', 'close', 'detail', 'itemdata']);
@ -185,6 +194,11 @@ const getControlClass = measure => {
半幅封闭: 'control-half',
正常通行: 'control-normal',
限制通行: 'control-limit',
限速限车: 'control-limit',
告警阻拦: 'control-limit',
半幅通行: 'control-half',
限速: 'control-limit',
告警阻拦: 'control-limit',
};
return classMap[measure] || '';
};
@ -219,25 +233,27 @@ const handleFilterChange = () => {
//
const fetchData = async () => {
try {
//
let measureType = 0;
if (filterForm.value.roadConditionType === '全幅封闭') {
measureType = 1;
} else if (filterForm.value.roadConditionType === '半幅封闭') {
measureType = 2;
} else if (filterForm.value.roadConditionType === '限速') {
measureType = 3;
} else if (filterForm.value.roadConditionType === '告警阻拦') {
measureType = 4;
let params = {
start: '',
end: '',
};
if (props.dateRange && props.dateRange.length === 2) {
params.start = formatDateTime(props.dateRange[0]);
params.end = formatDateTime(props.dateRange[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/control-list',
method: 'GET',
params: {
start: params.start,
end: params.end,
pageNum: currentPage.value,
pageSize: pageSize.value,
measureType: measureType,
// measureType: measureType,
districtCode: filterForm.value.district, //
roadConditionType: filterForm.value.type, //
processingMeasure: filterForm.value.roadConditionType, //
},
});
@ -246,6 +262,7 @@ const fetchData = async () => {
//
tableData.value = data.records.map((item, index) => {
return {
gl1SjId: item.sjId || '-',
id: currentPage.value * pageSize.value - (pageSize.value - index - 1),
district: item.affectedArea || '-',
routeNo: item.routeNo || '-',
@ -276,6 +293,16 @@ watch(
}
}
);
watch(
() => filterForm.value,
newVal => {
console.log('filterForm.value变化:', newVal);
if (newVal) {
currentPage.value = 1;
fetchData();
}
}
);
</script>
<style lang="scss" scoped>

View File

@ -1,9 +1,5 @@
<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="corner corner-top-left"></div>
@ -37,7 +33,7 @@
</template>
<script setup>
import { Close } from "@element-plus/icons-vue";
import { Close } from '@element-plus/icons-vue';
const props = defineProps({
visible: {
@ -46,34 +42,34 @@ const props = defineProps({
},
title: {
type: String,
default: "提示",
default: '提示',
},
message: {
type: String,
default: "",
default: '',
},
confirmText: {
type: String,
default: "已拨打",
default: '已拨打',
},
cancelText: {
type: String,
default: "未拨打",
default: '未拨打',
},
});
const emit = defineEmits(["update:visible", "confirm", "cancel"]);
const emit = defineEmits(['update:visible', 'confirm', 'cancel']);
//
const handleConfirm = () => {
emit("confirm");
emit("update:visible", false);
emit('confirm');
emit('update:visible', false);
};
//
const handleCancel = () => {
emit("cancel");
emit("update:visible", false);
emit('cancel');
emit('update:visible', false);
};
//
@ -99,11 +95,7 @@ const handleOverlayClick = () => {
.confirm-dialog {
width: 80vw;
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);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
overflow: hidden;
@ -170,11 +162,7 @@ const handleOverlayClick = () => {
align-items: center;
justify-content: space-between;
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);
.header-title {

View File

@ -18,7 +18,13 @@
<div class="filter-row">
<div class="filter-item">
<span class="filter-label">影响区域</span>
<el-select :teleported="false" v-model="filterForm.region" placeholder="请选择" class="filter-select" clearable>
<el-select
:teleported="false"
v-model="filterForm.region"
placeholder="请选择"
class="filter-select"
clearable
>
<el-option
v-for="item in regionOptions"
:key="item.value"
@ -29,7 +35,13 @@
</div>
<div class="filter-item">
<span class="filter-label">驻地风险等级</span>
<el-select :teleported="false" v-model="filterForm.riskLevel" placeholder="请选择" class="filter-select" clearable>
<el-select
:teleported="false"
v-model="filterForm.riskLevel"
placeholder="请选择"
class="filter-select"
clearable
>
<el-option
v-for="item in riskLevelOptions"
:key="item.value"
@ -63,10 +75,10 @@
</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";
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: {
@ -75,12 +87,12 @@ const props = defineProps({
},
});
const emit = defineEmits(["update:visible", "close"]);
const emit = defineEmits(['update:visible', 'close']);
//
const filterForm = ref({
region: "",
riskLevel: "",
region: '',
riskLevel: '',
});
//
@ -106,35 +118,35 @@ const tableColumns = ref([
const tableData = ref([
{
id: 1,
region: "沙坪坝区",
stationName: "沙坪坝区S545茅山峡公路桥新建工程渝黔铁路扩能改造工程项目经理部",
project: "沙坪坝区S545茅山峡公路桥新建工程渝黔铁路扩能改造工程",
region: '沙坪坝区',
stationName: '沙坪坝区S545茅山峡公路桥新建工程渝黔铁路扩能改造工程项目经理部',
project: '沙坪坝区S545茅山峡公路桥新建工程渝黔铁路扩能改造工程',
peopleCount: 21,
riskLevel: "Ⅳ级",
riskLevel: 'Ⅳ级',
},
{
id: 2,
region: "万州区",
stationName: "万州区项目经理部",
project: "万州区公路改造项目",
region: '万州区',
stationName: '万州区项目经理部',
project: '万州区公路改造项目',
peopleCount: 15,
riskLevel: "Ⅲ级",
riskLevel: 'Ⅲ级',
},
{
id: 3,
region: "渝中区",
stationName: "渝中区桥梁维护项目部",
project: "渝中区桥梁维护工程",
region: '渝中区',
stationName: '渝中区桥梁维护项目部',
project: '渝中区桥梁维护工程',
peopleCount: 8,
riskLevel: "Ⅱ级",
riskLevel: 'Ⅱ级',
},
{
id: 4,
region: "江北区",
stationName: "江北区道路施工项目部",
project: "江北区道路施工项目",
region: '江北区',
stationName: '江北区道路施工项目部',
project: '江北区道路施工项目',
peopleCount: 32,
riskLevel: "Ⅰ级",
riskLevel: 'Ⅰ级',
},
]);
@ -162,43 +174,43 @@ const visiblePages = computed(() => {
});
//
const getRiskClass = (level) => {
const getRiskClass = level => {
const classMap = {
"Ⅰ级": "risk-level-1",
"Ⅱ级": "risk-level-2",
"Ⅲ级": "risk-level-3",
"Ⅳ级": "risk-level-4",
Ⅰ级: 'risk-level-1',
Ⅱ级: 'risk-level-2',
Ⅲ级: 'risk-level-3',
Ⅳ级: 'risk-level-4',
};
return classMap[level] || "";
return classMap[level] || '';
};
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
//
const handleSizeChange = (val) => {
const handleSizeChange = val => {
pageSize.value = val;
fetchData();
};
const handleCurrentChange = (val) => {
const handleCurrentChange = val => {
currentPage.value = val;
fetchData();
};
//
const fetchData = () => {
console.log("获取第", currentPage.value, "页数据");
console.log('获取第', currentPage.value, '页数据');
// API
};
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal) {
currentPage.value = 1;
fetchData();

View File

@ -18,7 +18,8 @@
<div class="filter-row">
<div class="filter-item">
<span class="filter-label">影响区域</span>
<el-select :teleported="false"
<el-select
:teleported="false"
v-model="filterForm.region"
placeholder="请选择"
popper-class="custom-select-popper"
@ -36,7 +37,8 @@
</div>
<div class="filter-item">
<span class="filter-label">类型</span>
<el-select :teleported="false"
<el-select
:teleported="false"
v-model="filterForm.type"
placeholder="请选择"
class="filter-select"
@ -56,10 +58,10 @@
</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";
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: {
@ -68,12 +70,12 @@ const props = defineProps({
},
});
const emit = defineEmits(["update:visible", "close"]);
const emit = defineEmits(['update:visible', 'close']);
//
const filterForm = ref({
region: "",
type: "",
region: '',
type: '',
});
//
@ -87,52 +89,52 @@ const tableHeight = ref(300);
//
const tableColumns = ref([
{ prop: "id", label: "序号", width: "60px" },
{ prop: "district", label: "区县/镇街", width: "120px" },
{ prop: "name", label: "姓名", width: "80px" },
{ prop: "phone", label: "电话", width: "120px" },
{ prop: "type", label: "类型", width: "120px" },
{ prop: "role", label: "角色", width: "120px" },
{ prop: "dispatchTime", label: "调度时间", width: "160px" },
{ prop: 'id', label: '序号', width: '60px' },
{ prop: 'district', label: '区县/镇街', width: '120px' },
{ prop: 'name', label: '姓名', width: '80px' },
{ prop: 'phone', label: '电话', width: '120px' },
{ prop: 'type', label: '类型', width: '120px' },
{ prop: 'role', label: '角色', width: '120px' },
{ prop: 'dispatchTime', label: '调度时间', width: '160px' },
]);
//
const tableData = ref([
{
id: 1,
district: "柏梓镇",
name: "赵海浪",
phone: "18623520681",
type: "交通主管部门",
role: "一般人员(路长履职)",
dispatchTime: "2025-08-11 04:53:42",
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",
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",
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",
district: '沙坪坝区',
name: '李华',
phone: '18623520683',
type: '护路员',
role: '一般人员',
dispatchTime: '2025-08-09 09:15:30',
},
]);
@ -161,36 +163,36 @@ const visiblePages = computed(() => {
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
//
const handleSizeChange = (val) => {
const handleSizeChange = val => {
pageSize.value = val;
fetchData();
};
const handleCurrentChange = (val) => {
const handleCurrentChange = val => {
currentPage.value = val;
fetchData();
};
//
const fetchData = () => {
console.log("获取第", currentPage.value, "页数据");
console.log('获取第', currentPage.value, '页数据');
// API
};
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal) {
currentPage.value = 1;
fetchData();
}
},
}
);
</script>

View File

@ -18,7 +18,8 @@
<div class="filter-row">
<div class="filter-item">
<span class="filter-label">影响区域</span>
<el-select :teleported="false"
<el-select
:teleported="false"
v-model="filterForm.region"
placeholder="请选择"
class="filter-select"
@ -37,18 +38,16 @@
<!-- 调度数列插槽 -->
<template #dispatchCount="{ row }">
<span class="dispatch-count" @click="handleDispatchClick(row)">{{
row.dispatchCount
}}</span>
<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";
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: {
@ -58,14 +57,14 @@ const props = defineProps({
});
const emit = defineEmits({
"update:visible": (value) => typeof value === "boolean",
'update:visible': value => typeof value === 'boolean',
close: () => true,
dispatchClick: (item) => item !== undefined,
dispatchClick: item => item !== undefined,
});
//
const filterForm = ref({
region: "",
region: '',
});
//
@ -76,37 +75,37 @@ const tableHeight = ref(300);
//
const tableColumns = ref([
{ prop: "id", label: "序号", width: "" },
{ prop: "region", label: "影响区域", width: "" },
{ prop: "dispatchCount", label: "调度数", width: "", slot: "dispatchCount" },
{ prop: "lastDispatchTime", label: "最近调度时间", width: "" },
{ prop: 'id', label: '序号', width: '' },
{ prop: 'region', label: '影响区域', width: '' },
{ prop: 'dispatchCount', label: '调度数', width: '', slot: 'dispatchCount' },
{ prop: 'lastDispatchTime', label: '最近调度时间', width: '' },
]);
//
const tableData = ref([
{
id: 1,
region: "重庆市",
region: '重庆市',
dispatchCount: 1,
lastDispatchTime: "2025-08-11 04:53:42",
lastDispatchTime: '2025-08-11 04:53:42',
},
{
id: 2,
region: "万州区",
region: '万州区',
dispatchCount: 1,
lastDispatchTime: "2025-08-11 04:53:42",
lastDispatchTime: '2025-08-11 04:53:42',
},
{
id: 3,
region: "沙坪坝区",
region: '沙坪坝区',
dispatchCount: 3,
lastDispatchTime: "2025-08-10 16:20:15",
lastDispatchTime: '2025-08-10 16:20:15',
},
{
id: 4,
region: "渝中区",
region: '渝中区',
dispatchCount: 2,
lastDispatchTime: "2025-08-09 11:45:30",
lastDispatchTime: '2025-08-09 11:45:30',
},
]);
@ -135,43 +134,43 @@ const visiblePages = computed(() => {
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
//
const handleDispatchClick = (item) => {
emit("dispatchClick", item);
const handleDispatchClick = item => {
emit('dispatchClick', item);
};
//
const handleSizeChange = (val) => {
const handleSizeChange = val => {
pageSize.value = val;
fetchData();
};
const handleCurrentChange = (val) => {
const handleCurrentChange = val => {
currentPage.value = val;
fetchData();
};
//
const fetchData = () => {
console.log("获取第", currentPage.value, "页数据");
console.log('获取第', currentPage.value, '页数据');
// API
};
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal) {
currentPage.value = 1;
//
filterForm.value.region = "";
filterForm.value.region = '';
fetchData();
}
},
}
);
</script>

View File

@ -21,118 +21,132 @@
<span class="title-icon"></span>
事件基本信息
</div>
<div class="info-grid">
<div class="info-row">
<div class="info-item">
<span class="info-label">事件编号</span>
<span class="info-value">{{ eventInfo.eventNo }}</span>
</div>
<div class="info-item">
<span class="info-label">发生时间</span>
<span class="info-value">{{ eventInfo.occurTime }}</span>
<!-- 事件类型标签 -->
<div class="event-type-tag">{{ eventInfo.eventType }}</div>
<!-- 三列信息网格 -->
<div class="info-grid-three">
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">路况类型</div>
<div class="info-value">{{ eventInfo.roadConditionType }}</div>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">事件类型</span>
<span class="info-value">{{ eventInfo.eventType }}</span>
</div>
<div class="info-item">
<span class="info-label">事件等级</span>
<span
class="info-value level-tag"
:class="eventInfo.levelClass"
>{{ eventInfo.eventLevel }}</span
>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">是否阻断</div>
<div class="info-value">{{ eventInfo.isBlocked }}</div>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">所属区域</span>
<span class="info-value">{{ eventInfo.region }}</span>
</div>
<div class="info-item">
<span class="info-label">上报人</span>
<span class="info-value">{{ eventInfo.reporter }}</span>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">上报区县</div>
<div class="info-value">{{ eventInfo.reportCounty }}</div>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">详细地址</span>
<span class="info-value">{{ eventInfo.address }}</span>
</div>
<div class="info-item">
<span class="info-label">上报时间</span>
<span class="info-value">{{ eventInfo.reportTime }}</span>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">阻断点小地名</div>
<div class="info-value">{{ eventInfo.blockLocation }}</div>
</div>
</div>
<div class="info-row">
<div class="info-item full-width">
<span class="info-label">事件描述</span>
<span class="info-value">{{ eventInfo.description }}</span>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">线路编码</div>
<div class="info-value">{{ eventInfo.routeCode }}</div>
</div>
</div>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">处理措施</div>
<div class="info-value">{{ eventInfo.handleMeasure }}</div>
</div>
</div>
<div class="info-item-three full-row">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">路况位置</div>
<div class="info-value">{{ eventInfo.roadPosition }}</div>
</div>
</div>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">起点桩号-止点桩号</div>
<div class="info-value">{{ eventInfo.stakeRange }}</div>
</div>
</div>
<div class="info-item-three">
<span class="info-dot"></span>
<div>
<div style="margin-bottom: 5px" class="info-label">发现时间</div>
<div class="info-value">{{ eventInfo.discoverTime }}</div>
</div>
</div>
</div>
</div>
<!-- 处置反馈信息 -->
<!-- 填报动态信息 -->
<div class="section">
<div class="section-title">
<span class="title-icon"></span>
处置反馈信息
填报动态信息
</div>
<div class="feedback-list">
<div
v-for="(item, index) in feedbackList"
:key="item.id"
class="feedback-item"
>
<div class="feedback-header">
<div class="feedback-num">{{ index + 1 }}</div>
<div class="feedback-info">
<div class="feedback-row">
<span class="feedback-label">处置时间</span>
<span class="feedback-value">{{ item.handleTime }}</span>
</div>
<div class="feedback-row">
<span class="feedback-label">处置人</span>
<span class="feedback-value">{{ item.handler }}</span>
</div>
</div>
<div class="feedback-image" @click="previewImage(item.image)">
<img :src="item.image" alt="处置图片" />
<div class="timeline-list">
<div v-for="(item, index) in feedbackList" :key="item.id" class="timeline-item">
<div class="timeline-left">
<div class="timeline-badge" :class="{ 'first-report': item.isFirst }">
{{ item.reportType }}
</div>
<div class="timeline-number">{{ index + 1 }}</div>
</div>
<div class="feedback-detail">
<div class="detail-row">
<span class="detail-label">预计开始时间</span>
<span class="detail-value">{{
item.estimatedStartTime
}}</span>
<span class="detail-label" style="margin-left: 40px"
>预计结束时间</span
>
<span class="detail-value">{{ item.estimatedEndTime }}</span>
<div class="timeline-content">
<div class="timeline-row">
<span class="timeline-label">报送时间</span>
<span class="timeline-value">{{ item.reportTime }}</span>
</div>
<div class="detail-row">
<span class="detail-label">实际开始时间</span>
<span class="detail-value">{{ item.actualStartTime }}</span>
<span class="detail-label" style="margin-left: 40px"
>实际结束时间</span
>
<span class="detail-value">{{ item.actualEndTime }}</span>
<div class="timeline-row">
<span class="timeline-label">处置措施</span>
<span class="timeline-value highlight">{{ item.handleMeasure }}</span>
</div>
<div class="detail-row">
<span class="detail-label">处置人</span>
<span class="detail-value">{{ item.handlerName }}</span>
<span class="detail-label" style="margin-left: 40px"
>联系电话</span
>
<span class="detail-value">{{ item.contactPhone }}</span>
<div class="timeline-row two-col">
<div class="col-item">
<span class="timeline-label">预计恢复时间</span>
<span class="timeline-value">{{ item.estimatedRecoverTime }}</span>
</div>
<div class="col-item">
<span class="timeline-label">实际恢复时间</span>
<span class="timeline-value">{{ item.actualRecoverTime }}</span>
</div>
</div>
<div class="detail-row">
<span class="detail-label">处置情况描述</span>
<span class="detail-value">{{ item.handleDesc }}</span>
<div class="timeline-row two-col">
<div class="col-item">
<span class="timeline-label">填报人</span>
<span class="timeline-value">{{ item.reporter }}</span>
</div>
<div class="col-item">
<span class="timeline-label">联系电话</span>
<span class="timeline-value">{{ item.contactPhone }}</span>
</div>
</div>
<div class="timeline-row">
<span class="timeline-label">现场情况描述</span>
<span class="timeline-value highlight">{{ item.sceneDesc }}</span>
</div>
<div class="timeline-images" v-if="item.images && item.images.length > 0">
<div
v-for="(img, imgIndex) in item.images"
:key="imgIndex"
class="timeline-image"
@click="previewImage(img)"
>
<img :src="img" alt="现场图片" />
</div>
</div>
</div>
</div>
@ -143,11 +157,7 @@
</base-dialog>
<!-- 图片预览弹窗 -->
<div
v-if="previewVisible"
class="image-preview-overlay"
@click="closePreview"
>
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
<div class="image-preview-container" @click.stop>
<img :src="previewImageUrl" alt="预览" />
<div class="close-preview-btn" @click="closePreview">
@ -158,9 +168,11 @@
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
import baseDialog from "../component/baseDialog.vue";
import { ref, watch, onMounted } from 'vue';
import { Close } from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
import { request } from '@/utils/request';
import { formatDateTime } from '../component/index.js';
const props = defineProps({
visible: {
@ -172,116 +184,189 @@ const props = defineProps({
default: () => ({}),
},
});
const emit = defineEmits(["update:visible", "close"]);
onMounted(() => {
console.log('props.eventData', props.eventData);
});
const emit = defineEmits(['update:visible', 'close']);
//
const eventInfo = ref({
eventNo: "202310120001",
occurTime: "2023-10-12 14:30:00",
eventType: "路面塌陷",
eventLevel: "一般事件",
levelClass: "level-normal",
region: "万州区",
reporter: "张三",
address: "万州区太白路123号附近",
reportTime: "2023-10-12 14:35:00",
description:
"路面出现塌陷面积约2平方米深度约0.5米,已设置警示标志,请尽快处理。",
eventType: '',
roadConditionType: '',
isBlocked: '',
reportCounty: '',
blockLocation: '',
routeCode: '',
handleMeasure: '',
roadPosition: '',
stakeRange: '',
discoverTime: '',
});
//
const feedbackList = ref([
{
id: 1,
handleTime: "2023-10-12 14:45:26",
handler: "李四",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=图片1",
estimatedStartTime: "2023-10-12 14:30:00",
estimatedEndTime: "2023-10-12 16:30:00",
actualStartTime: "2023-10-12 14:45:00",
actualEndTime: "2023-10-12 16:20:00",
handlerName: "王五",
contactPhone: "13800138000",
handleDesc: "已到达现场,正在设置围挡,准备进行修复作业。",
},
{
id: 2,
handleTime: "2023-10-12 16:20:45",
handler: "李四",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=图片2",
estimatedStartTime: "2023-10-12 14:30:00",
estimatedEndTime: "2023-10-12 16:30:00",
actualStartTime: "2023-10-12 14:45:00",
actualEndTime: "2023-10-12 16:20:00",
handlerName: "王五",
contactPhone: "13800138000",
handleDesc: "修复作业已完成,路面已恢复平整,围挡已拆除,交通恢复正常。",
},
]);
//
const feedbackList = ref([]);
//
const fetchEventDetail = async () => {
try {
const gl1SjId = props.eventData?.gl1SjId;
if (!gl1SjId) {
console.warn('gl1SjId 不存在');
return;
}
const res = await request({
url: '/snow-ops-platform/sm-event/detail-by-sjid',
method: 'GET',
params: {
sjid: gl1SjId + '',
// sjid: '00092c5f0c054c67b0ad00071dd94630',
},
});
if (res && res.code === '00000') {
// - API
const data = res.data || {};
eventInfo.value = {
// eventType:
eventType: data.eventType || '-',
// eventLevel: ->
roadConditionType: data.eventLevel || '-',
// isBlocked: eventDesc
isBlocked: data.eventDesc?.includes('阻断') ? '是' : '否',
// district: ->
reportCounty: data.district || '-',
// detailAddress: ->
blockLocation: data.detailAddress || '-',
// eventNo: -> 线
routeCode: data.eventNo || '-',
// eventDesc: ->
handleMeasure: data.eventDesc || '-',
// detailAddress: ->
roadPosition: data.detailAddress || '-',
// stakeRange
stakeRange: formatStakeRangeFromData(data),
// occurTime: ->
discoverTime: formatDateTime(data.occurTime) || '-',
};
console.log('eventInfo', eventInfo.value);
// - API
if (data.handleList && Array.isArray(data.handleList)) {
feedbackList.value = data.handleList.map((item, index) => ({
id: index + 1,
isFirst: index === 0,
reportType: index === 0 ? '首报' : '续报',
// disposeTime:
reportTime: formatDateTime(item.disposeTime) || '-',
// handleMeasure: disposeDesc
handleMeasure: item.disposeDesc?.substring(0, 10) || '-',
// expectStartTime:
estimatedRecoverTime: formatDateTime(item.expectStartTime) || '-',
// actualStartTime:
actualRecoverTime: formatDateTime(item.actualStartTime) || '-',
// disposer:
reporter: item.disposer || '-',
// contactPhone:
contactPhone: item.contactPhone || '-',
// disposeDesc:
sceneDesc: item.disposeDesc || '-',
}));
} else {
feedbackList.value = [];
}
}
} catch (error) {
console.error('获取事件详情失败:', error);
}
};
//
const formatRoadPosition = data => {
const parts = [];
if (data.gl1Qxmc) parts.push(data.gl1Qxmc);
if (data.gl1Zddxdm) parts.push(data.gl1Zddxdm);
if (data.gl1Lxbh) parts.push(data.gl1Lxbh);
return parts.length > 0 ? parts.join('') : '-';
};
//
const formatStakeRange = data => {
const start = data.gl1Qdzh || '';
const end = data.gl1Zdzh || '';
if (start && end) return `${start}-${end}`;
if (start) return start;
if (end) return end;
return '-';
};
// API- APIdetailAddress'-'
const formatStakeRangeFromData = data => {
// APIdetailAddress'-'
// API
return '-';
};
//
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewImageUrl = ref('');
const previewImage = (url) => {
const previewImage = url => {
previewImageUrl.value = url;
previewVisible.value = true;
};
const closePreview = () => {
previewVisible.value = false;
previewImageUrl.value = "";
previewImageUrl.value = '';
};
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
// base-dialog
// visible
// eventData
watch(
() => props.visible,
(newVal) => {
if (newVal && props.eventData) {
//
Object.assign(eventInfo.value, props.eventData);
newVal => {
if (newVal) {
fetchEventDetail();
}
},
}
);
</script>
<style lang="scss" scoped>
.content-wrapper{
height: 500px;
.content-wrapper {
width: 700px;
height: 70vh;
overflow-y: auto;
//
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: rgba(20, 46, 73, 0.3);
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #142E49;
background: #142e49;
border-radius: 3px;
&:hover {
background: #1a3a5c;
}
}
// Firefox
scrollbar-width: thin;
scrollbar-color: #142E49 rgba(20, 46, 73, 0.3);
scrollbar-color: #142e49 rgba(20, 46, 73, 0.3);
}
//
.section {
margin-bottom: 24px;
@ -306,132 +391,165 @@ watch(
}
}
//
.info-grid {
background-color: rgba(30, 70, 120, 0.3);
border-radius: 8px;
padding: 16px 20px;
//
.event-type-tag {
display: inline-block;
background-color: #40a9ff;
color: #fff;
padding: 4px 16px;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
margin-bottom: 16px;
}
.info-row {
//
.info-grid-three {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px 20px;
}
.info-item-three {
display: flex;
margin-bottom: 12px;
// align-items: center;
gap: 8px;
.info-dot {
color: #40a9ff;
font-size: 10px;
flex-shrink: 0;
}
.info-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
white-space: nowrap;
flex-shrink: 0;
}
.info-value {
font-size: 13px;
color: #40a9ff;
word-break: break-all;
}
}
//
.timeline-list {
position: relative;
padding-left: 20px;
// &::before {
// content: '';
// position: absolute;
// left: 34px;
// top: 0;
// bottom: 0;
// width: 2px;
// background: linear-gradient(to bottom, #40a9ff, rgba(64, 169, 255, 0.3));
// }
}
.timeline-item {
display: flex;
margin-bottom: 20px;
position: relative;
&:last-child {
margin-bottom: 0;
}
}
.info-item {
flex: 1;
.timeline-left {
display: flex;
align-items: flex-start;
&.full-width {
flex: none;
width: 100%;
}
// flex-direction: column;
// align-items: center;
margin-right: 16px;
position: relative;
z-index: 1;
}
.info-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
.timeline-badge {
background-color: #52c41a;
color: #fff;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
min-width: 70px;
}
height: 28px;
width: 50px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
.info-value {
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
flex: 1;
word-break: break-all;
&.level-tag {
display: inline-block;
padding: 2px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
&.level-urgent {
background-color: rgba(255, 77, 79, 0.2);
color: #ff4d4f;
border: 1px solid rgba(255, 77, 79, 0.4);
}
&.level-normal {
background-color: rgba(64, 169, 255, 0.2);
color: #40a9ff;
border: 1px solid rgba(64, 169, 255, 0.4);
}
&.level-low {
background-color: rgba(82, 196, 26, 0.2);
color: #52c41a;
border: 1px solid rgba(82, 196, 26, 0.4);
}
&.first-report {
background-color: #40a9ff;
}
}
//
.feedback-list {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 10px;
}
.feedback-item {
background-color: rgba(30, 70, 120, 0.3);
border-radius: 8px;
padding: 16px 20px;
border-left: 3px solid #40a9ff;
}
.feedback-header {
display: flex;
align-items: flex-start;
margin-bottom: 12px;
}
.feedback-num {
width: 24px;
height: 24px;
.timeline-number {
width: 28px;
height: 28px;
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-size: 14px;
font-weight: 600;
color: #fff;
margin-right: 12px;
flex-shrink: 0;
border: 2px solid rgba(255, 255, 255, 0.2);
}
.feedback-info {
.timeline-content {
flex: 1;
background-color: rgba(30, 70, 120, 0.3);
border-radius: 8px;
padding: 12px 16px;
margin-left: 8px;
}
.feedback-row {
margin-bottom: 6px;
.timeline-row {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
&.two-col {
display: flex;
gap: 40px;
.col-item {
display: flex;
align-items: center;
gap: 8px;
}
}
}
.feedback-label {
.timeline-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
}
.feedback-value {
.timeline-value {
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
&.highlight {
color: #40a9ff;
}
}
.feedback-image {
.timeline-images {
display: flex;
gap: 8px;
margin-top: 8px;
}
.timeline-image {
width: 80px;
height: 60px;
border-radius: 4px;
@ -452,31 +570,6 @@ watch(
}
}
//
.feedback-detail {
padding-left: 36px;
padding-top: 12px;
border-top: 1px solid rgba(64, 169, 255, 0.1);
}
.detail-row {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
.detail-label {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
}
.detail-value {
font-size: 12px;
color: rgba(255, 255, 255, 0.8);
}
//
.image-preview-overlay {
position: fixed;

View File

@ -296,6 +296,7 @@ watch(
<style lang="scss" scoped>
.hazard-info-panel {
height: 500px;
width: 600px;
color: rgba(255, 255, 255, 0.9);
overflow-y: auto;
//

View File

@ -32,11 +32,9 @@
<div class="info-item">
<span class="info-dot"></span>
<span class="info-label">影响点等级</span>
<span
class="info-value level-tag"
:class="basicInfo.levelClass"
>{{ basicInfo.level }}</span
>
<span class="info-value level-tag" :class="basicInfo.levelClass">
{{ basicInfo.level }}
</span>
</div>
<div class="info-item">
<span class="info-dot"></span>
@ -53,11 +51,9 @@
<div class="info-item">
<span class="info-dot"></span>
<span class="info-label">风险点描述</span>
<span
class="info-value"
:class="getStatusClass(basicInfo.riskDesc)"
>{{ basicInfo.riskDesc }}</span
>
<span class="info-value" :class="getStatusClass(basicInfo.riskDesc)">
{{ basicInfo.riskDesc }}
</span>
</div>
<div class="info-item">
<span class="info-dot"></span>
@ -93,11 +89,7 @@
填报动态信息
</div>
<div class="timeline-list">
<div
v-for="(record, index) in dynamicRecords"
:key="index"
class="timeline-item"
>
<div v-for="(record, index) in dynamicRecords" :key="index" class="timeline-item">
<div class="timeline-marker">{{ index + 1 }}</div>
<div class="timeline-content">
<div class="timeline-header">
@ -128,8 +120,9 @@
<span
class="detail-value"
:class="record.hasProblem ? 'status-yes' : 'status-no'"
>{{ record.hasProblem ? "是" : "否" }}</span
>
{{ record.hasProblem ? '是' : '否' }}
</span>
</div>
</div>
</div>
@ -141,11 +134,7 @@
</base-dialog>
<!-- 图片预览弹窗 -->
<div
v-if="previewVisible"
class="image-preview-overlay"
@click="closePreview"
>
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
<div class="image-preview-container" @click.stop>
<img :src="previewImageUrl" alt="预览" />
<div class="close-preview-btn" @click="closePreview">
@ -156,10 +145,10 @@
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
import baseDialog from "../component/baseDialog.vue";
import { request } from "@/utils/request";
import { ref, watch } from 'vue';
import { Close } from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
import { request } from '@/utils/request';
const props = defineProps({
visible: {
@ -176,18 +165,17 @@ const props = defineProps({
},
});
const emit = defineEmits(["update:visible", "close"]);
const emit = defineEmits(['update:visible', 'close']);
//
const basicInfo = ref({
district: "合川区",
level: "一般隐患",
levelClass: "level-normal",
roadCode: "G348",
location: "丁吴路(K116+656至K116+739)",
riskDesc: "未回应",
discoverTime:
"立即启动防汛Ⅰ级应急响应,立即转移危险区群众,医疗机构做好应急准备",
district: '合川区',
level: '一般隐患',
levelClass: 'level-normal',
roadCode: 'G348',
location: '丁吴路(K116+656至K116+739)',
riskDesc: '未回应',
discoverTime: '立即启动防汛Ⅰ级应急响应,立即转移危险区群众,医疗机构做好应急准备',
});
//
@ -196,61 +184,61 @@ const photoList = ref([]);
//
const dynamicRecords = ref([
{
type: "首报",
patrolTime: "2026-03-28 14:30:00",
patrolPerson: "刘伟",
description: "设置警示标识,半幅通行",
type: '首报',
patrolTime: '2026-03-28 14:30:00',
patrolPerson: '刘伟',
description: '设置警示标识,半幅通行',
hasProblem: true,
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场",
image: 'https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场',
},
{
type: "续报",
patrolTime: "2026-03-28 14:30:00",
patrolPerson: "刘伟",
description: "设置警示标识,半幅通行",
type: '续报',
patrolTime: '2026-03-28 14:30:00',
patrolPerson: '刘伟',
description: '设置警示标识,半幅通行',
hasProblem: false,
image: null,
},
]);
//
const getStatusClass = (status) => {
if (status === "未回应") return "status-unresponse";
if (status === "已回应") return "status-response";
return "";
const getStatusClass = status => {
if (status === '未回应') return 'status-unresponse';
if (status === '已回应') return 'status-response';
return '';
};
//
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewImageUrl = ref('');
const previewImage = (url) => {
const previewImage = url => {
previewImageUrl.value = url;
previewVisible.value = true;
};
const closePreview = () => {
previewVisible.value = false;
previewImageUrl.value = "";
previewImageUrl.value = '';
};
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
const leveltext = (level) => {
if (level.includes("一") || level.includes("1")) return "一类";
if (level.includes("二") || level.includes("2")) return "二类";
if (level.includes("三") || level.includes("3")) return "三类";
if (level.includes("四") || level.includes("4")) return "四类";
if (level.includes("五") || level.includes("5")) return "五类";
if (level.includes("9")) return "未评定";
return "未评定";
const leveltext = level => {
if (level.includes('一') || level.includes('1')) return '一类';
if (level.includes('二') || level.includes('2')) return '二类';
if (level.includes('三') || level.includes('3')) return '三类';
if (level.includes('四') || level.includes('4')) return '四类';
if (level.includes('五') || level.includes('5')) return '五类';
if (level.includes('9')) return '未评定';
return '未评定';
};
// base-dialog
//
const getAffectedObjectTypeId = (data) => {
const getAffectedObjectTypeId = data => {
let pointType = props.item.pointType;
if (!data) {
basicInfo.value = {};
@ -258,19 +246,19 @@ const getAffectedObjectTypeId = (data) => {
dynamicRecords.value = [];
return;
}
if (pointType === "桥梁") {
if (pointType === '桥梁') {
// -
basicInfo.value = {
district: data.GL1_QXMC || "-", //
level: leveltext(data.GL1_JSZKPJDJ) || "未评定", //
district: data.GL1_QXMC || '-', //
level: leveltext(data.GL1_JSZKPJDJ) || '未评定', //
levelClass:
data.GL1_JSZKPJDJ === "一类" || data.GL1_JSZKPJDJ === "二类"
? "level-normal"
: "level-serious", //
roadCode: data.GL1_LXBH || "-", // 线
location: data.GL1_QLMC || "-", //
riskDesc: data.GL1_DQBH || "-", //
discoverTime: data.GL1_JSZKPDRQ || "-", //
data.GL1_JSZKPJDJ === '一类' || data.GL1_JSZKPJDJ === '二类'
? 'level-normal'
: 'level-serious', //
roadCode: data.GL1_LXBH || '-', // 线
location: data.GL1_QLMC || '-', //
riskDesc: data.GL1_DQBH || '-', //
discoverTime: data.GL1_JSZKPDRQ || '-', //
};
// - 使
const photos = [];
@ -291,29 +279,29 @@ const getAffectedObjectTypeId = (data) => {
// - 使
dynamicRecords.value = [
{
type: "桥梁信息",
patrolTime: data.GL1_JCTCRQ || "-", //
patrolPerson: data.GL1_QLZRR || "-", //
description: `桥梁全长:${data.GL1_QLQC || "-"}m跨径总长${data.GL1_KJZC || "-"}m上部结构${data.GL1_SBJGLXMC || "-"}`,
type: '桥梁信息',
patrolTime: data.GL1_JCTCRQ || '-', //
patrolPerson: data.GL1_QLZRR || '-', //
description: `桥梁全长:${data.GL1_QLQC || '-'}m跨径总长${data.GL1_KJZC || '-'}m上部结构${data.GL1_SBJGLXMC || '-'}`,
hasProblem: false,
image: null,
},
];
} else if (pointType === "边坡") {
} else if (pointType === '边坡') {
//
const data = resData || {};
// -
basicInfo.value = {
district: data.GL1_QXMC || "-", //
level: leveltext(data.GL1_FXDJ) || "未评定", //
district: data.GL1_QXMC || '-', //
level: leveltext(data.GL1_FXDJ) || '未评定', //
levelClass:
data.GL1_FXDJ?.includes("一级") || data.GL1_FXDJ?.includes("二级")
? "level-normal"
: "level-serious", //
roadCode: data.GL1_LXBM || "-", // 线
location: data.GL1_BPGC || "-", //
riskDesc: data.GL1_JCSSSZ || "-", //
discoverTime: data.GL1_ZRRXM || "-", //
data.GL1_FXDJ?.includes('一级') || data.GL1_FXDJ?.includes('二级')
? 'level-normal'
: 'level-serious', //
roadCode: data.GL1_LXBM || '-', // 线
location: data.GL1_BPGC || '-', //
riskDesc: data.GL1_JCSSSZ || '-', //
discoverTime: data.GL1_ZRRXM || '-', //
};
// -
@ -326,27 +314,25 @@ const getAffectedObjectTypeId = (data) => {
// -
dynamicRecords.value = [
{
type: "边坡信息",
patrolTime: data.GL1_BPPGC || "-", //
patrolPerson: data.GL1_ZRRXM || "-", //
description: `起点桩号:${data.GL1_QDZH || "-"},终点桩号:${data.GL1_ZDZH || "-"},起点经度:${data.GL1_QDJD || "-"},起点纬度:${data.GL1_QDWD || "-"},监测设施:${data.GL1_JCSSSZ || "-"},综合措施:${data.GL1_ZHXS || "-"}`,
hasProblem: data.GL1_JCSSSZ !== "无" && data.GL1_JCSSSZ !== null,
type: '边坡信息',
patrolTime: data.GL1_BPPGC || '-', //
patrolPerson: data.GL1_ZRRXM || '-', //
description: `起点桩号:${data.GL1_QDZH || '-'},终点桩号:${data.GL1_ZDZH || '-'},起点经度:${data.GL1_QDJD || '-'},起点纬度:${data.GL1_QDWD || '-'},监测设施:${data.GL1_JCSSSZ || '-'},综合措施:${data.GL1_ZHXS || '-'}`,
hasProblem: data.GL1_JCSSSZ !== '无' && data.GL1_JCSSSZ !== null,
image: null,
},
];
} else if (pointType === "隧道") {
} else if (pointType === '隧道') {
// -
basicInfo.value = {
district: data.GL1_QXMC || "-", //
level: leveltext(data.GL1_PDDJ) || "未评定", //
district: data.GL1_QXMC || '-', //
level: leveltext(data.GL1_PDDJ) || '未评定', //
levelClass:
data.GL1_PDDJ === "一级" || data.GL1_PDDJ === "二级"
? "level-normal"
: "level-serious", //
roadCode: data.GL1_LXBH || "-", // 线
location: data.GL1_SDMC || "-", //
riskDesc: data.GL1_BHMS || "-", //
discoverTime: data.GL1_PDRQ || "-", //
data.GL1_PDDJ === '一级' || data.GL1_PDDJ === '二级' ? 'level-normal' : 'level-serious', //
roadCode: data.GL1_LXBH || '-', // 线
location: data.GL1_SDMC || '-', //
riskDesc: data.GL1_BHMS || '-', //
discoverTime: data.GL1_PDRQ || '-', //
};
// - 使
@ -368,29 +354,27 @@ const getAffectedObjectTypeId = (data) => {
// -
dynamicRecords.value = [
{
type: "隧道信息",
patrolTime: data.GL1_XCTCSJ || "-", //
patrolPerson: data.GL1_GLDW || "-", //
description: `隧道全长:${data.GL1_SDC || "-"}m隧道净宽${data.GL1_SDJK || "-"}m围岩等级${data.GL1_WYDJ || "-"},衬砌类型:${data.GL1_CQLXMC || "-"}`,
type: '隧道信息',
patrolTime: data.GL1_XCTCSJ || '-', //
patrolPerson: data.GL1_GLDW || '-', //
description: `隧道全长:${data.GL1_SDC || '-'}m隧道净宽${data.GL1_SDJK || '-'}m围岩等级${data.GL1_WYDJ || '-'},衬砌类型:${data.GL1_CQLXMC || '-'}`,
hasProblem: false,
image: null,
},
];
} else if (pointType === "路段") {
} else if (pointType === '路段') {
//
const data = resData || {};
// -
basicInfo.value = {
district: data.GL1_QDMC || "-", //
level: leveltext(data.GL1_JSDJ) || "未评定", //
district: data.GL1_QDMC || '-', //
level: leveltext(data.GL1_JSDJ) || '未评定', //
levelClass:
data.GL1_JSDJ === "一级" || data.GL1_JSDJ === "二级"
? "level-normal"
: "level-serious", //
roadCode: data.GL1_LXBH || "-", // 线
location: `${data.GL1_QDMC || "-"} - ${data.GL1_ZDMC || "-"}`, //
riskDesc: data.GL1_TZSJ || "-", // /
discoverTime: data.GL1_XZDJ || "-", //
data.GL1_JSDJ === '一级' || data.GL1_JSDJ === '二级' ? 'level-normal' : 'level-serious', //
roadCode: data.GL1_LXBH || '-', // 线
location: `${data.GL1_QDMC || '-'} - ${data.GL1_ZDMC || '-'}`, //
riskDesc: data.GL1_TZSJ || '-', // /
discoverTime: data.GL1_XZDJ || '-', //
};
// -
@ -399,10 +383,10 @@ const getAffectedObjectTypeId = (data) => {
// -
dynamicRecords.value = [
{
type: "路段信息",
patrolTime: data.GL1_TZSJ || "-", //
patrolPerson: data.GL1_XZDJ || "-", //
description: `路段长度:${data.GL1_LDLC || "-"}km路面宽度${data.GL1_LMKD || "-"}m路面类型${data.GL1_LMLX || "-"},车道数量:${data.GL1_CDSL || "-"}`,
type: '路段信息',
patrolTime: data.GL1_TZSJ || '-', //
patrolPerson: data.GL1_XZDJ || '-', //
description: `路段长度:${data.GL1_LDLC || '-'}km路面宽度${data.GL1_LMKD || '-'}m路面类型${data.GL1_LMLX || '-'},车道数量:${data.GL1_CDSL || '-'}`,
hasProblem: false,
image: null,
},
@ -413,52 +397,52 @@ const getAffectedObjectTypeId = (data) => {
//
const getAffectedObjectDetail = async () => {
try {
let id = "";
let apiUrl = "";
let id = '';
let apiUrl = '';
const pointType = props.item?.pointType;
if (pointType === "桥梁") {
id = props.item?.rawData?.GL1_ZJ || "";
if (pointType === '桥梁') {
id = props.item?.rawData?.GL1_ZJ || '';
apiUrl = `/snow-ops-platform/weather-warning/affected-object/bridge/${id}`;
} else if (pointType === "边坡") {
id = props.item?.rawData?.GL1_ID || "";
} else if (pointType === '边坡') {
id = props.item?.rawData?.GL1_ID || '';
apiUrl = `/snow-ops-platform/weather-warning/affected-object/slope/${id}`;
} else if (pointType === "隧道") {
id = props.item?.rawData?.GL1_ZJ || "";
} else if (pointType === '隧道') {
id = props.item?.rawData?.GL1_ZJ || '';
apiUrl = `/snow-ops-platform/weather-warning/affected-object/tunnel/${id}`;
} else if (pointType === "路段") {
id = props.item?.rawData?.GL1ZJ || "";
} else if (pointType === '路段') {
id = props.item?.rawData?.GL1ZJ || '';
apiUrl = `/snow-ops-platform/weather-warning/affected-object/road-section/${id}`;
}
if (!id || !apiUrl) {
console.warn("未找到影响点ID或API地址");
console.warn('未找到影响点ID或API地址');
return;
}
const res = await request({
url: apiUrl,
method: "GET",
method: 'GET',
});
console.log("影响点详情数据:", res);
if (res.code === "00000") {
console.log('影响点详情数据:', res);
if (res.code === '00000') {
getAffectedObjectTypeId(res.data || {});
}
} catch (error) {
console.error("获取影响点详情数据失败:", error);
console.error('获取影响点详情数据失败:', error);
}
};
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal) {
//
getAffectedObjectDetail();
}
},
}
);
</script>

View File

@ -216,7 +216,7 @@ import Icon3 from '../../../assets/xiangying/未选中3@2x.png';
import Icon4 from '../../../assets/xiangying/未选中4@2x.png';
import { formatDateTime } from '../component/index.js';
onMounted(() => {});
const props = defineProps({
visible: {
type: Boolean,
@ -386,12 +386,17 @@ const cardTypeVal = ref('路段');
// cardType
const getColumnsByType = type => {
const typeMap = {
0: bridgeColumns,
1: slopeColumns,
2: tunnelColumns,
3: projectColumns,
4: roadColumns,
路段: bridgeColumns,
桥梁: slopeColumns,
隧道: tunnelColumns,
边坡: roadColumns,
项目: projectColumns,
};
// { name: '', count: 0, icon: Icon4, type: '' },
// { name: '', count: 0, icon: Icon0, type: '' },
// { name: '', count: 0, icon: Icon2, type: '' },
// { name: '', count: 0, icon: Icon1, type: '' },
// { name: '', count: 0, icon: Icon3, type: '' },
return typeMap[type] || bridgeColumns;
};
@ -413,7 +418,7 @@ const handleClick = (index, item) => {
cardType.value = index + '';
cardTypeVal.value = item.type;
//
tableColumns.value = getColumnsByType(cardType.value);
tableColumns.value = getColumnsByType(item.type);
//
currentPage.value = 1;
fetchData();
@ -797,6 +802,7 @@ watch(
pointLevel: '',
region: '',
};
tableData.value = [];
cardType.value = '0';
loadBarChartData();
currentPage.value = 1;

View File

@ -215,7 +215,7 @@ const dialogItems = computed(() => {
},
{
label: '位置',
value: data.GL1_GLMC ,
value: data.GL1_GLMC,
},
{
label: '风险描述',
@ -232,7 +232,7 @@ const dialogItems = computed(() => {
];
case 'emergency':
return [
{ label: '队伍名称', value: data.gl1Yjllmc || '-' },
{ label: '队伍名称', value: data.gl1Yjllmc || '-' },
{ label: '防范状态', value: data.preventionStatus || '-' },
{ label: '人数', value: data.gl1Rysl || '-' },
{ label: '联系人', value: data.gl1Lxr || '-' },

View File

@ -59,9 +59,6 @@ import baseDialog from '../component/baseDialog.vue';
import { request } from '@/utils/request';
import { regionOptions } from '../component/index.js';
const props = defineProps({
visible: {
type: Boolean,
@ -79,7 +76,6 @@ const filterForm = ref({
//
const countyOptions = ref(regionOptions);
//
const tableColumns = ref([
{ prop: 'id', label: '序号', width: '' },
@ -114,18 +110,18 @@ const handleSearch = () => {
};
//
const handleSizeChange = (val) => {
const handleSizeChange = val => {
pageSize.value = val;
fetchData();
};
const handleCurrentChange = (val) => {
const handleCurrentChange = val => {
currentPage.value = val;
fetchData();
};
//
const handleAttachmentClick = (row) => {
const handleAttachmentClick = row => {
console.log('点击附件:', row);
//
};
@ -168,7 +164,7 @@ const fetchData = async () => {
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal) {
currentPage.value = 1;
fetchData();

View File

@ -31,11 +31,9 @@
</div>
<div class="info-item">
<span class="info-label">影响点等级</span>
<span
class="info-value level-tag"
:class="basicInfo.levelClass"
>{{ basicInfo.level }}</span
>
<span class="info-value level-tag" :class="basicInfo.levelClass">
{{ basicInfo.level }}
</span>
</div>
<div class="info-item">
<span class="info-label">公路编号</span>
@ -85,11 +83,7 @@
</div>
<div class="patrol-list">
<!-- 巡查记录列表 -->
<div
v-for="(record, index) in patrolRecords"
:key="index"
class="patrol-record-item"
>
<div v-for="(record, index) in patrolRecords" :key="index" class="patrol-record-item">
<div class="patrol-number">{{ index + 1 }}</div>
<div class="patrol-content">
<div class="patrol-row">
@ -111,11 +105,7 @@
<span class="patrol-value">{{ record.hasIssue }}</span>
</div>
</div>
<div
v-if="record.image"
class="patrol-image"
@click="previewImage(record.image)"
>
<div v-if="record.image" class="patrol-image" @click="previewImage(record.image)">
<img :src="record.image" alt="现场照片" />
</div>
</div>
@ -126,11 +116,7 @@
</base-dialog>
<!-- 图片预览弹窗 -->
<div
v-if="previewVisible"
class="image-preview-overlay"
@click="closePreview"
>
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
<div class="image-preview-container" @click.stop>
<img :src="previewImageUrl" alt="预览" />
<div class="close-preview-btn" @click="closePreview">
@ -141,9 +127,9 @@
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
import baseDialog from "../component/baseDialog.vue";
import { ref, watch } from 'vue';
import { Close } from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
const props = defineProps({
visible: {
@ -156,75 +142,74 @@ const props = defineProps({
},
});
const emit = defineEmits(["update:visible", "close", "viewTrack"]);
const emit = defineEmits(['update:visible', 'close', 'viewTrack']);
//
const basicInfo = ref({
district: "合川区",
level: "一般隐患",
levelClass: "level-normal",
roadCode: "G348",
location: "丁吴路(K116+656至K116+739)",
district: '合川区',
level: '一般隐患',
levelClass: 'level-normal',
roadCode: 'G348',
location: '丁吴路(K116+656至K116+739)',
riskDesc:
"泥岩风化严重,受雨水冲刷影响,常有强风化岩体散落于边沟或塌散于路面(路面处落石已清理),影响道路正常使用。[类型:路内风险点-边坡]",
measures:
"拟对开裂边坡进行清方处理后,采取挂网喷射混凝土处理,部分路段增设挡土墙",
'泥岩风化严重,受雨水冲刷影响,常有强风化岩体散落于边沟或塌散于路面(路面处落石已清理),影响道路正常使用。[类型:路内风险点-边坡]',
measures: '拟对开裂边坡进行清方处理后,采取挂网喷射混凝土处理,部分路段增设挡土墙',
});
//
const photoList = ref([
"https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片1",
"https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片2",
'https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片1',
'https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片2',
]);
//
const patrolRecords = ref([
{
time: "2026-03-28 14:30:00",
person: "刘伟",
situation: "现场通行正常、无异常情况发生。",
hasIssue: "否",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场1",
time: '2026-03-28 14:30:00',
person: '刘伟',
situation: '现场通行正常、无异常情况发生。',
hasIssue: '否',
image: 'https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场1',
},
{
time: "2026-03-28 14:30:00",
person: "刘伟",
situation: "现场通行正常、无异常情况发生。",
hasIssue: "否",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场2",
time: '2026-03-28 14:30:00',
person: '刘伟',
situation: '现场通行正常、无异常情况发生。',
hasIssue: '否',
image: 'https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场2',
},
]);
//
const getStatusClass = (status) => {
if (status === "未回应") return "status-unresponse";
if (status === "已回应") return "status-response";
return "";
const getStatusClass = status => {
if (status === '未回应') return 'status-unresponse';
if (status === '已回应') return 'status-response';
return '';
};
//
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewImageUrl = ref('');
const previewImage = (url) => {
const previewImage = url => {
previewImageUrl.value = url;
previewVisible.value = true;
};
const closePreview = () => {
previewVisible.value = false;
previewImageUrl.value = "";
previewImageUrl.value = '';
};
//
const viewTrack = () => {
emit("viewTrack", patrolRecord.value);
emit('viewTrack', patrolRecord.value);
};
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
// base-dialog
@ -232,11 +217,11 @@ const handleClose = () => {
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal && props.pointData) {
Object.assign(basicInfo.value, props.pointData);
}
},
}
);
</script>
@ -502,7 +487,7 @@ watch(
position: relative;
&::after {
content: "";
content: '';
position: absolute;
top: 12px;
left: 50%;

View File

@ -47,12 +47,16 @@
<div class="info-item">
<span class="info-dot"></span>
<span class="info-label">回应状态</span>
<span class="info-value" :class="getStatusClass(basicInfo.responseStatus)">{{ basicInfo.responseStatus }}</span>
<span class="info-value" :class="getStatusClass(basicInfo.responseStatus)">
{{ basicInfo.responseStatus }}
</span>
</div>
<div class="info-item">
<span class="info-dot"></span>
<span class="info-label">审核状态</span>
<span class="info-value" :class="getAuditClass(basicInfo.auditStatus)">{{ basicInfo.auditStatus }}</span>
<span class="info-value" :class="getAuditClass(basicInfo.auditStatus)">
{{ basicInfo.auditStatus }}
</span>
</div>
</div>
<div class="info-row">
@ -117,7 +121,11 @@
<div class="detail-row">
<span class="detail-label">现场情况</span>
<span class="detail-text">{{ patrolRecord.situation }}</span>
<div v-if="patrolRecord.image" class="detail-image" @click="previewImage(patrolRecord.image)">
<div
v-if="patrolRecord.image"
class="detail-image"
@click="previewImage(patrolRecord.image)"
>
<img :src="patrolRecord.image" alt="现场照片" />
</div>
</div>
@ -133,9 +141,13 @@
<span class="timeline-type">{{ record.typeName }}</span>
<span class="timeline-person">{{ record.person }}</span>
<span class="timeline-time">{{ record.time }}</span>
<span v-if="record.status" class="timeline-status" :class="record.statusClass">{{ record.status }}</span>
<span v-if="record.status" class="timeline-status" :class="record.statusClass">
{{ record.status }}
</span>
<span v-if="record.target" class="timeline-target">
<span class="target-name">{{ record.target }}</span> {{ record.targetPhone }}
<span class="target-name">{{ record.target }}</span>
{{ record.targetPhone }}
</span>
</div>
</div>
@ -157,9 +169,9 @@
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
import baseDialog from "../component/baseDialog.vue";
import { ref, watch } from 'vue';
import { Close } from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
const props = defineProps({
visible: {
@ -172,112 +184,112 @@ const props = defineProps({
},
});
const emit = defineEmits(["update:visible", "close", "viewTrack"]);
const emit = defineEmits(['update:visible', 'close', 'viewTrack']);
//
const basicInfo = ref({
district: "合川区",
roadCode: "G542",
riskType: "风险路段",
riskLocation: "丁吴路(K116+656至K116+739)",
responseStatus: "未回应",
auditStatus: "未审核",
warningLevel: "红色预警",
stakeRange: "三级治理中心发布发布暴雨红色预警信号",
discoverTime: "立即启动防汛Ⅰ级应急响应,立即转移危险区群众,医疗机构做好应急准备",
district: '合川区',
roadCode: 'G542',
riskType: '风险路段',
riskLocation: '丁吴路(K116+656至K116+739)',
responseStatus: '未回应',
auditStatus: '未审核',
warningLevel: '红色预警',
stakeRange: '三级治理中心发布发布暴雨红色预警信号',
discoverTime: '立即启动防汛Ⅰ级应急响应,立即转移危险区群众,医疗机构做好应急准备',
});
//
const photoList = ref([
"https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片1",
"https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片2",
"https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片3",
"https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片4",
'https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片1',
'https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片2',
'https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片3',
'https://via.placeholder.com/100x70/40a9ff/ffffff?text=照片4',
]);
//
const patrolRecord = ref({
person: "蒋汉成 18702307964",
time: "2025-10-14 15:43:24",
situation: "收到暴雨黄色预警信息,开展公路夜间巡查排查,道路滑坡涉灾点,无明显变化",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场",
person: '蒋汉成 18702307964',
time: '2025-10-14 15:43:24',
situation: '收到暴雨黄色预警信息,开展公路夜间巡查排查,道路滑坡涉灾点,无明显变化',
image: 'https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场',
});
//
const dynamicRecords = ref([
{
type: "dispatch",
typeName: "调度记录",
person: "蒋汉成",
time: "2025-10-13 15:43:24",
status: "【已接通语音】",
statusClass: "status-success",
target: "养护站负责人",
targetPhone: "刘孝万13609403931",
type: 'dispatch',
typeName: '调度记录',
person: '蒋汉成',
time: '2025-10-13 15:43:24',
status: '【已接通语音】',
statusClass: 'status-success',
target: '养护站负责人',
targetPhone: '刘孝万13609403931',
},
{
type: "warning",
typeName: "预警记录",
person: "蒋汉成18702307964",
time: "2025-10-13 15:43:24",
status: "审核驳回",
statusClass: "status-reject",
type: 'warning',
typeName: '预警记录',
person: '蒋汉成18702307964',
time: '2025-10-13 15:43:24',
status: '审核驳回',
statusClass: 'status-reject',
},
{
type: "warning",
typeName: "预警记录",
person: "蒋汉成18702307964",
time: "2025-10-13 15:43:24",
status: "审核通过",
statusClass: "status-success",
type: 'warning',
typeName: '预警记录',
person: '蒋汉成18702307964',
time: '2025-10-13 15:43:24',
status: '审核通过',
statusClass: 'status-success',
},
{
type: "warning",
typeName: "预警记录",
person: "蒋汉成18702307964",
time: "2025-10-13 15:43:24",
status: "响应预警",
statusClass: "status-success",
type: 'warning',
typeName: '预警记录',
person: '蒋汉成18702307964',
time: '2025-10-13 15:43:24',
status: '响应预警',
statusClass: 'status-success',
},
]);
//
const getStatusClass = (status) => {
if (status === "未回应") return "status-unresponse";
if (status === "已回应") return "status-response";
return "";
const getStatusClass = status => {
if (status === '未回应') return 'status-unresponse';
if (status === '已回应') return 'status-response';
return '';
};
const getAuditClass = (status) => {
if (status === "未审核") return "status-unaudit";
if (status === "审核通过") return "status-pass";
if (status === "审核驳回") return "status-reject";
return "";
const getAuditClass = status => {
if (status === '未审核') return 'status-unaudit';
if (status === '审核通过') return 'status-pass';
if (status === '审核驳回') return 'status-reject';
return '';
};
//
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewImageUrl = ref('');
const previewImage = (url) => {
const previewImage = url => {
previewImageUrl.value = url;
previewVisible.value = true;
};
const closePreview = () => {
previewVisible.value = false;
previewImageUrl.value = "";
previewImageUrl.value = '';
};
//
const viewTrack = () => {
emit("viewTrack", patrolRecord.value);
emit('viewTrack', patrolRecord.value);
};
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
// base-dialog
@ -285,7 +297,7 @@ const handleClose = () => {
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal && props.pointData) {
Object.assign(basicInfo.value, props.pointData);
}
@ -294,8 +306,6 @@ watch(
</script>
<style lang="scss" scoped>
//
.section {
margin-bottom: 20px;
@ -636,6 +646,4 @@ watch(
color: #fff;
}
}
</style>

View File

@ -75,7 +75,7 @@
</template>
<script setup>
import { ref, computed, watch } from "vue";
import { ref, computed, watch } from 'vue';
import {
Close,
VideoCamera,
@ -86,8 +86,8 @@ import {
User,
OfficeBuilding,
MapLocation,
} from "@element-plus/icons-vue";
import baseDialog from "../component/baseDialog.vue";
} from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
const props = defineProps({
visible: {
@ -97,12 +97,12 @@ const props = defineProps({
allCountyData: {
type: Object,
default: () => ({
name: "",
name: '',
}),
},
});
const emit = defineEmits(["update:visible", "close"]);
const emit = defineEmits(['update:visible', 'close']);
//
const stats = ref({
@ -113,112 +113,112 @@ const stats = ref({
//
const tableColumns = ref([
{ prop: "id", label: "序号", width: "" },
{ prop: "district", label: "区县/镇街", width: "" },
{ prop: "name", label: "姓名", width: "" },
{ prop: "phone", label: "电话", width: "" },
{ prop: "role", label: "角色", width: "" },
{ prop: "position", label: "职务", width: "" },
{ prop: "operation", label: "操作", width: "120px", slot: "operation" },
{ prop: 'id', label: '序号', width: '' },
{ prop: 'district', label: '区县/镇街', width: '' },
{ prop: 'name', label: '姓名', width: '' },
{ prop: 'phone', label: '电话', width: '' },
{ prop: 'role', label: '角色', width: '' },
{ prop: 'position', label: '职务', width: '' },
{ prop: 'operation', label: '操作', width: '120px', slot: 'operation' },
]);
//
const tableData = ref([
{
id: 1,
district: "万州区柏梓镇",
name: "赵海浪",
phone: "1862352068",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区柏梓镇',
name: '赵海浪',
phone: '1862352068',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 2,
district: "万州区柏梓镇",
name: "赵海浪",
phone: "1862352068",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区柏梓镇',
name: '赵海浪',
phone: '1862352068',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 3,
district: "万州区柏梓镇",
name: "赵海浪",
phone: "1862352068",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区柏梓镇',
name: '赵海浪',
phone: '1862352068',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 4,
district: "万州区柏梓镇",
name: "赵海浪",
phone: "1862352068",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区柏梓镇',
name: '赵海浪',
phone: '1862352068',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 5,
district: "万州区李河镇",
name: "王建国",
phone: "1398324567",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区李河镇',
name: '王建国',
phone: '1398324567',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 6,
district: "万州区李河镇",
name: "王建国",
phone: "1398324567",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区李河镇',
name: '王建国',
phone: '1398324567',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 7,
district: "万州区李河镇",
name: "王建国",
phone: "1398324567",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区李河镇',
name: '王建国',
phone: '1398324567',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 8,
district: "万州区李河镇",
name: "王建国",
phone: "1398324567",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区李河镇',
name: '王建国',
phone: '1398324567',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 9,
district: "万州区分水镇",
name: "刘志强",
phone: "1387654321",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区分水镇',
name: '刘志强',
phone: '1387654321',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 10,
district: "万州区分水镇",
name: "刘志强",
phone: "1387654321",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区分水镇',
name: '刘志强',
phone: '1387654321',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 11,
district: "万州区分水镇",
name: "刘志强",
phone: "1387654321",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区分水镇',
name: '刘志强',
phone: '1387654321',
role: '一般人员(路长履职)',
position: '其他',
},
{
id: 12,
district: "万州区分水镇",
name: "刘志强",
phone: "1387654321",
role: "一般人员(路长履职)",
position: "其他",
district: '万州区分水镇',
name: '刘志强',
phone: '1387654321',
role: '一般人员(路长履职)',
position: '其他',
},
]);
@ -229,49 +229,49 @@ const total = ref(36);
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
//
const handleSizeChange = (val) => {
const handleSizeChange = val => {
pageSize.value = val;
fetchData();
};
const handleCurrentChange = (val) => {
const handleCurrentChange = val => {
currentPage.value = val;
fetchData();
};
//
const fetchData = () => {
console.log("获取第", currentPage.value, "页数据");
console.log('获取第', currentPage.value, '页数据');
// API
};
//
const handleView = (item) => {
console.log("查看视频:", item);
const handleView = item => {
console.log('查看视频:', item);
};
const handleVoice = (item) => {
console.log("语音通话:", item);
const handleVoice = item => {
console.log('语音通话:', item);
};
const handleCall = (item) => {
console.log("拨打电话:", item);
const handleCall = item => {
console.log('拨打电话:', item);
};
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal) {
currentPage.value = 1;
fetchData();
}
},
}
);
</script>
@ -287,11 +287,7 @@ watch(
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%
);
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;

View File

@ -168,7 +168,12 @@
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { Close, ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { pointTypeOptions, pointLevelOptions, isRespondedOptions, formatDateTime } from '../component/index.js';
import {
pointTypeOptions,
pointLevelOptions,
isRespondedOptions,
formatDateTime,
} from '../component/index.js';
import baseDialog from '../component/baseDialog.vue';
import { request } from '@/utils/request.js';
@ -203,7 +208,7 @@ const filterForm = ref({
isResponded: '',
});
const cardType = ref('0');
const cardType = ref('路段');
//
const statsCardsData = ref([
@ -246,6 +251,7 @@ const handleClose = () => {
//
const handleClick = type => {
cardType.value = type;
fetchData();
};
//
const loadBarChartData = async () => {
@ -378,11 +384,11 @@ const fetchData = async () => {
};
//
const getTypeLabel = (type) => {
const getTypeLabel = type => {
const typeMap = {
'road-section': '路段',
'road_section': '路段',
'roadSection': '路段',
road_section: '路段',
roadSection: '路段',
bridge: '桥梁',
tunnel: '隧道',
slope: '边坡',
@ -392,7 +398,7 @@ const getTypeLabel = (type) => {
};
//
const getLevelClass = (riskLevel) => {
const getLevelClass = riskLevel => {
if (!riskLevel) return '';
if (riskLevel.includes('高')) return 'level-serious';
if (riskLevel.includes('一般')) return 'level-normal';

View File

@ -43,27 +43,21 @@
</div>
<div class="info-item">
<span class="info-label">回应状态</span>
<span
class="info-value"
:class="getStatusClass(basicInfo.responseStatus)"
>{{ basicInfo.responseStatus }}</span
>
<span class="info-value" :class="getStatusClass(basicInfo.responseStatus)">
{{ basicInfo.responseStatus }}
</span>
</div>
<div class="info-item">
<span class="info-label">审核状态</span>
<span
class="info-value"
:class="getAuditClass(basicInfo.auditStatus)"
>{{ basicInfo.auditStatus }}</span
>
<span class="info-value" :class="getAuditClass(basicInfo.auditStatus)">
{{ basicInfo.auditStatus }}
</span>
</div>
</div>
<div class="info-row three-col">
<div class="info-item">
<span class="info-label">预警等级</span>
<span class="info-value level-red">{{
basicInfo.warningLevel
}}</span>
<span class="info-value level-red">{{ basicInfo.warningLevel }}</span>
</div>
<div class="info-item">
<span class="info-label">起点桩号-止点桩号</span>
@ -126,9 +120,7 @@
:class="{ 'row-even': index % 2 === 1 }"
>
<div class="td" style="width: 30%">{{ item.type }}</div>
<div class="td" style="width: 40%">
{{ item.name }} {{ item.phone }}
</div>
<div class="td" style="width: 40%">{{ item.name }} {{ item.phone }}</div>
<div class="td" style="width: 30%">{{ item.frequency }}</div>
</div>
</div>
@ -172,25 +164,19 @@
</div>
<!-- 动态记录列表 -->
<div
v-for="(record, index) in dynamicRecords"
:key="index"
class="timeline-item"
>
<div v-for="(record, index) in dynamicRecords" :key="index" class="timeline-item">
<div class="timeline-marker" :class="record.type"></div>
<div class="timeline-content">
<div class="timeline-header">
<span class="timeline-type">{{ record.typeName }}</span>
<span class="timeline-person">{{ record.person }}</span>
<span class="timeline-time">{{ record.time }}</span>
<span
v-if="record.status"
class="timeline-status"
:class="record.statusClass"
>{{ record.status }}</span
>
<span v-if="record.status" class="timeline-status" :class="record.statusClass">
{{ record.status }}
</span>
<span v-if="record.target" class="timeline-target">
<span class="target-name">{{ record.target }}</span>
<span class="target-name">{{ record.target }}</span>
{{ record.targetPhone }}
</span>
</div>
@ -202,11 +188,7 @@
</base-dialog>
<!-- 图片预览弹窗 -->
<div
v-if="previewVisible"
class="image-preview-overlay"
@click="closePreview"
>
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
<div class="image-preview-container" @click.stop>
<img :src="previewImageUrl" alt="预览" />
<div class="close-preview-btn" @click="closePreview">
@ -217,9 +199,9 @@
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
import baseDialog from "../component/baseDialog.vue";
import { ref, watch } from 'vue';
import { Close } from '@element-plus/icons-vue';
import baseDialog from '../component/baseDialog.vue';
const props = defineProps({
visible: {
@ -232,150 +214,148 @@ const props = defineProps({
},
});
const emit = defineEmits(["update:visible", "close", "viewTrack"]);
const emit = defineEmits(['update:visible', 'close', 'viewTrack']);
//
const tableColumns = ref([
{ label: "责任人类型", width: "30%" },
{ label: "责任人", width: "40%" },
{ label: "巡查频率", width: "30%" },
{ label: '责任人类型', width: '30%' },
{ label: '责任人', width: '40%' },
{ label: '巡查频率', width: '30%' },
]);
//
const basicInfo = ref({
district: "合川区",
roadCode: "G542",
riskType: "风险路段",
riskLocation: "丁吴路(K116+656至K116+739)",
responseStatus: "未回应",
auditStatus: "未审核",
warningLevel: "红色预警",
stakeRange: "三级治理中心发布发布暴雨红色预警信号",
discoverTime:
"立即启动防汛Ⅰ级应急响应,立即转移危险区群众,医疗机构做好应急准备",
warningContent: "",
district: '合川区',
roadCode: 'G542',
riskType: '风险路段',
riskLocation: '丁吴路(K116+656至K116+739)',
responseStatus: '未回应',
auditStatus: '未审核',
warningLevel: '红色预警',
stakeRange: '三级治理中心发布发布暴雨红色预警信号',
discoverTime: '立即启动防汛Ⅰ级应急响应,立即转移危险区群众,医疗机构做好应急准备',
warningContent: '',
});
//
const photoList = ref([
"https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片1",
"https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片2",
"https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片3",
"https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片4",
'https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片1',
'https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片2',
'https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片3',
'https://via.placeholder.com/120x80/40a9ff/ffffff?text=照片4',
]);
//
const responsibleList = ref([
{
type: "交通主管部门负责人",
name: "胡雷",
phone: "18983923577",
frequency: "半年巡查一次",
type: '交通主管部门负责人',
name: '胡雷',
phone: '18983923577',
frequency: '半年巡查一次',
},
{
type: "公路机构负责人",
name: "刘孝万",
phone: "13609403931",
frequency: "每月巡查一次",
type: '公路机构负责人',
name: '刘孝万',
phone: '13609403931',
frequency: '每月巡查一次',
},
{
type: "养护站负责人",
name: "彭应成",
phone: "18323031454",
frequency: "每周巡查一次",
type: '养护站负责人',
name: '彭应成',
phone: '18323031454',
frequency: '每周巡查一次',
},
{
type: "护路员",
name: "蒋汉成",
phone: "1870230796",
frequency: "每周巡查两次",
type: '护路员',
name: '蒋汉成',
phone: '1870230796',
frequency: '每周巡查两次',
},
]);
//
const patrolRecord = ref({
person: "蒋汉成 18702307964",
time: "2025-10-14 15:43:24",
situation:
"收到暴雨黄色预警信息,开展公路夜间巡查排查,道路滑坡涉灾点,无明显变化",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场",
person: '蒋汉成 18702307964',
time: '2025-10-14 15:43:24',
situation: '收到暴雨黄色预警信息,开展公路夜间巡查排查,道路滑坡涉灾点,无明显变化',
image: 'https://via.placeholder.com/80x60/40a9ff/ffffff?text=现场',
});
//
const dynamicRecords = ref([
{
type: "dispatch",
typeName: "调度记录",
person: "蒋汉成",
time: "2025-10-13 15:43:24",
status: "【已接通语音】",
statusClass: "status-success",
target: "养护站负责人",
targetPhone: "刘孝万13609403931",
type: 'dispatch',
typeName: '调度记录',
person: '蒋汉成',
time: '2025-10-13 15:43:24',
status: '【已接通语音】',
statusClass: 'status-success',
target: '养护站负责人',
targetPhone: '刘孝万13609403931',
},
{
type: "warning",
typeName: "预警记录",
person: "蒋汉成18702307964",
time: "2025-10-13 15:43:24",
status: "审核驳回",
statusClass: "status-reject",
type: 'warning',
typeName: '预警记录',
person: '蒋汉成18702307964',
time: '2025-10-13 15:43:24',
status: '审核驳回',
statusClass: 'status-reject',
},
{
type: "warning",
typeName: "预警记录",
person: "蒋汉成18702307964",
time: "2025-10-13 15:43:24",
status: "审核通过",
statusClass: "status-success",
type: 'warning',
typeName: '预警记录',
person: '蒋汉成18702307964',
time: '2025-10-13 15:43:24',
status: '审核通过',
statusClass: 'status-success',
},
{
type: "warning",
typeName: "预警记录",
person: "蒋汉成18702307964",
time: "2025-10-13 15:43:24",
status: "响应预警",
statusClass: "status-success",
type: 'warning',
typeName: '预警记录',
person: '蒋汉成18702307964',
time: '2025-10-13 15:43:24',
status: '响应预警',
statusClass: 'status-success',
},
]);
//
const getStatusClass = (status) => {
if (status === "未回应") return "status-unresponse";
if (status === "已回应") return "status-response";
return "";
const getStatusClass = status => {
if (status === '未回应') return 'status-unresponse';
if (status === '已回应') return 'status-response';
return '';
};
const getAuditClass = (status) => {
if (status === "未审核") return "status-unaudit";
if (status === "审核通过") return "status-pass";
if (status === "审核驳回") return "status-reject";
return "";
const getAuditClass = status => {
if (status === '未审核') return 'status-unaudit';
if (status === '审核通过') return 'status-pass';
if (status === '审核驳回') return 'status-reject';
return '';
};
//
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewImageUrl = ref('');
const previewImage = (url) => {
const previewImage = url => {
previewImageUrl.value = url;
previewVisible.value = true;
};
const closePreview = () => {
previewVisible.value = false;
previewImageUrl.value = "";
previewImageUrl.value = '';
};
//
const viewTrack = () => {
emit("viewTrack", patrolRecord.value);
emit('viewTrack', patrolRecord.value);
};
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
// base-dialog
@ -383,11 +363,11 @@ const handleClose = () => {
// visible
watch(
() => props.visible,
(newVal) => {
newVal => {
if (newVal && props.riskData) {
Object.assign(basicInfo.value, props.riskData);
}
},
}
);
</script>
@ -580,7 +560,7 @@ watch(
position: relative;
&::after {
content: "";
content: '';
position: absolute;
top: 12px;
left: 50%;

View File

@ -35,8 +35,8 @@
</template>
<script setup>
import { computed } from "vue";
import { ArrowRight, Location } from "@element-plus/icons-vue";
import { computed } from 'vue';
import { ArrowRight, Location } from '@element-plus/icons-vue';
const props = defineProps({
visible: {
@ -45,11 +45,11 @@ const props = defineProps({
},
value: {
type: [String, Number],
default: "",
default: '',
},
roadCount: {
type: [String, Number],
default: "128",
default: '128',
},
zIndex: {
type: Number,
@ -57,11 +57,11 @@ const props = defineProps({
},
width: {
type: String,
default: "200px",
default: '200px',
},
});
const emit = defineEmits(["update:visible", "close", "detail"]);
const emit = defineEmits(['update:visible', 'close', 'detail']);
const dialogStyle = computed(() => ({
width: props.width,
@ -69,13 +69,13 @@ const dialogStyle = computed(() => ({
//
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
//
const handleDetail = () => {
emit("detail");
emit('detail');
};
</script>
@ -98,7 +98,7 @@ const handleDetail = () => {
.center-card-dialog {
position: relative;
background-image: url("../../../assets/MaMap_img/区县弹窗背景@2x.png");
background-image: url('../../../assets/MaMap_img/区县弹窗背景@2x.png');
background-size: 100% 100%;
background-repeat: no-repeat;
min-width: vw(200);

View File

@ -36,8 +36,8 @@
</template>
<script setup>
import { defineProps, defineEmits } from "vue";
import baseDialog from "../component/baseDialog.vue";
import { defineProps, defineEmits } from 'vue';
import baseDialog from '../component/baseDialog.vue';
const props = defineProps({
visible: {
@ -47,20 +47,20 @@ const props = defineProps({
data: {
type: Object,
default: () => ({
title: "项目信息",
title: '项目信息',
items: [
{ label: "项目名称", value: "蔺市隧道右线" },
{ label: "编号", value: "G212线" },
{ label: "所属区县", value: "涪陵" },
{ label: "隧道长度", value: "1782(米)" },
{ label: "路线编号", value: "G50351" },
{ label: "路线名称", value: "石柱-重庆" },
{ label: "建成时间", value: "2023年" },
{ label: "入口桩号", value: "159.079" },
{ label: "隧道净宽", value: "22(米)" },
{ label: "隧道净高", value: "5(米)" },
{ label: "长度分类", value: "长隧道" },
{ label: "评定等级", value: "2类" },
{ label: '项目名称', value: '蔺市隧道右线' },
{ label: '编号', value: 'G212线' },
{ label: '所属区县', value: '涪陵' },
{ label: '隧道长度', value: '1782(米)' },
{ label: '路线编号', value: 'G50351' },
{ label: '路线名称', value: '石柱-重庆' },
{ label: '建成时间', value: '2023年' },
{ label: '入口桩号', value: '159.079' },
{ label: '隧道净宽', value: '22(米)' },
{ label: '隧道净高', value: '5(米)' },
{ label: '长度分类', value: '长隧道' },
{ label: '评定等级', value: '2类' },
],
}),
},
@ -68,69 +68,69 @@ const props = defineProps({
//
const slopeData = {
title: "边坡信息",
title: '边坡信息',
items: [
{ label: "边坡坡长", value: "0.1(km)" },
{ label: "边坡最大高度", value: "46(m)" },
{ label: "边坡构成", value: "土石混合边坡 (坡高>=25m)" },
{ label: "风险等级", value: "三级 (一般)" },
{ label: "变形形式", value: "框架梁" },
{ label: "监测设施设置", value: "无" },
{ label: "起点桩号", value: "1447.7" },
{ label: "止点桩号", value: "1447.8" },
{ label: '边坡坡长', value: '0.1(km)' },
{ label: '边坡最大高度', value: '46(m)' },
{ label: '边坡构成', value: '土石混合边坡 (坡高>=25m)' },
{ label: '风险等级', value: '三级 (一般)' },
{ label: '变形形式', value: '框架梁' },
{ label: '监测设施设置', value: '无' },
{ label: '起点桩号', value: '1447.7' },
{ label: '止点桩号', value: '1447.8' },
],
};
//
const tunnelData = {
title: "隧道信息",
title: '隧道信息',
items: [
{ label: "隧道名称", value: "蔺市隧道右线" },
{ label: "编号", value: "G212 线" },
{ label: "所属区县", value: "涪陵" },
{ label: "隧道长度", value: "1782(米)" },
{ label: "路线编号", value: "G50351" },
{ label: "路线名称", value: "石柱 - 重庆" },
{ label: "建成时间", value: "2023 年" },
{ label: "入口桩号", value: "159.079" },
{ label: "隧道净宽", value: "22(米)" },
{ label: "隧道净高", value: "5(米)" },
{ label: "长度分类", value: "长隧道" },
{ label: "评定等级", value: "2 类" },
{ label: '隧道名称', value: '蔺市隧道右线' },
{ label: '编号', value: 'G212 线' },
{ label: '所属区县', value: '涪陵' },
{ label: '隧道长度', value: '1782(米)' },
{ label: '路线编号', value: 'G50351' },
{ label: '路线名称', value: '石柱 - 重庆' },
{ label: '建成时间', value: '2023 年' },
{ label: '入口桩号', value: '159.079' },
{ label: '隧道净宽', value: '22(米)' },
{ label: '隧道净高', value: '5(米)' },
{ label: '长度分类', value: '长隧道' },
{ label: '评定等级', value: '2 类' },
],
};
//
const bridgeData = {
title: "桥梁信息",
title: '桥梁信息',
items: [
{ label: "桥梁名称", value: "蔺市隧道右线" },
{ label: "编号", value: "K212 线" },
{ label: "所属区县", value: "涪陵" },
{ label: "桥梁长度", value: "46(米)" },
{ label: "路线编号", value: "G50351" },
{ label: "路线名称", value: "银川 - 重庆" },
{ label: "建成时间", value: "2013" },
{ label: "中心桩号", value: "1278.994" },
{ label: "桥梁长度", value: "46 米" },
{ label: "跨径总长", value: "40 米" },
{ label: "跨径分类", value: "长隧道" },
{ label: "技术状况", value: "一类" },
{ label: '桥梁名称', value: '蔺市隧道右线' },
{ label: '编号', value: 'K212 线' },
{ label: '所属区县', value: '涪陵' },
{ label: '桥梁长度', value: '46(米)' },
{ label: '路线编号', value: 'G50351' },
{ label: '路线名称', value: '银川 - 重庆' },
{ label: '建成时间', value: '2013' },
{ label: '中心桩号', value: '1278.994' },
{ label: '桥梁长度', value: '46 米' },
{ label: '跨径总长', value: '40 米' },
{ label: '跨径分类', value: '长隧道' },
{ label: '技术状况', value: '一类' },
],
};
//
const rescueTeamData = {
title: "抢险队伍",
title: '抢险队伍',
items: [
{ label: "队伍名称", value: "重庆公路应急抢险指挥及物资储备中心" },
{ label: "防范状态", value: "已出动" },
{ label: "人数", value: "50" },
{ label: "联系人", value: "18602981928" },
{ label: "地址", value: "重庆市江津区双福工业园区赵坪路 157 号" },
{ label: "物资装备", value: "应急物资:8100 件;应急装备:33 台" },
{ label: '队伍名称', value: '重庆公路应急抢险指挥及物资储备中心' },
{ label: '防范状态', value: '已出动' },
{ label: '人数', value: '50' },
{ label: '联系人', value: '18602981928' },
{ label: '地址', value: '重庆市江津区双福工业园区赵坪路 157 号' },
{ label: '物资装备', value: '应急物资:8100 件;应急装备:33 台' },
],
imgs: ["", "", "", "", ""],
imgs: ['', '', '', '', ''],
};
defineExpose({
@ -140,11 +140,11 @@ defineExpose({
rescueTeamData,
});
const emit = defineEmits(["update:visible", "close"]);
const emit = defineEmits(['update:visible', 'close']);
const handleClose = () => {
emit("update:visible", false);
emit("close");
emit('update:visible', false);
emit('close');
};
</script>
@ -183,7 +183,7 @@ const handleClose = () => {
grid-template-columns: repeat(3, 1fr);
gap: 6px;
padding: 16px 20px;
.dialog-img {
width: 75px;
height: 75px;

View File

@ -231,9 +231,11 @@ const handleClick = (item, index) => {
}
activeIndex.value = index;
emit('changeActiveIndex', {
...item,
});
if (item.label !== '路段') {
emit('changeActiveIndex', {
...item,
});
}
};
//

View File

@ -1,4 +1,5 @@
<template>
<!-- 检查URL参数中是否有Map=dev如果有则使用本地地图数据否则使用阿里云地图数据 -->
<div class="chongqing-map-container">
<div ref="mapContainer" class="map-container"></div>
<div v-if="loading" class="loading-overlay">
@ -9,13 +10,6 @@
<span class="error-text">{{ error }}</span>
<button class="retry-btn" @click="loadMapData">重试</button>
</div>
<!-- <TongnanCenterCardDialog
ref="tongnanCenterCardDialog"
:visible.sync="visible"
:value="value"
:z-index="zIndex"
:width="width"
></TongnanCenterCardDialog> -->
<mapInfoDialog
v-model:visible="mapInfoDialogVisible"
:type="mapInfoDialogType"
@ -33,7 +27,6 @@
<hazardPointSituationDialog
v-model:visible="hazardPointSituationDialogVisible"
:data="{}"
:visible="true"
@close="closeHazardPointSituationDialog"
/>
</div>
@ -43,7 +36,6 @@
import { ref, onMounted, onUnmounted, watch, defineExpose, h, render } from 'vue';
import axios from 'axios';
import { request } from '@/utils/request';
import TongnanCenterCardDialog from '../Dialog/tongnanCenterCardDialog.vue';
import projectIcon from '../../../assets/MaMap_img/项目@2x.png';
import bridgeIcon from '../../../assets/MaMap_img/桥梁icon@2x.png';
@ -66,6 +58,7 @@ import tunnelLineIcon from '../../../assets/MaMap_img/线路icon定位@2x.png';
import mapInfoDialog from '../Dialog/mapInfoDialog.vue';
import centerInfoCard from '../Dialog/centerInfoCard.vue';
import hazardPointSituationDialog from '../Dialog/hazardPointSituationDialog.vue';
import I from '../../../../dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain';
const mapContainer = ref(null);
const loading = ref(false);
@ -97,7 +90,7 @@ watch(
() => props.roadItem,
async (newVal, oldVal) => {
if (newVal !== oldVal) {
await getAffectedRoadSectionData();
await getAffectedRoadSectionData(false);
}
},
{ immediate: true }
@ -117,10 +110,6 @@ const emit = defineEmits([
const selectedDistrict = ref(null);
let selectedLayer = null;
//
const tunnelDialogVisible = ref(false);
const tunnelDialogData = ref({});
//
const mapInfoDialogVisible = ref(false);
const mapInfoDialogType = ref('project');
@ -181,6 +170,9 @@ const showCountyCardsOnMap = dataList => {
//
dataList.forEach(item => {
// if (j.countyName === item.countyName) {
// item = j;
// }
const countyName = item.countyName || item.name;
if (!countyName) return;
@ -203,7 +195,6 @@ const showCountyCardsOnMap = dataList => {
// Vue
const container = document.createElement('div');
container.className = 'county-card-wrapper';
console.log(item);
// 使 Vue h
const vnode = h(centerInfoCard, {
visible: true,
@ -233,11 +224,11 @@ const showCountyCardsOnMap = dataList => {
const marker = window.L.marker(center, {
icon: customIcon,
interactive: true,
zIndexOffset: 2000, //
});
// marker
marker.on('click', () => {
console.log('centerInfoCard clicked, county:', countyName);
//
handleCenterCardItemClick(item);
//
@ -279,9 +270,21 @@ const openCenterCard = data => {
centerCardDataList.value = data.dataList || [];
centerCardTitle.value = data.title || '调度统计';
centerCardVisible.value = true;
let affectedItems = [];
//
data.dataList.forEach(item => {
if (item.countyName && (item.countyName.includes('渝北') || item.countyName.includes('江北'))) {
item.countyName = '两江新区';
}
affectedCountyData.value.sortedList.forEach(j => {
if (item.countyName.includes(j.name)) {
affectedItems.push(item);
}
});
});
//
showCountyCardsOnMap(data.dataList);
showCountyCardsOnMap(affectedItems);
};
//
@ -354,10 +357,26 @@ const getAffectedCountyData = async () => {
console.log('区县预警统计:', warningStats);
affectedCountyData.value = warningStats;
// getAffectedProjectData();
// getAffectedTunnelData();
// getAffectedBridgeData();
// getAffectedRoadSectionData();
getAffectedProjectData(true);
getAffectedTunnelData(true);
getAffectedBridgeData(true);
for (let index = 0; index < 5; index++) {
console.log(index);
if (index == 0) {
props.roadItem.label = '高风险路段';
} else if (index == 1) {
props.roadItem.label = '较高风险路段';
} else if (index == 2) {
props.roadItem.label = '中风险路段';
} else if (index == 3) {
props.roadItem.label = '低风险路段';
} else if (index == 4) {
props.roadItem.label = '';
}
if (props.roadItem.label) {
getAffectedRoadSectionData(true);
}
}
// getEmergencyForceData();
@ -370,7 +389,7 @@ const getAffectedCountyData = async () => {
const affectedBridgeData = ref([]);
//
const getAffectedBridgeData = async () => {
const getAffectedBridgeData = async flag => {
try {
const timeParams = getTimeParams();
const res = await request({
@ -380,14 +399,19 @@ const getAffectedBridgeData = async () => {
});
if (res.data) {
res.data.forEach(item => {
item.COORDINATE_POINT = [item.GL1_QLJD, item.GL1_QLWD];
// if (
// Number(item.GL1_JSZKPJDM) > 3 ||
// item.GL1_AKJFLLX == '' ||
// item.GL1_AKJFLLX == ''
// ) {
// }
affectedBridgeData.value.push(item);
if (item.COUNTY && (item.COUNTY.includes('江北') || item.COUNTY.includes('渝北'))) {
item.COUNTY = '两江新区';
}
affectedCountyData.value.sortedList.forEach(j => {
//
if (flag && item.GL1_QXMC && j.name && item.GL1_QXMC.includes(j.name)) {
item.COORDINATE_POINT = [item.GL1_QLJD, item.GL1_QLWD];
affectedBridgeData.value.push(item);
} else if (!flag) {
item.COORDINATE_POINT = [item.GL1_QLJD, item.GL1_QLWD];
affectedBridgeData.value.push(item);
}
});
});
}
console.log('受影响桥梁数据:', affectedBridgeData.value);
@ -400,7 +424,7 @@ const getAffectedBridgeData = async () => {
const tunnelInfoDialogRef = ref([]);
//
const getAffectedTunnelData = async () => {
const getAffectedTunnelData = async flag => {
try {
const timeParams = getTimeParams();
const res = await request({
@ -410,10 +434,19 @@ const getAffectedTunnelData = async () => {
});
if (res.code === '00000' && res.data) {
res.data.forEach(item => {
item.COORDINATE_POINT = [Number(item.GL1_SDJD2), Number(item.GL1_SDWD2)];
// if (Number(item.GL1_PDDJ) > 3 || item.GL1_SDLX == '') {
// }
tunnelInfoDialogRef.value.push(item);
if (item.COUNTY && (item.COUNTY.includes('江北') || item.COUNTY.includes('渝北'))) {
item.COUNTY = '两江新区';
}
affectedCountyData.value.sortedList.forEach(j => {
if (flag && j.name && item.GL1_QXMC && item.GL1_QXMC.includes(j.name)) {
item.COORDINATE_POINT = [Number(item.GL1_SDJD2), Number(item.GL1_SDWD2)];
tunnelInfoDialogRef.value.push(item);
} else if (!flag) {
item.COORDINATE_POINT = [Number(item.GL1_SDJD2), Number(item.GL1_SDWD2)];
tunnelInfoDialogRef.value.push(item);
}
});
});
console.log('受影响隧道数据:', tunnelInfoDialogRef.value);
addProjectMarkers(tunnelInfoDialogRef.value, tunnelIcon2, 'tunnel');
@ -427,7 +460,7 @@ const getAffectedTunnelData = async () => {
//
const affectedProjectData = ref([]);
const getAffectedProjectData = async () => {
const getAffectedProjectData = async flag => {
try {
const timeParams = getTimeParams();
const res = await request({
@ -440,19 +473,42 @@ const getAffectedProjectData = async () => {
console.log('项目数据条数:', res.data.length);
//
const parsedData = res.data.map(item => {
const newItem = { ...item };
if (item.COORDINATE_POINT) {
console.log('原始坐标:', item.COORDINATE_POINT);
newItem.COORDINATE_POINT = item.COORDINATE_POINT.substring(
6,
item.COORDINATE_POINT.length - 1
)
.split(' ')
.reverse();
console.log('解析后坐标:', newItem.COORDINATE_POINT);
if (item.COUNTY && (item.COUNTY.includes('江北') || item.COUNTY.includes('渝北'))) {
item.COUNTY = '两江新区';
}
return newItem;
affectedCountyData.value.sortedList.forEach(j => {
const newItem = { ...item };
// flag = true
if (
flag &&
item.COORDINATE_POINT &&
j.name &&
item.COUNTY &&
item.COUNTY.includes(j.name)
) {
console.log('原始坐标:', item.COORDINATE_POINT);
newItem.COORDINATE_POINT = item.COORDINATE_POINT.substring(
6,
item.COORDINATE_POINT.length - 1
)
.split(' ')
.reverse();
console.log('解析后坐标:', newItem.COORDINATE_POINT);
} else if (!flag && item.COORDINATE_POINT) {
console.log('原始坐标:', item.COORDINATE_POINT);
newItem.COORDINATE_POINT = item.COORDINATE_POINT.substring(
6,
item.COORDINATE_POINT.length - 1
)
.split(' ')
.reverse();
console.log('解析后坐标:', newItem.COORDINATE_POINT);
}
return newItem;
});
});
affectedProjectData.value = parsedData;
//
console.log('开始添加项目标记...');
@ -475,7 +531,7 @@ const roadvalArr = ref([
{ label: '中风险', value: 0, show: false },
{ label: '低风险', value: 0, show: false },
]);
const getAffectedRoadSectionData = async () => {
const getAffectedRoadSectionData = async flag => {
try {
console.log('受影响路段数据:', props.roadItem);
const { start, end } = getTimeParams();
@ -503,8 +559,17 @@ const getAffectedRoadSectionData = async () => {
console.log('受影响路段数据:', res);
if (res.code === '00000' && res.data) {
res.data.forEach(item => {
// item.COORDINATE_POINT = JSON.parse(item.STARTPOINT);
item.COORDINATE_POINT = [item.GL1_LON, item.GL1_LAT];
if (item.COUNTY && (item.COUNTY.includes('江北') || item.COUNTY.includes('渝北'))) {
item.COUNTY = '两江新区';
}
affectedCountyData.value.sortedList.forEach(j => {
if (flag && item.GL1_QXMC && j.name && item.GL1_QXMC.includes(j.name)) {
// item.COORDINATE_POINT = JSON.parse(item.STARTPOINT);
item.COORDINATE_POINT = [item.GL1_LON, item.GL1_LAT];
} else if (!flag) {
item.COORDINATE_POINT = [item.GL1_LON, item.GL1_LAT];
}
});
});
affectedRoadSectionData.value = res.data;
//
@ -565,8 +630,8 @@ const getEmergencyForceData = async () => {
if (res.code === '00000' && res.data) {
//
res.data.forEach(item => {
item.COORDINATE_POINT = [item.lng, item.lat];
console.log('解析后坐标:', item.COORDINATE_POINT);
item.COORDINATE_POINT = [item.lng, item.lat];
console.log('解析后坐标:', item.COORDINATE_POINT);
});
emergencyForceData.value = res.data;
@ -665,7 +730,6 @@ const clearProjectMarkers = () => {
projectMarkers = [];
//
tunnelDialogVisible.value = false;
mapInfoDialogVisible.value = false;
centerCardVisible.value = false;
};
@ -706,14 +770,6 @@ const getIconByType = (item, type) => {
//
const addProjectMarkers = (data, iconUrl, type = 'project') => {
console.log(
'addProjectMarkers 被调用, mapInstance:',
!!mapInstance,
'数据条数:',
data?.length,
'类型:',
type
);
if (!mapInstance) {
console.warn('mapInstance 未初始化,无法添加标记');
return;
@ -728,7 +784,7 @@ const addProjectMarkers = (data, iconUrl, type = 'project') => {
//
data.forEach(item => {
if (item.COORDINATE_POINT && item.COORDINATE_POINT.length === 2) {
if (item && item.COORDINATE_POINT && item.COORDINATE_POINT.length == 2) {
// COORDINATE_POINT : [, ]
// Leaflet : [, ]
const lng = item.COORDINATE_POINT[0];
@ -751,6 +807,7 @@ const addProjectMarkers = (data, iconUrl, type = 'project') => {
const marker = window.L.marker([latNum, lngNum], {
icon: projectIconObj,
zIndexOffset: 1000, //
});
// marker
@ -877,7 +934,7 @@ const countWarningsByCounty = data => {
//
const sortedList = Object.entries(stats)
.map(([name, data]) => ({
name,
name: name.substring(0, 2),
total: data.total,
levels: data.levels,
}))
@ -981,8 +1038,6 @@ const processDistrictMerge = geoJsonData => {
//
geoJsonData.features.push(liangjiangFeature);
console.log('已合并渝北区和江北区为两江新区');
}
};
@ -1168,7 +1223,10 @@ const initMap = geoJsonData => {
iconAnchor: [40, 15],
});
const marker = window.L.marker(centroid, { icon: label });
const marker = window.L.marker(centroid, {
icon: label,
zIndexOffset: 500, //
});
// marker.on("click", (e) => {
// //
// if (selectedLayer) {
@ -1230,18 +1288,18 @@ watch(
await getRiskPointData();
break;
case '项目':
await getAffectedProjectData();
await getAffectedProjectData(false);
break;
case '隧道':
await getAffectedTunnelData();
await getAffectedTunnelData(false);
break;
case '边坡':
break;
case '桥梁':
await getAffectedBridgeData();
await getAffectedBridgeData(false);
break;
case '路段':
await getAffectedRoadSectionData();
await getAffectedRoadSectionData(false);
break;
case '队伍':
await getEmergencyForceData();
@ -1332,7 +1390,6 @@ const locateToDistrict = countyName => {
};
const targetName = simplifyName(countyName);
console.log('定位到区县:', countyName, '简化后:', targetName);
//
let targetLayer = null;
@ -1362,8 +1419,6 @@ const locateToDistrict = countyName => {
// color: "#ff4d4f",
// });
selectedLayer = targetLayer;
console.log('已定位到区县:', countyName, '中心点:', center);
} else {
console.warn('未找到区县:', countyName);
}

View File

@ -25,92 +25,92 @@
/* 防止样式被覆盖,提高优先级 */
.custom-date-picker {
/* 弹出框整体背景色 */
background-color: #122C45 !important;
background-color: #122c45 !important;
/* 弹出框边框(主题色) */
border: 1px solid #289DFF !important;
border: 1px solid #289dff !important;
/* 可选:阴影效果 */
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3) !important;
}
.el-date-editor .el-range-input {
color: #289DFF !important;
color: #289dff !important;
}
/* ========== 1. 顶部栏(年月切换区域) ========== */
.custom-date-picker .el-date-picker__header,
.custom-date-picker .el-picker-panel__header {
background-color: #122C45 !important;
background-color: #122c45 !important;
border-bottom: 1px solid rgba(40, 157, 255, 0.3) !important;
}
.custom-date-picker .el-date-picker__header-label,
.custom-date-picker .el-picker-panel__header-label {
color: #FFFFFF !important;
color: #ffffff !important;
}
.custom-date-picker .el-picker-panel__icon-btn {
color: #FFFFFF !important;
color: #ffffff !important;
}
.custom-date-picker .el-picker-panel__icon-btn:hover {
color: #289DFF !important;
color: #289dff !important;
}
/* 年份/月份快速选择面板 */
.custom-date-picker .el-year-table td .el-year-table__cell__text,
.custom-date-picker .el-month-table td .el-month-table__cell__text {
color: #FFFFFF !important;
color: #ffffff !important;
background-color: transparent !important;
}
.custom-date-picker .el-year-table td .el-year-table__cell__text:hover,
.custom-date-picker .el-month-table td .el-month-table__cell__text:hover {
color: #289DFF !important;
color: #289dff !important;
background-color: rgba(40, 157, 255, 0.2) !important;
}
.custom-date-picker .el-year-table td.current .el-year-table__cell__text,
.custom-date-picker .el-month-table td.current .el-month-table__cell__text {
background-color: #289DFF !important;
color: #FFFFFF !important;
background-color: #289dff !important;
color: #ffffff !important;
}
/* ========== 2. 星期栏 ========== */
.custom-date-picker .el-date-table th,
.custom-date-picker .el-date-table__header th {
color: #289DFF !important;
background-color: #122C45 !important;
color: #289dff !important;
background-color: #122c45 !important;
border-bottom: 1px solid rgba(40, 157, 255, 0.3) !important;
}
/* ========== 3. 日期单元格(默认状态) ========== */
.custom-date-picker .el-date-table td .el-date-table-cell__text {
color: #FFFFFF !important;
color: #ffffff !important;
background-color: transparent !important;
border-radius: 4px;
transition: all 0.2s ease;
}
.custom-date-picker .el-date-table td .el-date-table-cell__text:hover {
color: #289DFF !important;
color: #289dff !important;
background-color: rgba(40, 157, 255, 0.2) !important;
}
/* ========== 4. 选中状态(核心样式) ========== */
.custom-date-picker .el-date-table td.current .el-date-table-cell__text {
background-color: #289DFF !important;
color: #FFFFFF !important;
background-color: #289dff !important;
color: #ffffff !important;
}
/* ========== 5. 今天按钮样式 ========== */
.custom-date-picker .el-date-table td.today .el-date-table-cell__text {
color: #289DFF !important;
color: #289dff !important;
font-weight: bold;
position: relative;
}
.custom-date-picker .el-date-table td.today.current .el-date-table-cell__text {
color: #FFFFFF !important;
color: #ffffff !important;
}
/* ========== 6. 其他月份日期(灰色显示) ========== */
@ -128,12 +128,12 @@
/* ========== 8. 底部按钮区域 ========== */
.custom-date-picker .el-picker-panel__footer {
background-color: #122C45 !important;
background-color: #122c45 !important;
border-top: 1px solid rgba(40, 157, 255, 0.3) !important;
}
.custom-date-picker .el-button--text {
color: #289DFF !important;
color: #289dff !important;
background-color: transparent !important;
}
@ -143,8 +143,8 @@
}
.custom-date-picker .el-button--primary {
background-color: #289DFF !important;
border-color: #289DFF !important;
background-color: #289dff !important;
border-color: #289dff !important;
}
.custom-date-picker .el-button--primary:hover {
@ -155,53 +155,53 @@
/* ========== 9. 小三角箭头 ========== */
/* Element Plus 版本 */
.custom-date-picker .el-popper__arrow::before {
background-color: #122C45 !important;
border: 1px solid #289DFF !important;
background-color: #122c45 !important;
border: 1px solid #289dff !important;
}
/* Element UI 版本 */
.custom-date-picker .popper__arrow {
border-bottom-color: #122C45 !important;
border-bottom-color: #122c45 !important;
}
.custom-date-picker .popper__arrow::after {
border-bottom-color: #122C45 !important;
border-bottom-color: #122c45 !important;
}
/* ========== 10. 范围选择器样式 ========== */
/* 范围选择器整体背景 */
.custom-date-picker.el-picker-panel--date-range {
background-color: #122C45 !important;
background-color: #122c45 !important;
}
/* 范围选择左右面板 */
.custom-date-picker .el-date-range-picker__content {
background-color: #152D47 !important;
background-color: #152d47 !important;
}
/* 范围选择头部 */
.custom-date-picker .el-date-range-picker__header {
color: #FFFFFF !important;
background-color: #122C45 !important;
color: #ffffff !important;
background-color: #122c45 !important;
}
/* 范围选择 - 起始日期 */
.custom-date-picker .el-date-table td.start-date .el-date-table-cell__text,
.custom-date-picker .el-date-table td.end-date .el-date-table-cell__text {
background-color: #289DFF !important;
color: #FFFFFF !important;
background-color: #289dff !important;
color: #ffffff !important;
border-radius: 4px;
}
.el-date-table td.in-range .el-date-table-cell {
background-color: #27374A !important;
background-color: #27374a !important;
border-radius: 0;
}
/* 范围选择 - 中间区间 */
.custom-date-picker .el-date-table td.in-range .el-date-table-cell__text {
background-color: #3E91BC !important;
color: #FFFFFF !important;
background-color: #3e91bc !important;
color: #ffffff !important;
border-radius: 0;
}
@ -216,13 +216,13 @@
}
.custom-date-picker .el-scrollbar__thumb {
background-color: #289DFF !important;
background-color: #289dff !important;
}
/* ========== 12. 时间选择器样式(如有) ========== */
.custom-date-picker .el-time-spinner__item {
color: #FFFFFF !important;
background-color: #122C45 !important;
color: #ffffff !important;
background-color: #122c45 !important;
}
.custom-date-picker .el-time-spinner__item:hover {
@ -230,21 +230,21 @@
}
.custom-date-picker .el-time-spinner__item.active {
background-color: #289DFF !important;
color: #FFFFFF !important;
background-color: #289dff !important;
color: #ffffff !important;
}
/* ========== 13. 快捷选项样式 ========== */
.custom-date-picker .el-picker-panel__shortcut {
color: #FFFFFF !important;
background-color: #122C45 !important;
color: #ffffff !important;
background-color: #122c45 !important;
}
.custom-date-picker .el-picker-panel__shortcut:hover {
background-color: rgba(40, 157, 255, 0.2) !important;
color: #289DFF !important;
color: #289dff !important;
}
.el-range__icon {
color: #289DFF !important;
}
color: #289dff !important;
}

View File

@ -13,11 +13,10 @@
box-shadow: none;
outline: none;
color: #fff !important;
}
.el-select__placeholder {
color: #16D9E0;
color: #16d9e0;
font-weight: 400;
}
@ -46,8 +45,8 @@
align-items: center;
color: #fff;
background-color: #122c46;
text-stroke: 0px #16D9E0;
-webkit-text-stroke: 0px #16D9E0;
text-stroke: 0px #16d9e0;
-webkit-text-stroke: 0px #16d9e0;
height: 40px;
&.is-hovering {
@ -62,4 +61,4 @@
}
}
}
}
}

View File

@ -3,20 +3,7 @@ import { ref } from 'vue';
import { request } from '@/utils/request';
// 影响区域选项
export const regionOptions = ref([
// { label: "重庆市", value: "重庆市" },
// { label: "万州区", value: "万州区" },
// { label: "沙坪坝区", value: "沙坪坝区" },
// { label: "渝中区", value: "渝中区" },
// { label: "巫溪县", value: "巫溪县" },
// { label: "涪陵区", value: "涪陵区" },
// { label: "合川区", value: "合川区" },
// { label: "万盛区", value: "万盛区" },
// { label: "长寿区", value: "长寿区" },
// { label: "城口区", value: "城口区" },
// { label: "柏梓镇", value: "柏梓镇" },
// { label: "江北区", value: "江北区" },
]);
export const regionOptions = ref([]);
// 获取影响区域选项
export const fetchDistrictOptions = async () => {
@ -32,10 +19,7 @@ export const fetchDistrictOptions = async () => {
value: item.xzdm,
}));
// 保留"全部"选项,并添加接口返回的数据
regionOptions.value = [
{ label: "全部", value: "" },
...options,
];
regionOptions.value = [{ label: '全部', value: '' }, ...options];
return options;
}
} catch (error) {
@ -45,14 +29,23 @@ export const fetchDistrictOptions = async () => {
};
// 路况类型选项默认数据会被API数据替换
export const typeOptions = ref([
export const typeOptions = ref([]);
// 管控措施选项默认数据会被API数据替换
export const controlMeasureOptions = ref([
// { label: "正常通行", value: "正常通行" },
// { label: "全幅封闭", value: "全幅封闭" },
// { label: "半幅封闭", value: "半幅封闭" },
// { label: "限速限车", value: "限速限车" },
// { label: "限速", value: "限速" },
// { label: "告警阻拦", value: "告警阻拦" },
]);
// 获取路况类型选项
export const fetchRoadConditionOptions = async () => {
try {
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/road-condition-options',
url: '/snow-ops-platform/sm-event/dashboard/processing-measure-options',
method: 'GET',
});
if (res && res.code === '00000' && Array.isArray(res.data)) {
@ -70,76 +63,101 @@ export const fetchRoadConditionOptions = async () => {
return typeOptions.value;
};
// 管控措施选项
export const controlMeasureOptions = [
{ label: "全幅封闭", value: "全幅封闭" },
{ label: "半幅通行", value: "半幅通行" },
{ label: "限速", value: "限速" },
{ label: "告警阻拦", value: "告警阻拦" },
];
// 获取管控措施选项
export const fetchControlMeasureOptions = async () => {
try {
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/processing-measure-options',
method: 'GET',
});
if (res && res.code === '00000' && Array.isArray(res.data)) {
const options = res.data
.map(item => {
if (typeof item === 'string') {
return { label: item, value: item };
}
if (item && typeof item === 'object') {
const label = item.label ?? item.name ?? item.text ?? item.value ?? item.val;
const value = item.value ?? item.val ?? item.code ?? label;
if (label == null || value == null) return null;
return { label: String(label), value: String(value) };
}
return null;
})
.filter(Boolean);
if (options.length > 0) {
controlMeasureOptions.value = options;
return options;
}
}
} catch (error) {
console.error('获取管控措施选项失败:', error);
}
return controlMeasureOptions.value;
};
// 风险等级选项
export const riskLevelOptions = [
{ label: "一级", value: "一级" },
{ label: "二级", value: "二级" },
{ label: "三级", value: "三级" },
{ label: "四级", value: "四级" },
{ label: '一级', value: '一级' },
{ label: '二级', value: '二级' },
{ label: '三级', value: '三级' },
{ label: '四级', value: '四级' },
];
// 影响点类型选项
export const pointTypeOptions = [
{ label: "全部", value: "" },
{ label: "边坡", value: "slope" },
{ label: "桥梁", value: "bridge" },
{ label: "隧道", value: "tunnel" },
{ label: "路面", value: "road" },
{ label: '全部', value: '' },
{ label: '边坡', value: 'slope' },
{ label: '桥梁', value: 'bridge' },
{ label: '隧道', value: 'tunnel' },
{ label: '路面', value: 'road' },
];
// 影响点等级选项
export const pointLevelOptions = [
{ label: "全部", value: "" },
{ label: "一般隐患", value: "normal" },
{ label: "重大隐患", value: "serious" },
{ label: '全部', value: '' },
{ label: '一般隐患', value: 'normal' },
{ label: '重大隐患', value: 'serious' },
];
// 是否回应选项
export const isRespondedOptions = [
{ label: "全部", value: "" },
{ label: "是", value: "yes" },
{ label: "否", value: "no" },
{ label: '全部', value: '' },
{ label: '是', value: 'yes' },
{ label: '否', value: 'no' },
];
// 预警等级选项
export const warningLevelOptions = [
{ label: "全部", value: "" },
{ label: "红色预警", value: "红色预警" },
{ label: "橙色预警", value: "橙色预警" },
{ label: "黄色预警", value: "黄色预警" },
{ label: "蓝色预警", value: "蓝色预警" },
{ label: '全部', value: '' },
{ label: '红色预警', value: '红色预警' },
{ label: '橙色预警', value: '橙色预警' },
{ label: '黄色预警', value: '黄色预警' },
{ label: '蓝色预警', value: '蓝色预警' },
];
// 是否结束选项
export const isEndedOptions = [
{ label: "全部", value: "" },
{ label: "是", value: true },
{ label: "否", value: false },
{ label: '全部', value: '' },
{ label: '是', value: true },
{ label: '否', value: false },
];
// 影响区域选项(带全部)
export const regionOptionsWithAll = ref([
]);
export const regionOptionsWithAll = ref([]);
// 格式化日期时间为接口所需格式
export const formatDateTime = (date) => {
if (!date) return "";
export const formatDateTime = date => {
if (!date) return '';
const d = new Date(date);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
const hours = String(d.getHours()).padStart(2, "0");
const minutes = String(d.getMinutes()).padStart(2, "0");
const seconds = String(d.getSeconds()).padStart(2, "0");
const month = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
const hours = String(d.getHours()).padStart(2, '0');
const minutes = String(d.getMinutes()).padStart(2, '0');
const seconds = String(d.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
@ -158,4 +176,5 @@ export default {
formatDateTime,
fetchRoadConditionOptions,
fetchDistrictOptions,
fetchControlMeasureOptions,
};

View File

@ -3,8 +3,8 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import * as echarts from 'echarts'
import { ref, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts';
const props = defineProps({
chartData: {
@ -13,28 +13,28 @@ const props = defineProps({
{ name: '蓝色', value: 13, color: '#40a9ff' },
{ name: '橙色', value: 40.2, color: '#ff7a45' },
{ name: '黄色', value: 22, color: '#ffc53d' },
{ name: '红色', value: 8, color: '#ff4d4f' }
]
{ name: '红色', value: 8, color: '#ff4d4f' },
],
},
centerText: {
type: String,
default: '风险\n状况'
}
})
default: '风险\n状况',
},
});
const chartRef = ref(null)
let chartInstance = null
const chartRef = ref(null);
let chartInstance = null;
const initChart = () => {
if (!chartRef.value) return
if (!chartRef.value) return;
chartInstance = echarts.init(chartRef.value)
chartInstance = echarts.init(chartRef.value);
const option = {
backgroundColor: 'transparent',
tooltip: {
trigger: 'item',
formatter: '{b}: {c}%'
formatter: '{b}: {c}%',
},
legend: {
orient: 'vertical',
@ -44,12 +44,12 @@ const initChart = () => {
itemHeight: 10,
textStyle: {
color: '#fff',
fontSize: 12
fontSize: 12,
},
data: props.chartData.map(item => ({
name: item.name,
icon: 'circle'
}))
icon: 'circle',
})),
},
series: [
{
@ -63,30 +63,30 @@ const initChart = () => {
position: 'outside',
formatter: '{c}%',
color: '#fff',
fontSize: 12
fontSize: 12,
},
labelLine: {
show: true,
length: 15,
length2: 10,
lineStyle: {
color: 'rgba(255, 255, 255, 0.3)'
}
color: 'rgba(255, 255, 255, 0.3)',
},
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
fontWeight: 'bold',
},
},
data: props.chartData.map(item => ({
value: item.value,
name: item.name,
itemStyle: {
color: item.color
}
}))
color: item.color,
},
})),
},
{
type: 'pie',
@ -100,25 +100,25 @@ const initChart = () => {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
lineHeight: 24
lineHeight: 24,
},
data: [{ value: 1, name: '', itemStyle: { color: 'transparent' } }]
}
]
}
data: [{ value: 1, name: '', itemStyle: { color: 'transparent' } }],
},
],
};
chartInstance.setOption(option)
}
chartInstance.setOption(option);
};
const updateChart = () => {
if (!chartInstance) return
if (!chartInstance) return;
const option = {
legend: {
data: props.chartData.map(item => ({
name: item.name,
icon: 'circle'
}))
icon: 'circle',
})),
},
series: [
{
@ -126,37 +126,37 @@ const updateChart = () => {
value: item.value,
name: item.name,
itemStyle: {
color: item.color
}
}))
color: item.color,
},
})),
},
{
label: {
formatter: props.centerText
}
}
]
}
formatter: props.centerText,
},
},
],
};
chartInstance.setOption(option)
}
chartInstance.setOption(option);
};
const handleResize = () => {
chartInstance?.resize()
}
chartInstance?.resize();
};
onMounted(() => {
initChart()
window.addEventListener('resize', handleResize)
})
initChart();
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
chartInstance?.dispose()
})
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
});
watch(() => props.chartData, updateChart, { deep: true })
watch(() => props.centerText, updateChart)
watch(() => props.chartData, updateChart, { deep: true });
watch(() => props.centerText, updateChart);
</script>
<style lang="scss" scoped>

View File

@ -12,12 +12,12 @@
</template>
<script setup>
import bgImg from "@/assets/RiskWarning_img/标题bg@2x.png";
import bgImg from '@/assets/RiskWarning_img/标题bg@2x.png';
defineProps({
title: {
type: String,
default: "",
default: '',
},
});
</script>

View File

@ -35,10 +35,10 @@ defineProps({
{ type: '隧道', red: 0, orange: 0, yellow: 6, blue: 12 },
{ type: '边坡', red: 0, orange: 1, yellow: 9, blue: 9 },
{ type: '路段', red: 0, orange: 2, yellow: 11, blue: 7 },
{ type: '项目', red: 0, orange: 2, yellow: 11, blue: 7 }
]
}
})
{ type: '项目', red: 0, orange: 2, yellow: 11, blue: 7 },
],
},
});
</script>
<style lang="scss" scoped>

View File

@ -42,10 +42,11 @@
</div>
<div class="right">
<right
:dateRange="getdateRange"
:getdateRange="getdateRange"
@openResourceDetail="openResourceDetail"
@openClearanceSituation="openDialog('clearanceSituation')"
@openControlSituation="openDialog('controlSituation')"
@update:dateRange="updateDateRange"
></right>
</div>
<!-- 地图中心 -->
@ -195,6 +196,7 @@
<!-- 抢通情况对话框 -->
<clearanceSituationDialog
:dateRange="rightDateRange"
v-model:visible="dialogVisible.clearanceSituation"
@close="closeDialog('clearanceSituation')"
@detail="openDialog('eventDetail')"
@ -254,7 +256,6 @@
v-model:visible="dialogVisible.offlineHelp"
@close="closeDialog('offlineHelp')"
/>
</div>
</div>
</template>
@ -268,7 +269,11 @@ import right from './right.vue';
import bottom from './bottom.vue';
import top from './top.vue';
import ChongqingMap from './component/ChongqingMap.vue';
import { fetchRoadConditionOptions, fetchDistrictOptions } from './component/index.js';
import {
fetchRoadConditionOptions,
fetchDistrictOptions,
fetchControlMeasureOptions,
} from './component/index.js';
//
import responseSituationDiaLog from './Dialog/responseSituationDiaLog.vue';
@ -489,6 +494,11 @@ const dispatchDateRange = ref([]);
const handleDispatchDateRange = range => {
dispatchDateRange.value = range;
};
const rightDateRange = ref([]);
const updateDateRange = range => {
console.log('更新日期范围:', range);
rightDateRange.value = range;
};
//
const confirmConfig = ref({
@ -510,7 +520,7 @@ const allCountyData = ref({});
const handleDistrictClick = item => {
console.log('区县点击:', item);
allCountyData.value = item;
if (item.data.roadType == 'national') {
if (item.data.roadType == 'national') {
//
openDialog('tongnanTeam');
} else if (item.data.roadType == 'rural') {
@ -612,6 +622,7 @@ onMounted(() => {
mapBase.loadBaseData();
fetchRoadConditionOptions(); //
fetchDistrictOptions(); //
fetchControlMeasureOptions(); //
});
</script>
@ -711,10 +722,7 @@ onMounted(() => {
position: absolute;
top: vw(100);
left: 25%;
width: 50%;
z-index: 4;
// height: 15%;
// background-color: #15293B;
}
.center {

View File

@ -39,7 +39,7 @@
<div class="impact-section">
<div class="impact-header">
<div class="impact-title">影响点概况</div>
<div class="impact-detail clickable" @click="handleImpactDetailClick">清单(影响点)</div>
<div class="impact-detail clickable" @click="handleImpactDetailClick">清单(影响点)</div>
</div>
<div class="chart-container">
<div class="chart-y-label">数量</div>
@ -173,7 +173,7 @@ watch(
() => getdateRange.value,
newVal => {
console.log('left.vue 日期范围变化:', newVal);
init();
// init();
},
{ deep: true }
);

View File

@ -212,13 +212,21 @@ import icon55 from '../../assets/RiskWarning_img/路径55@2x.png';
import icon62 from '../../assets/RiskWarning_img/路径62@2x.png';
import icon621 from '../../assets/RiskWarning_img/路径62@2x (1).png';
import icon622 from '../../assets/RiskWarning_img/路径62@2x (2).png';
import { formatDateTime } from './component/index.js';
const emit = defineEmits(['openClearanceSituation', 'openControlSituation', 'openResourceDetail']);
const emit = defineEmits([
'openClearanceSituation',
'openControlSituation',
'openResourceDetail',
'update:dateRange',
]);
//
const setRefreshRightData = inject('setRefreshRightData');
const getdateRange = inject('getdateRange', ref([]));
const props = defineProps({});
//
const handleDateChange = val => {
dateRange.value = val;
@ -317,9 +325,18 @@ const getYhYjllListMaterials = async () => {
//
const getControlStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/control-stats',
method: 'GET',
params: params,
});
console.log('管控统计数据:', res);
if (res.code == '00000' && res.data) {
@ -345,9 +362,18 @@ const getControlStats = async () => {
//
const getRescueInputStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/rescue-input-stats',
method: 'GET',
params: params,
});
console.log('抢险投入统计数据:', res);
if (res.code == '00000' && res.data) {
@ -387,9 +413,18 @@ const getRescueInputStats = async () => {
//
const getDisasterStats = async () => {
try {
let params = {
start: '',
end: '',
};
if (dateRange.value && dateRange.value.length === 2) {
params.start = formatDateTime(dateRange.value[0]);
params.end = formatDateTime(dateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/sm-event/dashboard/disaster-stats',
method: 'GET',
params: params,
});
console.log('灾害统计数据:', res);
if (res.code == '00000' && res.data) {
@ -491,6 +526,7 @@ const extractAndSumNumbers = value => {
const handleControlClick = item => {
if (item.label === '封闭管控数') {
emit('openClearanceSituation');
emit('update:dateRange', getdateRange.value || []);
} else if (item.label === '关闭驻地数') {
emit('openControlSituation');
}
@ -499,6 +535,7 @@ const handleControlClick = item => {
//
const handleBlockClick = () => {
emit('openClearanceSituation');
emit('update:dateRange', dateRange.value);
};
//
@ -557,9 +594,18 @@ const controlData2 = ref([
//
const getAffectedCountByProject = async () => {
try {
let params = {
start: '',
end: '',
};
if (getdateRange.value && getdateRange.value.length === 2) {
params.start = formatDateTime(getdateRange.value[0]);
params.end = formatDateTime(getdateRange.value[1]);
}
const res = await request({
url: '/snow-ops-platform/weather-warning/affected-count/_by_project',
method: 'GET',
params: params,
});
console.log('气象预警受影响统计:', res);
if (res.code === '00000' && res.data) {
@ -636,12 +682,14 @@ const majorEvent = '0';
// watch
const init = () => {
console.log('right.vue 刷新数据');
getYhYjllList();
getYhYjllListMaterials();
getControlStats();
getRescueInputStats();
getDisasterStats();
getAffectedCountByProject();
getYhYjllList(); //
getYhYjllListMaterials(); //
getControlStats(); //
getAffectedCountByProject(); //
getRescueInputStats(); //
getDisasterStats(); //
};
//
@ -658,8 +706,8 @@ watch(
newVal => {
console.log('right.vue 日期范围变化:', newVal);
if (newVal && newVal.length === 2) {
init();
}
init();
},
{ deep: true, immediate: true }
);

760
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff