@@ -11,4 +11,4 @@ VITE_PROXY = [["/api-local","http://127.0.0.1:8002/api"],["/api-mock","http://12 | |||
VITE_APP_GLOB_BASE_API = '/api-local' | |||
# mock base api | |||
VITE_APP_GLOB_BASE_API_MOCK = '/api-mock' | |||
VITE_APP_GLOB_BASE_API_MOCK = '/api-mock' |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1643199049164" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2889" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M853.333333 213.333333l-682.666667 0c-47.146667 0-84.906667 38.186667-84.906667 85.333333l-0.426667 426.666667c0 47.146667 38.186667 85.333333 85.333333 85.333333l682.666667 0c47.146667 0 85.333333-38.186667 85.333333-85.333333l0-426.666667c0-47.146667-38.186667-85.333333-85.333333-85.333333zM469.333333 341.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM469.333333 469.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM341.333333 341.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM341.333333 469.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM298.666667 554.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM298.666667 426.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM682.666667 725.333333l-341.333333 0 0-85.333333 341.333333 0 0 85.333333zM682.666667 554.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM682.666667 426.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM810.666667 554.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM810.666667 426.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333z" p-id="2890" fill="#bfbfbf"></path></svg> |
@@ -0,0 +1 @@ | |||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1643199049164" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2889" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M853.333333 213.333333l-682.666667 0c-47.146667 0-84.906667 38.186667-84.906667 85.333333l-0.426667 426.666667c0 47.146667 38.186667 85.333333 85.333333 85.333333l682.666667 0c47.146667 0 85.333333-38.186667 85.333333-85.333333l0-426.666667c0-47.146667-38.186667-85.333333-85.333333-85.333333zM469.333333 341.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM469.333333 469.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM341.333333 341.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM341.333333 469.333333l85.333333 0 0 85.333333-85.333333 0 0-85.333333zM298.666667 554.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM298.666667 426.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM682.666667 725.333333l-341.333333 0 0-85.333333 341.333333 0 0 85.333333zM682.666667 554.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM682.666667 426.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM810.666667 554.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333zM810.666667 426.666667l-85.333333 0 0-85.333333 85.333333 0 0 85.333333z" p-id="2890" fill="#007AFF"></path></svg> |
@@ -0,0 +1,309 @@ | |||
<template> | |||
<div class="control" :style="{ width: 2 * outerRadius + 'rem', height: 2 * outerRadius + 'rem' }"> | |||
<div class="vertical common" :style="{ top: `${iconDistance || 12}rem` }"> | |||
<slot name="top"> | |||
<UpOutlined class="common" /> | |||
</slot> | |||
</div> | |||
<div class="horizontal common" :style="{ left: `${iconDistance || 12}rem` }"> | |||
<slot name="left"> | |||
<LeftOutlined class="common" /> | |||
</slot> | |||
</div> | |||
<div class="vertical common" :style="{ bottom: `${iconDistance || 12}rem` }"> | |||
<slot name="bottom"> | |||
<DownOutlined class="common" /> | |||
</slot> | |||
</div> | |||
<div class="horizontal common" :style="{ right: `${iconDistance || 12}rem` }"> | |||
<slot name="right"> | |||
<RightOutlined class="common" /> | |||
</slot> | |||
</div> | |||
<span v-if="lock"> | |||
<span | |||
v-for="item of 4" | |||
:key="item" | |||
class="divider" | |||
:style="{ transform: `rotate(${ 45 * (2 * item + 1) }deg) translateX(${innerRadius}rem)`,width: outerRadius - innerRadius + 'rem',}" | |||
/> | |||
</span> | |||
<div | |||
class="circle" | |||
:style="{ | |||
top: data.distanceY + 'rem', | |||
left: data.distanceX + 'rem', | |||
width: 2 * innerRadius + 'rem', | |||
height: 2 * innerRadius + 'rem', | |||
}" | |||
/> | |||
<div | |||
class="mask base" | |||
:style="{ | |||
width: 2 * outerRadius + 'rem', | |||
height: 2 * outerRadius + 'rem', | |||
}" | |||
@mousedown="mousedown" | |||
@mouseup="mouseup" | |||
/> | |||
</div> | |||
</template> | |||
<script> | |||
import { | |||
DownOutlined, | |||
UpOutlined, | |||
LeftOutlined, | |||
RightOutlined | |||
} from '@vicons/antd' | |||
import { computed, ref, toRaw, watch } from 'vue' | |||
// import { mapActions, mapGetters } from 'vuex' | |||
export default { | |||
components: { | |||
DownOutlined, | |||
UpOutlined, | |||
LeftOutlined, | |||
RightOutlined | |||
}, | |||
props: { | |||
lock: { | |||
type: Boolean, | |||
default() { | |||
return true | |||
} | |||
}, | |||
iconDistance: { | |||
type: Number, | |||
default() { | |||
return 7 / 136.6 | |||
} | |||
}, | |||
outerRadius: { | |||
type: Number, | |||
default() { | |||
return 60 / 136.6 | |||
} | |||
}, | |||
innerRadius: { | |||
type: Number, | |||
default() { | |||
return 15 / 136.6 | |||
} | |||
}, | |||
command: { | |||
type: Object, | |||
default() { | |||
return {} | |||
} | |||
}, | |||
keyboardMode: { | |||
type: Boolean, | |||
default() { | |||
return false | |||
} | |||
}, | |||
keyMap: { | |||
type: Object, | |||
default() { | |||
return { 38: 'up', 39: 'right', 40: 'down', 37: 'left' } | |||
} | |||
} | |||
}, | |||
setup(props, { emit }) { | |||
const data = ref({ | |||
direction: null, | |||
distanceX: 0, | |||
distanceY: 0, | |||
offsetX: 0, | |||
offsetY: 0, | |||
actualRemUnit: 0, | |||
keycode: null | |||
}) | |||
const circleDistance = computed(() => { | |||
return props.outerRadius - props.innerRadius | |||
}) | |||
data.value.distanceX = data.value.distanceY = circleDistance.value | |||
function keyup(e) { | |||
if (!props.keyboardMode || e.keyCode !== data.value.keyCode) return | |||
const keys = Object.keys(toRaw(props.keyMap)) | |||
if (keys.includes(e.keyCode + '')) { | |||
data.value.direction = null | |||
emit('endAction') | |||
} | |||
data.value.keyCode = null | |||
// this.updateRemoteControlling(false) | |||
document.removeEventListener('keyup', keyup) | |||
document.addEventListener('keydown', keydown) | |||
} | |||
function keydown(e) { | |||
// if (this.remoteControlling || !this.keyboardMode) return | |||
const direction = props.keyMap[e.keyCode] | |||
if (!direction) return | |||
// this.updateRemoteControlling(true) | |||
data.value.direction = direction | |||
data.value.keyCode = e.keyCode | |||
document.removeEventListener('keydown', keydown) | |||
document.addEventListener('keyup', keyup) | |||
} | |||
function mousedown(e) { | |||
if (props.keyboardMode) return | |||
data.value.actualRemUnit = parseFloat(document.documentElement.style.fontSize) || 4 | |||
const offset = e.target.parentNode.getBoundingClientRect() | |||
data.value.offsetX = offset.left / data.value.actualRemUnit | |||
data.value.offsetY = offset.top / data.value.actualRemUnit | |||
const x = e.clientX / data.value.actualRemUnit - props.outerRadius - data.value.offsetX | |||
const y = -(e.clientY / data.value.actualRemUnit - props.outerRadius - data.value.offsetY) | |||
let deg = getTanDeg(x, y) | |||
deg = deg === 360 ? 0 : deg | |||
const { resultX, resultY } = getBoundary( | |||
data.value.offsetX + props.outerRadius, | |||
data.value.offsetY + props.outerRadius, | |||
deg, | |||
e.clientX / data.value.actualRemUnit, | |||
e.clientY / data.value.actualRemUnit | |||
) | |||
data.value.distanceX = resultX - props.innerRadius | |||
data.value.distanceY = resultY - props.innerRadius | |||
let direction | |||
if (deg > 45 && deg < 135) { | |||
direction = 'right' | |||
} else if (deg > 135 && deg < 225) { | |||
direction = 'down' | |||
} else if (deg > 225 && deg < 315) { | |||
direction = 'left' | |||
} else { | |||
direction = 'up' | |||
} | |||
data.value.direction = direction | |||
return deg | |||
} | |||
function mouseup() { | |||
if (props.keyboardMode) return | |||
data.value.distanceX = circleDistance.value | |||
data.value.distanceY = circleDistance.value | |||
data.value.direction = null | |||
emit('endAction') | |||
} | |||
function getTanDeg(x, y) { | |||
var result = Math.atan(x / y) / (Math.PI / 180) | |||
if (result <= 0) { | |||
if (y <= 0) { | |||
result += 180 | |||
} else { | |||
result += 360 | |||
} | |||
} else { | |||
if (y <= 0) { | |||
result += 180 | |||
} | |||
} | |||
return result | |||
} | |||
function getBoundary(radX, radY, deg, X, Y) { | |||
let resultX = X - radX | |||
let resultY = Y - radY | |||
const radian = (Math.PI * deg) / 180 | |||
const offsetX = circleDistance.value * Math.sin(radian) | |||
const offsetY = circleDistance.value * Math.cos(radian) | |||
if (Math.abs(offsetX) < Math.abs(resultX)) { | |||
resultX = offsetX | |||
resultY = -offsetY | |||
} | |||
if (deg === 0 || deg === 180) { | |||
if (Math.abs(offsetY) < Math.abs(resultY)) { | |||
resultX = offsetX | |||
resultY = -offsetY | |||
} | |||
} | |||
resultX += props.outerRadius | |||
resultY += props.outerRadius | |||
if (props.lock) { | |||
if ( | |||
(deg >= 0 && deg <= 45) || | |||
(deg >= 315 && deg <= 360) || | |||
(deg >= 135 && deg <= 225) | |||
) { | |||
resultX = radX - data.value.offsetX | |||
} else { | |||
resultY = radY - data.value.offsetY | |||
} | |||
} | |||
return { | |||
resultX, | |||
resultY: resultY | |||
} | |||
} | |||
// computed: { | |||
// | |||
// // ...mapGetters(['remoteControlling']) | |||
// }, | |||
watch(() => data.value.direction, (newValue) => { | |||
if (newValue === null) return | |||
emit('executeAction', props.command[newValue]) | |||
}) | |||
watch(() => props.keyboardMode, (flag) => { | |||
if (flag) { | |||
document.addEventListener('keydown', keydown) | |||
} else { | |||
document.removeEventListener('keydown', keydown) | |||
} | |||
}) | |||
return { | |||
data, | |||
circleDistance, | |||
keyup, | |||
keydown, | |||
mouseup, | |||
mousedown, | |||
getTanDeg, | |||
getBoundary | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.control { | |||
position: relative; | |||
border-radius: 50%; | |||
background: #3f3f3f; | |||
color: rgba(255, 255, 255, 0.7); | |||
.common { | |||
width: 20px; | |||
color: #fff; | |||
font-size: 14px; | |||
z-index: 1; | |||
} | |||
.vertical { | |||
position: absolute; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
} | |||
.horizontal { | |||
position: absolute; | |||
top: 50%; | |||
transform: translateY(-50%); | |||
} | |||
.divider { | |||
height: 1px; | |||
background: #333435; | |||
position: absolute; | |||
top: 50%; | |||
left: 50%; | |||
transform-origin: 0 50%; | |||
pointer-events: none; | |||
} | |||
.circle { | |||
position: absolute; | |||
border-radius: 50%; | |||
background: #121416; | |||
} | |||
.mask { | |||
position: absolute; | |||
top: 0; | |||
left: 0; | |||
z-index: 5; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,16 @@ | |||
export default { | |||
hovering: { 'zhilin': '01' }, | |||
goBack: { 'zhilin': '03' }, | |||
endLanding: { 'zhilin': '02' }, | |||
movingToLeft: { 'yaogan': '04' }, | |||
movingToRight: { 'yaogan': '05' }, | |||
movingToForward: { 'yaogan': '06' }, | |||
MovingToBack: { 'yaogan': '07' }, | |||
rising: { 'yaogan': '08' }, | |||
falling: { 'yaogan': '09' }, | |||
rollingToLeft: { 'yaogan': '10' }, | |||
rollingToRight: { 'yaogan': '11' }, | |||
stopAction: { 'yaogan': '12' }, | |||
excuteTask: { 'zhilin': '04' }, | |||
environmentCheck: { 'zhilin': '05' } | |||
} |
@@ -0,0 +1,161 @@ | |||
<template> | |||
<div class="control__container" :class="[isCollpase ? 'open': 'closed']"> | |||
<n-icon class="control__close" size="20" color="#fff" @click="isCollpase = true"> | |||
<DoubleLeftOutlined /> | |||
</n-icon> | |||
<n-icon class="control__open" size="20" color="#fff" @click="isCollpase = false"> | |||
<DoubleRightOutlined /> | |||
</n-icon> | |||
<div class="crcle__panel"> | |||
<div class="pannel__item item-1" /> | |||
<div class="pannel__item item-2" /> | |||
<div class="pannel__item item-3" /> | |||
<div class="pannel__item item-4" /> | |||
<n-icon class="top" size="24" color="#fff"> | |||
<CaretUpFilled /> | |||
</n-icon> | |||
<n-icon class="right" size="24" color="#fff"> | |||
<CaretRightFilled /> | |||
</n-icon> | |||
<n-icon class="bottom" size="24" color="#fff"> | |||
<CaretDownFilled /> | |||
</n-icon> | |||
<n-icon class="left" size="24" color="#fff"> | |||
<CaretLeftFilled /> | |||
</n-icon> | |||
</div> | |||
<div class="square__panel"> | |||
<n-icon size="24" color="#fff"> | |||
<PlusOutlined /> | |||
</n-icon> | |||
<p>焦距</p> | |||
<n-icon size="24" color="#fff"> | |||
<LineOutlined /> | |||
</n-icon> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { | |||
DoubleLeftOutlined, | |||
DoubleRightOutlined, | |||
CaretUpFilled, | |||
CaretRightFilled, | |||
CaretDownFilled, | |||
CaretLeftFilled, | |||
PlusOutlined, | |||
LineOutlined | |||
} from '@vicons/antd' | |||
import { defineComponent, reactive, toRefs } from 'vue' | |||
export default defineComponent({ | |||
name: 'ControlPanel', | |||
components: { DoubleLeftOutlined, DoubleRightOutlined, CaretUpFilled, CaretRightFilled, CaretDownFilled, CaretLeftFilled, PlusOutlined, LineOutlined }, | |||
props: { | |||
mode: { | |||
type: [Array, String], | |||
default: () => ['camera', 'locus'] | |||
} | |||
}, | |||
setup() { | |||
const camera = reactive({ | |||
isCollpase: false | |||
}) | |||
return { | |||
...toRefs(camera) | |||
} | |||
} | |||
}) | |||
</script> | |||
<style scoped lang='scss'> | |||
.control__container{ | |||
position: relative; | |||
z-index: 99; | |||
width: 300px; | |||
height: 220px; | |||
background: rgba(0, 0, 0, 1); | |||
padding: 10px; | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-around; | |||
overflow: hidden; | |||
.crcle__panel{ | |||
width: 180px; | |||
height: 180px; | |||
position: relative; | |||
.pannel__item{ | |||
position:absolute; | |||
width: 180px; | |||
height: 180px; | |||
background-color: rgba(87, 87, 87, 1); | |||
clip: rect(auto, 90px, 90px, auto); | |||
border-radius: 50%; | |||
} | |||
@for $i from 1 through 4{ | |||
.item-#{$i}{ | |||
transform: rotate(90deg * ($i) - 45deg); | |||
} | |||
} | |||
.n-icon{ | |||
position: absolute; | |||
&.top{ | |||
left: 50%; | |||
top: 25%; | |||
transform: translate(-50%,-100%); | |||
} | |||
&.right{ | |||
right: 25%; | |||
top: 50%; | |||
transform: translate(100%,-50%); | |||
} | |||
&.bottom{ | |||
left: 50%; | |||
top: 75%; | |||
transform: translate(-50%,0); | |||
} | |||
&.left{ | |||
left: 25%; | |||
top: 50%; | |||
transform: translate(-100%,-50%); | |||
} | |||
} | |||
} | |||
.square__panel{ | |||
width: 60px; | |||
height: 180px; | |||
background-color: rgba(87, 87, 87, 1); | |||
border-radius: 50px; | |||
padding: 10px 0; | |||
color: #fff; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-around; | |||
align-items: center; | |||
} | |||
&.open{ | |||
transition: width 1s; | |||
.control__close{ | |||
display: none; | |||
} | |||
} | |||
&.closed{ | |||
width: 70px; | |||
transition: width 1s; | |||
.square__panel,.crcle__panel,.control__open{ | |||
display: none; | |||
} | |||
} | |||
} | |||
.n-icon{ | |||
cursor: pointer; | |||
} | |||
.control__close,.control__open{ | |||
position: absolute; | |||
right: 5px; | |||
top: 5px; | |||
} | |||
</style> |
@@ -46,6 +46,8 @@ | |||
</div> | |||
</div> | |||
</div> | |||
<ControlPanel /> | |||
</div> | |||
<div ref="mapRef" class="warn__back"> | |||
<Underlay /> | |||
@@ -60,10 +62,10 @@ | |||
<script> | |||
import { defineComponent, ref, reactive, toRefs, computed, onMounted, watch, nextTick } from 'vue' | |||
import Underlay from './Underlay.vue' | |||
import ControlPanel from './ControlPanel.vue' | |||
export default defineComponent({ | |||
name: 'WarningDrawer', | |||
components: { Underlay }, | |||
components: { Underlay, ControlPanel }, | |||
props: { | |||
/* 可见 */ | |||
visible: { |
@@ -0,0 +1,253 @@ | |||
<template> | |||
<div class="remoate-sensing"> | |||
<div class="keyboard-mode"> | |||
<svg-icon | |||
class="keyboard" | |||
:icon-class="data.keyboardMode ? 'keyboard_active' : 'keyboard'" | |||
@click="changeMode" | |||
/> | |||
</div> | |||
<div class="height-controller base-extrinsic"> | |||
<click-controller | |||
:lock="true" | |||
:outer-radius="40 / data.remUnit" | |||
:inner-radius="8 / data.remUnit" | |||
:command="{ left: 'movingToLeft', right: 'movingToRight', down: 'falling', up: 'rising' }" | |||
:keyboard-mode="data.keyboardMode" | |||
:key-map="{ 87: 'up', 68: 'right', 83: 'down', 65: 'left' }" | |||
@endAction="endCommand" | |||
@executeAction="executeCommand" | |||
> | |||
<template #right> | |||
<RedoOutlined /> | |||
</template> | |||
<template #left> | |||
<UndoOutlined /> | |||
</template> | |||
</click-controller> | |||
<div class="title">高度控制</div> | |||
</div> | |||
<div class="displacement-controller base-extrinsic"> | |||
<click-controller | |||
:lock="true" | |||
:outer-radius="40 / data.remUnit" | |||
:inner-radius="8 / data.remUnit" | |||
:command="{ left: 'rollingToLeft', right: 'rollingToRight', down: 'MovingToBack', up: 'movingToForward' }" | |||
:keyboard-mode="data.keyboardMode" | |||
:key-map="{ 38: 'up', 39: 'right', 40: 'down', 37: 'left' }" | |||
@endAction="endCommand" | |||
@executeAction="executeCommand" | |||
/> | |||
<div class="title">平移控制</div> | |||
</div> | |||
<div class="pwm"> | |||
<n-row :align="'middle'"> | |||
<n-col :span="7"> | |||
<span>上升:</span> | |||
</n-col> | |||
<n-col :span="17"> | |||
<n-input-number v-model:value="data.pwm.up" size="tiny" :bordered="false" /> | |||
</n-col> | |||
</n-row> | |||
<n-row :align="'middle'"> | |||
<n-col :span="7"> | |||
<span>下降:</span> | |||
</n-col> | |||
<n-col :span="17"> | |||
<n-input-number v-model:value="data.pwm.down" size="tiny" /> | |||
</n-col> | |||
</n-row> | |||
<n-row :align="'middle'"> | |||
<n-col :span="7"> | |||
<span>平移:</span> | |||
</n-col> | |||
<n-col :span="17"> | |||
<n-input-number v-model:value="data.pwm.translating" size="tiny" /> | |||
</n-col> | |||
</n-row> | |||
<n-row :align="'middle'"> | |||
<n-col :span="7"> | |||
<span>自旋:</span> | |||
</n-col> | |||
<n-col :span="17"> | |||
<n-input-number v-model:value="data.pwm.rotating" size="tiny" /> | |||
</n-col> | |||
</n-row> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import ClickController from '../../../components/clickController.vue' | |||
import { RedoOutlined, UndoOutlined } from '@vicons/antd' | |||
import { ArrowUpCircleOutline, ArrowDownCircleOutline } from '@vicons/ionicons5' | |||
import droneCommand from '../../../utils/droneCommand' | |||
import { ref } from 'vue' | |||
const remoateSensing = { | |||
rollingToRight: '无人机右移', | |||
movingToForward: '无人机前进', | |||
MovingToBack: '无人机后退', | |||
rollingToLeft: '无人机左移', | |||
rising: '无人机爬升', | |||
falling: '无人机下降', | |||
movingToLeft: '无人机左旋', | |||
movingToRight: '无人机右移' | |||
} | |||
export default { | |||
components: { | |||
ClickController, | |||
RedoOutlined, | |||
UndoOutlined | |||
}, | |||
inject: ['droneInfo'], | |||
emits: ['endCommand', 'executeCommand'], | |||
setup(props, { emit }) { | |||
const data = ref({ | |||
remUnit: parseFloat(document.documentElement.style.fontSize) || 4, | |||
keyboardMode: false, | |||
height: 5, | |||
pwm: { | |||
up: 200, | |||
down: 50, | |||
rotating: 75, | |||
translating: 100 | |||
}, | |||
action: '' | |||
}) | |||
function changeMode() { | |||
data.value.keyboardMode = !data.value.keyboardMode | |||
} | |||
function endCommand() { | |||
emit('command', { order: droneCommand.stopAction, msg: '停止' + remoateSensing[data.value.action] + '操作' }) | |||
} | |||
function executeCommand(action) { | |||
const command = droneCommand[action] | |||
if (action === 'rising') { | |||
command.PWM = data.value.pwm.up | |||
} else if (action === 'falling') { | |||
command.PWM = data.value.pwm.down | |||
} else if (action === 'movingToLeft' || action === 'movingToRight') { | |||
command.PWM = data.value.pwm.rotating | |||
} else { | |||
command.PWM = data.value.pwm.translating | |||
} | |||
data.value.action = action | |||
emit('command', { order: command, msg: remoateSensing[action] + '(' + command.PWM + ')' }) | |||
} | |||
function fixedHeight() { | |||
if (!data.value.height) return | |||
emit('command', { order: { toAlt: data.value.height }, msg: '飞行至' + data.value.height + 'M高度' }) | |||
} | |||
return { | |||
data, | |||
changeMode, | |||
endCommand, | |||
executeCommand, | |||
fixedHeight, | |||
ArrowUpCircleOutline, | |||
ArrowDownCircleOutline | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.remoate-sensing { | |||
display: flex; | |||
align-items: center; | |||
font-size:12PX; | |||
pointer-events: auto; | |||
.fixed-height { | |||
// padding: 5px; | |||
// width: 180px; | |||
flex: 1; | |||
height: 100%; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
.title { | |||
color: #fff; | |||
} | |||
.height { | |||
margin-top: 10px; | |||
display: flex; | |||
align-items: center; | |||
div { | |||
color: #fff; | |||
} | |||
} | |||
.btn { | |||
cursor: pointer; | |||
font-size: 14px; | |||
height: 26px; | |||
width: 80px; | |||
margin-top: 15px; | |||
appearance: none; | |||
outline: none; | |||
background: #007aff; | |||
border: none; | |||
color: #fff; | |||
} | |||
} | |||
.base-extrinsic { | |||
height: 100%; | |||
width: 86px; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: space-around; | |||
.title { | |||
color: #fff; | |||
} | |||
} | |||
.pwm { | |||
height: 100%; | |||
width: 120px; | |||
color: #fff; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-evenly; | |||
margin-right: 10px; | |||
.ant-row.ant-row-middle{ | |||
margin-bottom: 3px; | |||
} | |||
span { | |||
color: #fff; | |||
} | |||
} | |||
.keyboard { | |||
height: 40px; | |||
width: 40px; | |||
cursor: pointer; | |||
} | |||
input,.ant-input-number { | |||
background: #3b3e45; | |||
border: none; | |||
outline: none !important; | |||
width: 80px; | |||
height: 20px; | |||
margin-right: 2px; | |||
color: #fff; | |||
box-shadow: none; | |||
font-size: 12px; | |||
padding: 0 5px; | |||
box-sizing: border-box; | |||
&::selection { | |||
background: transparent; | |||
} | |||
&::-moz-selection { | |||
background: #fff; | |||
} | |||
&:focus { | |||
outline: none; | |||
background-color: #3b3e45; | |||
} | |||
} | |||
.ant-input-number-input{ | |||
height:20px; | |||
} | |||
} | |||
</style> |
@@ -3,6 +3,10 @@ | |||
<OneMap ref="Map" /> | |||
<Extend ref="extendRef" class="extend" @send="getmessage" /> | |||
<RemoateSensing | |||
class="remoate-sensing-extrinsic" | |||
@command="setCommandAndLog" | |||
/> | |||
</div> | |||
</template> | |||
@@ -10,11 +14,11 @@ | |||
import { useRouter } from 'vue-router' | |||
import OneMap from './components/OneMap.vue' | |||
import Extend from './components/Extend.vue' | |||
import WarningDrawer from './components/WarningDrawer.vue' | |||
import { ref, onMounted } from 'vue' | |||
import RemoateSensing from './components/RemoateSensing.vue' | |||
export default { | |||
name: 'HomePage', | |||
components: { OneMap, Extend, WarningDrawer }, | |||
components: { OneMap, Extend, RemoateSensing }, | |||
setup(props) { | |||
const router = useRouter() | |||
const extendRef = ref() | |||
@@ -26,19 +30,57 @@ export default { | |||
const getmessage = (data) => { | |||
Map.value.addPonit(data) | |||
} | |||
const data = ref({ | |||
currentDroneInfo: { | |||
auth: 1, | |||
ground_station_url: 'xxxxxxxxxxxxxxx' | |||
} | |||
}) | |||
function setCommandAndLog(params, errorMsg) { | |||
// 权限认证 | |||
if (data.value.currentDroneInfo.auth === 1) { | |||
$message.warning('用户无该机场操作权限!') | |||
return | |||
} | |||
const base = { sid: data.value.currentDroneInfo.ground_station_url } | |||
return this.$http.post('/airportControl/droneCommand', Object.assign(params, base)).then(res => { | |||
if (res.data.code === 0) { | |||
const data = res.data.data | |||
if (data.value) { | |||
// this.logList.unshift({ value: data.value, createTime: data.createTime, status: data.status, id: Date.now() }) | |||
} | |||
return data | |||
} else { | |||
$message.error(errorMsg || res.data.msg) | |||
} | |||
}).catch(e => { | |||
$message.error(errorMsg || e.message) | |||
}) | |||
} | |||
onMounted(() => { | |||
extendRef.value.handleClick(0) | |||
}) | |||
return { | |||
data, | |||
toSystem, | |||
extendRef, | |||
getmessage, | |||
Map | |||
Map, | |||
setCommandAndLog | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.remoate-sensing-extrinsic { | |||
height: 120px; | |||
// width: 50%; | |||
position: absolute; | |||
bottom: 10%; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
background: rgba(0, 0, 0, 0.8); | |||
} | |||
.dashboard__main{ | |||
height: calc(100vh - 80px); | |||
.dashboard__top{ |