sean.zhou
2 years ago
24 changed files with 1048 additions and 546 deletions
@ -1,182 +0,0 @@ |
|||||||
<template> |
|
||||||
<div class="header">Task Plan Library</div> |
|
||||||
<div class="plan-panel-wrapper"> |
|
||||||
<!-- <router-link :to=" '/' + ERouterName.CREATE_PLAN"> |
|
||||||
<a-button type="primary">Create Plan</a-button> |
|
||||||
</router-link> --> |
|
||||||
<a-table class="plan-table" :columns="columns" :data-source="plansData.data" row-key="job_id" |
|
||||||
:pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData"> |
|
||||||
<template #status="{ record }"> |
|
||||||
<span v-if="taskProgressMap[record.bid]"> |
|
||||||
<a-progress type="line" :percent="taskProgressMap[record.bid]?.progress?.percent" |
|
||||||
:status="taskProgressMap[record.bid]?.status.indexOf(ETaskStatus.FAILED) != -1 ? 'exception' : taskProgressMap[record.bid]?.status.indexOf(ETaskStatus.OK) != -1 ? 'success' : 'normal'"> |
|
||||||
<template #format="percent"> |
|
||||||
<a-tooltip :title="taskProgressMap[record.bid]?.status"> |
|
||||||
<div style="white-space: nowrap; text-overflow: ellipsis; overflow: hidden; position: absolute; left: 5px; top: -12px;"> |
|
||||||
{{ percent }}% {{ taskProgressMap[record.bid]?.status }} |
|
||||||
</div> |
|
||||||
</a-tooltip> |
|
||||||
</template> |
|
||||||
</a-progress> |
|
||||||
</span> |
|
||||||
</template> |
|
||||||
<template #action="{ record }"> |
|
||||||
<span class="action-area"> |
|
||||||
<a-popconfirm |
|
||||||
title="Are you sure execute this task?" |
|
||||||
ok-text="Yes" |
|
||||||
cancel-text="No" |
|
||||||
@confirm="executePlan(record.job_id)" |
|
||||||
> |
|
||||||
<a-button type="primary" size="small">Execute</a-button> |
|
||||||
</a-popconfirm> |
|
||||||
</span> |
|
||||||
</template> |
|
||||||
</a-table> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup lang="ts"> |
|
||||||
import { reactive, ref } from '@vue/reactivity' |
|
||||||
import { message } from 'ant-design-vue' |
|
||||||
import { TableState } from 'ant-design-vue/lib/table/interface' |
|
||||||
import { computed, onMounted, watch } from 'vue' |
|
||||||
import { IPage } from '../api/http/type' |
|
||||||
import { executeWaylineJobs, getWaylineJobs } from '../api/wayline' |
|
||||||
import { getRoot } from '../root' |
|
||||||
import { useMyStore } from '../store' |
|
||||||
import { ELocalStorageKey, ERouterName } from '../types/enums' |
|
||||||
import router from '/@/router' |
|
||||||
import { ETaskStatus } from '/@/types/wayline' |
|
||||||
|
|
||||||
const store = useMyStore() |
|
||||||
|
|
||||||
const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)! |
|
||||||
|
|
||||||
const root = getRoot() |
|
||||||
const body: IPage = { |
|
||||||
page: 1, |
|
||||||
total: 0, |
|
||||||
page_size: 50 |
|
||||||
} |
|
||||||
const paginationProp = reactive({ |
|
||||||
pageSizeOptions: ['20', '50', '100'], |
|
||||||
showQuickJumper: true, |
|
||||||
showSizeChanger: true, |
|
||||||
pageSize: 50, |
|
||||||
current: 1, |
|
||||||
total: 0 |
|
||||||
}) |
|
||||||
|
|
||||||
const columns = [ |
|
||||||
{ |
|
||||||
title: 'Plan Name', |
|
||||||
dataIndex: 'job_name' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Flight Route Name', |
|
||||||
dataIndex: 'file_name', |
|
||||||
ellipsis: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Dock Name', |
|
||||||
dataIndex: 'dock_name', |
|
||||||
ellipsis: true |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Creator', |
|
||||||
dataIndex: 'username', |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Updated', |
|
||||||
dataIndex: 'update_time' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Status', |
|
||||||
key: 'status', |
|
||||||
width: 200, |
|
||||||
slots: { customRender: 'status' } |
|
||||||
}, |
|
||||||
|
|
||||||
{ |
|
||||||
title: 'Action', |
|
||||||
slots: { customRender: 'action' } |
|
||||||
} |
|
||||||
] |
|
||||||
type Pagination = TableState['pagination'] |
|
||||||
|
|
||||||
interface TaskPlan { |
|
||||||
bid: string, |
|
||||||
job_id: string, |
|
||||||
job_name: string, |
|
||||||
file_name: string, |
|
||||||
dock_name: string, |
|
||||||
username: string, |
|
||||||
create_time: string, |
|
||||||
} |
|
||||||
|
|
||||||
const plansData = reactive({ |
|
||||||
data: [] as TaskPlan[] |
|
||||||
}) |
|
||||||
|
|
||||||
function createPlan () { |
|
||||||
root.$router.push('/' + ERouterName.CREATE_PLAN) |
|
||||||
} |
|
||||||
|
|
||||||
const taskProgressMap = computed(() => store.state.taskProgressInfo) |
|
||||||
|
|
||||||
onMounted(() => { |
|
||||||
getPlans() |
|
||||||
}) |
|
||||||
|
|
||||||
function getPlans () { |
|
||||||
getWaylineJobs(workspaceId, body).then(res => { |
|
||||||
if (res.code !== 0) { |
|
||||||
return |
|
||||||
} |
|
||||||
plansData.data = res.data.list |
|
||||||
paginationProp.total = res.data.pagination.total |
|
||||||
paginationProp.current = res.data.pagination.page |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
function refreshData (page: Pagination) { |
|
||||||
body.page = page?.current! |
|
||||||
body.page_size = page?.pageSize! |
|
||||||
getPlans() |
|
||||||
} |
|
||||||
|
|
||||||
function executePlan (jobId: string) { |
|
||||||
executeWaylineJobs(workspaceId, jobId).then(res => { |
|
||||||
if (res.code === 0) { |
|
||||||
message.success('Executed Successfully') |
|
||||||
getPlans() |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
.plan-panel-wrapper { |
|
||||||
width: 100%; |
|
||||||
padding: 16px; |
|
||||||
.plan-table { |
|
||||||
background: #fff; |
|
||||||
margin-top: 10px; |
|
||||||
} |
|
||||||
.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; |
|
||||||
} |
|
||||||
</style> |
|
@ -0,0 +1,233 @@ |
|||||||
|
<template> |
||||||
|
<div class="header">Task Plan Library</div> |
||||||
|
<div class="plan-panel-wrapper"> |
||||||
|
<a-table class="plan-table" :columns="columns" :data-source="plansData.data" row-key="job_id" |
||||||
|
:pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData"> |
||||||
|
<!-- 执行时间 --> |
||||||
|
<template #duration="{ record }"> |
||||||
|
<div> |
||||||
|
<div>{{ formatTaskTime(record.execute_time) }}</div> |
||||||
|
<div>{{ formatTaskTime(record.end_time) }}</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<!-- 任务类型 --> |
||||||
|
<template #taskType="{ record }"> |
||||||
|
<div>{{ formatTaskType(record) }}</div> |
||||||
|
</template> |
||||||
|
<!-- 状态 --> |
||||||
|
<template #status="{ record }"> |
||||||
|
<div> |
||||||
|
<div class="flex-display flex-align-center"> |
||||||
|
<span class="circle-icon" :style="{backgroundColor: formatTaskStatus(record).color}"></span> |
||||||
|
{{ formatTaskStatus(record).text }} |
||||||
|
<a-tooltip v-if="!!record.code" placement="bottom" arrow-point-at-center > |
||||||
|
<template #title> |
||||||
|
<div>{{ getCodeMessage(record.code) }}</div> |
||||||
|
</template> |
||||||
|
<exclamation-circle-outlined class="ml5" :style="{color: commonColor.WARN, fontSize: '16px' }"/> |
||||||
|
</a-tooltip> |
||||||
|
</div> |
||||||
|
<div v-if="record.status === TaskStatus.Carrying"> |
||||||
|
<a-progress :percent="record.progress || 0" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<!-- 操作 --> |
||||||
|
<template #action="{ record }"> |
||||||
|
<span class="action-area"> |
||||||
|
<a-popconfirm |
||||||
|
v-if="record.status === TaskStatus.Wait" |
||||||
|
title="Are you sure you want to delete flight task?" |
||||||
|
ok-text="Yes" |
||||||
|
cancel-text="No" |
||||||
|
@confirm="onDeleteTask(record.job_id)" |
||||||
|
> |
||||||
|
<a-button type="primary" size="small">Delete</a-button> |
||||||
|
</a-popconfirm> |
||||||
|
</span> |
||||||
|
</template> |
||||||
|
</a-table> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { reactive, ref } from '@vue/reactivity' |
||||||
|
import { message } from 'ant-design-vue' |
||||||
|
import { TableState } from 'ant-design-vue/lib/table/interface' |
||||||
|
import { onMounted } from 'vue' |
||||||
|
import { IPage } from '/@/api/http/type' |
||||||
|
import { deleteTask, getWaylineJobs, Task } from '/@/api/wayline' |
||||||
|
import { useMyStore } from '/@/store' |
||||||
|
import { ELocalStorageKey } from '/@/types/enums' |
||||||
|
import { useFormatTask } from './use-format-task' |
||||||
|
import { TaskStatus, TaskProgressInfo, TaskProgressStatus, TaskProgressWsStatusMap } from '/@/types/task' |
||||||
|
import { useTaskProgressEvent } from './use-task-progress-event' |
||||||
|
import { getErrorMessage } from '/@/utils/error-code/index' |
||||||
|
import { commonColor } from '/@/utils/color' |
||||||
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue' |
||||||
|
|
||||||
|
const store = useMyStore() |
||||||
|
const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)! |
||||||
|
|
||||||
|
const body: IPage = { |
||||||
|
page: 1, |
||||||
|
total: 0, |
||||||
|
page_size: 50 |
||||||
|
} |
||||||
|
const paginationProp = reactive({ |
||||||
|
pageSizeOptions: ['20', '50', '100'], |
||||||
|
showQuickJumper: true, |
||||||
|
showSizeChanger: true, |
||||||
|
pageSize: 50, |
||||||
|
current: 1, |
||||||
|
total: 0 |
||||||
|
}) |
||||||
|
|
||||||
|
const columns = [ |
||||||
|
{ |
||||||
|
title: 'Planned/Actual Time', |
||||||
|
dataIndex: 'duration', |
||||||
|
width: 200, |
||||||
|
slots: { customRender: 'duration' }, |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Plan Name', |
||||||
|
dataIndex: 'job_name', |
||||||
|
width: 150, |
||||||
|
ellipsis: true |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Type', |
||||||
|
dataIndex: 'taskType', |
||||||
|
width: 150, |
||||||
|
slots: { customRender: 'taskType' }, |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Flight Route Name', |
||||||
|
dataIndex: 'file_name', |
||||||
|
width: 150, |
||||||
|
ellipsis: true |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Dock Name', |
||||||
|
dataIndex: 'dock_name', |
||||||
|
width: 150, |
||||||
|
ellipsis: true |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Creator', |
||||||
|
dataIndex: 'username', |
||||||
|
width: 150, |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Status', |
||||||
|
key: 'status', |
||||||
|
width: 200, |
||||||
|
slots: { customRender: 'status' } |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: 'Action', |
||||||
|
width: 120, |
||||||
|
slots: { customRender: 'action' } |
||||||
|
} |
||||||
|
] |
||||||
|
type Pagination = TableState['pagination'] |
||||||
|
|
||||||
|
const plansData = reactive({ |
||||||
|
data: [] as Task[] |
||||||
|
}) |
||||||
|
|
||||||
|
const { formatTaskType, formatTaskTime, formatTaskStatus } = useFormatTask() |
||||||
|
|
||||||
|
// 设备任务执行进度更新 |
||||||
|
function onTaskProgressWs (data: TaskProgressInfo) { |
||||||
|
const { bid, output } = data |
||||||
|
if (output) { |
||||||
|
const { status, progress } = output || {} |
||||||
|
const taskItem = plansData.data.find(task => task.job_id === bid) |
||||||
|
if (!taskItem) return |
||||||
|
if (status) { |
||||||
|
taskItem.status = TaskProgressWsStatusMap[status] |
||||||
|
// 执行中,更新进度 |
||||||
|
if (status === TaskProgressStatus.Sent || status === TaskProgressStatus.inProgress) { |
||||||
|
taskItem.progress = progress?.percent || 0 |
||||||
|
} else if ([TaskProgressStatus.Rejected, TaskProgressStatus.Canceled, TaskProgressStatus.Timeout, TaskProgressStatus.Failed, TaskProgressStatus.OK].includes(status)) { |
||||||
|
getPlans() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function getCodeMessage (code: number) { |
||||||
|
return getErrorMessage(code) + `(code: ${code})` |
||||||
|
} |
||||||
|
|
||||||
|
useTaskProgressEvent(onTaskProgressWs) |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
getPlans() |
||||||
|
}) |
||||||
|
|
||||||
|
function getPlans () { |
||||||
|
getWaylineJobs(workspaceId, body).then(res => { |
||||||
|
if (res.code !== 0) { |
||||||
|
return |
||||||
|
} |
||||||
|
plansData.data = res.data.list |
||||||
|
paginationProp.total = res.data.pagination.total |
||||||
|
paginationProp.current = res.data.pagination.page |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function refreshData (page: Pagination) { |
||||||
|
body.page = page?.current! |
||||||
|
body.page_size = page?.pageSize! |
||||||
|
getPlans() |
||||||
|
} |
||||||
|
|
||||||
|
// 删除任务 |
||||||
|
async function onDeleteTask (jobId: string) { |
||||||
|
const { code } = await deleteTask(workspaceId, { |
||||||
|
job_id: jobId |
||||||
|
}) |
||||||
|
if (code === 0) { |
||||||
|
message.success('Deleted successfully') |
||||||
|
getPlans() |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.plan-panel-wrapper { |
||||||
|
width: 100%; |
||||||
|
padding: 16px; |
||||||
|
.plan-table { |
||||||
|
background: #fff; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
.action-area { |
||||||
|
color: $primary; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
.circle-icon { |
||||||
|
display: inline-block; |
||||||
|
width: 12px; |
||||||
|
height: 12px; |
||||||
|
margin-right: 3px; |
||||||
|
border-radius: 50%; |
||||||
|
vertical-align: middle; |
||||||
|
flex-shrink: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
.header { |
||||||
|
width: 100%; |
||||||
|
height: 60px; |
||||||
|
background: #fff; |
||||||
|
padding: 16px; |
||||||
|
font-size: 20px; |
||||||
|
font-weight: bold; |
||||||
|
text-align: start; |
||||||
|
color: #000; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,30 @@ |
|||||||
|
import { DEFAULT_PLACEHOLDER } from '/@/utils/constants' |
||||||
|
import { Task } from '/@/api/wayline' |
||||||
|
import { TaskStatusColor, TaskStatusMap, TaskTypeMap } from '/@/types/task' |
||||||
|
|
||||||
|
export function useFormatTask () { |
||||||
|
function formatTaskType (task: Task) { |
||||||
|
return TaskTypeMap[task.task_type] || DEFAULT_PLACEHOLDER |
||||||
|
} |
||||||
|
|
||||||
|
function formatTaskTime (time: string) { |
||||||
|
return time || DEFAULT_PLACEHOLDER |
||||||
|
} |
||||||
|
|
||||||
|
function formatTaskStatus (task: Task) { |
||||||
|
const statusObj = { |
||||||
|
text: '', |
||||||
|
color: '' |
||||||
|
} |
||||||
|
const { status } = task |
||||||
|
statusObj.text = TaskStatusMap[status] |
||||||
|
statusObj.color = TaskStatusColor[status] |
||||||
|
return statusObj |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
formatTaskType, |
||||||
|
formatTaskTime, |
||||||
|
formatTaskStatus, |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
import EventBus from '/@/event-bus/' |
||||||
|
import { onMounted, onBeforeUnmount } from 'vue' |
||||||
|
import { TaskProgressInfo } from '/@/types/task' |
||||||
|
|
||||||
|
export function useTaskProgressEvent (onTaskProgressWs: (data: TaskProgressInfo) => void): void { |
||||||
|
function handleTaskProgress (payload: any) { |
||||||
|
onTaskProgressWs(payload.data) |
||||||
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
// console.log('payload', payload.data)
|
||||||
|
} |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
EventBus.on('deviceTaskProgress', handleTaskProgress) |
||||||
|
}) |
||||||
|
|
||||||
|
onBeforeUnmount(() => { |
||||||
|
EventBus.off('deviceTaskProgress', handleTaskProgress) |
||||||
|
}) |
||||||
|
} |
@ -1,123 +0,0 @@ |
|||||||
<template> |
|
||||||
<div class="panel-wrapper" draggable="true"> |
|
||||||
<div class="header">Wayline Library</div> |
|
||||||
<a-button type="primary" style="margin-top:20px" @click="onRefresh" |
|
||||||
>Refresh</a-button |
|
||||||
> |
|
||||||
<a-table class="table" :columns="columns" :data-source="data"> |
|
||||||
<template #name="{ text, record }"> |
|
||||||
<a :href="record.preview_url">{{ text }}</a> |
|
||||||
</template> |
|
||||||
<template #action> |
|
||||||
<span class="action-area"> |
|
||||||
action |
|
||||||
</span> |
|
||||||
</template> |
|
||||||
</a-table> |
|
||||||
</div> |
|
||||||
</template> |
|
||||||
|
|
||||||
<script setup lang="ts"> |
|
||||||
import { ref } from '@vue/reactivity' |
|
||||||
import { onMounted } from 'vue' |
|
||||||
import { ELocalStorageKey } from '../types/enums' |
|
||||||
import { getWaylineFiles } from '/@/api/wayline' |
|
||||||
const columns = [ |
|
||||||
{ |
|
||||||
title: 'FileName', |
|
||||||
dataIndex: 'name', |
|
||||||
key: 'name', |
|
||||||
slots: { customRender: 'name' } |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'TemplateType', |
|
||||||
dataIndex: 'template_type', |
|
||||||
key: 'template_type' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Favorited', |
|
||||||
dataIndex: 'favorite', |
|
||||||
key: 'favorite' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'DroneType', |
|
||||||
dataIndex: 'drone_type', |
|
||||||
key: 'drone_type' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'PayloadType', |
|
||||||
dataIndex: 'payload_type', |
|
||||||
key: 'payload_type' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'User', |
|
||||||
dataIndex: 'user', |
|
||||||
key: 'user' |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Action', |
|
||||||
key: 'action', |
|
||||||
slots: { customRender: 'action' } |
|
||||||
} |
|
||||||
] |
|
||||||
const data = ref([ |
|
||||||
{ |
|
||||||
key: '1', |
|
||||||
name: 'name1', |
|
||||||
template_type: '0', |
|
||||||
drone_type: '0-60-0', |
|
||||||
payload_type: 'PM320_DUAL', |
|
||||||
user: 'pilot', |
|
||||||
favorited: 'true' |
|
||||||
} |
|
||||||
]) |
|
||||||
onMounted(() => { |
|
||||||
onRefresh() |
|
||||||
}) |
|
||||||
const onRefresh = async () => { |
|
||||||
const wid: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) |
|
||||||
data.value = [] |
|
||||||
const index = 1 |
|
||||||
const res = await getWaylineFiles(wid, { |
|
||||||
page: 1, // 页数 |
|
||||||
page_size: 9, // 每页大小 |
|
||||||
order_by: 'update_time desc' // 排序, xxx_column_desc, xxx_column_asc, xxx_column(default asc) |
|
||||||
}) |
|
||||||
console.log(res) |
|
||||||
res.data.list.forEach(ele => { |
|
||||||
data.value.push({ |
|
||||||
key: index.toString(), |
|
||||||
name: ele.name, |
|
||||||
template_type: ele.template_types[0], |
|
||||||
drone_type: ele.drone_model_key, |
|
||||||
payload_type: ele.payload_model_keys[0], |
|
||||||
user: ele.user_name, |
|
||||||
favorite: ele.favorited.toString() |
|
||||||
}) |
|
||||||
}) |
|
||||||
console.log('wayline files:', data.value) |
|
||||||
} |
|
||||||
</script> |
|
||||||
|
|
||||||
<style lang="scss" scoped> |
|
||||||
.panel-wrapper { |
|
||||||
width: 100%; |
|
||||||
.table { |
|
||||||
background: #fff; |
|
||||||
margin-top: 32px; |
|
||||||
} |
|
||||||
.header { |
|
||||||
width: 100%; |
|
||||||
height: 60px; |
|
||||||
background: #fff; |
|
||||||
padding: 16px 24px; |
|
||||||
font-size: 20px; |
|
||||||
text-align: start; |
|
||||||
color: #000; |
|
||||||
} |
|
||||||
.action-area { |
|
||||||
color: $primary; |
|
||||||
cursor: pointer; |
|
||||||
} |
|
||||||
} |
|
||||||
</style> |
|
@ -0,0 +1,78 @@ |
|||||||
|
import { commonColor } from '/@/utils/color' |
||||||
|
|
||||||
|
// 任务类型
|
||||||
|
export enum TaskType { |
||||||
|
Immediate = 0, // 立即执行
|
||||||
|
Single = 1, // 单次定时任务
|
||||||
|
} |
||||||
|
|
||||||
|
export const TaskTypeMap = { |
||||||
|
[TaskType.Immediate]: 'Immediate', |
||||||
|
[TaskType.Single]: 'Timed & One-Time', |
||||||
|
} |
||||||
|
|
||||||
|
// 任务状态
|
||||||
|
export enum TaskStatus { |
||||||
|
Wait = 1, // 待执行
|
||||||
|
Carrying = 2, // 执行中
|
||||||
|
Success = 3, // 完成
|
||||||
|
CanCel = 4, // 取消
|
||||||
|
Fail = 5, // 失败
|
||||||
|
} |
||||||
|
|
||||||
|
export const TaskStatusMap = { |
||||||
|
[TaskStatus.Wait]: 'To be performed', |
||||||
|
[TaskStatus.Carrying]: 'In progress', |
||||||
|
[TaskStatus.Success]: 'Task completed', |
||||||
|
[TaskStatus.CanCel]: 'Task canceled', |
||||||
|
[TaskStatus.Fail]: 'Task failed', |
||||||
|
} |
||||||
|
|
||||||
|
export const TaskStatusColor = { |
||||||
|
[TaskStatus.Wait]: commonColor.BLUE, |
||||||
|
[TaskStatus.Carrying]: commonColor.BLUE, |
||||||
|
[TaskStatus.Success]: commonColor.NORMAL, |
||||||
|
[TaskStatus.CanCel]: commonColor.FAIL, |
||||||
|
[TaskStatus.Fail]: commonColor.FAIL, |
||||||
|
} |
||||||
|
|
||||||
|
// 任务执行 ws 消息状态
|
||||||
|
export enum TaskProgressStatus { |
||||||
|
Sent = 'sent', // 已下发
|
||||||
|
inProgress = 'in_progress', // 执行中
|
||||||
|
Paused = 'paused', // 暂停
|
||||||
|
Rejected = 'rejected', // 拒绝
|
||||||
|
Canceled = 'canceled', // 取消或终止
|
||||||
|
Timeout = 'timeout', // 超时
|
||||||
|
Failed = 'failed', // 失败
|
||||||
|
OK = 'ok', // 上传成功
|
||||||
|
} |
||||||
|
|
||||||
|
// 任务进度消息
|
||||||
|
export interface TaskProgressInfo { |
||||||
|
bid: string, |
||||||
|
output:{ |
||||||
|
ext: { |
||||||
|
current_waypoint_index: number, |
||||||
|
media_count: number // 媒体文件
|
||||||
|
}, |
||||||
|
progress:{ |
||||||
|
current_step: number, |
||||||
|
percent: number |
||||||
|
}, |
||||||
|
status: TaskProgressStatus |
||||||
|
}, |
||||||
|
result: number, |
||||||
|
} |
||||||
|
|
||||||
|
// ws status => log status
|
||||||
|
export const TaskProgressWsStatusMap = { |
||||||
|
[TaskProgressStatus.Sent]: TaskStatus.Carrying, |
||||||
|
[TaskProgressStatus.inProgress]: TaskStatus.Carrying, |
||||||
|
[TaskProgressStatus.Rejected]: TaskStatus.Fail, |
||||||
|
[TaskProgressStatus.OK]: TaskStatus.Success, |
||||||
|
[TaskProgressStatus.Failed]: TaskStatus.Fail, |
||||||
|
[TaskProgressStatus.Canceled]: TaskStatus.CanCel, |
||||||
|
[TaskProgressStatus.Timeout]: TaskStatus.Fail, |
||||||
|
[TaskProgressStatus.Paused]: TaskStatus.Wait, |
||||||
|
} |
@ -0,0 +1,310 @@ |
|||||||
|
export interface ErrorCode { |
||||||
|
code: number; |
||||||
|
msg: string; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据错误码翻译错误信息 |
||||||
|
* @param code |
||||||
|
* @param errorMsg |
||||||
|
* @returns |
||||||
|
*/ |
||||||
|
export function getErrorMessage (code: number, errorMsg?: string): string { |
||||||
|
const errorInfo = ERROR_CODE.find((item: ErrorCode) => item.code === code) |
||||||
|
return errorInfo ? errorInfo.msg : errorMsg || 'Server error' |
||||||
|
} |
||||||
|
|
||||||
|
// 暂时只添加航线错误
|
||||||
|
export const ERROR_CODE = [ |
||||||
|
{ |
||||||
|
code: 314001, |
||||||
|
msg: 'The issued route task url is empty', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314002, |
||||||
|
msg: 'The issued route task md5 is empty', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314003, |
||||||
|
msg: 'MissionID is invalid', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314004, |
||||||
|
msg: 'Failed to send flight route task from cloud', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314005, |
||||||
|
msg: 'Route md5 check failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314006, |
||||||
|
msg: 'Timeout waiting for aircraft to upload route (waiting for gs_state)', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314007, |
||||||
|
msg: 'Failed to upload route to aircraft', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314008, |
||||||
|
msg: 'Timeout waiting for the aircraft to enter the route executable state', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314009, |
||||||
|
msg: 'Failed to open route mission', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 314010, |
||||||
|
msg: 'Route execution failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316001, |
||||||
|
msg: 'Failed to set alternate point', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316002, |
||||||
|
msg: 'Alternate safety transfer altitude equipment failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316003, |
||||||
|
msg: 'Failed to set takeoff altitude. Remarks: The default safe takeoff height of the aircraft set by the current DJI Dock is: 1.8', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316004, |
||||||
|
msg: 'Failed to set runaway behavior', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316005, |
||||||
|
msg: 'Aircraft RTK convergence failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316013, |
||||||
|
msg: 'DJI Dock Moved', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316015, |
||||||
|
msg: 'The aircraft RTK convergence position is too far from the DJI Dock', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316007, |
||||||
|
msg: 'Set parameter timeout while waiting for aircraft to be ready', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316008, |
||||||
|
msg: 'Failed to gain control of aircraft', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316009, |
||||||
|
msg: 'Aircraft power is low', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316010, |
||||||
|
msg: 'After power on, the aircraft is not connected for more than 2 minutes (flight control OSD reception timeout)', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 316011, |
||||||
|
msg: 'Landing Position Offset', |
||||||
|
}, |
||||||
|
|
||||||
|
{ |
||||||
|
code: 317001, |
||||||
|
msg: 'Failed to get the number of media files', |
||||||
|
}, |
||||||
|
|
||||||
|
{ |
||||||
|
code: 319001, |
||||||
|
msg: 'The task center is not currently idle', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 319002, |
||||||
|
msg: 'dronenest communication timeout', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 319999, |
||||||
|
msg: 'Unknown error, e.g. restart after crash', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321000, |
||||||
|
msg: 'Route execution failed, unknown error', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321257, |
||||||
|
msg: 'The route has already started and cannot be started again', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321258, |
||||||
|
msg: 'The route cannot be interrupted in this state', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321259, |
||||||
|
msg: 'The route has not started and cannot end the route', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321513, |
||||||
|
msg: 'Reach the height limit', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321514, |
||||||
|
msg: 'Reach the limit', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321515, |
||||||
|
msg: 'Crossing the restricted flight zone', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321516, |
||||||
|
msg: 'Low limit', |
||||||
|
}, |
||||||
|
|
||||||
|
{ |
||||||
|
code: 321517, |
||||||
|
msg: 'Obstacle Avoidance', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321769, |
||||||
|
msg: 'Weak GPS signal', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321770, |
||||||
|
msg: 'The current gear state cannot be executed, B control seizes the control, and the gear is switched', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321771, |
||||||
|
msg: 'The home point is not refreshed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321772, |
||||||
|
msg: 'The current battery is too low to start the task', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321773, |
||||||
|
msg: 'Low battery return', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321776, |
||||||
|
msg: 'RTK not ready', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 321778, |
||||||
|
msg: 'The aircraft is idling on the ground and is not allowed to start the route, thinking that the user is not ready.', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 322282, |
||||||
|
msg: 'User interrupt (B control takeover)', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514100, |
||||||
|
msg: 'Command not supported', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514101, |
||||||
|
msg: 'Failed to close putter', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514102, |
||||||
|
msg: 'Failed to release putter', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514103, |
||||||
|
msg: 'Aircraft battery is low', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514104, |
||||||
|
msg: 'Failed to start charging', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514105, |
||||||
|
msg: 'Failed to stop charging', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514106, |
||||||
|
msg: 'Failed to restart the aircraft', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514107, |
||||||
|
msg: 'Failed to open hatch', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514108, |
||||||
|
msg: 'Failed to close hatch', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514109, |
||||||
|
msg: 'Failed to open the plane', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514110, |
||||||
|
msg: 'Failed to close the plane', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514111, |
||||||
|
msg: 'The aircraft failed to turn on the slow-rotating propeller in the cabin', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514112, |
||||||
|
msg: 'The aircraft failed to stop the slow-rotating propeller in the cabin', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514113, |
||||||
|
msg: 'Failed to establish wired connection with aircraft', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514114, |
||||||
|
msg: 'Get aircraft power status, command timed out, or return code is not 0', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514116, |
||||||
|
msg: 'The DJI Dock is busy and other control orders are being executed at the DJI Dock', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514117, |
||||||
|
msg: 'Check hatch status failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514118, |
||||||
|
msg: 'Check putter status failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514120, |
||||||
|
msg: 'DJI Dock and aircraft SDR connection failed', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514121, |
||||||
|
msg: 'Emergency stop state', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514122, |
||||||
|
msg: 'Failed to get the charging status of the aircraft (Failed to get the charging status, the flight mission can be executed, affecting charging and remote troubleshooting)', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514123, |
||||||
|
msg: 'Unable to power on due to low battery', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514124, |
||||||
|
msg: 'Failed to get battery information', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514125, |
||||||
|
msg: 'The battery is fully charged and cannot be charged', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514145, |
||||||
|
msg: 'Can not work while debugging on site', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514146, |
||||||
|
msg: 'Unable to work in remote debugging', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514147, |
||||||
|
msg: 'Unable to work in upgrade state', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514148, |
||||||
|
msg: 'Unable to execute new tasks in job state', |
||||||
|
}, |
||||||
|
{ |
||||||
|
code: 514150, |
||||||
|
msg: 'DJI Dock is automatically restarting', |
||||||
|
}, |
||||||
|
] |
Loading…
Reference in new issue