| | |
| | | <template> |
| | | <div class="setting"> |
| | | <a-popover |
| | | placement="bottom" |
| | | trigger="click" |
| | | :getPopupContainer="(triggerNode: any) => triggerNode.parentNode"> |
| | | <a-popover placement="bottom" trigger="click" :getPopupContainer="(triggerNode: any) => triggerNode.parentNode"> |
| | | <template #content> |
| | | <div class="setting-content"> |
| | | <div class="start-point common"> |
| | | <div class="title">起飞点</div> |
| | | <div class="value"> |
| | | {{ xmlTemplate.missionConfig?.takeOffRefPoint['#text'] !== '' ? '已设置' : '未设置' }} |
| | | </div> |
| | | </div> |
| | | <div class="photo-setting common"> |
| | | <div class="title">拍照设置</div> |
| | | <ul class="select-box"> |
| | | <li class="select-item">广角照片</li> |
| | | <li class="select-item">变焦照片</li> |
| | | <li |
| | | class="select-item" |
| | | v-for="item in photoSetting" |
| | | :key="item.value" |
| | | :style="{ |
| | | '--settingColor': xmlTemplate.Folder.payloadParam?.imageFormat['#text'] |
| | | .split(',') |
| | | .includes(item.value) |
| | | ? '#409eff' |
| | | : '#3c3c3c', |
| | | }" |
| | | @click="selectPhotoSetting(item.value)"> |
| | | {{ item.title }}照片 |
| | | </li> |
| | | </ul> |
| | | <div class="auto-low-light"> |
| | | <!-- <div class="auto-low-light"> |
| | | <div class="title">自动低光</div> |
| | | <a-switch /> |
| | | </div> |
| | | <a-tooltip |
| | | placement="right" |
| | | :title="tipDescriptionEnums.rowLightModeTip"> |
| | | <a-switch |
| | | v-model:checked="setting.orientedPhotoMode" |
| | | checkedValue="lowLightSmartShooting" |
| | | unCheckedValue="normalPhoto" /> |
| | | </a-tooltip> |
| | | </div> --> |
| | | </div> |
| | | <!-- 爬升 --> |
| | | <div class="climb-mode common"> |
| | | <a-tooltip placement="right" :title="tipDescriptionEnums.climbModeTip"> |
| | | <div class="mode-box"> |
| | | <a-radio-group v-model:value="xmlTemplate.missionConfig.flyToWaylineMode['#text']" button-style="solid"> |
| | | <a-radio-button value="safely">垂直爬升</a-radio-button> |
| | | <a-radio-button value="pointToPoint">倾斜爬升</a-radio-button> |
| | | </a-radio-group> |
| | | </div> |
| | | <div class="parameter-tool"> |
| | | <div class="example-img"> |
| | | <img :src="climbImage" alt="climb-img" /> |
| | | </div> |
| | | <ul class="parameter-btn"> |
| | | <li @click="numberControls(true, 100, 'takeOffSecurityHeight')">+100</li> |
| | | <li @click="numberControls(true, 10, 'takeOffSecurityHeight')">+10</li> |
| | | <li class="parameter-input"> |
| | | <a-input-number |
| | | :min="2" |
| | | :max="1500" |
| | | v-model:value="xmlTemplate.missionConfig.takeOffSecurityHeight['#text']"></a-input-number |
| | | >m |
| | | </li> |
| | | <li @click="numberControls(false, 100, 'takeOffSecurityHeight')">-100</li> |
| | | <li @click="numberControls(false, 10, 'takeOffSecurityHeight')">-10</li> |
| | | </ul> |
| | | </div> |
| | | </a-tooltip> |
| | | </div> |
| | | <!-- 高度模式 --> |
| | | <div class="height-mode common"> |
| | | <div class="title">航线高度模式</div> |
| | | <div class="mode-box"> |
| | | <a-radio-group button-style="solid"> |
| | | <a-radio-button value="a">绝对高度</a-radio-button> |
| | | <a-radio-button value="b">相对起飞高度</a-radio-button> |
| | | <a-radio-button value="c">相对地面高度</a-radio-button> |
| | | </a-radio-group> |
| | | <a-tooltip |
| | | placement="right" |
| | | :title="tipDescriptionEnums[xmlTemplate.Folder.waylineCoordinateSysParam.heightMode['#text']]"> |
| | | <div class="title">航线高度模式</div> |
| | | <div class="mode-box"> |
| | | <a-radio-group |
| | | v-model:value="xmlTemplate.Folder.waylineCoordinateSysParam.heightMode['#text']" |
| | | button-style="solid"> |
| | | <a-radio-button v-for="item in heightModeSetting" :key="item.value" :value="item.value">{{ |
| | | item.title |
| | | }}</a-radio-button> |
| | | </a-radio-group> |
| | | </div> |
| | | <div class="parameter-tool"> |
| | | <div class="example-img"> |
| | | <img :src="true ? heightModeSetting[0].img : heightModeSetting[1].img" alt="height-img" /> |
| | | </div> |
| | | <div class="parameter-btn"> |
| | | <li @click="numberControls(true, 100, 'globalHeight')">+100</li> |
| | | <li @click="numberControls(true, 10, 'globalHeight')">+10</li> |
| | | <li class="parameter-input"> |
| | | <a-input-number |
| | | :min="0" |
| | | :max="10000" |
| | | v-model:value="xmlTemplate.Folder.globalHeight['#text']"></a-input-number |
| | | >m |
| | | </li> |
| | | <li @click="numberControls(false, 100, 'globalHeight')">-100</li> |
| | | <li @click="numberControls(false, 10, 'globalHeight')">-10</li> |
| | | </div> |
| | | </div> |
| | | </a-tooltip> |
| | | </div> |
| | | <!-- 航线速度 --> |
| | | <div class="speed-setting common"> |
| | | <div class="title">全局航线速度</div> |
| | | <div class="speed-box"> |
| | | <div class="subtract" @click="numberControls(false, 1, 'autoFlightSpeed')">-</div> |
| | | <div class="text"> |
| | | <a-input-number |
| | | v-model:value="xmlTemplate.Folder.autoFlightSpeed['#text']" |
| | | :min="1" |
| | | :max="15" |
| | | class="value"> |
| | | </a-input-number> |
| | | m / s |
| | | </div> |
| | | <div class="add" @click="numberControls(true, 1, 'autoFlightSpeed')">+</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | const getResource = (name: string) => { |
| | | return new URL(`/src/assets/icons/${name}`, import.meta.url).href |
| | | import { reactive, defineProps } from 'vue' |
| | | import { tipDescriptionEnums } from './enums' |
| | | import useKmzTsa, { kmlStr, template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa' |
| | | import useMapDraw, { kmlEntities as globalEntities } from '/@/utils/cesium/use-map-draw' |
| | | import { getKmlParams } from '/@/utils/cesium/kmz' |
| | | import { cesiumOperation } from '/@/hooks/use-cesium-tsa' |
| | | import { message } from 'ant-design-vue' |
| | | import type { missionConfig, payloadParam as payloadParamConfig, Folder } from '/@/utils/cesium/types/kml' |
| | | const { appContext }: any = getCurrentInstance() |
| | | const global = appContext.config.globalProperties |
| | | |
| | | const mapDraw = useMapDraw('', '', '', global) |
| | | const { removeAllDataSource, removeAllPoint } = cesiumOperation() |
| | | const kmzUtils = useKmzTsa() |
| | | |
| | | interface setting { |
| | | imageFormat: string[] |
| | | } |
| | | |
| | | const waylineSetting = reactive({}) |
| | | const props = defineProps({ |
| | | loadCompleted: Boolean, |
| | | }) |
| | | |
| | | const getSvgResource = (name: string) => { |
| | | return new URL(`/src/assets/svg/${name}`, import.meta.url).href |
| | | } |
| | | |
| | | const climbImage = getSvgResource('climb.svg') |
| | | const imgs = [] |
| | | |
| | | // 拍照设置 |
| | | interface photoSetting { |
| | | title: string |
| | | value: string |
| | | } |
| | | const photoSetting = reactive<photoSetting[]>([ |
| | | { title: '广角', value: 'wide' }, |
| | | { title: '变焦', value: 'zoom' }, |
| | | { title: '红外', value: 'ir' }, |
| | | ]) |
| | | |
| | | // 高度模式 |
| | | const heightModeSetting = reactive([ |
| | | { |
| | | title: '绝对高度', |
| | | value: 'EGM96', |
| | | img: getSvgResource('jdgd.svg'), |
| | | }, |
| | | { |
| | | title: '相对起飞高度', |
| | | value: 'relativeToStartPoint', |
| | | img: getSvgResource('xdqfd.svg'), |
| | | }, |
| | | ]) |
| | | |
| | | // 计算 |
| | | const numberControls = (isAdd: boolean, computeVal: number, key: string) => { |
| | | let obj = { '#text': '0' } |
| | | if (key === 'takeOffSecurityHeight') { |
| | | obj = xmlTemplate.value.missionConfig.takeOffSecurityHeight |
| | | } |
| | | if (key === 'globalHeight') { |
| | | obj = xmlTemplate.value.Folder.globalHeight |
| | | } |
| | | if (key === 'autoFlightSpeed') { |
| | | obj = xmlTemplate.value.Folder.autoFlightSpeed |
| | | } |
| | | let value = Number(obj['#text']) |
| | | if (isAdd) { |
| | | value += computeVal |
| | | } else { |
| | | value -= computeVal |
| | | } |
| | | obj['#text'] = value.toString() |
| | | if (key === 'globalHeight') { |
| | | const placemarkArr = xmlTemplate.value.Folder.Placemark |
| | | placemarkArr.forEach((placemark: { useGlobalHeight: { [x: string]: any }; height: { [x: string]: string } }) => { |
| | | if (Reflect.has(placemark, 'useGlobalHeight')) { |
| | | placemark.height['#text'] = value.toString() |
| | | } |
| | | }) |
| | | const xmlString = kmzUtils.generateXML(xmlTemplate.value) |
| | | mapDraw.drawWayline(globalEntities.value, xmlString) |
| | | } |
| | | } |
| | | |
| | | // 拍照选择 |
| | | const selectPhotoSetting = (value: string) => { |
| | | const imageFormat = xmlTemplate.value.Folder.payloadParam.imageFormat |
| | | const imageFormatArr = imageFormat['#text'].split(',') |
| | | if (imageFormatArr.includes(value)) { |
| | | const index = imageFormatArr.findIndex((item: string) => item === value) |
| | | imageFormatArr.splice(index, 1) |
| | | } else { |
| | | imageFormatArr.push(value) |
| | | } |
| | | xmlTemplate.value.Folder.payloadParam.imageFormat['#text'] = imageFormatArr.join(',') |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .setting { |
| | | margin-left: auto; |
| | | .setting-content { |
| | | width: 390px; |
| | | height: 50vh; |
| | | max-height: 80vh; |
| | | overflow-y: auto; |
| | | color: #fff; |
| | | |
| | | .common { |
| | | background-color: #232323; |
| | | border-radius: 10px; |
| | | padding: 15px; |
| | | margin-bottom: 16px; |
| | | |
| | | .title { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | &:last-child { |
| | | margin: 0; |
| | | } |
| | | } |
| | | |
| | | .start-point { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | |
| | | .value { |
| | | margin-left: auto; |
| | | color: #409eff; |
| | | } |
| | | } |
| | | |
| | | .photo-setting { |
| | | .select-box { |
| | | padding: 0; |
| | | display: flex; |
| | | margin-top: 10px; |
| | | |
| | | li { |
| | | list-style-type: none; |
| | | padding: 3px 15px; |
| | | margin-left: 10px; |
| | | background-color: #409eff; |
| | | background-color: var(--settingColor); |
| | | border-radius: 9999px; |
| | | font-weight: bold; |
| | | cursor: pointer; |
| | | |
| | | &:first-child { |
| | | margin: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .auto-low-light { |
| | | display: flex; |
| | | |
| | | .title { |
| | | font-weight: bold; |
| | | margin-right: auto; |
| | | } |
| | | } |
| | | } |
| | | .height-mode { |
| | | |
| | | .height-mode, |
| | | .climb-mode { |
| | | .mode-box { |
| | | margin-top: 10px; |
| | | |
| | | :deep() { |
| | | .ant-radio-group { |
| | | display: flex; |
| | | |
| | | .ant-radio-button-wrapper { |
| | | flex: 1; |
| | | text-align: center; |
| | |
| | | color: #fff; |
| | | font-weight: bold; |
| | | border: 0; |
| | | |
| | | &::before { |
| | | background-color: #101010; |
| | | } |
| | | |
| | | &-checked { |
| | | background-color: #409eff !important; |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .parameter-tool { |
| | | margin-top: 15px; |
| | | display: flex; |
| | | |
| | | .example-img { |
| | | flex: 3; |
| | | flex-shrink: 0; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | |
| | | img { |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | .parameter-btn { |
| | | flex: 1; |
| | | padding: 0; |
| | | margin: 0; |
| | | flex-shrink: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | li { |
| | | width: 50px; |
| | | border-radius: 3px; |
| | | padding: 2px 0; |
| | | list-style-type: none; |
| | | cursor: pointer; |
| | | background-color: #3c3c3c; |
| | | margin-bottom: 5px; |
| | | text-align: center; |
| | | font-weight: bold; |
| | | transition: all 0.3s ease-in-out; |
| | | |
| | | &:nth-child(3) { |
| | | width: 100%; |
| | | background-color: transparent; |
| | | cursor: auto; |
| | | |
| | | span { |
| | | color: #409eff; |
| | | font-size: 23px; |
| | | font-weight: bolder; |
| | | margin-right: 5px; |
| | | } |
| | | } |
| | | |
| | | &:not(:nth-child(3)) { |
| | | &:hover { |
| | | background-color: #5d5f61; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .parameter-input { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | :deep() { |
| | | .ant-input-number { |
| | | background-color: transparent; |
| | | color: #409eff; |
| | | font-size: 23px; |
| | | border: 0; |
| | | |
| | | .ant-input-number-handler-wrap { |
| | | display: none; |
| | | } |
| | | |
| | | .ant-input-number-input-wrap { |
| | | input { |
| | | font-weight: bold; |
| | | text-align: center; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .speed-setting { |
| | | .speed-box { |
| | | margin-top: 10px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .text { |
| | | font-weight: bolder; |
| | | |
| | | .value { |
| | | color: #409eff; |
| | | width: 60px; |
| | | font-size: 30px; |
| | | background-color: transparent; |
| | | border: 0; |
| | | |
| | | :deep() { |
| | | .ant-input-number-handler-wrap { |
| | | display: none; |
| | | } |
| | | |
| | | .ant-input-number-input-wrap { |
| | | input { |
| | | font-weight: bolder; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .subtract, |
| | | .add { |
| | | width: 32px; |
| | | height: 32px; |
| | | text-align: center; |
| | | line-height: 32px; |
| | | font-size: 20px; |
| | | font-weight: bolder; |
| | | background-color: #3c3c3c; |
| | | border-radius: 3px; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | background-color: #5d5f61; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | :deep() { |
| | | .ant-popover-content { |
| | | .ant-popover-arrow, |
| | | .ant-popover-inner { |
| | | background-color: #101010; |
| | | } |
| | | .ant-popover-arrow { |
| | | border-top-color: #101010 !important; |
| | | border-left-color: #101010 !important; |
| | | } |
| | | .ant-popover-inner { |
| | | border-radius: 15px; |
| | | .ant-popover-inner-content { |
| | | padding: 16px; |
| | | :deep() { |
| | | .ant-popover-content { |
| | | .ant-popover-arrow, |
| | | .ant-popover-inner { |
| | | background-color: #101010; |
| | | } |
| | | |
| | | .ant-popover-arrow { |
| | | border-top-color: #101010 !important; |
| | | border-left-color: #101010 !important; |
| | | } |
| | | |
| | | .ant-popover-inner { |
| | | border-radius: 15px; |
| | | |
| | | .ant-popover-inner-content { |
| | | padding: 16px; |
| | | } |
| | | } |
| | | } |
| | | } |