|
|
@@ -0,0 +1,258 @@
|
|
|
+<template>
|
|
|
+ <div class="taskPanel">
|
|
|
+ <a-spin :spinning="state.loading">
|
|
|
+ <a-form ref="formRef" layout="vertical" :hideRequiredMark="true" :model="state.formModel">
|
|
|
+ <!-- 任务名称 -->
|
|
|
+ <a-form-item label='任务名称' name="name" :rules="[{ required: true, message: '任务名称不能为空', whitespace: true }]">
|
|
|
+ <a-input placeholder="请输入任务名称" :maxlength="20" v-model:value="state.formModel.name" />
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 执行航线 -->
|
|
|
+ <a-form-item label="执行航线" name="file_id" :rules="[{ required: true, message: '执行航线不能为空' }]">
|
|
|
+ <a-button type="primary">
|
|
|
+ 选择航线
|
|
|
+ </a-button>
|
|
|
+ <div class="wayline-panel" style="padding-top: 5px;">
|
|
|
+ <div class="title">
|
|
|
+ <a-tooltip :title="wayline.name">
|
|
|
+ <div class="pr10" style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">
|
|
|
+ {{ wayline.name }}</div>
|
|
|
+ </a-tooltip>
|
|
|
+ <div class="ml10">
|
|
|
+ <UserOutlined />
|
|
|
+ </div>
|
|
|
+ <a-tooltip :title="wayline.user_name">
|
|
|
+ <div class="ml5 pr10"
|
|
|
+ style="width: 80px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">{{
|
|
|
+ wayline.user_name }}</div>
|
|
|
+ </a-tooltip>
|
|
|
+ </div>
|
|
|
+ <div class="ml10 mt5" style="color: hsla(0,0%,100%,0.65);">
|
|
|
+ <span>
|
|
|
+ <RocketOutlined />
|
|
|
+ </span>
|
|
|
+ <span class="ml5">{{ DEVICE_NAME[wayline.drone_model_key] }}</span>
|
|
|
+ <span class="ml10">
|
|
|
+ <CameraFilled style="border-top: 1px solid; padding-top: -3px;" />
|
|
|
+ </span>
|
|
|
+ <span class="ml5" v-for="payload in wayline.payload_model_keys" :key="payload.id">
|
|
|
+ {{ DEVICE_NAME[payload] }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="mt5 ml10" style="color: hsla(0,0%,100%,0.35);">
|
|
|
+ <span class="mr10">Update at {{ new Date(wayline.update_time).toLocaleString() }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 执行设备 -->
|
|
|
+ <a-form-item label="执行设备" name="dock_sn" :rules="[{ required: true, message: '执行设备不能为空' }]">
|
|
|
+ <a-button type="primary">
|
|
|
+ 选择设备
|
|
|
+ </a-button>
|
|
|
+ <div class="panel" style="padding-top: 5px;">
|
|
|
+ <div class="title">
|
|
|
+ <a-tooltip :title="dock.nickname">
|
|
|
+ <div class="pr10" style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">
|
|
|
+ {{ dock.nickname }}</div>
|
|
|
+ </a-tooltip>
|
|
|
+ </div>
|
|
|
+ <div class="ml10 mt5" style="color: hsla(0,0%,100%,0.65);">
|
|
|
+ <span>
|
|
|
+ <RocketOutlined />
|
|
|
+ </span>
|
|
|
+ <!-- <span class="ml5">{{ dock.children?.nickname ?? 'No drone' }}</span> -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 任务精度 -->
|
|
|
+ <a-form-item label="任务精度" name="wayline_precision_type">
|
|
|
+ <a-radio-group button-style="solid" v-model:value="state.formModel.wayline_precision_type">
|
|
|
+ <a-radio-button :value="1">
|
|
|
+ 高精度RTK
|
|
|
+ </a-radio-button>
|
|
|
+ <a-radio-button :value="0">
|
|
|
+ GNSS
|
|
|
+ </a-radio-button>
|
|
|
+ </a-radio-group>
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 任务策略 -->
|
|
|
+ <a-form-item label="任务策略" name="task_type">
|
|
|
+ <div style="white-space: nowrap;">
|
|
|
+ <a-radio-group button-style="solid" v-model:value="state.formModel.task_type">
|
|
|
+ <a-radio-button :value="0">
|
|
|
+ 立即
|
|
|
+ </a-radio-button>
|
|
|
+ <a-radio-button :value="1">
|
|
|
+ 定时
|
|
|
+ </a-radio-button>
|
|
|
+ <a-radio-button :value="2">
|
|
|
+ 循环
|
|
|
+ </a-radio-button>
|
|
|
+ </a-radio-group>
|
|
|
+ </div>
|
|
|
+ </a-form-item>
|
|
|
+ <template v-if="state.formModel.task_type === 1">
|
|
|
+ <!-- 执行时间 -->
|
|
|
+ <a-form-item label="执行时间" name="select_execute_date_time" :rules="[{ required: true, message: '执行时间不能为空' }]">
|
|
|
+ <a-date-picker style="width: 100%;" show-time valueFormat="YYYY-MM-DD HH:mm:ss" placeholder="请选择执行时间"
|
|
|
+ v-model:value="state.formModel.select_execute_date_time" />
|
|
|
+ </a-form-item>
|
|
|
+ </template>
|
|
|
+ <template v-if="state.formModel.task_type === 2">
|
|
|
+ <!-- 执行日期 -->
|
|
|
+ <a-form-item label="执行日期" name="select_execute_range_date" :rules="[{ required: true, message: '执行日期不能为空' }]">
|
|
|
+ <a-range-picker style="width: 100%;" valueFormat="YYYY-MM-DD"
|
|
|
+ :disabledDate="(current: any) => current < moment().subtract(1, 'days')" :placeholder="['开始日期', '结束日期']"
|
|
|
+ v-model:value="state.formModel.select_execute_range_date" />
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 执行时间 -->
|
|
|
+ <a-form-item label="执行时间" name="select_execute_range_time">
|
|
|
+ <a-range-picker style="width: 100%;" :show-time="{ format: 'HH:mm' }" format="HH:mm" valueFormat="HH:mm"
|
|
|
+ :placeholder="['开始时间', '结束时间']" v-model:value="state.formModel.select_execute_range_time" />
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 任务开始执行的电量 -->
|
|
|
+ <a-form-item label="任务开始执行的电量" name="min_battery_capacity">
|
|
|
+ <a-input-number :min="50" :max="100" :formatter="(value: number) => `${value}%`"
|
|
|
+ :parser="(value: string) => value.replace('%', '')" v-model:value="state.formModel.min_battery_capacity">
|
|
|
+ </a-input-number>
|
|
|
+ </a-form-item>
|
|
|
+ </template>
|
|
|
+ <!-- 返航高度 -->
|
|
|
+ <a-form-item label="返航高度(相对机场返航高度)" name="rth_altitude">
|
|
|
+ <a-input-number style="width: 100%;" :min="20" :max="1500" v-model:value="state.formModel.rth_altitude" />
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 自动断点续飞 -->
|
|
|
+ <a-form-item label="自动断点续飞" name="breakpoint_continuation">
|
|
|
+ <a-switch checked-children="开" un-checked-children="关"
|
|
|
+ v-model:checked="state.formModel.breakpoint_continuation" />
|
|
|
+ </a-form-item>
|
|
|
+ <!-- 自动断点续飞 -->
|
|
|
+ <a-form-item>
|
|
|
+ <div class="taskPanel-footer">
|
|
|
+ <a-button style="background: #3c3c3c;margin-right: 10px;" @click="onClickCancel">
|
|
|
+ 取消
|
|
|
+ </a-button>
|
|
|
+ <a-button type="primary" @click="handleClickConfirm">
|
|
|
+ 确定
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ </a-spin>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, computed, reactive } from 'vue'
|
|
|
+import { RocketOutlined, CameraFilled, UserOutlined } from '@ant-design/icons-vue'
|
|
|
+import { useMyStore } from '/@/store'
|
|
|
+import { WaylineFile } from '/@/types/wayline'
|
|
|
+import { Device, DEVICE_NAME } from '/@/types/device'
|
|
|
+import moment from 'moment'
|
|
|
+import { createPlan } from '/@/api/wayline'
|
|
|
+
|
|
|
+interface Props {
|
|
|
+ onClickConfirm: (data: any) => Promise<any>,
|
|
|
+ onClickCancel: () => void,
|
|
|
+};
|
|
|
+
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
+
|
|
|
+});
|
|
|
+
|
|
|
+const formRef = ref();
|
|
|
+
|
|
|
+const store = useMyStore()
|
|
|
+
|
|
|
+const dock = computed<Device>(() => {
|
|
|
+ return store.state.dockInfo
|
|
|
+})
|
|
|
+
|
|
|
+const wayline = computed<WaylineFile>(() => {
|
|
|
+ return store.state.waylineInfo
|
|
|
+})
|
|
|
+
|
|
|
+interface State {
|
|
|
+ loading: boolean,
|
|
|
+ formModel: {
|
|
|
+ name: string;
|
|
|
+ file_id: string;
|
|
|
+ dock_sn: string;
|
|
|
+ wayline_precision_type: number;
|
|
|
+ task_type: number;
|
|
|
+ select_execute_date_time?: string;
|
|
|
+ select_execute_range_date?: any[],
|
|
|
+ select_execute_range_time?: any[],
|
|
|
+ min_battery_capacity: number,
|
|
|
+ rth_altitude: number,
|
|
|
+ breakpoint_continuation: boolean;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const state: State = reactive({
|
|
|
+ loading: false,
|
|
|
+ formModel: {
|
|
|
+ name: '',// 任务名称
|
|
|
+ file_id: '',// 执行航线
|
|
|
+ dock_sn: '',// 执行设备
|
|
|
+ wayline_precision_type: 1,// 任务精度
|
|
|
+ task_type: 0,// 任务策略
|
|
|
+ select_execute_date_time: undefined,// 定时-执行时间
|
|
|
+ select_execute_range_date: undefined,// 循环-执行日期
|
|
|
+ select_execute_range_time: undefined,// 循环-执行时间
|
|
|
+ min_battery_capacity: 90,// 循环-任务开始执行的电量
|
|
|
+ rth_altitude: 20,// 返航高度
|
|
|
+ breakpoint_continuation: true,// 自动断点续飞
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 点击确定
|
|
|
+const handleClickConfirm = async () => {
|
|
|
+ formRef.value?.validateFields().then(async (values: any) => {
|
|
|
+ const data = { ...values };
|
|
|
+ // await createPlan()
|
|
|
+ console.log(data, 'data');
|
|
|
+ }).catch((error: any) => {
|
|
|
+ console.error(error);
|
|
|
+ });
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.taskPanel {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ color: #FFFFFF;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ &-footer {
|
|
|
+ display: flex;
|
|
|
+ padding: 10px 0;
|
|
|
+
|
|
|
+ button {
|
|
|
+ width: 45%;
|
|
|
+ color: #fff;
|
|
|
+ border: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ form {
|
|
|
+ margin: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ form,
|
|
|
+ label,
|
|
|
+ input,
|
|
|
+ .ant-input,
|
|
|
+ .ant-calendar-range-picker-separator,
|
|
|
+ .ant-input:hover,
|
|
|
+ .ant-time-picker .anticon,
|
|
|
+ .ant-calendar-picker .anticon {
|
|
|
+ background-color: #232323;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+::-webkit-scrollbar {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+</style>
|