飞行标注-目录树、地图编辑后同步修改后台和展示数据

main
滕嵩 2 months ago
parent 0b6a1c2d69
commit a233865ed1

@ -37,6 +37,7 @@ export function getAppEnvConfig() {
VITE_GLOB_UPLOAD_URL,
VITE_GLOB_APP_LOGO,
VITE_GLOB_INFO_IMAGE_URL,
VITE_MEDIALIBRARY_IMAGE_URL,
VITE_GLOB_APP_MANAGEMENT_UNIT,
VITE_GLOB_APP_TECHINICAL_SUPPORT,
VITE_GLOB_APP_VERSIONS,
@ -56,6 +57,7 @@ export function getAppEnvConfig() {
VITE_GLOB_UPLOAD_URL,
VITE_GLOB_APP_LOGO,
VITE_GLOB_INFO_IMAGE_URL,
VITE_MEDIALIBRARY_IMAGE_URL,
VITE_GLOB_APP_MANAGEMENT_UNIT,
VITE_GLOB_APP_TECHINICAL_SUPPORT,
VITE_GLOB_APP_VERSIONS,

@ -285,10 +285,12 @@
import Path from './path/index.vue';
import { AddFolderModal, MoveFileModal, CompressFileModal, RenameModal } from './modal/modal';
import { PermissionBtn } from '@/components/PermissionBtn/index';
import { getAppEnvConfig } from '@/utils/env';
import { columns, searchFormSchema, svg_showOnMap_0, svg_showOnMap_1 } from './modal.data';
import dayjs from 'dayjs';
import { cloneDeep } from 'lodash-es';
const { VITE_MEDIALIBRARY_IMAGE_URL } = getAppEnvConfig();
const { createConfirm, createMessage } = useMessage();
// --------------------------------------------------------------------
@ -456,8 +458,25 @@
}
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
let uu = VITE_MEDIALIBRARY_IMAGE_URL + url;
// 使
// getImageDimensions(uu, function (dimensions) {
// console.log(': ' + dimensions.width);
// console.log(': ' + dimensions.height);
// });
return uu;
}
function getImageDimensions(url, callback) {
const img = new Image();
img.src = url;
img.onload = function () {
const width = img.width;
const height = img.height;
callback({ width: width, height: height });
};
}
// ----------------------------------------------------------------------
//
function handleSelect(orgId = '') {
@ -784,7 +803,7 @@
padding-left: 16px;
background: #ffffff;
display: flex;
align-items: center;
align-items: flex-start;
justify-content: flex-start;
}
@ -799,7 +818,7 @@
.storeDiv {
position: relative;
width: 150px;
width: 160px;
height: 120px;
outline: 1px solid #000000;
margin: 16px;

@ -37,7 +37,7 @@ export const columns: BasicColumn[] = [
{
title: '操作',
dataIndex: 'action',
align: 'left',
align: 'center',
width: 120,
},
];

@ -62,7 +62,7 @@
}
//
if (imageInfoShow.value) {
width += 720;
width += 1040;
}
return 'calc(100% - ' + width + 'px)';
});
@ -152,23 +152,11 @@
// width: auto;
}
.annotationInfoDiv {
position: relative;
height: 100%;
width: 320px;
}
.areaInfoDiv {
position: relative;
height: 100%;
width: 320px;
}
.imageInfoDiv {
position: relative;
height: 100%;
// width: 37%;
width: 720px;
width: 1040px;
// min-width: 720px;
}
}

@ -126,7 +126,7 @@
transition: 'transform 0.2s',
width: `${imageWidth}px`,
height: `${imageHeight}px`,
background: `url(${getImgurl(props.nowShowImageData.objectKey)}) no-repeat center center`,
background: `url(${VITE_MEDIALIBRARY_IMAGE_URL + props.nowShowImageData.objectKey}) no-repeat center center`,
backgroundSize: 'contain',
backgroundPosition: 'center',
}"
@ -584,15 +584,12 @@
PlusSquareOutlined,
} from '@ant-design/icons-vue';
import dayjs from 'dayjs';
import {
UpdatePicStatus,
Deletepic,
UpdatePicName,
UpdatePicParentKey,
} from '@/api/demo/mediaLibrary';
import { UpdatePicStatus, UpdatePicName } from '@/api/demo/mediaLibrary';
import { getAppEnvConfig } from '@/utils/env';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const { VITE_MEDIALIBRARY_IMAGE_URL } = getAppEnvConfig();
const props = defineProps(['nowShowImageData', 'allImageDataList']);
const emits = defineEmits([
@ -603,11 +600,6 @@
'funUpdateDisplayOrShowOnMapData',
]);
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
}
// --------------------------------
const focusInputRef = ref();
const editNameFlag = ref(true);
@ -719,21 +711,21 @@
}
//
const imageWidth = ref(720);
const imageHeight = ref(553);
const imageWidth = ref(1040);
const imageHeight = ref(800);
//
function getImageWidthAndHeight() {
if (
props.nowShowImageData.width &&
props.nowShowImageData.height &&
props.nowShowImageData.width > 720 &&
props.nowShowImageData.height > 553
props.nowShowImageData.width > 1040 &&
props.nowShowImageData.height > 800
) {
imageWidth.value = 720;
imageHeight.value = (720 / props.nowShowImageData.width) * props.nowShowImageData.height;
imageHeight.value = 800;
imageWidth.value = (800 / props.nowShowImageData.height) * props.nowShowImageData.width;
} else {
imageHeight.value = 553;
imageWidth.value = 720;
imageHeight.value = 800;
imageWidth.value = 1040;
}
}
onMounted(() => {
@ -1035,7 +1027,7 @@
//
const dragDocument: any = document.querySelector('.dragModal');
isDragging.value = false;
dragDocument.style.cursor = 'default';
// dragDocument.style.cursor = 'default';
}
}
//

@ -307,9 +307,9 @@
}
}
UpdatePicStatus({
id: props.nowShowImageData.id,
fileTags: JSON.stringify(props.nowShowImageData.fileTags),
graffitiJson: JSON.stringify(props.nowShowImageData.graffitiJson),
id: show.id,
fileTags: JSON.stringify(show.fileTags),
graffitiJson: JSON.stringify(show.graffitiJson),
display: show.display,
showOnMap: show.showOnMap,
}).then((res) => {

@ -25,6 +25,8 @@
import * as turf from '@turf/turf';
import { WktToGeojson, GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import dayjs from 'dayjs';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_MEDIALIBRARY_IMAGE_URL } = getAppEnvConfig();
const props = defineProps([
'allImageDataList',
@ -411,7 +413,7 @@
const image = new Image();
image.crossOrigin = 'Anonymous';
// image.src = item.preview_url;
// image.src = getImgurl(item.objectKey);
// image.src = VITE_MEDIALIBRARY_IMAGE_URL + item.objectKey;
image.src =
'https://m.tuniucdn.com/fb2/t1/G5/M00/44/52/Cii-s1soezyIF2UxABn76u-yKl8AAIwBgB34jAAGfwC3020871';
image.onload = () => {
@ -608,10 +610,7 @@
}
});
};
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
}
// -
function imageRestoreDefault() {
//

@ -12,7 +12,7 @@
transition: 'transform 0.2s',
width: `${imageWidth}px`,
height: `${imageHeight}px`,
background: `url(${getImgurl(props.nowPreviewRecord.objectKey)}) no-repeat center center`,
background: `url(${VITE_MEDIALIBRARY_IMAGE_URL + props.nowPreviewRecord.objectKey}) no-repeat center center`,
backgroundSize: 'contain',
backgroundPosition: 'center',
}"
@ -263,7 +263,7 @@
</div>
</div>
<div class="bottom">
<div class="bottomDiv">
<div class="buttonList">
<!-- 放大 -->
<div class="button">
@ -399,7 +399,12 @@
v-if="li.objectKey"
:class="li.id == props.nowPreviewRecord.id ? 'bottom_div_choose' : 'bottom_div'"
>
<img :src="getImgurl(li.objectKey)" loading="lazy" :width="60" :height="40" />
<img
:src="VITE_MEDIALIBRARY_IMAGE_URL + li.objectKey"
loading="lazy"
:width="60"
:height="35"
/>
</div>
</div>
</div>
@ -529,7 +534,8 @@
} from '@/api/demo/mediaLibrary';
import { useMessage } from '@/hooks/web/useMessage';
import { cloneDeep } from 'lodash-es';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_MEDIALIBRARY_IMAGE_URL } = getAppEnvConfig();
const { createConfirm, createMessage } = useMessage();
const props = defineProps(['nowPreviewRecord', 'previewRecordList']);
@ -539,11 +545,6 @@
'setHideOrShowTextboxFlag',
]);
//
function getImgurl(url) {
return 'http://175.27.168.120:6014/api/v1/buckets/test/objects/download?prefix=' + url;
}
//
function clickLeftOrRightButton(direction) {
const list = props.previewRecordList.filter((item) => item.objectKey);
@ -680,7 +681,7 @@
//
const copyToClipboard = async (url) => {
try {
await navigator.clipboard.writeText(getImgurl(url));
await navigator.clipboard.writeText(VITE_MEDIALIBRARY_IMAGE_URL + url);
createMessage.success('图片链接已复制到剪贴板');
} catch (err) {
createMessage.error('无法复制图片链接');
@ -713,7 +714,7 @@
//
async function fetchAndDownloadImage(url) {
try {
const response = await fetch(getImgurl(url), {
const response = await fetch(VITE_MEDIALIBRARY_IMAGE_URL + url, {
mode: 'cors',
});
if (!response.ok) {
@ -1096,16 +1097,17 @@
align-items: center;
justify-content: center;
width: 100%;
height: 820px;
height: 89%;
background: #101010;
}
.bottom {
position: absolute;
bottom: 0px;
left: 0px;
.bottomDiv {
// position: absolute;
// bottom: 0px;
// left: 0px;
position: relative;
width: 100%;
height: 100px;
height: 10%;
background: #1c1c1c;
display: flex;
flex-wrap: wrap;

@ -24,6 +24,7 @@
<div class="mapDiv" :style="{ width: dynamicWidth }">
<PathMap
ref="pathMapRef"
:allWorkspaceDataList="allWorkspaceDataList"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
@setNowShowAnnotationData="setNowShowAnnotationData"
@ -47,7 +48,6 @@
import { ref, computed, onMounted } from 'vue';
import { PathLeftMenu, PathMap, PathAnnotationInfo } from './path';
import { cloneDeep } from 'lodash-es';
import imageJson from './json/image.json';
import { GetWorkspaceList, GetAnnotationList, DeleteAnnotation } from '@/api/demo/mediaLibrary';
import { WktToGeojson, GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import { useMessage } from '@/hooks/web/useMessage';
@ -109,6 +109,7 @@
//
getAnnotationList();
}
//
function getAnnotationList(showThis = true) {
GetWorkspaceList().then((result1) => {
@ -175,7 +176,7 @@
return 'Polygon';
}
//
if (geom.indexOf('POLYGON') > -1 && radiusFlag) {
if (geom.indexOf('POINT') > -1 && radiusFlag) {
return 'Circle';
}
}

@ -191,64 +191,17 @@
</a-tooltip>
</div>
</a-col>
<!-- 经纬模式 -->
<a-col :span="6" v-if="[0, 3].includes(nowAnnotationData.type)">
<div class="annotationTitle">经纬模式</div>
</a-col>
<a-col :span="18" v-if="[0, 3].includes(nowAnnotationData.type)">
<div class="annotationContent">
<a-radio-group v-model:value="modalType">
<a-radio :value="0"><span style="color: white">十进制</span></a-radio>
<a-radio :value="1"><span style="color: white">度分秒</span></a-radio>
</a-radio-group>
</div>
</a-col>
<!-- 经度 -->
<a-col :span="6" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationTitle">经度</div>
</a-col>
<a-col :span="18" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationContent">
<!-- 十进制 -->
<a-input v-if="modalType == 0" v-model:value="nowAnnotationData.coordinates[0]">
<a-input v-model:value="nowAnnotationData.coordinates[0]">
<template #addonAfter>
<span style="color: white">°</span>
</template>
</a-input>
<!-- 度分秒 -->
<a-input
v-if="modalType == 1"
v-model:value="decimalToDMS_0.degrees"
style="max-width: 32px"
@change="
decimalToDMS_0.degrees = parseFloat(
decimalToDMS_0.degrees.toString().replace(/[^-0-9]/g, ''),
)
"
/>
<span v-if="modalType == 1" style="margin: 2px; color: white">°</span>
<a-input
v-if="modalType == 1"
v-model:value="decimalToDMS_0.minutes"
style="max-width: 30px"
@change="
decimalToDMS_0.minutes = parseFloat(
decimalToDMS_0.minutes.toString().replace(/[^-0-9]/g, ''),
)
"
/>
<span v-if="modalType == 1" style="margin: 2px; color: white"></span>
<a-input
v-if="modalType == 1"
v-model:value="decimalToDMS_0.seconds"
style="width: 120px"
@change="
decimalToDMS_0.seconds = parseFloat(
decimalToDMS_0.seconds.toString().replace(/[^-0-9]/g, ''),
)
"
/>
<span v-if="modalType == 1" style="margin: 2px; color: white"></span>
</div>
</a-col>
<!-- 纬度 -->
@ -257,46 +210,11 @@
</a-col>
<a-col :span="18" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationContent">
<!-- 十进制 -->
<a-input v-if="modalType == 0" v-model:value="nowAnnotationData.coordinates[1]">
<a-input v-model:value="nowAnnotationData.coordinates[1]">
<template #addonAfter>
<span style="color: white">°</span>
</template>
</a-input>
<!-- 度分秒 -->
<a-input
v-if="modalType == 1"
v-model:value="decimalToDMS_1.degrees"
style="max-width: 32px"
@change="
decimalToDMS_1.degrees = parseFloat(
decimalToDMS_1.degrees.toString().replace(/[^-0-9]/g, ''),
)
"
/>
<span v-if="modalType == 1" style="margin: 2px; color: white">°</span>
<a-input
v-if="modalType == 1"
v-model:value="decimalToDMS_1.minutes"
style="max-width: 30px"
@change="
decimalToDMS_1.minutes = parseFloat(
decimalToDMS_1.minutes.toString().replace(/[^-0-9]/g, ''),
)
"
/>
<span v-if="modalType == 1" style="margin: 2px; color: white"></span>
<a-input
v-if="modalType == 1"
v-model:value="decimalToDMS_1.seconds"
style="width: 120px"
@change="
decimalToDMS_1.seconds = parseFloat(
decimalToDMS_1.seconds.toString().replace(/[^-0-9]/g, ''),
)
"
/>
<span v-if="modalType == 1" style="margin: 2px; color: white"></span>
</div>
</a-col>
<!-- 高度 -->
@ -508,62 +426,6 @@
return returnIcon.replaceAll('currentColor', '#ffffff');
}
//
const modalType = ref<number>(0);
// -
const decimalToDMS_0 = ref({
degrees: 0,
minutes: 0,
seconds: 0,
});
// -
const decimalToDMS_1 = ref({
degrees: 0,
minutes: 0,
seconds: 0,
});
watch(
() => modalType.value,
(newValue) => {
if (newValue == 0) {
// - -
let { degrees, minutes, seconds } = decimalToDMS_0.value;
let decimal = Math.abs(degrees) + minutes / 60 + seconds / 3600;
nowAnnotationData.value.coordinates[0] = decimal;
// - -
degrees = decimalToDMS_1.value.degrees;
minutes = decimalToDMS_1.value.minutes;
seconds = decimalToDMS_1.value.seconds;
decimal = Math.abs(degrees) + minutes / 60 + seconds / 3600;
nowAnnotationData.value.coordinates[1] = decimal;
}
if (newValue == 1) {
// - -
const decimal1 = nowAnnotationData.value.coordinates[0];
const degrees1 = Math.floor(decimal1);
const minutesFull1 = (decimal1 - degrees1) * 60;
const minutes1 = Math.floor(minutesFull1);
const seconds1 = parseFloat((minutesFull1 - minutes1) * 60);
decimalToDMS_0.value = {
degrees: degrees1,
minutes: minutes1,
seconds: seconds1,
};
// - -
const decimal2 = nowAnnotationData.value.coordinates[1];
const degrees2 = Math.floor(decimal2);
const minutesFull2 = (decimal2 - degrees2) * 60;
const minutes2 = Math.floor(minutesFull2);
const seconds2 = parseFloat((minutesFull2 - minutes2) * 60);
decimalToDMS_1.value = {
degrees: degrees2,
minutes: minutes2,
seconds: seconds2,
};
}
},
);
//
function closePathAnnotationInfo() {
emits('closePathAnnotationInfo');
@ -571,8 +433,8 @@
//
function handlerLocation() {
emits('handlerLocation', {
lng: props.nowShowAnnotationData.properties.centerPoint[0],
lat: props.nowShowAnnotationData.properties.centerPoint[1],
lng: parseFloat(props.nowShowAnnotationData.coordinates[0]),
lat: parseFloat(props.nowShowAnnotationData.coordinates[1]),
});
}
//
@ -603,47 +465,56 @@
() => props.nowShowAnnotationData,
() => {
nowAnnotationData.value = props.nowShowAnnotationData;
// 线
if (nowAnnotationData.value.type == 1) {
// 线
linearDistance.value = mars3d.MeasureUtil.getDistance(
nowAnnotationData.value.coordinates,
).toFixed(2);
//
horizontalDistance.value = mars3d.MeasureUtil.getSurfaceDistance(
nowAnnotationData.value.coordinates,
).toFixed(2);
//
let heightlist: any = [];
nowAnnotationData.value.coordinates.forEach((item) => {
heightlist.push(item[2]);
});
heightDiff.value = (Math.max(...heightlist) - Math.min(...heightlist)).toFixed(2);
}
//
if (nowAnnotationData.value.type == 2) {
//
horizontalArea.value = mars3d.MeasureUtil.getSurfaceArea(
nowAnnotationData.value.coordinates[0],
).toFixed(2);
//
horizontalPerimeter.value = mars3d.MeasureUtil.getSurfaceDistance(
nowAnnotationData.value.coordinates[0],
).toFixed(2);
//
let heightlist: any = [];
nowAnnotationData.value.coordinates[0].forEach((item) => {
heightlist.push(item[2]);
});
heightDiff.value = (Math.max(...heightlist) - Math.min(...heightlist)).toFixed(2);
}
restoreAreaAndDistance();
},
{
deep: true,
immediate: true,
},
);
onMounted(() => {});
function restoreAreaAndDistance() {
// 线
if (nowAnnotationData.value.type == 1) {
// 线
linearDistance.value = mars3d.MeasureUtil.getDistance(
nowAnnotationData.value.coordinates,
).toFixed(2);
//
horizontalDistance.value = mars3d.MeasureUtil.getSurfaceDistance(
nowAnnotationData.value.coordinates,
).toFixed(2);
//
let heightlist: any = [];
nowAnnotationData.value.coordinates.forEach((item) => {
heightlist.push(item[2]);
});
heightDiff.value = (Math.max(...heightlist) - Math.min(...heightlist)).toFixed(2);
}
//
if (nowAnnotationData.value.type == 2) {
//
horizontalArea.value = mars3d.MeasureUtil.getSurfaceArea(
nowAnnotationData.value.coordinates[0],
).toFixed(2);
//
horizontalPerimeter.value = mars3d.MeasureUtil.getSurfaceDistance(
nowAnnotationData.value.coordinates[0],
).toFixed(2);
//
let heightlist: any = [];
nowAnnotationData.value.coordinates[0].forEach((item) => {
heightlist.push(item[2]);
});
heightDiff.value = (Math.max(...heightlist) - Math.min(...heightlist)).toFixed(2);
console.log(horizontalArea.value);
console.log(horizontalPerimeter.value);
console.log(heightDiff.value);
}
}
defineExpose({
restoreAreaAndDistance,
});
</script>
<style lang="less" scoped>
.annotationInfo {

@ -5,74 +5,81 @@
<div class="leftMenuContent_title">
{{ showMenuInfoName }}
</div>
<div class="leftMenuContent_list">
<!-- 列表 -->
<div v-for="show in showMenuInfoList" :key="show.id">
<!-- 地图标注 -->
<div
v-if="showMenuInfoName == '地图标注'"
class="showMenuInfo_annotation"
:style="{
background:
props.nowShowAnnotationData && props.nowShowAnnotationData.id == show.id
? '#274D75'
: show.mouse
? '#393939'
: '',
}"
@mouseenter="
show.mouse = true;
show.deleteClickNum = 0;
"
@mouseleave="
show.mouse = false;
show.deleteClickNum = 0;
"
>
<div @click="setNowShowAnnotationData(show)">
<AntDesignOutlined v-if="show.type == 0" />
<ExpandAltOutlined v-if="show.type == 1" />
<BorderOutlined v-if="show.type == 2" />
<LogoutOutlined v-if="show.type == 3" />
</div>
<a-input-search
v-model:value="searchValue"
placeholder="按标注名称搜索"
style="width: 90%; margin: 10px"
@search="handleChangeAnnotationSearch"
allowClear
size="small"
/>
<div class="leftMenuContent_tree">
<a-tree :expanded-keys="expandedKeys" :tree-data="treeData" defaultExpandAll>
<template #title="{ dataRef }">
<div
class="eye"
@click="show.state == 0 ? hideThisAnnotation(show) : showThisAnnotation(show)"
:style="{ background: show.state == 0 ? '#2d8cf0' : '#000000' }"
class="showMenuInfo_annotation"
@mouseenter="
dataRef.mouse = true;
dataRef.deleteClickNum = 0;
"
@mouseleave="
dataRef.mouse = false;
dataRef.deleteClickNum = 0;
"
>
<EyeOutlined v-if="show.state == 0" style="color: #ffffff; font-size: 16px" />
<EyeInvisibleOutlined
v-if="show.state == 1"
style="color: #ffffff; font-size: 16px"
/>
</div>
<div @click="setNowShowAnnotationData(show)">{{ show.name }}</div>
<div class="buttonRight2" v-if="show.mouse">
<a-tooltip placement="top">
<template #title>
<span>回中</span>
</template>
<AimOutlined @click="handlerLocation(show)" />
</a-tooltip>
</div>
<div
class="buttonRight1"
v-if="show.mouse"
:style="{ background: show.deleteClickNum == 1 ? '#FF0000' : '' }"
>
<a-tooltip placement="top">
<template #title>
<span>删除</span>
</template>
<DeleteOutlined
@click="
show.deleteClickNum == 1 ? deleteAnnotation(show) : show.deleteClickNum++
"
<AntDesignOutlined v-if="dataRef.type == 0" />
<ExpandAltOutlined v-if="dataRef.type == 1" />
<BorderOutlined v-if="dataRef.type == 2" />
<LogoutOutlined v-if="dataRef.type == 3" />
<div
class="eye"
v-if="!dataRef.children"
@click="
dataRef.state == 0 ? hideThisAnnotation(dataRef) : showThisAnnotation(dataRef)
"
:style="{ background: dataRef.state == 0 ? '#2d8cf0' : '#000000' }"
>
<EyeOutlined v-if="dataRef.state == 0" style="color: #ffffff; font-size: 16px" />
<EyeInvisibleOutlined
v-if="dataRef.state == 1"
style="color: #ffffff; font-size: 16px"
/>
</a-tooltip>
</div>
<div
:class="dataRef.mouse ? 'title_mouse' : 'title_nomouse'"
@click="setNowShowAnnotationData(dataRef)"
>
{{ dataRef.title }}
</div>
<div class="buttonRight2" v-if="!dataRef.children && dataRef.mouse">
<a-tooltip placement="top">
<template #title>
<span>回中</span>
</template>
<AimOutlined @click="handlerLocation(dataRef)" />
</a-tooltip>
</div>
<div
class="buttonRight1"
v-if="!dataRef.children && dataRef.mouse"
:style="{ background: dataRef.deleteClickNum == 1 ? '#FF0000' : '' }"
>
<a-tooltip placement="top">
<template #title>
<span>{{ dataRef.deleteClickNum == 0 ? '删除' : '再次点击删除' }}</span>
</template>
<DeleteOutlined
@click="
dataRef.deleteClickNum == 1
? deleteAnnotation(dataRef)
: dataRef.deleteClickNum++
"
/>
</a-tooltip>
</div>
</div>
</div>
</div>
</template>
</a-tree>
</div>
</div>
</div>
@ -99,12 +106,13 @@
} from '@ant-design/icons-vue';
import { UpdateWorkArea, UpdateAnnotation } from '@/api/demo/mediaLibrary';
import { cloneDeep } from 'lodash-es';
import dayjs from 'dayjs';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const props = defineProps([
'leftMenuShow',
'allWorkspaceList',
'allWorkspaceDataList',
'allAnnotationDataList',
'nowShowAnnotationData',
]);
@ -115,8 +123,8 @@
'setAllAnnotationData',
'deleteAnnotation',
]);
const showMenuInfoList = ref(props.allAnnotationDataList);
const showMenuInfoName = ref('地图标注');
function updateShowMenuInfoList(type) {
if (type == '地图标注') {
handleChangeAnnotationSearch();
@ -128,28 +136,47 @@
emits('changeLeftMenuShow');
}
// -
function funAddOrRemoveToMap(show) {
show.show_on_map = !show.show_on_map;
if (show.show_on_map) {
createMessage.success('在地图上加载成功');
} else {
createMessage.success('在地图上取消加载成功');
}
}
// -
const filterAfterAnnotationDataList = ref(props.allAnnotationDataList);
const treeData: any = ref([]);
const expandedKeys: any = ref([]);
const searchValue = ref('');
function handleChangeAnnotationSearch() {
let filterAnnotationData = props.allAnnotationDataList;
// if (areatype.value !== 'all') {
// filterAnnotationData = filterAnnotationData.filter((item) => item.type == areatype.value);
// }
// if (areastate.value !== 'all') {
// filterAnnotationData = filterAnnotationData.filter((item) => item.state == areastate.value);
// }
filterAfterAnnotationDataList.value = filterAnnotationData;
showMenuInfoList.value = filterAfterAnnotationDataList.value;
treeData.value = [];
//
let allWorkspaceDataList = props.allWorkspaceDataList.sort((a, b) => {
return dayjs(a.CreateTime) - dayjs(b.CreateTime);
});
allWorkspaceDataList.forEach((item) => {
treeData.value.push({
key: item.Id,
title: item.WorkspaceName,
children: [],
});
});
//
expandedKeys.value = allWorkspaceDataList.map((item) => item.Id);
//
let allAnnotationDataList = props.allAnnotationDataList.sort((a, b) => {
return dayjs(a.createTime) - dayjs(b.createTime);
});
allAnnotationDataList.forEach((annotation) => {
treeData.value.forEach((tree) => {
if (tree.key == annotation.workSpaceId) {
tree.children.push({
...annotation,
key: annotation.id,
title: annotation.name,
});
}
});
});
//
if (searchValue.value) {
treeData.value.forEach((tree) => {
tree.children = tree.children.filter((item) => item.title.includes(searchValue.value));
});
}
}
// -
function deleteAnnotation(show) {
@ -195,13 +222,13 @@
if (showMenuInfoName.value == '地图标注') {
if (position.geomtype == 'Circle') {
emits('handlerLocation', {
lng: position.properties.centerPoint[0],
lat: position.properties.centerPoint[1],
lng: parseFloat(position.coordinates[0]),
lat: parseFloat(position.coordinates[1]),
});
} else {
emits('handlerLocation', {
lng: position.properties.centerPoint[0],
lat: position.properties.centerPoint[1],
lng: parseFloat(position.coordinates[0]),
lat: parseFloat(position.coordinates[1]),
});
}
}
@ -246,69 +273,6 @@
height: calc(100%-50px);
// height: 800px;
.leftMenuContent_1 {
position: relative;
width: 64px;
height: 100%;
border-right: 1px solid #ffffff55;
// padding-top: 10px;
// padding-bottom: 10px;
.leftMenu_closeButton {
position: relative;
padding-top: 7px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
}
.leftMenu_buttonList {
position: relative;
width: 50px;
height: 100%;
border-radius: 10px;
background: #1a375a;
margin-top: 15px;
margin-left: 7px;
margin-right: 7px;
padding-top: 5px;
padding-bottom: 5px;
gap: 10px;
.leftMenu_buttonList_annotation {
position: relative;
border-radius: 5px;
height: 40px;
width: 40px;
margin: 5px;
display: flex;
align-items: center;
justify-content: center;
}
.leftMenu_buttonList_image {
position: relative;
border-radius: 5px;
height: 40px;
width: 40px;
margin: 5px;
display: flex;
align-items: center;
justify-content: center;
}
.leftMenu_buttonList_area {
position: relative;
border-radius: 5px;
height: 40px;
width: 40px;
margin: 5px;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.leftMenuContent_2 {
position: relative;
width: 275px;
@ -321,131 +285,64 @@
font-size: 16px;
}
.leftMenuContent_list {
.leftMenuContent_tree {
overflow-y: auto;
max-height: 800px;
//
.showMenuInfo_annotation {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
color: #ffffff;
height: 30px;
padding-left: 15px;
gap: 10px;
.eye {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
}
.buttonRight2 {
position: absolute;
right: 30px;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.buttonRight1 {
position: absolute;
right: 5px;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
}
//
.showMenuInfo_image {
display: flex;
align-items: center;
justify-content: flex-start;
color: #ffffff;
height: 30px;
padding-left: 15px;
gap: 10px;
.eye {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
}
.buttonRight2 {
position: absolute;
right: 35px;
}
.buttonRight1 {
position: absolute;
right: 10px;
}
}
//
.showMenuInfo_area {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
height: 70px;
margin: 10px 15px;
.name {
position: absolute;
top: 6px;
left: 6px;
color: #ffffff;
font-size: 15px;
width: 90%;
height: 30px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.type {
position: absolute;
display: inline-flex;
align-items: center;
justify-content: flex-start;
bottom: 6px;
left: 8px;
color: #ffffff;
font-size: 15px;
width: 165px;
}
.buttonlist {
position: absolute;
bottom: 6px;
right: 6px;
width: 75px;
height: 25px;
display: flex;
gap: 1px;
.button {
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-size: 16px;
width: 25px;
height: 25px;
}
}
}
max-height: 750px;
}
}
}
}
//
.showMenuInfo_annotation {
position: relative;
display: inline-flex;
align-items: center;
justify-content: flex-start;
color: #ffffff;
height: 30px;
width: 100%;
gap: 5px;
.eye {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
}
.title_mouse {
width: 135px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.title_nomouse {
width: 170px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.buttonRight2 {
position: absolute;
right: -15px;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.buttonRight1 {
position: absolute;
right: -35px;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
}
.suojinButton {
position: absolute;
top: 45%;
@ -459,4 +356,20 @@
justify-content: center;
border-radius: 5px;
}
::v-deep .ant-tree-list {
background: #232323 !important;
}
::v-deep .ant-tree {
color: #ffffff !important;
}
::v-deep .ant-tree-switcher {
color: #ffffff !important;
}
::v-deep .ant-tree-node-selected {
background: #25384c !important;
}
//
</style>

@ -5,7 +5,7 @@
<div class="annotationButtons">
<div
:class="mapDrawType == 'drawPoint' ? 'button_choose' : 'button_nochoose'"
@click="drawPoint"
@click="fun_chooseWorkSpaceType('drawPoint')"
>
<a-popover placement="left">
<template #content>
@ -31,7 +31,7 @@
</div>
<div
:class="mapDrawType == 'drawPolyline' ? 'button_choose' : 'button_nochoose'"
@click="drawPolyline"
@click="fun_chooseWorkSpaceType('drawPolyline')"
>
<a-popover placement="left">
<template #content>
@ -57,7 +57,7 @@
</div>
<div
:class="mapDrawType == 'drawPolygon' ? 'button_choose' : 'button_nochoose'"
@click="drawPolygon"
@click="fun_chooseWorkSpaceType('drawPolygon')"
>
<a-popover placement="left">
<template #content>
@ -83,7 +83,7 @@
</div>
<div
:class="mapDrawType == 'drawCricle' ? 'button_choose' : 'button_nochoose'"
@click="drawCricle"
@click="fun_chooseWorkSpaceType('drawCricle')"
>
<a-popover placement="left">
<template #content>
@ -108,6 +108,36 @@
</a-popover>
</div>
</div>
<!-- 标签弹窗 -->
<a-modal
title="选择项目"
:open="chooseWorkSpaceOpen"
:mask="false"
:maskClosable="false"
:closable="false"
@ok="fun_workSpaceOk"
@cancel="fun_workSpaceCancel"
>
<div style="margin: 10px 30px">
<a-radio-group v-model:value="chooseWorkSpaceId">
<a-radio
v-for="workspace in props.allWorkspaceDataList"
style="
display: flex;
align-items: center;
justify-content: flex-start;
height: 30px;
lineheight: 30px;
"
:key="workspace.Id"
:value="workspace.Id"
>
{{ workspace.WorkspaceName }}
</a-radio>
</a-radio-group>
</div>
</a-modal>
<!-- </div> -->
<!-- </div> -->
</div>
@ -135,10 +165,16 @@
closeIcon,
} from './svg';
import * as turf from '@turf/turf';
import { GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import { WktToGeojson, GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import dayjs from 'dayjs';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const props = defineProps(['allAnnotationDataList', 'nowShowAnnotationData']);
const props = defineProps([
'allAnnotationDataList',
'allWorkspaceDataList',
'nowShowAnnotationData',
]);
const emits = defineEmits(['setNowShowAnnotationData', 'setAllAnnotationData']);
const vChartRef: any = ref<HTMLElement>();
@ -478,7 +514,6 @@
parseFloat(props.nowShowAnnotationData.coordinates[2]),
];
graphicLayer.setStyle({
//
image: dataURL2,
iconname: props.nowShowAnnotationData.properties.iconname,
label: {
@ -690,6 +725,24 @@
});
emits('setNowShowAnnotationData', item);
});
//
pointGraphic.on(mars3d.EventType.editMovePoint, (event) => {
let point = event.target.point;
let coordinates = [point.lng, point.lat, point.alt];
let geom = GeojsonToWkt(turf.point(coordinates).geometry);
let properties = {
...item.properties,
centerPoint: coordinates,
};
let params = {
...item,
properties: JSON.stringify(properties),
geom: geom,
};
UpdateAnnotation(params).then((result) => {
emits('setAllAnnotationData');
});
});
//
graphicLayers.addGraphic(pointGraphic);
//
@ -752,6 +805,66 @@
});
emits('setNowShowAnnotationData', item);
});
//
lineGraphic.on(mars3d.EventType.editMovePoint, (event) => {
let positions = event.target._positions_draw;
let coordinates = positions.map((position) => {
const cartographic = Cesium.Cartographic.fromCartesian(position);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
return [lng, lat, height];
});
let geom = GeojsonToWkt(turf.lineString(coordinates).geometry);
let properties = {
...item.properties,
centerPoint: coordinates[0],
};
let params = {
...item,
properties: JSON.stringify(properties),
geom: geom,
};
UpdateAnnotation(params).then((result) => {
emits('setAllAnnotationData');
emits('setNowShowAnnotationData', {
...item,
properties: properties,
geom: geom,
coordinates: coordinates,
});
});
});
//
lineGraphic.on(mars3d.EventType.editRemovePoint, (event) => {
let positions = event.target._positions_draw;
let coordinates = positions.map((position) => {
const cartographic = Cesium.Cartographic.fromCartesian(position);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
return [lng, lat, height];
});
let geom = GeojsonToWkt(turf.lineString(coordinates).geometry);
let properties = {
...item.properties,
centerPoint: coordinates[0],
};
let params = {
...item,
properties: JSON.stringify(properties),
geom: geom,
};
UpdateAnnotation(params).then((result) => {
emits('setAllAnnotationData');
emits('setNowShowAnnotationData', {
...item,
properties: properties,
geom: geom,
coordinates: coordinates,
});
});
});
// 线
graphicLayers.addGraphic(lineGraphic);
//
@ -817,6 +930,70 @@
});
emits('setNowShowAnnotationData', item);
});
//
polygonGraphic.on(mars3d.EventType.editMovePoint, (event) => {
let positions = event.target._positions_draw;
let coordinates = positions.map((position) => {
const cartographic = Cesium.Cartographic.fromCartesian(position);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
return [lng, lat, height];
});
let polygonData: any = [];
polygonData.push(coordinates);
let geom = GeojsonToWkt(turf.polygon(polygonData).geometry);
let properties = {
...item.properties,
centerPoint: coordinates[0],
};
let params = {
...item,
properties: JSON.stringify(properties),
geom: geom,
};
UpdateAnnotation(params).then((result) => {
emits('setAllAnnotationData');
emits('setNowShowAnnotationData', {
...item,
properties: properties,
geom: geom,
coordinates: polygonData,
});
});
});
//
polygonGraphic.on(mars3d.EventType.editRemovePoint, (event) => {
let positions = event.target._positions_draw;
let coordinates = positions.map((position) => {
const cartographic = Cesium.Cartographic.fromCartesian(position);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
return [lng, lat, height];
});
let polygonData: any = [];
polygonData.push(coordinates);
let geom = GeojsonToWkt(turf.polygon(polygonData).geometry);
let properties = {
...item.properties,
centerPoint: coordinates[0],
};
let params = {
...item,
properties: JSON.stringify(properties),
geom: geom,
};
UpdateAnnotation(params).then((result) => {
emits('setAllAnnotationData');
emits('setNowShowAnnotationData', {
...item,
properties: properties,
geom: geom,
coordinates: polygonData,
});
});
});
//
graphicLayers.addGraphic(polygonGraphic);
//
@ -880,6 +1057,30 @@
});
emits('setNowShowAnnotationData', item);
});
//
circleGraphic.on(mars3d.EventType.editMovePoint, (event) => {
let coordinates = event.graphic.options.position;
let radius = event.graphic.options.style.radius;
let geom = GeojsonToWkt(turf.point(coordinates).geometry);
let properties = {
...item.properties,
centerPoint: coordinates,
radius: radius,
};
let params = {
...item,
properties: JSON.stringify(properties),
geom: geom,
};
UpdateAnnotation(params).then((result) => {
emits('setAllAnnotationData');
emits('setNowShowAnnotationData', {
...item,
properties: properties,
geom: geom,
});
});
});
//
graphicLayers.addGraphic(circleGraphic);
//
@ -938,13 +1139,50 @@
const drawColorPolygon = ref('#2D8CF0');
const drawColorCricle = ref('#2D8CF0');
// --
async function drawPoint() {
if (mapDrawType.value == 'drawPoint') {
mapDrawType.value = '';
//
const chooseWorkSpaceOpen = ref(false);
const chooseWorkSpaceId = ref('');
//
function fun_chooseWorkSpaceType(type) {
chooseWorkSpaceOpen.value = true;
mapDrawType.value = type;
}
// -
function fun_workSpaceOk() {
if (chooseWorkSpaceId.value == '') {
createMessage.warning('先选择要标注的项目!');
return;
}
mapDrawType.value = 'drawPoint';
chooseWorkSpaceOpen.value = false;
switch (mapDrawType.value) {
// --
case 'drawPoint':
drawPoint();
break;
// --线
case 'drawPolyline':
drawPolyline();
break;
// --
case 'drawPolygon':
drawPolygon();
break;
// --
case 'drawCricle':
drawCricle();
break;
}
}
//
function fun_workSpaceCancel() {
chooseWorkSpaceOpen.value = false;
mapDrawType.value = '';
chooseWorkSpaceId.value == '';
}
// --
async function drawPoint() {
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const image = new Image();
image.crossOrigin = 'Anonymous';
@ -987,11 +1225,6 @@
}
// --线
async function drawPolyline() {
if (mapDrawType.value == 'drawPolyline') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawPolyline';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const graphic = await graphicLayers.startDraw({
type: 'polyline',
@ -1018,11 +1251,6 @@
}
// --
async function drawPolygon() {
if (mapDrawType.value == 'drawPolygon') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawPolygon';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const graphic = await graphicLayers.startDraw({
type: 'polygon',
@ -1047,11 +1275,6 @@
}
// --
async function drawCricle() {
if (mapDrawType.value == 'drawCricle') {
mapDrawType.value = '';
return;
}
mapDrawType.value = 'drawCricle';
let time = dayjs().format('YYYY-MM-DD HH:mm:ss');
const graphic = await graphicLayers.startDraw({
type: 'circle',
@ -1091,8 +1314,7 @@
geom = GeojsonToWkt(turf.point(coordinates).geometry);
properties = {
iconname: addOrUpdate == 'add' ? 'defaultIcon' : graphicJson.style.iconname,
font_size: 16,
iconnum: 0,
font_size: addOrUpdate == 'add' ? 16 : graphicJson.style.label.font_size,
clampToGround: false,
color: addOrUpdate == 'add' ? drawColorPoint.value : graphicJson.style.label.color,
centerPoint: coordinates,
@ -1102,10 +1324,10 @@
type = 1;
geom = GeojsonToWkt(turf.lineString(coordinates).geometry);
properties = {
font_size: 16,
font_size: addOrUpdate == 'add' ? 16 : graphicJson.style.label.font_size,
line_width: 5,
clampToGround: false,
color: drawColorPolyline.value,
color: addOrUpdate == 'add' ? drawColorPolyline.value : graphicJson.style.label.color,
centerPoint: coordinates[0],
line_start_cap: 0,
line_end_cap: 0,
@ -1113,27 +1335,27 @@
break;
case 'polygon':
type = 2;
coordinates.push(coordinates[0]);
if (addOrUpdate == 'add') {
coordinates.push(coordinates[0]);
polygonData.push(coordinates);
} else {
polygonData = coordinates;
polygonData.push(coordinates);
}
geom = GeojsonToWkt(turf.polygon(polygonData).geometry);
properties = {
font_size: 16,
font_size: addOrUpdate == 'add' ? 16 : graphicJson.style.label.font_size,
clampToGround: false,
color: drawColorPolygon.value,
color: addOrUpdate == 'add' ? drawColorPolygon.value : graphicJson.style.label.color,
centerPoint: coordinates[0],
};
break;
case 'circle':
type = 3;
geom = GeojsonToWkt(turf.circle(coordinates, graphicJson.style.radius).geometry);
geom = GeojsonToWkt(turf.point(coordinates).geometry);
properties = {
font_size: 16,
font_size: addOrUpdate == 'add' ? 16 : graphicJson.style.label.font_size,
clampToGround: true,
color: drawColorCricle.value,
color: addOrUpdate == 'add' ? drawColorCricle.value : graphicJson.style.label.color,
radius: graphicJson.style.radius,
centerPoint: coordinates,
};
@ -1146,29 +1368,26 @@
properties: JSON.stringify(properties),
createTime: time,
createUser: '',
createUserName: '',
geom: geom,
workSpaceId: '1',
workSpaceId: chooseWorkSpaceId.value,
state: 0,
createUserName: '',
};
AddAnnotation(params).then((result) => {
//
emits('setAllAnnotationData');
mapDrawType.value = '';
chooseWorkSpaceId.value = '';
});
} else {
params = {
id: graphicJson.id,
name: graphicJson.style.label.text,
type: type,
...props.nowShowAnnotationData,
properties: JSON.stringify(properties),
geom: geom,
workSpaceId: '1',
state: props.nowShowAnnotationData.state,
};
UpdateAnnotation(params).then((result) => {
//
// emits('setAllAreaData');
// emits('setAllAnnotationData');
// mapAreaDrawFlag.value = false;
});
}

1
types/config.d.ts vendored

@ -164,6 +164,7 @@ export interface GlobEnvConfig {
VITE_GLOB_APP_LOGO?: string;
// info image video
VITE_GLOB_INFO_IMAGE_URL?: string;
VITE_MEDIALIBRARY_IMAGE_URL?: string;
VITE_GLOB_APP_MANAGEMENT_UNIT?: string;
VITE_GLOB_APP_TECHINICAL_SUPPORT?: string;
VITE_GLOB_APP_VERSIONS?: string;

Loading…
Cancel
Save