刘妍 2 months ago
commit e630e2302f

@ -160,7 +160,8 @@
"vxe-table-plugin-export-xlsx": "^3.1.0",
"xe-utils": "^3.5.14",
"xlsx": "^0.18.5",
"xml-js": "^1.6.11"
"xml-js": "^1.6.11",
"vue3-cron-plus":"^0.1.9"
},
"devDependencies": {
"@commitlint/cli": "^18.4.4",

@ -1,5 +1,14 @@
import { defHttp } from '@/utils/http/axios';
enum Api {
// 获取地图标注列表
GetAnnotationList = '/api/Manage/GetAnnotationList',
// 添加地图标注
AddAnnotation = '/api/Manage/AddAnnotation',
// 更新地图标注
UpdateAnnotation = '/api/Manage/UpdateAnnotation',
// 删除地图标注
DeleteAnnotation = '/api/Manage/DeleteAnnotation',
// 获取地图作业区域列表
GetWorkAreaList = '/api/Manage/GetWorkAreaList',
// 添加地图作业区域
@ -10,6 +19,35 @@ enum Api {
DeleteWorkArea = '/api/Manage/DeleteWorkArea',
}
// 获取地图标注列表
export function GetAnnotationList(params) {
return defHttp.get({
url: Api.GetAnnotationList,
params
});
}
// 添加地图标注
export function AddAnnotation(params) {
return defHttp.post({
url: Api.AddAnnotation,
data:params
});
}
// 更新地图标注
export function UpdateAnnotation(params) {
return defHttp.post({
url: Api.UpdateAnnotation,
data:params
});
}
// 删除地图标注
export function DeleteAnnotation(params) {
return defHttp.post({
url: Api.DeleteAnnotation + '?id=' + params.id,
data:params
});
}
// 获取地图作业区域列表
export function GetWorkAreaList(params) {
return defHttp.get({
@ -26,15 +64,15 @@ export function AddWorkArea(params) {
}
// 更新地图作业区域
export function UpdateWorkArea(params) {
return defHttp.post({
url: Api.UpdateWorkArea,
data:params
});
return defHttp.post({
url: Api.UpdateWorkArea,
data:params
});
}
// 删除地图作业区域
export function DeleteWorkArea(params) {
return defHttp.post({
url: Api.DeleteWorkArea + '?id=' + params.id,
data:params
});
}
return defHttp.post({
url: Api.DeleteWorkArea + '?id=' + params.id,
data:params
});
}

@ -11,8 +11,8 @@
ref="pathLeftMenuRef"
:pathRecord="props.pathRecord"
:leftMenuShow="leftMenuShow"
:allMarkDataList="allMarkDataList"
:nowShowMarkData="nowShowMarkData"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
:allImageDataList="allImageDataList"
@ -20,12 +20,13 @@
@changeLeftMenuShow="changeLeftMenuShow"
@handlerLocation="handlerLocation"
@closePathModal="closePathModal"
@changeMarkInfoShow="changeMarkInfoShow"
@setNowShowMarkData="setNowShowMarkData"
@changeAnnotationInfoShow="changeAnnotationInfoShow"
@setNowShowAnnotationData="setNowShowAnnotationData"
@setNowShowImageData="setNowShowImageData"
@setNowShowAreaData="setNowShowAreaData"
@setAllAnnotationData="setAllAnnotationData"
@setAllAreaData="setAllAreaData"
@deleteMark="deleteMark"
@deleteAnnotation="deleteAnnotation"
@deleteArea="deleteArea"
/>
</div>
@ -33,30 +34,30 @@
<div class="mapDiv" :style="{ width: dynamicWidth }">
<PathMap
ref="pathMapRef"
:allMarkDataList="allMarkDataList"
:nowShowMarkData="nowShowMarkData"
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
:allAreaDataList="allAreaDataList"
:nowShowAreaData="nowShowAreaData"
:allImageDataList="allImageDataList"
:nowShowImageData="nowShowImageData"
@setNowShowMarkData="setNowShowMarkData"
@setNowShowAnnotationData="setNowShowAnnotationData"
@setNowShowImageData="setNowShowImageData"
@setNowShowAreaData="setNowShowAreaData"
@setAllMarkData="setAllMarkData"
@setAllAnnotationData="setAllAnnotationData"
@setAllImageData="setAllImageData"
@setAllAreaData="setAllAreaData"
@closePathImageInfo="closePathImageInfo"
/>
</div>
<!-- 地图标注 -->
<div class="markInfoDiv" v-if="markInfoShow">
<PathMarkInfo
:allMarkDataList="allMarkDataList"
:nowShowMarkData="nowShowMarkData"
@setNowShowMarkData="setNowShowMarkData"
@closePathMarkInfo="closePathMarkInfo"
<div class="annotationInfoDiv" v-if="annotationInfoShow">
<PathAnnotationInfo
:allAnnotationDataList="allAnnotationDataList"
:nowShowAnnotationData="nowShowAnnotationData"
@setNowShowAnnotationData="setNowShowAnnotationData"
@closePathAnnotationInfo="closePathAnnotationInfo"
@handlerLocation="handlerLocation"
@deleteMark="deleteMark"
@deleteAnnotation="deleteAnnotation"
/>
</div>
<!-- 地图作业区域 -->
@ -84,15 +85,13 @@
</template>
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue';
import { PathLeftMenu, PathMap, PathMarkInfo, PathAreaInfo, PathImageInfo } from './path';
import { PathLeftMenu, PathMap, PathAnnotationInfo, PathAreaInfo, PathImageInfo } from './path';
import { cloneDeep } from 'lodash-es';
import markJson from './json/mark.json';
import areaJson from './json/area.json';
import imageJson from './json/image.json';
import {
GetAnnotationList,
DeleteAnnotation,
GetWorkAreaList,
AddWorkArea,
UpdateWorkArea,
DeleteWorkArea,
} from '@/api/demo/mediaLibrary';
import { WktToGeojson, GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
@ -111,7 +110,7 @@
width += 64;
}
//
if (markInfoShow.value) {
if (annotationInfoShow.value) {
width += 320;
}
//
@ -136,36 +135,73 @@
}
// ----------------------------------------------------
const markInfoShow = ref(false);
function changeMarkInfoShow() {
markInfoShow.value = !markInfoShow.value;
const annotationInfoShow = ref(false);
function changeAnnotationInfoShow() {
annotationInfoShow.value = !annotationInfoShow.value;
}
//
function closePathMarkInfo() {
markInfoShow.value = false;
nowShowMarkData.value = {};
function closePathAnnotationInfo() {
annotationInfoShow.value = false;
nowShowAnnotationData.value = {};
pathMapRef.value.annotationRestoreDefault();
}
//
const nowShowMarkData = ref();
const allMarkDataList = ref(markJson);
const nowShowAnnotationData = ref();
const allAnnotationDataList: any = ref([]);
//
function setNowShowMarkData(value) {
function setNowShowAnnotationData(value, restore = true) {
if (value.id) {
markInfoShow.value = true;
annotationInfoShow.value = true;
} else {
markInfoShow.value = false;
annotationInfoShow.value = false;
}
if (restore) {
pathMapRef.value.annotationRestoreDefault();
}
nowShowAnnotationData.value = value;
}
//
function setAllAnnotationData() {
//
getAnnotationList();
}
//
async function getAnnotationList(showThis = true) {
allAnnotationDataList.value = await GetAnnotationList({ workspaceid: 1 });
if (allAnnotationDataList.value.length > 0) {
allAnnotationDataList.value.forEach((annotation, index) => {
let geomjson = WktToGeojson(annotation.geom);
annotation = {
...annotation,
properties: JSON.parse(annotation.properties),
geomtype: getGeomType(annotation),
coordinates: geomjson.coordinates,
};
allAnnotationDataList.value[index] = annotation;
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图标注');
}, 50);
}
nowShowMarkData.value = value;
}
//
function deleteMark(value) {
allMarkDataList.value = cloneDeep(allMarkDataList.value).filter((item) => item.id != value.id);
markInfoShow.value = false;
nowShowMarkData.value = {};
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图标注');
}, 50);
createMessage.success('标注删除成功');
function deleteAnnotation(value) {
if (nowShowAnnotationData.value && nowShowAnnotationData.value.id == value.id) {
annotationInfoShow.value = false;
nowShowAnnotationData.value = {};
}
DeleteAnnotation({
id: value.id,
}).then((result) => {
if (result) {
//
getAnnotationList();
createMessage.success('删除成功');
}
});
}
// ----------------------------------------------------
@ -181,8 +217,7 @@
}
//
const nowShowAreaData = ref();
const allAreaDataList: any = ref(areaJson);
const allAreaDataList: any = ref([]);
//
function setNowShowAreaData(value, restore = true) {
if (value.id) {
@ -200,16 +235,41 @@
//
getWorkAreaList();
}
//
async function getWorkAreaList(showThis = true) {
allAreaDataList.value = await GetWorkAreaList({ workspaceid: 1 });
if (allAreaDataList.value.length > 0) {
allAreaDataList.value.forEach((area, index) => {
let geomjson = WktToGeojson(area.geom);
area = {
...area,
properties: JSON.parse(area.properties),
geomtype: getGeomType(area),
coordinates: geomjson.coordinates,
};
allAreaDataList.value[index] = area;
});
}
if (showThis) {
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图作业区域');
}, 50);
}
}
//
async function deleteArea(value) {
if (nowShowAreaData.value && nowShowAreaData.value.id == value.id) {
areaInfoShow.value = false;
nowShowAreaData.value = {};
}
DeleteWorkArea({
id: value.id,
}).then((result) => {
if (result) {
//
getWorkAreaList();
areaInfoShow.value = false;
nowShowAreaData.value = {};
createMessage.success('删除成功');
}
});
}
@ -246,50 +306,32 @@
pathMapRef.value.handlerLocation([position.lng, position.lat]);
}
//
async function getWorkAreaList() {
allAreaDataList.value = await GetWorkAreaList({ workspaceid: 1 });
allAreaDataList.value.forEach((area, index) => {
let geomjson = WktToGeojson(area.geom);
area = {
...area,
properties: JSON.parse(area.properties),
geomtype: getGeomType(area),
coordinates: geomjson.coordinates,
};
allAreaDataList.value[index] = area;
});
setTimeout(() => {
pathLeftMenuRef.value.updateShowMenuInfoList('地图作业区域');
}, 50);
}
// WKT
function getGeomType(area) {
let geom = area.geom;
let radiusFlag = area.properties.indexOf('radius') > -1 ? true : false;
//
if (geom.indexOf('POINT Z') > -1 && !radiusFlag) {
if (geom.indexOf('POINT') > -1 && !radiusFlag) {
return 'Point';
}
// 线
if (geom.indexOf('LINESTRING Z') > -1 && !radiusFlag) {
if (geom.indexOf('LINESTRING') > -1 && !radiusFlag) {
return 'Polyline';
}
//
if (geom.indexOf('MULTIPOLYGON Z') > -1 && !radiusFlag) {
if (geom.indexOf('POLYGON') > -1 && !radiusFlag) {
return 'Polygon';
}
//
if (geom.indexOf('MULTIPOLYGON Z') > -1 && radiusFlag) {
if (geom.indexOf('POLYGON') > -1 && radiusFlag) {
return 'Circle';
}
}
onMounted(() => {
//
getWorkAreaList();
nowShowMarkData.value = markJson[1];
getWorkAreaList(false);
getAnnotationList();
});
</script>
<style lang="less" scoped>
@ -310,7 +352,7 @@
// width: auto;
}
.markInfoDiv {
.annotationInfoDiv {
position: relative;
height: 100%;
width: 320px;

@ -1,206 +0,0 @@
[
{
"id": "84b09cdc-8138-461a-9008-2ac2fd2dabe1",
"name": "fence-2025-07-09 10:58",
"status": "enable",
"type": "dfence",
"content": {
"type": "Feature",
"geometry": {
"type": "Circle",
"radius": 25.98278531053457,
"coordinates": [
113.94260619946274,
22.581532991805254
]
},
"properties": {
"color": "#00FF00"
}
},
"area_hash": "enable_dfence_602389930bf13745ad901786a991ee0a",
"created_time": 1752029923657,
"created_by": "1921832882836627456",
"created_nickname": "17854119262",
"updated_time": 1752029923657,
"updated_by": "1921832882836627456",
"updated_nickname": "17854119262"
},
{
"id": "f8a1ba2f-3d75-45e3-8c37-c305b8a8a18f",
"name": "noland-2025-07-03 09:37",
"status": "enable",
"type": "noland",
"content": {
"type": "Feature",
"geometry": {
"type": "Polyline",
"coordinates": [
[
[
113.94250795742009,
22.58060189921086
],
[
113.94251951924755,
22.580338767560157
],
[
113.94278841610303,
22.580473014976874
],
[
113.94264963349448,
22.580583102519093
],
[
113.9425571112225,
22.580658284012188
]
]
]
},
"properties": {
"color": "#FF9900",
"width": 50,
"clampToGround": true
}
},
"area_hash": "enable_noland_64e037d7470402c7ab2fac8e314dcfd6",
"created_time": 1751506632716,
"created_by": "1921832882836627456",
"created_nickname": "17854119262",
"updated_time": 1752051379960,
"updated_by": "1921832882836627456",
"updated_nickname": "17854119262"
},
{
"id": "c30566e1-efcd-4d23-9f7e-d103816ebf22",
"name": "nfz-2025-07-03 09:36",
"status": "enable",
"type": "nfz",
"content": {
"type": "Feature",
"geometry": {
"type": "Circle",
"radius": 21.689063819799266,
"coordinates": [
113.94177749877194,
22.58107812199575
]
},
"properties": {
"color": "#FF0000"
}
},
"area_hash": "enable_nfz_d1da0a6137ef50153537ee83155f5cef",
"created_time": 1751506599545,
"created_by": "1921832882836627456",
"created_nickname": "17854119262",
"updated_time": 1751506599545,
"updated_by": "1921832882836627456",
"updated_nickname": "17854119262"
},
{
"id": "53d34e36-83a1-4f27-9379-59916ac22f94",
"name": "作业区",
"status": "enable",
"type": "dfence",
"content": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
113.93691743280002,
22.580990598743295,
13.105187747054286
],
[
113.93696596905927,
22.57814717285005,
50.58228204435394
],
[
113.9391350491713,
22.57816355777337,
62.20456885650349
],
[
113.93905350496071,
22.5810254053995,
14.889189566602015
],
[
113.93691743280002,
22.580990598743295,
13.105187747054286
]
]
]
},
"properties": {
"color": "#00FF00"
}
},
"area_hash": "enable_dfence_d0dc9ea80f32a4ddf9737ed27059da89",
"created_time": 1747035695040,
"created_by": "",
"created_nickname": "",
"updated_time": 1751870133102,
"updated_by": "1921832882836627456",
"updated_nickname": "17854119262"
},
{
"id": "189b2247-a5be-49ef-83cb-768056a00ed6",
"name": "限飞区",
"status": "enable",
"type": "nfz",
"content": {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
113.93818303751036,
22.57955559024499
],
[
113.93817466012537,
22.579329971314916
],
[
113.93810624285746,
22.579017475880626
],
[
113.93833802482754,
22.57902266288293
],
[
113.93833942091635,
22.57956207360456
],
[
113.93818303751036,
22.57955559024499
]
]
]
},
"properties": {
"color": "#FF0000",
"clampToGround": true
}
},
"area_hash": "enable_nfz_d362c13ac83407d94d7e8754f25b1f8d",
"created_time": 1747035694853,
"created_by": "",
"created_nickname": "",
"updated_time": 1751870135023,
"updated_by": "1921832882836627456",
"updated_nickname": "17854119262"
}
]

@ -1,348 +0,0 @@
[
{
"id": "302914d9-cb64-42b6-b149-504a8da5fc57",
"name": "限时通行",
"order": 0,
"status": 1,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#2D8CF0",
"is3d": false,
"font_size": 24,
"line_width": 13,
"line_start_cap": 0,
"line_end_cap": 3
},
"geometry": {
"type": "LineString",
"coordinates": [
[
113.93791036656113,
22.580846919934572,
16.289661439575617
],
[
113.93790662794272,
22.58080525893029,
16.978841881531686
],
[
113.93793537498757,
22.580571144993392,
20.678091836753808
],
[
113.93771086752942,
22.580362654641405,
24.05391008697749
],
[
113.93799551314106,
22.58016161251263,
26.888214419326214
],
[
113.93793224643738,
22.579899786408422,
31.450909981361924
]
]
}
},
"type": 1,
"user_name": "",
"user_id": "",
"remark": ""
},
"update_time": 1751619820885,
"create_time": 1729664978199,
"elevation_load_status": 0
},
{
"id": "5f26f8ac-5a35-4254-93a0-0bfc73765c78",
"name": "禁止停车区域",
"order": 0,
"status": 1,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#B620E0",
"is3d": false
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
113.93710053086316,
22.579672717186753,
23.320508205597196
],
[
113.93794932236936,
22.579691102044677,
34.89822401294342
],
[
113.93880753828225,
22.579712215916796,
27.103696311361936
],
[
113.93880540494872,
22.579771626594315,
25.942309355632386
],
[
113.93709983416198,
22.579734423484975,
23.235941922329605
]
]
]
}
},
"type": 2,
"user_name": "",
"user_id": "",
"remark": ""
},
"update_time": 1751620038100,
"create_time": 1729664978199,
"elevation_load_status": 0
},
{
"id": "f52f7506-8b18-4447-a323-8c49033de5c8",
"name": "出入口2",
"order": 0,
"status": 1,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#19BE6B",
"is3d": false,
"font_size": 16,
"clampToGround": false
},
"geometry": {
"type": "Point",
"coordinates": [
113.938434636,
22.580695156,
8982.852151371233
]
}
},
"type": 0,
"user_name": "",
"user_id": "",
"remark": ""
},
"update_time": 1751593215069,
"create_time": 1729664978199,
"elevation_load_status": 0
},
{
"id": "05739f91-a6c3-4ba4-9e95-57c75e099a94",
"name": "17854119262 1",
"order": 0,
"status": 0,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#B620E0",
"clampToGround": true,
"is3d": false,
"font_size": 16,
"icon": -4
},
"geometry": {
"type": "Point",
"coordinates": [
113.9406391943762,
22.580527744164762,
21.51958588283192
],
"breadCrumbs": null
}
},
"type": 0,
"user_name": "17854119262",
"user_id": "1921832882836627456",
"remark": ""
},
"update_time": 1751685220114,
"create_time": 1751448270707,
"elevation_load_status": 0
},
{
"id": "9c991a85-8d8f-476f-bece-67ce0c554d55",
"name": "17854119262 2123",
"order": 0,
"status": 0,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#2D8CF0",
"is3d": false,
"line_width": 5,
"line_start_cap": 3,
"line_end_cap": 3
},
"geometry": {
"type": "LineString",
"coordinates": [
[
113.94138861698154,
22.580643029700447,
20.832049922045826
],
[
113.9413698107081,
22.5800551336431,
23.231842464666247
],
[
113.94119605807259,
22.579448966138774,
26.76552516976654
],
[
113.94156736523672,
22.579691602916927,
28.181016541167885
]
]
}
},
"type": 1,
"user_name": "17854119262",
"user_id": "1921832882836627456",
"remark": "线"
},
"update_time": 1751685219204,
"create_time": 1751506017591,
"elevation_load_status": 0
},
{
"id": "1e1a0eb8-22af-41b0-ad3a-f79292e128c5",
"name": "17854119262 1",
"order": 0,
"status": 0,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#2D8CF0",
"is3d": false
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
113.94179483601683,
22.5803370571891,
24.600344506309114
],
[
113.94193361411388,
22.579958468841305,
29.67288586963777
],
[
113.94226611869635,
22.58025381696287,
28.052565527104434
]
]
]
}
},
"type": 2,
"user_name": "17854119262",
"user_id": "1921832882836627456",
"remark": "矩"
},
"update_time": 1751685218498,
"create_time": 1751506060690,
"elevation_load_status": 0
},
{
"id": "92c3fb1e-fa82-48bf-911d-af742c737c96",
"name": "17854119262 2",
"order": 0,
"status": 0,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#2D8CF0",
"clampToGround": true,
"is3d": false
},
"geometry": {
"radius": 23.519013068778005,
"type": "Circle",
"coordinates": [
113.94093593815374,
22.58033819250183
],
"breadCrumbs": null
}
},
"type": 3,
"user_name": "17854119262",
"user_id": "1921832882836627456",
"remark": "圈"
},
"update_time": 1751685217792,
"create_time": 1751530265940,
"elevation_load_status": 0
},
{
"id": "6d522cc6-3d9e-4b08-9b7c-b578314e8b50",
"name": "出入口1",
"order": 0,
"status": 1,
"display": 1,
"resource": {
"content": {
"type": "Feature",
"properties": {
"color": "#2D8CF0",
"clampToGround": false,
"is3d": false
},
"geometry": {
"type": "Point",
"coordinates": [
113.93743037203272,
22.580735812179856,
8985.824886104954
]
}
},
"type": 0,
"user_name": "",
"user_id": "",
"remark": "点"
},
"update_time": 1751611711104,
"create_time": 1729664978199,
"elevation_load_status": 0
}
]

@ -1,5 +1,5 @@
export { default as PathLeftMenu } from './pathLeftMenu.vue';
export { default as PathMap } from './pathMap.vue';
export { default as PathImageInfo } from './pathImageInfo.vue';
export { default as PathMarkInfo } from './pathMarkInfo.vue';
export { default as PathAnnotationInfo } from './pathAnnotationInfo.vue';
export { default as PathAreaInfo } from './pathAreaInfo.vue';

@ -1,76 +1,85 @@
<template>
<div class="markInfo">
<div class="annotationInfo">
<!-- 关闭按钮 -->
<div class="closeButton">
<CloseOutlined @click="closePathMarkInfo" style="font-size: 20px; color: white" />
<CloseOutlined @click="closePathAnnotationInfo" style="font-size: 20px; color: white" />
</div>
<div class="markInfo_biaozhu_1">
<div class="annotationInfo_biaozhu_1">
<a-row>
<a-col :span="24">
<div class="markTitle">标注信息</div>
<div class="annotationTitle">标注信息</div>
</a-col>
<!-- 标题名线 -->
<a-col :span="24">
<div class="markTitle">
<div class="markTitleButton_right">
<div class="annotationTitle">
<div class="annotationTitleButton_right">
<AntDesignOutlined
v-if="nowMarkData.resource.type == '0'"
:style="{ color: nowMarkData.resource.content.properties.color }"
v-if="nowAnnotationData.type == 0"
:style="{ color: nowAnnotationData.properties.color }"
/>
<ExpandAltOutlined
v-if="nowMarkData.resource.type == '1'"
:style="{ color: nowMarkData.resource.content.properties.color }"
v-if="nowAnnotationData.type == 1"
:style="{ color: nowAnnotationData.properties.color }"
/>
<BorderOutlined
v-if="nowMarkData.resource.type == '2'"
:style="{ color: nowMarkData.resource.content.properties.color }"
v-if="nowAnnotationData.type == 2"
:style="{ color: nowAnnotationData.properties.color }"
/>
<LogoutOutlined
v-if="nowMarkData.resource.type == '3'"
:style="{ color: nowMarkData.resource.content.properties.color }"
v-if="nowAnnotationData.type == 3"
:style="{ color: nowAnnotationData.properties.color }"
/>
</div>
<a-input v-model:value="nowMarkData.name" style="width: 60%" size="small"></a-input>
<div class="markTitleButton" @click="handlerLocation">
<a-input
v-model:value="nowAnnotationData.name"
style="width: 60%"
size="small"
></a-input>
<div class="annotationTitleButton" @click="handlerLocation">
<AimOutlined />
</div>
<div class="markTitleButton" @click="deleteMark">
<div class="annotationTitleButton" @click="deleteAnnotation">
<DeleteOutlined />
</div>
</div>
</a-col>
<!-- 颜色线 -->
<a-col :span="6">
<div class="markTitle">颜色</div>
<div class="annotationTitle">颜色</div>
</a-col>
<a-col :span="18">
<div class="markContent">
<div class="annotationContent">
<div
class="popoverClass"
v-for="color in ['#2D8CF0', '#19BE6B', '#FF9900', '#E23C39', '#B620E0']"
:key="color"
:style="{ background: color }"
@click="nowMarkData.resource.content.properties.color = color"
@click="nowAnnotationData.properties.color = color"
>
<CheckOutlined
v-if="nowMarkData?.resource?.content?.properties?.color == color"
v-if="nowAnnotationData.properties.color == color"
style="color: white"
/>
</div>
</div>
</a-col>
<!-- 形态线 -->
<a-col :span="6" v-if="nowMarkData.resource.type == '1'">
<div class="markTitle">形态</div>
<a-col :span="6" v-if="nowAnnotationData.type == 1">
<div class="annotationTitle">形态</div>
</a-col>
<a-col :span="18" v-if="nowMarkData.resource.type == '1'">
<div class="markContent" style="gap: 5%">
<a-col :span="18" v-if="nowAnnotationData.type == 1">
<div class="annotationContent" style="gap: 5%">
<a-tooltip placement="top">
<template #title> 线宽度 </template>
<a-input
v-model:value="nowMarkData.resource.content.properties.line_width"
v-model:value="nowAnnotationData.properties.line_width"
style="width: 30%"
@change="
nowAnnotationData.properties.line_width = parseFloat(
nowAnnotationData.properties.line_width.toString().replace(/[^-0-9]/g, ''),
)
"
>
<template #prefix><AlignLeftOutlined /></template>
</a-input>
@ -78,7 +87,7 @@
<a-tooltip placement="top">
<template #title> 线头部样式 </template>
<a-select
v-model:value="nowMarkData.resource.content.properties.line_start_cap"
v-model:value="nowAnnotationData.properties.line_start_cap"
style="width: 30%"
option-label-prop="children"
>
@ -99,7 +108,7 @@
<a-tooltip placement="top">
<template #title> 线尾部样式 </template>
<a-select
v-model:value="nowMarkData.resource.content.properties.line_end_cap"
v-model:value="nowAnnotationData.properties.line_end_cap"
style="width: 30%"
option-label-prop="children"
>
@ -120,20 +129,20 @@
</div>
</a-col>
<!-- 图标 -->
<a-col :span="6" v-if="nowMarkData.resource.type == '0'">
<div class="markTitle">图标</div>
<a-col :span="6" v-if="nowAnnotationData.type == 0">
<div class="annotationTitle">图标</div>
</a-col>
<a-col :span="18" v-if="nowMarkData.resource.type == '0'">
<div class="markContent"></div>
<a-col :span="18" v-if="nowAnnotationData.type == 0">
<div class="annotationContent"></div>
</a-col>
<!-- 字体线 -->
<a-col :span="6">
<div class="markTitle">字体</div>
<div class="annotationTitle">字体</div>
</a-col>
<a-col :span="18">
<div class="markContent">
<div class="annotationContent">
<a-radio-group
v-model:value="nowMarkData.resource.content.properties.font_size"
v-model:value="nowAnnotationData.properties.font_size"
button-style="solid"
size="small"
>
@ -146,10 +155,10 @@
</a-row>
</div>
<div style="border-bottom: 1px solid #ffffff55; margin-left: 15px; margin-right: 15px"></div>
<div class="markInfo_biaozhu_2">
<div class="annotationInfo_biaozhu_2">
<a-row>
<a-col :span="24">
<div class="markTitle">
<div class="annotationTitle">
测量数据
<a-tooltip placement="top">
<template #title> 只能测量出当前视窗范围内的数据 </template>
@ -158,11 +167,11 @@
</div>
</a-col>
<!-- 经纬模式 -->
<a-col :span="6" v-if="[0, 3].includes(nowMarkData.resource.type)">
<div class="markTitle">经纬模式</div>
<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(nowMarkData.resource.type)">
<div class="markContent">
<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>
@ -170,16 +179,13 @@
</div>
</a-col>
<!-- 经度 -->
<a-col :span="6" v-if="[0].includes(nowMarkData.resource.type)">
<div class="markTitle">经度</div>
<a-col :span="6" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationTitle">经度</div>
</a-col>
<a-col :span="18" v-if="[0].includes(nowMarkData.resource.type)">
<div class="markContent">
<a-col :span="18" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationContent">
<!-- 十进制 -->
<a-input
v-if="modalType == 0"
v-model:value="nowMarkData.resource.content.geometry.coordinates[0]"
>
<a-input v-if="modalType == 0" v-model:value="nowAnnotationData.coordinates[0]">
<template #addonAfter>
<span style="color: white">°</span>
</template>
@ -221,16 +227,13 @@
</div>
</a-col>
<!-- 纬度 -->
<a-col :span="6" v-if="[0].includes(nowMarkData.resource.type)">
<div class="markTitle">纬度</div>
<a-col :span="6" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationTitle">纬度</div>
</a-col>
<a-col :span="18" v-if="[0].includes(nowMarkData.resource.type)">
<div class="markContent">
<a-col :span="18" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationContent">
<!-- 十进制 -->
<a-input
v-if="modalType == 0"
v-model:value="nowMarkData.resource.content.geometry.coordinates[1]"
>
<a-input v-if="modalType == 0" v-model:value="nowAnnotationData.coordinates[1]">
<template #addonAfter>
<span style="color: white">°</span>
</template>
@ -272,126 +275,121 @@
</div>
</a-col>
<!-- 高度 -->
<a-col :span="6" v-if="[0].includes(nowMarkData.resource.type)">
<div class="markTitle">高度</div>
<a-col :span="6" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationTitle">高度</div>
</a-col>
<a-col :span="18" v-if="[0].includes(nowMarkData.resource.type)">
<div class="markContent">
<a-input v-model:value="nowMarkData.resource.content.geometry.coordinates[2]">
<a-col :span="18" v-if="[0].includes(nowAnnotationData.type)">
<div class="annotationContent">
<a-input v-model:value="nowAnnotationData.coordinates[2]">
<template #addonAfter> <span style="color: white">m</span> </template>
</a-input>
</div>
</a-col>
<!-- 圆心经度 -->
<a-col :span="6" v-if="[3].includes(nowMarkData.resource.type)">
<div class="markTitle">圆心经度</div>
<a-col :span="6" v-if="[3].includes(nowAnnotationData.type)">
<div class="annotationTitle">圆心经度</div>
</a-col>
<a-col :span="18" v-if="[3].includes(nowMarkData.resource.type)">
<div class="markContent">
<a-input v-model:value="nowMarkData.resource.content.geometry.coordinates[0]">
<a-col :span="18" v-if="[3].includes(nowAnnotationData.type)">
<div class="annotationContent">
<a-input v-model:value="nowAnnotationData.properties.centerPoint[0]">
<template #addonAfter> <span style="color: white">°</span> </template>
</a-input>
</div>
</a-col>
<!-- 圆心纬度 -->
<a-col :span="6" v-if="[3].includes(nowMarkData.resource.type)">
<div class="markTitle">圆心纬度</div>
<a-col :span="6" v-if="[3].includes(nowAnnotationData.type)">
<div class="annotationTitle">圆心纬度</div>
</a-col>
<a-col :span="18" v-if="[3].includes(nowMarkData.resource.type)">
<div class="markContent">
<a-input v-model:value="nowMarkData.resource.content.geometry.coordinates[1]">
<a-col :span="18" v-if="[3].includes(nowAnnotationData.type)">
<div class="annotationContent">
<a-input v-model:value="nowAnnotationData.properties.centerPoint[1]">
<template #addonAfter> <span style="color: white">°</span> </template>
</a-input>
</div>
</a-col>
<!-- 水平半径 -->
<a-col :span="6" v-if="[3].includes(nowMarkData.resource.type)">
<div class="markTitle">水平半径</div>
<a-col :span="6" v-if="[3].includes(nowAnnotationData.type)">
<div class="annotationTitle">水平半径</div>
</a-col>
<a-col :span="18" v-if="[3].includes(nowMarkData.resource.type)">
<div class="markContent">
<a-input v-model:value="nowMarkData.resource.content.geometry.radius">
<a-col :span="18" v-if="[3].includes(nowAnnotationData.type)">
<div class="annotationContent">
<a-input v-model:value="nowAnnotationData.properties.radius">
<template #addonAfter> <span style="color: white">m</span> </template>
</a-input>
</div>
</a-col>
<!-- 水平面积形状 -->
<a-col :span="6" v-if="[2, 3].includes(nowMarkData.resource.type)">
<div class="markTitle">水平面积</div>
<a-col :span="6" v-if="[2, 3].includes(nowAnnotationData.type)">
<div class="annotationTitle">水平面积</div>
</a-col>
<a-col :span="18" v-if="[2, 3].includes(nowMarkData.resource.type)">
<div class="markContent">
<span style="color: white; gap: 10px" v-if="[2].includes(nowMarkData.resource.type)">
<a-col :span="18" v-if="[2, 3].includes(nowAnnotationData.type)">
<div class="annotationContent">
<span style="color: white; gap: 10px" v-if="[2].includes(nowAnnotationData.type)">
{{ horizontalArea }}
</span>
<span style="color: white; gap: 10px" v-if="[3].includes(nowMarkData.resource.type)">
<span style="color: white; gap: 10px" v-if="[3].includes(nowAnnotationData.type)">
{{
(
Math.PI *
nowMarkData.resource.content.geometry.radius *
nowMarkData.resource.content.geometry.radius
nowAnnotationData.properties.radius *
nowAnnotationData.properties.radius
).toFixed(2)
}}
</span>
</div>
</a-col>
<!-- 水平周长形状 -->
<a-col :span="6" v-if="[2, 3].includes(nowMarkData.resource.type)">
<div class="markTitle">水平周长</div>
<a-col :span="6" v-if="[2, 3].includes(nowAnnotationData.type)">
<div class="annotationTitle">水平周长</div>
</a-col>
<a-col :span="18" v-if="[2, 3].includes(nowMarkData.resource.type)">
<div class="markContent">
<span style="color: white; gap: 10px" v-if="[2].includes(nowMarkData.resource.type)">
m
<a-col :span="18" v-if="[2, 3].includes(nowAnnotationData.type)">
<div class="annotationContent">
<span style="color: white; gap: 10px" v-if="[2].includes(nowAnnotationData.type)">
{{ horizontalPerimeter }}m
</span>
<span style="color: white; gap: 10px" v-if="[3].includes(nowMarkData.resource.type)">
{{ (2 * Math.PI * nowMarkData.resource.content.geometry.radius).toFixed(1) }}
<span style="color: white; gap: 10px" v-if="[3].includes(nowAnnotationData.type)">
{{ (2 * Math.PI * nowAnnotationData.properties.radius).toFixed(1) }}
m
</span>
</div>
</a-col>
<!-- 水平距离线 -->
<a-col :span="6" v-if="[1].includes(nowMarkData.resource.type)">
<div class="markTitle">水平距离</div>
<a-col :span="6" v-if="[1].includes(nowAnnotationData.type)">
<div class="annotationTitle">水平距离</div>
</a-col>
<a-col :span="18" v-if="[1].includes(nowMarkData.resource.type)">
<div class="markContent">
<span style="color: white; gap: 10px">
<!-- {{ getLineStringDistance(nowMarkData.resource)[0] }}m -->
</span>
<a-col :span="18" v-if="[1].includes(nowAnnotationData.type)">
<div class="annotationContent">
<span style="color: white; gap: 10px"> {{ horizontalDistance }}m </span>
</div>
</a-col>
<!-- 直线距离线 -->
<a-col :span="6" v-if="[1].includes(nowMarkData.resource.type)">
<div class="markTitle">直线距离</div>
<a-col :span="6" v-if="[1].includes(nowAnnotationData.type)">
<div class="annotationTitle">直线距离</div>
</a-col>
<a-col :span="18" v-if="[1].includes(nowMarkData.resource.type)">
<div class="markContent">
<span style="color: white; gap: 10px"> m </span>
<a-col :span="18" v-if="[1].includes(nowAnnotationData.type)">
<div class="annotationContent">
<span style="color: white; gap: 10px"> {{ linearDistance }}m </span>
</div>
</a-col>
<!-- 高度差线 -->
<a-col :span="6" v-if="[1, 2].includes(nowMarkData.resource.type)">
<div class="markTitle">高度差</div>
<a-col :span="6" v-if="[1, 2].includes(nowAnnotationData.type)">
<div class="annotationTitle">高度差</div>
</a-col>
<a-col :span="18" v-if="[1, 2].includes(nowMarkData.resource.type)">
<div class="markContent">
<span style="color: white; gap: 10px" v-if="[1].includes(nowMarkData.resource.type)">
m
</span>
<span style="color: white; gap: 10px" v-if="[2].includes(nowMarkData.resource.type)">
m
<a-col :span="18" v-if="[1, 2].includes(nowAnnotationData.type)">
<div class="annotationContent">
<span style="color: white; gap: 10px" v-if="[1, 2].includes(nowAnnotationData.type)">
{{ heightDiff }}m
</span>
</div>
</a-col>
<!-- 简介线 -->
<a-col :span="6">
<div class="markTitle">简介</div>
<div class="annotationTitle">简介</div>
</a-col>
<a-col :span="18">
<div class="markContent">
<div class="annotationContent">
<a-textarea
v-model:value="nowMarkData.resource.remark"
v-model:value="nowAnnotationData.remark"
:rows="4"
:maxlength="10"
placeholder="请输入"
@ -401,11 +399,11 @@
</a-col>
<!-- 绘制者线 -->
<a-col :span="6">
<div class="markTitle">绘制者</div>
<div class="annotationTitle">绘制者</div>
</a-col>
<a-col :span="18">
<div class="markContent">
<span style="color: white">{{ nowMarkData.resource.user_name }}</span>
<div class="annotationContent">
<span style="color: white">{{ nowAnnotationData.createUserName }}</span>
</div>
</a-col>
</a-row>
@ -413,7 +411,7 @@
</div>
</template>
<script lang="ts" setup>
import { ref, watch, watchEffect, computed, onMounted } from 'vue';
import { ref, watch, computed, onMounted } from 'vue';
import * as mars3d from 'mars3d';
import * as Cesium from 'mars3d-cesium';
import {
@ -441,14 +439,14 @@
import { cloneDeep } from 'lodash-es';
let map: mars3d.Map;
const props = defineProps(['allMarkDataList', 'nowShowMarkData']);
const props = defineProps(['allAnnotationDataList', 'nowShowAnnotationData']);
const emits = defineEmits([
'setNowShowMarkData',
'closePathMarkInfo',
'setNowShowAnnotationData',
'closePathAnnotationInfo',
'handlerLocation',
'deleteMark',
'deleteAnnotation',
]);
const nowMarkData: any = ref(props.nowShowMarkData);
const nowAnnotationData: any = ref(props.nowShowAnnotationData);
//
const modalType = ref<number>(0);
// -
@ -470,17 +468,17 @@
// - -
let { degrees, minutes, seconds } = decimalToDMS_0.value;
let decimal = Math.abs(degrees) + minutes / 60 + seconds / 3600;
nowMarkData.value.resource.content.geometry.coordinates[0] = decimal;
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;
nowMarkData.value.resource.content.geometry.coordinates[1] = decimal;
nowAnnotationData.value.coordinates[1] = decimal;
}
if (newValue == 1) {
// - -
const decimal1 = nowMarkData.value.resource.content.geometry.coordinates[0];
const decimal1 = nowAnnotationData.value.coordinates[0];
const degrees1 = Math.floor(decimal1);
const minutesFull1 = (decimal1 - degrees1) * 60;
const minutes1 = Math.floor(minutesFull1);
@ -491,7 +489,7 @@
seconds: seconds1,
};
// - -
const decimal2 = nowMarkData.value.resource.content.geometry.coordinates[1];
const decimal2 = nowAnnotationData.value.coordinates[1];
const degrees2 = Math.floor(decimal2);
const minutesFull2 = (decimal2 - degrees2) * 60;
const minutes2 = Math.floor(minutesFull2);
@ -506,48 +504,78 @@
);
//
function closePathMarkInfo() {
emits('closePathMarkInfo');
function closePathAnnotationInfo() {
emits('closePathAnnotationInfo');
}
//
function handlerLocation() {
let coordinates = props.nowShowMarkData.resource.content.geometry.coordinates;
switch (props.nowShowMarkData.resource.type) {
case 0:
emits('handlerLocation', {
lng: coordinates[0],
lat: coordinates[1],
});
break;
case 1:
emits('handlerLocation', {
lng: coordinates[0][0],
lat: coordinates[0][1],
});
break;
case 2:
emits('handlerLocation', {
lng: coordinates[0][0][0],
lat: coordinates[0][0][1],
});
break;
case 3:
emits('handlerLocation', {
lng: coordinates[0],
lat: coordinates[1],
});
break;
}
emits('handlerLocation', {
lng: props.nowShowAnnotationData.properties.centerPoint[0],
lat: props.nowShowAnnotationData.properties.centerPoint[1],
});
}
//
function deleteMark() {
emits('deleteMark', props.nowShowMarkData);
function deleteAnnotation() {
emits('deleteAnnotation', props.nowShowAnnotationData);
}
// 线-线
const linearDistance: any = ref();
// 线-
const horizontalDistance: any = ref();
// -
const horizontalArea: any = ref();
// -
const horizontalPerimeter: any = ref();
//
const heightDiff: any = ref();
watch(
() => props.nowShowMarkData,
() => nowAnnotationData.value,
() => {
nowMarkData.value = props.nowShowMarkData;
emits('setNowShowAnnotationData', nowAnnotationData.value, false);
},
{
deep: true,
},
);
watch(
() => 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);
}
},
{
deep: true,
@ -557,7 +585,7 @@
onMounted(() => {});
</script>
<style lang="less" scoped>
.markInfo {
.annotationInfo {
//
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
@ -569,10 +597,10 @@
height: 100%;
background: #232323;
.markInfo_biaozhu_1 {
.annotationInfo_biaozhu_1 {
padding: 15px;
}
.markInfo_biaozhu_2 {
.annotationInfo_biaozhu_2 {
padding: 15px;
overflow-y: auto;
height: 650px;
@ -587,7 +615,7 @@
z-index: 200;
}
.markTitle {
.annotationTitle {
display: flex;
align-items: center;
justify-content: flex-start;
@ -598,7 +626,7 @@
width: 100%;
flex-wrap: wrap;
.markTitleButton_right {
.annotationTitleButton_right {
height: 20px;
width: 20px;
display: flex;
@ -607,7 +635,7 @@
margin-right: 12px;
font-size: 18px;
}
.markTitleButton {
.annotationTitleButton {
height: 20px;
width: 20px;
display: flex;
@ -617,7 +645,7 @@
font-size: 18px;
}
}
.markContent {
.annotationContent {
display: flex;
align-items: center;
justify-content: flex-start;
@ -640,11 +668,11 @@
.svg-container {
display: block;
}
::v-deep .markContent .ant-input {
::v-deep .annotationContent .ant-input {
padding: 0px !important;
}
::v-deep .markContent .ant-select-selection-item {
::v-deep .annotationContent .ant-select-selection-item {
height: 20px !important;
}
</style>

@ -2,17 +2,17 @@
<div class="areaInfo">
<a-row>
<a-col :span="24">
<div class="markTitle"> 自定义飞行区 </div>
<div class="annotationTitle"> 自定义飞行区 </div>
</a-col>
<a-col :span="24">
<div class="markTitle">
<div class="annotationTitle">
<!-- 自定义禁降区 -->
<div
v-if="props.nowShowAreaData.type == 'noland'"
:style="{
width: '15px',
height: '15px',
background: `linear-gradient(to bottom right, transparent 45%, #FF9900 45%, #FF9900 60%, transparent 60%), #ffffff00`,
outline: `2px solid #FF9900`,
'margin-left': '2px',
'margin-right': '12px',
}"
@ -43,111 +43,68 @@
}"
/>
<a-input v-model:value="nowAreaData.name" style="width: 65%" size="small"></a-input>
<div class="markTitleButton" @click="handlerLocation">
<div class="annotationTitleButton" @click="handlerLocation">
<AimOutlined />
</div>
<div class="markTitleButton" @click="deleteArea">
<div class="annotationTitleButton" @click="deleteArea">
<DeleteOutlined />
</div>
</div>
</a-col>
<a-col :span="24">
<div class="markPrompt" v-if="props.nowShowAreaData.type == 'noland'">
<div class="annotationPrompt" v-if="props.nowShowAreaData.type == 'noland'">
自定义作业区绘制后飞行器只能在该区域内飞行
</div>
<div class="markPrompt" v-if="props.nowShowAreaData.type == 'dfence'">
<div class="annotationPrompt" v-if="props.nowShowAreaData.type == 'dfence'">
自定义禁降区绘制后飞行器不能在绘制区域内自动降落
</div>
<div class="markPrompt" v-if="props.nowShowAreaData.type == 'nfz'">
<div class="annotationPrompt" v-if="props.nowShowAreaData.type == 'nfz'">
自定义作业区绘制后飞行器只能在该区域内飞行
</div>
</a-col>
<a-col :span="24">
<div class="markTitle"> 更多信息 </div>
<div class="annotationTitle"> 更多信息 </div>
</a-col>
<!-- 启用状态 -->
<a-col :span="6">
<div class="markTitle">启用状态</div>
<div class="annotationTitle">启用状态</div>
</a-col>
<a-col :span="18">
<div class="markContent">
<div class="annotationContent">
{{ props.nowShowAreaData.state == 0 ? '已启用' : '已禁用' }}
</div>
</a-col>
<!-- 水平距离 -->
<a-col :span="6" v-if="props.nowShowAreaData.type == 'noland'">
<div class="markTitle">水平距离</div>
<!-- 水平周长 -->
<a-col :span="6">
<div class="annotationTitle">水平周长</div>
</a-col>
<a-col :span="18" v-if="props.nowShowAreaData.type == 'noland'">
<div class="markContent"> {{ nowAreaData.length.toFixed(1) }}m</div>
<a-col :span="18">
<div class="annotationContent"> {{ length.toFixed(2) }}m</div>
</a-col>
<!-- 水平面积 -->
<a-col :span="6">
<div class="markTitle">水平面积</div>
<div class="annotationTitle">水平面积</div>
</a-col>
<a-col :span="18">
<div class="markContent"> {{ nowAreaData.area.toFixed(2) }}</div>
</a-col>
<!-- 水平周长 -->
<a-col :span="6" v-if="props.nowShowAreaData.geomtype == 'Polygon'">
<div class="markTitle">水平周长</div>
</a-col>
<a-col :span="18" v-if="props.nowShowAreaData.geomtype == 'Polygon'">
<div class="markContent"> {{ nowAreaData.length.toFixed(1) }}m</div>
<div class="annotationContent"> {{ area.toFixed(2) }}</div>
</a-col>
<!-- 半径 -->
<a-col :span="6" v-if="props.nowShowAreaData.geomtype == 'Circle'">
<div class="markTitle">半径</div>
<div class="annotationTitle">半径</div>
</a-col>
<a-col :span="18" v-if="props.nowShowAreaData.geomtype == 'Circle'">
<div class="markContent">
<div class="annotationContent">
<a-input v-model:value="nowAreaData.properties.radius" style="width: 100%" size="small">
<template #addonAfter> <span style="color: white">m</span> </template>
</a-input>
</div>
</a-col>
<!-- 宽度 -->
<a-col :span="6" v-if="props.nowShowAreaData.type == 'noland'">
<div class="markTitle">宽度</div>
</a-col>
<a-col :span="18" v-if="props.nowShowAreaData.type == 'noland'">
<div class="markContent">
<div
class="button"
:class="{ disabled: nowAreaData.properties.width == 10 }"
@click="removeRecordNum"
>
<MinusOutlined style="font-size: 20px; color: #ffffff" />
</div>
<div class="numDiv">
<span v-if="!numInputFlag" class="numSpan" @click="focusInput">
{{ nowAreaData.properties.width }}
</span>
<a-input
v-if="numInputFlag"
ref="focusInputRef"
v-model:value="nowAreaData.properties.width"
style="width: 50%"
@blur="blurInput"
@keypress.enter="blurInput"
/>
<span style="margin-left: 10px; font-size: 18px; color: #ffffff">m</span>
</div>
<div
class="button"
:class="{ disabled: nowAreaData.properties.width == 100 }"
@click="addRecordNum"
>
<PlusOutlined style="font-size: 20px; color: #ffffff" />
</div>
</div>
</a-col>
<!-- 绘制者 -->
<a-col :span="6">
<div class="markTitle">绘制者</div>
<div class="annotationTitle">绘制者</div>
</a-col>
<a-col :span="18">
<div class="markContent"> {{ props.nowShowAreaData.createdUser }}</div>
<div class="annotationContent"> {{ props.nowShowAreaData.createdUser }}</div>
</a-col>
<a-col :span="24">
<div class="area_buttons">
@ -195,85 +152,16 @@
]);
const nowAreaData: any = ref(props.nowShowAreaData);
watch(
() => nowAreaData.value,
() => {
emits('setNowShowAreaData', nowAreaData.value, false);
},
{
deep: true,
},
);
// ----------------------------------------------------------------------
const numInputFlag = ref(false);
const focusInputRef = ref();
// input
function focusInput() {
numInputFlag.value = true;
nextTick(() => {
if (focusInputRef.value && focusInputRef.value.focus) {
focusInputRef.value.focus();
}
});
}
// inputorEnter
function blurInput() {
numInputFlag.value = false;
//
if (/^-?\d+(\.\d+)?$/.test(nowAreaData.value.properties.width.toString())) {
if (nowAreaData.value.properties.width > 100) {
// 100
nowAreaData.value.properties.width = 100;
} else if (nowAreaData.value.properties.width < 10) {
// 10
nowAreaData.value.properties.width = 10;
} else {
//
let newnum = cloneDeep(nowAreaData.value.properties.width);
nowAreaData.value.properties.width = parseFloat(parseFloat(newnum).toFixed(2));
}
} else {
//
nowAreaData.value.properties.width = 10;
}
}
// -
function removeRecordNum() {
let newnum = cloneDeep(nowAreaData.value.properties.width);
if (newnum == 10) {
return;
}
newnum -= 5;
nowAreaData.value.properties.width = parseFloat(newnum.toFixed(2));
}
// -
function addRecordNum() {
let newnum = cloneDeep(nowAreaData.value.properties.width);
if (newnum == 100) {
return;
}
newnum += 5;
nowAreaData.value.properties.width = parseFloat(newnum.toFixed(2));
}
//
function closePathAreaInfo() {
emits('closePathAreaInfo');
}
//
function handlerLocation() {
if (props.nowShowAreaData.geomtype == 'Circle') {
emits('handlerLocation', {
lng: props.nowShowAreaData.properties.centerPoint[0],
lat: props.nowShowAreaData.properties.centerPoint[1],
});
} else {
emits('handlerLocation', {
lng: props.nowShowAreaData.properties.centerPoint[0],
lat: props.nowShowAreaData.properties.centerPoint[1],
});
}
emits('handlerLocation', {
lng: props.nowShowAreaData.properties.centerPoint[0],
lat: props.nowShowAreaData.properties.centerPoint[1],
});
}
//
function deleteArea() {
@ -287,19 +175,37 @@
});
}
//
const length: any = ref();
const area: any = ref();
watch(
() => nowAreaData.value,
() => {
emits('setNowShowAreaData', nowAreaData.value, false);
},
{
deep: true,
},
);
watch(
() => props.nowShowAreaData,
() => {
nowAreaData.value = props.nowShowAreaData;
//
// getArea();
if (props.nowShowAreaData.type == 'noland') {
if (props.nowShowAreaData.geomtype == 'Polygon') {
//
// getDistance();
length.value = mars3d.MeasureUtil.getDistance(nowAreaData.value.coordinates[0]);
//
area.value = mars3d.MeasureUtil.getArea(nowAreaData.value.coordinates[0]);
}
if (props.nowShowAreaData.geomtype == 'Polygon') {
if (props.nowShowAreaData.geomtype == 'Circle') {
//
// getDistance();
length.value = 2 * Math.PI * parseFloat(nowAreaData.value.properties.radius);
//
area.value =
Math.PI *
parseFloat(nowAreaData.value.properties.radius) *
parseFloat(nowAreaData.value.properties.radius);
}
},
{
@ -323,7 +229,7 @@
padding: 15px;
}
.markTitle {
.annotationTitle {
display: flex;
align-items: center;
justify-content: flex-start;
@ -334,7 +240,7 @@
width: 100%;
flex-wrap: wrap;
.markTitleButton_right {
.annotationTitleButton_right {
height: 20px;
width: 20px;
display: flex;
@ -343,7 +249,7 @@
margin-right: 12px;
font-size: 18px;
}
.markTitleButton {
.annotationTitleButton {
height: 20px;
width: 20px;
display: flex;
@ -354,7 +260,7 @@
}
}
.markContent {
.annotationContent {
display: flex;
align-items: center;
justify-content: flex-start;
@ -365,7 +271,7 @@
color: #ffffff;
}
.markButton {
.annotationButton {
display: flex;
align-items: center;
justify-content: flex-start;
@ -375,7 +281,7 @@
flex-wrap: wrap;
}
.markPrompt {
.annotationPrompt {
display: flex;
align-items: center;
justify-content: flex-start;

@ -24,13 +24,14 @@
</div>
<div class="leftMenu_buttonList">
<div
class="leftMenu_buttonList_mark"
class="leftMenu_buttonList_annotation"
:style="{
background: showMenuInfoName == '地图标注' ? '#2D8CF0' : '#1a375a',
}"
@click="
showMenuInfoName = '地图标注';
updateShowMenuInfoList(showMenuInfoName);
showMenuInfoList = filterAfterAnnotationDataList;
"
>
<a-tooltip placement="right">
@ -103,10 +104,10 @@
<!-- 地图标注 -->
<div
v-if="showMenuInfoName == '地图标注'"
class="showMenuInfo_mark"
class="showMenuInfo_annotation"
:style="{
background:
props.nowShowMarkData && props.nowShowMarkData.id == show.id
props.nowShowAnnotationData && props.nowShowAnnotationData.id == show.id
? '#274D75'
: show.mouse
? '#393939'
@ -121,24 +122,24 @@
show.deleteClickNum = 0;
"
>
<div @click="setNowShowMarkData(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 @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>
<div
class="eye"
@click="show.status == 0 ? (show.status = 1) : (show.status = 0)"
:style="{ background: show.status == 1 ? '#2d8cf0' : '#000000' }"
@click="show.state == 0 ? hideThisAnnotation(show) : showThisAnnotation(show)"
:style="{ background: show.state == 0 ? '#2d8cf0' : '#000000' }"
>
<EyeOutlined v-if="show.status == 1" style="color: #ffffff; font-size: 16px" />
<EyeOutlined v-if="show.state == 0" style="color: #ffffff; font-size: 16px" />
<EyeInvisibleOutlined
v-if="show.status == 0"
v-if="show.state == 1"
style="color: #ffffff; font-size: 16px"
/>
</div>
<div @click="setNowShowMarkData(show)">{{ show.name }}</div>
<div @click="setNowShowAnnotationData(show)">{{ show.name }}</div>
<div class="buttonRight2" v-if="show.mouse">
<a-tooltip placement="top">
<template #title>
@ -157,7 +158,9 @@
<span>删除</span>
</template>
<DeleteOutlined
@click="show.deleteClickNum == 1 ? deleteMark(show) : show.deleteClickNum++"
@click="
show.deleteClickNum == 1 ? deleteAnnotation(show) : show.deleteClickNum++
"
/>
</a-tooltip>
</div>
@ -286,9 +289,9 @@
<div
v-if="show.type == 'noland'"
:style="{
width: '15px',
height: '15px',
background: `linear-gradient(to bottom right, transparent 45%, #FF9900 45%, #FF9900 60%, transparent 60%), #ffffff00`,
width: '13px',
height: '13px',
outline: `2px solid #FF9900`,
'margin-right': '6px',
}"
/>
@ -407,12 +410,7 @@
CheckCircleOutlined,
StopOutlined,
} from '@ant-design/icons-vue';
import {
GetWorkAreaList,
AddWorkArea,
UpdateWorkArea,
DeleteWorkArea,
} from '@/api/demo/mediaLibrary';
import { UpdateWorkArea, UpdateAnnotation } from '@/api/demo/mediaLibrary';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
@ -420,8 +418,8 @@
const props = defineProps([
'pathRecord',
'leftMenuShow',
'allMarkDataList',
'nowShowMarkData',
'allAnnotationDataList',
'nowShowAnnotationData',
'allImageDataList',
'nowShowImageData',
'allAreaDataList',
@ -431,19 +429,20 @@
'changeLeftMenuShow',
'handlerLocation',
'closePathModal',
'changeMarkInfoShow',
'setNowShowMarkData',
'changeAnnotationInfoShow',
'setNowShowAnnotationData',
'setNowShowImageData',
'setNowShowAreaData',
'setAllAreaData',
'deleteMark',
'setAllAnnotationData',
'deleteAnnotation',
'deleteArea',
]);
const showMenuInfoList = ref(props.allMarkDataList);
const showMenuInfoList = ref(props.allAnnotationDataList);
const showMenuInfoName = ref('地图标注');
function updateShowMenuInfoList(type) {
if (type == '地图标注') {
showMenuInfoList.value = props.allMarkDataList;
handleChangeAnnotationSearch();
}
if (type == '地图照片') {
showMenuInfoList.value = props.allImageDataList;
@ -461,7 +460,6 @@
function closePathModal() {
emits('closePathModal');
}
// -
function funAddOrRemoveToMap(show) {
show.show_on_map = !show.show_on_map;
@ -472,9 +470,51 @@
}
}
// -
const filterAfterAnnotationDataList = ref(props.allAnnotationDataList);
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;
}
// -
function deleteMark(show) {
emits('deleteMark', show);
function deleteAnnotation(show) {
show.deleteClickNum = 0;
emits('deleteAnnotation', show);
}
// -
function showThisAnnotation(value) {
setNowShowAnnotationData({
...value,
state: 0,
});
UpdateAnnotation({
...value,
properties: JSON.stringify(value.properties),
state: 0,
}).then((res) => {
emits('setAllAnnotationData');
});
}
// -
function hideThisAnnotation(value) {
setNowShowAnnotationData({
...value,
state: 1,
});
UpdateAnnotation({
...value,
properties: JSON.stringify(value.properties),
state: 1,
}).then((res) => {
emits('setAllAnnotationData');
});
}
// -------------------------------------------------
@ -519,12 +559,7 @@
});
UpdateWorkArea({
...value,
// id: value.id,
// name: value.name,
// type: value.type,
properties: JSON.stringify(value.properties),
// geom: value.geom,
// workSpaceId: '1',
state: 0,
}).then((res) => {
emits('setAllAreaData');
@ -537,13 +572,8 @@
state: 1,
});
UpdateWorkArea({
// id: value.id,
// name: value.name,
// type: value.type,
...value,
properties: JSON.stringify(value.properties),
// geom: value.geom,
// workSpaceId: '1',
state: 1,
}).then((res) => {
emits('setAllAreaData');
@ -555,8 +585,8 @@
}
//
function setNowShowMarkData(value) {
emits('setNowShowMarkData', value);
function setNowShowAnnotationData(value) {
emits('setNowShowAnnotationData', value);
}
//
function setNowShowImageData(value) {
@ -689,7 +719,7 @@
padding-bottom: 5px;
gap: 10px;
.leftMenu_buttonList_mark {
.leftMenu_buttonList_annotation {
position: relative;
border-radius: 5px;
height: 40px;
@ -739,7 +769,7 @@
max-height: 800px;
//
.showMenuInfo_mark {
.showMenuInfo_annotation {
position: relative;
display: flex;
align-items: center;

File diff suppressed because it is too large Load Diff

@ -39,7 +39,7 @@ const flyToTherePosition = ref({
const flyToThere = (e)=>{
console.log(e);
}
const planListShow = ref(true);
const workPlanFormShow = ref(false);

@ -158,7 +158,7 @@
setTimeout(() => {
uavLive.value = true;
livePreviewVisible.value = true;
}, 2000);
}, 5000);
}
};
const loadLiveStreaming = () => {

@ -154,8 +154,10 @@
};
//
onBeforeUnmount(() => {
player.dispose();
player = null;
if(player){
player.dispose();
player = null;
}
});
</script>
<style lang="less" scoped>

@ -1,13 +1,6 @@
<template>
<VueDragResize
:w="width"
:h="height"
:x="left"
:y="top"
:isActive="true"
:parentLimitation="true"
:isResizable="false"
>
<VueDragResize :w="width" :h="height" :x="left" :y="top" :isActive="true" :parentLimitation="true"
:isResizable="false">
<div class="flight-control" v-if="airportVal" v-drag>
<div class="title">
<div>
@ -31,89 +24,64 @@
<!-- <a-button>智能环绕</a-button> -->
<a-button @click="returnVoyage"></a-button>
<a-button @click="obtain" style="background-color: #1b71e8; border: none">
<template #icon v-if="flightGrab"><CheckOutlined /></template>
<template #icon v-if="flightGrab">
<CheckOutlined />
</template>
获取飞行器控制权
</a-button>
<a-button @click="enterDRC" style="background-color: #24d365; border: none">
<template #icon v-if="modeEnter"><CheckOutlined /></template>
<template #icon v-if="modeEnter">
<CheckOutlined />
</template>
进入飞行控制
</a-button>
<a-button @click="exitDRC" style="background-color: #e3150e; border: none"
>退出飞行控制</a-button
>
<a-button @click="exitDRC" style="background-color: #e3150e; border: none">退出飞行控制</a-button>
</div>
<div class="content-info">
<div class="info-item">
<!-- <img src="@/assets/images/flightoperation/flight_control.png" alt="" /> -->
<div class="info-item-top" title="上升" @click="changeDRC('throttle', 'up', '上升')">
<img
src="@/assets/images/flightoperation/top-active.png"
alt=""
v-if="selectName == '上升'"
/>
<div class="info-item-top" title="上升" @mousedown="changeDRC('throttle', 'up', '上升')"
@mouseup="changeDRC('throttle', 'up', '')">
<img src="@/assets/images/flightoperation/top-active.png" alt="" v-if="selectName == ''" />
<img src="@/assets/images/flightoperation/top.png" alt="" v-else />
</div>
<div class="info-item-right" title="右旋转" @click="changeDRC('yaw', 'up', '右旋转')">
<img
src="@/assets/images/flightoperation/right-active.png"
alt=""
v-if="selectName == '右旋转'"
/>
<div class="info-item-right" title="右旋转" @mousedown="changeDRC('yaw', 'up', '右旋转')"
@mouseup="changeDRC('yaw', 'up', '')">
<img src="@/assets/images/flightoperation/right-active.png" alt="" v-if="selectName == ''" />
<img src="@/assets/images/flightoperation/right.png" alt="" v-else />
</div>
<div
class="info-item-bottom"
title="下降"
@click="changeDRC('throttle', 'down', '下降')"
>
<img
src="@/assets/images/flightoperation/bottom-active.png"
alt=""
v-if="selectName == '下降'"
/>
<div class="info-item-bottom" title="下降" @mousedown="changeDRC('throttle', 'down', '下降')"
@mouseup="changeDRC('throttle', 'down', '')">
<img src="@/assets/images/flightoperation/bottom-active.png" alt="" v-if="selectName == ''" />
<img src="@/assets/images/flightoperation/bottom.png" alt="" v-else />
</div>
<div class="info-item-left" title="左旋转" @click="changeDRC('yaw', 'down', '左旋转')">
<img
src="@/assets/images/flightoperation/left-active.png"
alt=""
v-if="selectName == '左旋转'"
/>
<div class="info-item-left" title="左旋转" @mousedown="changeDRC('yaw', 'down', '左旋转')"
@mouseup="changeDRC('yaw', 'down', '')">
<img src="@/assets/images/flightoperation/left-active.png" alt="" v-if="selectName == ''" />
<img src="@/assets/images/flightoperation/left.png" alt="" v-else />
</div>
</div>
<div class="info-item">
<!-- <img src="@/assets/images/flightoperation/flight_control.png" alt="" /> -->
<div class="info-item-top" title="前进" @click="changeDRC('pitch', 'up', '前进')">
<img
src="@/assets/images/flightoperation/top-active.png"
alt=""
v-if="selectName == '前进'"
/>
<div class="info-item-top" title="前进"
@mousedown="changeDRC('pitch', 'up', '前进')" @mouseup="changeDRC('pitch', 'up', '')">
<img src="@/assets/images/flightoperation/top-active.png" alt=""
v-if="selectName == '前进'" />
<img src="@/assets/images/flightoperation/top.png" alt="" v-else />
</div>
<div class="info-item-right" title="右移" @click="changeDRC('roll', 'up', '右移')">
<img
src="@/assets/images/flightoperation/right-active.png"
alt=""
v-if="selectName == '右移'"
/>
<div class="info-item-right" title="右移"
@mousedown="changeDRC('roll', 'up', '右移')" @mouseup="changeDRC('roll', 'up', '')">
<img src="@/assets/images/flightoperation/right-active.png" alt="" v-if="selectName == ''" />
<img src="@/assets/images/flightoperation/right.png" alt="" v-else />
</div>
<div class="info-item-bottom" title="后退" @click="changeDRC('pitch', 'down', '后退')">
<img
src="@/assets/images/flightoperation/bottom-active.png"
alt=""
v-if="selectName == '后退'"
/>
<div class="info-item-bottom" title="后退"
@mousedown="changeDRC('pitch', 'down', '后退')" @mouseup="changeDRC('pitch', 'down', '')">
<img src="@/assets/images/flightoperation/bottom-active.png" alt="" v-if="selectName == '退'" />
<img src="@/assets/images/flightoperation/bottom.png" alt="" v-else />
</div>
<div class="info-item-left" title="左移" @click="changeDRC('roll', 'down', '左移')">
<img
src="@/assets/images/flightoperation/left-active.png"
alt=""
v-if="selectName == '左移'"
/>
<div class="info-item-left" title="左移"
@mousedown="changeDRC('roll', 'down', '左移')" @mouseup="changeDRC('roll', 'down', '')">
<img src="@/assets/images/flightoperation/left-active.png" alt="" v-if="selectName == ''" />
<img src="@/assets/images/flightoperation/left.png" alt="" v-else />
</div>
</div>
@ -123,412 +91,467 @@
</VueDragResize>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, reactive, onUnmounted } from 'vue';
import {
getClient,
createSeizeConnection,
destroySeizeConnection,
connection,
} from '@/utils/mqtt';
import { CloseOutlined, CheckOutlined } from '@ant-design/icons-vue';
import { vDrag } from '@/utils/drag';
import { drcDownTopicReize, eventsTopicSubscribeReize } from '@/utils/debugging/events';
import {
servicesTopic,
services_replyTopic,
drcDownTopic,
eventsTopicSubscribe,
drcUpTopic,
errorName,
} from '@/utils/debugging/remote';
import { buildGUID } from '@/utils/uuid';
import { useMessage } from '@/hooks/web/useMessage';
import {
getRedisUser,
addOrUpdateRedisUser,
getLockedClients,
} from '@/api/workmanagement/airportMaintenance';
import { useUserStore } from '@/store/modules/user';
import { timestampToFormattedDate } from '@/utils/index';
import VueDragResize from 'vue-drag-resize/src';
import { airPortStore } from '@/store/modules/airport';
import { onMounted, ref, watch, reactive, onUnmounted } from 'vue';
import {
getClient,
createSeizeConnection,
destroySeizeConnection,
connection,
} from '@/utils/mqtt';
import { CloseOutlined, CheckOutlined } from '@ant-design/icons-vue';
import { vDrag } from '@/utils/drag';
import { drcDownTopicReize, eventsTopicSubscribeReize } from '@/utils/debugging/events';
import {
servicesTopic,
services_replyTopic,
drcDownTopic,
eventsTopicSubscribe,
drcUpTopic,
errorName,
} from '@/utils/debugging/remote';
import { buildGUID } from '@/utils/uuid';
import { useMessage } from '@/hooks/web/useMessage';
import {
getRedisUser,
addOrUpdateRedisUser,
getLockedClients,
} from '@/api/workmanagement/airportMaintenance';
import { useUserStore } from '@/store/modules/user';
import { timestampToFormattedDate } from '@/utils/index';
import VueDragResize from 'vue-drag-resize/src';
import { airPortStore } from '@/store/modules/airport';
const airPortStoreVal = airPortStore();
const uav = airPortStoreVal.getUAV;
const airPortStoreVal = airPortStore();
const uav = airPortStoreVal.getUAV;
const width = ref(380);
const height = ref(390);
const left = ref(700);
const top = ref(100);
const userStore = useUserStore();
const userInfo = userStore.getUserInfo;
const redisUser = ref({});
const { createMessage } = useMessage();
const emits = defineEmits(['changeFlightControl', 'clickTakeOff', 'clickFlyTo']);
const monitorDRC = ref(false);
//
const flightGrab = ref(false);
//
const modeEnter = ref(false);
const airportVal: any = ref({
mode_code: 0,
});
const selectName = ref('');
const bid = buildGUID();
//redis
const changeRedisUser = (val: boolean) => {
const querys = redisUser.value;
querys.isLock = val;
querys.connectTime = timestampToFormattedDate(new Date().getTime());
addOrUpdateRedisUser(querys);
};
const isLocked = ref(false);
// redis
const lockedClient = () => {
getLockedClients().then((res) => {
if (res.length > 0) {
res.forEach((item, index) => {
if (item.userId != userInfo.id) {
isLocked.value = true;
}
});
}
});
};
//
const takeOff = () => {
if (isLocked.value) {
createMessage.warning('当前有用户正在操作,请稍后再试');
return;
const width = ref(380);
const height = ref(390);
const left = ref(700);
const top = ref(100);
const userStore = useUserStore();
const userInfo = userStore.getUserInfo;
const redisUser = ref({});
const { createMessage } = useMessage();
const emits = defineEmits(['changeFlightControl', 'clickTakeOff', 'clickFlyTo']);
const monitorDRC = ref(false);
//
const flightGrab = ref(false);
//
const modeEnter = ref(false);
const airportVal: any = ref({
mode_code: 0,
});
const selectName = ref('');
const bid = buildGUID();
//redis
const changeRedisUser = (val: boolean) => {
const querys = redisUser.value;
querys.isLock = val;
querys.connectTime = timestampToFormattedDate(new Date().getTime());
addOrUpdateRedisUser(querys);
};
const isLocked = ref(false);
// redis
const lockedClient = () => {
getLockedClients().then((res) => {
if (res.length > 0) {
res.forEach((item, index) => {
if (item.userId != userInfo.id) {
isLocked.value = true;
}
});
}
});
};
//
const takeOff = () => {
if (isLocked.value) {
createMessage.warning('当前有用户正在操作,请稍后再试');
return;
}
emits('clickTakeOff');
changeRedisUser(true);
};
//
const obtain = () => {
// if (!getClient()) {
// createConnection();
// }
if (isLocked.value) {
createMessage.warning('当前有用户正在操作,请稍后再试');
return;
}
if (flightGrab.value) {
createMessage.warning('已经获取了飞行器控制权');
return;
}
createMessage.info('正在获取飞行器控制权,请稍候');
changeRedisUser(true);
//
servicesTopic({
bid: bid,
method: 'flight_authority_grab',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {},
});
//
servicesTopic({
bid: bid,
method: 'payload_authority_grab',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
payload_index: uav.camera_index,
},
});
services_replyTopic();
};
//
const returnBtn = ref(false);
const returnVoyage = () => {
if (returnBtn.value) {
createMessage.warning('正在返航或已返航,请勿重复操作');
emits('clickTakeOff');
changeRedisUser(true);
};
//
const obtain = () => {
// if (!getClient()) {
// createConnection();
// }
if (isLocked.value) {
createMessage.warning('当前有用户正在操作,请稍后再试');
return;
}
if (flightGrab.value) {
createMessage.warning('已经获取了飞行器控制权');
return;
}
createMessage.info('正在获取飞行器控制权,请稍候');
changeRedisUser(true);
//
servicesTopic({
bid: bid,
method: 'flight_authority_grab',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {},
});
//
servicesTopic({
bid: bid,
method: 'payload_authority_grab',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
payload_index: uav.camera_index,
},
});
services_replyTopic();
};
//
const returnBtn = ref(false);
const returnVoyage = () => {
if (returnBtn.value) {
createMessage.warning('正在返航或已返航,请勿重复操作');
return;
}
returnBtn.value = true;
servicesTopic({
bid: buildGUID(),
method: 'return_home',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {},
});
};
const seq = ref(1);
const longPressTimer = ref();
const longPressInterval = ref();
const longPressDuration = ref(1000);//
const changeDRC = (type, value, name) => {
selectName.value = name;
if (name !== '') {
console.log('鼠标按下');
if (!flightGrab.value) {
createMessage.warning('请先获取飞行器控制权');
return;
}
returnBtn.value = true;
servicesTopic({
bid: buildGUID(),
method: 'return_home',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {},
});
};
const seq = ref(1);
const changeDRC = (type, value, name) => {
selectName.value = name;
setTimeout(() => {
selectName.value = '';
}, 2000);
if (!modeEnter.value) {
createMessage.warning('请先进入指令飞行控制');
return;
}
createMessage.info(name + '指令已发送');
seq.value = seq.value + 1;
let data = {
roll: 1024,
pitch: 1024,
throttle: 1024,
yaw: 1024,
gimbal_pitch: 1024,
};
if (value == 'up') {
data[type] = 1684;
} else {
data[type] = 364;
let isLongPress = false;
longPressTimer.value = setTimeout(() => {
console.log('长按事件触发!');
isLongPress = true;
longPressInterval.value = setInterval(() => {
seq.value = seq.value + 1;
let querys = getDRCFlightQuery(type, value, seq);
drcDownTopicReize(querys);
createMessage.info(name + '指令已发送');
}, 1000)
}, longPressDuration.value);
if (isLongPress) {
isLongPress = false;
return;
}
const querys = {
seq: seq.value,
method: 'stick_control',
data: data,
bid: buildGUID(),
tid: buildGUID(),
timestamp: new Date().getTime(),
};
seq.value = seq.value + 1;
let querys = getDRCFlightQuery(type, value, seq);
drcDownTopicReize(querys);
};
const drcSeq = ref(1);
const enterDRC = () => {
if (!flightGrab.value) {
createMessage.warning('请先获取飞行控制权');
return;
createMessage.info(name + '指令已发送');
} else {
if (longPressTimer.value) {
clearTimeout(longPressTimer.value);
longPressTimer.value = null;
console.log('清除延时器');
}
createSeizeConnection();
createMessage.info('正在进入飞行控制,请稍后');
//
const { protocol, host, port, endpoint } = connection;
const connectUrl = `${protocol}://${host}:${port}${endpoint}`;
const querys = {
bid: bid,
data: {
hsi_frequency: 10,
mqtt_broker: {
address: connectUrl,
// client_id: 'mqtt_client_1581F8HGX254V00A0BUY',
client_id: 'mqtt_client_1581F8HGX254V00A0BUYSeize',
enable_tls: false,
expire_time: 3600,
password: '',
username: 'sdhc',
},
osd_frequency: 5,
},
tid: buildGUID(),
timestamp: new Date().getTime(),
method: 'drc_mode_enter',
};
servicesTopic(querys);
drc_eart_beat();
drcUpTopic();
if (longPressInterval.value) {
clearTimeout(longPressInterval.value);
longPressInterval.value = null;
console.log('清除定时器');
}
console.log('鼠标松开');
}
};
const getDRCFlightQuery = (type, value, seq) => {
let data = {
roll: 1024,
pitch: 1024,
throttle: 1024,
yaw: 1024,
gimbal_pitch: 1024,
};
let timer;
const drc_eart_beat = () => {
monitorDRC.value = true;
// drc
timer = window.setInterval(() => {
drcSeq.value = drcSeq.value + 1;
const drcQuerys = {
bid: buildGUID(),
tid: buildGUID(),
timestamp: new Date().getTime(),
method: 'heart_beat',
data: {
timestamp: new Date().getTime(),
},
seq: drcSeq.value,
};
drcDownTopic(drcQuerys);
}, 5000);
// drc
eventsTopicSubscribe();
if (value == 'up') {
data[type] = 1684;
} else {
data[type] = 364;
}
const querys = {
seq: seq.value,
method: 'stick_control',
data: data,
bid: buildGUID(),
tid: buildGUID(),
timestamp: new Date().getTime(),
};
console.log(querys);
return querys;
};
const drcSeq = ref(1);
const enterDRC = () => {
if (!flightGrab.value) {
createMessage.warning('请先获取飞行控制权');
return;
}
createSeizeConnection();
createMessage.info('正在进入飞行控制,请稍后');
//
const { protocol, host, port, endpoint } = connection;
const connectUrl = `${protocol}://${host}:${port}${endpoint}`;
const querys = {
bid: bid,
data: {
hsi_frequency: 10,
mqtt_broker: {
address: connectUrl,
// client_id: 'mqtt_client_1581F8HGX254V00A0BUY',
client_id: 'mqtt_client_1581F8HGX254V00A0BUYSeize',
enable_tls: false,
expire_time: 3600,
password: '',
username: 'sdhc',
},
osd_frequency: 5,
},
tid: buildGUID(),
timestamp: new Date().getTime(),
method: 'drc_mode_enter',
};
const exitDRC = () => {
createMessage.info('正在退出飞行控制,请稍后');
const querys = {
bid: bid,
data: {},
servicesTopic(querys);
drc_eart_beat();
drcUpTopic();
};
let timer;
const drc_eart_beat = () => {
monitorDRC.value = true;
// drc
timer = window.setInterval(() => {
drcSeq.value = drcSeq.value + 1;
const drcQuerys = {
bid: buildGUID(),
tid: buildGUID(),
timestamp: new Date().getTime(),
method: 'drc_mode_exit',
method: 'heart_beat',
data: {
timestamp: new Date().getTime(),
},
seq: drcSeq.value,
};
servicesTopic(querys);
drcDownTopic(drcQuerys);
}, 5000);
// drc
eventsTopicSubscribe();
};
const exitDRC = () => {
createMessage.info('正在退出飞行控制,请稍后');
const querys = {
bid: bid,
data: {},
tid: buildGUID(),
timestamp: new Date().getTime(),
method: 'drc_mode_exit',
};
onMounted(() => {
// mqtt
getRedisUser(userInfo.id).then((res) => {
if (res) {
redisUser.value = res;
}
});
lockedClient();
// //
getClient().on('message', (topic, message) => {
const rs = JSON.parse(message);
if (rs.data.mode_code || rs.data.mode_code == 0) {
airportVal.value.mode_code = rs.data.mode_code;
}
if (rs.method == 'flight_authority_grab' && rs.bid == bid) {
if (rs.data.result == 0) {
flightGrab.value = true;
createMessage.success('飞行控制权抢夺成功');
} else {
flightGrab.value = false;
createMessage.error('飞行控制权抢夺失败,' + errorName(rs.data.result));
}
servicesTopic(querys);
};
onMounted(() => {
// mqtt
getRedisUser(userInfo.id).then((res) => {
if (res) {
redisUser.value = res;
}
});
lockedClient();
// //
getClient().on('message', (topic, message) => {
const rs = JSON.parse(message);
if (rs.data.mode_code || rs.data.mode_code == 0) {
airportVal.value.mode_code = rs.data.mode_code;
}
if (rs.method == 'flight_authority_grab' && rs.bid == bid) {
if (rs.data.result == 0) {
flightGrab.value = true;
createMessage.success('飞行控制权抢夺成功');
} else {
flightGrab.value = false;
createMessage.error('飞行控制权抢夺失败,' + errorName(rs.data.result));
}
if (rs.method == 'drc_mode_enter' && rs.bid == bid) {
if (rs.data.result == 0) {
modeEnter.value = true;
createMessage.success('进入指令飞行控制模式成功');
} else {
modeEnter.value = false;
createMessage.error('进入指令飞行控制模式失败,' + errorName(rs.data.result));
}
}
if (rs.method == 'drc_mode_enter' && rs.bid == bid) {
if (rs.data.result == 0) {
modeEnter.value = true;
createMessage.success('进入指令飞行控制模式成功');
} else {
modeEnter.value = false;
createMessage.error('进入指令飞行控制模式失败,' + errorName(rs.data.result));
}
if (rs.method == 'drc_mode_exit' && rs.bid == bid) {
if (rs.data.result == 0) {
modeEnter.value = false;
createMessage.success('退出指令飞行控制模式成功');
changeRedisUser(false);
} else {
createMessage.error('退出指令飞行控制模式失败,' + errorName(rs.data.result));
}
}
if (rs.method == 'drc_mode_exit' && rs.bid == bid) {
if (rs.data.result == 0) {
modeEnter.value = false;
createMessage.success('退出指令飞行控制模式成功');
changeRedisUser(false);
} else {
createMessage.error('退出指令飞行控制模式失败,' + errorName(rs.data.result));
}
//
if (rs.method === 'return_home') {
if (rs.data.result == 0) {
createMessage.success('一键返航成功');
monitorDRC.value = false;
returnBtn.value = true;
} else {
createMessage.error('一键返航失败,' + errorName(rs.data.result));
returnBtn.value = false;
}
}
//
if (rs.method === 'return_home') {
if (rs.data.result == 0) {
createMessage.success('一键返航成功');
monitorDRC.value = false;
returnBtn.value = true;
} else {
createMessage.error('一键返航失败,' + errorName(rs.data.result));
returnBtn.value = false;
}
if (rs.method === 'takeoff_to_point') {
if (rs.data.result == 0) {
createMessage.success('一键起飞成功');
} else {
createMessage.error('一键起飞失败,' + errorName(rs.data.result));
}
}
if (rs.method === 'takeoff_to_point') {
if (rs.data.result == 0) {
createMessage.success('一键起飞成功');
} else {
createMessage.error('一键起飞失败,' + errorName(rs.data.result));
}
if (rs.method === 'drc_status_notify' && monitorDRC.value) {
if (rs.data.result == 0) {
if (rs.data.drc_state == 0) {
drc_eart_beat();
}
} else {
}
if (rs.method === 'drc_status_notify' && monitorDRC.value) {
if (rs.data.result == 0) {
if (rs.data.drc_state == 0) {
drc_eart_beat();
createMessage.error('DRC连接失败' + errorName(rs.data.result));
}
} else {
drc_eart_beat();
createMessage.error('DRC连接失败' + errorName(rs.data.result));
}
//
if (rs.method == 'fly_to_point') {
if (rs.data.result == 0) {
createMessage.success('指点飞行成功');
} else {
createMessage.error('指点飞行失败,' + errorName(rs.data.result));
}
}
//
if (rs.method == 'fly_to_point') {
if (rs.data.result == 0) {
createMessage.success('指点飞行成功');
} else {
createMessage.error('指点飞行失败,' + errorName(rs.data.result));
}
});
});
onUnmounted(() => {
window.clearInterval(timer);
destroySeizeConnection();
changeRedisUser(false);
monitorDRC.value = false;
}
});
});
onUnmounted(() => {
window.clearInterval(timer);
destroySeizeConnection();
changeRedisUser(false);
monitorDRC.value = false;
});
</script>
<style lang="less" scoped>
.flight-control {
width: 96%;
height: 98%;
padding: 10px 20px;
margin: 10px 0 0 10px;
background: #0d0e15;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
border-radius: 6px;
backdrop-filter: blur(3px);
color: #fff;
.title {
width: 100%;
padding: 10px 0;
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-bottom: 1px solid #4e5778;
display: flex;
align-items: center;
justify-content: space-between;
i {
color: #f2762d;
font-style: normal;
}
div {
color: #fff;
cursor: pointer;
}
.flight-control {
width: 96%;
height: 98%;
padding: 10px 20px;
margin: 10px 0 0 10px;
background: #0d0e15;
box-shadow:
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
border-radius: 6px;
backdrop-filter: blur(3px);
color: #fff;
.title {
width: 100%;
padding: 10px 0;
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-bottom: 1px solid #4e5778;
display: flex;
align-items: center;
justify-content: space-between;
i {
color: #f2762d;
font-style: normal;
}
.content-item {
display: flex;
align-items: center;
border-bottom: 1px solid #4e5778;
padding: 10px 0;
div {
color: #fff;
cursor: pointer;
}
.content-button {
margin-top: 10px;
button {
background: none;
margin: 10px 0 0 10px;
color: #fff;
}
}
.content-item {
display: flex;
align-items: center;
border-bottom: 1px solid #4e5778;
padding: 10px 0;
}
.content-button {
margin-top: 10px;
button {
background: none;
margin: 10px 0 0 10px;
color: #fff;
}
.content-info {
display: flex;
align-items: center;
justify-content: space-between;
.info-item {
position: relative;
width: 48%;
height: 116px;
margin: 24px 0 20px 20px;
}
.content-info {
display: flex;
align-items: center;
justify-content: space-between;
.info-item {
position: relative;
width: 48%;
height: 116px;
margin: 24px 0 20px 20px;
img {
width: 36px;
}
.info-item-top {
position: absolute;
top: 8px;
left: 20px;
cursor: pointer;
img {
width: 36px;
width: 62px;
}
.info-item-top {
position: absolute;
top: 8px;
left: 20px;
cursor: pointer;
img {
width: 62px;
}
}
.info-item-right {
position: absolute;
top: 30px;
right: 36px;
cursor: pointer;
}
.info-item-bottom {
position: absolute;
bottom: 0px;
left: 21px;
cursor: pointer;
img {
width: 62px;
}
}
.info-item-left {
position: absolute;
top: 30px;
left: -2px;
cursor: pointer;
}
.info-item-right {
position: absolute;
top: 30px;
right: 36px;
cursor: pointer;
}
.info-item-bottom {
position: absolute;
bottom: 0px;
left: 21px;
cursor: pointer;
img {
width: 62px;
}
}
.info-item-left {
position: absolute;
top: 30px;
left: -2px;
cursor: pointer;
}
}
}
}
</style>

@ -286,8 +286,10 @@
};
//
onBeforeUnmount(() => {
player.dispose();
player = null;
if(player){
player.dispose();
player = null;
}
});
</script>
<style lang="less" scoped>

@ -261,14 +261,15 @@
let data = {
payload_index: uav.camera_index,
locked: true,
pitch_speed: 8,
yaw_speed: 8,
pitch_speed: 0,
yaw_speed: 0,
};
if (val == 'up') {
data[type] = 8;
} else {
data[type] = -8;
}
console.log('data', data);
//
servicesTopicReize({
bid: buildGUID(),

@ -67,7 +67,12 @@
value: item.Id,
};
});
selectVal.project = optionsArr.projectOptions[0].value;
if(sessionStorage.getItem('homeToFlightId')){
selectVal.project = sessionStorage.getItem('homeToFlightId');
sessionStorage.removeItem('homeToFlightId')
} else {
selectVal.project = optionsArr.projectOptions[0].value;
}
getAirPort(selectVal.project);
} else {
optionsArr.projectOptions = [];

@ -10,7 +10,7 @@
<div class="interval"></div>
<div class="list">
<div v-for="item in projectList">
<div :class="`project-list-item ${activeProject == item.Id? 'active': ''}`" @click="selectProject(item)">
<div :class="`project-list-item ${props.activeProject == item.Id? 'active': ''}`" @click="selectProject(item)">
<div style="display: flex;align-items: center;">
<div class="list-item-icon"></div>
<div class="list-item-content">{{ item.WorkspaceName }}</div>
@ -36,23 +36,40 @@ import { ref, defineProps, onMounted, createVNode } from "vue"
import { GetWorkspaceList, GetWorkSpaceById, DeleteWorkspace } from '@/api/demo/projecthome'
import { message, Modal } from 'ant-design-vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
import { getClient, createConnection, clientSubscribe, destroyConnection } from '@/utils/mqtt';
onMounted(() => {
getProjectList()
})
const props = defineProps(['map'])
const props = defineProps(['map', 'activeProject', 'airPort'])
const emits = defineEmits(['update:activeProject'])
const addModal = ref(false)
const modalType = ref('')
const projectList = ref([])
const activeProject = ref('')
const updateProject = ref({})
const lastSubscriptUrl = ref('')
const addProject = () => {
modalType.value = 'insert'
addModal.value = true
}
const selectProject = (item) => {
activeProject.value = item.Id
if(props.activeProject != item.Id){
props.airPort.latitude = null
props.airPort.longitude = null
getClient().unsubscribe(lastSubscriptUrl.value,(error, res) => {})
}
emits('update:activeProject',item.Id)
let params = {
id: item.Id
}
GetWorkSpaceById(params).then(res => {
res.lasaDronePort.forEach(item => {
const topicUrl = 'thing/product/' + item.sn + '/osd';
lastSubscriptUrl.value = topicUrl
clientSubscribe(topicUrl, { qos: 0 });
})
})
}
const getProjectList = () => {
GetWorkspaceList().then(res => {

@ -1,11 +1,11 @@
<template>
<div class="home-page">
<div style="width: 100%;height: calc(100vh - 80px);">
<Map @mapOnLoad="mapOnLoad"/>
<Map :airRoute="airRoute" @mapOnLoad="mapOnLoad" :airPort="airPort" @clickAirPort="clickAirPort"/>
</div>
<div ref="leftComponentRef" style="position: absolute;top: 0px;left: 0px;">
<!-- 项目列表 -->
<ProjectList :map="map"/>
<ProjectList :map="map" v-model:activeProject="activeProject" :airPort="airPort"/>
<!-- 基本信息 -->
<Info />
</div>
@ -19,20 +19,40 @@
</template>
<script setup lang="ts">
// import Map from '@/views/demo/workmanagement/workplan/components/map.vue'
import Map from './Map/index.vue'
import Map from '@/views/demo/workmanagement/workplan/components/map.vue'
// import Map from './Map/index.vue'
import ProjectList from './ProjectList/index.vue'
import Info from './Info/index.vue'
import Inspection from './Inspection/index.vue'
import Result from './Result/index.vue'
import { ref, onMounted, onBeforeUnmount, } from "vue"
import { getClient, createConnection, clientSubscribe, destroyConnection } from '@/utils/mqtt';
import { useRouter } from 'vue-router';
const router = useRouter();
const airRoute = ref({
airLineType: null,
airType: null,
airModel: null,
name: null,
});
const airPort = ref({
latitude: null,
longitude: null,
});
const activeProject = ref('')
const DESIGN_WIDTH = 1912
const DESIGN_HEIGHT = 962
const leftComponentRef = ref<HTMLElement | null>(null)
const rightComponentRef = ref<HTMLElement | null>(null)
let map
const map = ref()
const clickAirPort = () => {
sessionStorage.setItem('homeToFlightId', activeProject.value);
router.push({
path: '/workmanagement/flightoperation',
});
}
function updateScale() {
const scaleX = window.innerWidth / DESIGN_WIDTH
const scaleY = window.innerHeight / DESIGN_HEIGHT
@ -47,16 +67,28 @@ function updateScale() {
right.style.transform = `scale(${scale}) translate(-50%, -50%)`
}
}
const connectionCallback = () => {
getClient().on('message', (topic, msg) => {
if (topic.endsWith("osd")) {
const rs = JSON.parse(msg)
if (rs.data.latitude && rs.data.longitude) {
airPort.value.latitude = rs.data.latitude;
airPort.value.longitude = rs.data.longitude;
}
}
});
}
onMounted(() => {
createConnection(connectionCallback)
updateScale()
window.addEventListener('resize', updateScale)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', updateScale)
destroyConnection()
})
const mapOnLoad = (value) => {
map = value
map.value = value
}
</script>

@ -1,7 +1,7 @@
<template>
<div class="container">
<div class="title">
<LeftOutlined @click="checkAriLine(null)" v-show="props.title=='线'" /> {{props.title}}
<div class="title" @click="closeAirLine()">
<LeftOutlined v-show="props.title=='线'" /> {{props.title}}
</div>
<div class="filter-container">
@ -188,7 +188,7 @@
import { getAirLineList,uploadXmlFile,deleteAirLine,addAirLine} from '@/api/sys/workplan';
import { Modal, message } from 'ant-design-vue';
const emit = defineEmits(["checkAriLine","createAirLine","previewAirLine"])
const emit = defineEmits(["checkAriLine","createAirLine","previewAirLine","closeAirLine"])
const props = defineProps(["title"])
@ -199,6 +199,11 @@
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
// 线
const closeAirLine = () => {
emit("closeAirLine");
}
//
const importAirLineShow = ref(false);
const fileList = ref([]);
@ -405,6 +410,7 @@
.title{
padding:15px;
color:#fff;
cursor:pointer;
}
.filter-container{
padding:0px 15px;
@ -436,7 +442,7 @@
display:flex;
font-size:14px;
border-top:1px solid rgba(204, 204, 204, 0.219) ;
height: 100%;
height: calc( 100% - 120px);
}
.file-container{

@ -1,6 +1,6 @@
<template>
<div>
<div class="title">
<div class="container">
<div class="title" @click="closeAirCraft()">
<div style="flex:1;">
<LeftOutlined @click="checkAriLine(null);"/> &nbsp; 选择飞行器
</div>
@ -50,12 +50,16 @@
import {ref,defineEmits} from 'vue'
import { getUavPageList,getPortList } from '@/api/sys/workplan';
const emit = defineEmits(["checkAriLine"])
const emit = defineEmits(["checkAriLine","closeAirCraft"])
const checkAriLine = (item)=> {
emit("checkAriLine",item);
}
const closeAirCraft = () => {
emit("closeAirCraft");
}
const ariLineList = ref([])
const pageQuery = ref({
@ -73,11 +77,19 @@
</script>
<style scoped>
.container{
width:100%;
height:100%;
background: #0D0E15;
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15), 0px 10px 30px 1px rgba(0,0,6,0.15), inset 0px 0px 20px 8px rgba(58,87,232,0.73);
border-radius: 6px;
}
.title{
padding:15px;
color:#fff;
font-size:14px;
display:flex;
cursor:pointer;
}
.filter-container{
padding:0px 15px;
@ -138,13 +150,15 @@
flex:1;
}
.ari-line{
background:#3F4150;
color:#fff;
padding:5px 10px;
margin-bottom:10px;
position:relative;
font-size: 13px;
border-radius: 3px;
background: linear-gradient( 132deg, #323D62 0%, #525F83 100%);
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
border-radius: 10px;
}
.ari-line::before{

@ -39,8 +39,8 @@
<div class="select-item" v-show="submitForm.airLineId">
<div class="item-name">{{submitForm.taskAirLineName}}</div>
<div class="item-operate">
<MoreOutlined @click="selectAriLine"/>
<div class="item-operate" @click="selectAriLine">
<MoreOutlined />
</div>
</div>
</a-form-item>
@ -53,8 +53,8 @@
<div class="select-item" v-show="submitForm.taskDronePort">
<div class="item-name">{{submitForm.taskDronePortName}}</div>
<div class="item-operate">
<MoreOutlined @click="selectAircraft" />
<div class="item-operate" @click="selectAircraft">
<MoreOutlined />
</div>
</div>
@ -88,6 +88,13 @@
</div>
</a-form-item>
<a-form-item ref="accuracy" label="设置时间" name="accuracy">
<a-button type="primary" @click="handlerSetTime"></a-button>
</a-form-item>
</div>
@ -152,19 +159,51 @@
<a-button style="width:100%;" type="primary" @click="onSubmit"></a-button>
</div>
</div>
<Modal
title="设置时间"
:open="visible"
@ok="handleOk"
@cancel="handleCancel"
footer=""
:destroyOnClose="true"
wrapClassName="v-code-modal"
:width="650"
>
<vue3CronPlus @change="changeCron"
@close="togglePopover(false)"
max-height="400px"
i18n="cn">
</vue3CronPlus>
</Modal>
</div>
</template>
<script lang="ts" setup>
import { ref, defineEmits, defineProps, watch } from "vue";
import { PlusOutlined,LeftOutlined,DeleteOutlined,MoreOutlined } from '@ant-design/icons-vue';
import { addTask,editTask } from "@/api/sys/workplan";
import { Modal, message } from 'ant-design-vue';
import {vue3CronPlus} from 'vue3-cron-plus'
import 'vue3-cron-plus/dist/index.css' //
const formRef = ref();
const labelCol = { span: 24 };
const wrapperCol = { span: 24 };
const props = defineProps(["checkedAriLine","checkedDronePort","formData"]);
const visible = ref(false);
const handleOk = ()=>{
}
const handlerSetTime = ()=>{
visible.value = true;
}
const handleCancel = () => {
visible.value = false
}
// const submitForm = ref({
// taskName:null, //
@ -181,6 +220,9 @@ const props = defineProps(["checkedAriLine","checkedDronePort","formData"]);
// taskAirLineName : null,
// taskDronePortName : null,
// })
const submitForm = ref({
"id": null,
"taskName": null,
@ -356,6 +398,14 @@ const resetForm = () => {
emit("cancleCraete");
formRef.value.resetFields();
};
const changeCron = ()=>{
}
const togglePopover = (e)=> {
}
</script>
<style scoped>
@ -365,7 +415,7 @@ const resetForm = () => {
background: #0D0E15;
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15), 0px 10px 30px 1px rgba(0,0,6,0.15), inset 0px 0px 20px 8px rgba(58,87,232,0.73);
border-radius: 6px;
position:relative;
}
.title{
padding:15px 15px;

@ -148,7 +148,7 @@ const generatePreviewPoint = (placemark)=>{
}
};
const emits = defineEmits(['exitDraw', 'flyToThere']);
const emits = defineEmits(['exitDraw', 'flyToThere', 'mapOnLoad', 'clickAirPort']);
const airPoints = ref([]);
const currentAirPoint = ref({});
@ -199,6 +199,9 @@ const generatePreviewPoint = (placemark)=>{
// 线
let lineGroundPointLayer: mars3d.layer.GraphicLayer;
//
let startGraphic;
let graphic = null;
const exitDraw = () => {
@ -457,6 +460,7 @@ const generatePreviewPoint = (placemark)=>{
}
//
loadChangGuangLayer();
emits('mapOnLoad',map)
});
};
@ -1254,19 +1258,19 @@ const loadChangGuangLayer = ()=>{
let position = mars3d.LngLatPoint.fromCartesian(e.position);
emits('flyToThere', position);
let mark = graphicLayer.getGraphicById('flytothere');
if (mark) {
graphicLayer.removeGraphic(mark);
graphicLayer.removeGraphic(mark);
}
//
const graphic = new mars3d.graphic.BillboardEntity({
id: 'flytothere-uav',
name: '标点',
position: [position._lng, position._lat, position._alt],
position: [position._lng, position._lat, position._alt+80],
style: {
image: '/map/uav-mark.png',
scale: 0.3,
@ -1310,7 +1314,7 @@ const loadChangGuangLayer = ()=>{
let connectLine = new mars3d.graphic.PolylineEntity({
id: 'flytothere-line',
positions: [
[position._lng, position._lat, position._alt],
[position._lng, position._lat, position._alt+80],
[position._lng, position._lat, 0],
],
style: {
@ -1322,6 +1326,10 @@ const loadChangGuangLayer = ()=>{
uavGraphicLayer.addGraphic(graphic);
stickGraphicLayer.addGraphic(stickGraphic);
uavGraphicLayer.addGraphic(connectLine);
//
let flyToPosition = mars3d.LngLatPoint.fromCartesian(graphic.position);
emits('flyToThere', flyToPosition);
};
//
@ -1402,8 +1410,6 @@ const loadChangGuangLayer = ()=>{
const latitude = mars3d.Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height; //
console.log(longitude, latitude, height);
emits('flyToThere', { _lng: longitude, _lat: latitude, _alt: height });
let line = uavGraphicLayer.getGraphicById('flytothere-line');
@ -1544,11 +1550,15 @@ const loadChangGuangLayer = ()=>{
//
const setAirportPosition = async () => {
if(!graphicLayer){
return
}
let point = graphicLayer.getGraphicById('set-airport');
// //
let position = [props.airPort.longitude, props.airPort.latitude, 70];
//
if (point) {
if (startGraphic) {
startGraphic.position = position
// point.setOptions({
// id: 'set-airport',
// name: '',
@ -1571,7 +1581,7 @@ const loadChangGuangLayer = ()=>{
// },
// });
} else {
let startGraphic = new mars3d.graphic.BillboardEntity({
startGraphic = new mars3d.graphic.BillboardEntity({
id: 'set-airport',
position: position,
style: {
@ -1591,9 +1601,13 @@ const loadChangGuangLayer = ()=>{
},
},
});
startGraphic.on(mars3d.EventType.click, function (event) {
emits('clickAirPort')
});
graphicLayer.addGraphic(startGraphic);
}
}
};
//
const setUAVPosition = () => {
let point = graphicLayer.getGraphicById('set-uav');

@ -4,28 +4,47 @@
<Map :workPlanFormShow="workPlanFormShow" :airRoute="airRoute" @exitDraw="exitDraw" @flyToThere="flyToThere" :wayline="wayline" :waylineInfo="waylineInfo"></Map>
</div>
<!-- 工作计划列表 -->
<div v-show="planListShow" style="width:360px;position:absolute;top:20px;left:20px;z-index:1;height: calc( 100vh - 144px);overflow-y:hidden;">
<planList :planListShow="planListShow" @planDetail="planDetail" @createWorkPlan="toCreateWorkPlan" ></planList>
<div style="position:absolute;top:20px;left:20px;z-index:1;display:flex;gap:15px;">
<!-- 工作计划列表 -->
<div v-if="planListShow" style="width:360px;height: calc( 100vh - 144px);flex:1;">
<planList :planListShow="planListShow" @planDetail="planDetail" @createWorkPlan="toCreateWorkPlan" ></planList>
</div>
<!-- 创建计划 -->
<div v-if="workPlanFormShow" style="width:360px;height: calc( 100vh - 144px);flex:1;">
<createWorkPlan :formData="formData" @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort"></createWorkPlan>
</div>
<!-- 航线库 -->
<div v-if="ariLineShow" style="width:566px;height: calc( 100vh - 144px);flex:1;">
<airLineList :title="'选择航线'" @checkAriLine="checkAriLine" @previewAirLine="previewAirLine" @createAirLine="handlerCreateAirLine" @closeAirLine="closeAirLine"></airLineList>
</div>
<!-- 设备 -->
<div v-if="aircraftShow" style="width:340px;height: calc( 100vh - 144px);flex:1;">
<aircraft @checkAriLine="checkDronePort" @closeAirCraft="closeAirCraft" ></aircraft>
</div>
</div>
<!-- 创建计划弹窗 -->
<div v-if="workPlanFormShow" style="width:380px;position:absolute;top:30px;left:30px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<!-- <div v-if="workPlanFormShow" style="width:380px;position:absolute;top:30px;left:30px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<createWorkPlan :formData="formData" @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort"></createWorkPlan>
</div>
</div> -->
<!-- 航线库 -->
<div v-if="ariLineShow" style="width:566px;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<!-- <div v-if="ariLineShow" style="width:566px;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<airLineList :title="'选择航线'" @checkAriLine="checkAriLine" @previewAirLine="previewAirLine" @createAirLine="handlerCreateAirLine"></airLineList>
</div>
</div> -->
<!-- 飞行器 -->
<div v-if="aircraftShow" style="width:340px;background:#0d0e15c1 ;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<!-- <div v-if="aircraftShow" style="width:340px;background:#0d0e15c1 ;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<aircraft @checkAriLine="checkDronePort" ></aircraft>
</div>
</div> -->
<!-- 新建航线 -->
<div v-if="createAirLineShow" style="width:566px;background:#0d0e15c1 ;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<div v-if="createAirLineShow" style="width:566px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<createAirLine @createAirLine="handlerCreateAirRoute" @cancle="cancleCreateAirLine"></createAirLine>
</div>
@ -57,7 +76,7 @@ const flyToTherePosition = ref({
const flyToThere = (e)=>{
console.log(e);
}
const planListShow = ref(true);
const workPlanFormShow = ref(false);
@ -70,6 +89,16 @@ const selectAriLine = ()=> {
aircraftShow.value = false;
}
// 线
const closeAirLine = ()=>{
ariLineShow.value = false;
}
//
const closeAirCraft = ()=>{
aircraftShow.value = false;
}
const selectAircraft = ()=>{
aircraftShow.value = true;
ariLineShow.value = false;

Loading…
Cancel
Save