Compare commits

...

10 Commits

36 changed files with 739 additions and 376 deletions

1
.gitignore vendored
View File

@ -13,6 +13,7 @@ dist
dist-ssr
*.local
public/Cesium
public/landmarkImg
# Editor directories and files
.vscode/*

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数字地球</title>
<title>地图轨迹绘制</title>
</head>
<body>
<div id="app"></div>

View File

@ -1,5 +1,5 @@
{
"name": "digital-earth",
"name": "map-trajectory-draw",
"private": true,
"version": "0.0.0",
"scripts": {
@ -9,12 +9,16 @@
},
"dependencies": {
"cesium": "^1.92.0",
"echarts": "^5.4.0",
"naive-ui": "^2.34.3",
"pinia": "^2.0.13",
"vue": "^3.2.25",
"vue-cesium": "^3.0.11"
"vue-cesium": "^3.0.11",
"vue-echarts": "^6.2.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.3.0",
"less": "^4.1.3",
"vite": "^2.9.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -1,30 +1,46 @@
<template>
<vc-config-provider :cesium-path="CESIUM_PATH">
<Earth>
<LocatingPoint />
<MarkPoints />
</Earth>
</vc-config-provider>
<LonlatForm id="lonlat-form"></LonlatForm>
<LonlatTable id="lonlat-table"></LonlatTable>
<HotLandmark id="hotlandmark"></HotLandmark>
<div class="w-h-full flex">
<div style="width: 80%; height: 100%;">
<vc-config-provider :cesium-path="CESIUM_PATH">
<Earth>
<LocatingPoint />
</Earth>
</vc-config-provider>
<LonlatForm id="lonlat-form" ref="clear"></LonlatForm>
</div>
<div style="width: 20%; height: 100%;">
<Application>
<CalculationArea @clear="handleClear" />
</Application>
</div>
</div>
</template>
<script setup>
import { VcConfigProvider } from 'vue-cesium'
import Earth from '/@/components/Earth.vue'
import LonlatForm from '/@/components/LonlatForm.vue'
import LonlatTable from '/@/components/LonlatTable.vue'
import MarkPoints from "/@/components/MarkPoints.vue"
import { ref } from "vue";
import { VcConfigProvider } from "vue-cesium";
import Earth from "/@/components/Earth.vue";
import LonlatForm from '/@/components/LonlatForm.vue';
import LocatingPoint from '/@/components/LocatingPoint.vue'
import HotLandmark from '/@/components/HotLandmark.vue'
import Application from "/@/components/Application.vue";
import CalculationArea from "/@/components/CalculationArea.vue";
const CESIUM_PATH = (process.env.NODE_ENV === 'development' ? './node_modules/cesium/Build/Cesium/Cesium.js': './Cesium/Cesium.js')
const CESIUM_PATH =
process.env.NODE_ENV === "development"
? "./node_modules/cesium/Build/Cesium/Cesium.js"
: "./Cesium/Cesium.js";
const clear = ref();
const handleClear = () => {
clear.value.onClearBtnClick();
}
</script>
<style>
html, body, #app {
html,
body,
#app {
margin: 0;
padding: 0;
width: 100%;

View File

@ -1,8 +1,8 @@
export const isLnglat = lnglat => {
const { lng, lat } = lnglat
if (isNaN(lng) || lng > 180 || lng < -180) return false
if (isNaN(lat) || lat > 90 || lat < -90 ) return false
if (lng=='' || isNaN(lng) || lng > 180 || lng < -180) return false
if (lat=='' || isNaN(lat) || lat > 90 || lat < -90 ) return false
return true
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,12 +0,0 @@
import poi1 from '/@/assets/poi/1.png'
import poi2 from '/@/assets/poi/2.png'
import poi3 from '/@/assets/poi/3.png'
import poi4 from '/@/assets/poi/4.png'
import poi5 from '/@/assets/poi/5.png'
import poi6 from '/@/assets/poi/6.png'
import poi7 from '/@/assets/poi/7.png'
import poi8 from '/@/assets/poi/8.png'
import poi9 from '/@/assets/poi/9.png'
import poi10 from '/@/assets/poi/10.png'
export default [ poi1, poi2, poi3, poi4, poi5, poi6, poi7, poi8, poi9, poi10 ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

59
src/common.less Normal file
View File

@ -0,0 +1,59 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
}
li {
list-style: none;
}
div::-webkit-scrollbar {
width: 0;
}
.w-full {
width: 100%;
}
.h-full {
height: 100%;
}
.w-h-full {
width: 100%;
height: 100%;
}
.text-center {
text-align: center;
}
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.flex-1 {
flex: 1 1 0%;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.text-right {
text-align: right;
}

View File

@ -0,0 +1,31 @@
<template>
<n-config-provider
:locale="zhCN"
:date-locale="dateZhCN"
:theme-overrides="themeOverrides"
>
<n-loading-bar-provider>
<n-message-provider>
<n-notification-provider>
<n-dialog-provider>
<slot name="default"></slot>
</n-dialog-provider>
</n-notification-provider>
</n-message-provider>
</n-loading-bar-provider>
</n-config-provider>
</template>
<script setup>
import {
zhCN,
dateZhCN,
NConfigProvider,
NDialogProvider,
NMessageProvider,
NLoadingBarProvider,
NNotificationProvider,
} from "naive-ui";
const themeOverrides = {};
</script>

View File

@ -0,0 +1,258 @@
<template>
<n-flex vertical>
<div style="height:100vh">
<n-scrollbar style="max-height: 100vh; border: 1px solid #ddd;padding-top:10vh;padding-bottom:10vh;">
<n-dynamic-input
v-model:value="geodata"
:on-create="onCreate"
:on-remove="onRemove"
>
<template #default="{ value }">
<div style="display: flex; align-items: flex-start; width: 100%">
<div style="width: 50%">
<n-input
maxlength="13"
clearable
v-model:value="value.lat"
type="text"
placeholder="经度"
@input="handleInput"
:status="value.latStatus"
/>
<n-gradient-text :size="12" type="error" v-show="value.latCheck">
<div v-html="value.latErrMsg"></div>
</n-gradient-text>
</div>
<div style="width: 50%">
<n-input
maxlength="12"
clearable
v-model:value="value.lng"
type="text"
placeholder="纬度"
@input="handleInput"
:status="value.lngStatus"
/>
<n-gradient-text :size="12" type="error" v-show="value.lngCheck">
<div v-html="value.lngErrMsg"></div>
</n-gradient-text>
</div>
</div>
</template>
</n-dynamic-input>
<div class="w-full flex flex-1" style="border: 1px solid #ddd;position:absolute;bottom:5vh;left:0;">
<n-button
class="mx-auto"
:disabled="geodata.length == 0 ? true : false"
size="large"
type="primary"
@click="drawTrajectory"
>生成轨迹</n-button
>
<n-button
class="mx-auto"
:disabled="geodata.length == 0 ? true : false"
size="large"
type="info"
@click="drawArea"
>生成图案</n-button
>
<n-button
class="mx-auto"
:disabled="geodata.length == 0 ? true : false"
size="large"
type="error"
@click="delgeo"
>清空输入</n-button
>
</div>
</n-scrollbar>
</div>
</n-flex>
</template>
<script setup>
import { ref, defineEmits } from "vue";
import {
NFlex,
NButton,
NDynamicInput,
NScrollbar,
NInput,
NGradientText,
useMessage,
useDialog,
} from "naive-ui";
import { usePositionArrStore } from "/@/stores/positionArr";
const message = useMessage();
const dialog = useDialog();
const emit = defineEmits(['clear']);
const positionArr = usePositionArrStore();
const geodata = ref([
{
lat: "",
latStatus: "",
latCheck: "",
latErrMsg: "",
lng: "",
lngStatus: "",
lngCheck: "",
lngErrMsg: "",
},
]);
const onCreate = () => {
return {
lat: "",
latStatus: "",
latCheck: "",
latErrMsg: "",
lng: "",
lngStatus: "",
lngCheck: "",
lngErrMsg: "",
};
};
const inputFilter = (inputData) => {
let infilter = [];
let beffilter = [...inputData];
beffilter.forEach((item) => {
if (item !== "\u00A0" && item !== "\u0020" && item !== "\u3000") {
if (!isNaN(Number(item))) {
infilter.push(item);
} else if (item == ".") {
if (infilter.indexOf(".") == "-1") {
infilter.push(item);
}
} else if (item == "-") {
if (infilter.indexOf("-") == "-1") {
infilter.push(item);
}
}
}
});
return infilter.join("");
};
const stuck = (dataObj, dataItem, Status, Check, ErrMsg, throwMsg) => {
dataObj[dataItem + "Status"] = Status;
dataObj[dataItem + "Check"] = Check;
dataObj[dataItem + "ErrMsg"] = ErrMsg;
if (throwMsg) {
message.error(ErrMsg);
throw new Error(ErrMsg);
}
};
const judgment = (dataObj, dataItem, ErrMsg, throwMsg) => {
let toJudgment;
if (dataItem == "lat") {
toJudgment =
Number(dataObj[dataItem]).toFixed(8) > 180 ||
Number(dataObj[dataItem]).toFixed(8) < -180;
} else if (dataItem == "lng") {
toJudgment =
Number(dataObj[dataItem]).toFixed(8) > 90 ||
Number(dataObj[dataItem]).toFixed(8) < -90;
}
if (dataObj[dataItem] == "") {
stuck(dataObj, dataItem, "error", true, ErrMsg + "不能为空", throwMsg);
} else if (
(dataObj[dataItem].indexOf("-") !== -1 && dataObj[dataItem].indexOf("-") !== 0) ||
dataObj[dataItem].indexOf(".") == dataObj[dataItem].length - 1 ||
dataObj[dataItem].indexOf("-") + 1 == dataObj[dataItem].indexOf(".")
) {
stuck(dataObj, dataItem, "error", true, ErrMsg + "数据格式错误", throwMsg);
} else if (toJudgment) {
stuck(dataObj, dataItem, "error", true, "非法的" + ErrMsg + "数据", throwMsg);
} else {
stuck(dataObj, dataItem, "success", false, "", false);
if (throwMsg) {
dataObj[dataItem] = Number(dataObj[dataItem]).toString();
}
}
};
const handleInput = () => {
geodata.value.forEach((element, index) => {
element.lat = inputFilter(element.lat);
element.lng = inputFilter(element.lng);
judgment(element, "lat", "经度", false);
judgment(element, "lng", "纬度", false);
});
};
const calculation = () => {
let pointArr = [];
geodata.value.forEach((element, index) => {
judgment(element, "lat", "经度", true);
judgment(element, "lng", "纬度", true);
pointArr.push({
longitude: element.lat.length > 8 ? Number(element.lat).toFixed(8) : Number(element.lat),
latitude: element.lng.length > 8 ? Number(element.lng).toFixed(8) : Number(element.lng),
});
});
return pointArr;
};
const delgeo = () => {
dialog.warning({
title: "警告",
content: "确定要清除全部输入吗?",
positiveText: "确定",
negativeText: "返回",
onPositiveClick: () => {
emit('clear');
positionArr.$reset();
geodata.value = [
{
lat: "",
latStatus: "",
latCheck: "",
lng: "",
lngStatus: "",
lngCheck: "",
},
];
},
onNegativeClick: () => {
message.error("已返回");
},
});
};
const drawTrajectory = () => {
if (geodata.value.length <= 1) {
message.error("经纬度数据对的数量不能满足运算");
return;
}
positionArr.add('trajectory', calculation());
};
const drawArea = () => {
if (geodata.value.length <= 2) {
message.error("经纬度数据对的数量不能满足运算");
return;
}
positionArr.add('area', calculation());
};
</script>
<style scoped lang="less">
.n-grid {
place-items: center;
}
.p {
padding: 1%;
padding-top: 2%;
}
.mt {
margin-top: 2%;
}
</style>

View File

@ -1,32 +1,32 @@
<template>
<div class="compass" @click="Compass">
<img class="north" src="../assets/compass.png">
</div>
<div class="compass" style="cursor: pointer" @click="Compass">
<img class="north" src="../assets/compass.png" />
</div>
</template>
<script setup>
import {defineEmits} from 'vue'
const emit = defineEmits(['Pointing'])
import { defineEmits } from "vue";
const emit = defineEmits(["Pointing"]);
const Compass = () => {
emit('Pointing')
}
emit("Pointing");
};
</script>
<style scoped>
.compass{
width:50px;
height:50px;
padding:5px;
padding-top:0;
border-radius:50%;
background-color:#fff;
position:fixed;
bottom:245px;
left:42px;
z-index:99;
.compass {
width: 50px;
height: 50px;
padding: 5px;
padding-top: 0;
border-radius: 50%;
background-color: #fff;
position: fixed;
bottom: 245px;
left: 42px;
z-index: 99;
}
.north{
width:40px;
.north {
width: 40px;
}
</style>
</style>

View File

@ -1,5 +1,10 @@
<template>
<vc-viewer :showCredit="false" @ready="ready" @leftDoubleClick="leftDoubleClick" :info-box="false">
<vc-viewer
:showCredit="false"
@ready="ready"
@leftDoubleClick="leftDoubleClick"
:info-box="false"
>
<vc-layer-imagery>
<vc-imagery-provider-urltemplate
:projectionTransforms="projectionTransforms"
@ -27,14 +32,14 @@
:locationOpts="false"
:otherOpts="false"
/>
<Compass @Pointing = "pointTo"/>
<Compass @Pointing="pointTo" />
</vc-viewer>
</template>
<script setup>
import Compass from '/@/components/Compass.vue'
import { usePointStore } from "/@/stores/point";
import Compass from "/@/components/Compass.vue";
import { usePositionStore } from "/@/stores/position";
import { usePositionArrStore } from "/@/stores/positionArr";
import {
VcViewer,
VcStatusBar,
@ -49,57 +54,81 @@ const projectionTransforms = { from: "GCJ02", to: "WGS84" };
const img_url = "https://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=6";
const ann_url = "https://webst01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=8";
let Cesium = null,
viewer = null;
const ready = (readyObj) => {
Cesium = readyObj.Cesium;
viewer = readyObj.viewer;
window.viewer = readyObj.viewer;
viewer._selectionIndicator = false;
//
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
);
//Cesiumentity
};
const point = usePointStore();
const leftDoubleClick = ({ position }) => {
if (!viewer) return;
const positionArr = usePositionArrStore();
if (point.index >= point.length) {
alert(`最多只能够添加 ${point.length} 个点`);
return;
const drawTrack = (points) => {
//
const pathEntity = viewer.entities.add({
id: "pathEntity",
name: "My pathEntity",
polyline: {
positions: [], //
width: 3,
material: Cesium.Color.RED,
},
});
// Cartesian3
points.forEach((point) => {
const position = Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude);
pathEntity.polyline.positions._value.push(position);
});
};
const drawPolygon = (positionsArray) => {
// Cesium.Cartesian3
const cartesianPositions = positionsArray.map((pos) => {
return Cesium.Cartesian3.fromDegrees(pos.longitude, pos.latitude);
});
// viewer.entities
const polygonEntity = viewer.entities.add({
id: "polygonEntity",
name: "My polygonEntity",
polygon: {
//
hierarchy: cartesianPositions,
//
material: Cesium.Color.BLUE.withAlpha(0.5), //
height: 0, //
// 线
outline: true, // 线
outlineColor: Cesium.Color.WHITE, // 线
outlineWidth: 2, // 线
},
});
return polygonEntity;
};
positionArr.$subscribe((_, state) => {
if (state.mode == "trajectory") {
drawTrack(state.positionArr);
}
const cartesian = viewer.camera.pickEllipsoid(position, viewer.scene.globe.ellipsoid);
if (!cartesian) return;
const lnglat = cartesian2Lonlat(cartesian);
point.addItem(lnglat);
};
const cartesian2Lonlat = (cartesian) => {
if (!Cesium) return;
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lng = Cesium.Math.toDegrees(cartographic.longitude).toFixed(8);
const lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(8);
return { lng, lat };
};
if (state.mode == "area") {
drawPolygon(state.positionArr);
}
if (state.mode == "") {
let pathEntity = viewer.entities.getById('pathEntity');
viewer.entities.remove(pathEntity);
let polygonEntity = viewer.entities.getById('polygonEntity');
viewer.entities.remove(polygonEntity);
}
});
const position = usePositionStore();
position.$subscribe((_, state) => {
// import { MutationType } from 'pinia'
// mutation.type // 'direct' | 'patch object' | 'patch function'
// same as cartStore.$id
// mutation.storeId // 'cart'
// only available with mutation.type === 'patch object'
// mutation.payload // patch object passed to cartStore.$patch()
// statestatelocalStorage
// localStorage.setItem('cart', JSON.stringify(state))
if (!isLnglat(state)) return;
viewer.camera.flyTo({
@ -109,12 +138,16 @@ position.$subscribe((_, state) => {
// 广 116.39140105, 39.90452844 2000.0
const pointTo = () => {
let initialPosition = Cesium.Cartesian3.fromDegrees(position.lng?position.lng:116.39140105, position.lat?position.lat:39.90452844, 2000.0);
let initialPosition = Cesium.Cartesian3.fromDegrees(
position.lng ? position.lng : 116.39140105,
position.lat ? position.lat : 39.90452844,
2000.0
);
let initialOrientation = Cesium.HeadingPitchRoll.fromDegrees(0.0, -90.0, 0.0);
viewer.camera.flyTo({
destination: initialPosition,
orientation: initialOrientation,
endtransform: Cesium.Matrix4.IDENTITY,
});
}
};
</script>

View File

@ -1,129 +0,0 @@
<template>
<div>
<div v-show="!showit" class="switch" style="position:absolute;top:-40px;right:0;z-index:99;" @click="showLandmark">
<img class="icon" src="../assets/up.png">
</div>
<div v-show="showit" class="switch" style="position:absolute;top:-50px;right:0;z-index:99;" @click="showLandmark">
<img class="icon" src="../assets/down.png">
</div>
<div class="landmark">
<table v-if="showit">
<thead>
<tr>
<th>景点名称</th>
<th>经度</th>
<th>纬度</th>
<th>访问景点</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in landmarkArr" :key="index">
<td>{{ item ? item.landmark : index+1 }}</td>
<td>{{ item ? item.lng : "" }}</td>
<td>{{ item ? item.lat : "" }}</td>
<td><button @click="write(item.lng,item.lat)">访</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { usePositionStore } from '/@/stores/position'
const landmarkArr = [
{
landmark:'北京天安门',
lng:116.391243,
lat:39.907202
},
{
landmark:'北京鸟巢',
lng:116.390502,
lat:39.991396
},
{
landmark:'上海东方明珠',
lng:121.495263,
lat:31.241829
},
{
landmark:'香港迪斯尼',
lng:114.042287,
lat:22.313002
},
{
landmark:'布达拉宫',
lng:91.117684,
lat:29.656959
}
]
let showit = ref(false);
const showLandmark = () => {
showit.value = !showit.value;
}
const position = usePositionStore()
const write = (lng,lat) => {
position.set({ lng: lng, lat: lat })
}
</script>
<style scoped>
.landmark {
max-height: 360px;
overflow-y:scroll;
}
.switch {
width:42px;
height:42px;
border-radius: 50%;
background-color:#fff;
padding-top:9px;
padding-left:3px;
}
.icon {
width:36px;
}
table {
color: #FFFFFF;
background-color: #242424;
padding: 10px;
border-radius: 7px;
border-collapse: separate;
border-spacing: 2px;
text-align:center;
}
table th:first-child {
width: 120px;
}
table th:not(:first-child) {
width: 100px;
}
table thead tr {
background-color: rgba(84, 84, 84, 0.8);
}
table tbody tr:nth-child(even) {
background-color: rgba(84, 84, 84, 0.8);
}
table tbody tr:nth-child(odd) {
background-color: rgba(84, 84, 84, 0.25);
}
table th, table td {
padding: 3px 5px;
}
</style>

View File

@ -1,37 +1,45 @@
<template>
<form @keyup.enter="onFlyBtnClick">
<label>经度</label>
<input type="number" v-model="lng" placeholder="请输入经度值">
<input type="number" v-model="lng" placeholder="请输入经度值" />
<label>纬度</label>
<input type="number" v-model="lat" placeholder="请输入纬度值">
<input type="button" id="fly-btn" @click="onFlyBtnClick" value="飞到这个点">
<input type="button" id="clear-btn" @click="onClearBtnClick" value="清除坐标">
<input type="number" v-model="lat" placeholder="请输入纬度值" />
<input
type="button"
style="cursor: pointer"
id="fly-btn"
@click="onFlyBtnClick"
value="飞到这个点"
/>
<input
type="button"
style="cursor: pointer"
id="clear-btn"
@click="onClearBtnClick"
value="清除坐标"
/>
</form>
</template>
<script setup>
import { ref } from 'vue';
import { usePointStore } from '/@/stores/point'
import { usePositionStore } from '/@/stores/position'
import { ref } from "vue";
import { usePositionStore } from "/@/stores/position";
const lng = ref(NaN);
const lat = ref(NaN);
const position = usePositionStore();
const lng = ref(NaN)
const lat = ref(NaN)
const position = usePositionStore()
const onFlyBtnClick = () => {
if ( !position.set({ lng: lng.value, lat: lat.value }) ) alert('请输入正确的经纬度信息')
}
if (!position.set({ lng: lng.value, lat: lat.value })) alert("请输入正确的经纬度信息");
};
const point = usePointStore()
const onClearBtnClick = () => {
lng.value = NaN
lat.value = NaN
position.$reset()
point.$reset()
}
lng.value = NaN;
lat.value = NaN;
position.$reset();
};
defineExpose({ onClearBtnClick });
</script>
<style scoped>
@ -63,25 +71,26 @@ input:focus {
}
/* Chrome, Safari, Edge, Opera */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
input[type="number"] {
-moz-appearance: textfield;
}
input#fly-btn, input#clear-btn {
input#fly-btn,
input#clear-btn {
border-radius: 3px;
background-color: #41ddee;
}
input#fly-btn:hover , input#clear-btn:hover {
input#fly-btn:hover,
input#clear-btn:hover {
background-color: #ffffff;
color: #41ddee;
}
</style>
</style>

View File

@ -1,62 +0,0 @@
<template>
<table v-if="show">
<thead>
<tr>
<th>序号</th>
<th>经度</th>
<th>纬度</th>
</tr>
</thead>
<tbody id="point-list">
<tr v-for="item, index in point.items" :key="index">
<td>{{ index + 1 }}</td>
<td>{{ item ? item.lng : ''}}</td>
<td>{{ item ? item.lat : ''}}</td>
</tr>
</tbody>
</table>
</template>
<script setup>
import { computed } from 'vue'
import { usePointStore } from '/@/stores/point'
const point = usePointStore()
const show = computed(() => point.index)
</script>
<style scoped>
table {
color: #FFFFFF;
background-color: #242424;
padding: 10px;
border-radius: 7px;
border-collapse: separate;
border-spacing: 2px;
text-align:center;
}
table th:first-child {
width: 60px;
}
table th:not(:first-child) {
width: 120px;
}
table thead tr {
background-color: rgba(84, 84, 84, 0.8);
}
table tbody tr:nth-child(even) {
background-color: rgba(84, 84, 84, 0.8);
}
table tbody tr:nth-child(odd) {
background-color: rgba(84, 84, 84, 0.25);
}
table th, table td {
padding: 3px 5px;
}
</style>

View File

@ -1,15 +0,0 @@
<template>
<Pin
v-for="item, index in point.items"
:key="index"
:position="item"
:image="pois[index]"/>
</template>
<script setup>
import { usePointStore } from '/@/stores/point'
import Pin from '/@/components/Pin.vue'
import pois from '/@/assets/poi'
const point = usePointStore()
</script>

View File

@ -1,25 +1,29 @@
<template>
<vc-entity :show="show" :position="position">
<vc-graphics-billboard :image="image" :verticalOrigin="1" />
</vc-entity>
<vc-entity
:show="show"
:position="position"
>
<vc-graphics-billboard
:image="pin"
:verticalOrigin="1"
:scale="1"
:color="'none'"
/>
</vc-entity>
</template>
<script setup>
import { computed } from 'vue'
import { VcEntity, VcGraphicsBillboard } from 'vue-cesium'
import { isLnglat } from '/@/api/util'
import pin from '/@/assets/pin.png'
import { computed } from "vue";
import { VcEntity, VcGraphicsBillboard } from "vue-cesium";
import { isLnglat } from "/@/api/util";
import pin from "/@/assets/pin.png";
const props = defineProps({
position: {
type: Object,
default: { lng: NaN, lat: NaN },
},
image: {
type: String,
default: pin,
}
})
});
const show = computed(() => isLnglat(props.position))
const show = computed(() => isLnglat(props.position));
</script>

View File

@ -2,6 +2,8 @@ import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
import './common.less'
import 'vue-cesium/dist/index.css';
createApp(App).use(createPinia()).mount('#app')

View File

@ -1,28 +0,0 @@
import { defineStore } from 'pinia'
export const usePointStore = defineStore({
id: 'point',
state: () => ({
index: 0,
length: 10,
rawItems: [],
}),
getters: {
items: (state) => {
const items = state.rawItems
items.length = state.length
return items
}
},
actions: {
addItem(item) {
if (this.index >= this.length) {
return
}
this.rawItems[this.index] = item
this.index++
},
},
})

View File

@ -7,6 +7,7 @@ export const usePositionStore = defineStore({
state: () => ({
lng: NaN,
lat: NaN,
change:true,
}),
getters: {
value: (state) => { state.lng, state.lat }
@ -17,6 +18,7 @@ export const usePositionStore = defineStore({
this.lng = position.lng
this.lat = position.lat
this.change = !this.change
return true
},

15
src/stores/positionArr.js Normal file
View File

@ -0,0 +1,15 @@
import { defineStore } from 'pinia'
export const usePositionArrStore = defineStore({
id: 'positionArr',
state: () => ({
mode:'',
positionArr:[]
}),
actions: {
add(inputMode, inputArr) {
this.mode = inputMode;
this.positionArr = inputArr;
}
},
})

View File

@ -9,6 +9,7 @@ function pathResolve(dir) {
// https://vitejs.dev/config/
export default defineConfig({
base: './',
resolve: {
alias: [
// /@/xxxx => src/xxxx

174
yarn.lock
View File

@ -12,6 +12,50 @@
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.17.8.tgz#2817fb9d885dd8132ea0f8eb615a6388cca1c240"
integrity sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==
"@babel/runtime@^7.21.0":
version "7.24.6"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e"
integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==
dependencies:
regenerator-runtime "^0.14.0"
"@css-render/plugin-bem@^0.15.12":
version "0.15.14"
resolved "https://registry.npmmirror.com/@css-render/plugin-bem/-/plugin-bem-0.15.14.tgz#de13fc9f59299c2b646119851763dfa08929b3c1"
integrity sha512-QK513CJ7yEQxm/P3EwsI+d+ha8kSOcjGvD6SevM41neEMxdULE+18iuQK6tEChAWMOQNQPLG/Rw3Khb69r5neg==
"@css-render/vue3-ssr@^0.15.10", "@css-render/vue3-ssr@^0.15.12":
version "0.15.14"
resolved "https://registry.npmmirror.com/@css-render/vue3-ssr/-/vue3-ssr-0.15.14.tgz#a2f4dedc3e86211a3ce1445555265095b7736491"
integrity sha512-//8027GSbxE9n3QlD73xFY6z4ZbHbvrOVB7AO6hsmrEzGbg+h2A09HboUyDgu+xsmj7JnvJD39Irt+2D0+iV8g==
"@emotion/hash@~0.8.0":
version "0.8.0"
resolved "https://registry.npmmirror.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
"@juggle/resize-observer@^3.3.1":
version "3.4.0"
resolved "https://registry.npmmirror.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
"@types/katex@^0.16.2":
version "0.16.7"
resolved "https://registry.npmmirror.com/@types/katex/-/katex-0.16.7.tgz#03ab680ab4fa4fbc6cb46ecf987ecad5d8019868"
integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==
"@types/lodash-es@^4.17.9":
version "4.17.12"
resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz#65f6d1e5f80539aa7cfbfc962de5def0cf4f341b"
integrity sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==
dependencies:
"@types/lodash" "*"
"@types/lodash@*", "@types/lodash@^4.14.198":
version "4.17.4"
resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.4.tgz#0303b64958ee070059e3a7184048a55159fe20b7"
integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==
"@vitejs/plugin-vue@^2.3.0":
version "2.3.1"
resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-2.3.1.tgz#5f286b8d3515381c6d5c8fa8eee5e6335f727e14"
@ -117,16 +161,51 @@
resolved "https://registry.npmmirror.com/@zouyaoji/heatmap.js/-/heatmap.js-2.0.8.tgz#5f6b285e7635ca07f2ecdb3d83a9dc1d240433d7"
integrity sha512-kBQny/zOUFH2OFoVyu6IdGJEcQMENIAASUsaZhk+OuJ9WexsYf6EU2lCyGURcsFly1kTMZKODlV7nBTCgfvJqg==
async-validator@^4.2.5:
version "4.2.5"
resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz#c96ea3332a521699d0afaaceed510a54656c6339"
integrity sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==
cesium@^1.92.0:
version "1.92.0"
resolved "https://registry.npmmirror.com/cesium/-/cesium-1.92.0.tgz#d4a736be7f3516830a814c4c99780a385c12a258"
integrity sha512-qU2EIV3M+ru6uF5UQUjUWXeq9UVieMBeq+Q8fzzNbFgeSbLrvnJ7jSJq0vvgaVDPe0PnmN72FZKMDiJdTFpMnQ==
css-render@^0.15.10, css-render@^0.15.12:
version "0.15.14"
resolved "https://registry.npmmirror.com/css-render/-/css-render-0.15.14.tgz#c23d8c8b9c0b44cd20b426f5e9de7ef7bade69b8"
integrity sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==
dependencies:
"@emotion/hash" "~0.8.0"
csstype "~3.0.5"
csstype@^2.6.8:
version "2.6.20"
resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda"
integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
csstype@~3.0.5:
version "3.0.11"
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
date-fns-tz@^2.0.0:
version "2.0.1"
resolved "https://registry.npmmirror.com/date-fns-tz/-/date-fns-tz-2.0.1.tgz#0a9b2099031c0d74120b45de9fd23192e48ea495"
integrity sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==
date-fns@^2.30.0:
version "2.30.0"
resolved "https://registry.npmmirror.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
dependencies:
"@babel/runtime" "^7.21.0"
echarts@^5.2.1:
version "5.3.2"
resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.2.tgz#0a7b3be8c48a48b2e7cb1b82121df0c208d42d2c"
@ -266,6 +345,11 @@ estree-walker@^2.0.2:
resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
evtd@^0.2.2, evtd@^0.2.4:
version "0.2.4"
resolved "https://registry.npmmirror.com/evtd/-/evtd-0.2.4.tgz#0aac39ba44d6926e6668948ac27618e0795b9d07"
integrity sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
@ -283,6 +367,11 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
highlight.js@^11.8.0:
version "11.9.0"
resolved "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.9.0.tgz#04ab9ee43b52a41a047432c8103e2158a1b8b5b0"
integrity sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==
is-core-module@^2.8.1:
version "2.8.1"
resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
@ -322,6 +411,31 @@ mitt@^3.0.0:
resolved "https://registry.npmmirror.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd"
integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==
naive-ui@^2.34.3:
version "2.38.2"
resolved "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.38.2.tgz#d7c8bdbe9319ea3dd2c24c4f6741090650eae24a"
integrity sha512-WhZ+6DW61aYSmFyfH7evcSGFmd2xR68Yq1mNRrVdJwBhZsnNdAUsMN9IeNCVEPMCND/jzYZghkStoNoR5Xa09g==
dependencies:
"@css-render/plugin-bem" "^0.15.12"
"@css-render/vue3-ssr" "^0.15.12"
"@types/katex" "^0.16.2"
"@types/lodash" "^4.14.198"
"@types/lodash-es" "^4.17.9"
async-validator "^4.2.5"
css-render "^0.15.12"
csstype "^3.1.3"
date-fns "^2.30.0"
date-fns-tz "^2.0.0"
evtd "^0.2.4"
highlight.js "^11.8.0"
lodash "^4.17.21"
lodash-es "^4.17.21"
seemly "^0.3.8"
treemate "^0.3.11"
vdirs "^0.1.8"
vooks "^0.2.12"
vueuc "^0.4.58"
nanoid@^3.3.1:
version "3.3.2"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557"
@ -362,6 +476,16 @@ proj4@^2.7.5:
mgrs "1.0.0"
wkt-parser "^1.3.1"
regenerator-runtime@^0.14.0:
version "0.14.1"
resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
resize-detector@^0.3.0:
version "0.3.0"
resolved "https://registry.npmmirror.com/resize-detector/-/resize-detector-0.3.0.tgz#fe495112e184695500a8f51e0389f15774cb1cfc"
integrity sha512-R/tCuvuOHQ8o2boRP6vgx8hXCCy87H1eY9V5imBYeVNyNVpuL9ciReSccLj2gDcax9+2weXy3bc8Vv+NRXeEvQ==
resolve@^1.22.0:
version "1.22.0"
resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
@ -378,6 +502,11 @@ rollup@^2.59.0:
optionalDependencies:
fsevents "~2.3.2"
seemly@^0.3.6, seemly@^0.3.8:
version "0.3.8"
resolved "https://registry.npmmirror.com/seemly/-/seemly-0.3.8.tgz#42879d8375d73126a04dc16b1bf92a773d2e5974"
integrity sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==
source-map-js@^1.0.2:
version "1.0.2"
resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
@ -398,11 +527,23 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
treemate@^0.3.11:
version "0.3.11"
resolved "https://registry.npmmirror.com/treemate/-/treemate-0.3.11.tgz#7d52f8f69ab9ce326f8d139e0a3d1ffb25e48222"
integrity sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==
tslib@2.3.0:
version "2.3.0"
resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
vdirs@^0.1.4, vdirs@^0.1.8:
version "0.1.8"
resolved "https://registry.npmmirror.com/vdirs/-/vdirs-0.1.8.tgz#a103bc43baca738f8dea912a7e9737154a19dbc2"
integrity sha512-H9V1zGRLQZg9b+GdMk8MXDN2Lva0zx72MPahDKc30v+DtwKjfyOSXWRIX4t2mhDubM1H09gPhWeth/BJWPHGUw==
dependencies:
evtd "^0.2.2"
vite@^2.9.0:
version "2.9.1"
resolved "https://registry.npmmirror.com/vite/-/vite-2.9.1.tgz#84bce95fae210a7beb566a0af06246748066b48f"
@ -415,6 +556,13 @@ vite@^2.9.0:
optionalDependencies:
fsevents "~2.3.2"
vooks@^0.2.12, vooks@^0.2.4:
version "0.2.12"
resolved "https://registry.npmmirror.com/vooks/-/vooks-0.2.12.tgz#2b6e23330b77bac81c7f7a344c4ca3e9f4f6c373"
integrity sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==
dependencies:
evtd "^0.2.2"
vue-cesium@^3.0.11:
version "3.0.11"
resolved "https://registry.npmmirror.com/vue-cesium/-/vue-cesium-3.0.11.tgz#442e45fd85c8bc7e1b095ae66fbeea8f9e141cca"
@ -435,6 +583,19 @@ vue-demi@*:
resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.12.5.tgz#8eeed566a7d86eb090209a11723f887d28aeb2d1"
integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
vue-demi@^0.13.11:
version "0.13.11"
resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
vue-echarts@^6.2.3:
version "6.7.2"
resolved "https://registry.npmmirror.com/vue-echarts/-/vue-echarts-6.7.2.tgz#66f3d9dcd9535f1d39a20f890b870a3e5c6598a8"
integrity sha512-SG8Vmszhx24KjtySsk361DogZLRkPCyLhgoyh7iN1eH3WGJ0kyl3k0g4QiSJqK0+F1Ej0HDopq4A5OGcBlAwzw==
dependencies:
resize-detector "^0.3.0"
vue-demi "^0.13.11"
vue@^3.2.25:
version "3.2.31"
resolved "https://registry.npmmirror.com/vue/-/vue-3.2.31.tgz#e0c49924335e9f188352816788a4cca10f817ce6"
@ -446,6 +607,19 @@ vue@^3.2.25:
"@vue/server-renderer" "3.2.31"
"@vue/shared" "3.2.31"
vueuc@^0.4.58:
version "0.4.58"
resolved "https://registry.npmmirror.com/vueuc/-/vueuc-0.4.58.tgz#03ee2ea6febf360ca9cbe490841fce91742eea12"
integrity sha512-Wnj/N8WbPRSxSt+9ji1jtDHPzda5h2OH/0sFBhvdxDRuyCZbjGg3/cKMaKqEoe+dErTexG2R+i6Q8S/Toq1MYg==
dependencies:
"@css-render/vue3-ssr" "^0.15.10"
"@juggle/resize-observer" "^3.3.1"
css-render "^0.15.10"
evtd "^0.2.4"
seemly "^0.3.6"
vdirs "^0.1.4"
vooks "^0.2.4"
wkt-parser@^1.3.1:
version "1.3.2"
resolved "https://registry.npmmirror.com/wkt-parser/-/wkt-parser-1.3.2.tgz#deeff04a21edc5b170a60da418e9ed1d1ab0e219"