1082 lines
29 KiB
Vue
1082 lines
29 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="card__content-box">
|
|||
|
|
<!-- 滚动表格区域 -->
|
|||
|
|
<div class="table">
|
|||
|
|
<!-- 表头容器 - 固定显示 -->
|
|||
|
|
<div class="table__header-container">
|
|||
|
|
<div class="table__item table__header">
|
|||
|
|
<div>序号</div>
|
|||
|
|
<div>预警名称</div>
|
|||
|
|
<div>预警点位</div>
|
|||
|
|
<div>预警摄像</div>
|
|||
|
|
<div>发布时间</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 内容滚动区域 -->
|
|||
|
|
<div class="table__body-container">
|
|||
|
|
<div class="scroll" v-if="tableData.length > 0">
|
|||
|
|
<vue3-seamless-scroll :step="0.5" :hover="true" :list="tableData">
|
|||
|
|
<div
|
|||
|
|
class="table__item"
|
|||
|
|
v-for="(item, index) in tableData"
|
|||
|
|
:key="index"
|
|||
|
|
@click="handleRowClick(item)"
|
|||
|
|
>
|
|||
|
|
<div class="scroll_table item_num">{{ index + 1 }}</div>
|
|||
|
|
|
|||
|
|
<!-- 1. 预警名称添加Tooltip -->
|
|||
|
|
<el-tooltip
|
|||
|
|
effect="dark"
|
|||
|
|
placement="top"
|
|||
|
|
:content="item.warningSigns"
|
|||
|
|
teleported
|
|||
|
|
popper-class="table-tooltip"
|
|||
|
|
>
|
|||
|
|
<div class="scroll_table item_courtName tooltip">
|
|||
|
|
{{ item.warningSigns }}
|
|||
|
|
</div>
|
|||
|
|
</el-tooltip>
|
|||
|
|
|
|||
|
|
<!-- 2. 预警点位添加Tooltip -->
|
|||
|
|
<el-tooltip
|
|||
|
|
effect="dark"
|
|||
|
|
placement="top"
|
|||
|
|
:content="item.pointName"
|
|||
|
|
teleported
|
|||
|
|
popper-class="table-tooltip"
|
|||
|
|
>
|
|||
|
|
<div class="scroll_table item_punisherName tooltip">
|
|||
|
|
{{ item.pointName }}
|
|||
|
|
</div>
|
|||
|
|
</el-tooltip>
|
|||
|
|
|
|||
|
|
<!-- 3. 预警摄像添加Tooltip -->
|
|||
|
|
<el-tooltip
|
|||
|
|
effect="dark"
|
|||
|
|
placement="top"
|
|||
|
|
:content="item.cameraName"
|
|||
|
|
teleported
|
|||
|
|
popper-class="table-tooltip"
|
|||
|
|
>
|
|||
|
|
<div class="scroll_table item_punisherName tooltip">
|
|||
|
|
{{ item.cameraName }}
|
|||
|
|
</div>
|
|||
|
|
</el-tooltip>
|
|||
|
|
|
|||
|
|
<!-- 4. 发布时间添加Tooltip -->
|
|||
|
|
<el-tooltip
|
|||
|
|
effect="dark"
|
|||
|
|
placement="top"
|
|||
|
|
:content="item.releaseTime"
|
|||
|
|
teleported
|
|||
|
|
popper-class="table-tooltip"
|
|||
|
|
>
|
|||
|
|
<div class="scroll_table item_courtName tooltip">
|
|||
|
|
{{ item.releaseTime }}
|
|||
|
|
</div>
|
|||
|
|
</el-tooltip>
|
|||
|
|
</div>
|
|||
|
|
</vue3-seamless-scroll>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div v-else class="nocontent">
|
|||
|
|
<el-empty :image-size="100" description="暂无数据" />
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 处置状态弹窗 -->
|
|||
|
|
<LargeScreenModal
|
|||
|
|
v-model:open="chargeOpen"
|
|||
|
|
:title="modalTitle"
|
|||
|
|
>
|
|||
|
|
<div class="tableWrap largeScreen">
|
|||
|
|
<el-descriptions
|
|||
|
|
class="largeScreen__descriptions"
|
|||
|
|
:column="2"
|
|||
|
|
size="large"
|
|||
|
|
border
|
|||
|
|
>
|
|||
|
|
<template v-for="item in formColumns">
|
|||
|
|
<el-descriptions-item :label="item.label">{{
|
|||
|
|
formInfo[item.key] || "-"
|
|||
|
|
}}</el-descriptions-item>
|
|||
|
|
</template>
|
|||
|
|
</el-descriptions>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="custom-timeline">
|
|||
|
|
<div
|
|||
|
|
v-for="(item, index) in timelineData"
|
|||
|
|
:key="index"
|
|||
|
|
class="timeline-item"
|
|||
|
|
>
|
|||
|
|
<div class="timeline-dot"></div>
|
|||
|
|
<div class="timeline-content">
|
|||
|
|
<div class="timeline-time">处理时间: {{ item.createTime }}</div>
|
|||
|
|
<div class="timeline-desc">
|
|||
|
|
<p>状态:{{ getStatusLabel(item.disposalStatus) }}</p>
|
|||
|
|
<p>措施:{{ item.disposalMeasures || "-" }}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</LargeScreenModal>
|
|||
|
|
|
|||
|
|
<!-- 预警详情与热力图弹窗 -->
|
|||
|
|
<LargeScreenModal
|
|||
|
|
v-model:open="warningModalOpen"
|
|||
|
|
title="预警详情与热力图"
|
|||
|
|
:width="styleUtil.px2vw(1200)"
|
|||
|
|
:height="styleUtil.px2vh(800)"
|
|||
|
|
@close="handleClose"
|
|||
|
|
>
|
|||
|
|
<div class="titles">{{ titlesTitle }}</div>
|
|||
|
|
<!-- 详情区域 -->
|
|||
|
|
<div class="detail-section">
|
|||
|
|
<el-descriptions
|
|||
|
|
class="largeScreen__descriptions"
|
|||
|
|
:column="2"
|
|||
|
|
size="large"
|
|||
|
|
border
|
|||
|
|
>
|
|||
|
|
<template #extra>
|
|||
|
|
</template>
|
|||
|
|
<template v-for="item in warningFormColumns">
|
|||
|
|
<!-- <el-descriptions-item v-if="item.label == '监控/外呼'" :label="item.label"> -->
|
|||
|
|
<el-descriptions-item v-if="item.label == '监控'" :label="item.label">
|
|||
|
|
<el-button type="primary" size="default" @click="lookJK">
|
|||
|
|
查看监控
|
|||
|
|
</el-button>
|
|||
|
|
<!-- <el-button type="primary" size="default" @click="CALL">
|
|||
|
|
外呼
|
|||
|
|
</el-button> -->
|
|||
|
|
</el-descriptions-item>
|
|||
|
|
<el-descriptions-item v-else :label="item.label">{{
|
|||
|
|
warningDetail[item.key] || "-"
|
|||
|
|
}}</el-descriptions-item>
|
|||
|
|
</template>
|
|||
|
|
</el-descriptions>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 地图区域 -->
|
|||
|
|
<div class="map-section">
|
|||
|
|
<div id="warningMap" ref="mapContainer"></div>
|
|||
|
|
|
|||
|
|
<!-- 加载状态 -->
|
|||
|
|
<div v-if="isLoading" class="map-loading">
|
|||
|
|
<el-icon class="is-loading"><Loading /></el-icon>加载中...
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 热力图图例 -->
|
|||
|
|
<div class="map-legend" v-if="showLegend && showHeatmap">
|
|||
|
|
<h4>客流热力等级</h4>
|
|||
|
|
<div class="legend-gradient"></div>
|
|||
|
|
<div class="legend-labels">
|
|||
|
|
<span>低</span><span>中</span><span>高</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</LargeScreenModal>
|
|||
|
|
|
|||
|
|
<!-- 视频弹窗 -->
|
|||
|
|
<LargeScreenModal
|
|||
|
|
v-model:open="chargeOpenJK"
|
|||
|
|
title="监控视频"
|
|||
|
|
:width="styleUtil.px2vw(1200)"
|
|||
|
|
:height="styleUtil.px2vh(800)"
|
|||
|
|
@close="handleVideoClose"
|
|||
|
|
>
|
|||
|
|
<div class="tableWrap largeScreen">
|
|||
|
|
<VideoMonitor
|
|||
|
|
:video-url="currentVideoUrl"
|
|||
|
|
width="100%"
|
|||
|
|
height="100%"
|
|||
|
|
style="margin-left: 40px"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</LargeScreenModal>
|
|||
|
|
<!-- 外呼的弹窗 -->
|
|||
|
|
<LargeScreenModal
|
|||
|
|
v-model:open="callDialog"
|
|||
|
|
title="外呼"
|
|||
|
|
:width="styleUtil.px2vw(400)"
|
|||
|
|
:height="styleUtil.px2vh(500)"
|
|||
|
|
@close="handleVideoClose2"
|
|||
|
|
>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="24">
|
|||
|
|
<div class="callDemo">
|
|||
|
|
<Call ref="CallRef" :listRows="callForm" width="100%" height="400px" />
|
|||
|
|
</div>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
</LargeScreenModal>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import {
|
|||
|
|
ref,
|
|||
|
|
reactive,
|
|||
|
|
onMounted,
|
|||
|
|
getCurrentInstance,
|
|||
|
|
nextTick,
|
|||
|
|
watch,
|
|||
|
|
} from "vue";
|
|||
|
|
import {
|
|||
|
|
getPoints,
|
|||
|
|
} from "@/api/points";
|
|||
|
|
import Call from "@/components/call.vue";
|
|||
|
|
|
|||
|
|
import styleUtil from "@/utils/styleUtils";
|
|||
|
|
import LargeScreenModal from "../largeScreenModal.vue";
|
|||
|
|
import { Vue3SeamlessScroll } from "vue3-seamless-scroll";
|
|||
|
|
import L from "leaflet";
|
|||
|
|
import "leaflet/dist/leaflet.css";
|
|||
|
|
import "leaflet.heat/dist/leaflet-heat.js"; // 与主地图一致的热力图库
|
|||
|
|
import { ElIcon, ElEmpty, ElMessage, ElSlider } from "element-plus";
|
|||
|
|
import { Loading } from "@element-plus/icons-vue";
|
|||
|
|
import _ from "lodash";
|
|||
|
|
import VideoMonitor from "../../../../components/VideoMonitor.vue";
|
|||
|
|
import moment from "moment";
|
|||
|
|
|
|||
|
|
// 接口导入 - 与主地图使用相同的接口
|
|||
|
|
import {
|
|||
|
|
getchuzhiList,
|
|||
|
|
getchuzhiListDetail,
|
|||
|
|
getchuzhiListLiucheng,
|
|||
|
|
getYJRLi,
|
|||
|
|
getYJRLiDetalis,
|
|||
|
|
getYJRLiJK,
|
|||
|
|
} from "@/api/map.js";
|
|||
|
|
|
|||
|
|
// 图标 - 与主地图一致
|
|||
|
|
import warningIcon from "@/assets/images/yujing2.png";
|
|||
|
|
|
|||
|
|
// 常量定义 - 与主地图完全一致
|
|||
|
|
const CHINA_BOUNDS = {
|
|||
|
|
minLat: 18.1,
|
|||
|
|
maxLat: 53.5,
|
|||
|
|
minLng: 73.6,
|
|||
|
|
maxLng: 135.1,
|
|||
|
|
};
|
|||
|
|
const DEFAULT_COORDS = [34.22, 108.96]; // 西安
|
|||
|
|
const DEFAULT_ZOOM = 11;
|
|||
|
|
const PARAM_ZOOM = 16;
|
|||
|
|
|
|||
|
|
const { proxy } = getCurrentInstance();
|
|||
|
|
const emit = defineEmits(["update-map-params"]);
|
|||
|
|
const { disposal_status } = proxy.useDict("disposal_status");
|
|||
|
|
|
|||
|
|
// 表格数据
|
|||
|
|
const tableData = ref([]);
|
|||
|
|
|
|||
|
|
// 处置弹窗相关
|
|||
|
|
const chargeOpen = ref(false);
|
|||
|
|
const modalTitle = ref("处置状态查看");
|
|||
|
|
const formInfo = ref({});
|
|||
|
|
const timelineData = ref([]);
|
|||
|
|
const formColumns = ref([
|
|||
|
|
{ label: "预警唯一标识符", key: "warningSigns" },
|
|||
|
|
{ label: "发布单位名称", key: "unitName" },
|
|||
|
|
{ label: "发布单位编码", key: "unitCode" },
|
|||
|
|
{ label: "发布时间", key: "releaseTime" },
|
|||
|
|
{ label: "经度", key: "lng" },
|
|||
|
|
{ label: "纬度", key: "lat" },
|
|||
|
|
{ label: "可能波及范围", key: "scopeImpact" },
|
|||
|
|
{ label: "异常数据值", key: "abnormalData" },
|
|||
|
|
{ label: "预计持续时间", key: "expectedDuration" },
|
|||
|
|
//{ label: "监控/外呼", key: "expectedDuration" },
|
|||
|
|
{ label: "监控", key: "expectedDuration" },
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
// 预警详情弹窗相关
|
|||
|
|
const warningModalOpen = ref(false);
|
|||
|
|
const warningDetail = ref({});
|
|||
|
|
const currentRow = ref(null);
|
|||
|
|
const isLoading = ref(false);
|
|||
|
|
const showLegend = ref(false);
|
|||
|
|
const showNoData = ref(false);
|
|||
|
|
const showHeatmap = ref(true);
|
|||
|
|
const showMarker = ref(true);
|
|||
|
|
|
|||
|
|
// 热力图参数 - 与主地图完全一致
|
|||
|
|
const heatRadius = ref(50); // 热力图半径
|
|||
|
|
const heatBlur = ref(30); // 热力图模糊度
|
|||
|
|
const heatMaxZoom = ref(10); // 最大缩放级别
|
|||
|
|
const heatMaxOpacity = ref(0.8); // 最大透明度
|
|||
|
|
|
|||
|
|
// 地图相关 - 与主地图保持一致的图层结构
|
|||
|
|
const mapContainer = ref(null);
|
|||
|
|
const mapInstance = ref(null);
|
|||
|
|
const markerObj = ref(null);
|
|||
|
|
const heatmapLayer = ref(null); // 热力图专用图层
|
|||
|
|
const markersLayer = ref(null); // 标记专用图层
|
|||
|
|
let currentHeatmapLayer = null; // 当前热力图层实例
|
|||
|
|
const filePathS = ref("");
|
|||
|
|
const chargeOpenJK = ref(false);
|
|||
|
|
const currentVideoUrl = ref("");
|
|||
|
|
// 预警详情表格配置
|
|||
|
|
const warningFormColumns = ref([
|
|||
|
|
{ label: "预警名称", key: "warningSigns" },
|
|||
|
|
{ label: "预警点位", key: "pointName" },
|
|||
|
|
{ label: "预警摄像", key: "cameraName" },
|
|||
|
|
{ label: "发布时间", key: "releaseTime" },
|
|||
|
|
{ label: "经度", key: "lng" },
|
|||
|
|
{ label: "纬度", key: "lat" },
|
|||
|
|
{ label: "可能波及范围", key: "scopeImpact" },
|
|||
|
|
{ label: "异常数据值", key: "abnormalData" },
|
|||
|
|
{ label: "预计持续时间", key: "expectedDuration" },
|
|||
|
|
// { label: "监控/外呼", key: "expectedDuration" }
|
|||
|
|
{ label: "监控", key: "expectedDuration" }
|
|||
|
|
]);
|
|||
|
|
const titlesTitle = ref('')
|
|||
|
|
const currentWarningId = ref('')
|
|||
|
|
// 行点击事件 - 与主地图逻辑一致
|
|||
|
|
const handleRowClick = async (row) => {
|
|||
|
|
console.log(row);
|
|||
|
|
currentWarningId.value = row.unitCode;
|
|||
|
|
filePathS.value = row.filePath;
|
|||
|
|
currentRow.value = row;
|
|||
|
|
isLoading.value = true;
|
|||
|
|
warningModalOpen.value = true;
|
|||
|
|
showNoData.value = false;
|
|||
|
|
showHeatmap.value = true;
|
|||
|
|
showMarker.value = true;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 解析经纬度
|
|||
|
|
const lat = Number(row.lat);
|
|||
|
|
const lng = Number(row.lng);
|
|||
|
|
const hasValidCoord = !isNaN(lat) && !isNaN(lng) && isInChina(lat, lng);
|
|||
|
|
|
|||
|
|
if (hasValidCoord) {
|
|||
|
|
emit("update-map-params", {
|
|||
|
|
latitude: lat.toFixed(6),
|
|||
|
|
longitude: lng.toFixed(6),
|
|||
|
|
monitoringTypeName: "warning",
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
ElMessage.warning("经纬度无效,使用默认位置");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await nextTick();
|
|||
|
|
let startTime = moment(row.releaseTime).format("YYYY-MM-DD");
|
|||
|
|
|
|||
|
|
// 并行加载数据 - 与主地图使用相同的接口
|
|||
|
|
const [detailRes, heatRes] = await Promise.all([
|
|||
|
|
getYJRLiDetalis(row.id).catch((err) => ({ code: 500, data: null })),
|
|||
|
|
getYJRLi({
|
|||
|
|
srcIndex: row.filePath || row.id,
|
|||
|
|
startTime: startTime ? `${startTime} 00:00:00` : "",
|
|||
|
|
endTime: row.releaseTime ? `${row.releaseTime}` : "",
|
|||
|
|
}).catch((err) => ({ code: 500, data: null })),
|
|||
|
|
]);
|
|||
|
|
console.log(heatRes, "热力");
|
|||
|
|
|
|||
|
|
// 处理详情数据
|
|||
|
|
warningDetail.value = detailRes.code === 200 ? detailRes.data || {} : {};
|
|||
|
|
console.log(warningDetail.value,'warningDetailwarningDetail');
|
|||
|
|
const index = warningDetail.value.warningSigns.indexOf('秒');
|
|||
|
|
titlesTitle.value = index !== -1 ? warningDetail.value.warningSigns.slice(index + 1) : '';
|
|||
|
|
// 初始化地图(与主地图配置一致)
|
|||
|
|
await initMap(row);
|
|||
|
|
|
|||
|
|
// 处理热力图数据 - 与主地图逻辑一致
|
|||
|
|
if (heatRes.code === 200 && heatRes.data && heatRes.data.length) {
|
|||
|
|
renderHeatmap(heatRes.data); // 使用与主地图相同的热力图渲染
|
|||
|
|
showLegend.value = true;
|
|||
|
|
showNoData.value = false;
|
|||
|
|
|
|||
|
|
// 调整地图视图到数据区域 - 与主地图逻辑一致
|
|||
|
|
const bounds = L.latLngBounds(
|
|||
|
|
heatRes.data.map((item) => [
|
|||
|
|
Number(item.latitude || item.lat),
|
|||
|
|
Number(item.longitude || item.lng),
|
|||
|
|
])
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (bounds.isValid()) {
|
|||
|
|
mapInstance.value.fitBounds(bounds, {
|
|||
|
|
padding: [80, 80], // 可选:增加边距,让视图更宽松
|
|||
|
|
maxZoom: 14, // 核心属性:限制最大缩放级别
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
showNoData.value = true;
|
|||
|
|
showLegend.value = false;
|
|||
|
|
ElMessage.info("未获取到热力图数据");
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error("加载失败:", error);
|
|||
|
|
ElMessage.error("加载数据失败,请重试");
|
|||
|
|
await initMap(currentRow.value);
|
|||
|
|
} finally {
|
|||
|
|
isLoading.value = false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 初始化地图 - 与主地图配置完全一致
|
|||
|
|
const initMap = async (row) => {
|
|||
|
|
const lat = Number(row.lat) || DEFAULT_COORDS[0];
|
|||
|
|
const lng = Number(row.lng) || DEFAULT_COORDS[1];
|
|||
|
|
|
|||
|
|
await nextTick();
|
|||
|
|
|
|||
|
|
if (!mapContainer.value) {
|
|||
|
|
console.error("地图容器不存在");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置容器尺寸
|
|||
|
|
mapContainer.value.style.width = "100%";
|
|||
|
|
mapContainer.value.style.height = "100%";
|
|||
|
|
|
|||
|
|
// 创建瓦片地图
|
|||
|
|
L.CRS.EPSG4490 = L.extend({},
|
|||
|
|
L.CRS.EPSG4326,
|
|||
|
|
{
|
|||
|
|
code: 'EPSG:4490',
|
|||
|
|
scale: function (zoom) { return 256 * Math.pow(2, zoom - 1); }
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 创建地图实例(与主地图参数一致)
|
|||
|
|
if (!mapInstance.value) {
|
|||
|
|
mapInstance.value = L.map(mapContainer.value, {
|
|||
|
|
center: [lat, lng],
|
|||
|
|
zoom: 12,
|
|||
|
|
maxZoom: 16, // 可选:限制手动缩放的最大级别
|
|||
|
|
minZoom: 8,
|
|||
|
|
zoomControl: false,
|
|||
|
|
attributionControl: false,
|
|||
|
|
dragging: true,
|
|||
|
|
touchZoom: true,
|
|||
|
|
scrollWheelZoom: true,
|
|||
|
|
doubleClickZoom: true,
|
|||
|
|
// 配置瓦片地图
|
|||
|
|
crs: L.CRS.EPSG4490,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 添加与主地图相同的底图
|
|||
|
|
L.tileLayer(
|
|||
|
|
// "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
|
|||
|
|
"https://10.22.245.209:18888/kgis/rest/services/GETileWGS20240425/MapServer/tile/{z}/{y}/{x}",
|
|||
|
|
{ subdomains: ["1", "2", "3", "4"], maxZoom: 20 }
|
|||
|
|
).addTo(mapInstance.value);
|
|||
|
|
|
|||
|
|
// // 添加与主地图相同的底图
|
|||
|
|
// const tileLayer1 = L.tileLayer(
|
|||
|
|
// "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
|
|||
|
|
// { subdomains: ["1", "2", "3", "4"] }
|
|||
|
|
// ).addTo(mapInstance.value);
|
|||
|
|
|
|||
|
|
// const tileLayer2 = L.tileLayer(
|
|||
|
|
// "https://webst0{s}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1",
|
|||
|
|
// { subdomains: ["1", "2", "3", "4"], pane: "markerPane" }
|
|||
|
|
// ).addTo(mapInstance.value);
|
|||
|
|
|
|||
|
|
// 添加相同的缩放控件
|
|||
|
|
L.control.zoom({ position: "topright" }).addTo(mapInstance.value);
|
|||
|
|
|
|||
|
|
// 创建图层(与主地图图层结构一致)
|
|||
|
|
heatmapLayer.value = L.layerGroup().addTo(mapInstance.value);
|
|||
|
|
markersLayer.value = L.layerGroup().addTo(mapInstance.value);
|
|||
|
|
|
|||
|
|
// 保持与主地图相同的图层顺序
|
|||
|
|
heatmapLayer.value.setZIndex(300);
|
|||
|
|
markersLayer.value.setZIndex(400);
|
|||
|
|
|
|||
|
|
// 监听地图事件 - 与主地图一致
|
|||
|
|
mapInstance.value.on(
|
|||
|
|
"zoomend moveend",
|
|||
|
|
_.debounce(() => {
|
|||
|
|
if (mapInstance.value) {
|
|||
|
|
mapInstance.value.invalidateSize();
|
|||
|
|
}
|
|||
|
|
}, 100)
|
|||
|
|
);
|
|||
|
|
} else {
|
|||
|
|
mapInstance.value.setView([lat, lng], PARAM_ZOOM);
|
|||
|
|
clearHeatmap();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加预警标记 - 与主地图标记样式一致
|
|||
|
|
if (row) {
|
|||
|
|
addWarningMarker(lat, lng, row);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 添加预警标记 - 与主地图标记逻辑一致
|
|||
|
|
const addWarningMarker = (lat, lng, row) => {
|
|||
|
|
if (markerObj.value) {
|
|||
|
|
markersLayer.value.removeLayer(markerObj.value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建与主地图一致的图标
|
|||
|
|
const icon = L.icon({
|
|||
|
|
iconUrl: warningIcon,
|
|||
|
|
iconSize: [32, 32],
|
|||
|
|
iconAnchor: [16, 32],
|
|||
|
|
popupAnchor: [0, -32],
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
markerObj.value = L.marker([lat, lng], {
|
|||
|
|
icon: icon,
|
|||
|
|
zIndexOffset: 1000, // 确保标记在热力图上方
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 绑定与主地图风格一致的弹窗内容
|
|||
|
|
markerObj.value.bindPopup(`
|
|||
|
|
<b>${row.warningSigns || "预警信息"}</b><br>
|
|||
|
|
点位: ${row.pointName || "未知"}<br>
|
|||
|
|
时间: ${row.releaseTime || "未知"}
|
|||
|
|
`);
|
|||
|
|
|
|||
|
|
markersLayer.value.addLayer(markerObj.value);
|
|||
|
|
markerObj.value.openPopup();
|
|||
|
|
|
|||
|
|
if (!showMarker.value) {
|
|||
|
|
markersLayer.value.removeLayer(markerObj.value);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 修改后的renderHeatmap函数,只显示一个圆圈
|
|||
|
|
const renderHeatmap = (heatData) => {
|
|||
|
|
// 清除现有热力图
|
|||
|
|
clearHeatmap();
|
|||
|
|
|
|||
|
|
if (!mapInstance.value || !heatData || !heatData.length) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 获取第一条数据
|
|||
|
|
const firstItem = heatData[0];
|
|||
|
|
if (!firstItem) {
|
|||
|
|
showNoData.value = true;
|
|||
|
|
ElMessage.warning("没有有效的热力图数据");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提取并验证经纬度和强度值
|
|||
|
|
const lat = Number(
|
|||
|
|
firstItem.latitude || firstItem.lat || firstItem.LAT || firstItem.Latitude
|
|||
|
|
);
|
|||
|
|
const lng = Number(
|
|||
|
|
firstItem.longitude ||
|
|||
|
|
firstItem.lng ||
|
|||
|
|
firstItem.LNG ||
|
|||
|
|
firstItem.Longitude
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 计算强度值
|
|||
|
|
const enterValue = Number(
|
|||
|
|
firstItem.enter || firstItem.count || firstItem.value || 50
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
let intensity;
|
|||
|
|
if (enterValue <= 0) {
|
|||
|
|
intensity = 30;
|
|||
|
|
} else {
|
|||
|
|
if (enterValue < 10000) {
|
|||
|
|
intensity = 50;
|
|||
|
|
} else if (enterValue < 100000) {
|
|||
|
|
intensity = 70;
|
|||
|
|
} else {
|
|||
|
|
intensity = 100;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 有效性检查
|
|||
|
|
if (isNaN(lat) || isNaN(lng)) {
|
|||
|
|
showNoData.value = true;
|
|||
|
|
ElMessage.warning(`经纬度无效: lat=${lat}, lng=${lng}`);
|
|||
|
|
console.error("无效的经纬度数据:", firstItem);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!isInChina(lat, lng)) {
|
|||
|
|
showNoData.value = true;
|
|||
|
|
ElMessage.warning(`经纬度不在有效范围内: lat=${lat}, lng=${lng}`);
|
|||
|
|
console.error("经纬度超出范围:", firstItem);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 只使用单个点
|
|||
|
|
const points = [
|
|||
|
|
[lat, lng, intensity], // 仅保留中心点位
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
// 确保热力图容器图层已添加到地图
|
|||
|
|
if (!mapInstance.value.hasLayer(heatmapLayer.value)) {
|
|||
|
|
mapInstance.value.addLayer(heatmapLayer.value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建热力图图层
|
|||
|
|
currentHeatmapLayer = L.heatLayer(points, {
|
|||
|
|
radius: 60, // 可以根据需要调整半径大小
|
|||
|
|
blur: 40, // 可以根据需要调整模糊度
|
|||
|
|
maxZoom: heatMaxZoom.value,
|
|||
|
|
maxOpacity: 0.9,
|
|||
|
|
gradient: {
|
|||
|
|
0.1: "#FFEDA0",
|
|||
|
|
0.3: "#FED976",
|
|||
|
|
0.5: "#FEB24C",
|
|||
|
|
0.7: "#FD8D3C",
|
|||
|
|
0.9: "#FC4E2A",
|
|||
|
|
1: "#E31A1C",
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 添加热力图到容器图层
|
|||
|
|
heatmapLayer.value.addLayer(currentHeatmapLayer);
|
|||
|
|
|
|||
|
|
// 确保标记层在热力图上方
|
|||
|
|
if (markersLayer.value) {
|
|||
|
|
mapInstance.value.removeLayer(markersLayer.value);
|
|||
|
|
mapInstance.value.addLayer(markersLayer.value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 显示图例
|
|||
|
|
showLegend.value = true;
|
|||
|
|
showNoData.value = false;
|
|||
|
|
|
|||
|
|
console.log(`成功渲染热力图,经纬度: (${lat}, ${lng}),强度: ${intensity}`);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error("热力图渲染失败:", error);
|
|||
|
|
ElMessage.error(`热力图渲染失败: ${error.message}`);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 更新热力图设置
|
|||
|
|
const updateHeatmapSettings = () => {
|
|||
|
|
if (currentRow.value && currentHeatmapLayer) {
|
|||
|
|
clearHeatmap();
|
|||
|
|
// 重新获取数据并渲染
|
|||
|
|
getYJRLi({
|
|||
|
|
srcIndex: currentRow.value.filePath || currentRow.value.id,
|
|||
|
|
startTime: currentRow.value.releaseTime
|
|||
|
|
? `${currentRow.value.releaseTime} 00:00:00`
|
|||
|
|
: "",
|
|||
|
|
endTime: currentRow.value.releaseTime
|
|||
|
|
? `${currentRow.value.releaseTime} 23:59:59`
|
|||
|
|
: "",
|
|||
|
|
}).then((res) => {
|
|||
|
|
if (res.code === 200 && res.data && res.data.length) {
|
|||
|
|
renderHeatmap(res.data);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 切换热力图显示 - 与主地图逻辑一致
|
|||
|
|
const toggleHeatmap = () => {
|
|||
|
|
showHeatmap.value = !showHeatmap.value;
|
|||
|
|
|
|||
|
|
if (showHeatmap.value) {
|
|||
|
|
mapInstance.value.addLayer(heatmapLayer.value);
|
|||
|
|
showLegend.value = true;
|
|||
|
|
} else {
|
|||
|
|
mapInstance.value.removeLayer(heatmapLayer.value);
|
|||
|
|
showLegend.value = false;
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 切换标记显示
|
|||
|
|
const toggleMarker = () => {
|
|||
|
|
showMarker.value = !showMarker.value;
|
|||
|
|
|
|||
|
|
if (showMarker.value && markerObj.value) {
|
|||
|
|
markersLayer.value.addLayer(markerObj.value);
|
|||
|
|
} else if (markerObj.value) {
|
|||
|
|
markersLayer.value.removeLayer(markerObj.value);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 清除热力图 - 与主地图逻辑一致
|
|||
|
|
const clearHeatmap = () => {
|
|||
|
|
if (
|
|||
|
|
currentHeatmapLayer &&
|
|||
|
|
heatmapLayer.value &&
|
|||
|
|
heatmapLayer.value.hasLayer(currentHeatmapLayer)
|
|||
|
|
) {
|
|||
|
|
heatmapLayer.value.removeLayer(currentHeatmapLayer);
|
|||
|
|
}
|
|||
|
|
currentHeatmapLayer = null;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 查看监控
|
|||
|
|
const lookJK = () => {
|
|||
|
|
let params = {
|
|||
|
|
typeinfo: filePathS.value,
|
|||
|
|
};
|
|||
|
|
getYJRLiJK(params).then((res) => {
|
|||
|
|
console.log(res, "监控返回");
|
|||
|
|
if (res.code === 200 && res.msg) {
|
|||
|
|
currentVideoUrl.value = res.msg;
|
|||
|
|
chargeOpenJK.value = true;
|
|||
|
|
} else {
|
|||
|
|
proxy.$modal.msgWarning("无监控数据");
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
const callDialog = ref(false);
|
|||
|
|
const callForm = ref({});
|
|||
|
|
// 外呼
|
|||
|
|
const CALL = () => {
|
|||
|
|
resetCall();
|
|||
|
|
getPoints(currentWarningId.value).then((response) => {
|
|||
|
|
console.log(response,'rq');
|
|||
|
|
callForm.value = {
|
|||
|
|
phone: response.data.dutyPhone
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
callDialog.value = true;
|
|||
|
|
}
|
|||
|
|
// 重置外呼内容
|
|||
|
|
function resetCall() {
|
|||
|
|
callDialog.value = false;
|
|||
|
|
callForm.value = {};
|
|||
|
|
}
|
|||
|
|
// 关闭弹窗
|
|||
|
|
const handleVideoClose = () => {
|
|||
|
|
chargeOpenJK.value = false;
|
|||
|
|
currentVideoUrl.value = "";
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 关闭弹窗清理 - 与主地图一致
|
|||
|
|
const handleClose = () => {
|
|||
|
|
if (mapInstance.value) {
|
|||
|
|
mapInstance.value.off();
|
|||
|
|
mapInstance.value.remove();
|
|||
|
|
mapInstance.value = null;
|
|||
|
|
}
|
|||
|
|
warningModalOpen.value = false;
|
|||
|
|
clearHeatmap();
|
|||
|
|
showLegend.value = false;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 查看处置详情
|
|||
|
|
const handleLook = (row) => {
|
|||
|
|
getchuzhiListDetail(row.warningId).then((res) => {
|
|||
|
|
formInfo.value = res.data || {};
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
getchuzhiListLiucheng({ handleId: row.id }).then((res) => {
|
|||
|
|
timelineData.value = res.rows || [];
|
|||
|
|
chargeOpen.value = true;
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 检查是否在中国范围内 - 与主地图一致
|
|||
|
|
const isInChina = (lat, lng) => {
|
|||
|
|
return (
|
|||
|
|
lat >= CHINA_BOUNDS.minLat &&
|
|||
|
|
lat <= CHINA_BOUNDS.maxLat &&
|
|||
|
|
lng >= CHINA_BOUNDS.minLng &&
|
|||
|
|
lng <= CHINA_BOUNDS.maxLng
|
|||
|
|
);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const getStatusLabel = (value) => {
|
|||
|
|
const found = disposal_status.value.find((item) => item.value === value);
|
|||
|
|
return found ? found.label : "未知状态";
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 加载表格数据
|
|||
|
|
const loadTableData = () => {
|
|||
|
|
getchuzhiList({ warningStatus: 1 })
|
|||
|
|
.then((res) => {
|
|||
|
|
tableData.value = res.rows || [];
|
|||
|
|
})
|
|||
|
|
.catch((err) => {
|
|||
|
|
console.error("加载表格数据失败:", err);
|
|||
|
|
ElMessage.error("加载表格数据失败");
|
|||
|
|
});
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 初始化 - 修复Leaflet图标路径问题与主地图一致
|
|||
|
|
onMounted(() => {
|
|||
|
|
loadTableData();
|
|||
|
|
|
|||
|
|
// 修复Leaflet默认图标路径问题
|
|||
|
|
if (!L.Icon.Default.prototype._getIconUrl) {
|
|||
|
|
delete L.Icon.Default.prototype._getIconUrl;
|
|||
|
|
L.Icon.Default.mergeOptions({
|
|||
|
|
iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
|
|||
|
|
iconUrl: require("leaflet/dist/images/marker-icon.png"),
|
|||
|
|
shadowUrl: require("leaflet/dist/images/marker-shadow.png"),
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
@use "@/assets/styles/computed.scss" as calculate;
|
|||
|
|
$tableColumnLength: 4;
|
|||
|
|
$table__title__height: calculate.vh(45px);
|
|||
|
|
$table__item__height: calculate.vh(35px);
|
|||
|
|
.titles {
|
|||
|
|
color: #fff;
|
|||
|
|
text-align: center;
|
|||
|
|
font-size: calculate.px2font(20px);
|
|||
|
|
}
|
|||
|
|
// 基础样式
|
|||
|
|
.nocontent {
|
|||
|
|
width: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
&:deep(.el-empty) {
|
|||
|
|
padding: calculate.vh(50px) 0;
|
|||
|
|
.el-empty__image {
|
|||
|
|
width: calculate.vw(100px) !important;
|
|||
|
|
}
|
|||
|
|
.el-empty__description {
|
|||
|
|
margin-top: calculate.vh(40px);
|
|||
|
|
p {
|
|||
|
|
font-size: calculate.px2font(20px);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
.callDemo {
|
|||
|
|
&:deep(#demo) {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 10px;
|
|||
|
|
|
|||
|
|
.el-button {
|
|||
|
|
max-width: 100px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 弹窗样式
|
|||
|
|
.detail-section {
|
|||
|
|
height: 50%;
|
|||
|
|
padding: 10px;
|
|||
|
|
overflow: auto;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.map-controls {
|
|||
|
|
height: 5%;
|
|||
|
|
padding: 5px 10px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 15px;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
|
|||
|
|
:deep(.el-slider) {
|
|||
|
|
width: 150px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.map-section {
|
|||
|
|
height: calculate.vh(500px);
|
|||
|
|
position: relative;
|
|||
|
|
padding: calculate.vh(10px);
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
margin-top: calculate.vh(10px);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#warningMap {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
position: relative;
|
|||
|
|
z-index: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 地图状态样式 - 与主地图一致
|
|||
|
|
.map-loading,
|
|||
|
|
.no-data {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 50%;
|
|||
|
|
left: 50%;
|
|||
|
|
transform: translate(-50%, -50%);
|
|||
|
|
z-index: 1001;
|
|||
|
|
background: rgba(255, 255, 255, 0.9);
|
|||
|
|
padding: 20px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.map-loading {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 10px;
|
|||
|
|
color: #555;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 热力图图例 - 与主地图完全一致
|
|||
|
|
.map-legend {
|
|||
|
|
position: absolute;
|
|||
|
|
bottom: 30px;
|
|||
|
|
right: 20px;
|
|||
|
|
z-index: 1000;
|
|||
|
|
background: rgba(255, 255, 255, 0.9);
|
|||
|
|
padding: 12px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
color: #333;
|
|||
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|||
|
|
border: 1px solid #eee;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.map-legend h4 {
|
|||
|
|
margin: 0 0 8px 0;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.legend-gradient {
|
|||
|
|
height: 20px;
|
|||
|
|
width: 180px;
|
|||
|
|
background: linear-gradient(
|
|||
|
|
to right,
|
|||
|
|
#ffeda0,
|
|||
|
|
/* 低 */ #fed976,
|
|||
|
|
#feb24c,
|
|||
|
|
#fd8d3c,
|
|||
|
|
#fc4e2a,
|
|||
|
|
#e31a1c /* 高 */
|
|||
|
|
);
|
|||
|
|
margin: 5px 0;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.legend-labels {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: #555;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card__content-box {
|
|||
|
|
.table {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
overflow: hidden;
|
|||
|
|
margin-top: 2vh;
|
|||
|
|
// 表头容器 - 固定不滚动
|
|||
|
|
&__header-container {
|
|||
|
|
flex-shrink: 0; // 不缩小
|
|||
|
|
border-bottom: 1px solid #888; // 增加分隔线
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 内容容器 - 可滚动
|
|||
|
|
&__body-container {
|
|||
|
|
flex-grow: 1; // 占满剩余空间
|
|||
|
|
overflow-y: auto; // 允许垂直滚动
|
|||
|
|
// 添加滚动条样式(可选)
|
|||
|
|
&::-webkit-scrollbar {
|
|||
|
|
width: 0;
|
|||
|
|
}
|
|||
|
|
&::-webkit-scrollbar-thumb {
|
|||
|
|
background-color: rgba(255, 255, 255, 0.3);
|
|||
|
|
border-radius: 3px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__item {
|
|||
|
|
line-height: $table__item__height;
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 2fr repeat(4, minmax(0, 3fr));
|
|||
|
|
color: #fff;
|
|||
|
|
text-align: center;
|
|||
|
|
font-size: calculate.px2font(14px);
|
|||
|
|
font-weight: bold;
|
|||
|
|
border-radius: calculate.px2font(2px);
|
|||
|
|
padding: calculate.vh(7px) 0;
|
|||
|
|
cursor: pointer;
|
|||
|
|
border-bottom: 10px solid #0b2342; // 红色分隔线(若只需纯间距可删除此句)
|
|||
|
|
// background-color: #29689e;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__item:nth-child(2n) {
|
|||
|
|
// background-color: #3c93d2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&__item:hover {
|
|||
|
|
box-shadow: inset 0 0 0 calculate.px2font(3px) #266fff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 表头样式
|
|||
|
|
&__header {
|
|||
|
|
font-weight: bold;
|
|||
|
|
border-bottom: none;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 时间线样式
|
|||
|
|
.custom-timeline {
|
|||
|
|
position: relative;
|
|||
|
|
padding-left: 20px;
|
|||
|
|
margin-top: 4%;
|
|||
|
|
|
|||
|
|
.timeline-item {
|
|||
|
|
position: relative;
|
|||
|
|
padding-bottom: 20px;
|
|||
|
|
|
|||
|
|
&:not(:last-child)::after {
|
|||
|
|
content: "";
|
|||
|
|
position: absolute;
|
|||
|
|
left: -2px;
|
|||
|
|
top: 16px;
|
|||
|
|
height: calc(100% - 16px);
|
|||
|
|
width: 2px;
|
|||
|
|
background: #e4e7ed;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.timeline-dot {
|
|||
|
|
position: absolute;
|
|||
|
|
left: -8px;
|
|||
|
|
top: 4px;
|
|||
|
|
width: 12px;
|
|||
|
|
height: 12px;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
background: #409eff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.timeline-content {
|
|||
|
|
padding-left: 20px;
|
|||
|
|
color: #fff;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tooltip {
|
|||
|
|
width: 98%;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 图层层级控制 - 与主地图完全一致
|
|||
|
|
:deep(.leaflet-map-pane) {
|
|||
|
|
z-index: 2 !important;
|
|||
|
|
}
|
|||
|
|
:deep(.leaflet-tile-pane) {
|
|||
|
|
z-index: 2 !important;
|
|||
|
|
} /* 底图 */
|
|||
|
|
:deep(.leaflet-overlay-pane) {
|
|||
|
|
z-index: 3 !important;
|
|||
|
|
} /* 热力图在底图上方 */
|
|||
|
|
:deep(.leaflet-marker-pane) {
|
|||
|
|
z-index: 4 !important;
|
|||
|
|
} /* 标记在热力图上方 */
|
|||
|
|
:deep(.leaflet-popup-pane) {
|
|||
|
|
z-index: 5 !important;
|
|||
|
|
} /* 弹窗在最上方 */
|
|||
|
|
.largeScreen__descriptions {
|
|||
|
|
:deep(.el-button){
|
|||
|
|
background: #0479fe;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|