main
徐景良 2026-02-28 08:16:03 +08:00
parent 70b35ef885
commit cc2a6a4492
73 changed files with 5036 additions and 194 deletions

View File

@ -12,13 +12,24 @@ VITE_BUILD_COMPRESS = 'none'
# Basic interface address SPA
# 天空地项目
VITE_GLOB_API_URL=http://221.2.83.243:6060
VITE_GLOB_INFO_IMAGE_URL=http://221.2.83.243:6060
# .net
VITE_GLOB_API_URL= http://221.2.83.243:6050/core
# java
VITE_GLOB_COFFEE_API_URL = http://221.2.83.243:6050/coffee
# image
VITE_GLOB_INFO_IMAGE_URL= http://221.2.83.243:6050/core
# geoserver
VITE_GLOB_GEOSERVER_BASE_URL = http://221.2.83.243:6050/
# File upload address optional
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=http://221.2.83.243:6060
# file
VITE_GLOB_UPLOAD_URL=http://221.2.83.243:6050/core
# Interface prefix
@ -38,4 +49,4 @@ VITE_GLOB_YINGXIANG_SERVER = http://192.168.31.205:8080/geoserver/ne/wms?service
VITE_GLOB_FILE_PREVIEW = http://120.222.154.7:6081
VITE_GLOB_API_URL_SITUATION = http://123.132.248.154:6033
VITE_GLOB_API_URL_SITUATION = https://wrj.wisestcity.com:6034

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
components/Weather/lei.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
components/Weather/qing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

BIN
components/Weather/wind.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

BIN
components/Weather/wu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

BIN
components/Weather/xue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

BIN
components/Weather/yin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

BIN
components/Weather/yu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

BIN
components/Weather/yun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

View File

@ -85,7 +85,7 @@
"@microsoft/signalr": "^8.0.0",
"@shikijs/monaco": "^1.1.6",
"@terraformer/wkt": "2.1.2",
"@turf/turf": "^7.1.0",
"@turf/turf": "^6.3.0",
"@vben/hooks": "workspace:*",
"@volar/cdn": "~1.11.1",
"@volar/monaco": "~1.11.1",

BIN
packages/mars3d.rar Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -49,6 +49,11 @@ import * as mars3d from "mars3d";
import { option } from '@/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColorRenderChart/barOptions'
import { EventBus } from '@/utils/eventBus';
import { getAppEnvConfig } from '@/utils/env'
var { VITE_GLOB_GEOSERVER_BASE_URL,VITE_GLOB_COFFEE_API_URL } = getAppEnvConfig();
const chartEditStore = useChartEditStore();
let map: mars3d.Map; //
@ -65,10 +70,16 @@ const layers = ref(null)
const handlerLayers:any = ref([]);
const handlerGetLayerTree = ()=>{
axios.get('http://221.2.83.254:9006/applicationMars/getApplicationInfo/feixian').then((res)=>{
axios.get(VITE_GLOB_COFFEE_API_URL+'/applicationMars/getApplicationInfo/feixian',{
headers:{
"X-Token":localStorage.getItem("X-Token")
}
}).then((res)=>{
layers.value = res.data.data
let configLayers = [];
let GEOSERVER_BASE_API = "http://221.2.83.254:9007/";
// let GEOSERVER_BASE_API = "http://221.2.83.254:9007/";
let GEOSERVER_BASE_API = VITE_GLOB_GEOSERVER_BASE_URL;
res.data.data.forEach((item, index) => {
let group:Object;
group = {
@ -220,6 +231,11 @@ const handlerGetLayerTree = ()=>{
attribute.show = attribute.show ? true : false;
attribute.headers = {
'X-Token': localStorage.getItem('X-Token'),
}
layerGroup.children.push(attribute);
});
}

View File

@ -1,9 +1,51 @@
<template>
<div ref="vChartRef" id="mars3d-container" ></div>
<div class="container" style="height:100%;">
<div ref="vChartRef" id="mars3d-container" style="width:100%;height:100%;position:absolute;top:0px;left:0px;"></div>
<div class="add-clue-fire" v-if="frieClueWindowShow">
<div class="title">火情线索
<div class="close-button" @click="cancleFireClue()">
<img src="@/assets/images/chart/tasks/taskclose.png" />
</div>
</div>
<!-- 线索描述 -->
<div class="form-item">
<div class="label">
地址
</div>
<div class="input">
<a-input type="text" v-model:value="fireClueForm.address" placeholder="请输入地址"></a-input>
</div>
</div>
<!-- 线索描述 -->
<div class="form-item">
<div class="label">
描述
</div>
<div class="input">
<a-textarea :rows="5" v-model:value="fireClueForm.describe" placeholder="请输入线索描述" :maxlength="250" />
</div>
</div>
<div class="form-item" style="text-align:right;">
<a-button @click="cancleFireClue()"></a-button>
&nbsp;
<a-button type="primary" @click="addFirClue()"></a-button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, PropType, toRefs, watch,onMounted,nextTick } from 'vue'
import axios from 'axios';
import AMapLoader from '@amap/amap-jsapi-loader'
import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks'
@ -11,12 +53,18 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { MarkerEnum, ThemeEnum } from './config'
import { isArray } from '@/utils'
import { EventBus } from '@/utils/eventBus';
import { getAppEnvConfig } from '@/utils/env';
import * as mars3d from "mars3d";
import * as Cesium from "mars3d-cesium";
import {wgs84ToGcj02} from './lib/CoordinateTransform';
//
import {getWeather,getWindDegree} from './lib/getWeather'
import { option } from '@/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColorRenderChart/barOptions'
let map: mars3d.Map; //
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const props = defineProps({
chartConfig: {
@ -94,8 +142,266 @@ const initMap = (newData: any) => {
handlerInitMeasureTool();
//
handlerInitDrawLayer();
//
window.globalMap.on(mars3d.EventType.load,(event)=>{
// const mapContextmenuItems = [
// {
// text: "",
// show: function (e) {
// return Cesium.defined(e.cartesian);
// },
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// let url =
// "https://restapi.amap.com/v3/geocode/regeo?key=" +
// AppConfigInfo.gaodeApi +
// "&location=" +
// mpt._lng +
// "," +
// mpt._lat +
// "&extensions=base";
// axios({
// method: "get",
// url: url,
// })
// .then((res) => {
// let name = res.data.regeocode.formatted_address;
// this.setDatas = {
// address: name,
// lng: mpt._lng,
// lat: mpt._lat,
// describe: "",
// areaname: localStorage.getItem("areaName"),
// sourceType: 5,
// };
// this.rightType = 1;
// })
// .catch((err) => {
// console.log("ee", err);
// });
// this.setVisibleShow = true;
// },
// },
// {
// text: "",
// show: function (e) {
// return Cesium.defined(e.cartesian)
// },
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian)
// this.tasklng = mpt._lng
// this.tasklat = mpt._lat
// this.taskDeliveryShow = true
// }
// },
// {
// text: "",
// show: function (e) {
// return Cesium.defined(e.cartesian);
// },
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian)
// this.currentInfo = {
// lng: mpt._lng,
// lat: mpt._lat,
// };
// this.aroundIndex = 0
// this.waterVisible = true
// this.goodsVisible = true
// this.barrackVisible = true
// this.endLngLat = [mpt._lng, mpt._lat];
// this.waterCenter = [mpt._lng, mpt._lat];
// this.findsourceShow = true
// this.callCenterVisible = true;
// this.rightDiaVisible = true
// this.toolsShow = true
// this.aroundBoxVisible = true;
// this.diaToggle()
// },
// // children: [
// // {
// // text: "",
// // callback: (e) => {
// // const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// // console.log("aaa", mpt);
// // this.currentInfo = {
// // lng: mpt._lng,
// // lat: mpt._lat,
// // };
// // this.personVisible = true;
// // this.goodsVisible = false;
// // this.waterVisible = false;
// // },
// // },
// // {
// // text: "",
// // callback: (e) => {
// // const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// // this.endLngLat = [mpt._lng, mpt._lat];
// // this.goodsVisible = true;
// // this.waterVisible = false;
// // this.personVisible = false;
// // },
// // },
// // {
// // text: "",
// // callback: (e) => {
// // const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// // this.waterCenter = [mpt._lng, mpt._lat];
// // this.waterVisible = true;
// // this.goodsVisible = false;
// // this.personVisible = false;
// // clearRouterFunc()
// // },
// // },
// // ],
// },
// {
// text: "",
// // show: function (e) {
// // return Cesium.defined(e.cartesian)
// // },
// children: [
// {
// text: "",
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// this.setDatas = {
// title: "",
// lng: mpt._lng,
// lat: mpt._lat,
// iconUrl: "",
// remark: "",
// };
// this.rightType = 3;
// this.setVisibleShow = true;
// },
// },
// {
// text: "",
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// this.setDatas = {
// title: "",
// lng: mpt._lng,
// lat: mpt._lat,
// iconUrl: "",
// remark: "",
// };
// this.rightType = 3;
// this.setVisibleShow = true;
// },
// },
// {
// text: "",
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian);
// this.setDatas = {
// title: "",
// lng: mpt._lng,
// lat: mpt._lat,
// iconUrl: "",
// remark: "",
// };
// this.rightType = 3;
// this.setVisibleShow = true;
// },
// },
// // {
// // text: "",
// // callback: (e) => {
// // const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian)
// // this.setDatas = {
// // title: '',
// // lng: mpt._lng,
// // lat: mpt._lat,
// // iconUrl:'',
// // remark: ''
// // }
// // this.rightType = 3
// // this.setVisibleShow = true
// // }
// // }
// ],
// },{
// text: "",
// show: function (e) {
// return Cesium.defined(e.cartesian);
// },
// callback: (e) => {
// const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian)
// let position = {
// lng: mpt._lng,
// lat: mpt._lat,
// };
// console.log("",position);
// getWeather().then((res)=>{
// if(res){
// res.position = [mpt._lng,mpt._lat];
// _self.handlerAddWeatherGraphic(res);
// }
// })
// }
// },
// ];
let mapContextmenuItems = [
{
text: "设为线索",
show: function (e) {
return Cesium.defined(e.cartesian);
},
callback:async (e) => {
const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian)
// fireClueForm.value = new Object<FireClue>();
fireClueForm.value.lng = String(mpt._lng);
fireClueForm.value.lng = String(mpt._lat);
getNameByPosition({lng:mpt._lng,lat:mpt._lat}).then(res=>{
fireClueForm.value.address = res.data.regeocode.formatted_address;
})
frieClueWindowShow.value = true;
},
},
{
text: "气象信息",
show: function (e) {
return Cesium.defined(e.cartesian);
},
callback: (e) => {
const mpt = mars3d.LngLatPoint.fromCartesian(e.cartesian)
let position = {
lng: mpt._lng,
lat: mpt._lat,
};
console.log("气象信息",position);
getWeather().then((res)=>{
if(res){
res.position = [mpt._lng,mpt._lat];
handlerAddWeatherGraphic(res);
}
})
}
}
]
window.globalMap.bindContextMenu(mapContextmenuItems);
})
return null;
//
AMapLoader.load({
@ -151,6 +457,99 @@ const initMap = (newData: any) => {
.catch(e => {})
}
let weatherGraphicLayer = null;
//
function handlerAddWeatherGraphic(info){
if(weatherGraphicLayer==null){
weatherGraphicLayer = new mars3d.layer.GraphicLayer()
window.globalMap.addLayer(weatherGraphicLayer)
//
weatherGraphicLayer.bindContextMenu([
{
text: "删除",
icon: "fa fa-trash-o",
show: (event) => {
const graphic = event.graphic
if (!graphic || graphic.isDestroy) {
return false
} else {
return true
}
},
callback: (e) => {
const graphic = e.graphic
if (!graphic) {
return
}
const parent = graphic.parent
let graphic_wind_info = weatherGraphicLayer.getGraphicById(graphic.id+"_info");
weatherGraphicLayer.removeGraphic(graphic_wind_info);
weatherGraphicLayer.removeGraphic(graphic)
if (parent) {
weatherGraphicLayer.removeGraphic(parent)
}
}
}
])
}
let uuid = (Math.random()*10000000).toFixed(0);
let graphic_wind = new mars3d.graphic.RectanglePrimitive({
id:"graphic_wind_"+uuid,
positions: [
info.position,
[info.position[0]-0.001, info.position[1]-0.001],
],
offsetHeight:100,
style: {
materialType: mars3d.MaterialType.Image,
materialOptions: {
image:"/components/Weather/wind_three.png",
font_size: 70,
color: new Cesium.Color(1.0, 1.0, 0.0, 1.0),
stroke: true,
strokeWidth: 10,
strokeColor: new Cesium.Color(1.0, 1.0, 1.0, 0.8)
},
rotationDegree:getWindDegree(info.win),
clampToGround: true
},
attr: { remark: "示例4" }
})
let graphic = new mars3d.graphic.DivGraphic({
id:"graphic_wind_"+uuid+"_info",
position: info.position,
style: {
html: `<h1 style="color:#eee;font-size:14px;">
<img src="/components/Weather/${info.wea_img}.png" style="width:24px;height:24px;" />
${info.win},${info.win_speed},${info.win_meter}</h1>`,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 200000), //
scaleByDistance: new Cesium.NearFarScalar(1000, 1.0, 200000, 0.2),
disableDepthTestDistance:Number.POSITIVE_INFINITY,
clampToGround: true,
eyeOffset:new Cesium.Cartesian3(0, 0, -5000),
},
attr: { remark: "示例9" },
pointerEvents: false // false穿div
})
weatherGraphicLayer.addGraphic(graphic);
weatherGraphicLayer.addGraphic(graphic_wind);
}
const dataHandle = (newData: any) => {
if (!mapIns && !AMapIns) {
// initMap(props.chartConfig.option)
@ -2373,7 +2772,139 @@ const handlerHiddenEntityLayer = ()=> {
graphicLayer.show = false;
}
// yi
// 线
interface FireClue {
id: number;
reportPerson: string;
describe: string;
lng: string;
lat: string;
address: string;
sourceType: number;
state: number;
createId: number;
areaName: string;
image: string;
modifyId: number;
eventId: string;
clueNo: string;
fireId: number;
audio: string;
degreeType: number;
}
const fireClueForm = ref<FireClue>({
"id": 0,
"reportPerson": "",
"describe": "",
"lng": "",
"lat": "",
"address": "",
"sourceType": 0,
"state": 0,
"createId": 0,
"areaName": "",
"image": "",
"modifyId": 0,
"eventId": "",
"clueNo": "",
"fireId": 0,
"audio": "",
"degreeType": 0
})
const frieClueWindowShow = ref<boolean>(false);
//
const cancleFireClue = () => {
frieClueWindowShow.value = false;
}
//
const addFirClue = () => {
axios({
method: 'post',
url: VITE_GLOB_API_URL+"/api/FireManagement/AddFireClueInfo",
data: fireClueForm.value,
headers: {
'X-Token': localStorage.getItem('X-Token'),
},
}).then((res) => {
frieClueWindowShow.value = false;
})
}
async function getNameByPosition(position){
let transformCoordinate = wgs84ToGcj02(position.lng,position.lat);
return axios({
method:"GET",
url:`https://restapi.amap.com/v3/geocode/regeo?key=4f992c089f9496201f6e4ea39ff3ab60&location=${transformCoordinate[0]},${transformCoordinate[1]}&extensions=base`
})
}
</script>
<style scoped>
.continer{
width:100%;
height:100%;
position:relative;
}
.add-clue-fire{
padding:24px;
width:380px;
height:490px;
position:absolute;
top:50%;
left:50%;
transform:translate( -50%, -50%);
background-image: url('@/assets/images/chart/tasks/taskassign/编组 78.png');
background-size: 100% 100%;
color:#fff;
.title{
width:100%;
height:50px;
line-height:50px;
font-weight:bold;
font-size:18px;
text-indent:10px;
.close-button{
width:50px;
height:60px;
position:absolute;
right:30px;
top:24px;
cursor:pointer;
img{
width:50px;
}
}
}
.form-item{
margin-top:20px;
padding:0px 8px;
.label{
margin:10px 0px;
}
}
}
.form-item:deep(.ant-input) {
background-color: #0D2813 !important;
border: 1px solid #00611A !important;
color: #fff !important;
border-radius:0px;
}
.form-item:deep(.ant-input::placeholder) {
color: rgba(255, 255, 255, 0.5) !important;
}
</style>

View File

@ -0,0 +1,93 @@
const PI = Math.PI
const a = 6378245.0
const ee = 0.00669342162296594323
function outOfChina(lng, lat) {
return (
lng < 72.004 || lng > 137.8347 ||
lat < 0.8293 || lat > 55.8271
)
}
function transformLat(x, y) {
let ret =
-100.0 +
2.0 * x +
3.0 * y +
0.2 * y * y +
0.1 * x * y +
0.2 * Math.sqrt(Math.abs(x))
ret +=
((20.0 * Math.sin(6.0 * x * PI) +
20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0
ret +=
((20.0 * Math.sin(y * PI) +
40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0
ret +=
((160.0 * Math.sin((y / 12.0) * PI) +
320 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0
return ret
}
function transformLng(x, y) {
let ret =
300.0 +
x +
2.0 * y +
0.1 * x * x +
0.1 * x * y +
0.1 * Math.sqrt(Math.abs(x))
ret +=
((20.0 * Math.sin(6.0 * x * PI) +
20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0
ret +=
((20.0 * Math.sin(x * PI) +
40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0
ret +=
((150.0 * Math.sin((x / 12.0) * PI) +
300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0
return ret
}
export function wgs84ToGcj02(lng, lat) {
if (outOfChina(lng, lat)) {
return [lng, lat]
}
let dLat = transformLat(lng - 105.0, lat - 35.0)
let dLng = transformLng(lng - 105.0, lat - 35.0)
const radLat = lat / 180.0 * PI
let magic = Math.sin(radLat)
magic = 1 - ee * magic * magic
const sqrtMagic = Math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI)
return [lng + dLng, lat + dLat]
}
export function gcj02ToWgs84(lng, lat) {
if (outOfChina(lng, lat)) {
return [lng, lat]
}
let dLat = transformLat(lng - 105.0, lat - 35.0)
let dLng = transformLng(lng - 105.0, lat - 35.0)
const radLat = lat / 180.0 * PI
let magic = Math.sin(radLat)
magic = 1 - ee * magic * magic
const sqrtMagic = Math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI)
const mgLat = lat + dLat
const mgLng = lng + dLng
return [lng * 2 - mgLng, lat * 2 - mgLat]
}

View File

@ -0,0 +1,53 @@
import axios from 'axios'
export const getWeather = ()=>{
return new Promise((resolve,reject)=>{
try{
// 易客云天气API http://yiketianqi.com/
axios({
method: 'get',
url:"http://v1.yiketianqi.com/api?unescape=1&version=v61&appid=45239454&appsecret=yZrOL1nv&city=费县",
}).then((res) => {
resolve(res.data);
}).catch(e=>{
reject(null);
});
}catch(e){
reject(null);
}
})
}
export const getWindDegree = (type)=>{
let degree = 0;
switch(type){
case "东风":
degree = 90;
break;
case "南风":
degree = 0;
break;
case "西风":
degree = 270;
break;
case "北风":
degree = 180;
break;
case "东北风":
degree = 135;
break;
case "东南风":
degree = 45;
break;
case "西北风":
degree = 225;
break;
case "西南风":
degree = 315;
break;
default:
degree = null;
break;
}
return degree;
}

View File

@ -43,10 +43,12 @@ import { MarkerEnum, ThemeEnum } from './config'
import { isArray } from '@/utils';
import axios from 'axios';
import { CaretDownOutlined, StarFilled, StarTwoTone,CheckOutlined,CaretRightOutlined } from '@ant-design/icons-vue';
import { getAppEnvConfig } from '@/utils/env'
import * as mars3d from "mars3d";
import { option } from '@/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColorRenderChart/barOptions'
var { VITE_GLOB_GEOSERVER_BASE_URL,VITE_GLOB_COFFEE_API_URL } = getAppEnvConfig();
let map: mars3d.Map; //
@ -66,11 +68,17 @@ const handlerLayers = ref([]);
const handlerGetLayerTree = ()=>{
axios.get('http://221.2.83.254:9006/applicationMars/getApplicationInfo/feixian').then((res)=>{
axios.get(VITE_GLOB_COFFEE_API_URL+'/applicationMars/getApplicationInfo/feixian',{
headers:{
"X-Token":localStorage.getItem("X-Token")
}
}).then((res)=>{
layers.value = res.data.data
console.log("res",layers.value);
let configLayers = [];
let GEOSERVER_BASE_API = "http://221.2.83.254:9007/";
res.data.data.forEach((item, index) => {
let group = null;
group = {

View File

@ -0,0 +1,18 @@
import { PublicConfigClass } from '@/packages/public'
import { chartInitConfig } from '@/settings/designSetting'
import { CreateComponentType } from '@/packages/index.d'
import { LocationSearchConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
textSize: 14,
colors: ['#0C2411','#00611A','#FFFFFF'],
text: '添加途经点'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = LocationSearchConfig.key
public attr = { ...chartInitConfig, w:400, h: 400, zIndex: 1 }
public chartConfig = cloneDeep(LocationSearchConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,64 @@
<template>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="文字">
<n-input-number
size="small"
v-model:value="optionData.text"
:min="10"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="文字大小">
<n-input-number
size="small"
v-model:value="optionData.textSize"
:min="10"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox
:name="`颜色-${index + 1}`"
v-for="(item, index) in optionData.colors"
:key="index"
>
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.colors[index]"
></n-color-picker>
</SettingItem>
<SettingItem>
<n-button
size="small"
@click="optionData.colors[index] = option.colors[index]"
>
恢复默认
</n-button>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import {
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
</script>

View File

@ -0,0 +1,100 @@
// drag.js
export default {
mounted(el) {
// 设置为相对于窗口定位
el.style.position = 'fixed'
const getBounds = () => ({
wMax: window.innerWidth - el.offsetWidth,
hMax: window.innerHeight - el.offsetHeight
})
if ('ontouchstart' in window) {
// 移动端
el.ontouchstart = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const startX = e.touches[0].clientX
const startY = e.touches[0].clientY
const offsetX = startX - rect.left
const offsetY = startY - rect.top
const { wMax, hMax } = getBounds()
document.ontouchmove = (e) => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-inactive')
el.classList.add('v-drag-active')
}
let left = e.touches[0].clientX - offsetX
let top = e.touches[0].clientY - offsetY
if (left < 0) left = 0
else if (left > wMax) left = wMax
if (top < 0) top = 0
else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
document.ontouchend = () => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-active')
el.classList.add('v-drag-inactive')
}
document.ontouchmove = document.ontouchend = null
}
}
} else {
// PC端
el.onmousedown = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const offsetX = e.clientX - rect.left
const offsetY = e.clientY - rect.top
const { wMax, hMax } = getBounds()
document.onmousemove = (e) => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-inactive')
el.classList.add('v-drag-active')
}
let left = e.clientX - offsetX
let top = e.clientY - offsetY
if (left < 0) left = 0
else if (left > wMax) left = wMax
if (top < 0) top = 0
else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
document.onmouseup = () => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-active')
el.classList.add('v-drag-inactive')
}
document.onmousemove = document.onmouseup = null
}
}
}
},
unmounted(el) {
el.onmousedown = null
el.ontouchstart = null
}
}

View File

@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d';
export const LocationSearchConfig: ConfigType = {
key: 'LocationSearch',
chartKey: 'VLocationSearch',
conKey: 'VCLocationSearch',
title: '地点搜索',
category: ChatCategoryEnum.TITLE,
categoryName: ChatCategoryEnumName.TITLE,
package: PackagesCategoryEnum.TASKS,
chartFrame: ChartFrameEnum.STATIC,
image: 'LocationSearch.png',
};

View File

@ -0,0 +1,242 @@
<template>
<div class="patrol-container">
<div class="search-container">
<div class="search-box">
<a-input
v-model:value="keywords"
:style="{
background: 'transparent',
border: 'none',
color: 'white',
height:'42px'
}" placeholder="请输入地名搜索" @keyup.native.enter="searchLocationByName" ></a-input>
<CloseCircleFilled @click="clearSearch()" />
</div>
<div class="search-button" @click="searchLocationByName()">
<SearchOutlined />
</div>
<div class="search-result-container" v-show="searchResult.length > 0 && keywords">
<div class="search-item" v-for="(item,index) in searchResult" :key="index"
@click="flyToMap(item.location)"
>{{item.name}}</div>
</div>
</div>
</div>
<!-- 海康监控画面 -->
</template>
<script lang="ts" setup>
import {computed,PropType,toRefs,watch,reactive,ref,onMounted,onUnmounted,createVNode,defineOptions} from 'vue';
import { CreateComponentType } from '@/packages/index.d';
import { eventHandlerHook } from '@/hooks/eventHandler.hook';
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore';
import { EventBus } from '@/utils/eventBus';
import { ElMessage } from 'element-plus'
import {getRedisUser,addOrUpdateRedisUser,getLockedClients,getTsgzProjectId,applyDroneControl} from '@/api/demo/airportMaintenance';
import { airPortStore } from '@/store/modules/airport';
import { useMessage } from '@/hooks/web/useMessage';
import axios from 'axios'
import { getAppEnvConfig } from '@/utils/env'
import { useUserStore } from '@/store/modules/user';
import { timestampToFormattedDate } from '@/utils/index';
import TCPlayer from 'tcplayer.js';
import 'tcplayer.js/dist/tcplayer.min.css'; //
import { listDronePort, saveHandFlyTask, endHandFlyTask, endAiInspection } from '@/api/situation';
import * as mars3d from "mars3d";
import * as Cesium from 'mars3d-cesium';
import {SearchOutlined,CloseCircleFilled} from '@ant-design/icons-vue';
var { VITE_GLOB_API_URL } = getAppEnvConfig();
const methodsShow = ref(false)
const { createMessage, createConfirm } = useMessage();
const userInfo = useUserStore.getUserInfo;
const isUAVLive = ref(true);
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true,
},
});
const { w, h, x, y } = toRefs(props.chartConfig.attr);
const chartEditStore = useChartEditStore();
// 线
const deliveryData = ref();
//
const droneData = ref();
const clickBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'click',
deliveryData.value,
);
};
const dblclickBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'dblclick',
val,
);
};
const rightclickBtn = (event) => {
event.preventDefault(); //
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'rightclick',
);
};
const mouseenterBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'mousein',
val,
);
};
const mouseleaveBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'mouseout',
val,
);
};
const searchResult = ref([]);
const keywords = ref<string>();
const searchLocationByName = async () => {
axios({
method: "post",
url: `https://restapi.amap.com/v3/place/text?keywords=${keywords.value}&city=临沂市&offset=10&page=1&key=2c5669982578bc963b5b840e4c421b73&extensions=all`,
}).then(res => {
let response = res.data;
if (response.status === "1" || response.infocode === "10000") {
searchResult.value = response.pois;
} else {
console.error("搜索失败:", response);
}
})
}
const clearSearch = () => {
keywords.value = "";
searchResult.value = [];
}
const flyToMap = (lngLat:string) =>{
let lngLatArr = lngLat.split(",");
window.globalMap.flyToPoint([Number(lngLatArr[0]),Number(lngLatArr[1])],{radius:200});
}
//
onMounted(()=>{
})
</script>
<style lang="scss" scoped>
.patrol-container {
width: v-bind('`${w}px`');
height: v-bind('`${h}px`');
border-radius: 2px;
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
img {
width: 16px;
}
span {
margin-left: 6px;
color: #fff;
}
.search-container{
width:100%;
height:42px;
display:flex;
position:relative;
.search-box{
padding:0px 12px 0px 0px;
display:flex;
width: calc( 100% - 60px);
height:42px;
background: rgba(7,38,30,0.85);
box-shadow: 0px 2px 12px 0px rgba(0,0,0,0.5);
border: 1px solid;
border-image: linear-gradient(180deg, rgba(0, 175, 74, 1), rgba(0, 117, 30, 0.21)) 1 1;
}
.search-button{
flex:1;
height:42px;
background: radial-gradient( 92% 92% at 50% 50%, #00C16B 0%, #008E39 100%), #000000;
text-align: center;
line-height:42px;
font-weight:bold;
font-size:22px;
}
.search-result-container{
width:100%;
max-height:240px;
position:absolute;
left:0px;
top:42px;
background:rgba(0,0,0,0.3);
border:1px solid rgba(0, 175, 74,0.5);
overflow-y:auto;
.search-item{
width:100%;
height:40px;
line-height:40px;
text-indent:20px;
color:#fff;
&:hover{
background: rgba(0,0,0,0.4);
}
}
}
}
}
:deep(.ant-input::placeholder) {
color: white !important;
}
</style>

View File

@ -0,0 +1,18 @@
import { PublicConfigClass } from '@/packages/public'
import { chartInitConfig } from '@/settings/designSetting'
import { CreateComponentType } from '@/packages/index.d'
import { MeasureToolsConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
textSize: 14,
colors: ['#0C2411','#00611A','#FFFFFF'],
text: '添加途经点'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = MeasureToolsConfig.key
public attr = { ...chartInitConfig, w:400, h: 400, zIndex: 1 }
public chartConfig = cloneDeep(MeasureToolsConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,64 @@
<template>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="文字">
<n-input-number
size="small"
v-model:value="optionData.text"
:min="10"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="文字大小">
<n-input-number
size="small"
v-model:value="optionData.textSize"
:min="10"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox
:name="`颜色-${index + 1}`"
v-for="(item, index) in optionData.colors"
:key="index"
>
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.colors[index]"
></n-color-picker>
</SettingItem>
<SettingItem>
<n-button
size="small"
@click="optionData.colors[index] = option.colors[index]"
>
恢复默认
</n-button>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import {
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
</script>

View File

@ -0,0 +1,100 @@
// drag.js
export default {
mounted(el) {
// 设置为相对于窗口定位
el.style.position = 'fixed'
const getBounds = () => ({
wMax: window.innerWidth - el.offsetWidth,
hMax: window.innerHeight - el.offsetHeight
})
if ('ontouchstart' in window) {
// 移动端
el.ontouchstart = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const startX = e.touches[0].clientX
const startY = e.touches[0].clientY
const offsetX = startX - rect.left
const offsetY = startY - rect.top
const { wMax, hMax } = getBounds()
document.ontouchmove = (e) => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-inactive')
el.classList.add('v-drag-active')
}
let left = e.touches[0].clientX - offsetX
let top = e.touches[0].clientY - offsetY
if (left < 0) left = 0
else if (left > wMax) left = wMax
if (top < 0) top = 0
else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
document.ontouchend = () => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-active')
el.classList.add('v-drag-inactive')
}
document.ontouchmove = document.ontouchend = null
}
}
} else {
// PC端
el.onmousedown = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const offsetX = e.clientX - rect.left
const offsetY = e.clientY - rect.top
const { wMax, hMax } = getBounds()
document.onmousemove = (e) => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-inactive')
el.classList.add('v-drag-active')
}
let left = e.clientX - offsetX
let top = e.clientY - offsetY
if (left < 0) left = 0
else if (left > wMax) left = wMax
if (top < 0) top = 0
else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
document.onmouseup = () => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-active')
el.classList.add('v-drag-inactive')
}
document.onmousemove = document.onmouseup = null
}
}
}
},
unmounted(el) {
el.onmousedown = null
el.ontouchstart = null
}
}

View File

@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d';
export const MeasureToolsConfig: ConfigType = {
key: 'MeasureTools',
chartKey: 'VMeasureTools',
conKey: 'VCMeasureTools',
title: '测量工具',
category: ChatCategoryEnum.TITLE,
categoryName: ChatCategoryEnumName.TITLE,
package: PackagesCategoryEnum.TASKS,
chartFrame: ChartFrameEnum.STATIC,
image: 'MeasureTools.png',
};

View File

@ -0,0 +1,444 @@
<template>
<div class="patrol-container">
<div class="measure-container">
<div class="title">
测量工具
<div class="clear-button" @click="drawClear"></div>
</div>
<div class="tools-container">
<div class="tool" v-for="(item,index) in tools" :key="index"
@click="startMeasure(item.name)"
>
<div class="image">
<img :src="getImageUrl(item.type)" alt="">
</div>
<div class="label">{{item.name}}</div>
</div>
</div>
</div>
</div>
<!-- 海康监控画面 -->
</template>
<script lang="ts" setup>
import {computed,PropType,toRefs,watch,reactive,ref,onMounted,onUnmounted,createVNode,defineOptions} from 'vue';
import { CreateComponentType } from '@/packages/index.d';
import { eventHandlerHook } from '@/hooks/eventHandler.hook';
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore';
import { EventBus } from '@/utils/eventBus';
import { ElMessage } from 'element-plus'
import {getRedisUser,addOrUpdateRedisUser,getLockedClients,getTsgzProjectId,applyDroneControl} from '@/api/demo/airportMaintenance';
import { airPortStore } from '@/store/modules/airport';
import { useMessage } from '@/hooks/web/useMessage';
import axios from 'axios'
import { getAppEnvConfig } from '@/utils/env'
import { useUserStore } from '@/store/modules/user';
import { timestampToFormattedDate } from '@/utils/index';
import TCPlayer from 'tcplayer.js';
import 'tcplayer.js/dist/tcplayer.min.css'; //
import { listDronePort, saveHandFlyTask, endHandFlyTask, endAiInspection } from '@/api/situation';
import * as mars3d from "mars3d";
import * as Cesium from 'mars3d-cesium';
import {SearchOutlined,CloseCircleFilled} from '@ant-design/icons-vue';
var { VITE_GLOB_API_URL } = getAppEnvConfig();
const methodsShow = ref(false)
const { createMessage, createConfirm } = useMessage();
const userInfo = useUserStore.getUserInfo;
const isUAVLive = ref(true);
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true,
},
});
const { w, h, x, y } = toRefs(props.chartConfig.attr);
const chartEditStore = useChartEditStore();
// 线
const deliveryData = ref();
//
const droneData = ref();
const clickBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'click',
deliveryData.value,
);
};
const dblclickBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'dblclick',
val,
);
};
const rightclickBtn = (event) => {
event.preventDefault(); //
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'rightclick',
);
};
const mouseenterBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'mousein',
val,
);
};
const mouseleaveBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'mouseout',
val,
);
};
const searchResult = ref([]);
const keywords = ref<string>();
const searchLocationByName = async () => {
axios({
method: "post",
url: `https://restapi.amap.com/v3/place/text?keywords=${keywords.value}&city=临沂市&offset=10&page=1&key=2c5669982578bc963b5b840e4c421b73&extensions=all`,
}).then(res => {
let response = res.data;
if (response.status === "1" || response.infocode === "10000") {
searchResult.value = response.pois;
} else {
console.error("搜索失败:", response);
}
})
}
const clearSearch = () => {
keywords.value = "";
searchResult.value = [];
}
const flyToMap = (lngLat:string) =>{
let lngLatArr = lngLat.split(",");
window.globalMap.flyToPoint([Number(lngLatArr[0]),Number(lngLatArr[1])],{radius:200});
}
//
onMounted(()=>{
})
interface MeasureTool {
name:string;
type:string;
}
const tools = ref<MeasureTool[]>([
{
name:"空间距离",
type:"kjjl",
},{
name:"贴地距离",
type:"tdjl",
},{
name:"剖面测量",
type:"paomian",
},{
name:"水平面积",
type:"spmj",
},{
name:"角度测量",
type:"jiaodu",
},{
name:"贴地面积",
type:"tiedi",
},{
name:"高差测量",
type:"gdc",
},{
name:"三角测量",
type:"sanjiao",
},
]);
const getImageUrl = (type:string) => {
// Vite
return new URL(`/src/assets/images/chart/tasks/measure/${type}.png`, import.meta.url).href
}
let measure:mars3d.thing.Measure;
let unit = "auto";
const startMeasure = (name) => {
if(measure == null){
initDrawLayer();
initMeasure();
}
switch(name){
case '空间距离': measureLength();
break;
case '贴地距离': measureSurfaceLength();
break;
case '剖面测量': measureSection();
break;
case '水平面积': measureArea();
break;
case '贴地面积': measureSurfaceeArea();
break;
case '高差测量': measureHeight();
break;
case '角度测量': measureAngle();
break;
case '三角测量': measureTriangleHeight();
break;
}
}
const initMeasure = () => { //
measure = new mars3d.thing.Measure({
// hasEdit: true,
isAutoEditing: true,
label: {
color: "#ffffff",
font_family: "楷体",
font_size: 20,
background: false
}
})
window.globalMap.addThing(measure)
}
const measureLength = () => { //
measure.distance({
showAddText: true,
unit: "auto",
})
}
const measureSurfaceLength = () => { //
measure.distanceSurface({
showAddText: true,
unit: unit,
exact: false
})
}
const measureSection = () => {
measure.section({
unit: unit,
// maxPointNum:2,
splitNum: 300,
exact: false
})
}
const measureArea = () => { //
measure.area({
unit: unit,
})
}
const measureSurfaceeArea = () => { //
measure.areaSurface({
unit: unit,
style: {
color: "#ffff00"
},
splitNum: 10, // step
exact: false // false
})
}
const measureHeight = () => { //
measure.height()
}
const measureAngle = () => { //
measure.angle()
}
const measureTriangleHeight = () => { //
measure.heightTriangle()
}
const measureClear = () => { //
if(measure){
measure.clear();
}
}
let graphicLayerbiaohui:mars3d.layer.GraphicLayer;
const drawClear = () => {
measureClear();
graphicLayerbiaohui.clear()
}
const initDrawLayer = () => { //
graphicLayerbiaohui = new mars3d.layer.GraphicLayer({
name:"标绘图层",
id:10101,
isRestorePositions: true,
// hasEdit: true,
isAutoEditing: true //
})
window.globalMap.addLayer(graphicLayerbiaohui)
}
</script>
<style lang="scss" scoped>
.patrol-container {
width: v-bind('`${w}px`');
height: v-bind('`${h}px`');
border-radius: 2px;
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
img {
width: 16px;
}
span {
margin-left: 6px;
color: #fff;
}
.search-container{
width:100%;
height:42px;
display:flex;
position:relative;
.search-box{
padding:0px 12px 0px 0px;
display:flex;
width: calc( 100% - 60px);
height:42px;
background: rgba(7,38,30,0.85);
box-shadow: 0px 2px 12px 0px rgba(0,0,0,0.5);
border: 1px solid;
border-image: linear-gradient(180deg, rgba(0, 175, 74, 1), rgba(0, 117, 30, 0.21)) 1 1;
}
.search-button{
flex:1;
height:42px;
background: radial-gradient( 92% 92% at 50% 50%, #00C16B 0%, #008E39 100%), #000000;
text-align: center;
line-height:42px;
font-weight:bold;
font-size:22px;
}
.search-result-container{
width:100%;
max-height:240px;
position:absolute;
left:0px;
top:42px;
background:rgba(0,0,0,0.3);
border:1px solid rgba(0, 175, 74,0.5);
overflow-y:auto;
.search-item{
width:100%;
height:40px;
line-height:40px;
text-indent:20px;
color:#fff;
&:hover{
background: rgba(0,0,0,0.4);
}
}
}
}
}
.measure-container{
width:100%;
height:100%;
background-image: url(@/assets/images/chart/uav/flight-bg.png);
background-size: 100% 100%;
.title{
width:100%;
padding:0px 30px;
font-weight: bold;
height:60px;
line-height:60px;
color:#fff;
font-size:18px;
position:relative;
.clear-button{
position:absolute;
width:60px;
height:25px;
right:60px;
font-size:14px;
font-weight: 400;
top:16px;
background-image: url(@/assets/images/chart/tasks/measure/clear-draw.png);
background-size:100% 100%;
background-repeat: no-repeat;
cursor:pointer;
}
}
.tools-container{
padding:20px;
width: 100%;
height: calc( 100% - 70px);
display: grid;
gap:20px;
grid-template-columns: repeat(4, 1fr);
.tool{
color:#fff;
text-align:center;
.image{
margin-bottom:12px;
}
img{
width: 60px;
}
}
}
}
:deep(.ant-input::placeholder) {
color: white !important;
}
</style>

View File

@ -0,0 +1,18 @@
import { PublicConfigClass } from '@/packages/public'
import { chartInitConfig } from '@/settings/designSetting'
import { CreateComponentType } from '@/packages/index.d'
import { OnlineUsersConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
export const option = {
textSize: 14,
colors: ['#0C2411','#00611A','#FFFFFF'],
text: '添加途经点'
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = OnlineUsersConfig.key
public attr = { ...chartInitConfig, w:400, h: 400, zIndex: 1 }
public chartConfig = cloneDeep(OnlineUsersConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,64 @@
<template>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="文字">
<n-input-number
size="small"
v-model:value="optionData.text"
:min="10"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox name="样式">
<SettingItem name="文字大小">
<n-input-number
size="small"
v-model:value="optionData.textSize"
:min="10"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
<CollapseItem name="样式" :expanded="true">
<SettingItemBox
:name="`颜色-${index + 1}`"
v-for="(item, index) in optionData.colors"
:key="index"
>
<SettingItem name="颜色">
<n-color-picker
size="small"
:modes="['hex']"
v-model:value="optionData.colors[index]"
></n-color-picker>
</SettingItem>
<SettingItem>
<n-button
size="small"
@click="optionData.colors[index] = option.colors[index]"
>
恢复默认
</n-button>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import {
CollapseItem,
SettingItemBox,
SettingItem
} from '@/components/Pages/ChartItemSetting'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
</script>

View File

@ -0,0 +1,100 @@
// drag.js
export default {
mounted(el) {
// 设置为相对于窗口定位
el.style.position = 'fixed'
const getBounds = () => ({
wMax: window.innerWidth - el.offsetWidth,
hMax: window.innerHeight - el.offsetHeight
})
if ('ontouchstart' in window) {
// 移动端
el.ontouchstart = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const startX = e.touches[0].clientX
const startY = e.touches[0].clientY
const offsetX = startX - rect.left
const offsetY = startY - rect.top
const { wMax, hMax } = getBounds()
document.ontouchmove = (e) => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-inactive')
el.classList.add('v-drag-active')
}
let left = e.touches[0].clientX - offsetX
let top = e.touches[0].clientY - offsetY
if (left < 0) left = 0
else if (left > wMax) left = wMax
if (top < 0) top = 0
else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
document.ontouchend = () => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-active')
el.classList.add('v-drag-inactive')
}
document.ontouchmove = document.ontouchend = null
}
}
} else {
// PC端
el.onmousedown = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const offsetX = e.clientX - rect.left
const offsetY = e.clientY - rect.top
const { wMax, hMax } = getBounds()
document.onmousemove = (e) => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-inactive')
el.classList.add('v-drag-active')
}
let left = e.clientX - offsetX
let top = e.clientY - offsetY
if (left < 0) left = 0
else if (left > wMax) left = wMax
if (top < 0) top = 0
else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
document.onmouseup = () => {
const time2 = Date.now()
if (time2 - time1 > 300) {
el.classList.remove('v-drag-active')
el.classList.add('v-drag-inactive')
}
document.onmousemove = document.onmouseup = null
}
}
}
},
unmounted(el) {
el.onmousedown = null
el.ontouchstart = null
}
}

View File

@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d';
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d';
export const OnlineUsersConfig: ConfigType = {
key: 'OnlineUsers',
chartKey: 'VOnlineUsers',
conKey: 'VCOnlineUsers',
title: '在线人员',
category: ChatCategoryEnum.TITLE,
categoryName: ChatCategoryEnumName.TITLE,
package: PackagesCategoryEnum.TASKS,
chartFrame: ChartFrameEnum.STATIC,
image: 'OnlineUsers.png',
};

View File

@ -0,0 +1,714 @@
<template>
<div
class="patrol-container"
>
<div class="monitor-video-container">
<div class="title">在线人员</div>
<div class="video-container" >
<!-- <iframe v-if="callUserShow" style="width:100%;height:100%;"
src="http://localhost:9239/#/?userID=yishuixian&callUserID=17861857725"
frameborder="0"
allow="microphone; camera; autoplay"
allowfullscreen
sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-modals"
></iframe> -->
</div>
<div class="filter-container">
<a-row :gutter="12">
<a-col :span="7">
<a-select
ref="select"
v-model:value="listParams.type"
placeholder="人员分类"
style="width: 100%;"
>
<a-select-option v-for="(item,index) in roleList" :key="index" :value="item.id">{{ item.name }}</a-select-option>
</a-select>
</a-col>
<a-col :span="7">
<a-select
ref="select"
v-model:value="listParams.unitname"
placeholder="所属单位"
style="width: 100%;"
>
<a-select-option v-for="(item,index) in unitList" :key="index" :value="item?.unitName">{{item?.unitName}}</a-select-option>
</a-select>
</a-col>
<a-col :span="7">
<a-input placeholder="人员名称"></a-input>
</a-col>
</a-row>
</div>
<div class="users-container">
<div class="user-box" v-for="(item,index) in userList" :key="index">
<div class="user-avater">
<img src="@/assets/images/chart/tasks/fire-user.png" alt="">
<div class="online-state"></div>
</div>
<div class="user-name">
{{ item.name }}
<img src="@/assets/images/chart/tasks/to-top.png" class="top-icon" alt="">
</div>
<div class="type">
类型{{ item.type }}
</div>
<div class="number">
电话{{ item.phone }}
</div>
<div class="operateion">
<div class="operation-item" @click="topUser(item);"></div>
<div class="operation-item" @click="positionUser(item);"></div>
<div class="operation-item" @click="callUser(item);"></div>
</div>
</div>
</div>
</div>
</div>
<!-- 海康监控画面 -->
</template>
<script lang="ts" setup>
import {computed,PropType,toRefs,watch,reactive,ref,onMounted,onUnmounted,createVNode,defineOptions} from 'vue';
import { CreateComponentType } from '@/packages/index.d';
import { eventHandlerHook } from '@/hooks/eventHandler.hook';
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore';
import { EventBus } from '@/utils/eventBus';
import { ElMessage } from 'element-plus'
import {getRedisUser,addOrUpdateRedisUser,getLockedClients,getTsgzProjectId,applyDroneControl} from '@/api/demo/airportMaintenance';
import { airPortStore } from '@/store/modules/airport';
import { useMessage } from '@/hooks/web/useMessage';
import axios from 'axios'
import { getAppEnvConfig } from '@/utils/env'
import { useUserStore } from '@/store/modules/user';
import { timestampToFormattedDate } from '@/utils/index';
import TCPlayer from 'tcplayer.js';
import 'tcplayer.js/dist/tcplayer.min.css'; //
import { listDronePort, saveHandFlyTask, endHandFlyTask, endAiInspection } from '@/api/situation';
import * as mars3d from "mars3d";
import * as Cesium from 'mars3d-cesium';
var { VITE_GLOB_API_URL } = getAppEnvConfig();
const methodsShow = ref(false)
const { createMessage, createConfirm } = useMessage();
const userInfo = useUserStore.getUserInfo;
const isUAVLive = ref(true);
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true,
},
});
const { w, h, x, y } = toRefs(props.chartConfig.attr);
const chartEditStore = useChartEditStore();
// 线
const deliveryData = ref();
//
const droneData = ref();
const clickBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'click',
deliveryData.value,
);
};
const dblclickBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'dblclick',
val,
);
};
const rightclickBtn = (event) => {
event.preventDefault(); //
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'rightclick',
);
};
const mouseenterBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'mousein',
val,
);
};
const mouseleaveBtn = (val) => {
eventHandlerHook(
chartEditStore.getComponentList,
props.chartConfig.events.interactConfigEvents,
'mouseout',
val,
);
};
//
interface Role {
id? : number | null,
name?: string | null,
status? : number | null,
createTime? : string | null,
createId? : string | null
}
const roleList = ref<Role[]>([]);
const getRoleList = () => {
axios({
method: "get",
url: VITE_GLOB_API_URL+"/api/Check/GetRoles",
headers: {
'X-Token': localStorage.getItem("X-Token")
}
}).then(res=>{
if(res.data && Array.isArray(res.data.result)){
roleList.value = res.data.result;
}else{
roleList.value = [];
}
})
}
//
interface Unit {
id : number | null,
unitName? : string | null,
unitType? : string | null,
createTime? :string | null,
createUserId? : string | null,
description? :string | null,
imaUrl? : string | null
}
//
const unitList = ref<Unit[]>([]);
//
const getUnitList = () => {
axios({
method: "get",
url: VITE_GLOB_API_URL+"/api/FireManagement/GetUserUnit",
headers: {
'X-Token': localStorage.getItem("X-Token")
}
}).then(res=>{
if(res.data && Array.isArray(res.data.result)){
unitList.value = res.data.result;
}else{
unitList.value = [];
}
})
}
//
onMounted(()=>{
//
getRoleList();
//
getUnitList();
})
//
const userList = ref([]);
//
const listParams = ref({
unitname:null,
type:null,
})
//
const getUserList = () => {
axios({
method: "get",
url: VITE_GLOB_API_URL+"/api/FireManagement/GetPointByUserType",
params: listParams.value,
headers: {
'X-Token': localStorage.getItem("X-Token")
}
}).then(res=>{
if(res.data){
userList.value = res.data.data;
//
loadUserGraphic();
}
})
}
getUserList();
//
const callUserShow = ref(false);
const callUser = (user) => {
window.open(`http://localhost:9239/#/?userID=yishuixian&callUserID=${user.phone}`,"视频通话", "location=no,toolbar=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=460");
}
//
const topUserList = ref([]);
const topUser = (user) => {
}
let markGraphicLayer:mars3d.layer.GraphicLayer;
//
const loadUserGraphic = () => {
//
if (markGraphicLayer == null) {
markGraphicLayer = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(markGraphicLayer);
}
userList.value?.forEach((item,index)=>{
let showVideo = item.type == '对讲机' ? 'none':'block';
let graphic = new mars3d.graphic.BillboardEntity({
id:item.createId,
position: [Number(item.lng), Number(item.lat)],
style: {
image:"/components/Map/fire-user.png",
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
clampToGround: true,
scale: 0.8,
label: {
text: item.name,
font_size: 12,
color: "#ffffff",
pixelOffsetY: -70,
distanceDisplayCondition: true,
distanceDisplayCondition_far: 2000,
distanceDisplayCondition_near: 0,
},
},
popup: `<div class="marsTiltPanel marsTiltPanel-theme-green">
<div class="marsTiltPanel-wrap">
<div class="area">
<div class="arrow-lt"></div>
<div class="b-t"></div>
<div class="b-r"></div>
<div class="b-b"></div>
<div class="b-l"></div>
<div class="arrow-rb"></div>
<div class="label-wrap">
<div class="title">${item.name}</div>
<div class="label-content">
<div class="data-li">
<div class="data-label" >电话/对讲机</div>
<div class="data-value">${item.phone}</div>
</div>
<div class="data-li">
<div class="data-label"></div>
<div class="data-value" title="视频通话" >
<div onclick="videoCall('${item.phone}')" style="background-image:url(/img/onlineuser-video-button.png);background-size:100% 100%;width:100px!important;height:28px!important;display:${showVideo};">&nbsp;</div>
</div>
</div>
</div>
</div>
</div>
<div class="b-t-l"></div>
<div class="b-b-r"></div>
</div>
<div class="arrow" ></div>
</div>`,
popupOptions: {
offsetY: -30,
template: "{content}",
horizontalOrigin: "Cesium.HorizontalOrigin.LEFT",
verticalOrigin: "Cesium.VerticalOrigin.CENTER",
},
pointerEvents: true,
});
markGraphicLayer.addGraphic(graphic);
})
}
//
const positionUser = (user) => {
let graphic = markGraphicLayer.getGraphicById(user.createId);
if(graphic){
window.globalMap.flyToGraphic(graphic,{radius:500});
}
}
</script>
<style lang="scss" scoped>
.patrol-container {
width: v-bind('`${w}px`');
height: v-bind('`${h}px`');
border-radius: 2px;
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
img {
width: 16px;
}
span {
margin-left: 6px;
color: #fff;
}
.monitor-video-container{
width:100%;
padding-bottom:30px;
z-index:999;
//
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE/Edge */
user-select: none;
background-image: url('@/assets/images/chart/uav/flight-bg.png');
background-size: 100% 100%;
overflow: hidden;
.title{
display: flex;
align-items: center;
justify-content: space-between;
margin: 16px 4%;
color:#fff;
font-size:18px;
font-weight:bold;
}
.left-panel{
flex:auto;
.ai-title {
display: flex;
align-items: center;
justify-content: space-between;
margin: 16px 4%;
button {
border: 1px solid #00ae4a;
background: none;
color: #fff;
border-radius: 10px;
padding: 6px 10px;
}
}
.ai-control {
width: 90%;
height: calc( 100% - 80px);
background: #0c2e25;
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
border-radius: 10px;
border: 1px solid #00611a;
margin-left: 5%;
margin-top: 20px;
.no-picture {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #fff;
margin-top: 6%;
img{
width:120px;
margin:20px 0px;
}
}
}
}
}
}
.video-container{
width: calc( 100% - 40px);
margin:20px;
height:280px;
background:rgba(0,0,0,0.5);
border-radius: 5px;
overflow:hidden;
}
.filter-container{
width: calc( 100% - 40px);
margin:0px auto;
}
/* */
.users-container{
padding:20px;
width:100%;
min-height:440px;
max-height:440px;
overflow-y:auto;
display:flex;
flex-wrap: wrap;
gap:8px;
.user-box{
color:#fff;
flex: 0 0 calc(25% - 6px);
max-height:180px;
background: #0D2813;
border-radius: 5px;
border: 1px solid #00611A;
padding:10px 10px;
font-size:10px;
position:relative;
transition-delay: all 2s;
.user-avater{
width:56px;
height:56px;
margin:0px auto;
border-radius: 50%;
border: 1px solid #00611A;
position:relative;
img{
width:56px;
height:56px;
}
.online-state{
position:absolute;
width:10px;
height:10px;
top:3px;
right:3px;
background: #57FF94 ;
border-radius:50%;
}
}
.user-name{
font-size:12px;
margin-top:12px;
border-top:1px solid #00611A;
height:30px;
line-height:35px;
.top-icon{
width:16px;
height:12px;
position:relative;
top:-1px;
}
}
.type{
position:relative;
line-height: 24px;
&::before{
content:" ";
width:6px;
height:6px;
}
}
.operateion{
width:100%;
height:100%;
background:rgba(0,0,0,0.6);
position:absolute;
top:0px;
left:0px;
display: none;
border-radius: 5px;
transition: all 0.3s ease 3s;
}
&:hover .operateion{
display:block;
}
.operation-item{
width: 80%;
height:36px;
background:#00b156e3;
border-radius: 8px;
line-height:36px;
font-size:12px;
text-align: center;
margin:14px auto;
}
}
}
/* 自定义选择框样式 */
.filter-container :deep(.ant-select-selector) {
background-color: #0D2813 !important;
border: 1px solid #00611A !important;
color: #fff !important;
}
.filter-container :deep(.ant-select-selection-placeholder),
.filter-container :deep(.ant-select-selection-item) {
color: #fff !important;
}
.filter-container :deep(.ant-select-arrow) {
color: #fff !important;
}
/* 自定义输入框样式 */
.filter-container:deep(.ant-input) {
background-color: #0D2813 !important;
border: 1px solid #00611A !important;
color: #fff !important;
}
.filter-container:deep(.ant-input::placeholder) {
color: rgba(255, 255, 255, 0.5) !important;
}
/* 鼠标悬停和聚焦状态 */
.filter-container :deep(.ant-select-selector:hover),
.filter-container:deep(.ant-input:hover) {
border-color: #00a829 !important;
}
.filter-container :deep(.ant-select-focused .ant-select-selector),
.filter-container :deep(.ant-input:focus) {
border-color: #00a829 !important;
box-shadow: 0
}
/* 下拉菜单整体样式 */
.filter-container :deep(.ant-select-dropdown) {
background-color: #0D2813 !important;
border: 1px solid #00611A !important;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3) !important;
}
/* 下拉菜单选项样式 */
.filter-container :deep(.ant-select-item) {
color: #fff !important;
background-color: transparent !important;
}
/* 选项悬停状态 */
.filter-container :deep(.ant-select-item-option:hover:not(.ant-select-item-option-disabled)) {
background-color: #00611A !important;
}
/* 选项选中状态 */
.filter-container :deep(.ant-select-item-option-selected:not(.ant-select-item-option-disabled)) {
background-color: rgba(0, 97, 26, 0.7) !important;
color: #fff !important;
font-weight: normal;
}
/* 选项激活状态 */
.filter-container :deep(.ant-select-item-option-active:not(.ant-select-item-option-disabled)) {
background-color: rgba(0, 168, 41, 0.3) !important;
}
/* 分组标题样式 */
.filter-container :deep(.ant-select-item-group) {
color: rgba(255, 255, 255, 0.8) !important;
border-bottom: 1px solid #00611A !important;
}
/* 搜索框样式 */
.filter-container :deep(.ant-select-dropdown .ant-select-item-option-grouped) {
padding-left: 24px;
}
/* 空状态样式 */
.filter-container :deep(.ant-empty-description) {
color: rgba(255, 255, 255, 0.7) !important;
}
/* 下拉菜单滚动条样式 */
.filter-container :deep(.ant-select-dropdown::-webkit-scrollbar) {
width: 6px;
}
.filter-container :deep(.ant-select-dropdown::-webkit-scrollbar-track) {
background: #0D2813;
}
.filter-container :deep(.ant-select-dropdown::-webkit-scrollbar-thumb) {
background: #00611A;
border-radius: 3px;
}
.filter-container :deep(.ant-select-dropdown::-webkit-scrollbar-thumb:hover) {
background: #00a829;
}
/* 虚拟滚动容器样式(如果启用) */
.filter-container :deep(.ant-select-item-virtual) {
background-color: #0D2813 !important;
}
/* 禁用状态样式 */
.filter-container :deep(.ant-select-disabled .ant-select-selector) {
background-color: #0a1f0d !important;
border-color: #004013 !important;
color: rgba(255, 255, 255, 0.5) !important;
}
.filter-container :deep(.ant-select-item-option-disabled) {
color: rgba(255, 255, 255, 0.3) !important;
}
/* 鼠标悬停和聚焦状态 */
.filter-container :deep(.ant-select-selector:hover) {
border-color: #00a829 !important;
}
.filter-container :deep(.ant-select-focused .ant-select-selector) {
border-color: #00a829 !important;
box-shadow: 0 0 0 2px rgba(0, 97, 26, 0.2) !important;
}
/* 清除按钮样式 */
.filter-container :deep(.ant-select-clear) {
background-color: transparent !important;
color: rgba(255, 255, 255, 0.7) !important;
}
.filter-container :deep(.ant-select-clear:hover) {
color: #fff !important;
}
</style>

View File

@ -1,38 +1,61 @@
// drag.js
export default {
mounted(el) {
// 设置为相对父元素定位
el.style.position = 'absolute'
// drag.ts
interface DragElement extends HTMLElement {
style: CSSStyleDeclaration;
offsetParent: HTMLElement;
offsetWidth: number;
offsetHeight: number;
}
const getBounds = () => {
const parent = el.offsetParent || document.body
interface Bounds {
parent: HTMLElement;
wMax: number;
hMax: number;
rect: DOMRect;
}
interface TouchEventWithTouches extends TouchEvent {
touches: TouchList;
}
interface MouseEventWithClient extends MouseEvent {
clientX: number;
clientY: number;
}
const dragDirective = {
mounted(el: DragElement): void {
// 设置为相对父元素定位
el.style.position = 'absolute';
const getBounds = (): Bounds => {
const parent = el.offsetParent || document.body;
return {
parent,
// 计算父容器的可见范围
wMax: parent.clientWidth - el.offsetWidth,
hMax: parent.clientHeight - el.offsetHeight,
rect: parent.getBoundingClientRect()
}
}
};
};
if ('ontouchstart' in window) {
// 移动端
el.ontouchstart = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const { parent, wMax, hMax, rect: parentRect } = getBounds()
const offsetX = e.touches[0].clientX - rect.left
const offsetY = e.touches[0].clientY - rect.top
el.ontouchstart = (e: TouchEventWithTouches) => {
const time1 = Date.now();
const rect = el.getBoundingClientRect();
const { parent, wMax, hMax, rect: parentRect } = getBounds();
const offsetX = e.touches[0].clientX - rect.left;
const offsetY = e.touches[0].clientY - rect.top;
document.ontouchmove = (e) => {
const time2 = Date.now()
document.ontouchmove = (e: TouchEventWithTouches) => {
const time2 = Date.now();
if (time2 - time1 > 300) {
el.classList.add('v-drag-active')
el.classList.add('v-drag-active');
}
// 相对于父容器左上角计算位置
let left = e.touches[0].clientX - parentRect.left - offsetX
let top = e.touches[0].clientY - parentRect.top - offsetY
let left = e.touches[0].clientX - parentRect.left - offsetX;
let top = e.touches[0].clientY - parentRect.top - offsetY;
// 可选:限制边界,不想限制就注释掉
// if (left < 0) left = 0
@ -40,33 +63,34 @@ export default {
// if (top < 0) top = 0
// else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
el.style.left = `${left}px`;
el.style.top = `${top}px`;
};
document.ontouchend = () => {
el.classList.remove('v-drag-active')
document.ontouchmove = document.ontouchend = null
}
}
document.ontouchend = (): void => {
el.classList.remove('v-drag-active');
document.ontouchmove = null;
document.ontouchend = null;
};
};
} else {
// PC端
el.onmousedown = (e) => {
const time1 = Date.now()
const rect = el.getBoundingClientRect()
const { parent, wMax, hMax, rect: parentRect } = getBounds()
const offsetX = e.clientX - rect.left
const offsetY = e.clientY - rect.top
el.onmousedown = (e: MouseEventWithClient) => {
const time1 = Date.now();
const rect = el.getBoundingClientRect();
const { parent, wMax, hMax, rect: parentRect } = getBounds();
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
document.onmousemove = (e) => {
const time2 = Date.now()
document.onmousemove = (e: MouseEventWithClient) => {
const time2 = Date.now();
if (time2 - time1 > 300) {
el.classList.add('v-drag-active')
el.classList.add('v-drag-active');
}
// 👇计算相对于父元素的位置,但用窗口坐标保证能拖出
let left = e.clientX - parentRect.left - offsetX
let top = e.clientY - parentRect.top - offsetY
let left = e.clientX - parentRect.left - offsetX;
let top = e.clientY - parentRect.top - offsetY;
// ✅允许超出父容器,所以不限制范围
// 想加边界限制可打开注释
@ -75,20 +99,23 @@ export default {
// if (top < 0) top = 0
// else if (top > hMax) top = hMax
el.style.left = `${left}px`
el.style.top = `${top}px`
}
el.style.left = `${left}px`;
el.style.top = `${top}px`;
};
document.onmouseup = () => {
el.classList.remove('v-drag-active')
document.onmousemove = document.onmouseup = null
}
}
document.onmouseup = (): void => {
el.classList.remove('v-drag-active');
document.onmousemove = null;
document.onmouseup = null;
};
};
}
},
unmounted(el) {
el.onmousedown = null
el.ontouchstart = null
unmounted(el: DragElement): void {
el.onmousedown = null;
el.ontouchstart = null;
}
}
};
export default dragDirective;

View File

@ -17,6 +17,10 @@ import { TaskAddRouteConfig } from './TaskAddRoute/index';
import { TaskRoutePlanConfig } from './TaskRoutePlan/index';
import {TaskAssignConfig} from './TaskAssign';
import {HikvisionConfig} from './Hikvision';
import {OnlineUsersConfig} from './OnlineUsers';
import { LocationSearchConfig } from './LocationSearch';
import { MeasureToolsConfig } from './MeasureTools';
export default [
@ -39,4 +43,6 @@ export default [
TaskRoutePlanConfig,
TaskAssignConfig,
HikvisionConfig,
OnlineUsersConfig,
MeasureToolsConfig,
];

View File

@ -6,17 +6,12 @@ import { ZhiChu_LuXianGuHuaConfig } from './index'
export const option = {
dataset: {
startName: '救援队伍1',
startLngLat: [117.923964,35.405512],
way: [
{
wayName: '国庄村',
wayLngLat: [117.915252,35.365226],
wayFlag: true,
},
],
endName: '费县北站',
endLngLat: [117.931713,35.319092],
startName: '起点',
startLngLat: [],
way: [],
endName: '终点',
endLngLat: [],
endWay:[]
},
dataStyle:{
marginTop: 25,

View File

@ -8,12 +8,14 @@
<Title :dataStyle="option.dataStyle" />
<span class="titleName"> 路径规划 </span>
</div>
<div class="way">
<!-- 起点 -->
<div class="way_start">
<n-tooltip placement="top" trigger="hover">
<template #trigger>
<StartAndEndTitle
:name="option.dataset.startName"
:name="'起点'"
:dataStyle="option.dataStyle"
:wayColor="wayColorList.startColor"
@click="moveLocation(option.dataset.startLngLat)"
@ -37,11 +39,13 @@
fontSize: option.dataStyle.wayStartFontSize + 'px',
}"
>
添加途经
添加
</span>
</n-button>
</div>
</div>
<!-- 起点列表 -->
<div class="way_list">
<div class="way_item" v-for="(item, index) in option.dataset.way" :key="index">
<div class="way_item_num">
@ -57,18 +61,7 @@
/>
</div>
<div class="way_item_input">
<n-select
v-model:value="item.wayName"
filterable
placeholder="请输入灭火队伍资源"
label-field="districtAndName"
value-field="districtAndName"
remote
:clear-filter-after-select="false"
:options="selectWayPointOptions[index]"
@search="searWayPointSelectOptions($event, index)"
@update:value="updateWayPointLocaion(item, index)"
/>
{{ item.wayName }}
</div>
<div class="way_item_button">
<ButtonUp
@ -81,22 +74,75 @@
</div>
</div>
</div>
<!-- 终点 -->
<div class="way_end">
<n-tooltip placement="top" trigger="hover">
<template #trigger>
<StartAndEndTitle
:name="option.dataset.endName"
:name="'终点'"
:dataStyle="option.dataStyle"
:wayColor="wayColorList.endColor"
@click="moveLocation(option.dataset.endLngLat)"
/>
</template>
{{ option.dataset.endName }}
<!-- {{ option.dataset.endName }} -->
终点
</n-tooltip>
<div class="way_start_addButton">
<n-button quaternary @click="setEndPoint">
<PlusOutlined
:style="{
marginRight: '5px',
color: option.dataStyle.wayStartFontColor,
fontSize: option.dataStyle.wayStartFontSize + 'px',
}"
/>
<span
:style="{
color: option.dataStyle.wayStartFontColor,
fontSize: option.dataStyle.wayStartFontSize + 'px',
}"
>
设置终点
</span>
</n-button>
</div>
</div>
<!-- 终点 -->
<div class="way_list">
<div class="way_item" v-for="(item, index) in option.dataset.endWay" :key="index">
<div class="way_item_num">
<span>{{ index + 1 }}</span>
</div>
<div class="way_item_icon">
<ButtonIcon
:dataStyle="option.dataStyle"
:wayColor="
item.wayFlag ? wayColorList.wayColorChoose : wayColorList.wayColorNoChoose
"
@click="changeWayPointFlag(item)"
/>
</div>
<div class="way_item_input">
{{ item.wayName }}
</div>
<div class="way_item_button">
<ButtonUp
v-if="index != 0"
:dataStyle="option.dataStyle"
@click="moveupWayPoint(index)"
/>
<ButtonClose :dataStyle="option.dataStyle" @click="removeWayPoint(index)" />
<ButtonLocation :dataStyle="option.dataStyle" @click="moveLocation(item.wayLngLat)" />
</div>
</div>
</div>
</div>
<div class="plan">
<n-button quaternary @click="directionRoute">
<!-- <n-button quaternary @click="directionRoute">
<PlanButton :dataStyle="option.dataStyle" />
<span
:style="{
@ -107,19 +153,28 @@
>
规划方案
</span>
</n-button>
</n-button> -->
<div class="driveOrWalkDiv">
<DriveOrWalk
:value="'驾车'"
:value="'导航'"
:type="'drive'"
:driveOrWalk="driveOrWalk"
:dataStyle="option.dataStyle"
@click="driveOrWalk = 'drive'"
@click="directionRoute"
/>
<n-tooltip placement="bottom" trigger="hover" :style="{ maxWidth: '90px' }">
<DriveOrWalk
:value="'清除'"
:type="'walk'"
:driveOrWalk="driveOrWalk"
:dataStyle="option.dataStyle"
@click="clearDraw"
/>
<!-- <n-tooltip placement="bottom" trigger="hover" :style="{ maxWidth: '90px' }">
<template #trigger>
<DriveOrWalk
:value="'步行'"
:value="'清除'"
:type="'walk'"
:driveOrWalk="driveOrWalk"
:dataStyle="option.dataStyle"
@ -127,7 +182,7 @@
/>
</template>
步行不经过途经点
</n-tooltip>
</n-tooltip> -->
</div>
</div>
<div class="line_result_list">
@ -171,6 +226,10 @@
import { useChartDataFetch } from '@/hooks';
import cloneDeep from 'lodash/cloneDeep';
import { PlusOutlined, CloseCircleOutlined, MinusCircleOutlined } from '@ant-design/icons-vue';
import {wgs84ToGcj02} from './lib/CoordinateTransform';
import { getNameByPosition } from './lib/AMapApi';
import { getRouter } from './lib/Navigation';
import { getRouterFunc, drawRouterFunc, clearRouterFunc,handlerStartRoaming,handlerStopRoaming } from './lib/routePath'
import {
CloseButton,
Title,
@ -194,6 +253,7 @@
import { useMessage } from '@/hooks/web/useMessage';
import { gcj02towgs84, wgs84togcj02 } from 'coordtransform';
import * as mars3d from 'mars3d';
import * as Cesium from 'mars3d-cesium';
const { createMessage } = useMessage();
@ -247,18 +307,90 @@
};
// -
function addWayPoint() {
async function addWayPoint() {
if (option.dataset.way.length > 15) {
createMessage.warning('途经地点最多只能设置16个');
return;
}
option.dataset.way.push({
wayName: '',
wayLngLat: [],
wayFlag: false,
});
//
let way = await setMarkPoint("start");
// selectWayPointOptions.value.push({});
}
async function setMarkPoint(type){
// +
window.globalMap.setCursor("crosshair");
window.globalMap.once(mars3d.EventType.click, async function (event) {
//
window.globalMap.setCursor("default")
const cartesian = event.cartesian
const point = mars3d.LngLatPoint.fromCartesian(cartesian)
point.format()
let response = await getNameByPosition(point);
if (response.data.status === "1" || response.data.infocode === "10000") {
option.dataset.way.push({
wayName: response.data.regeocode.formatted_address,
wayLngLat: [point.lng,point.lat],
wayFlag: false,
})
} else {
option.dataset.way.push({
wayName: point.lng+","+point.lat,
wayLngLat: [point.lng,point.lat],
wayFlag: false,
});
}
drawPoint("start",point.lng,point.lat,point.alt);
})
}
async function setEndMarkPoint(type){
// +
window.globalMap.setCursor("crosshair");
window.globalMap.once(mars3d.EventType.click, async function (event) {
//
window.globalMap.setCursor("default")
const cartesian = event.cartesian
const point = mars3d.LngLatPoint.fromCartesian(cartesian)
point.format()
let response = await getNameByPosition(point);
if (response.data.status === "1" || response.data.infocode === "10000") {
option.dataset.endWay = [{
wayName: response.data.regeocode.formatted_address,
wayLngLat: [point.lng,point.lat],
wayFlag: false,
}]
} else {
option.dataset.endWay = [{
wayName: point.lng+","+point.lat,
wayLngLat: [point.lng,point.lat],
wayFlag: false,
}];
}
drawPoint("end",point.lng,point.lat,point.alt);
})
}
// -
function changeWayPointFlag(item) {
item.wayFlag = !item.wayFlag;
@ -292,6 +424,69 @@
option.dataset.way.splice(index, 1);
}
}
//
function setEndPoint() {
setEndMarkPoint();
}
let pathPointGraphicLayer = null;
let startGraphicEntity= [];
let endGraphicEntity = null;
function clearDraw(){
clearRouterFunc();
pathPointGraphicLayer ? pathPointGraphicLayer.clear() : null;
}
function drawPoint(type, lng, lat, z) { //
if(pathPointGraphicLayer == null){
pathPointGraphicLayer = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathPointGraphicLayer);
}
let image = null;
if(type == 'start'){
image = "/components/Map/navigation-start-point.png"
var graphic = new mars3d.graphic.BillboardEntity({
position: [lng, lat, z],
style: {
image: image,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
clampToGround: true
},
attr: { remark: type == 'start'?'起点':'终点' }
})
startGraphicEntity.push(graphic);
pathPointGraphicLayer.addGraphic(graphic);
}else if(type == 'end'){
image = "/components/Map/navigation-end-point.png"
if(endGraphicEntity){
pathPointGraphicLayer.removeGraphic(endGraphicEntity);
endGraphicEntity = null;
}
endGraphicEntity = new mars3d.graphic.BillboardEntity({
position: [lng, lat, z],
style: {
image: image,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
clampToGround: true
},
attr: { remark: type == 'start'?'起点':'终点' }
})
pathPointGraphicLayer.addGraphic(endGraphicEntity);
}
}
//
function moveLocation(lngLat) {
if (lngLat.length > 0) {
@ -429,6 +624,11 @@
}
}
function hnadlerGetPoint () {
window.globalMap.on(mars3d.EventType.click,(e)=>{
console.log(e);
})
}
// --------------------------------------------------------------------------
const driveOrWalk = ref('drive');
const nowLine = ref(0);
@ -438,7 +638,7 @@
() => driveOrWalk.value,
() => {
// 线
directionRoute();
// directionRoute();
},
);
@ -447,53 +647,88 @@
// 线
const directionRoute = () => {
let endPoint = option.dataset.endWay[0]
option.dataset.way?.forEach((item,index)=>{
let postgisParams = {
startlng: item.wayLngLat[0],
startlat: item.wayLngLat[1],
endlng: endPoint.wayLngLat[0],
endlat: endPoint.wayLngLat[1],
areaname: "feixian",
}
// getRouter(postgisParams);
getRouterFunc(postgisParams,'all').then(res => {
if(res){
// this.tripFlyArray[index] = res.allCoordinates;
console.log("res:999",res);
drawRouterFunc(res)
}else{
// this.$message({
// type:"error",
// message:"PostGIS线"
// })
}
}).catch(err => {
clearRouterFunc()
})
})
//
if (driveOrWalk.value == 'walk') {
getWalkingRoute({
startlng: option.dataset.startLngLat[0],
startlat: option.dataset.startLngLat[1],
endlng: option.dataset.endLngLat[0],
endlat: option.dataset.endLngLat[1],
}).then((result) => {
if (typeof result == 'string') {
if (result == 'OVER_DIRECTION_RANGE') {
createMessage.warning('距离太远,超过导航范围!');
return;
}
if (result == 'USER DAILY_QUERY_OVER_LIMIT') {
createMessage.warning('已经达到用户每日查询限制!');
return;
}
}
lineResult.value = result;
// 线
getLocationLines(null);
});
}
//
if (driveOrWalk.value == 'drive') {
getDrivingRoute({
startlng: option.dataset.startLngLat[0],
startlat: option.dataset.startLngLat[1],
endlng: option.dataset.endLngLat[0],
endlat: option.dataset.endLngLat[1],
way: option.dataset.way,
}).then((result) => {
if (typeof result == 'string') {
if (result == 'OVER_DIRECTION_RANGE') {
createMessage.warning('距离太远,超过导航范围!');
return;
}
if (result == 'USER DAILY_QUERY_OVER_LIMIT') {
createMessage.warning('已经达到用户每日查询限制!');
return;
}
}
lineResult.value = result;
// 线
getLocationLines(null);
});
}
// if (driveOrWalk.value == 'walk') {
// getWalkingRoute({
// startlng: option.dataset.startLngLat[0],
// startlat: option.dataset.startLngLat[1],
// endlng: option.dataset.endLngLat[0],
// endlat: option.dataset.endLngLat[1],
// }).then((result) => {
// if (typeof result == 'string') {
// if (result == 'OVER_DIRECTION_RANGE') {
// createMessage.warning('');
// return;
// }
// if (result == 'USER DAILY_QUERY_OVER_LIMIT') {
// createMessage.warning('');
// return;
// }
// }
// lineResult.value = result;
// // 线
// getLocationLines(null);
// });
// }
// //
// if (driveOrWalk.value == 'drive') {
// getDrivingRoute({
// startlng: option.dataset.startLngLat[0],
// startlat: option.dataset.startLngLat[1],
// endlng: option.dataset.endLngLat[0],
// endlat: option.dataset.endLngLat[1],
// way: option.dataset.way,
// }).then((result) => {
// if (typeof result == 'string') {
// if (result == 'OVER_DIRECTION_RANGE') {
// createMessage.warning('');
// return;
// }
// if (result == 'USER DAILY_QUERY_OVER_LIMIT') {
// createMessage.warning('');
// return;
// }
// }
// lineResult.value = result;
// // 线
// getLocationLines(null);
// });
// }
};
// 线
@ -564,13 +799,13 @@
onMounted(() => {
setTimeout(() => {
//
setContextmenuByRightClick();
// setContextmenuByRightClick();
// -
getLocationPoints('start');
getLocationPoints('end');
getLocationPoints('way');
// getLocationPoints('start');
// getLocationPoints('end');
// getLocationPoints('way');
// 线+线
directionRoute();
// directionRoute();
}, 1000);
});
@ -799,6 +1034,10 @@
option.dataStyle.driveOrWalkHeight = (option.dataStyle.driveOrWalkWidth / 81) * 23;
},
);
</script>
<style lang="scss" scoped>
@ -900,6 +1139,7 @@
}
.way_item_input {
width: 55%;
color:#fff;
}
.way_item_button {
width: 25%;
@ -941,7 +1181,19 @@
.way_end {
margin-left: 10px;
position: relative;
margin-top: 5px;
.way_start_addButton {
background: #0c2411;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
height: v-bind('`${option.dataStyle.waySvgHeight}px`');
border: 1px solid #00611a;
top: 0px;
right: 0px;
}
}
.plan {

View File

@ -0,0 +1,13 @@
import axios from 'axios';
import {wgs84ToGcj02} from './CoordinateTransform';
export async function getNameByPosition(position){
let transformCoordinate = wgs84ToGcj02(position.lng,position.lat);
return axios({
method:"GET",
url:`https://restapi.amap.com/v3/geocode/regeo?key=4f992c089f9496201f6e4ea39ff3ab60&location=${transformCoordinate[0]},${transformCoordinate[1]}&extensions=base`
})
}

View File

@ -0,0 +1,93 @@
const PI = Math.PI
const a = 6378245.0
const ee = 0.00669342162296594323
function outOfChina(lng, lat) {
return (
lng < 72.004 || lng > 137.8347 ||
lat < 0.8293 || lat > 55.8271
)
}
function transformLat(x, y) {
let ret =
-100.0 +
2.0 * x +
3.0 * y +
0.2 * y * y +
0.1 * x * y +
0.2 * Math.sqrt(Math.abs(x))
ret +=
((20.0 * Math.sin(6.0 * x * PI) +
20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0
ret +=
((20.0 * Math.sin(y * PI) +
40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0
ret +=
((160.0 * Math.sin((y / 12.0) * PI) +
320 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0
return ret
}
function transformLng(x, y) {
let ret =
300.0 +
x +
2.0 * y +
0.1 * x * x +
0.1 * x * y +
0.1 * Math.sqrt(Math.abs(x))
ret +=
((20.0 * Math.sin(6.0 * x * PI) +
20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0
ret +=
((20.0 * Math.sin(x * PI) +
40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0
ret +=
((150.0 * Math.sin((x / 12.0) * PI) +
300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0
return ret
}
export function wgs84ToGcj02(lng, lat) {
if (outOfChina(lng, lat)) {
return [lng, lat]
}
let dLat = transformLat(lng - 105.0, lat - 35.0)
let dLng = transformLng(lng - 105.0, lat - 35.0)
const radLat = lat / 180.0 * PI
let magic = Math.sin(radLat)
magic = 1 - ee * magic * magic
const sqrtMagic = Math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI)
return [lng + dLng, lat + dLat]
}
export function gcj02ToWgs84(lng, lat) {
if (outOfChina(lng, lat)) {
return [lng, lat]
}
let dLat = transformLat(lng - 105.0, lat - 35.0)
let dLng = transformLng(lng - 105.0, lat - 35.0)
const radLat = lat / 180.0 * PI
let magic = Math.sin(radLat)
magic = 1 - ee * magic * magic
const sqrtMagic = Math.sqrt(magic)
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI)
const mgLat = lat + dLat
const mgLng = lng + dLng
return [lng * 2 - mgLng, lat * 2 - mgLat]
}

View File

@ -0,0 +1,30 @@
import axios from 'axios';
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_API_URL } = getAppEnvConfig();
// 获取路线数据
export const getRouter = (params, method = 'postgis') => {
let { startlng, startlat, endlng, endlat } = params;
let postgisParams = {
startlng: startlng,
startlat: startlat,
endlng: endlng,
endlat: endlat,
areaname: "feixian",
}
axios(VITE_GLOB_API_URL+"/api/FireResources/LoadRoad",{
method:"POST",
params:postgisParams,
}).then(res=>{
console.log(res);
})
}
// 绘制路线结果
export const renderRouter = () => {
}

View File

@ -0,0 +1,226 @@
var numberRegexp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
// Matches sequences like '100 100' or '100 100 100'.
var tuples = new RegExp('^' + numberRegexp.source + '(\\s' + numberRegexp.source + '){1,}');
/*
* Parse WKT and return GeoJSON.
*
* @param {string} _ A WKT geometry
* @return {?Object} A GeoJSON geometry object
*/
function parse(input) {
if (!input) {
return {
"coordinates": [],
"type": "LineString"
}
}
var parts = input.split(';');
var _ = parts.pop();
var srid = (parts.shift() || '').split('=').pop();
var i = 0;
function $(re) {
var match = _.substring(i).match(re);
if (!match) return null;
else {
i += match[0].length;
return match[0];
}
}
function crs(obj) {
if (obj && srid.match(/\d+/)) {
obj.crs = {
type: 'name',
properties: {
name: 'urn:ogc:def:crs:EPSG::' + srid
}
};
}
return obj;
}
function white() { $(/^\s*/); }
function multicoords() {
white();
var depth = 0;
var rings = [];
var stack = [rings];
var pointer = rings;
var elem;
while (elem =
$(/^(\()/) ||
$(/^(\))/) ||
$(/^(,)/) ||
$(tuples)) {
if (elem === '(') {
stack.push(pointer);
pointer = [];
stack[stack.length - 1].push(pointer);
depth++;
} else if (elem === ')') {
// For the case: Polygon(), ...
if (pointer.length === 0) return null;
pointer = stack.pop();
// the stack was empty, input was malformed
if (!pointer) return null;
depth--;
if (depth === 0) break;
} else if (elem === ',') {
pointer = [];
stack[stack.length - 1].push(pointer);
} else if (!elem.split(/\s/g).some(isNaN)) {
Array.prototype.push.apply(pointer, elem.split(/\s/g).map(parseFloat));
} else {
return null;
}
white();
}
if (depth !== 0) return null;
return rings;
}
function coords() {
var list = [];
var item;
var pt;
while (pt =
$(tuples) ||
$(/^(,)/)) {
if (pt === ',') {
list.push(item);
item = [];
} else if (!pt.split(/\s/g).some(isNaN)) {
if (!item) item = [];
Array.prototype.push.apply(item, pt.split(/\s/g).map(parseFloat));
}
white();
}
if (item) list.push(item);
else return null;
return list.length ? list : null;
}
function point() {
if (!$(/^(point(\sz)?)/i)) return null;
white();
if (!$(/^(\()/)) return null;
var c = coords();
if (!c) return null;
white();
if (!$(/^(\))/)) return null;
return {
type: 'Point',
coordinates: c[0]
};
}
function multipoint() {
if (!$(/^(multipoint)/i)) return null;
white();
var newCoordsFormat = _
.substring(_.indexOf('(') + 1, _.length - 1)
.replace(/\(/g, '')
.replace(/\)/g, '');
_ = 'MULTIPOINT (' + newCoordsFormat + ')';
var c = multicoords();
if (!c) return null;
white();
return {
type: 'MultiPoint',
coordinates: c
};
}
function multilinestring() {
if (!$(/^(multilinestring)/i)) return null;
white();
var c = multicoords();
if (!c) return null;
white();
return {
type: 'MultiLineString',
coordinates: c
};
}
function linestring() {
if (!$(/^(linestring(\sz)?)/i)) return null;
white();
if (!$(/^(\()/)) return null;
var c = coords();
if (!c) return null;
if (!$(/^(\))/)) return null;
return {
type: 'LineString',
coordinates: c
};
}
function polygon() {
if (!$(/^(polygon(\sz)?)/i)) return null;
white();
var c = multicoords();
if (!c) return null;
return {
type: 'Polygon',
coordinates: c
};
}
function multipolygon() {
if (!$(/^(multipolygon)/i)) return null;
white();
var c = multicoords();
if (!c) return null;
return {
type: 'MultiPolygon',
coordinates: c
};
}
function geometrycollection() {
var geometries = [];
var geometry;
if (!$(/^(geometrycollection)/i)) return null;
white();
if (!$(/^(\()/)) return null;
while (geometry = root()) {
geometries.push(geometry);
white();
$(/^(,)/);
white();
}
if (!$(/^(\))/)) return null;
return {
type: 'GeometryCollection',
geometries: geometries
};
}
function root() {
return point() ||
linestring() ||
polygon() ||
multipoint() ||
multilinestring() ||
multipolygon() ||
geometrycollection();
}
return crs(root());
}
export { parse }

View File

@ -0,0 +1,748 @@
import axios from "axios";
import { gcj02towgs84, wgs84togcj02 } from 'coordtransform'
import * as turf from '@turf/turf'
import { Url } from "./urlFormat";
// import { getMethodCommon } from "../../../api/common";
import { parse } from "./handleGeojson";
import { deepClone } from "./utils";
const urls = new Url()
import { getAppEnvConfig } from '@/utils/env';
const { VITE_GLOB_API_URL } = getAppEnvConfig();
const GD_URL = "https://restapi.amap.com/v5/direction/driving"
const GD_KEY = "6af6a87038f44c8c793aa70331f2b7ca"
import * as mars3d from 'mars3d';
import * as Cesium from 'mars3d-cesium';
//路线的图层
let pathGraphicLayers = null
let pathOneGraphicLayers= null
let pathWaterGraphicLayers = null
let pathRoadGraphicLayers = null
let pathRoadGraphicLayers1 = null
let pathRoadGraphicLayers2 = null
export const getMethodCommon = (url,params) => {
// VITE_GLOB_API_URL
return axios("http://221.2.83.254:9001"+url,{
method:"GET",
params:params,
})
}
//导航寻路
export const getRouterFunc = (params, method = 'postgis') => {
/**
* method
* postgis使postgis
* all : + postgis
* gaode:
*/
let { startlng, startlat, endlng, endlat } = params
if (method == 'postgis') {
//使用gpostgis进行导航
return new Promise((resolve, reject) => {
let postgisParams = {
startlng: startlng,
startlat: startlat,
endlng: endlng,
endlat: endlat,
areaname: "feixian",
}
getRouterByPostGis(postgisParams).then(geojson => {
//postGisCoordinates:postgis返回的geojson取出坐标数组
let postGisCoordinates = getOneLineCoordinatesFromGeometry(geojson)
let startRouterLngLat = postGisCoordinates[0]
let endRouterLngLat = postGisCoordinates.at(-1)
let resObject = {
allCoordinates: postGisCoordinates, //全部线路的合集
postGisRoute: postGisCoordinates, // postgis线路
gdRoute: [],
startLngLat: [startlng, startlat], // 起点
endLngLat: [endlng, endlat], //终点
startRouterLngLat: startRouterLngLat, // 路线查询结果的起点
endRouterLngLat: endRouterLngLat, //路线查询结果的终点
}
let simpleRoute = getMinimumRoute(resObject)
resolve(simpleRoute)
})
}).catch(err => {
})
}
if (method == 'all') {
// 先用高德进行导航
return new Promise((resolve, reject) => {
getRouterByGD(params).then(solution => {
// solution 为多条线路的数组,现在先用第一条线路 solution.path[0]
let gdRoute = solution.path[0]
let postgisParams = {
startlng: gdRoute.endCoordinates[0],
startlat: gdRoute.endCoordinates[1],
endlng: endlng,
endlat: endlat,
areaname: "feixian",
}
//使用gpostgis求出剩下的路线
getRouterByPostGis(postgisParams).then(geojson => {
//postGisCoordinates:postgis返回的geojson取出坐标数组
let postGisCoordinates = getOneLineCoordinatesFromGeometry(geojson)
// 高德返回的第一条线路的坐标数组
let path_gd = gdRoute.path_polyline
//合并高德和postgis的路线
let allCoordinates = path_gd.concat(postGisCoordinates)
//导航线路的起点和终点
let startRouterLngLat = allCoordinates[0]
let endRouterLngLat = allCoordinates.at(-1)
let resObject = {
allCoordinates: allCoordinates, //全部线路
gdRoute: path_gd, //高德的线路
postGisRoute: postGisCoordinates, // postgis的线路
startLngLat: [startlng, startlat], // 起点
endLngLat: [endlng, endlat], //终点
startRouterLngLat: startRouterLngLat, // 路线查询结果的起点
endRouterLngLat: endRouterLngLat, //路线查询结果的终点
}
let simpleRoute = getMinimumRoute(resObject)
resolve(simpleRoute)
})
})
})
}
}
//高德路线导航
export const getRouterByGD = (params) => {
/**
* type:Object
*/
let { startlng, startlat, endlng, endlat } = params
//wgs84转火星坐标系
var gcj02StartLngLat = wgs84togcj02(startlng, startlat);
var gcj02EndLngLat = wgs84togcj02(endlng, endlat);
let gd_params = {
origin: `${gcj02StartLngLat[0]},${gcj02StartLngLat[1]}`,
destination: `${gcj02EndLngLat[0]},${gcj02EndLngLat[1]}`,
show_fields: 'polyline',
key: GD_KEY,
strategy:2
}
let new_url = urls.getUrl(GD_URL, gd_params)
return new Promise((resolve, reject) => {
axios({
method: "get",
url: new_url,
}).then((res) => {
if (res.status === 200) {
let solution = []
//处理数据
res.data.route.paths.map(path => {
let route_len = path.distance
let path_polyline = path.steps.map(step => {
return step.polyline
})
let router_path_str = [] //暂时存放 ['117.927498,35.263264']
path_polyline.forEach(polyline => {
let step = polyline.split(';')
router_path_str = router_path_str.concat(step)
});
// 去掉重复点
let unique_router_path_str = [...new Set(router_path_str)]
// 坐标转数组
let unique_router_path = unique_router_path_str.map(path_str => {
let lng_lat_list = path_str.split(',')
//高德坐标系转wgs84坐标系
var wgs84Coordinate = gcj02towgs84(...lng_lat_list);
return wgs84Coordinate
})
//高德导航的起点和终点
let startCoordinates = unique_router_path[0]
let endCoordinates = unique_router_path.at(-1)
// 高德地图返回的结果:方案一。长度,线
solution.push(
{
route_len: route_len,
path_polyline: unique_router_path,
startCoordinates: startCoordinates,
endCoordinates: endCoordinates
}
)
})
let result = {
routerCount: parseInt(res.data.count),
path: solution
}
resolve(result)
} else {
reject(res)
}
}).catch(err => {
reject(err)
})
})
}
//使用postgres + postgis寻路
export const getRouterByPostGis = (params) => {
return new Promise((resolve, reject) => {
// /api/FireResources/LoadRoad
getMethodCommon("/api/FirePrevention/LoadRoad", params).then((res) => {
console.log("Res1213",res);
if (res.data.data.length > 0) {
console.log('res.data::: ', res.data);
let LineString = res.data.data[0].route;
if (LineString == null || LineString == "null") {
//没有找到路线,返回空
console.log('PostGIS未找到合适了路线')
resolve(parse(null))
} else {
resolve(parse(LineString))
}
} else {
console.log('PostGIS未找到合适了路线')
resolve(parse(null))
}
}).catch(err => {
console.log('PostGIS寻路算法服务端错误')
resolve(parse(null))
})
})
}
// 绘制线路
export const drawRouterFunc = (pathObject) => {
let { allCoordinates, startLngLat, endLngLat, startRouterLngLat, endRouterLngLat, gdRoute, postGisRoute } = pathObject
// 添加graphic
if (pathGraphicLayers == null) {
pathGraphicLayers = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathGraphicLayers);
} else {
// pathGraphicLayers.clear();
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (allCoordinates.length == 2) {
//只绘制开头到结尾的路线的路段
let endPathGraphic = drawPolylineDashEntity([startLngLat, endLngLat], 'YELLOW')
pathGraphicLayers.addGraphic(endPathGraphic);
} else {
// 导航数据路段
// let gdPathGraphic = drawLineFlowEntity(gdRoute, 'YELLOW',10)
// let postgisPathGraphic = drawLineFlowEntity(postGisRoute, 'RED',10)
let pathGraphic = drawLineFlowEntity(allCoordinates, '#E6472B')
//开始的路段
let startPathGraphic = drawPolylineDashEntity([startLngLat, startRouterLngLat], 'YELLOW')
//结尾的路段
let endPathGraphic = drawPolylineDashEntity([endRouterLngLat, endLngLat], 'YELLOW')
// pathGraphicLayers.addGraphic(gdPathGraphic);
// pathGraphicLayers.addGraphic(postgisPathGraphic);
pathGraphicLayers.addGraphic(pathGraphic);
pathGraphicLayers.addGraphic(startPathGraphic);
pathGraphicLayers.addGraphic(endPathGraphic);
}
}
// 绘制线路
export const drawRoutersFunc = (pathObject) => {
let { allCoordinates, startLngLat, endLngLat, startRouterLngLat, endRouterLngLat, gdRoute, postGisRoute } = pathObject
// 添加graphic
if (pathGraphicLayers == null) {
pathGraphicLayers = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathGraphicLayers);
} else {
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (allCoordinates.length == 2) {
//只绘制开头到结尾的路线的路段
// let endPathGraphic = drawPolylineDashEntity([startLngLat, endLngLat], 'YELLOW')
// pathGraphicLayers.addGraphic(endPathGraphic);
} else {
// 导航数据路段
// let gdPathGraphic = drawLineFlowEntity(gdRoute, 'YELLOW',10)
// let postgisPathGraphic = drawLineFlowEntity(postGisRoute, 'RED',10)
let pathGraphic = drawLineFlowEntityColor(allCoordinates, '#E6472B')
//开始的路段
// let startPathGraphic = drawPolylineDashEntity([startLngLat, startRouterLngLat], 'YELLOW')
//结尾的路段
// let endPathGraphic = drawPolylineDashEntity([endRouterLngLat, endLngLat], 'YELLOW')
let endPathGraphic = drawPolylineEntity([endRouterLngLat, endLngLat], 'YELLOW')
// pathGraphicLayers.addGraphic(gdPathGraphic);
// pathGraphicLayers.addGraphic(postgisPathGraphic);
pathGraphicLayers.addGraphic(pathGraphic);
// pathGraphicLayers.addGraphic(startPathGraphic);
pathGraphicLayers.addGraphic(endPathGraphic);
}
}
export const drawRoutersFuncWaterGrid = (pathObject) => {
let { pointArr } = pathObject
// 添加graphic
if (pathWaterGraphicLayers == null) {
pathWaterGraphicLayers = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathWaterGraphicLayers);
} else {
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (pointArr.length == 2) {
} else {
// 导航数据路段
let pathGraphic
pathGraphic = drawLineFlowEntityColor2(pointArr, '#56C3F9')
pathWaterGraphicLayers.addGraphic(pathGraphic);
}
}
export const drawRoutersFuncGrid = (pathObject) => {
let { pointArr, Type } = pathObject
// 添加graphic
if (pathRoadGraphicLayers == null) {
pathRoadGraphicLayers = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathRoadGraphicLayers);
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (pointArr.length == 2) {
} else {
// 导航数据路段
let pathGraphic;
pathGraphic = drawLineFlowEntityColor1(pointArr, '#E6472B')
pathRoadGraphicLayers.addGraphic(pathGraphic);
}
}
export const drawRoutersFuncGrid1 = (pathObject) => {
let { pointArr, Type } = pathObject
// 添加graphic
if (pathRoadGraphicLayers1 == null) {
pathRoadGraphicLayers1 = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathRoadGraphicLayers1);
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (pointArr.length == 2) {
} else {
// 导航数据路段
let pathGraphic1;
pathGraphic1 = drawLineFlowEntityColor2(pointArr, '#1F5FDE')
pathRoadGraphicLayers1.addGraphic(pathGraphic1);
}
}
export const drawRoutersFuncGrid2 = (pathObject) => {
let { pointArr, Type } = pathObject
// 添加graphic
if (pathRoadGraphicLayers2 == null) {
pathRoadGraphicLayers2 = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathRoadGraphicLayers2);
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (pointArr.length == 2) {
} else {
// 导航数据路段
let pathGraphic2;
pathGraphic2 = drawLineFlowEntityColor2(pointArr, '#9C9C9C')
pathRoadGraphicLayers2.addGraphic(pathGraphic2);
}
}
// 高亮路线
export const drawOneRouterFunc = (pathObject) => {
let { allCoordinates, startLngLat, endLngLat, startRouterLngLat, endRouterLngLat, gdRoute, postGisRoute } = pathObject
// 添加graphic
if (pathOneGraphicLayers == null) {
pathOneGraphicLayers = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(pathOneGraphicLayers);
} else {
pathOneGraphicLayers.clear();
}
//当只有两组数据时,说明没有导航的路线,直接使用虚线连接
if (allCoordinates.length == 2) {
//只绘制开头到结尾的路线的路段
let endPathGraphic = drawPolylineDashEntity([startLngLat, endLngLat], 'YELLOW')
pathOneGraphicLayers.addGraphic(endPathGraphic);
} else {
// 导航数据路段
// let gdPathGraphic = drawLineFlowEntity(gdRoute, 'YELLOW',10)
// let postgisPathGraphic = drawLineFlowEntity(postGisRoute, 'RED',10)
let pathGraphic = drawLineFlowEntity(allCoordinates, 'CYAN')
//开始的路段
// let startPathGraphic = drawPolylineDashEntity([startLngLat, startRouterLngLat], 'YELLOW')
//结尾的路段
// let endPathGraphic = drawPolylineDashEntity([endRouterLngLat, endLngLat], 'YELLOW')
// pathGraphicLayers.addGraphic(gdPathGraphic);
// pathGraphicLayers.addGraphic(postgisPathGraphic);
pathOneGraphicLayers.addGraphic(pathGraphic);
// pathGraphicLayers.addGraphic(startPathGraphic);
// pathGraphicLayers.addGraphic(endPathGraphic);
}
}
// 生成虚线实体
const drawPolylineDashEntity = (positions, cesiumColor,width=5) => {
return new mars3d.graphic.PolylineEntity({
positions: positions,
style: {
width: width,
clampToGround: true,
materialType: mars3d.MaterialType.PolylineDash,
materialOptions: {
color: Cesium.Color[cesiumColor],
dashLength: 8.0,
},
},
});
}
const drawPolylineEntity = (positions, cesiumColor,width=5) => {
return new mars3d.graphic.PolylineEntity({
positions: positions,
style: {
width: width,
clampToGround: true,
// materialType: mars3d.MaterialType.PolylineDash,
materialOptions: {
color: Cesium.Color[cesiumColor],
// dashLength: 8.0,
},
},
});
}
// 生成动态线实体
const drawLineFlowEntity = (positions, cesiumColor,width=5) => {
return new mars3d.graphic.PolylineEntity({
positions: positions,
style: {
width: width,
clampToGround: true,
materialType: mars3d.MaterialType.LineFlowColor,
materialOptions: {
color: cesiumColor,
speed: 1000,
percent: 1,
alpha: 1
},
},
});
}
const drawLineFlowEntityColor = (positions, cesiumColor,width=5) => {
return new mars3d.graphic.PolylineEntity({
positions: positions,
style: {
width: width,
clampToGround: true,
materialType: mars3d.MaterialType.LineFlowColor,
materialOptions: {
color: cesiumColor,
speed: 1000,
percent: 1,
alpha: 1
},
},
});
}
const drawLineFlowEntityColor1 = (positions, cesiumColor,width=5) => {
return new mars3d.graphic.PolylineEntity({
positions: positions,
style: {
width: width,
clampToGround: true,
materialType: mars3d.MaterialType.LineFlowColor,
materialOptions: {
color: cesiumColor,
speed: 1000,
percent: 1,
alpha: 1
},
},
});
}
const drawLineFlowEntityColor2 = (positions, cesiumColor,width=5) => {
return new mars3d.graphic.PolylineEntity({
positions: positions,
style: {
width: width,
clampToGround: true,
materialType: mars3d.MaterialType.LineFlowColor,
materialOptions: {
color: cesiumColor,
speed: 1000,
percent: 1,
alpha: 1
},
},
});
}
//删除路线
export const clearRouterFunc = () => {
if (pathGraphicLayers == null) {
return false
} else {
pathGraphicLayers.clear();
}
if (pathOneGraphicLayers == null) {
return false
} else {
pathOneGraphicLayers.clear();
}
}
//删除水网路线
export const clearWaterRouterFunc = () => {
if (pathWaterGraphicLayers == null) {
return false
} else {
pathWaterGraphicLayers.clear();
}
}
//删除路网路线
export const clearRoadRouterFunc = () => {
if (pathRoadGraphicLayers == null) {
return false
} else {
pathRoadGraphicLayers.clear();
}
}
export const clearRoadRouterFunc1 = () => {
if (pathRoadGraphicLayers1 == null) {
return false
} else {
pathRoadGraphicLayers1.clear();
}
}
export const clearRoadRouterFunc2 = () => {
if (pathRoadGraphicLayers2 == null) {
return false
} else {
pathRoadGraphicLayers2.clear();
}
}
//计算最近路线
const getMinimumRoute = (pathObject) => {
//备份Object
let pathObjectClone = deepClone(pathObject)
let { allCoordinates, startLngLat, endLngLat, startRouterLngLat, endRouterLngLat, gdRoute, postGisRoute } = pathObjectClone
// 当只有一个点时终点说明高德地图和postgis都未查询到线路直接返回两点
if (allCoordinates.length <= 1) {
pathObjectClone.allCoordinates = [startLngLat, endLngLat]
return pathObjectClone
}
//当postgis寻路时计算两条线路的重叠之处
if (postGisRoute.length && gdRoute.length) {
//实例化turf标准格式
let gdRouteLine = turf.lineString(gdRoute);
let postGisRouteLine = turf.lineString(postGisRoute);
//获取postgis和高德寻路的所有交点
let intersectsGeojson = turf.lineIntersect(gdRouteLine, postGisRouteLine);
let intersectsCoordinates = getMultPointCoordinatesFromGeoJson(intersectsGeojson)
//如果相交点大于1说明路线有重复部分
if (intersectsCoordinates.length > 1) {
let lastIntersectsCoordinates = intersectsCoordinates[0]
let [slicedGdCoordinates, slicedPostGisCoordinates] = sliceByPoint(startRouterLngLat, gdRouteLine, endRouterLngLat, postGisRoute, lastIntersectsCoordinates)
allCoordinates = slicedGdCoordinates.concat(slicedPostGisCoordinates)
//处理后的结果赋值给pathObjectClone
pathObjectClone.gdRoute = slicedGdCoordinates
pathObjectClone.postGisRoute = slicedPostGisCoordinates
gdRouteLine = turf.lineString(slicedGdCoordinates);
postGisRouteLine = turf.lineString(slicedPostGisCoordinates);
}
// 阈值计算重复路线,去除重复线路
let overlapping = turf.lineOverlap(gdRouteLine, postGisRouteLine, { tolerance: 0.1 });
if (overlapping.features.length) {
let lastOverlapPoint = overlapping.features.at(-1).geometry.coordinates[0]
let [overlapGdCoordinates, overlapPostGisCoordinates] = sliceByPoint(startRouterLngLat, gdRouteLine, endRouterLngLat, postGisRoute, lastOverlapPoint)
allCoordinates = overlapGdCoordinates.concat(overlapPostGisCoordinates)
// 连接路段平滑过渡
}
}
// 转成turf标准线格式
let allRouteLine = turf.lineString(allCoordinates);
// 转成turf标准点格式
let startLngLatPoint = turf.point(startLngLat);
let startRouterLngLatPoint = turf.point(startRouterLngLat);
let endLngLatPoint = turf.point(endLngLat);
let endRouterLngLatPoint = turf.point(endRouterLngLat);
//获取终点到导航线最近的点
let snappedGeojson = turf.nearestPointOnLine(allRouteLine, endLngLatPoint, { units: 'miles' });
let snappedCoordinates = getOnePointCoordinatesFromGeoJson(snappedGeojson)
// 根据最近的点截取路线,取前半部分
let slicedGeojson = turf.lineSlice(startRouterLngLat, turf.point(snappedCoordinates), allRouteLine);
let slicedCoordinates = getOnePointCoordinatesFromGeoJson(slicedGeojson)
//把截取后的路线赋值给pathObjectClone
pathObjectClone.allCoordinates = slicedCoordinates
//计算出发地到目的地的图上距离(直线)
let distanceStartToEnd = turf.distance(startLngLatPoint, endLngLatPoint)
//计算出发点到出发导航路线出发点的步行距离
let distanceStartToStartRoute = turf.distance(startLngLatPoint, startRouterLngLatPoint)
//计算终点到出发导航路线终点的步行距离
let distanceEndToEndRoute = turf.distance(endLngLatPoint, endRouterLngLatPoint)
//如果出发点与目的地的实际距离小于步行的距离,直接使用出发点到目的地的距离,导航此时不适用
if (distanceStartToEnd < (distanceStartToStartRoute + distanceEndToEndRoute)) {
pathObjectClone.allCoordinates = [startLngLat, endLngLat]
}
//把终点到导航终点改为距离线路的最近的的点
pathObjectClone.endRouterLngLat = snappedCoordinates
return pathObjectClone
}
const sliceByPoint = (line1Start, line1, line2End, line2, point) => {
/**
* pointline1line2
* line1Start:line1 [lng.lat]
* line2End:line2 [lng,lat]
*/
//拷贝line2的坐标数组进行倒序排列
let line2Copy = [...line2]
line2Copy.reverse()
let line2CopyReverseLineString = turf.lineString(line2Copy);
// 根据point截取路线line1取前半部分
// 根据point截取路线line2取后半部分
//然后将两部分拼接让line1路线从第一个交点处转向line2路段
let slicedLine1Geojson = turf.lineSlice(line1Start, turf.point(point), line1);
let slicedLine1Coordinates = getOnePointCoordinatesFromGeoJson(slicedLine1Geojson)
let slicedLine2Geojson = turf.lineSlice(line2End, turf.point(point), line2CopyReverseLineString);
let slicedLine2Coordinates = getOnePointCoordinatesFromGeoJson(slicedLine2Geojson)
slicedLine2Coordinates.reverse()
return [slicedLine1Coordinates, slicedLine2Coordinates]
}
// 坐标转geoJson
const comLineStringGeoJson = (coordinates) => {
return {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": coordinates,
"type": "LineString"
}
}
}
// 从一条线的geometry中获取坐标
const getOneLineCoordinatesFromGeometry = (geometry) => {
let coordinates = geometry.coordinates
// console.log('geometry::: ', geometry);
let list = []
if (geometry.type == "MultiLineString") {
coordinates.map(coord => {
list = list.concat(coord)
})
} else if (geometry.type == 'LineString') {
list = list.concat(geometry.coordinates)
} else {
list = []
}
return list
}
//从一个点的geojson中返回坐标点
const getOnePointCoordinatesFromGeoJson = (geojson) => {
return geojson.geometry.coordinates
}
//从多个点的geojson中返回坐标点
const getMultPointCoordinatesFromGeoJson = (geojson) => {
// console.log('geojson::: ', geojson);
return geojson.features.map(feature => {
return feature.geometry.coordinates
})
}
// 全局漫游
let carGraphicEntity = null;
let carGraphicLayer = null;
export const handlerStartRoaming = (coordinates,roaming=true)=>{
if(carGraphicLayer == null){
carGraphicLayer = new mars3d.layer.GraphicLayer();
window.globalMap.addLayer(carGraphicLayer);
}else{
carGraphicLayer.clear();
}
carGraphicEntity = new mars3d.graphic.FixedRoute({
name: "步行路线",
frameRate: 1,
speed: 500,
autoStop: false, // 到达终点自动停止
clockLoop: true, // 循环播放
positions: coordinates,
pauseTime: 0,
camera: {
type: "gs",
radius: 2500
},
model: {
// url: "//data.mars3d.cn/gltf/mars/car/bus3.gltf",
url:"/cartoon_fire_truck/xiaofangche.gltf",
scale: 5,
minimumPixelSize: 50,
clampToGround: true
},
circle: {
radius: 10,
materialType: mars3d.MaterialType.CircleWave,
materialOptions: {
color: "#ffff00",
opacity: 0.3,
speed: 10,
count: 3,
gradient: 0.1
},
clampToGround: true
}
})
carGraphicLayer.addGraphic(carGraphicEntity)
// 开始漫游
carGraphicEntity.enabled = roaming;
carGraphicEntity.start()
}
export const handlerStopRoaming = ()=>{
if(carGraphicEntity){
carGraphicLayer.removeGraphic(carGraphicEntity);
carGraphicEntity = null;
}
}

View File

@ -0,0 +1,28 @@
export class Url {
/**
* url
* @param {Object} data {a:1}
* @returns {string}
*/
getParam(data) {
let url = '';
for (let k in data) {
let value = data[k] !== undefined ? data[k] : '';
if (value !== undefined && value !== "" && value !== null) {
url += `&${k}=${encodeURIComponent(value)}`
}
}
return url ? url.substring(1) : ''
}
/**
* url
* @param {string} url url
* @param {Json} data json
* @returns {string}
*/
getUrl(url, data) {
//看原始url地址中开头是否带?,然后拼接处理好的参数
return url += (url.indexOf('?') < 0 ? '?' : '') + this.getParam(data)
}
}

View File

@ -0,0 +1,147 @@
/**
* Created by jiachenpan on 16/11/18.
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if (('' + time).length === 10) time = parseInt(time) * 1000
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
export function formatTime(format) {
const now = new Date()
var o = {
'M+': now.getMonth() + 1, // month
'd+': now.getDate(), // day
'h+': now.getHours(), // hour
'm+': now.getMinutes(), // minute
's+': now.getSeconds(), // second
'q+': Math.floor((now.getMonth() + 3) / 3), // quarter
'S': now.getMilliseconds() // millisecond
}
if (/(y+)/.test(format)) {
format = format.replace(RegExp.$1,
(now.getFullYear() + '').substr(4 - RegExp.$1.length))
}
for (var k in o) {
if (new RegExp('(' + k + ')').test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length))
}
}
return format
}
// 将list转成tree使用前注意把array进行深拷贝
export function listToTreeSelect(array, parent, tree) {
tree = typeof tree !== 'undefined' ? tree : []
parent = typeof parent !== 'undefined' ? parent : {
id: null
}
var children = array.filter((val) => {
return val.parentId === parent.id
})
if (children.length > 0) {
if (parent.id === null) {
tree = children
} else {
parent['children'] = children
}
children.forEach((val) => {
listToTreeSelect(array, val)
})
}
return tree
}
// 深拷贝
export const deepClone = (obj) => {
var objArray = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (obj[key] && typeof obj[key] === "object") {
objArray[key] = deepClone(obj[key]);
} else {
objArray[key] = obj[key];
}
}
}
}
return objArray;
}
export const generateRandomString = (e = null) => {
e = e || 32;
let t = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz012345678",
a = t.length,
n = "";
for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a));
return n
}
export const diffArrFunc = (arr1, arr2) => {
let oneArr = arr1;
let twoArr = arr2;
let diffArr = []
for (let i = 0; i < oneArr.length; i++) {
let flag = true
for (let j = 0; j < twoArr.length; j++) {
if (twoArr[j] === oneArr[i]) {
flag = false
break
}
}
if (flag) {
diffArr.push(oneArr[i])
}
}
return diffArr
}
// 判断的是否是JSON字符串
export const isJson=(str)=>{
if (typeof str == 'string') {
try {
var obj = JSON.parse(str);
// 等于这个条件说明就是JSON字符串 会返回true
if (typeof obj == 'object' && obj) {
return true;
} else {
//不是就返回false
return false;
}
} catch (e) {
return false;
}
}
return false;
}

View File

@ -30,6 +30,41 @@
/>
</div>
<!-- 云台控制 -->
<div class="ptz-control">
<img src="@/assets/images/chart/zhigan/component/cloud-control.png" />
云台控制
<!-- 云台遥控器 -->
<div class="ptz-control-container" v-if="ptzVisible">
<p>方向控制</p>
<div class="button-container">
<div class="button" v-for="(item,index) in directionCommends" :key="index" @click="ptzClick(item);"
:style="{'color':item.state ? '#408eff' : '#ffffff'}"
>
{{ item.name }}
</div>
</div>
<p>镜头控制</p>
<div class="button-container">
<div class="button" v-for="(item,index) in monitorCommends" :key="index" @click="ptzClick(item);"
:style="{'color':item.state ? '#408eff' : '#ffffff'}"
>
{{ item.name }}
</div>
</div>
</div>
</div>
<div class="mainBodyDiv">
<!-- 监控列表 -->
@ -79,7 +114,7 @@
v-for="(videoItem, videoIndex) in playList"
v-show="videoIndex < option.dataStyle.nowType"
:key="videoIndex"
@click="changeThisVideoIfIsNum(videoIndex)"
@click="changeThisVideoIfIsNum(videoIndex,videoItem)"
>
<!-- 监控名称 -->
<div class="rightVideoItemTitle" >
@ -235,9 +270,31 @@
limit:9999
})
const monitorList = ref([]);
interface Monitor {
id: string;
name: string;
model: string;
status: string;
manufacturer: string;
serialNumber: string;
ip: string;
channel: number;
lng: any;
lat: any;
updateTime: string;
appKey: string;
appSecret: string;
port: string;
regionPathName: string;
cameraType: number;
serialNumberRcx: any;
}
const monitorList = ref<Monitor[]>([]);
function getMonitorList(){
Axios({
method: "get",
url: VITE_GLOB_API_URL + '/api/FireManagement/GetCameraInfoPageList',
@ -246,11 +303,11 @@
'X-Token': localStorage.getItem("X-Token")
}
}).then(res=>{
monitorList.value = [];
monitorList.value = res.data.result.items;
})
}
getMonitorList()
@ -346,10 +403,11 @@
//
const changeThisFlag = ref(false);
const changeThisNum = ref(9);
const changeThisNum = ref<number>();
//
function changeThisVideo(videoIndex) {
if (videoIndex == changeThisNum.value) {
changeThisNum.value = 9;
changeThisFlag.value = false;
@ -360,7 +418,11 @@
}
// -
function changeThisVideoIfIsNum(videoIndex) {
function changeThisVideoIfIsNum(videoIndex,videoItem:Monitor) {
currentMonitor.value = videoItem;
console.log("data",videoItem,currentMonitor.value);
if (!option.videoList[videoIndex].videourl) {
if (changeThisNum.value == videoIndex) {
changeThisNum.value = 9;
@ -404,7 +466,13 @@
}
//
function clickListVideo(item) {
function clickListVideo(item:Monitor) {
currentMonitor.value = item;
//
if(changeThisNum.value == undefined){
createMessage.warning('请选择需要播放的窗口!');
return null;
}
//
@ -484,6 +552,9 @@
//
onMounted(() => {
//
getMonitorList();
// id
if (!option.dataStyle.timestamp) {
option.dataStyle.timestamp = dayjs().unix();
@ -541,6 +612,139 @@
(option.dataStyle.leftDivVideoListIconWidth / 23) * 16;
},
);
//
const ptzVisible = ref<Boolean>(true);
const currentMonitor = ref<Monitor>();
interface Commend {
name:string;
value:string;
state:boolean;
}
//
const directionCommends = ref<Commend[]>([
{
name:"左转",
value:"LEFT",
state:false
},{
name:"右转",
value:"RIGHT",
state:false
},{
name:"上转",
value:"UP",
state:false
},{
name:"下转",
value:"DOWN",
state:false
},{
name:"左上",
value:"LEFT_UP",
state:false
},{
name:"左下",
value:"LEFT_DOWN",
state:false
},{
name:"右上",
value:"RIGHT_UP",
state:false
},{
name:"右下",
value:"RIGHT_DOWN",
state:false
}
])
const monitorCommends = ref<Commend[]>([
{
name:"焦距变大",
value:"ZOOM_IN",
state:false
},{
name:"焦距变小",
value:"ZOOM_OUT",
state:false
},{
name:"焦点前移",
value:"FOCUS_NEAR",
state:false
},{
name:"焦点后移",
value:"FOCUS_FAR",
state:false
},{
name:"光圈扩大",
value:"IRIS_ENLARGE",
state:false
},{
name:"光圈缩小",
value:"IRIS_REDUCE",
state:false
}
])
//
const ptzClick = (commend:Commend):void|null => {
//
if(!currentMonitor.value){
alert("请选择需要操作的监控");
return null;
}
//
if(!commend.state){
directionCommends.value?.map((item,index)=>{
item.state = false;
})
monitorCommends.value?.map((item,index)=>{
item.state = false;
})
}
commend.state = !commend.state;
let data = {
cameraIndexCode:currentMonitor.value.serialNumber,
url:currentMonitor.value.ip,
appkey:currentMonitor.value.appKey,
appsecret:currentMonitor.value.appSecret,
port:currentMonitor.value.port,
action: commend.state ? 0 : 1,
command: commend.value,
speed:5,
presetIndex:20,
}
console.log("data",data);
Axios({
method: "get",
url: VITE_GLOB_API_URL + '/api/FireManagement/HKControlling',
params:data,
headers: {
'X-Token': localStorage.getItem("X-Token")
}
}).then(response => {
createMessage.success(`${commend.name}操作成功`);
}).catch(error => {
console.error(error);
createMessage.warning('操作失败!');
})
}
</script>
<style lang="scss" scoped>
@ -588,6 +792,52 @@
display: inline-flex;
}
.ptz-control{
display: inline-flex;
position:absolute;
top:30px;
right:80px;
cursor:pointer;
color:#fff;
border-radius:5px;
background:rgba(0,0,0,0.4);
line-height:24px;
padding:5px 12px;
img{
width:24px;
margin-right:2px;
}
&:hover .ptz-control-container{
display:block;
}
.ptz-control-container{
width:400px;
background:rgba(0,0,0,0.7);
padding:20px;
position:absolute;
top:36px;
right:0px;
z-index:999;
display:none;
border-radius:5px;
.button-container{
display: grid;
gap:8px;
grid-template-columns: repeat(4, 1fr);
.button{
padding:8px 10px;
background:rgba(0,0,0,0.6);
border-radius:4px;
margin:4px 0px;
text-align:center;
}
}
}
}
//
.mainBodyDiv {
padding-top: v-bind('`${h*75/838}px`');

View File

@ -1,5 +1,5 @@
<template>
<div class="video-container" :id="'player'+props.monitor.serialNumber">
<div class="video-container" :id="'player'+props.monitor.serialNumber.trim()">
</div>
</template>
@ -11,7 +11,6 @@ import {onMounted,defineProps} from 'vue';
import { getAppEnvConfig } from '@/utils/env'
var { VITE_GLOB_API_URL } = getAppEnvConfig();
console.log("monitor123",props.monitor);
const props = defineProps({
monitor:{
@ -71,11 +70,30 @@ function realplay() {
//
function getPlayUrl(){
// let queryParam = {
// deviceCode:props.monitor.serialNumber,
// protocol:"wss"
// }
let queryParam = {
deviceCode:props.monitor.serialNumber,
cameraIndexCode:props.monitor.serialNumber,
url:props.monitor.ip,
appkey:props.monitor.appKey,
appsecret:props.monitor.appSecret,
port:props.monitor.port,
protocol:"wss"
}
axios(VITE_GLOB_API_URL+"/api/FireManagement/GetPreviewURLs",{
let url = VITE_GLOB_API_URL+"/api/FireManagement/GetPreviewURL";
// if(props.monitor.appKey == "23604396"){
// url = VITE_GLOB_API_URL+"/api/FireManagement/GetPreviewURLs"
// }else {
// url = VITE_GLOB_API_URL+"/api/FireManagement/GetPreviewURLs2"
// }
axios(url,{
method:"get",
params:queryParam
}).then(res=>{
@ -84,6 +102,9 @@ function getPlayUrl(){
realplay();
}
})
}
</script>

View File

@ -17,12 +17,12 @@ export const airPortStore = defineStore({
video_id: null,
},
liveInfo: {
rtmp: 'rtmp://175.27.168.120:6019/live/',
url: 'http://175.27.168.120:6012/live/',
rtmp: 'rtmp://wrj.wisestcity.com:6019/live/',
url: 'https://wrj.wisestcity.com:6012/live/',
// rtmp: 'rtmp://box.wisestcity.com:1935/live/',
// url: 'http://box.wisestcity.com:8081/live/',
// rtmp: 'http://175.27.168.120:5005/rtc/v1/whip/?app=live&stream=',
// url: 'http://175.27.168.120:5005/rtc/v1/whep/?app=live&stream=',
// rtmp: 'http://wrj.wisestcity.com:5005/rtc/v1/whip/?app=live&stream=',
// url: 'http://wrj.wisestcity.com:5005/rtc/v1/whep/?app=live&stream=',
},
gateway: null,
project: null,

View File

@ -42,6 +42,7 @@ export function getAppEnvConfig() {
VITE_GLOB_API_URL_SITUATION,
VITE_GLOB_FILE_PREVIEW,
VITE_GLOB_GEOSERVER_BASE_URL,
VITE_GLOB_COFFEE_API_URL,
} = ENV;
let { VITE_GLOB_API_URL } = ENV;
if (localStorage.getItem(API_ADDRESS)) {
@ -61,6 +62,7 @@ export function getAppEnvConfig() {
VITE_GLOB_API_URL_SITUATION,
VITE_GLOB_FILE_PREVIEW,
VITE_GLOB_GEOSERVER_BASE_URL,
VITE_GLOB_COFFEE_API_URL,
};
}

View File

@ -12,7 +12,7 @@ const { createMessage } = useMessage();
const seizeClientId = 'mqtt_client_1581F8HGX254V00A0BUY_seize';
const connection = {
protocol: 'ws',
host: '175.27.168.120',
host: 'wrj.wisestcity.com',
// server less服务器只有两种协议mqtts: 8883; wss: 8084
port: 6010,
endpoint: '/mqtt',

View File

@ -2,6 +2,9 @@ import { BasicColumn, FormSchema } from '@/components/Table';
import { h } from 'vue';
import { Tag } from 'ant-design-vue';
import { getPosGroupList } from '@/api/demo/system';
import axios from 'axios';
import { getAppEnvConfig } from '@/utils/env';
let { VITE_GLOB_API_URL } = getAppEnvConfig();
export const columns: BasicColumn[] = [
{
@ -47,6 +50,38 @@ export const columns: BasicColumn[] = [
}
];
async function getCamreas(){
try {
const url = "/api/SysDataItemDetail/Load";
const querys = { code: "FMCamera" };
const res = await axios({
method: "get",
url: VITE_GLOB_API_URL + url,
params: querys,
headers: {
'X-Token': localStorage.getItem("X-Token")
}
});
// 直接返回普通数组不要用ref/reactive
return res.data.result?.map(item => ({
value: item.itemValue,
label: item.itemName
})) || [];
} catch (error) {
console.error('获取摄像头类型失败:', error);
return []; // 返回空数组
}
}
let options = getCamreas();
console.log("options999",options)
export const searchFormSchema: FormSchema[] = [
{
field: 'model',
@ -60,29 +95,43 @@ export const searchFormSchema: FormSchema[] = [
},
defaultValue: null,
componentProps: {
placeholder:"摄像头类型",
options: [
{
value: 1,
label: '移动端上报',
},
{
value: 2,
label: '高空瞭望',
},
{
value: 3,
label: '无人机上报',
},
{
value: 4,
label: '人工合并',
},
{
value: 6,
label: '卫星遥感',
},
],
placeholder: "摄像头类型",
// 确保返回普通数组不要用ref/reactive包裹
options: (() => {
// 先返回空数组
const options = [];
// 异步获取数据并更新
(async () => {
try {
const url = "/api/SysDataItemDetail/Load";
const querys = { code: "FMCamera" };
const res = await axios({
method: "get",
url: VITE_GLOB_API_URL + url,
params: querys,
headers: {
'X-Token': localStorage.getItem("X-Token")
}
});
const newOptions = res.data.result?.map(item => ({
value: item.itemValue,
label: item.itemName
})) || [];
// 直接修改数组内容
options.length = 0;
options.push(...newOptions);
} catch (error) {
console.error('获取摄像头类型失败:', error);
}
})();
return options; // 返回空数组不是Promise
})()
},
},
{

View File

@ -8,6 +8,11 @@
<PermissionBtn @btn-event="onBtnClicked" />
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'model'">
{{ cameraTypes[record.model] }}
</template>
<template v-if="column.key === 'action'">
<TableAction
:actions="[
@ -60,6 +65,10 @@
import { AddModal, Detail } from './page';
import { PermissionBtn } from '@/components/PermissionBtn/index';
import { columns, searchFormSchema } from './data';
import axios from 'axios';
import { getAppEnvConfig } from '@/utils/env';
let { VITE_GLOB_API_URL } = getAppEnvConfig();
defineOptions({ name: 'DeptManagement' });
const { createConfirm, createMessage } = useMessage();
@ -189,6 +198,32 @@
};
const cameraTypes = ref({});
const getCameraType = () => {
let url = "/api/SysDataItemDetail/Load";
let querys = {
code:"FMCamera"
}
axios({
method: "get",
url: VITE_GLOB_API_URL + url,
params: querys,
headers: {
'X-Token': localStorage.getItem("X-Token")
}
}).then(res=>{
// cameraTypes.value =
res.data.result?.forEach((item,index)=>{
cameraTypes.value[item.itemValue] = item.itemName
})
})
}
getCameraType();
</script>

View File

@ -68,6 +68,7 @@ export const searchFormSchema: FormSchema[] = [
},
}
];
export const formGroupSchema: FormSchema[] = [
{
field: 'posGroupId',

View File

@ -0,0 +1,73 @@
// vite.config.ts
import { defineApplicationConfig } from "file:///E:/projects/%E6%9E%97%E4%B8%9A%E9%98%B2%E7%81%AB/LinYeFangHuoVersion1.0/LinYeFangHuo/internal/vite-config/dist/index.mjs";
import { mars3dPlugin } from "file:///E:/projects/%E6%9E%97%E4%B8%9A%E9%98%B2%E7%81%AB/LinYeFangHuoVersion1.0/LinYeFangHuo/node_modules/.pnpm/vite-plugin-mars3d@3.1.3_rollup@3.29.5/node_modules/vite-plugin-mars3d/dist/index.js";
var vite_config_default = defineApplicationConfig({
overrides: {
optimizeDeps: {
include: [
"echarts/core",
"echarts/charts",
"echarts/components",
"echarts/renderers",
"qrcode",
"@iconify/iconify",
"ant-design-vue/es/locale/zh_CN",
"ant-design-vue/es/locale/en_US",
"@/../lib/vform/designer.umd.js"
]
},
build: {
/* 其他build生产打包配置省略 */
//...
target: "esnext",
commonjsOptions: {
include: [
/node_modules|lib/,
/node_modules|packages/
]
//这里记得把lib目录加进来否则生产打包会报错
}
},
server: {
proxy: {
"/basic-api": {
target: "http://localhost:3000",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/basic-api`), "")
// only https
// secure: false
},
"/upload": {
target: "http://localhost:3300/upload",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/upload`), "")
}
},
warmup: {
clientFiles: ["./index.html", "./src/{views,components}/*"]
}
},
define: {
"process.env": {
BASE_URL: "/"
}
},
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: `@import "src/styles/common/style.scss";`
}
}
},
plugins: [
mars3dPlugin()
]
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxwcm9qZWN0c1xcXFxcdTY3OTdcdTRFMUFcdTk2MzJcdTcwNkJcXFxcTGluWWVGYW5nSHVvVmVyc2lvbjEuMFxcXFxMaW5ZZUZhbmdIdW9cIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkU6XFxcXHByb2plY3RzXFxcXFx1Njc5N1x1NEUxQVx1OTYzMlx1NzA2QlxcXFxMaW5ZZUZhbmdIdW9WZXJzaW9uMS4wXFxcXExpblllRmFuZ0h1b1xcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdHMvJUU2JTlFJTk3JUU0JUI4JTlBJUU5JTk4JUIyJUU3JTgxJUFCL0xpblllRmFuZ0h1b1ZlcnNpb24xLjAvTGluWWVGYW5nSHVvL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQXBwbGljYXRpb25Db25maWcgfSBmcm9tICdAdmJlbi92aXRlLWNvbmZpZyc7XG5pbXBvcnQge21hcnMzZFBsdWdpbn0gZnJvbSAndml0ZS1wbHVnaW4tbWFyczNkJztcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQXBwbGljYXRpb25Db25maWcoe1xuICBvdmVycmlkZXM6IHtcbiAgICBvcHRpbWl6ZURlcHM6IHtcbiAgICAgIGluY2x1ZGU6IFtcbiAgICAgICAgJ2VjaGFydHMvY29yZScsXG4gICAgICAgICdlY2hhcnRzL2NoYXJ0cycsXG4gICAgICAgICdlY2hhcnRzL2NvbXBvbmVudHMnLFxuICAgICAgICAnZWNoYXJ0cy9yZW5kZXJlcnMnLFxuICAgICAgICAncXJjb2RlJyxcbiAgICAgICAgJ0BpY29uaWZ5L2ljb25pZnknLFxuICAgICAgICAnYW50LWRlc2lnbi12dWUvZXMvbG9jYWxlL3poX0NOJyxcbiAgICAgICAgJ2FudC1kZXNpZ24tdnVlL2VzL2xvY2FsZS9lbl9VUycsXG4gICAgICAgICdALy4uL2xpYi92Zm9ybS9kZXNpZ25lci51bWQuanMnLFxuICAgICAgXSxcbiAgICB9LFxuICAgIGJ1aWxkOiB7XG4gICAgICAvKiBcdTUxNzZcdTRFRDZidWlsZFx1NzUxRlx1NEVBN1x1NjI1M1x1NTMwNVx1OTE0RFx1N0Y2RVx1NzcwMVx1NzU2NSAqL1xuICAgICAgLy8uLi5cbiAgICAgIHRhcmdldDogJ2VzbmV4dCcsXG4gICAgICBjb21tb25qc09wdGlvbnM6IHtcbiAgICAgICAgaW5jbHVkZTogW1xuICAgICAgICAgIC9ub2RlX21vZHVsZXN8bGliLyxcbiAgICAgICAgICAvbm9kZV9tb2R1bGVzfHBhY2thZ2VzL1xuICAgICAgICBdIC8vXHU4RkQ5XHU5MUNDXHU4QkIwXHU1Rjk3XHU2MjhBbGliXHU3NkVFXHU1RjU1XHU1MkEwXHU4RkRCXHU2NzY1XHVGRjBDXHU1NDI2XHU1MjE5XHU3NTFGXHU0RUE3XHU2MjUzXHU1MzA1XHU0RjFBXHU2MkE1XHU5NTE5XHVGRjAxXHVGRjAxXG4gICAgICB9LFxuICAgIH0sXG4gICAgc2VydmVyOiB7XG4gICAgICBwcm94eToge1xuICAgICAgICAnL2Jhc2ljLWFwaSc6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vbG9jYWxob3N0OjMwMDAnLFxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcbiAgICAgICAgICB3czogdHJ1ZSxcbiAgICAgICAgICByZXdyaXRlOiAocGF0aCkgPT4gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4vYmFzaWMtYXBpYCksICcnKSxcbiAgICAgICAgICAvLyBvbmx5IGh0dHBzXG4gICAgICAgICAgLy8gc2VjdXJlOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICAnL3VwbG9hZCc6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vbG9jYWxob3N0OjMzMDAvdXBsb2FkJyxcbiAgICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXG4gICAgICAgICAgd3M6IHRydWUsXG4gICAgICAgICAgcmV3cml0ZTogKHBhdGgpID0+IHBhdGgucmVwbGFjZShuZXcgUmVnRXhwKGBeL3VwbG9hZGApLCAnJyksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgd2FybXVwOiB7XG4gICAgICAgIGNsaWVudEZpbGVzOiBbJy4vaW5kZXguaHRtbCcsICcuL3NyYy97dmlld3MsY29tcG9uZW50c30vKiddLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGRlZmluZToge1xuICAgICAgJ3Byb2Nlc3MuZW52Jzoge1xuICAgICAgICBCQVNFX1VSTDogJy8nLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGNzczoge1xuICAgICAgcHJlcHJvY2Vzc29yT3B0aW9uczoge1xuICAgICAgICBzY3NzOiB7XG4gICAgICAgICAgamF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgYWRkaXRpb25hbERhdGE6IGBAaW1wb3J0IFwic3JjL3N0eWxlcy9jb21tb24vc3R5bGUuc2Nzc1wiO2AsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAgcGx1Z2luczogW1xuICAgICAgbWFyczNkUGx1Z2luKClcbiAgICBdLFxuICB9LFxufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXdYLFNBQVMsK0JBQStCO0FBQ2hhLFNBQVEsb0JBQW1CO0FBRTNCLElBQU8sc0JBQVEsd0JBQXdCO0FBQUEsRUFDckMsV0FBVztBQUFBLElBQ1QsY0FBYztBQUFBLE1BQ1osU0FBUztBQUFBLFFBQ1A7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFDQSxPQUFPO0FBQUE7QUFBQTtBQUFBLE1BR0wsUUFBUTtBQUFBLE1BQ1IsaUJBQWlCO0FBQUEsUUFDZixTQUFTO0FBQUEsVUFDUDtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUE7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ04sT0FBTztBQUFBLFFBQ0wsY0FBYztBQUFBLFVBQ1osUUFBUTtBQUFBLFVBQ1IsY0FBYztBQUFBLFVBQ2QsSUFBSTtBQUFBLFVBQ0osU0FBUyxDQUFDLFNBQVMsS0FBSyxRQUFRLElBQUksT0FBTyxhQUFhLEdBQUcsRUFBRTtBQUFBO0FBQUE7QUFBQSxRQUcvRDtBQUFBLFFBQ0EsV0FBVztBQUFBLFVBQ1QsUUFBUTtBQUFBLFVBQ1IsY0FBYztBQUFBLFVBQ2QsSUFBSTtBQUFBLFVBQ0osU0FBUyxDQUFDLFNBQVMsS0FBSyxRQUFRLElBQUksT0FBTyxVQUFVLEdBQUcsRUFBRTtBQUFBLFFBQzVEO0FBQUEsTUFDRjtBQUFBLE1BQ0EsUUFBUTtBQUFBLFFBQ04sYUFBYSxDQUFDLGdCQUFnQiw0QkFBNEI7QUFBQSxNQUM1RDtBQUFBLElBQ0Y7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOLGVBQWU7QUFBQSxRQUNiLFVBQVU7QUFBQSxNQUNaO0FBQUEsSUFDRjtBQUFBLElBQ0EsS0FBSztBQUFBLE1BQ0gscUJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFVBQ0osbUJBQW1CO0FBQUEsVUFDbkIsZ0JBQWdCO0FBQUEsUUFDbEI7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsU0FBUztBQUFBLE1BQ1AsYUFBYTtBQUFBLElBQ2Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K

View File

@ -0,0 +1,73 @@
// vite.config.ts
import { defineApplicationConfig } from "file:///E:/projects/%E6%9E%97%E4%B8%9A%E9%98%B2%E7%81%AB/LinYeFangHuoVersion1.0/LinYeFangHuo/internal/vite-config/dist/index.mjs";
import { mars3dPlugin } from "file:///E:/projects/%E6%9E%97%E4%B8%9A%E9%98%B2%E7%81%AB/LinYeFangHuoVersion1.0/LinYeFangHuo/node_modules/.pnpm/vite-plugin-mars3d@3.1.3_rollup@3.29.5/node_modules/vite-plugin-mars3d/dist/index.js";
var vite_config_default = defineApplicationConfig({
overrides: {
optimizeDeps: {
include: [
"echarts/core",
"echarts/charts",
"echarts/components",
"echarts/renderers",
"qrcode",
"@iconify/iconify",
"ant-design-vue/es/locale/zh_CN",
"ant-design-vue/es/locale/en_US",
"@/../lib/vform/designer.umd.js"
]
},
build: {
/* 其他build生产打包配置省略 */
//...
target: "esnext",
commonjsOptions: {
include: [
/node_modules|lib/,
/node_modules|packages/
]
//这里记得把lib目录加进来否则生产打包会报错
}
},
server: {
proxy: {
"/basic-api": {
target: "http://localhost:3000",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/basic-api`), "")
// only https
// secure: false
},
"/upload": {
target: "http://localhost:3300/upload",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/upload`), "")
}
},
warmup: {
clientFiles: ["./index.html", "./src/{views,components}/*"]
}
},
define: {
"process.env": {
BASE_URL: "/"
}
},
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: `@import "src/styles/common/style.scss";`
}
}
},
plugins: [
mars3dPlugin()
]
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxwcm9qZWN0c1xcXFxcdTY3OTdcdTRFMUFcdTk2MzJcdTcwNkJcXFxcTGluWWVGYW5nSHVvVmVyc2lvbjEuMFxcXFxMaW5ZZUZhbmdIdW9cIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkU6XFxcXHByb2plY3RzXFxcXFx1Njc5N1x1NEUxQVx1OTYzMlx1NzA2QlxcXFxMaW5ZZUZhbmdIdW9WZXJzaW9uMS4wXFxcXExpblllRmFuZ0h1b1xcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdHMvJUU2JTlFJTk3JUU0JUI4JTlBJUU5JTk4JUIyJUU3JTgxJUFCL0xpblllRmFuZ0h1b1ZlcnNpb24xLjAvTGluWWVGYW5nSHVvL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQXBwbGljYXRpb25Db25maWcgfSBmcm9tICdAdmJlbi92aXRlLWNvbmZpZyc7XG5pbXBvcnQge21hcnMzZFBsdWdpbn0gZnJvbSAndml0ZS1wbHVnaW4tbWFyczNkJztcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQXBwbGljYXRpb25Db25maWcoe1xuICBvdmVycmlkZXM6IHtcbiAgICBvcHRpbWl6ZURlcHM6IHtcbiAgICAgIGluY2x1ZGU6IFtcbiAgICAgICAgJ2VjaGFydHMvY29yZScsXG4gICAgICAgICdlY2hhcnRzL2NoYXJ0cycsXG4gICAgICAgICdlY2hhcnRzL2NvbXBvbmVudHMnLFxuICAgICAgICAnZWNoYXJ0cy9yZW5kZXJlcnMnLFxuICAgICAgICAncXJjb2RlJyxcbiAgICAgICAgJ0BpY29uaWZ5L2ljb25pZnknLFxuICAgICAgICAnYW50LWRlc2lnbi12dWUvZXMvbG9jYWxlL3poX0NOJyxcbiAgICAgICAgJ2FudC1kZXNpZ24tdnVlL2VzL2xvY2FsZS9lbl9VUycsXG4gICAgICAgICdALy4uL2xpYi92Zm9ybS9kZXNpZ25lci51bWQuanMnLFxuICAgICAgXSxcbiAgICB9LFxuICAgIGJ1aWxkOiB7XG4gICAgICAvKiBcdTUxNzZcdTRFRDZidWlsZFx1NzUxRlx1NEVBN1x1NjI1M1x1NTMwNVx1OTE0RFx1N0Y2RVx1NzcwMVx1NzU2NSAqL1xuICAgICAgLy8uLi5cbiAgICAgIHRhcmdldDogJ2VzbmV4dCcsXG4gICAgICBjb21tb25qc09wdGlvbnM6IHtcbiAgICAgICAgaW5jbHVkZTogW1xuICAgICAgICAgIC9ub2RlX21vZHVsZXN8bGliLyxcbiAgICAgICAgICAvbm9kZV9tb2R1bGVzfHBhY2thZ2VzL1xuICAgICAgICBdIC8vXHU4RkQ5XHU5MUNDXHU4QkIwXHU1Rjk3XHU2MjhBbGliXHU3NkVFXHU1RjU1XHU1MkEwXHU4RkRCXHU2NzY1XHVGRjBDXHU1NDI2XHU1MjE5XHU3NTFGXHU0RUE3XHU2MjUzXHU1MzA1XHU0RjFBXHU2MkE1XHU5NTE5XHVGRjAxXHVGRjAxXG4gICAgICB9LFxuICAgIH0sXG4gICAgc2VydmVyOiB7XG4gICAgICBwcm94eToge1xuICAgICAgICAnL2Jhc2ljLWFwaSc6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vbG9jYWxob3N0OjMwMDAnLFxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcbiAgICAgICAgICB3czogdHJ1ZSxcbiAgICAgICAgICByZXdyaXRlOiAocGF0aCkgPT4gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4vYmFzaWMtYXBpYCksICcnKSxcbiAgICAgICAgICAvLyBvbmx5IGh0dHBzXG4gICAgICAgICAgLy8gc2VjdXJlOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICAnL3VwbG9hZCc6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vbG9jYWxob3N0OjMzMDAvdXBsb2FkJyxcbiAgICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXG4gICAgICAgICAgd3M6IHRydWUsXG4gICAgICAgICAgcmV3cml0ZTogKHBhdGgpID0+IHBhdGgucmVwbGFjZShuZXcgUmVnRXhwKGBeL3VwbG9hZGApLCAnJyksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgd2FybXVwOiB7XG4gICAgICAgIGNsaWVudEZpbGVzOiBbJy4vaW5kZXguaHRtbCcsICcuL3NyYy97dmlld3MsY29tcG9uZW50c30vKiddLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGRlZmluZToge1xuICAgICAgJ3Byb2Nlc3MuZW52Jzoge1xuICAgICAgICBCQVNFX1VSTDogJy8nLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGNzczoge1xuICAgICAgcHJlcHJvY2Vzc29yT3B0aW9uczoge1xuICAgICAgICBzY3NzOiB7XG4gICAgICAgICAgamF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgYWRkaXRpb25hbERhdGE6IGBAaW1wb3J0IFwic3JjL3N0eWxlcy9jb21tb24vc3R5bGUuc2Nzc1wiO2AsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAgcGx1Z2luczogW1xuICAgICAgbWFyczNkUGx1Z2luKClcbiAgICBdLFxuICB9LFxufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXdYLFNBQVMsK0JBQStCO0FBQ2hhLFNBQVEsb0JBQW1CO0FBRTNCLElBQU8sc0JBQVEsd0JBQXdCO0FBQUEsRUFDckMsV0FBVztBQUFBLElBQ1QsY0FBYztBQUFBLE1BQ1osU0FBUztBQUFBLFFBQ1A7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFDQSxPQUFPO0FBQUE7QUFBQTtBQUFBLE1BR0wsUUFBUTtBQUFBLE1BQ1IsaUJBQWlCO0FBQUEsUUFDZixTQUFTO0FBQUEsVUFDUDtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUE7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ04sT0FBTztBQUFBLFFBQ0wsY0FBYztBQUFBLFVBQ1osUUFBUTtBQUFBLFVBQ1IsY0FBYztBQUFBLFVBQ2QsSUFBSTtBQUFBLFVBQ0osU0FBUyxDQUFDLFNBQVMsS0FBSyxRQUFRLElBQUksT0FBTyxhQUFhLEdBQUcsRUFBRTtBQUFBO0FBQUE7QUFBQSxRQUcvRDtBQUFBLFFBQ0EsV0FBVztBQUFBLFVBQ1QsUUFBUTtBQUFBLFVBQ1IsY0FBYztBQUFBLFVBQ2QsSUFBSTtBQUFBLFVBQ0osU0FBUyxDQUFDLFNBQVMsS0FBSyxRQUFRLElBQUksT0FBTyxVQUFVLEdBQUcsRUFBRTtBQUFBLFFBQzVEO0FBQUEsTUFDRjtBQUFBLE1BQ0EsUUFBUTtBQUFBLFFBQ04sYUFBYSxDQUFDLGdCQUFnQiw0QkFBNEI7QUFBQSxNQUM1RDtBQUFBLElBQ0Y7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOLGVBQWU7QUFBQSxRQUNiLFVBQVU7QUFBQSxNQUNaO0FBQUEsSUFDRjtBQUFBLElBQ0EsS0FBSztBQUFBLE1BQ0gscUJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFVBQ0osbUJBQW1CO0FBQUEsVUFDbkIsZ0JBQWdCO0FBQUEsUUFDbEI7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsU0FBUztBQUFBLE1BQ1AsYUFBYTtBQUFBLElBQ2Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K

View File

@ -0,0 +1,73 @@
// vite.config.ts
import { defineApplicationConfig } from "file:///E:/projects/%E6%9E%97%E4%B8%9A%E9%98%B2%E7%81%AB/LinYeFangHuoVersion1.0/LinYeFangHuo/internal/vite-config/dist/index.mjs";
import { mars3dPlugin } from "file:///E:/projects/%E6%9E%97%E4%B8%9A%E9%98%B2%E7%81%AB/LinYeFangHuoVersion1.0/LinYeFangHuo/node_modules/.pnpm/vite-plugin-mars3d@3.1.3_rollup@3.29.5/node_modules/vite-plugin-mars3d/dist/index.js";
var vite_config_default = defineApplicationConfig({
overrides: {
optimizeDeps: {
include: [
"echarts/core",
"echarts/charts",
"echarts/components",
"echarts/renderers",
"qrcode",
"@iconify/iconify",
"ant-design-vue/es/locale/zh_CN",
"ant-design-vue/es/locale/en_US",
"@/../lib/vform/designer.umd.js"
]
},
build: {
/* 其他build生产打包配置省略 */
//...
target: "esnext",
commonjsOptions: {
include: [
/node_modules|lib/,
/node_modules|packages/
]
//这里记得把lib目录加进来否则生产打包会报错
}
},
server: {
proxy: {
"/basic-api": {
target: "http://localhost:3000",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/basic-api`), "")
// only https
// secure: false
},
"/upload": {
target: "http://localhost:3300/upload",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/upload`), "")
}
},
warmup: {
clientFiles: ["./index.html", "./src/{views,components}/*"]
}
},
define: {
"process.env": {
BASE_URL: "/"
}
},
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: `@import "src/styles/common/style.scss";`
}
}
},
plugins: [
mars3dPlugin()
]
}
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxwcm9qZWN0c1xcXFxcdTY3OTdcdTRFMUFcdTk2MzJcdTcwNkJcXFxcTGluWWVGYW5nSHVvVmVyc2lvbjEuMFxcXFxMaW5ZZUZhbmdIdW9cIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkU6XFxcXHByb2plY3RzXFxcXFx1Njc5N1x1NEUxQVx1OTYzMlx1NzA2QlxcXFxMaW5ZZUZhbmdIdW9WZXJzaW9uMS4wXFxcXExpblllRmFuZ0h1b1xcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vRTovcHJvamVjdHMvJUU2JTlFJTk3JUU0JUI4JTlBJUU5JTk4JUIyJUU3JTgxJUFCL0xpblllRmFuZ0h1b1ZlcnNpb24xLjAvTGluWWVGYW5nSHVvL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQXBwbGljYXRpb25Db25maWcgfSBmcm9tICdAdmJlbi92aXRlLWNvbmZpZyc7XG5pbXBvcnQge21hcnMzZFBsdWdpbn0gZnJvbSAndml0ZS1wbHVnaW4tbWFyczNkJztcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQXBwbGljYXRpb25Db25maWcoe1xuICBvdmVycmlkZXM6IHtcbiAgICBvcHRpbWl6ZURlcHM6IHtcbiAgICAgIGluY2x1ZGU6IFtcbiAgICAgICAgJ2VjaGFydHMvY29yZScsXG4gICAgICAgICdlY2hhcnRzL2NoYXJ0cycsXG4gICAgICAgICdlY2hhcnRzL2NvbXBvbmVudHMnLFxuICAgICAgICAnZWNoYXJ0cy9yZW5kZXJlcnMnLFxuICAgICAgICAncXJjb2RlJyxcbiAgICAgICAgJ0BpY29uaWZ5L2ljb25pZnknLFxuICAgICAgICAnYW50LWRlc2lnbi12dWUvZXMvbG9jYWxlL3poX0NOJyxcbiAgICAgICAgJ2FudC1kZXNpZ24tdnVlL2VzL2xvY2FsZS9lbl9VUycsXG4gICAgICAgICdALy4uL2xpYi92Zm9ybS9kZXNpZ25lci51bWQuanMnLFxuICAgICAgXSxcbiAgICB9LFxuICAgIGJ1aWxkOiB7XG4gICAgICAvKiBcdTUxNzZcdTRFRDZidWlsZFx1NzUxRlx1NEVBN1x1NjI1M1x1NTMwNVx1OTE0RFx1N0Y2RVx1NzcwMVx1NzU2NSAqL1xuICAgICAgLy8uLi5cbiAgICAgIHRhcmdldDogJ2VzbmV4dCcsXG4gICAgICBjb21tb25qc09wdGlvbnM6IHtcbiAgICAgICAgaW5jbHVkZTogW1xuICAgICAgICAgIC9ub2RlX21vZHVsZXN8bGliLyxcbiAgICAgICAgICAvbm9kZV9tb2R1bGVzfHBhY2thZ2VzL1xuICAgICAgICBdIC8vXHU4RkQ5XHU5MUNDXHU4QkIwXHU1Rjk3XHU2MjhBbGliXHU3NkVFXHU1RjU1XHU1MkEwXHU4RkRCXHU2NzY1XHVGRjBDXHU1NDI2XHU1MjE5XHU3NTFGXHU0RUE3XHU2MjUzXHU1MzA1XHU0RjFBXHU2MkE1XHU5NTE5XHVGRjAxXHVGRjAxXG4gICAgICB9LFxuICAgIH0sXG4gICAgc2VydmVyOiB7XG4gICAgICBwcm94eToge1xuICAgICAgICAnL2Jhc2ljLWFwaSc6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vbG9jYWxob3N0OjMwMDAnLFxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcbiAgICAgICAgICB3czogdHJ1ZSxcbiAgICAgICAgICByZXdyaXRlOiAocGF0aCkgPT4gcGF0aC5yZXBsYWNlKG5ldyBSZWdFeHAoYF4vYmFzaWMtYXBpYCksICcnKSxcbiAgICAgICAgICAvLyBvbmx5IGh0dHBzXG4gICAgICAgICAgLy8gc2VjdXJlOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICAnL3VwbG9hZCc6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdodHRwOi8vbG9jYWxob3N0OjMzMDAvdXBsb2FkJyxcbiAgICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXG4gICAgICAgICAgd3M6IHRydWUsXG4gICAgICAgICAgcmV3cml0ZTogKHBhdGgpID0+IHBhdGgucmVwbGFjZShuZXcgUmVnRXhwKGBeL3VwbG9hZGApLCAnJyksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgd2FybXVwOiB7XG4gICAgICAgIGNsaWVudEZpbGVzOiBbJy4vaW5kZXguaHRtbCcsICcuL3NyYy97dmlld3MsY29tcG9uZW50c30vKiddLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGRlZmluZToge1xuICAgICAgJ3Byb2Nlc3MuZW52Jzoge1xuICAgICAgICBCQVNFX1VSTDogJy8nLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGNzczoge1xuICAgICAgcHJlcHJvY2Vzc29yT3B0aW9uczoge1xuICAgICAgICBzY3NzOiB7XG4gICAgICAgICAgamF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgYWRkaXRpb25hbERhdGE6IGBAaW1wb3J0IFwic3JjL3N0eWxlcy9jb21tb24vc3R5bGUuc2Nzc1wiO2AsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gICAgcGx1Z2luczogW1xuICAgICAgbWFyczNkUGx1Z2luKClcbiAgICBdLFxuICB9LFxufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXdYLFNBQVMsK0JBQStCO0FBQ2hhLFNBQVEsb0JBQW1CO0FBRTNCLElBQU8sc0JBQVEsd0JBQXdCO0FBQUEsRUFDckMsV0FBVztBQUFBLElBQ1QsY0FBYztBQUFBLE1BQ1osU0FBUztBQUFBLFFBQ1A7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsUUFDQTtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFDQSxPQUFPO0FBQUE7QUFBQTtBQUFBLE1BR0wsUUFBUTtBQUFBLE1BQ1IsaUJBQWlCO0FBQUEsUUFDZixTQUFTO0FBQUEsVUFDUDtBQUFBLFVBQ0E7QUFBQSxRQUNGO0FBQUE7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ04sT0FBTztBQUFBLFFBQ0wsY0FBYztBQUFBLFVBQ1osUUFBUTtBQUFBLFVBQ1IsY0FBYztBQUFBLFVBQ2QsSUFBSTtBQUFBLFVBQ0osU0FBUyxDQUFDLFNBQVMsS0FBSyxRQUFRLElBQUksT0FBTyxhQUFhLEdBQUcsRUFBRTtBQUFBO0FBQUE7QUFBQSxRQUcvRDtBQUFBLFFBQ0EsV0FBVztBQUFBLFVBQ1QsUUFBUTtBQUFBLFVBQ1IsY0FBYztBQUFBLFVBQ2QsSUFBSTtBQUFBLFVBQ0osU0FBUyxDQUFDLFNBQVMsS0FBSyxRQUFRLElBQUksT0FBTyxVQUFVLEdBQUcsRUFBRTtBQUFBLFFBQzVEO0FBQUEsTUFDRjtBQUFBLE1BQ0EsUUFBUTtBQUFBLFFBQ04sYUFBYSxDQUFDLGdCQUFnQiw0QkFBNEI7QUFBQSxNQUM1RDtBQUFBLElBQ0Y7QUFBQSxJQUNBLFFBQVE7QUFBQSxNQUNOLGVBQWU7QUFBQSxRQUNiLFVBQVU7QUFBQSxNQUNaO0FBQUEsSUFDRjtBQUFBLElBQ0EsS0FBSztBQUFBLE1BQ0gscUJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFVBQ0osbUJBQW1CO0FBQUEsVUFDbkIsZ0JBQWdCO0FBQUEsUUFDbEI7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLElBQ0EsU0FBUztBQUFBLE1BQ1AsYUFBYTtBQUFBLElBQ2Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K