merge
|
|
@ -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
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 860 B |
|
After Width: | Height: | Size: 889 B |
|
After Width: | Height: | Size: 950 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 980 B |
|
After Width: | Height: | Size: 689 B |
|
After Width: | Height: | Size: 800 B |
|
After Width: | Height: | Size: 619 B |
|
After Width: | Height: | Size: 771 B |
|
After Width: | Height: | Size: 882 B |
|
|
@ -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",
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 306 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 528 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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',
|
||||
};
|
||||
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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',
|
||||
};
|
||||
|
|
@ -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>
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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',
|
||||
};
|
||||
|
|
@ -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};"> </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>
|
||||
|
|
@ -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;
|
||||
|
|
@ -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,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
})
|
||||
|
||||
}
|
||||
|
|
@ -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]
|
||||
}
|
||||
|
|
@ -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 = () => {
|
||||
|
||||
}
|
||||
|
|
@ -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 }
|
||||
|
|
@ -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) => {
|
||||
/**
|
||||
* 根据点point把line1的前半部分和line2的后半部分进行拼接
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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`');
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})()
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ export const searchFormSchema: FormSchema[] = [
|
|||
},
|
||||
}
|
||||
];
|
||||
|
||||
export const formGroupSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'posGroupId',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||