<template>
|
<ul class="btn-list" v-if="waylineAbout.isShow">
|
<!-- 参数按钮 -->
|
<li class="s-btn" v-for="(item, index) in btnList" :key="index">
|
<div class="title">{{ item.title }}</div>
|
<a-popover placement="leftTop" trigger="click" arrow-point-at-center class="param-popover">
|
<template #title>
|
<span>{{ item.title }}</span>
|
</template>
|
<template #content>
|
<div class="popover-content">
|
<div v-for="sParam in item.param" :key="sParam.key" class="content-box">
|
<div>{{ sParam.title }}</div>
|
<a-input v-model:value="sParam.value" placeholder="请输入参数" v-if="!sParam.isRadio" />
|
<a-radio-group :options="sParam.options" v-model:value="sParam.value" v-else />
|
<div class="annotation" v-if="sParam.annotation">
|
注:{{ sParam.annotation }}
|
</div>
|
</div>
|
<div class="btn-tool">
|
<a-button @click="resetParamSetting(item)">重置</a-button>
|
<a-button type="primary" @click="item.event(item)">确定</a-button>
|
</div>
|
</div>
|
</template>
|
<div class="btn" @click="() => saveInitPopoverParam(item.param)"
|
:style="{ backgroundColor: item.selected ? '#2D8CF0' : '#323131' }">
|
<img :src="item.icon" alt="icon">
|
</div>
|
</a-popover>
|
</li>
|
<!-- 确认和取消按钮 -->
|
<li class="s-btn">
|
<div class="title">取消编辑</div>
|
<div class="btn cancel-edit" @click="cencalEdit">
|
<CloseOutlined />
|
</div>
|
</li>
|
<li class="s-btn">
|
<div class="title">确认编辑</div>
|
<div class="btn confirm-edit" @click="confirmEdit">
|
<CheckOutlined />
|
</div>
|
</li>
|
</ul>
|
</template>
|
<script lang="ts" setup>
|
import { ref, computed } from 'vue'
|
import { useMyStore } from '/@/store'
|
import axios from 'axios'
|
import JSZIP from 'jszip'
|
import { saveAs } from 'file-saver'
|
import { message } from 'ant-design-vue'
|
import { cloneDeep } from 'lodash'
|
import {
|
CloseOutlined,
|
CheckOutlined
|
} from '@ant-design/icons-vue'
|
// 初始化jszip
|
const JsZip = new JSZIP()
|
|
const store = useMyStore()
|
|
const prefix = import.meta.env.VITE_MEDIAPANEL_API_URL
|
|
const getResource = (name: string) => {
|
return new URL(`/src/assets/icons/${name}`, import.meta.url).href
|
}
|
|
interface popoverParamType {
|
title: string,
|
key: string,
|
isRadio?: boolean,
|
annotation?: string,
|
options?: {
|
label: string,
|
value: string
|
}[],
|
value: string
|
}
|
|
// 点击按钮list
|
interface sBtn {
|
key: string,
|
icon: string,
|
title: string,
|
distinguish?: string,
|
param: popoverParamType[],
|
event: Function,
|
selected?: boolean
|
}
|
|
// 保存当前选择的kmz文件
|
const kmzFileZip = ref()
|
// 当前选中的位置
|
const currentPosition = ref()
|
const curKmzName = ref<string>('')
|
// 当前kmzpath
|
const curKmzPath = ref<string>('')
|
// popover初始参数
|
const initPopoverParam = ref<popoverParamType[]>([])
|
|
const btnList = ref<sBtn[]>([
|
// 开始录像
|
{
|
key: 'startRecord',
|
icon: getResource('waylinetool/camera-on.png'),
|
title: '开始录像',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '拍摄照片文件后缀',
|
key: 'fileSuffix',
|
annotation: '为生成媒体文件命名时将额外附带该后缀',
|
value: ''
|
},
|
{
|
title: '拍摄照片存储类型',
|
key: 'payloadLensIndex',
|
isRadio: true,
|
options: [
|
{ label: '存储变焦镜头拍摄照片', value: 'zoom' },
|
{ label: '存储广角镜头拍摄照片', value: 'wide' },
|
{ label: '存储红外镜头拍摄照片', value: 'ir' },
|
{ label: '存储窄带镜头拍摄照片', value: 'narrow_band' },
|
{ label: '全部使用', value: 'zoom, wide, ir, narrow_band' }
|
],
|
value: ''
|
},
|
{
|
title: '是否使用全局存储类型',
|
key: 'useGlobalPayloadLensIndex',
|
isRadio: true,
|
options: [
|
{ label: '不使用全局设置', value: '0' },
|
{ label: '使用全局设置', value: '1' }
|
],
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('startRecord', obj)
|
}
|
},
|
// 停止录像
|
{
|
key: 'stopRecord',
|
icon: getResource('waylinetool/camera-off.png'),
|
title: '停止录像',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '拍摄照片存储类型',
|
key: 'payloadLensIndex',
|
isRadio: true,
|
options: [
|
{ label: '存储变焦镜头拍摄照片', value: 'zoom' },
|
{ label: '存储广角镜头拍摄照片', value: 'wide' },
|
{ label: '存储红外镜头拍摄照片', value: 'ir' },
|
{ label: '存储窄带镜头拍摄照片', value: 'narrow_band' },
|
{ label: '全部使用', value: 'zoom, wide, ir, narrow_band' }
|
],
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('stopRecord', obj)
|
}
|
},
|
// 开始等时间隔拍照
|
{
|
key: 'time',
|
icon: getResource('waylinetool/shoot1.png'),
|
title: '开始等时间隔拍照',
|
param: [],
|
event: (obj: sBtn) => {
|
obj.selected = true
|
editKmlFile('time')
|
}
|
},
|
// 开始等距间隔拍照
|
{
|
key: 'distance',
|
icon: getResource('waylinetool/shoot2.png'),
|
title: '开始等距间隔拍照',
|
param: [],
|
event: (obj: sBtn) => {
|
obj.selected = true
|
editKmlFile('distance')
|
}
|
},
|
// 结束间隔拍照
|
{
|
key: 'deleteShootType',
|
icon: getResource('waylinetool/shoot3.png'),
|
title: '结束间隔拍照',
|
param: [],
|
event: (obj: sBtn) => {
|
obj.selected = true
|
editKmlFile('deleteShootType')
|
}
|
},
|
// 悬停
|
{
|
key: 'hover',
|
icon: getResource('waylinetool/xt.png'),
|
title: '悬停',
|
param: [
|
{
|
title: '飞行器悬停等待时间',
|
key: 'hoverTime',
|
annotation: '参数需大于0, 单位为秒',
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('hover', obj)
|
}
|
},
|
// 飞行器偏航角
|
{
|
key: 'rotateYaw',
|
icon: getResource('waylinetool/droneyaw.png'),
|
title: '飞行器偏航角',
|
param: [
|
{
|
title: '飞行器目标偏航角(相对于地理北)',
|
key: 'aircraftHeading',
|
annotation: '范围为-180°到180°,飞行器旋转至该目标偏航角。0°为正北方向,90°为正东方向,-90°为正西方向,-180°/180°为正南方向。',
|
value: ''
|
},
|
{
|
title: '飞行器偏航角转动模式',
|
key: 'aircraftPathMode',
|
isRadio: true,
|
options: [
|
{ label: '顺时针旋转', value: 'clockwise' },
|
{ label: '逆时针旋转', value: 'counterClockwise' }
|
],
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('rotateYaw', obj)
|
}
|
},
|
// 云台偏航角
|
{
|
key: 'gimbalRotate',
|
distinguish: 'yaw',
|
icon: getResource('waylinetool/holderyaw.png'),
|
title: '云台偏航角',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '云台转动模式',
|
key: 'gimbalRotateMode',
|
isRadio: true,
|
options: [
|
{ label: '绝对角度,相对于正北方的角度', value: 'relativeAngle' },
|
{ label: '相对角度,相对于飞行器机头的角度', value: 'absoluteAngle' }
|
],
|
value: ''
|
},
|
{
|
title: '是否使能云台Yaw转动',
|
key: 'gimbalYawRotateEnable',
|
isRadio: true,
|
options: [
|
{ label: '不使能', value: '0' },
|
{ label: '使能', value: '1' }
|
],
|
value: ''
|
},
|
{
|
title: '云台Yaw转动角度',
|
key: 'gimbalYawRotateAngle',
|
annotation: '不同云台可转动范围不同',
|
value: ''
|
},
|
{
|
title: '云台完成转动用时',
|
key: 'gimbalRotateTime',
|
annotation: '单位为秒',
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('gimbalRotate', obj, {
|
gimbalHeadingYawBase: 'north',
|
gimbalRotateMode: 'relativeAngle',
|
// 上下摆动 pitch xyz中心点为基准
|
gimbalPitchRotateEnable: 0,
|
gimbalPitchRotateAngle: 0,
|
// 摆动 roll 已x位基准
|
gimbalRollRotateEnable: 0,
|
gimbalRollRotateAngle: 0,
|
// 左右摆动 yaw xyz中心点为基准
|
gimbalRotateTimeEnable: 0,
|
})
|
}
|
},
|
// 云台俯仰角
|
{
|
key: 'gimbalRotate',
|
distinguish: 'pitch',
|
icon: getResource('waylinetool/holdertilt.png'),
|
title: '云台俯仰角',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '云台转动模式',
|
key: 'gimbalRotateMode',
|
isRadio: true,
|
options: [
|
{ label: '绝对角度,相对于正北方的角度', value: 'relativeAngle' },
|
{ label: '相对角度,相对于飞行器机头的角度', value: 'absoluteAngle' }
|
],
|
value: ''
|
},
|
{
|
title: '是否使能云台Pitch转动',
|
key: 'gimbalPitchRotateEnable',
|
isRadio: true,
|
options: [
|
{ label: '不使能', value: '0' },
|
{ label: '使能', value: '1' }
|
],
|
value: ''
|
},
|
{
|
title: '云台Pitch转动角度',
|
key: 'gimbalPitchRotateAngle',
|
annotation: '不同云台可转动范围不同',
|
value: ''
|
},
|
{
|
title: '云台完成转动用时',
|
key: 'gimbalRotateTime',
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('gimbalRotate', obj, {
|
gimbalHeadingYawBase: 'north',
|
gimbalRotateMode: 'relativeAngle',
|
gimbalRollRotateEnable: 0,
|
gimbalRollRotateAngle: 0,
|
gimbalYawRotateEnable: 0,
|
gimbalYawRotateAngle: 0,
|
gimbalRotateTimeEnable: 0,
|
})
|
}
|
},
|
// 拍照
|
{
|
key: 'takePhoto',
|
icon: getResource('waylinetool/camera.png'),
|
title: '拍照',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '拍摄照片文件后缀',
|
key: 'fileSuffix',
|
annotation: '为生成媒体文件命名时将额外附带该后缀。',
|
value: ''
|
},
|
{
|
title: '拍摄照片存储类型',
|
key: 'payloadLensIndex',
|
isRadio: true,
|
options: [
|
{ label: '存储变焦镜头拍摄照片', value: 'zoom' },
|
{ label: '存储广角镜头拍摄照片', value: 'wide' },
|
{ label: '存储红外镜头拍摄照片', value: 'ir' },
|
{ label: '存储窄带镜头拍摄照片', value: 'narrow_band' },
|
{ label: '全部使用', value: 'zoom, wide, ir, narrow_band' }
|
],
|
value: ''
|
},
|
{
|
title: '是否使用全局存储类型',
|
key: 'useGlobalPayloadLensIndex',
|
isRadio: true,
|
options: [
|
{ label: '不使用全局设置', value: '0' },
|
{ label: '使用全局设置', value: '1' }
|
],
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('takePhoto', obj)
|
}
|
},
|
// 相机变焦
|
{
|
key: 'zoom',
|
icon: getResource('waylinetool/fd.png'),
|
title: '相机变焦',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '变焦焦距',
|
key: 'focalLength',
|
annotation: '单位mm,值>0',
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('zoom', obj)
|
}
|
},
|
// 创建文件夹
|
{
|
key: 'customDirName',
|
icon: getResource('waylinetool/create-file.png'),
|
title: '创建文件夹',
|
param: [
|
{
|
title: '负载挂载位置',
|
key: 'payloadPositionIndex',
|
isRadio: true,
|
options: [
|
{ label: '飞行器1号挂载位置', value: '0' },
|
{ label: '飞行器2号挂载位置', value: '1' },
|
{ label: '飞行器3号挂载位置', value: '2' },
|
],
|
annotation: '飞行器1号挂载位置。M300 RTK,M350 RTK机型,对应机身左前方。其它机型,对应主云台。飞行器2号挂载位置。M300 RTK,M350 RTK机型,对应机身右前方。飞行器3号挂载位置。M300 RTK,M350 RTK机型,对应机身上方。',
|
value: ''
|
},
|
{
|
title: '新文件夹的名称',
|
key: 'directoryName',
|
value: ''
|
}
|
],
|
event: (obj: sBtn) => {
|
paramPopover('customDirName', obj)
|
}
|
}
|
])
|
|
const waylineAbout = computed(() => {
|
return store.state.waylineTool
|
})
|
|
/**
|
* @description: 读取kmz文件转blob
|
* @param {*} kmzPath 文件地址
|
* @return {*} void
|
*/
|
const readKmzFile = (kmzPath: string) => {
|
return axios.get(kmzPath, { responseType: 'arraybuffer' })
|
.then(fileRes => fileRes.data)
|
.then(kmzData => JsZip.loadAsync(kmzData)) // 解压kmz文件
|
.then(kmzZip => kmzZip)
|
.catch(() => message.error('请求kmz文件失败!!'))
|
}
|
|
watch(() => store.state.waylineTool.kmzPath, (n: string) => {
|
curKmzPath.value = n
|
const arr = n.split('/')
|
curKmzName.value = decodeURIComponent(arr[arr.length - 1])
|
readKmzFile(n).then(kmzFile => {
|
kmzFileZip.value = kmzFile
|
})
|
}, {
|
deep: true
|
})
|
|
watch(() => store.state.waylineTool.position, (position: number) => {
|
currentPosition.value = position
|
eventLight()
|
}, {
|
deep: true
|
})
|
|
// 事件高亮
|
const eventLight = () => {
|
// 已经添加的事件高亮
|
btnList.value.forEach(item => { item.selected = false })
|
kmzFileZip.value.file(/\.kml$/i)[0].async('text').then((content: string) => {
|
const regx = /<Placemark>([\s\S]*?)<\/Placemark>/g
|
const points = content.match(regx) || []
|
const funcRegx = /<wpml:actionActuatorFunc>([\s\S]*?)<\/wpml:actionActuatorFunc>/g
|
const funcs = (points[currentPosition.value] || '').match(funcRegx)
|
const funcNameRegx = /<wpml:actionActuatorFunc>(.*?)<\/wpml:actionActuatorFunc>/
|
const shootTypeRegx = /<wpml:shootType>([\s\S]*?)<\/wpml:shootType>/g
|
const shootType = (points[currentPosition.value] || '').match(shootTypeRegx)
|
const shootTypeValueRegx = /<wpml:shootType>(.*?)<\/wpml:shootType>/
|
|
// 云台正则
|
const actionRegx = /<wpml:action>([\s\S]*?)<\/wpml:action>/g
|
const actions = (points[currentPosition.value] || '').match(actionRegx)
|
const gimbalPitchRotateAngleRegx = /<wpml:gimbalPitchRotateAngle>(.*?)<\/wpml:gimbalPitchRotateAngle>/
|
const gimbalYawRotateAngleRegx = /<wpml:gimbalYawRotateAngle>(.*?)<\/wpml:gimbalYawRotateAngle>/
|
|
btnList.value.forEach(sBtn => {
|
funcs?.forEach((func: string) => {
|
const funcName = func.match(funcNameRegx) || []
|
if (funcName[1] === sBtn.key && !sBtn.distinguish) {
|
sBtn.selected = true
|
}
|
})
|
shootType?.forEach((shootType: string) => {
|
const typeValue = shootType.match(shootTypeValueRegx) || []
|
if (typeValue[1] === sBtn.key) {
|
sBtn.selected = true
|
}
|
})
|
if (sBtn.distinguish) {
|
const action = actions?.find((action: string) => action.includes('<wpml:actionActuatorFunc>gimbalRotate</wpml:actionActuatorFunc>'))
|
const pitchAngle = action?.match(gimbalPitchRotateAngleRegx) || []
|
const yawAngle = action?.match(gimbalYawRotateAngleRegx) || []
|
if (!!Number(pitchAngle[1]) && sBtn.distinguish === 'pitch') {
|
sBtn.selected = true
|
}
|
if (!!Number(yawAngle[1]) && sBtn.distinguish === 'yaw') {
|
sBtn.selected = true
|
}
|
}
|
})
|
settingDefaultValue(content)
|
})
|
}
|
|
// popover设置默认值
|
const settingDefaultValue = (content: string) => {
|
const regx = /<Placemark>([\s\S]*?)<\/Placemark>/g
|
const points = content.match(regx) || []
|
// 当前选中的点
|
const currentPoint = points[currentPosition.value] || ''
|
const actionRegx = /<wpml:action>([\s\S]*?)<\/wpml:action>/g
|
const actionsKML = currentPoint.match(actionRegx)
|
btnList.value.forEach((sBtn: sBtn) => {
|
const kml = `<wpml:actionActuatorFunc>${sBtn.key}</wpml:actionActuatorFunc>`
|
const action = actionsKML?.find((action: string) => action.includes(kml))
|
sBtn.param.forEach((sParam) => {
|
const paramRegex = new RegExp(`<wpml:${sParam.key}>([\\s\\S]*?)<\\/wpml:${sParam.key}>`, 'g')
|
const actionParam = action?.match(paramRegex) || ['']
|
const infoRegx = new RegExp(`<wpml:${sParam.key}>([\\s\\S]*?)<\\/wpml:${sParam.key}>`)
|
const value: string[] = actionParam[0]?.match(infoRegx) || ['']
|
sParam.value = value[1] || ''
|
})
|
})
|
}
|
|
/**
|
* @description: 创建kml模版
|
* @param {*} actionId 事件id(唯一)
|
* @param {*} actionType 事件类型
|
* @param {*} param 事件参数
|
* @return {*} void
|
*/
|
const createActionKML = (actionId: string, actionType: string, param: any) => {
|
let paramKML = ''
|
Object.keys(param).forEach((key: string) => {
|
paramKML += `
|
<wpml:${key}>${param[key]}</wpml:${key}>
|
`
|
})
|
const template = `
|
<wpml:action>
|
<wpml:actionId>${actionId}</wpml:actionId>
|
<wpml:actionActuatorFunc>${actionType}</wpml:actionActuatorFunc>
|
<wpml:actionActuatorFuncParam>
|
${paramKML}
|
</wpml:actionActuatorFuncParam>
|
</wpml:action>
|
`
|
return template
|
}
|
|
/**
|
* @description: Popover参数编辑
|
* @param {*} btnobj: 事件按钮所有参数
|
* @param {*} eventType 事件类型
|
* @param {*} eventParam 事件参数Param
|
* @return {*}
|
*/
|
const paramPopover = (eventType: string, btnobj: sBtn, eventParam?: any) => {
|
// 判断参数是否为有存在空的
|
let isParamNull = false
|
btnobj.param.some((sParam: any) => {
|
isParamNull = sParam.value === ''
|
return isParamNull
|
})
|
if (isParamNull) return message.warning('确认失败,请检查填写的参数')
|
// 参数处理
|
const param = { ...eventParam }
|
btnobj.param.forEach((sParam: { key: string, value: string | number }) => {
|
param[sParam.key] = sParam.value
|
})
|
editKmlFile(eventType, param)
|
btnobj.selected = true
|
}
|
|
const saveInitPopoverParam = (param: popoverParamType[]) => {
|
initPopoverParam.value = cloneDeep(param)
|
}
|
|
const resetParamSetting = (btnParam: sBtn) => {
|
btnParam.param = cloneDeep(initPopoverParam.value)
|
}
|
|
/**
|
* @description: 修改template.kml文件
|
* @param {*} eventType 事件类型
|
* @param {*} eventParam 事件参数
|
* @return {*} void
|
*/
|
const editKmlFile = (eventType: string, eventParam?: any) => {
|
// kmzZip文件处理
|
const kmlFile = kmzFileZip.value.file(/\.kml$/i)[0]
|
kmlFile.async('text').then((kmlText: string) => {
|
const regx = /<Placemark>([\s\S]*?)<\/Placemark>/g
|
const points = kmlText.match(regx) || []
|
// 当前要修改的字段
|
// const curSelected: string | any = points?.find(item => item.includes(currentPosition.value.join(',')))
|
const curSelected: string | any = points[currentPosition.value]
|
// 判断是不是间隔拍照任务
|
if (eventType === 'time' || eventType === 'distance' || eventType === 'deleteShootType') {
|
// 判断当前选中的点是否存在shootType
|
const shootTypeRegx = /<wpml:shootType>([\s\S]*?)<\/wpml:shootType>/g
|
const kmlResult: string[] = curSelected.match(shootTypeRegx) || []
|
const shootTypeKML = kmlResult[0]
|
let replacedKML = ''
|
// 判断是不是结束间隔拍照任务
|
if (eventType === 'deleteShootType') {
|
if (!shootTypeKML) {
|
message.warning('暂未设置间隔任务,无法结束!!')
|
} else {
|
replacedKML = curSelected.replace(shootTypeRegx, '')
|
}
|
} else {
|
// 判断是否已经设置间隔拍照任务
|
if (shootTypeKML) {
|
replacedKML = curSelected.replace(shootTypeRegx, `<wpml:shootType>${eventType}</wpml:shootType>`)
|
} else {
|
// 判断是否存在actionGroup
|
const index = curSelected.indexOf('<wpml:actionGroup>')
|
if (index === -1) {
|
const placeMarkIdx = curSelected.indexOf('</Placemark>')
|
replacedKML = curSelected.slice(0, placeMarkIdx) + `<wpml:shootType>${eventType}</wpml:shootType>` + curSelected.slice(placeMarkIdx)
|
} else {
|
replacedKML = curSelected.slice(0, index) + `<wpml:shootType>${eventType}</wpml:shootType>` + curSelected.slice(index)
|
}
|
}
|
}
|
// 将另外两个间隔任务按钮高亮取消
|
btnList.value.forEach((sBtn: sBtn) => {
|
if (sBtn.key === 'time' || sBtn.key === 'distance' || sBtn.key === 'deleteShootType') {
|
if (sBtn.key !== eventType) {
|
sBtn.selected = false
|
}
|
}
|
})
|
// 替换原本KML
|
const replacedTemplateKML = kmlText.replace(curSelected, replacedKML)
|
JsZip.file('wpmz/template.kml', replacedTemplateKML)
|
kmzFileZip.value.file('wpmz/template.kml', replacedTemplateKML)
|
return
|
}
|
// 查找actionGroup
|
const actionGroupReg = /<wpml:actionGroup>([\s\S]*?)<\/wpml:actionGroup>/g
|
const actionGroup = curSelected.match(actionGroupReg) ? curSelected.match(actionGroupReg)[0] : ''
|
// 查找action
|
const actionReg = /<wpml:action>([\s\S]*?)<\/wpml:action>/g
|
const actions = actionGroup.match(actionReg) || []
|
|
// 判断kml文件中是否存在当前事件
|
const actionIndex = actions.findIndex((action: string) => action.includes(eventType))
|
if (actionIndex === -1) {
|
// 创建事件
|
const actionKML = createActionKML(actions.length, eventType, eventParam)
|
actions.push(actionKML)
|
} else {
|
// 移除当前存在的事件
|
actions.splice(actionIndex, 1)
|
}
|
|
let replacedActionsKML = ''
|
// 创建actionGroup
|
const actionGroupKML = `
|
<wpml:actionGroup>
|
${actions.join('')}
|
</wpml:actionGroup>
|
`
|
// 判断是否存在事件组
|
if (!actionGroup) {
|
const index = curSelected.indexOf('</Placemark>')
|
replacedActionsKML = curSelected.slice(0, index) + actionGroupKML + curSelected.slice(index)
|
} else {
|
// 替换原有的action
|
replacedActionsKML = curSelected.replace(actionGroupReg, actionGroupKML)
|
}
|
// Placemark代替
|
const replacedTemplateKML = kmlText.replace(curSelected, replacedActionsKML)
|
|
JsZip.file('wpmz/template.kml', replacedTemplateKML)
|
kmzFileZip.value.file('wpmz/template.kml', replacedTemplateKML)
|
})
|
}
|
|
const cencalEdit = () => {
|
readKmzFile(curKmzPath.value).then(kmzFile => {
|
kmzFileZip.value = kmzFile
|
eventLight()
|
})
|
}
|
|
const confirmEdit = () => {
|
JsZip.generateAsync({ type: 'blob' }).then(content => {
|
saveAs(content, curKmzName.value)
|
})
|
}
|
|
onMounted(() => {
|
kmzFileZip.value = null
|
})
|
</script>
|
<style lang="scss" scoped>
|
.btn-list {
|
position: absolute;
|
right: 75px;
|
top: 50%;
|
transform: translateY(-50%);
|
|
.s-btn {
|
margin-bottom: 15px;
|
display: flex;
|
align-items: center;
|
|
&:last-child {
|
margin: 0;
|
}
|
|
.title {
|
width: 130px;
|
text-align: right;
|
margin-right: 10px;
|
color: #fff;
|
text-shadow: 2px 2px 2px #000;
|
font-weight: bold;
|
}
|
|
.btn {
|
width: 34px;
|
height: 34px;
|
background-color: #323131;
|
cursor: pointer;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
|
img {
|
width: 20px;
|
}
|
}
|
}
|
|
.cancel-edit {
|
font-size: 20px;
|
color: #fff;
|
|
&:hover {
|
background-color: #FF4D4F;
|
}
|
}
|
|
.confirm-edit {
|
font-size: 20px;
|
color: #fff;
|
|
&:hover {
|
background-color: #1777FF;
|
}
|
}
|
}
|
|
.popover-content {
|
.content-box {
|
margin-bottom: 10px;
|
|
.annotation {
|
font-size: 12px;
|
color: rgb(188, 187, 187);
|
max-width: 300px;
|
}
|
}
|
|
.btn-tool {
|
display: flex;
|
justify-content: center;
|
gap: 10px;
|
|
.ant-btn {
|
flex: 1;
|
}
|
}
|
}
|
|
:deep() {
|
.ant-radio-wrapper {
|
display: block;
|
max-width: 300px;
|
text-wrap: wrap;
|
}
|
}
|
</style>
|