From 9c9038b7b7967408d6d99babcd4e09a7936e6646 Mon Sep 17 00:00:00 2001
From: husq <931347610@qq.com>
Date: Fri, 29 Sep 2023 00:19:30 +0800
Subject: [PATCH] Merge branch 'demo' of http://s16s652780.51mypc.cn:49896/r/yskj/iot_drone_web into demo
---
src/api/media.ts | 18
src/components/MediaPanel.vue | 317 +++++++++---------
src/router/index.ts | 4
src/components/g-map/DroneControlPanel.vue | 666 +++++++++++++++++++++-----------------
4 files changed, 529 insertions(+), 476 deletions(-)
diff --git a/src/api/media.ts b/src/api/media.ts
index 95a6614..adcf442 100644
--- a/src/api/media.ts
+++ b/src/api/media.ts
@@ -2,7 +2,6 @@
import request, { IPage, IWorkspaceResponse } from '/@/api/http/request'
const HTTP_PREFIX = '/media/api/v1'
-
export interface MediaQueryParam{
subFileType?:any
payload?:any
@@ -11,26 +10,19 @@
name?:string
}
-
-
-
-
-
-
// Get Media Files
-export const getMediaFiles = async function (wid: string, pagination: IPage,params:MediaQueryParam): Promise<IWorkspaceResponse<any>> {
+export const getMediaFiles = async function (wid: string, pagination: IPage, params:MediaQueryParam): Promise<IWorkspaceResponse<any>> {
const url = `${HTTP_PREFIX}/files/${wid}/files?page=${pagination.page}&page_size=${pagination.page_size}`
- const result = await request.get(url,{params})
+ const result = await request.get(url, { params })
return result.data
}
-//修改文件名
-export const updateMediaFile = async function (wid: string,params:any): Promise<IWorkspaceResponse<any>> {
+// 修改文件名
+export const updateMediaFile = async function (wid: string, params:any): Promise<IWorkspaceResponse<any>> {
const url = `${HTTP_PREFIX}/files/${wid}/updateFile?`
- const result = await request.get(url,{params})
+ const result = await request.get(url, { params })
return result.data
}
-
// Download Media File
export const downloadMediaFile = async function (workspaceId: string, fileId: string): Promise<any> {
diff --git a/src/components/MediaPanel.vue b/src/components/MediaPanel.vue
index 549e063..911fb2e 100644
--- a/src/components/MediaPanel.vue
+++ b/src/components/MediaPanel.vue
@@ -1,98 +1,99 @@
<template>
- <!-- <div class="header">媒体文件</div>-->
- <!--搜索栏-->
- <div class="search-panel-wrapper">
- <div class="search-part">
- <a-range-picker :size="searchPanelOptions.size" :format="searchPanelOptions.dateFormat"
- :valueFormat="searchPanelOptions.valueFormat" v-model:value="timeRangeArr.data"
- @change="dateChange" style="width: 300px"/>
+ <!-- <div class="header">媒体文件</div>-->
+ <!--搜索栏-->
+ <div class="search-panel-wrapper">
+ <div class="search-part">
+ <a-range-picker :size="searchPanelOptions.size" :format="searchPanelOptions.dateFormat"
+ :valueFormat="searchPanelOptions.valueFormat" v-model:value="timeRangeArr.data"
+ @change="dateChange" style="width: 300px"/>
+ </div>
+
+ <div class="search-part">
+ <a-select v-model:value="subFileTypeArr" allowClear @change="subFileTypeChange"
+ :options="subFileTypeOptions"
+ :maxTagCount="searchPanelOptions.maxTagCount" mode="multiple"
+ :size="searchPanelOptions.size" placeholder="所有类型" style="width: 300px">
+ </a-select>
+ </div>
+
+ <div class="search-part">
+ <a-select v-model:value="payloadArr" allowClear @change="payloadChange" :options="payloadOptions"
+ :maxTagCount="searchPanelOptions.maxTagCount" mode="multiple"
+ :size="searchPanelOptions.size" placeholder="所有负载" style="width: 300px">
+ </a-select>
+ </div>
+
+ <div class="search-part">
+ <a-input-search :size="searchPanelOptions.size" v-model:value="searchQuery.name" @change="inputChange"
+ placeholder="按文件名称搜索" style="width: 300px"/>
+ </div>
+
</div>
- <div class="search-part">
- <a-select v-model:value="subFileTypeArr" allowClear @change="subFileTypeChange" :options="subFileTypeOptions"
- :maxTagCount="searchPanelOptions.maxTagCount" mode="multiple"
- :size="searchPanelOptions.size" placeholder="所有类型" style="width: 300px">
- </a-select>
+ <div class="button-wrapper">
+ <a-button type="primary" @click="compress">压缩打包</a-button>
</div>
- <div class="search-part">
- <a-select v-model:value="payloadArr" allowClear @change="payloadChange" :options="payloadOptions"
- :maxTagCount="searchPanelOptions.maxTagCount" mode="multiple"
- :size="searchPanelOptions.size" placeholder="所有负载" style="width: 300px">
- </a-select>
+ <a-spin :spinning="loading" :delay="1000" tip="downloading" size="large">
+ <div class="media-panel-wrapper">
+ <a-table class="media-table" :columns="columns" :data-source="mediaData.data" row-key="fingerprint"
+ rowKey="file_id" :row-selection="rowSelection"
+ :pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData">
+ <template v-for="col in ['name']" #[col]="{text, record}" :key="col">
+
+ <div>
+ <a-input
+ v-if="editableData[record.file_id]"
+ v-model:value="editableData[record.file_id]['file_name']"
+ style="margin: -5px 0"
+ />
+ <template v-else>
+ <a-tooltip :title="text">
+ <a @click="viewFile(record.object_key)">{{ text }}</a>
+ </a-tooltip>
+ </template>
+ </div>
+
+ </template>
+ <template #original="{ text }">
+ {{ text }}
+ </template>
+ <template #action="{ record }">
+
+ <div class="editable-row-operations">
+ <!-- 编辑态操作 -->
+ <div v-if="editableData[record.file_id]">
+ <a-tooltip title="保存">
+ <span @click="save(record)" style="color: #28d445;"><CheckOutlined/></span>
+ </a-tooltip>
+ <a-tooltip title="取消">
+ <span @click="() => delete editableData[record.file_id]" style="color: #e70102;"><CloseOutlined/></span>
+ </a-tooltip>
+ </div>
+ <!-- 非编辑态操作 -->
+ <div v-else class="flex-align-center flex-row" style="color: #2d8cf0">
+ <a-tooltip title="下载">
+ <a class="fz18" @click="downloadMedia(record)">
+ <DownloadOutlined/>
+ </a>
+ </a-tooltip>
+
+ <a-tooltip title="编辑">
+ <a class="fz18" @click="edit(record)">
+ <EditOutlined/>
+ </a>
+ </a-tooltip>
+ </div>
+ </div>
+
+ </template>
+ </a-table>
+ </div>
+ </a-spin>
+
+ <div @click.self="showVideo = false" v-if="showVideo" class="modal">
+ <video class="video-js" :id="videoPlayerId"></video>
</div>
-
- <div class="search-part">
- <a-input-search :size="searchPanelOptions.size" v-model:value="searchQuery.name" @change="inputChange"
- placeholder="按文件名称搜索" style="width: 300px"/>
- </div>
-
- </div>
-
- <div class="button-wrapper">
- <a-button type="primary" @click="compress">压缩打包</a-button>
- </div>
-
- <a-spin :spinning="loading" :delay="1000" tip="downloading" size="large">
- <div class="media-panel-wrapper">
- <a-table class="media-table" :columns="columns" :data-source="mediaData.data" row-key="fingerprint"
- rowKey="file_id" :row-selection="rowSelection"
- :pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData">
- <template v-for="col in ['name']" #[col]="{text, record}" :key="col">
-
- <div>
- <a-input
- v-if="editableData[record.file_id]"
- v-model:value="editableData[record.file_id]['file_name']"
- style="margin: -5px 0"
- />
- <template v-else>
- <a-tooltip :title="text">
- <a @click="viewFile(record.object_key)">{{ text }}</a>
- </a-tooltip>
- </template>
- </div>
-
- </template>
- <template #original="{ text }">
- {{ text }}
- </template>
- <template #action="{ record }">
-
- <div class="editable-row-operations">
- <!-- 编辑态操作 -->
- <div v-if="editableData[record.file_id]">
- <a-tooltip title="保存">
- <span @click="save(record)" style="color: #28d445;"><CheckOutlined/></span>
- </a-tooltip>
- <a-tooltip title="取消">
- <span @click="() => delete editableData[record.file_id]" style="color: #e70102;"><CloseOutlined/></span>
- </a-tooltip>
- </div>
- <!-- 非编辑态操作 -->
- <div v-else class="flex-align-center flex-row" style="color: #2d8cf0">
- <a-tooltip title="下载">
- <a class="fz18" @click="downloadMedia(record)">
- <DownloadOutlined/>
- </a>
- </a-tooltip>
-
- <a-tooltip title="编辑">
- <a class="fz18" @click="edit(record)">
- <EditOutlined/>
- </a>
- </a-tooltip>
- </div>
- </div>
-
- </template>
- </a-table>
- </div>
- </a-spin>
-
- <div @click.self="showVideo = false" v-if="showVideo" class="modal">
- <video class="video-js" :id="videoPlayerId"></video>
- </div>
</template>
@@ -122,7 +123,7 @@
const showVideo = ref(false)
const videoPlayerId = ref('videoPlayerId')
// 文件前缀
-const prefix = 'https://dev.jxpskj.com:9000/cloud-bucket'
+const prefix = 'https://dev.jxpskj.com:8026/cloud-bucket'
// 搜索栏配置项
const searchPanelOptions = reactive({
size: 'large',
@@ -132,15 +133,15 @@
})
interface MediaFile {
- fingerprint: string,
- drone: string,
- payload: string,
- is_original: string,
- file_name: string,
- file_path: string,
- create_time: string,
- file_id: string,
- object_key: string
+ fingerprint: string,
+ drone: string,
+ payload: string,
+ is_original: string,
+ file_name: string,
+ file_path: string,
+ create_time: string,
+ file_id: string,
+ object_key: string
}
const subFileTypeOptions = [
@@ -370,6 +371,7 @@
})
Promise.all(promiseList).then(res => {
+ console.log(res, '+++++++++++')
res.forEach(e => {
zip.file(e.name, e.data, { base64: true })
})
@@ -393,10 +395,6 @@
.then((response) => {
const ext = url.split('.')[1]
// 若文件名不以后缀结尾,则手动添加后缀
- if (!name.endsWith(ext)) {
- name = name + '.' + ext
- }
-
resolve({
name: name,
data: response.data
@@ -444,86 +442,91 @@
function downloadMedia (media: MediaFile) {
loading.value = true
- downloadMediaFile(workspaceId, media.file_id).then(res => {
- if (!res) {
- return
- }
+ const url = prefix + '/' + media.object_key
+ const data = new Blob([url])
+ downloadFile(data, media.file_name)
+ loading.value = false
- const data = new Blob([res])
- downloadFile(data, media.file_name)
- loading.value = false
- }).finally(() => {
-
- })
+ // downloadMediaFile(workspaceId, media.file_id).then(res => {
+ // if (!res) {
+ // return
+ // }
+ //
+ // const data = new Blob([url])
+ // downloadFile(data, media.file_name)
+ // loading.value = false
+ // }).finally(() => {
+ // loading.value = false
+ // })
}
</script>
<style lang="scss" scoped>
.media-panel-wrapper {
- width: 100%;
- padding: 16px;
+ width: 100%;
+ padding: 16px;
- .media-table {
- background: #fff;
- margin-top: 10px;
- }
+ .media-table {
+ background: #fff;
+ margin-top: 10px;
+ }
- .action-area {
- color: $primary;
- cursor: pointer;
- }
+ .action-area {
+ color: $primary;
+ cursor: pointer;
+ }
}
.header {
- width: 100%;
- height: 60px;
- background: #fff;
- padding: 16px;
- font-size: 20px;
- font-weight: bold;
- text-align: start;
- color: #000;
+ width: 100%;
+ height: 60px;
+ background: #fff;
+ padding: 16px;
+ font-size: 20px;
+ font-weight: bold;
+ text-align: start;
+ color: #000;
}
.search-panel-wrapper {
- height: 85px;
- background: #ffffff;
- padding: 0 20px;
- display: flex;
- align-items: center;
+ height: 85px;
+ background: #ffffff;
+ padding: 0 20px;
+ display: flex;
+ align-items: center;
- .search-part {
- margin-right: 10px;
- }
+ .search-part {
+ margin-right: 10px;
+ }
}
.button-wrapper {
- background: #ffffff;
- padding-left: 20px;
+ background: #ffffff;
+ padding-left: 20px;
}
.editable-row-operations {
- div > span {
- margin-right: 10px;
- }
+ div > span {
+ margin-right: 10px;
+ }
}
.modal {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- background-color: rgba(0, 0, 0, 0.5);
- display: flex;
- align-items: center;
- justify-content: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ background-color: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
- #videoPlayerId {
- width: 70%;
- height: 80%;
- }
+ #videoPlayerId {
+ width: 70%;
+ height: 80%;
+ }
}
</style>
diff --git a/src/components/g-map/DroneControlPanel.vue b/src/components/g-map/DroneControlPanel.vue
index bd5764f..04947f5 100644
--- a/src/components/g-map/DroneControlPanel.vue
+++ b/src/components/g-map/DroneControlPanel.vue
@@ -1,245 +1,276 @@
<template>
- <div class="drone-control-wrapper" v-if="modelValue">
- <div class="drone-control-header width-100 flex-display flex-align-center flex-justify-between">
- <span>无人机飞行控制</span>
- <span @click="closeDrone">
- <CloseOutlined />
+ <div class="drone-control-wrapper" v-if="modelValue">
+ <div class="drone-control-header width-100 flex-display flex-align-center flex-justify-between">
+ <span>无人机飞行控制</span>
+ <span @click="closeDrone">
+ <CloseOutlined/>
</span>
- </div>
- <div class="drone-control-box">
- <div class="box">
- <div class="row">
- <div class="drone-control"><Button :ghost="!flightController" size="small" @click="onClickFightControl">{{ flightController ? '退出控制' : '进入控制'}}</Button></div>
</div>
- <div class="row">
- <div class="drone-control-direction">
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_Q)" @onmouseup="onMouseUp">
- <template #icon><UndoOutlined /></template><span class="word">Q</span>
- </Button>
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_W)" @onmouseup="onMouseUp">
- <template #icon><UpOutlined/></template><span class="word">W</span>
- </Button>
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_E)" @onmouseup="onMouseUp">
- <template #icon><RedoOutlined /></template><span class="word">E</span>
- </Button>
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.ARROW_UP)" @onmouseup="onMouseUp">
- <template #icon><ArrowUpOutlined /></template>
- </Button>
- <br />
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_A)" @onmouseup="onMouseUp">
- <template #icon><LeftOutlined/></template><span class="word">A</span>
- </Button>
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_S)" @onmouseup="onMouseUp">
- <template #icon><DownOutlined/></template><span class="word">S</span>
- </Button>
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_D)" @onmouseup="onMouseUp">
- <template #icon><RightOutlined/></template><span class="word">D</span>
- </Button>
- <Button size="small" ghost @mousedown="onMouseDown(KeyCode.ARROW_DOWN)" @onmouseup="onMouseUp">
- <template #icon><ArrowDownOutlined /></template>
- </Button>
- </div>
- <Button type="primary" size="small" danger ghost @click="handleEmergencyStop" >
- <template #icon><PauseCircleOutlined/></template><span>结束</span>
- </Button>
- </div>
- <div class="row">
- <DroneControlPopover
- :visible="flyToPointPopoverData.visible"
- :loading="flyToPointPopoverData.loading"
- @confirm="($event) => onFlyToConfirm(true)"
- @cancel="($event) =>onFlyToConfirm(false)"
- >
- <template #formContent>
- <div class="form-content">
- <div>
- <span class="form-label">纬度:</span>
- <a-input-number v-model:value="flyToPointPopoverData.latitude"/>
+ <div class="drone-control-box">
+ <div class="box">
+ <div class="row">
+ <div class="drone-control">
+ <Button :ghost="!flightController" size="small" @click="onClickFightControl">
+ {{ flightController ? '退出控制' : '进入控制' }}
+ </Button>
+ </div>
</div>
- <div>
- <span class="form-label">经度:</span>
- <a-input-number v-model:value="flyToPointPopoverData.longitude"/>
+ <div class="row">
+ <div class="drone-control-direction">
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_Q)" @onmouseup="onMouseUp">
+ <template #icon>
+ <UndoOutlined/>
+ </template>
+ <span class="word">Q</span>
+ </Button>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_W)" @onmouseup="onMouseUp">
+ <template #icon>
+ <UpOutlined/>
+ </template>
+ <span class="word">W</span>
+ </Button>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_E)" @onmouseup="onMouseUp">
+ <template #icon>
+ <RedoOutlined/>
+ </template>
+ <span class="word">E</span>
+ </Button>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.ARROW_UP)" @onmouseup="onMouseUp">
+ <template #icon>
+ <ArrowUpOutlined/>
+ </template>
+ </Button>
+ <br/>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_A)" @onmouseup="onMouseUp">
+ <template #icon>
+ <LeftOutlined/>
+ </template>
+ <span class="word">A</span>
+ </Button>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_S)" @onmouseup="onMouseUp">
+ <template #icon>
+ <DownOutlined/>
+ </template>
+ <span class="word">S</span>
+ </Button>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_D)" @onmouseup="onMouseUp">
+ <template #icon>
+ <RightOutlined/>
+ </template>
+ <span class="word">D</span>
+ </Button>
+ <Button size="small" ghost @mousedown="onMouseDown(KeyCode.ARROW_DOWN)" @onmouseup="onMouseUp">
+ <template #icon>
+ <ArrowDownOutlined/>
+ </template>
+ </Button>
+ </div>
+ <Button type="primary" size="small" danger ghost @click="handleEmergencyStop">
+ <template #icon>
+ <PauseCircleOutlined/>
+ </template>
+ <span>结束</span>
+ </Button>
</div>
- <div>
- <span class="form-label">高度(m):</span>
- <a-input-number v-model:value="flyToPointPopoverData.height"/>
+ <div class="row">
+ <DroneControlPopover
+ :visible="flyToPointPopoverData.visible"
+ :loading="flyToPointPopoverData.loading"
+ @confirm="($event) => onFlyToConfirm(true)"
+ @cancel="($event) =>onFlyToConfirm(false)"
+ >
+ <template #formContent>
+ <div class="form-content">
+ <div>
+ <span class="form-label">纬度:</span>
+ <a-input-number v-model:value="flyToPointPopoverData.latitude"/>
+ </div>
+ <div>
+ <span class="form-label">经度:</span>
+ <a-input-number v-model:value="flyToPointPopoverData.longitude"/>
+ </div>
+ <div>
+ <span class="form-label">高度(m):</span>
+ <a-input-number v-model:value="flyToPointPopoverData.height"/>
+ </div>
+ </div>
+ </template>
+ <Button size="small" ghost @click="onShowFlyToPopover">
+ <span>起飞</span>
+ </Button>
+ </DroneControlPopover>
+ <Button size="small" ghost @click="onStopFlyToPoint">
+ <span>停止起飞</span>
+ </Button>
+ <DroneControlPopover
+ :visible="takeoffToPointPopoverData.visible"
+ :loading="takeoffToPointPopoverData.loading"
+ @confirm="($event) => onTakeoffToPointConfirm(true)"
+ @cancel="($event) =>onTakeoffToPointConfirm(false)"
+ >
+ <template #formContent>
+ <div class="form-content">
+ <div>
+ <span class="form-label">纬度:</span>
+ <a-input-number v-model:value="takeoffToPointPopoverData.latitude"/>
+ </div>
+ <div>
+ <span class="form-label">经度:</span>
+ <a-input-number v-model:value="takeoffToPointPopoverData.longitude"/>
+ </div>
+ <div>
+ <span class="form-label">高度(m):</span>
+ <a-input-number v-model:value="takeoffToPointPopoverData.height"/>
+ </div>
+ <div>
+ <span class="form-label">安全起飞高度(m):</span>
+ <a-input-number v-model:value="takeoffToPointPopoverData.securityTakeoffHeight"/>
+ </div>
+ <div>
+ <span class="form-label">返回原点高度(m):</span>
+ <a-input-number v-model:value="takeoffToPointPopoverData.rthAltitude"/>
+ </div>
+ <div>
+ <span class="form-label">失控操作:</span>
+ <a-select
+ v-model:value="takeoffToPointPopoverData.rcLostAction"
+ style="width: 120px"
+ :options="LostControlActionInCommandFLightOptions"
+ ></a-select>
+ </div>
+ <div>
+ <span class="form-label">线路丢失操作:</span>
+ <a-select
+ v-model:value="takeoffToPointPopoverData.exitWaylineWhenRcLost"
+ style="width: 120px"
+ :options="WaylineLostControlActionInCommandFlightOptions"
+ ></a-select>
+ </div>
+ </div>
+ </template>
+ <Button size="small" ghost @click="onShowTakeoffToPointPopover">
+ <span>一键起飞</span>
+ </Button>
+ </DroneControlPopover>
+ <Button :loading="cmdItem.loading" size="small" ghost @click="sendControlCmd(cmdItem, 0)">
+ {{ cmdItem.operateText }}
+ </Button>
</div>
- </div>
- </template>
- <Button size="small" ghost @click="onShowFlyToPopover" >
- <span>起飞</span>
- </Button>
- </DroneControlPopover>
- <Button size="small" ghost @click="onStopFlyToPoint" >
- <span>停止起飞</span>
- </Button>
- <DroneControlPopover
- :visible="takeoffToPointPopoverData.visible"
- :loading="takeoffToPointPopoverData.loading"
- @confirm="($event) => onTakeoffToPointConfirm(true)"
- @cancel="($event) =>onTakeoffToPointConfirm(false)"
- >
- <template #formContent>
- <div class="form-content">
- <div>
- <span class="form-label">纬度:</span>
- <a-input-number v-model:value="takeoffToPointPopoverData.latitude"/>
- </div>
- <div>
- <span class="form-label">经度:</span>
- <a-input-number v-model:value="takeoffToPointPopoverData.longitude"/>
- </div>
- <div>
- <span class="form-label">高度(m):</span>
- <a-input-number v-model:value="takeoffToPointPopoverData.height"/>
- </div>
- <div>
- <span class="form-label">安全起飞高度(m):</span>
- <a-input-number v-model:value="takeoffToPointPopoverData.securityTakeoffHeight"/>
- </div>
- <div>
- <span class="form-label">返回原点高度(m):</span>
- <a-input-number v-model:value="takeoffToPointPopoverData.rthAltitude"/>
- </div>
- <div>
- <span class="form-label">失控操作:</span>
- <a-select
- v-model:value="takeoffToPointPopoverData.rcLostAction"
- style="width: 120px"
- :options="LostControlActionInCommandFLightOptions"
- ></a-select>
- </div>
- <div>
- <span class="form-label">线路丢失操作:</span>
- <a-select
- v-model:value="takeoffToPointPopoverData.exitWaylineWhenRcLost"
- style="width: 120px"
- :options="WaylineLostControlActionInCommandFlightOptions"
- ></a-select>
- </div>
- </div>
- </template>
- <Button size="small" ghost @click="onShowTakeoffToPointPopover" >
- <span>一键起飞</span>
- </Button>
- </DroneControlPopover>
- <Button :loading="cmdItem.loading" size="small" ghost @click="sendControlCmd(cmdItem, 0)">
- {{ cmdItem.operateText }}
- </Button>
- </div>
- </div>
- <div class="box">
- <div class="row">
- <Select v-model:value="payloadSelectInfo.value" style="width: 110px; marginRight: 5px" :options="payloadSelectInfo.options" @change="handlePayloadChange"/>
- <div class="drone-control">
- <Button type="primary" size="small" @click="onAuthPayload">负载控制</Button>
- </div>
- </div>
- <div class="row">
- <DroneControlPopover
- :visible="gimbalResetPopoverData.visible"
- :loading="gimbalResetPopoverData.loading"
- @confirm="($event) => onGimbalResetConfirm(true)"
- @cancel="($event) =>onGimbalResetConfirm(false)"
- >
- <template #formContent>
- <div class="form-content">
- <div>
- <span class="form-label">重置模式:</span>
- <a-select
- v-model:value="gimbalResetPopoverData.resetMode"
- style="width: 180px"
- :options="GimbalResetModeOptions"
- ></a-select>
- </div>
</div>
- </template>
- <Button size="small" ghost @click="onShowGimbalResetPopover">
- <span>复位</span>
- </Button>
- </DroneControlPopover>
- <Button size="small" ghost @click="onSwitchCameraMode">
- <span>相机模式开关</span>
- </Button>
- </div>
- <div class="row">
- <Button size="small" ghost @click="onStartCameraRecording">
- <span>开始录制</span>
- </Button>
- <Button size="small" ghost @click="onStopCameraRecording">
- <span>停止录制</span>
- </Button>
- </div>
- <div class="row">
- <Button size="small" ghost @click="onTakeCameraPhoto">
- <span>拍照</span>
- </Button>
- <DroneControlPopover
- :visible="zoomFactorPopoverData.visible"
- :loading="zoomFactorPopoverData.loading"
- @confirm="($event) => onZoomFactorConfirm(true)"
- @cancel="($event) =>onZoomFactorConfirm(false)"
- >
- <template #formContent>
- <div class="form-content">
- <div>
- <span class="form-label">相机类型:</span>
- <a-select
- v-model:value="zoomFactorPopoverData.cameraType"
- style="width: 120px"
- :options="ZoomCameraTypeOptions"
- ></a-select>
- </div>
- <div>
- <span class="form-label">缩放:</span>
- <a-input-number v-model:value="zoomFactorPopoverData.zoomFactor" :min="2" :max="200" />
- </div>
+ <div class="box">
+ <div class="row">
+ <Select v-model:value="payloadSelectInfo.value" style="width: 110px; marginRight: 5px"
+ :options="payloadSelectInfo.options" @change="handlePayloadChange"/>
+ <div class="drone-control">
+ <Button type="primary" size="small" @click="onAuthPayload">负载控制</Button>
+ </div>
+ </div>
+ <div class="row">
+ <DroneControlPopover
+ :visible="gimbalResetPopoverData.visible"
+ :loading="gimbalResetPopoverData.loading"
+ @confirm="($event) => onGimbalResetConfirm(true)"
+ @cancel="($event) =>onGimbalResetConfirm(false)"
+ >
+ <template #formContent>
+ <div class="form-content">
+ <div>
+ <span class="form-label">重置模式:</span>
+ <a-select
+ v-model:value="gimbalResetPopoverData.resetMode"
+ style="width: 180px"
+ :options="GimbalResetModeOptions"
+ ></a-select>
+ </div>
+ </div>
+ </template>
+ <Button size="small" ghost @click="onShowGimbalResetPopover">
+ <span>复位</span>
+ </Button>
+ </DroneControlPopover>
+ <Button size="small" ghost @click="onSwitchCameraMode">
+ <span>相机模式开关</span>
+ </Button>
+ </div>
+ <div class="row">
+ <Button size="small" ghost @click="onStartCameraRecording">
+ <span>开始录制</span>
+ </Button>
+ <Button size="small" ghost @click="onStopCameraRecording">
+ <span>停止录制</span>
+ </Button>
+ </div>
+ <div class="row">
+ <Button size="small" ghost @click="onTakeCameraPhoto">
+ <span>拍照</span>
+ </Button>
+ <DroneControlPopover
+ :visible="zoomFactorPopoverData.visible"
+ :loading="zoomFactorPopoverData.loading"
+ @confirm="($event) => onZoomFactorConfirm(true)"
+ @cancel="($event) =>onZoomFactorConfirm(false)"
+ >
+ <template #formContent>
+ <div class="form-content">
+ <div>
+ <span class="form-label">相机类型:</span>
+ <a-select
+ v-model:value="zoomFactorPopoverData.cameraType"
+ style="width: 120px"
+ :options="ZoomCameraTypeOptions"
+ ></a-select>
+ </div>
+ <div>
+ <span class="form-label">缩放:</span>
+ <a-input-number v-model:value="zoomFactorPopoverData.zoomFactor" :min="2"
+ :max="200"/>
+ </div>
+ </div>
+ </template>
+ <Button size="small" ghost @click="($event) => onShowZoomFactorPopover()">
+ <span class="word" @click=";">聚焦</span>
+ </Button>
+ </DroneControlPopover>
+ <DroneControlPopover
+ :visible="cameraAimPopoverData.visible"
+ :loading="cameraAimPopoverData.loading"
+ @confirm="($event) => onCameraAimConfirm(true)"
+ @cancel="($event) =>onCameraAimConfirm(false)"
+ >
+ <template #formContent>
+ <div class="form-content">
+ <div>
+ <span class="form-label">相机类型:</span>
+ <a-select
+ v-model:value="cameraAimPopoverData.cameraType"
+ style="width: 120px"
+ :options="CameraTypeOptions"
+ ></a-select>
+ </div>
+ <div>
+ <span class="form-label">锁定:</span>
+ <a-switch v-model:checked="cameraAimPopoverData.locked"/>
+ </div>
+ <div>
+ <span class="form-label">x:</span>
+ <a-input-number v-model:value="cameraAimPopoverData.x" :min="0" :max="1"/>
+ </div>
+ <div>
+ <span class="form-label">y:</span>
+ <a-input-number v-model:value="cameraAimPopoverData.y" :min="0" :max="1"/>
+ </div>
+ </div>
+ </template>
+ <Button size="small" ghost @click="($event) => onShowCameraAimPopover()">
+ <span class="word" @click=";">目标</span>
+ </Button>
+ </DroneControlPopover>
+ </div>
</div>
- </template>
- <Button size="small" ghost @click="($event) => onShowZoomFactorPopover()">
- <span class="word" @click=";">聚焦</span>
- </Button>
- </DroneControlPopover>
- <DroneControlPopover
- :visible="cameraAimPopoverData.visible"
- :loading="cameraAimPopoverData.loading"
- @confirm="($event) => onCameraAimConfirm(true)"
- @cancel="($event) =>onCameraAimConfirm(false)"
- >
- <template #formContent>
- <div class="form-content">
- <div>
- <span class="form-label">相机类型:</span>
- <a-select
- v-model:value="cameraAimPopoverData.cameraType"
- style="width: 120px"
- :options="CameraTypeOptions"
- ></a-select>
- </div>
- <div>
- <span class="form-label">锁定:</span>
- <a-switch v-model:checked="cameraAimPopoverData.locked"/>
- </div>
- <div>
- <span class="form-label">x:</span>
- <a-input-number v-model:value="cameraAimPopoverData.x" :min="0" :max="1"/>
- </div>
- <div>
- <span class="form-label">y:</span>
- <a-input-number v-model:value="cameraAimPopoverData.y" :min="0" :max="1"/>
- </div>
- </div>
- </template>
- <Button size="small" ghost @click="($event) => onShowCameraAimPopover()">
- <span class="word" @click=";">目标</span>
- </Button>
- </DroneControlPopover>
- </div>
+ </div>
+ <!-- 信息提示 -->
+ <!-- <DroneControlInfoPanel :message="drcInfo"></DroneControlInfoPanel> -->
</div>
- </div>
- <!-- 信息提示 -->
- <!-- <DroneControlInfoPanel :message="drcInfo"></DroneControlInfoPanel> -->
- </div>
</template>
<script setup lang="ts">
@@ -249,25 +280,45 @@
import { useMyStore } from '/@/store'
import { postDrcEnter, postDrcExit } from '/@/api/drc'
import { useMqtt, DeviceTopicInfo } from './use-mqtt'
-import { DownOutlined, UpOutlined, LeftOutlined, RightOutlined, PauseCircleOutlined, UndoOutlined, RedoOutlined, ArrowUpOutlined, ArrowDownOutlined, CloseOutlined } from '@ant-design/icons-vue'
+import {
+ DownOutlined,
+ UpOutlined,
+ LeftOutlined,
+ RightOutlined,
+ PauseCircleOutlined,
+ UndoOutlined,
+ RedoOutlined,
+ ArrowUpOutlined,
+ ArrowDownOutlined,
+ CloseOutlined
+} from '@ant-design/icons-vue'
import { useManualControl, KeyCode } from './use-manual-control'
import { usePayloadControl } from './use-payload-control'
import { CameraMode, CameraType, CameraTypeOptions, ZoomCameraTypeOptions, CameraListItem } from '/@/types/live-stream'
import { useDroneControlWsEvent } from './use-drone-control-ws-event'
import { useDroneControlMqttEvent } from './use-drone-control-mqtt-event'
-import { postFlightAuth, LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight } from '/@/api/drone-control/drone'
+import {
+ postFlightAuth,
+ LostControlActionInCommandFLight,
+ WaylineLostControlActionInCommandFlight
+} from '/@/api/drone-control/drone'
import { useDroneControl } from './use-drone-control'
-import { GimbalResetMode, GimbalResetModeOptions, LostControlActionInCommandFLightOptions, WaylineLostControlActionInCommandFlightOptions } from '/@/types/drone-control'
+import {
+ GimbalResetMode,
+ GimbalResetModeOptions,
+ LostControlActionInCommandFLightOptions,
+ WaylineLostControlActionInCommandFlightOptions
+} from '/@/types/drone-control'
import DroneControlPopover from './DroneControlPopover.vue'
import DroneControlInfoPanel from './DroneControlInfoPanel.vue'
import { noDebugCmdList as baseCmdList, DeviceCmdItem, DeviceCmd } from '/@/types/device-cmd'
import { useDockControl } from './use-dock-control'
const props = defineProps<{
- sn: string,
- deviceInfo: DeviceInfoType,
- payloads: null | PayloadInfo[],
- modelValue: Boolean,
+ sn: string,
+ deviceInfo: DeviceInfoType,
+ payloads: null | PayloadInfo[],
+ modelValue: Boolean,
}>()
const store = useMyStore()
@@ -297,6 +348,7 @@
}
cmdItem.loading = false
}
+
const emits = defineEmits(['update:modelValue'])
// 关闭弹窗
const closeDrone = () => {
@@ -376,10 +428,10 @@
async function onTakeoffToPointConfirm (confirm: boolean) {
if (confirm) {
if (!takeoffToPointPopoverData.height ||
- !takeoffToPointPopoverData.latitude ||
- !takeoffToPointPopoverData.longitude ||
- !takeoffToPointPopoverData.securityTakeoffHeight ||
- !takeoffToPointPopoverData.rthAltitude) {
+ !takeoffToPointPopoverData.latitude ||
+ !takeoffToPointPopoverData.longitude ||
+ !takeoffToPointPopoverData.securityTakeoffHeight ||
+ !takeoffToPointPopoverData.rthAltitude) {
message.error('输入错误')
return
}
@@ -421,8 +473,13 @@
}
enterFlightControl()
}
+
// 进入飞行控制
async function enterFlightControl () {
+ if (!clientId.value) {
+ message.error('无人机不在空中,不能进入指挥飞行模式。')
+ return
+ }
try {
const { code, data } = await postDrcEnter({
client_id: clientId.value,
@@ -714,71 +771,72 @@
</script>
<style lang='scss' scoped>
-.drone-control-wrapper{
- position: absolute;
+.drone-control-wrapper {
+ position: absolute;
background: #000;
color: #fff;
- left: calc( 100% + 10px);
+ left: calc(100% + 10px);
width: 480px;
top: 0;
- .drone-control-header{
- font-size: 14px;
- font-weight: 600;
- padding: 10px 10px 0px;
- }
-
- .drone-control-box {
- display: flex;
- flex-wrap: 1;
- .box {
- width: 50%;
- padding: 5px;
- border: 0.5px solid rgba(255,255,255,0.3);
-
- .row {
- display: flex;
- flex-wrap: wrap;
- padding: 2px;
-
- + .row{
- margin-bottom: 6px;
- }
-
- &::v-deep{
- .ant-btn{
- font-size: 12px;
- padding: 0px 4px;
- margin-right: 5px;
- }
- }
- }
-
- .drone-control{
- &::v-deep{
-
- .ant-select-single:not(.ant-select-customize-input) .ant-select-selector{
- padding: 0 2px;
- }
- }
- }
-
- .drone-control-direction{
- margin-right: 10px;
-
- .ant-btn {
- // padding: 0px 1px;
- margin-right: 0;
- }
-
- .word{
- width: 12px;
- margin-left: 2px;
- font-size: 12px;
- color: #aaa;
- }
- }
+ .drone-control-header {
+ font-size: 14px;
+ font-weight: 600;
+ padding: 10px 10px 0px;
}
- }
+
+ .drone-control-box {
+ display: flex;
+ flex-wrap: 1;
+
+ .box {
+ width: 50%;
+ padding: 5px;
+ border: 0.5px solid rgba(255, 255, 255, 0.3);
+
+ .row {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 2px;
+
+ + .row {
+ margin-bottom: 6px;
+ }
+
+ &::v-deep {
+ .ant-btn {
+ font-size: 12px;
+ padding: 0px 4px;
+ margin-right: 5px;
+ }
+ }
+ }
+
+ .drone-control {
+ &::v-deep {
+
+ .ant-select-single:not(.ant-select-customize-input) .ant-select-selector {
+ padding: 0 2px;
+ }
+ }
+ }
+
+ .drone-control-direction {
+ margin-right: 10px;
+
+ .ant-btn {
+ // padding: 0px 1px;
+ margin-right: 0;
+ }
+
+ .word {
+ width: 12px;
+ margin-left: 2px;
+ font-size: 12px;
+ color: #aaa;
+ }
+ }
+ }
+ }
}
</style>
diff --git a/src/router/index.ts b/src/router/index.ts
index f6b974c..c639123 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -85,8 +85,8 @@
path: '/' + ERouterName.MEDIA,
name: ERouterName.MEDIA,
component: () => import('/@/pages/page-web/projects/media.vue'),
- meta:{
- hidden:true
+ meta: {
+ hidden: true
}
},
{
--
Gitblit v1.9.3