格式化代码并添加视角高度控制以及视角范围控制

This commit is contained in:
wzy-warehouse
2026-04-13 10:30:03 +08:00
parent 83f8fec3a4
commit 5eb71642d2
46 changed files with 2084 additions and 1535 deletions
+71 -58
View File
@@ -1,68 +1,81 @@
<!-- 内容显示组件 -->
<template>
<div class="infomation-box" :style="{ width: `${width}px`, 'max-height': `${height}px`, top: `${newOffsetY}px`, left: `${newOffsetX}px` }">
<header>
<div class="title">
<h3>{{ title }}</h3>
</div>
</header>
<div class="content">
<table class="table">
<tr v-for="(tableData, index) in tableDatas" :key="index">
<td class="label">{{ tableData.title }}</td>
<td>{{ tableData.content }}</td>
</tr>
</table>
</div>
<div
class="infomation-box"
:style="{
width: `${width}px`,
'max-height': `${height}px`,
top: `${newOffsetY}px`,
left: `${newOffsetX}px`,
}"
>
<header>
<div class="title">
<h3>{{ title }}</h3>
</div>
</header>
<div class="content">
<table class="table">
<tr v-for="(tableData, index) in tableDatas" :key="index">
<td class="label">{{ tableData.title }}</td>
<td>{{ tableData.content }}</td>
</tr>
</table>
</div>
</div>
</template>
<script lang="ts" setup>
import { Utils } from '@/utils/utils';
import { onMounted, ref, type Ref } from 'vue';
import { Utils } from '@/utils/utils';
import { onMounted, ref, type Ref } from 'vue';
const props = defineProps<{
title: string
data: Record<string, any>
field: Record<string, string>
offsetX: number
offsetY: number
}>()
const props = defineProps<{
title: string;
data: Record<string, string>;
field: Record<string, string>;
offsetX: number;
offsetY: number;
}>();
// 定义宽高和偏移
const width = ref(400)
const height = ref(450)
const newOffsetX = ref(props.offsetX)
const newOffsetY = ref(props.offsetY)
// 定义宽高和偏移
const width = ref(400);
const height = ref(450);
const newOffsetX = ref(props.offsetX);
const newOffsetY = ref(props.offsetY);
const tableDatas: Ref<{ title: string, content: string }[]> = ref([])
const tableDatas: Ref<{ title: string; content: string }[]> = ref([]);
onMounted(() => {
onMounted(() => {
// 判断是否超出屏幕,超出就重新定位
[newOffsetX.value, newOffsetY.value] = Utils.keepWithinScreen(props.offsetX, props.offsetY, width.value, height.value)
[newOffsetX.value, newOffsetY.value] = Utils.keepWithinScreen(
props.offsetX,
props.offsetY,
width.value,
height.value
);
// 数据转换
Object.entries(props.data).forEach(([key, value]) => {
// 判读key是不是存在field中,存在就添加到表格数据,不存在则不添加
if (Object.hasOwn(props.field, key) && value) {
tableDatas.value.push({
title: props.field[key],
content: value
})
}
// 判读key是不是存在field中,存在就添加到表格数据,不存在则不添加
if (Object.hasOwn(props.field, key) && value) {
tableDatas.value.push({
title: props.field[key],
content: value,
});
}
});
})
});
</script>
<style scoped>
.infomation-box {
.infomation-box {
overflow-y: auto;
position: absolute;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
}
.title {
.title {
width: 100%;
display: flex;
align-items: center;
@@ -71,40 +84,40 @@ onMounted(() => {
border-bottom: 1px solid #e9ecef;
box-sizing: border-box;
height: 40px;
}
}
.title h3 {
color: #FFF;
.title h3 {
color: #fff;
font-size: 14px;
font-weight: bold;
font-family: "Source Han Sans CN";
}
font-family: 'Source Han Sans CN';
}
.content {
.content {
width: 100%;
color: #FFF;
color: #fff;
background-color: rgba(0, 94, 153, 1);
}
}
.table {
.table {
width: 100%;
height: 100%;
border-collapse: collapse;
}
}
.table tr td {
.table tr td {
padding: 8px;
border-top: 1px solid #000;
border-bottom: 1px solid #000;
border-left: none;
border-right: none;
text-align: left;
font-family: "Source Han Sans CN";
font-family: 'Source Han Sans CN';
font-size: 13px;
}
}
.label {
.label {
width: 30%;
font-size: 13px;
}
</style>
}
</style>
+88 -61
View File
@@ -1,75 +1,102 @@
<!-- 加载行政区划 -->
<template>
<div></div>
</template>
<script lang="ts" setup>
import BaQiiao from '@/assets/json/BaQiao.json';
import BeiLin from '@/assets/json/BeiLin.json';
import ChangAn from '@/assets/json/ChangAn.json';
import GaoLing from '@/assets/json/GaoLing.json';
import HuYi from '@/assets/json/HuYi.json';
import LanTian from '@/assets/json/LanTian.json';
import LianHu from '@/assets/json/LianHu.json';
import LinTong from '@/assets/json/LinTong.json';
import WeiYang from '@/assets/json/WeiYang.json';
import XinCheng from '@/assets/json/XinCheng.json';
import YanLiang from '@/assets/json/YanLiang.json';
import YanTa from '@/assets/json/YanTa.json';
import ZhouZhi from '@/assets/json/ZhouZhi.json';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
import { Color } from 'cesium';
import { onMounted } from 'vue';
import BaQiiao from '@/assets/json/BaQiao.json';
import BeiLin from '@/assets/json/BeiLin.json';
import ChangAn from '@/assets/json/ChangAn.json';
import GaoLing from '@/assets/json/GaoLing.json';
import HuYi from '@/assets/json/HuYi.json';
import LanTian from '@/assets/json/LanTian.json';
import LianHu from '@/assets/json/LianHu.json';
import LinTong from '@/assets/json/LinTong.json';
import WeiYang from '@/assets/json/WeiYang.json';
import XinCheng from '@/assets/json/XinCheng.json';
import YanLiang from '@/assets/json/YanLiang.json';
import YanTa from '@/assets/json/YanTa.json';
import ZhouZhi from '@/assets/json/ZhouZhi.json';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
import { Color } from 'cesium';
import { onMounted } from 'vue';
const areas = [BaQiiao, BeiLin, ChangAn, GaoLing, HuYi, LanTian, LianHu, LinTong, WeiYang, XinCheng, YanLiang, YanTa, ZhouZhi]
const areasId = ['baqiao', 'beilin', 'changan', 'gaoling', 'huyi', 'lantian', 'lianhu', 'lintong', 'weiyang', 'xincheng', 'yanliang', 'yanta', 'zhouzhi'];
const areasColor = [
new Color(255 / 255, 153 / 255, 0 / 255),
new Color(255 / 255, 51 / 255, 102 / 255),
new Color(0 / 255, 178 / 255, 255 / 255),
new Color(102 / 255, 255 / 255, 102 / 255),
new Color(204 / 255, 102 / 255, 255 / 255),
new Color(255 / 255, 204 / 255, 0 / 255),
new Color(0 / 255, 204 / 255, 153 / 255),
new Color(255 / 255, 102 / 255, 102 / 255),
new Color(102 / 255, 153 / 255, 255 / 255),
new Color(255 / 255, 178 / 255, 102 / 255),
new Color(153 / 255, 255 / 255, 204 / 255),
new Color(255 / 255, 153 / 255, 204 / 255),
new Color(190 / 255, 255 / 255, 232 / 255)
]
const areaTransparency = 0.3;
const labelTransparency = 1;
const areas = [
BaQiiao,
BeiLin,
ChangAn,
GaoLing,
HuYi,
LanTian,
LianHu,
LinTong,
WeiYang,
XinCheng,
YanLiang,
YanTa,
ZhouZhi,
];
const areasId = [
'baqiao',
'beilin',
'changan',
'gaoling',
'huyi',
'lantian',
'lianhu',
'lintong',
'weiyang',
'xincheng',
'yanliang',
'yanta',
'zhouzhi',
];
const areasColor = [
new Color(255 / 255, 153 / 255, 0 / 255),
new Color(255 / 255, 51 / 255, 102 / 255),
new Color(0 / 255, 178 / 255, 255 / 255),
new Color(102 / 255, 255 / 255, 102 / 255),
new Color(204 / 255, 102 / 255, 255 / 255),
new Color(255 / 255, 204 / 255, 0 / 255),
new Color(0 / 255, 204 / 255, 153 / 255),
new Color(255 / 255, 102 / 255, 102 / 255),
new Color(102 / 255, 153 / 255, 255 / 255),
new Color(255 / 255, 178 / 255, 102 / 255),
new Color(153 / 255, 255 / 255, 204 / 255),
new Color(255 / 255, 153 / 255, 204 / 255),
new Color(190 / 255, 255 / 255, 232 / 255),
];
const areaTransparency = 0.3;
const labelTransparency = 1;
onMounted(() => {
onMounted(() => {
// 构建批量添加配置数组
const layerConfigs = areasId.map((id, index) => ({
layerId: id,
geojsonData: areas[index],
isDefault: true,
options: {
showName: true,
labelStyle: {
labelText: areas[index].features[0].properties.name,
center: [
areas[index].features[0].properties.center[0],
areas[index].features[0].properties.center[1],
0
] as [number, number, number],
labelColor: Color.BLACK,
backgroundColor: areasColor[index].withAlpha(labelTransparency)
},
polygonStyle: {
fill: true,
fillColor: areasColor[index].withAlpha(areaTransparency),
outline: false
}
}
layerId: id,
geojsonData: areas[index],
isDefault: true,
options: {
showName: true,
labelStyle: {
labelText: areas[index].features[0].properties.name,
center: [
areas[index].features[0].properties.center[0],
areas[index].features[0].properties.center[1],
0,
] as [number, number, number],
labelColor: Color.BLACK,
backgroundColor: areasColor[index].withAlpha(labelTransparency),
},
polygonStyle: {
fill: true,
fillColor: areasColor[index].withAlpha(areaTransparency),
outline: false,
},
},
}));
CesiumUtilsSingleton.batchAddGeoJsonLayers(layerConfigs);
})
});
</script>
<style scoped></style>
<style scoped></style>
-90
View File
@@ -1,90 +0,0 @@
<template>
<div class="map_container" id="map-container"></div>
<!-- 行政区划 -->
<AdministrativeDivision v-if="useViewerStore().getViewerLoadingCompleted()" />
</template>
<script lang="ts" setup>
import { onBeforeMount, onMounted } from 'vue';
import config from '@/config/config.json';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
import AdministrativeDivision from './AdministrativeDivision.vue';
import { useViewerStore } from '@/stores/useViewerStore';
import { useLoadingInformationStore } from '@/stores/useLoadingInformation';
import xiAnGeoJSON from '@/assets/json/XiAn.json'
import type { GeoJsonFileType } from '@/types/cesium/GeoJsonFileType';
import { Color } from 'cesium';
onBeforeMount(() => {
// 初始化为false
useViewerStore().setViewerLoadingCompleted(false)
// 重置状态
useLoadingInformationStore().resetStatue()
})
onMounted(async() => {
await CesiumUtilsSingleton.initCesiumViewer({
containerId: 'map-container',
mark: {
include: true,
geoJson: xiAnGeoJSON as GeoJsonFileType,
color: Color.BLACK.withAlpha(0.8),
border: {
width: 3
}
}
},)
useViewerStore().setViewerLoadingCompleted(true)
// 注册全局点击监听器
CesiumUtilsSingleton.clickLayer((pickedObject: any) => {
if (pickedObject && pickedObject.id && (typeof pickedObject.id === 'string')) {
const matchResult = pickedObject.id.match(/\d+$/)
const id = matchResult ? parseInt(matchResult[0]) : -1
// 当id改变时候,重置状态
if (useLoadingInformationStore().getHiddenPointId() !== id && useLoadingInformationStore().getRiskPointId() !== id) {
useLoadingInformationStore().resetStatue()
}
// 点击对象
useLoadingInformationStore().setClickObject(pickedObject)
// 隐患点
if (pickedObject.id.startsWith(config.prefix.hiddenDangerPointId)) {
useLoadingInformationStore().setHiddenPointId(id)
}
// 风险点
else if (pickedObject.id.startsWith(config.prefix.riskPointId)) {
useLoadingInformationStore().setRiskPointId(id)
} else {
// 重置状态
useLoadingInformationStore().resetStatue()
}
} else {
// 重置状态
useLoadingInformationStore().resetStatue()
}
})
CesiumUtilsSingleton.viewToTarget(config.defaultPosition as [number, number, number]);
})
</script>
<style scoped>
.map_container {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
}
</style>
+118
View File
@@ -0,0 +1,118 @@
<template>
<div class="map_container" id="map-container"></div>
<!-- 行政区划 -->
<AdministrativeDivision v-if="useViewerStore().getViewerLoadingCompleted()" />
</template>
<script lang="ts" setup>
import { onBeforeMount, onMounted } from 'vue';
import config from '@/config/config.json';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
import AdministrativeDivision from './AdministrativeDivision.vue';
import { useViewerStore } from '@/stores/useViewerStore';
import { useLoadingInformationStore } from '@/stores/useLoadingInformation';
import xiAnGeoJSON from '@/assets/json/XiAn.json';
import type { GeoJsonFileType } from '@/types/cesium/GeoJsonFileType';
import { Color, ScreenSpaceEventType } from 'cesium';
import type { ClickObject } from '@/types/cesium/ClickObject';
onBeforeMount(() => {
// 初始化为false
useViewerStore().setViewerLoadingCompleted(false);
// 重置状态
useLoadingInformationStore().resetStatue();
});
onMounted(async () => {
await CesiumUtilsSingleton.initCesiumViewer({
containerId: 'map-container',
mark: {
include: true,
geoJson: xiAnGeoJSON as GeoJsonFileType,
color: Color.BLACK.withAlpha(0.8),
border: {
width: 3,
},
},
});
useViewerStore().setViewerLoadingCompleted(true);
// 注册全局点击监听器
CesiumUtilsSingleton.clickLayer((pickedObject: ClickObject) => {
console.log('点击对象:', pickedObject);
if (
pickedObject &&
pickedObject.id &&
typeof pickedObject.id === 'string'
) {
const matchResult = pickedObject.id.match(/\d+$/);
const id = matchResult ? parseInt(matchResult[0]) : -1;
// 当id改变时候,重置状态
if (
useLoadingInformationStore().getHiddenPointId() !== id &&
useLoadingInformationStore().getRiskPointId() !== id
) {
useLoadingInformationStore().resetStatue();
}
// 点击对象
useLoadingInformationStore().setClickObject(pickedObject);
// 隐患点
if (pickedObject.id.startsWith(config.prefix.hiddenDangerPointId)) {
useLoadingInformationStore().setHiddenPointId(id);
}
// 风险点
else if (pickedObject.id.startsWith(config.prefix.riskPointId)) {
useLoadingInformationStore().setRiskPointId(id);
} else {
// 重置状态
useLoadingInformationStore().resetStatue();
}
} else {
// 重置状态
useLoadingInformationStore().resetStatue();
}
});
// 注册全局滚轮监听器
CesiumUtilsSingleton.getViewer()!.scene.canvas.addEventListener(
'wheel',
() => {
// 设置最小最大高度
CesiumUtilsSingleton.setHeightLimits();
}
);
// 当行政区超出页面时,自动拉回视角
CesiumUtilsSingleton.outOverView();
// 禁止全局默认双击事件
CesiumUtilsSingleton.getViewer()?.cesiumWidget.screenSpaceEventHandler.removeInputAction(
ScreenSpaceEventType.LEFT_DOUBLE_CLICK
);
// 默认视角
CesiumUtilsSingleton.viewToTarget(
config.defaultPosition as [number, number, number]
);
});
</script>
<style scoped>
.map_container {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
}
</style>
@@ -5,24 +5,27 @@
<MapComponent />
<!-- 隐患点组件 -->
<HiddenPointComponent :disaster-type="props.disasterType" v-if="useViewerStore().getViewerLoadingCompleted()"/>
<HiddenPointComponent
:disaster-type="props.disasterType"
v-if="useViewerStore().getViewerLoadingCompleted()"
/>
<!-- 风险点组件 -->
<RiskPointComponent v-if="useViewerStore().getViewerLoadingCompleted()"/>
<RiskPointComponent v-if="useViewerStore().getViewerLoadingCompleted()" />
</div>
</template>
<script setup lang="ts">
import MapComponent from "@/component/map/Map.vue"
import type { DisasterType } from "@/types/common/DisasterType";
import HiddenPointComponent from "./HiddenPointComponent.vue";
import RiskPointComponent from "./RiskPointComponent.vue";
import { useViewerStore } from "@/stores/useViewerStore";
import MapComponent from '@/component/map/MapComponent.vue';
import type { DisasterType } from '@/types/common/DisasterType';
import HiddenPointComponent from './HiddenPointComponent.vue';
import RiskPointComponent from './RiskPointComponent.vue';
import { useViewerStore } from '@/stores/useViewerStore';
// 获取父组件传递德数据
const props = defineProps<{
disasterType: DisasterType
}>()
// 获取父组件传递德数据
const props = defineProps<{
disasterType: DisasterType;
}>();
</script>
<style scoped></style>
@@ -2,107 +2,129 @@
<template>
<div>
<!-- 加载基础隐患点 -->
<LoadingPoints v-if="useViewerStore().getViewerLoadingCompleted() && baseHiddenPoints.length > 0"
:base-points="baseHiddenPoints" :get-disaster-icon="getDisasterIcon"
:prefix="config.prefix.hiddenDangerPointId" />
<LoadingPoints
v-if="
useViewerStore().getViewerLoadingCompleted() &&
baseHiddenPoints.length > 0
"
:base-points="baseHiddenPoints"
:get-disaster-icon="getDisasterIcon"
:prefix="config.prefix.hiddenDangerPointId"
/>
<!-- 显示信息框 -->
<InformationBox :data='hiddenDangerPointDetail as Record<string, any>' :field="field"
v-if="useLoadingInformationStore().getLoadingHiddenPointInformationStatus()" :title="informationBoxTitle"
:offset-x="offsetX" :offset-y="offsetY" :key="useLoadingInformationStore().getHiddenPointId()" />
<InformationBox
:data="hiddenDangerPointDetail as Record<string, any>"
:field="field"
v-if="
useLoadingInformationStore().getLoadingHiddenPointInformationStatus()
"
:title="informationBoxTitle"
:offset-x="offsetX"
:offset-y="offsetY"
:key="useLoadingInformationStore().getHiddenPointId()"
/>
</div>
</template>
<script setup lang="ts">
import { DisasterType } from "@/types/common/DisasterType";
import { ref, watch } from "vue";
import { $api } from "@/api/api.ts";
import type { Point } from "@/types/base/Point";
import LoadingPoints from "@/component/rain-earthquake/LoadingPoints.vue";
import landslide from '@/assets/images/icon/landslide.png';
import debrisFlow from '@/assets/images/icon/debris-flow.png';
import flashFlood from '@/assets/images/icon/flash-flood.png';
import waterlogging from '@/assets/images/icon/waterlogging.png';
import config from '@/config/config.json'
import InformationBox from "@/component/common/InformationBox.vue";
import { useViewerStore } from "@/stores/useViewerStore";
import { useLoadingInformationStore } from "@/stores/useLoadingInformation";
import { CesiumUtilsSingleton } from "@/utils/cesium/CesiumUtils";
import { DisasterType } from '@/types/common/DisasterType';
import { ref, watch } from 'vue';
import { $api } from '@/api/api.ts';
import type { Point } from '@/types/base/Point';
import LoadingPoints from '@/component/rain-earthquake/LoadingPoints.vue';
import landslide from '@/assets/images/icon/landslide.png';
import debrisFlow from '@/assets/images/icon/debris-flow.png';
import flashFlood from '@/assets/images/icon/flash-flood.png';
import waterlogging from '@/assets/images/icon/waterlogging.png';
import config from '@/config/config.json';
import InformationBox from '@/component/common/InformationBox.vue';
import { useViewerStore } from '@/stores/useViewerStore';
import { useLoadingInformationStore } from '@/stores/useLoadingInformation';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
const props = defineProps<{
disasterType: DisasterType
}>()
const props = defineProps<{
disasterType: DisasterType;
}>();
const baseHiddenPoints = ref<Point[]>([]);
const baseHiddenPoints = ref<Point[]>([]);
const informationBoxTitle = ref('')
const offsetX = ref(0)
const offsetY = ref(0)
const hiddenDangerPointDetail = ref<Point>()
const informationBoxTitle = ref('');
const offsetX = ref(0);
const offsetY = ref(0);
const hiddenDangerPointDetail = ref<Point>();
const field = {
fieldCode: '野外编号',
disasterName: '灾害点名称',
position: '位置',
disasterType: '灾害类型',
scaleGrade: '规模等级',
riskGrade: '风险等级'
}
const field = {
fieldCode: '野外编号',
disasterName: '灾害点名称',
position: '位置',
disasterType: '灾害类型',
scaleGrade: '规模等级',
riskGrade: '风险等级',
};
$api.hiddenDangerSpots.getBasePoins(props.disasterType).then((res) => {
baseHiddenPoints.value = res.data
})
$api.hiddenDangerSpots.getBasePoins(props.disasterType).then((res) => {
baseHiddenPoints.value = res.data;
});
// 监听id变化
watch(() => useLoadingInformationStore().getHiddenPointId(), async (newId: number) => {
// 监听id变化
watch(
() => useLoadingInformationStore().getHiddenPointId(),
async (newId: number) => {
if (newId === -1) {
return;
}
if (newId === -1) {
return
}
// 获取隐患点数据
const clickObject = useLoadingInformationStore().getClickObject();
// 获取隐患点数据
const clickObject = useLoadingInformationStore().getClickObject();
if (!clickObject || !clickObject.primitive) {
console.warn('点击对象或图元不存在');
return;
}
if (!clickObject || !clickObject.primitive) {
console.warn('点击对象或图元不存在');
return;
}
const res = await $api.hiddenDangerSpots.getPointDetailById(
useLoadingInformationStore().getHiddenPointId()
);
const res = await $api.hiddenDangerSpots.getPointDetailById(useLoadingInformationStore().getHiddenPointId());
// 更新数据
hiddenDangerPointDetail.value = res.data;
informationBoxTitle.value = res.data.disasterType + '隐患点';
// 更新数据
hiddenDangerPointDetail.value = res.data;
informationBoxTitle.value = res.data.disasterType + '隐患点';
try {
// 将坐标转换为偏移量
const screenPos = CesiumUtilsSingleton.convertScreenPosition(
clickObject.primitive.position
);
offsetX.value = screenPos.x;
offsetY.value = screenPos.y;
try {
// 将坐标转换为偏移量
const screenPos = CesiumUtilsSingleton.convertScreenPosition(clickObject.primitive.position);
offsetX.value = screenPos.x;
offsetY.value = screenPos.y;
// 显示新的信息框
useLoadingInformationStore().setLoadingHiddenPointInformationStatus(true);
} catch (error) {
throw new Error(`坐标转换失败:${error}`);
}
})
// 显示新的信息框
useLoadingInformationStore().setLoadingHiddenPointInformationStatus(
true
);
} catch (error) {
throw new Error(`坐标转换失败:${error}`);
}
}
);
</script>
<script lang="ts">
function getDisasterIcon(disasterType?: string): string {
switch (disasterType) {
case '滑坡':
return landslide
case '泥石流':
return debrisFlow
case '内涝':
return waterlogging
case "山洪":
return flashFlood
default:
throw new Error(`未知的灾害类型: ${disasterType}`);
function getDisasterIcon(disasterType?: string): string {
switch (disasterType) {
case '滑坡':
return landslide;
case '泥石流':
return debrisFlow;
case '内涝':
return waterlogging;
case '山洪':
return flashFlood;
default:
throw new Error(`未知的灾害类型: ${disasterType}`);
}
}
}
</script>
<style scoped></style>
+19 -15
View File
@@ -1,27 +1,31 @@
<!-- 加载点的组件 -->
<template>
<div></div>
</template>
<script lang="ts" setup>
import { onMounted } from 'vue';
import { usePointsHandle } from '@/hooks/usePointsHandle';
import type { Point } from '@/types/base/Point';
import { onMounted } from 'vue';
import { usePointsHandle } from '@/hooks/usePointsHandle';
import type { Point } from '@/types/base/Point';
// 属性
const props = defineProps<{
basePoints: Point[]
getDisasterIcon: (disasterType?: string) => string
prefix: string
}>();
// 属性
const props = defineProps<{
basePoints: Point[];
getDisasterIcon: (disasterType?: string) => string;
prefix: string;
}>();
// 点处理钩子
const pointsHandle = usePointsHandle()
// 点处理钩子
const pointsHandle = usePointsHandle();
onMounted(() => {
onMounted(() => {
// 加载点
pointsHandle.addPoints(props.basePoints, props.getDisasterIcon, props.prefix)
})
pointsHandle.addPoints(
props.basePoints,
props.getDisasterIcon,
props.prefix
);
});
</script>
<style scoped></style>
@@ -1,37 +1,49 @@
<!-- 风险点组件 -->
<template>
<div>
<!-- 加载风险点 -->
<LoadingPoints v-if="useViewerStore().getViewerLoadingCompleted() && riskPoints.length > 0"
:base-points="riskPoints" :get-disaster-icon="getDisasterIcon" :prefix="config.prefix.riskPointId" />
<div>
<!-- 加载风险点 -->
<LoadingPoints
v-if="
useViewerStore().getViewerLoadingCompleted() && riskPoints.length > 0
"
:base-points="riskPoints"
:get-disaster-icon="getDisasterIcon"
:prefix="config.prefix.riskPointId"
/>
<!-- 显示信息框 -->
<InformationBox :data='riskPointDetail as Record<string, any>' :field="field"
v-if="useLoadingInformationStore().getLoadingRiskPointInformationStatus()" :title="informationBoxTitle"
:offset-x="offsetX" :offset-y="offsetY" :key="useLoadingInformationStore().getRiskPointId()" />
</div>
<!-- 显示信息框 -->
<InformationBox
:data="riskPointDetail as Record<string, any>"
:field="field"
v-if="useLoadingInformationStore().getLoadingRiskPointInformationStatus()"
:title="informationBoxTitle"
:offset-x="offsetX"
:offset-y="offsetY"
:key="useLoadingInformationStore().getRiskPointId()"
/>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { $api } from "@/api/api.ts";
import type { Point } from "@/types/base/Point";
import LoadingPoints from "@/component/rain-earthquake/LoadingPoints.vue";
import riskArea from '@/assets/images/icon/risk-area.png';
import config from '@/config/config.json'
import InformationBox from "@/component/common/InformationBox.vue";
import { useViewerStore } from "@/stores/useViewerStore";
import { useLoadingInformationStore } from "@/stores/useLoadingInformation";
import { CesiumUtilsSingleton } from "@/utils/cesium/CesiumUtils";
import { ref, watch } from 'vue';
import { $api } from '@/api/api.ts';
import type { Point } from '@/types/base/Point';
import LoadingPoints from '@/component/rain-earthquake/LoadingPoints.vue';
import riskArea from '@/assets/images/icon/risk-area.png';
import config from '@/config/config.json';
import InformationBox from '@/component/common/InformationBox.vue';
import { useViewerStore } from '@/stores/useViewerStore';
import { useLoadingInformationStore } from '@/stores/useLoadingInformation';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
const riskPoints = ref<Point[]>([]);
const riskPoints = ref<Point[]>([]);
const informationBoxTitle = '风险区域'
const offsetX = ref(0)
const offsetY = ref(0)
const riskPointDetail = ref<Point>()
const informationBoxTitle = '风险区域';
const offsetX = ref(0);
const offsetY = ref(0);
const riskPointDetail = ref<Point>();
const field = {
const field = {
riskName: '风险区名称',
unitCode: '统一编号',
housing: '住房(间)',
@@ -42,49 +54,56 @@ const field = {
inspectorTele: '巡查员手机号',
position: '位置',
lon: '经度',
lat: '纬度'
}
lat: '纬度',
};
$api.riskSpots.getBasePoins().then((res) => {
riskPoints.value = res.data
})
$api.riskSpots.getBasePoins().then((res) => {
riskPoints.value = res.data;
});
// 监听id变化
watch(() => useLoadingInformationStore().getRiskPointId(), async (newId: number) => {
if (newId === -1) {
return
}
// 获取风险点数据
const clickObject = useLoadingInformationStore().getClickObject();
// 监听id变化
watch(
() => useLoadingInformationStore().getRiskPointId(),
async (newId: number) => {
if (newId === -1) {
return;
}
// 获取风险点数据
const clickObject = useLoadingInformationStore().getClickObject();
if (!clickObject || !clickObject.primitive) {
if (!clickObject || !clickObject.primitive) {
console.warn('点击对象或图元不存在');
return;
}
}
const res = await $api.riskSpots.getPointDetailById(useLoadingInformationStore().getRiskPointId());
const res = await $api.riskSpots.getPointDetailById(
useLoadingInformationStore().getRiskPointId()
);
// 更新数据
riskPointDetail.value = res.data;
// 更新数据
riskPointDetail.value = res.data;
try {
try {
// 将坐标转换为偏移量
const screenPos = CesiumUtilsSingleton.convertScreenPosition(clickObject.primitive.position);
const screenPos = CesiumUtilsSingleton.convertScreenPosition(
clickObject.primitive.position
);
offsetX.value = screenPos.x;
offsetY.value = screenPos.y;
// 显示新的信息框
useLoadingInformationStore().setLoadingRiskPointInformationStatus(true);
} catch (error) {
} catch (error) {
throw new Error(`坐标转换失败:${error}`);
}
}
})
);
</script>
<script lang="ts">
function getDisasterIcon(): string {
function getDisasterIcon(): string {
return riskArea;
}
}
</script>
<style scoped></style>