}) | }) | ||||
} | } | ||||
// 预警已确认 | |||||
export function emergencyList(params = { airportFlyType: 2, statusList: 2 }) { | |||||
return request({ | |||||
url: `/mission/emergency/list`, | |||||
method: 'GET', | |||||
params | |||||
}) | |||||
} | |||||
<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> |
<span class="header__name">{{ platFormTitle }}</span> | <span class="header__name">{{ platFormTitle }}</span> | ||||
</div> | </div> | ||||
<n-dropdown trigger="hover" :options="options" @select="handleSelect"> | |||||
<div class="user_msg"> | |||||
<n-image | |||||
class="user_avatar" | |||||
:src="getUserInfo.avatar" | |||||
preview-disabled | |||||
/> | |||||
<span class="user_name">{{ getUserInfo.realname }}</span> | |||||
<div class="header__tool"> | |||||
<div class="header__scroll"> | |||||
<div class="scroll__content"> | |||||
<ul ref="scrollRef"> | |||||
<li v-for="(item,index) in list" :key="index"> | |||||
<n-ellipsis :tooltip="false"> | |||||
{{ item.name }} | |||||
</n-ellipsis> | |||||
</li> | |||||
</ul> | |||||
</div> | |||||
<!-- <button class="scroll__button">1</button> --> | |||||
</div> | </div> | ||||
</n-dropdown> | |||||
<n-dropdown trigger="hover" :options="options" @select="handleSelect"> | |||||
<div class="user_msg"> | |||||
<n-image | |||||
class="user_avatar" | |||||
:src="getUserInfo.avatar" | |||||
preview-disabled | |||||
/> | |||||
<span class="user_name">{{ getUserInfo.realname }}</span> | |||||
</div> | |||||
</n-dropdown> | |||||
</div> | |||||
</n-layout-header> | </n-layout-header> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import { defineComponent, reactive, toRefs, computed } from 'vue' | |||||
import { defineComponent, ref, reactive, toRefs, computed } from 'vue' | |||||
import { useRouter } from 'vue-router' | import { useRouter } from 'vue-router' | ||||
import { EditOutlined, LogoutOutlined } from '@vicons/antd' | import { EditOutlined, LogoutOutlined } from '@vicons/antd' | ||||
import { renderIcon } from '@/utils' | import { renderIcon } from '@/utils' | ||||
import { useUserStore } from '@/store/modules/user.js' | import { useUserStore } from '@/store/modules/user.js' | ||||
import { useSettingStore } from '@/store/modules/setting.js' | import { useSettingStore } from '@/store/modules/setting.js' | ||||
import setting from '@/setting/config.js' | import setting from '@/setting/config.js' | ||||
import { emergencyList } from '@/api/dashboard/index.js' | |||||
export default defineComponent({ | export default defineComponent({ | ||||
name: 'LayoutHeader', | name: 'LayoutHeader', | ||||
setup() { | setup() { | ||||
const router = useRouter() | const router = useRouter() | ||||
const userStore = useUserStore() | const userStore = useUserStore() | ||||
const settingStore = useSettingStore() | const settingStore = useSettingStore() | ||||
const scrollRef = ref() | |||||
const data = reactive({ | const data = reactive({ | ||||
options: [ | options: [ | ||||
{ | |||||
label: '修改密码', | |||||
key: 'edit', | |||||
icon: renderIcon(EditOutlined) | |||||
}, | |||||
// { | |||||
// label: '修改密码', | |||||
// key: 'edit', | |||||
// icon: renderIcon(EditOutlined) | |||||
// }, | |||||
{ | { | ||||
label: '退出登录', | label: '退出登录', | ||||
key: 'out', | key: 'out', | ||||
icon: renderIcon(LogoutOutlined) | icon: renderIcon(LogoutOutlined) | ||||
} | } | ||||
], | ], | ||||
platFormTitle: setting.title | |||||
platFormTitle: setting.title, | |||||
num: 0, | |||||
list: [] | |||||
}) | }) | ||||
const getUserInfo = computed(() => { | const getUserInfo = computed(() => { | ||||
} | } | ||||
} | } | ||||
const inspectionSroll = async() => { | |||||
const viewNum = 1 | |||||
if (data.list.length >= (viewNum + data.num)) { | |||||
scrollRef.value.style.top = -(data.num * 30) + 'px' | |||||
data.num++ | |||||
} else { | |||||
data.num = 0 | |||||
scrollRef.value.style.top = 0 | |||||
} | |||||
} | |||||
const queryList = async() => { | |||||
const res = await emergencyList() | |||||
if (res.code === 0) { | |||||
data.list = res.data | |||||
} | |||||
} | |||||
setInterval(() => { | |||||
queryList() | |||||
inspectionSroll() | |||||
}, 3000) | |||||
return { | return { | ||||
...toRefs(data), | ...toRefs(data), | ||||
getUserInfo, | getUserInfo, | ||||
getLogoWidth, | getLogoWidth, | ||||
handleSelect | |||||
handleSelect, | |||||
scrollRef | |||||
} | } | ||||
} | } | ||||
}) | }) | ||||
</script> | </script> | ||||
<style scoped> | |||||
<style lang="scss" scoped> | |||||
.layout__header { | .layout__header { | ||||
padding: 0 20px; | padding: 0 20px; | ||||
background: #36475D; | background: #36475D; | ||||
align-items: center; | align-items: center; | ||||
justify-content: space-between; | justify-content: space-between; | ||||
} | } | ||||
.header__tool{ | |||||
display: flex; | |||||
align-items: center; | |||||
.header__scroll{ | |||||
width: 150px; | |||||
margin-right: 50px; | |||||
position: relative; | |||||
} | |||||
.scroll__content{ | |||||
width: 150px; | |||||
height: 30px; | |||||
overflow: hidden; | |||||
position: absolute; | |||||
top: -15px; | |||||
z-index: 99; | |||||
ul{ | |||||
position: absolute; | |||||
transition: all .5s; | |||||
} | |||||
li{ | |||||
width: 150px; | |||||
line-height: 30px; | |||||
color: rgba(255,255,255,1); | |||||
cursor: pointer; | |||||
} | |||||
} | |||||
.scroll__button{ | |||||
position: absolute; | |||||
right: 0; | |||||
transform: translate(0,-50%); | |||||
} | |||||
} | |||||
.header__title{ | .header__title{ | ||||
display: flex; | display: flex; | ||||
justify-content: flex-start; | justify-content: flex-start; |
<DoubleRightOutlined /> | <DoubleRightOutlined /> | ||||
</n-icon> | </n-icon> | ||||
<div class="crcle__panel"> | <div class="crcle__panel"> | ||||
<div class="pannel__item item-1" @click="handleClick(1)" /> | |||||
<div class="pannel__item item-2" @click="handleClick(2)" /> | |||||
<div class="pannel__item item-3" @click="handleClick(3)" /> | |||||
<div class="pannel__item item-4" @click="handleClick(4)" /> | |||||
<div | |||||
v-for="(item,index) in cameraList" | |||||
:key="index" | |||||
class="pannel__item" | |||||
:class="`item-${index+1}`" | |||||
@mousedown="handleEvent('down',item)" | |||||
@mouseup="handleEvent('up',item)" | |||||
@mouseleave="handleEvent('leave',item)" | |||||
/> | |||||
<n-icon class="top" size="24" color="#fff"> | <n-icon class="top" size="24" color="#fff"> | ||||
<CaretUpFilled /> | <CaretUpFilled /> | ||||
</n-icon> | </n-icon> | ||||
<DoubleRightOutlined /> | <DoubleRightOutlined /> | ||||
</n-icon> | </n-icon> | ||||
<div class="crcle__panel"> | <div class="crcle__panel"> | ||||
<div class="pannel__item item-1" @click="handleClick(1)" /> | |||||
<div class="pannel__item item-2" @click="handleClick(1)" /> | |||||
<div class="pannel__item item-3" @click="handleClick(1)" /> | |||||
<div class="pannel__item item-4" @click="handleClick(1)" /> | |||||
<div | |||||
v-for="(item,index) in locusList" | |||||
:key="index" | |||||
class="pannel__item" | |||||
:class="`item-${index+1}`" | |||||
@mousedown="handleEvent('down',item.list,item.key)" | |||||
@mouseup="handleEvent('up',item.list,item.key)" | |||||
@mouseleave="handleEvent('leave',item.list,item.key)" | |||||
/> | |||||
<n-icon class="top" size="24" color="#fff"> | <n-icon class="top" size="24" color="#fff"> | ||||
<UpOutlined /> | <UpOutlined /> | ||||
</n-icon> | </n-icon> | ||||
default: () => ['camera', 'locus'] | default: () => ['camera', 'locus'] | ||||
} | } | ||||
}, | }, | ||||
emits: ['start', 'reset'], | |||||
setup(props, { emit }) { | setup(props, { emit }) { | ||||
const camera = reactive({ | |||||
const data = reactive({ | |||||
cameraShow: true, | cameraShow: true, | ||||
locusShow: true, | locusShow: true, | ||||
config: { | config: { | ||||
{ label: '下降', key: 'down' }, | { label: '下降', key: 'down' }, | ||||
{ label: '平移', key: 'move' }, | { label: '平移', key: 'move' }, | ||||
{ label: '自旋', key: 'redo' } | { label: '自旋', key: 'redo' } | ||||
] | |||||
], | |||||
cameraList: [ | |||||
{ yuntai: '01' }, | |||||
{ yuntai: '04' }, | |||||
{ yuntai: '02' }, | |||||
{ yuntai: '03' } | |||||
], | |||||
locusList: [ | |||||
{ list: { yaogan: '08', pwm: '' }, key: 'up' }, | |||||
{ list: { yaogan: '11', pwm: '' }, key: 'redo' }, | |||||
{ list: { yaogan: '09', pwm: '' }, key: 'down' }, | |||||
{ list: { yaogan: '10', pwm: '' }, key: 'redo' } | |||||
], | |||||
moveList: [ | |||||
{ list: { yaogan: '06', pwm: '' }, key: 'move' }, | |||||
{ list: { yaogan: '05', pwm: '' }, key: 'move' }, | |||||
{ list: { yaogan: '07', pwm: '' }, key: 'move' }, | |||||
{ list: { yaogan: '04', pwm: '' }, key: 'move' } | |||||
], | |||||
hasEvent: false | |||||
}) | }) | ||||
const getMode = computed(() => { | const getMode = computed(() => { | ||||
return isArray(props.mode) ? props.mode : [props.mode] | return isArray(props.mode) ? props.mode : [props.mode] | ||||
}) | }) | ||||
const handleClick = (num) => { | |||||
console.log(num) | |||||
const handleEvent = (event, params, key) => { | |||||
let reset = {} | |||||
if (key) { | |||||
params.pwm = data.config[key] | |||||
reset = { yaogan: '12', pwm: '200' } | |||||
} else { | |||||
reset = { yuntai: '09' } | |||||
} | |||||
switch (event) { | |||||
case 'down': | |||||
data.hasEvent = true | |||||
emit('start', params) | |||||
break | |||||
case 'up': | |||||
if (data.hasEvent) { | |||||
emit('reset', reset) | |||||
data.hasEvent = false | |||||
} | |||||
break | |||||
case 'leave': | |||||
if (data.hasEvent) { | |||||
emit('reset', reset) | |||||
data.hasEvent = false | |||||
} | |||||
break | |||||
} | |||||
} | } | ||||
return { | return { | ||||
...toRefs(camera), | |||||
...toRefs(data), | |||||
getMode, | getMode, | ||||
handleClick | |||||
handleEvent | |||||
} | } | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
.n-icon{ | .n-icon{ | ||||
position: absolute; | position: absolute; | ||||
pointer-events: none; | |||||
&.top{ | &.top{ | ||||
left: 50%; | left: 50%; | ||||
top: 25%; | top: 25%; |
<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> |
<div class="basic"> | <div class="basic"> | ||||
<OneMap ref="Map" /> | <OneMap ref="Map" /> | ||||
<Extend ref="extendRef" class="extend" @send="getmessage" /> | <Extend ref="extendRef" class="extend" @send="getmessage" /> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
ground_station_url: 'xxxxxxxxxxxxxxx' | 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(() => { | onMounted(() => { | ||||
extendRef.value.handleClick(0) | extendRef.value.handleClick(0) | ||||
}) | }) | ||||
toSystem, | toSystem, | ||||
extendRef, | extendRef, | ||||
getmessage, | getmessage, | ||||
Map, | |||||
setCommandAndLog | |||||
Map | |||||
} | } | ||||
} | } | ||||
} | } |
</n-gi> | </n-gi> | ||||
</n-grid> | </n-grid> | ||||
<p class="title">火灾核实记录</p> | <p class="title">火灾核实记录</p> | ||||
<div> | |||||
<div class="content"> | |||||
<p v-for="(item,index) in fireDetail.warningRecordVOList" :key="index" class="content"> | <p v-for="(item,index) in fireDetail.warningRecordVOList" :key="index" class="content"> | ||||
{{ `${item.recordStartTime} ${item.airportName}执行任务,` }} | {{ `${item.recordStartTime} ${item.airportName}执行任务,` }} | ||||
<span>查看详情</span> | |||||
</p> | </p> | ||||
</div> | </div> | ||||
<p class="title">处理记录</p> | <p class="title">处理记录</p> | ||||
} | } | ||||
.content{ | .content{ | ||||
padding: 0 5px; | padding: 0 5px; | ||||
min-height: 32px; | |||||
font-size: 16px; | font-size: 16px; | ||||
} | } | ||||
</style> | </style> |
const searchParams = ref() | const searchParams = ref() | ||||
function handleSearch(params) { | function handleSearch(params) { | ||||
searchParams.value = { ...params } | |||||
searchParams.value = { ...params, type: 1 } | |||||
tableRef.value.reFetch({ searchParams }) | tableRef.value.reFetch({ searchParams }) | ||||
} | } | ||||
onClick: handleTaskDemand.bind(null, row) | onClick: handleTaskDemand.bind(null, row) | ||||
}, | }, | ||||
auth: 'basic_list', | auth: 'basic_list', | ||||
show: row.status === 4 | |||||
show: row.status === 4 && row.aiVideoUrl && row.videoUrl | |||||
}, | }, | ||||
{ | { | ||||
label: '问题核实', | label: '问题核实', |