Merge branch 'main' of http://123.132.248.154:10000/gitY/DiKongGanZhiPingTai
|
After Width: | Height: | Size: 307 B |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 859 B |
|
After Width: | Height: | Size: 347 B |
|
After Width: | Height: | Size: 410 B |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 802 B |
|
After Width: | Height: | Size: 968 B |
|
|
@ -0,0 +1,486 @@
|
||||||
|
<template>
|
||||||
|
<div class="title-div">
|
||||||
|
<div class="title-span-div">
|
||||||
|
<div class="title-icon"></div>
|
||||||
|
<div class="title-span">创建算法</div>
|
||||||
|
</div>
|
||||||
|
<div class="close-button" @click="emits('changeAddModal',false)"></div>
|
||||||
|
</div>
|
||||||
|
<div class="interval"></div>
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="left-content">
|
||||||
|
<div class="item-title">模型名称</div>
|
||||||
|
<a-input class="name-input" v-model:value="modelName" placeholder="请输入相关名称" />
|
||||||
|
<div class="item-title">模型描述</div>
|
||||||
|
<a-textarea class="item-desc" v-model:value="modelDescription" placeholder="请输入相关描述" :rows="4" />
|
||||||
|
<div class="item-title">模型封面</div>
|
||||||
|
<div class="item-image">
|
||||||
|
<div class="empty-image" @click="changeSelectImageModal(true)">
|
||||||
|
<div class="empty-image-content">
|
||||||
|
<div class="empty-image-icon"></div>
|
||||||
|
<div class="empty-image-span">请选择文件上传</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="right-content">
|
||||||
|
<div class="item-title">模型类型</div>
|
||||||
|
<a-segmented class="item-type" v-model:value="modelType" :options="modelTypeOptions"></a-segmented>
|
||||||
|
<template v-if="modelType == '0'">
|
||||||
|
<div class="item-title">模型规模</div>
|
||||||
|
<a-segmented class="item-type" v-model:value="modelScale" :options="modelScaleOptions"></a-segmented>
|
||||||
|
<div class="item-title">模型文件</div>
|
||||||
|
<a-upload
|
||||||
|
v-model:file-list="modelFile"
|
||||||
|
accept=".zip"
|
||||||
|
:maxCount="1"
|
||||||
|
:custom-request="customRequest"
|
||||||
|
>
|
||||||
|
<a-button class="select-model-file-button" type="primary" :icon="h(PlusOutlined)">选择模型文件</a-button>
|
||||||
|
<!-- <template #itemRender="{ file, actions }">
|
||||||
|
<a-space>
|
||||||
|
<span>{{ file.name }}</span>
|
||||||
|
</a-space>
|
||||||
|
</template> -->
|
||||||
|
</a-upload>
|
||||||
|
<div class="upload-hint">(*请上传模型压缩文件,支持pt格式)</div>
|
||||||
|
<div class="item-title">模型标签</div>
|
||||||
|
<div class="item-label-div">
|
||||||
|
<div class="label-title-div">
|
||||||
|
<div class="label-title-span">请根据模型实际情况填写信息</div>
|
||||||
|
<div class="add-button" @click="addLabelRow">
|
||||||
|
<div class="button-icon"></div>
|
||||||
|
<div class="button-span">添加行</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="label-interval"></div>
|
||||||
|
<div class="label-table-title">
|
||||||
|
<div class="table-title-item" style="padding-left: 6px;">枚举值</div>
|
||||||
|
<div class="table-title-item">名称</div>
|
||||||
|
<div class="table-title-item">推荐置信度</div>
|
||||||
|
<div class="table-title-item" style="width: 55px;justify-content: center;">操作</div>
|
||||||
|
</div>
|
||||||
|
<div class="label-table-content">
|
||||||
|
<div class="table-row" v-for="(item,index) in modelLabelList" :key="index">
|
||||||
|
<div class="table-item">
|
||||||
|
<a-input class="table-item-input" v-model:value="item.test"/>
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<a-input class="table-item-input" />
|
||||||
|
</div>
|
||||||
|
<div class="table-item">
|
||||||
|
<a-input class="table-item-input" />
|
||||||
|
</div>
|
||||||
|
<div class="table-item" style="width: 55px; justify-content: center">
|
||||||
|
<div class="del-table-row" @click="delLabelRow(index)"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="item-title">推流地址</div>
|
||||||
|
<a-input class="name-input" v-model:value="modelPushAddress" placeholder="请输入地址" />
|
||||||
|
<div class="item-title">拉流地址</div>
|
||||||
|
<a-input class="name-input" v-model:value="modelPullAddress" placeholder="请输入地址" />
|
||||||
|
<div class="item-title">服务地址</div>
|
||||||
|
<a-input class="name-input" v-model:value="modelServeAddress" placeholder="请输入地址" />
|
||||||
|
<div class="item-title">密钥</div>
|
||||||
|
<a-textarea class="item-key" v-model:value="modelKey" placeholder="请输入密钥" :rows="4" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="interval"></div>
|
||||||
|
<div class="footer">
|
||||||
|
<a-button class="cancel-button" @click="emits('changeAddModal',false)">取消</a-button>
|
||||||
|
<a-button class="save-button" type="primary">确定</a-button>
|
||||||
|
</div>
|
||||||
|
<a-modal v-model:open="selectImageModal" title="选择封面" width="1000px" :footer="null" :destroyOnClose="true">
|
||||||
|
<SelectImageModal @changeSelectImageModal="changeSelectImageModal"/>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, h, defineEmits, defineProps } from "vue"
|
||||||
|
import { uploadFile } from '@/api/formrender/index';
|
||||||
|
import { PlusOutlined, } from '@ant-design/icons-vue';
|
||||||
|
import SelectImageModal from "./SelectImageModal.vue";
|
||||||
|
const props = defineProps([''])
|
||||||
|
const emits = defineEmits(['changeAddModal'])
|
||||||
|
const modelName = ref('')
|
||||||
|
const modelDescription = ref('')
|
||||||
|
const modelType = ref('0')
|
||||||
|
const modelScale = ref('N')
|
||||||
|
const modelPullAddress = ref('')
|
||||||
|
const modelPushAddress = ref('')
|
||||||
|
const modelServeAddress = ref('')
|
||||||
|
const modelKey = ref('')
|
||||||
|
const modelFile = ref([])
|
||||||
|
const modelFilePath = ref()
|
||||||
|
const modelLabelList = ref([])
|
||||||
|
const selectImageModal = ref(false)
|
||||||
|
const modelTypeOptions = ref([
|
||||||
|
{ label: '本地模型', value: '0' },
|
||||||
|
{ label: '远程模型', value: '1' }
|
||||||
|
])
|
||||||
|
const modelScaleOptions = ref([
|
||||||
|
{ label: 'N', value: 'N' },
|
||||||
|
{ label: 'S', value: 'S' },
|
||||||
|
{ label: 'M', value: 'M' },
|
||||||
|
{ label: 'L', value: 'L' },
|
||||||
|
{ label: 'XI', value: 'XI' },
|
||||||
|
])
|
||||||
|
const customRequest = (file) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('files', file.file)
|
||||||
|
uploadFile(formData).then(res => {
|
||||||
|
modelFilePath.value = res[0].filePath
|
||||||
|
// emits('update:shppath',res[0].filePath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const addLabelRow = () => {
|
||||||
|
// TODO
|
||||||
|
modelLabelList.value.push({
|
||||||
|
test:''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const delLabelRow = (index) => {
|
||||||
|
modelLabelList.value.splice(index,1)
|
||||||
|
}
|
||||||
|
const changeSelectImageModal = (type: boolean) => {
|
||||||
|
selectImageModal.value = type
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.title-div{
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-left: 26px;
|
||||||
|
padding-right: 35px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.title-span-div{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.title-icon{
|
||||||
|
width: 3px;
|
||||||
|
height: 18px;
|
||||||
|
background: #0B60BD;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
margin-right: 9px;
|
||||||
|
}
|
||||||
|
.title-span{
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #11131B;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.close-button{
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background-image: url('/public/ailist/add_algorithm_close_button.png');
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.interval{
|
||||||
|
width: 631px;
|
||||||
|
height: 1px;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border: 1px solid #DBDBDB;
|
||||||
|
opacity: 0.66;
|
||||||
|
}
|
||||||
|
.modal-content{
|
||||||
|
display: flex;
|
||||||
|
padding-top: 14px;
|
||||||
|
padding-left: 27px;
|
||||||
|
padding-right: 35px;
|
||||||
|
padding-bottom: 28px;
|
||||||
|
.item-title{
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #222738;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
margin-bottom: 9px;
|
||||||
|
}
|
||||||
|
.name-input{
|
||||||
|
height: 40px;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.left-content{
|
||||||
|
width: 253px;
|
||||||
|
margin-right: 46px;
|
||||||
|
.item-desc{
|
||||||
|
height: 151px;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.item-image{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 155px;
|
||||||
|
background: #F5F5F5;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border: 2px dashed rgba(28,29,34,0.08);
|
||||||
|
.empty-image{
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 209px;
|
||||||
|
height: 119px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15), 0px 8px 6px 0px rgba(28,29,34,0.06);
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
.empty-image-content{
|
||||||
|
width: 98px;
|
||||||
|
height: 63px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
.empty-image-icon{
|
||||||
|
width: 26px;
|
||||||
|
height: 28px;
|
||||||
|
background-image: url('/public/ailist/algorithm_upload_icon.png');
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
.empty-image-span{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #222738;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right-content{
|
||||||
|
width: 269px;
|
||||||
|
.item-type{
|
||||||
|
width: 262px;
|
||||||
|
height: 40px;
|
||||||
|
background: rgba(28,29,34,0.04);
|
||||||
|
border-radius: 20px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
:deep(.ant-segmented-group){
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
:deep(.ant-segmented-item){
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 18px;
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
color: rgba(28,29,34,0.5);
|
||||||
|
line-height: 20px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
:deep(.ant-segmented-item-selected){
|
||||||
|
font-weight: 500;
|
||||||
|
color: #1C1D22;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.select-model-file-button{
|
||||||
|
width: 151px;
|
||||||
|
height: 40px;
|
||||||
|
background: #0D68CB;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
.upload-hint{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 28px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
.item-label-div{
|
||||||
|
width: 100%;
|
||||||
|
height: 155px;
|
||||||
|
background: #F5F5F5;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
padding-top: 3px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 10px;
|
||||||
|
.label-title-div{
|
||||||
|
width: 100%;
|
||||||
|
height: 34px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
.label-title-span{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #222738;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
.add-button{
|
||||||
|
width: 66px;
|
||||||
|
height: 26px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15), 0px 8px 6px 0px rgba(28,29,34,0.06);
|
||||||
|
border: 1px solid rgba(28,29,34,0.06);
|
||||||
|
border-radius: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
.button-icon{
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-image: url('/public/ailist/algorithm_add_row_icon.png');
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
.button-span{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #0D68CB;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.label-interval{
|
||||||
|
height: 1px;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
background:#DBDBDB;
|
||||||
|
opacity: 0.66;
|
||||||
|
margin-left: -8px;
|
||||||
|
margin-right: -10px;
|
||||||
|
}
|
||||||
|
.label-table-title{
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
.table-title-item{
|
||||||
|
display: flex;
|
||||||
|
width: 66px;
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #222738;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.label-table-content{
|
||||||
|
height: 75px;
|
||||||
|
overflow: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-row{
|
||||||
|
width: 100%;
|
||||||
|
height: 26px;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
.table-item{
|
||||||
|
width: 65px;
|
||||||
|
height: 26px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15), 0px 8px 6px 0px rgba(28,29,34,0.06);
|
||||||
|
border-radius: 2px 0px 0px 2px;
|
||||||
|
margin-right: 1px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
// padding-left: 9px;
|
||||||
|
.table-item-input{
|
||||||
|
height: 26px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
.table-item-input:focus{
|
||||||
|
box-shadow: none
|
||||||
|
}
|
||||||
|
.del-table-row{
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
background-image: url('/public/ailist/del_table_row.png');
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item-key{
|
||||||
|
height: 88px;
|
||||||
|
// box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.footer{
|
||||||
|
height: 85px;
|
||||||
|
padding-right: 34px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: end;
|
||||||
|
.cancel-button{
|
||||||
|
width: 101px;
|
||||||
|
height: 40px;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #979797;
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #222738;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
margin-right: 14px;
|
||||||
|
}
|
||||||
|
.save-button{
|
||||||
|
width: 146px;
|
||||||
|
height: 40px;
|
||||||
|
background: #0D68CB;
|
||||||
|
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 33px;
|
||||||
|
text-shadow: 0px 10px 30px rgba(0,0,6,0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
<template>
|
||||||
|
<div class="cropper-tool">
|
||||||
|
<div class="container">
|
||||||
|
<div class="left">
|
||||||
|
<div style="padding-left: 20px;">
|
||||||
|
<a-upload :fileList="[]" accept="image/*" :beforeUpload="onFileChange">
|
||||||
|
<a-button size="small" type="primary">选择图片</a-button>
|
||||||
|
</a-upload>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:8px">
|
||||||
|
<img style="width: 640px;height: 266px;" ref="sourceImg" crossorigin="anonymous" />
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<button @click="zoomIn">放大</button>
|
||||||
|
<button @click="zoomOut">缩小</button>
|
||||||
|
<button @click="rotateLeft">左旋</button>
|
||||||
|
<button @click="rotateRight">右旋</button>
|
||||||
|
<button @click="flipHorizontal">水平翻转</button>
|
||||||
|
<button @click="flipVertical">垂直翻转</button>
|
||||||
|
<button @click="reset">重置</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<div style="margin-bottom:10px">裁切预览(固定 300×200)</div>
|
||||||
|
<div class="preview" ref="previewBox" style="width:300px;height:200px;">
|
||||||
|
<span v-if="!croppedUrl">(无)</span>
|
||||||
|
<img v-if="croppedUrl" :src="croppedUrl" alt="预览" />
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:8px; display:flex; gap:8px;">
|
||||||
|
<a v-if="croppedUrl" :href="croppedUrl" download="cropped.png">下载裁切图</a>
|
||||||
|
<button @click="clear">清空</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<a-button style="margin-right: 15px;" @click="emits('changeSelectImageModal',false)">取消</a-button>
|
||||||
|
<a-button type="primary" @click="submitImage">确定</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, defineEmits } from 'vue';
|
||||||
|
import Cropper from 'cropperjs';
|
||||||
|
import 'cropperjs/dist/cropper.css';
|
||||||
|
import { dataURLtoBlob } from '@/utils/file/base64Conver';
|
||||||
|
import { uploadFile } from '@/api/formrender/index';
|
||||||
|
const emits = defineEmits(['changeSelectImageModal'])
|
||||||
|
const sourceImg = ref(null);
|
||||||
|
const cropper = ref(null);
|
||||||
|
const flipH = ref(1);
|
||||||
|
const flipV = ref(1);
|
||||||
|
const zoomValue = ref(1);
|
||||||
|
const croppedUrl = ref('');
|
||||||
|
|
||||||
|
const onFileChange = (e) => {
|
||||||
|
console.log(e)
|
||||||
|
const file = e
|
||||||
|
if (!file) return;
|
||||||
|
const url = URL.createObjectURL(file);
|
||||||
|
sourceImg.value.src = url;
|
||||||
|
sourceImg.value.onload = () => {
|
||||||
|
if (cropper.value) {
|
||||||
|
cropper.value.destroy();
|
||||||
|
}
|
||||||
|
cropper.value = new Cropper(sourceImg.value, {
|
||||||
|
viewMode: 1,
|
||||||
|
aspectRatio: 3 / 2, // 固定比例 300:200
|
||||||
|
autoCropArea: 1,
|
||||||
|
movable: true,
|
||||||
|
zoomable: true,
|
||||||
|
rotatable: true,
|
||||||
|
scalable: true,
|
||||||
|
responsive: true,
|
||||||
|
background: true,
|
||||||
|
cropBoxResizable: false,
|
||||||
|
cropBoxMovable: false,
|
||||||
|
dragMode: 'move',
|
||||||
|
ready() {
|
||||||
|
zoomValue.value = 1;
|
||||||
|
flipH.value = 1;
|
||||||
|
flipV.value = 1;
|
||||||
|
croppedUrl.value = '';
|
||||||
|
getCropped()
|
||||||
|
},
|
||||||
|
crop() {
|
||||||
|
getCropped()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const zoomIn = () => cropper.value?.zoom(0.1);
|
||||||
|
const zoomOut = () => cropper.value?.zoom(-0.1);
|
||||||
|
const rotateLeft = () => cropper.value?.rotate(-90);
|
||||||
|
const rotateRight = () => cropper.value?.rotate(90);
|
||||||
|
const flipHorizontal = () => {
|
||||||
|
flipH.value = -flipH.value;
|
||||||
|
cropper.value?.scaleX(flipH.value);
|
||||||
|
};
|
||||||
|
const flipVertical = () => {
|
||||||
|
flipV.value = -flipV.value;
|
||||||
|
cropper.value?.scaleY(flipV.value);
|
||||||
|
};
|
||||||
|
const reset = () => {
|
||||||
|
cropper.value?.reset();
|
||||||
|
zoomValue.value = 1;
|
||||||
|
flipH.value = 1;
|
||||||
|
flipV.value = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCropped = () => {
|
||||||
|
const canvas = cropper.value.getCroppedCanvas({ width: 300, height: 200 });
|
||||||
|
if (!canvas) return;
|
||||||
|
croppedUrl.value = canvas.toDataURL('image/png');
|
||||||
|
console.log('croppedUrl.value',croppedUrl.value)
|
||||||
|
};
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
if (cropper.value) {
|
||||||
|
cropper.value.destroy();
|
||||||
|
cropper.value = null;
|
||||||
|
}
|
||||||
|
sourceImg.value.src = '';
|
||||||
|
croppedUrl.value = '';
|
||||||
|
};
|
||||||
|
const submitImage = (format='image/jpeg', quality = 0.9) => {
|
||||||
|
// const blob = dataURLtoBlob(croppedUrl.value);
|
||||||
|
// const formData = new FormData();
|
||||||
|
// formData.append('files', blob);
|
||||||
|
// uploadFile(formData).then(res => {
|
||||||
|
// console.log(res)
|
||||||
|
// })
|
||||||
|
if (!cropper.value) return;
|
||||||
|
cropper.value.getCroppedCanvas({ width: 300, height: 200 })
|
||||||
|
.toBlob(async (blob) => {
|
||||||
|
if (!blob) return;
|
||||||
|
|
||||||
|
// 用 FormData 上传
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('files', blob, `cropped.jpeg`);
|
||||||
|
|
||||||
|
uploadFile(formData).then(res => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
}, format, quality);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container { display: flex; gap: 20px; }
|
||||||
|
.left { width: 640px; }
|
||||||
|
.right { width: 320px; }
|
||||||
|
img { max-width: 100%; display: block; max-height: 480px; background: #f3f3f3; }
|
||||||
|
.controls { margin-top: 10px; display:flex; flex-wrap:wrap; gap:8px; }
|
||||||
|
.preview { border:1px solid #ddd; display:flex; align-items:center; justify-content:center; overflow:hidden; background:#fafafa }
|
||||||
|
.footer{
|
||||||
|
margin-top: 12px;
|
||||||
|
height: 53px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: end;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,136 +1,403 @@
|
||||||
<template>
|
<template>
|
||||||
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
||||||
<div class="w-1/4 xl:w-1/5 leftbox flex column">
|
<div class="w-1/4 xl:w-1/5 leftbox">
|
||||||
<div class="flex ai-c jc-sb">
|
<div class="left-title-div">
|
||||||
<div class="textbox">
|
<div class="span-div">
|
||||||
<p>算法库</p>
|
<div class="span-title">算法库</div>
|
||||||
<span>行业生态算法厂商</span>
|
<div class="span-subtitle">行业生态算法厂商</div>
|
||||||
</div>
|
</div>
|
||||||
<a-button type="primary" size="small" @click="createAddClick">
|
<a-button class="add-algorithm" type="primary" :icon="h(PlusOutlined)" @click="changeAddModal(true)">创建</a-button>
|
||||||
<template #icon><PlusOutlined /></template>
|
|
||||||
创建
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex ai-c jc-c column flex-1">
|
<div class="left-interval"></div>
|
||||||
<div class="descbox">
|
<div class="show-algorithm-list-div">
|
||||||
<p>请先创建自定义算法,基于算法新增实例<br />了解更多:<BookOutlined :style="{fontSize: '14px', color: '#0A99EB'}" /> 说明书</p>
|
<div class="empty-list">
|
||||||
|
<div class="empty-image"></div>
|
||||||
|
<div class="empty-span-title">暂无数据</div>
|
||||||
|
<div class="empty-span-subtitle">请先创建自定义算法,基于算法新增实例</div>
|
||||||
|
<div style="display: flex;align-items: center;margin-bottom: 28px;">
|
||||||
|
<div class="empty-span-subtitle" style="display: inline;">了解更多:</div>
|
||||||
|
<div class="empty-icon-image"></div>
|
||||||
|
<div class="empty-span-subtitle" style="display: inline;">说明书 </div>
|
||||||
|
</div>
|
||||||
|
<a-button class="empty-add-algorithm" type="primary" :icon="h(PlusOutlined)" @click="changeAddModal(true)">创建自定义算法</a-button>
|
||||||
</div>
|
</div>
|
||||||
<a-button type="primary" @click="createAddClick">
|
|
||||||
<template #icon><PlusOutlined /></template>
|
|
||||||
创建自定义算法
|
|
||||||
</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BasicTable
|
<div class="w-3/4 xl:w-4/5 right-out-div">
|
||||||
class="w-3/4 xl:w-4/5"
|
<div class="search-div">
|
||||||
@register="registerTable"
|
<div class="search-span-icon"></div>
|
||||||
@fetch-success="onFetchSuccess"
|
<div class="search-span">算法库</div>
|
||||||
:searchInfo="searchInfo"
|
<div class="search-input-div">
|
||||||
>
|
<a-input-search
|
||||||
|
class="search-input"
|
||||||
</BasicTable>
|
v-model:value="searchValue"
|
||||||
<Modal
|
placeholder="按照实例搜索"
|
||||||
@submitsuccess="submitsuccess"
|
enter-button="搜索"
|
||||||
@register="registerModal"
|
@search="onSearch"
|
||||||
@submit-reload="submitReload"
|
>
|
||||||
/>
|
<template #prefix>
|
||||||
|
<div class="search-input-icon"></div>
|
||||||
|
</template>
|
||||||
|
</a-input-search>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-interval">
|
||||||
|
<div class="interval-icon"></div>
|
||||||
|
</div>
|
||||||
|
<div class="show-list-div">
|
||||||
|
<div class="list-div">
|
||||||
|
<div class="item" v-for="value in 8">
|
||||||
|
<div class="image-div">
|
||||||
|
<img class="image-item" src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png">
|
||||||
|
<div class="image-span">
|
||||||
|
<div class="image-span-icon"></div>
|
||||||
|
<div class="image-span-info">#排水沟盖板缺</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="info-div">
|
||||||
|
<div class="info-icon"></div>
|
||||||
|
<div class="info-span-div">
|
||||||
|
<div class="info-span-title">高速排水沟盖板缺失检测算法</div>
|
||||||
|
<div class="info-span-subtitle">识别高速公路两侧的排水沟盖板缺……</div>
|
||||||
|
</div>
|
||||||
|
<a-button class="show-info-button" type="primary">查看</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pagination-div">
|
||||||
|
<a-pagination
|
||||||
|
size="small"
|
||||||
|
:total="50"
|
||||||
|
show-size-changer
|
||||||
|
show-quick-jumper
|
||||||
|
:show-total="total => `共 ${total} 条数据`"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a-modal width="631px" v-model:open="addAlgorithmModal" :footer="null" :closable="false" :destroyOnClose="true" :maskClosable="false" :keyboard="false">
|
||||||
|
<AddAlgorithmModal @changeAddModal="changeAddModal"/>
|
||||||
|
</a-modal>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, nextTick, ref } from 'vue';
|
import { ref,h } from 'vue';
|
||||||
import { PlusOutlined, BookOutlined } from '@ant-design/icons-vue';
|
import { PlusOutlined, } from '@ant-design/icons-vue';
|
||||||
import { BasicTable, useTable } from '@/components/Table';
|
|
||||||
import { getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
|
|
||||||
import { PageWrapper } from '@/components/Page';
|
import { PageWrapper } from '@/components/Page';
|
||||||
import { columns, searchFormSchema } from './index.data';
|
import AddAlgorithmModal from './AddAlgorithmModal.vue';
|
||||||
import { useMessage } from '@/hooks/web/useMessage';
|
|
||||||
import Modal from './modal.vue';
|
|
||||||
import { useModal } from '@/components/Modal';
|
|
||||||
|
|
||||||
const { createConfirm, createMessage } = useMessage();
|
const searchValue = ref('');
|
||||||
defineOptions({ name: 'MenuManagement' });
|
const addAlgorithmModal = ref(false)
|
||||||
const searchInfo = reactive<Recordable>({});
|
const onSearch = () => {
|
||||||
|
}
|
||||||
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
|
const changeAddModal = (type: boolean) => {
|
||||||
title: '算法列表',
|
addAlgorithmModal.value = type
|
||||||
// api: getButtonList,
|
|
||||||
columns,
|
|
||||||
rowKey: 'id',
|
|
||||||
formConfig: {
|
|
||||||
labelWidth: 120,
|
|
||||||
schemas: searchFormSchema,
|
|
||||||
},
|
|
||||||
isTreeTable: true,
|
|
||||||
striped: false,
|
|
||||||
useSearchForm: true,
|
|
||||||
showTableSetting: true,
|
|
||||||
bordered: true,
|
|
||||||
showIndexColumn: false,
|
|
||||||
rowSelection: {
|
|
||||||
//多选框
|
|
||||||
// type: 'checkbox',
|
|
||||||
type: 'radio',
|
|
||||||
},
|
|
||||||
handleSearchInfoFn(info) {
|
|
||||||
return info;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const [registerModal, { openModal }] = useModal();
|
|
||||||
function createAddClick(){
|
|
||||||
openModal(true, {
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFetchSuccess() {
|
|
||||||
// 演示默认展开所有表项
|
|
||||||
nextTick(expandAll);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.flex{
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.flex-1{
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.column{
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.ai-c{
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.jc-sb{
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.jc-c{
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.leftbox{
|
.leftbox{
|
||||||
background: #fff;
|
background: #fff;
|
||||||
margin: 16px 0 16px 16px;
|
margin: 16px 0 16px 16px;
|
||||||
padding: 16px;
|
.left-title-div{
|
||||||
.textbox{
|
width: 100%;
|
||||||
p{
|
height: 82px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-right: 33px;
|
||||||
|
justify-content: space-between;
|
||||||
|
.span-div{
|
||||||
|
width: 104px;
|
||||||
|
height: 42px;
|
||||||
|
.span-title{
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #060606;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
.span-subtitle{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #393939;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.add-algorithm{
|
||||||
|
width: 80px;
|
||||||
|
height: 30px;
|
||||||
|
background: #0B60BD;
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.left-interval{
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
border: 1px solid rgba(28,29,34,0.08);
|
||||||
|
opacity: 0.46;
|
||||||
|
}
|
||||||
|
.show-algorithm-list-div{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 84px );
|
||||||
|
.empty-list{
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 280px;
|
||||||
|
height: 311px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 5px 18px 32px 0px rgba(0,0,0,0.1);
|
||||||
|
border: 2px dashed rgba(28,29,34,0.08);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding-top: 28px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
.empty-image{
|
||||||
|
width: 114px;
|
||||||
|
height: 120px;
|
||||||
|
background-image: url('/public/ailist/empty_image.png');
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.empty-span-title{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #000000;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.empty-span-subtitle{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #393939;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
.empty-icon-image{
|
||||||
|
width: 16px;
|
||||||
|
height: 14px;
|
||||||
|
background-image: url('/public/ailist/empty_icon_image.png');
|
||||||
|
line-height: 18px;
|
||||||
|
display: inline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.empty-add-algorithm{
|
||||||
|
width: 167px;
|
||||||
|
height: 30px;
|
||||||
|
background: #0D68CB;
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right-out-div{
|
||||||
|
padding: 16px 16px 16px 33px;
|
||||||
|
.search-div{
|
||||||
|
position: relative;
|
||||||
|
height: 57px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.search-span-icon{
|
||||||
|
width: 20px;
|
||||||
|
height: 18px;
|
||||||
|
background-image: url('/public/ailist/search_span_icon.png');
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.search-span{
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #060606;
|
color: #060606;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
}
|
||||||
span{
|
.search-input-div{
|
||||||
font-weight: 400;
|
position: absolute;
|
||||||
font-size: 13px;
|
top: 0px;
|
||||||
color: #393939;
|
right: 0px;
|
||||||
line-height: 18px;
|
width: 304px;
|
||||||
|
height: 38px;
|
||||||
|
.search-input{
|
||||||
|
:deep(.ant-input-affix-wrapper){
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 28px;
|
||||||
|
height: 38px;
|
||||||
|
border-top-left-radius: 19px;
|
||||||
|
border-bottom-left-radius: 19px;
|
||||||
|
}
|
||||||
|
:deep(.ant-input-search-button,){
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 28px;
|
||||||
|
height: 38px;
|
||||||
|
border-top-right-radius: 19px;
|
||||||
|
border-bottom-right-radius: 19px;
|
||||||
|
}
|
||||||
|
:deep(.ant-input){
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
.search-input-icon{
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background-image: url('/public/ailist/search_input_icon.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.descbox{
|
.search-interval{
|
||||||
font-weight: 400;
|
position: relative;
|
||||||
font-size: 13px;
|
width: 100%;
|
||||||
color: #393939;
|
height: 2px;
|
||||||
line-height: 18px;
|
background:rgba(28,29,34,0.08);
|
||||||
text-align: center;
|
margin-bottom: 22px;
|
||||||
|
.interval-icon{
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 137px;
|
||||||
|
height: 2px;
|
||||||
|
background: #0B60BD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show-list-div{
|
||||||
|
width: 100%;
|
||||||
|
height: calc( 100% - 81px );
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 2px dashed rgba(28,29,34,0.08);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 32px;
|
||||||
|
.list-div{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 90px;
|
||||||
|
.item{
|
||||||
|
width: 300px;
|
||||||
|
height: 268px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 5px 18px 32px 0px rgba(28,29,34,0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
.image-div{
|
||||||
|
position: relative;
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
.image-item{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
}
|
||||||
|
.image-span{
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 205px;
|
||||||
|
height: 20px;
|
||||||
|
background: linear-gradient( 270deg, rgba(7,7,7,0) 0%, #111111 100%);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 9px;
|
||||||
|
.image-span-icon{
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background: #FFA048;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.image-span-info{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.info-div{
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 7px;
|
||||||
|
.info-icon{
|
||||||
|
width: 3px;
|
||||||
|
height: 34px;
|
||||||
|
background: #0B60BD;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.info-span-div{
|
||||||
|
width: 187px;
|
||||||
|
margin-right: 22px;
|
||||||
|
.info-span-title{
|
||||||
|
font-family: PingFangSC-Medium;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1C1D22;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.info-span-subtitle{
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(28,29,34,0.5);
|
||||||
|
line-height: 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show-info-button{
|
||||||
|
width: 54px;
|
||||||
|
height: 23px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #0B60BD;
|
||||||
|
:deep(span){
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-family: PingFangSC-Regular;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item:nth-child(4n){
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-div{
|
||||||
|
padding-right: 32px;
|
||||||
|
width: 100%;
|
||||||
|
height: 66px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right-box{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
<template>
|
|
||||||
<BasicModal
|
|
||||||
v-bind="$attrs"
|
|
||||||
@register="registerModal"
|
|
||||||
:canFullscreen="false"
|
|
||||||
:defaultFullscreen="false"
|
|
||||||
:showCancelBtn="true"
|
|
||||||
:showOkBtn="true"
|
|
||||||
:draggable="false"
|
|
||||||
title="创建算法"
|
|
||||||
@ok="submitClick"
|
|
||||||
>
|
|
||||||
<div class="flex titlesbox">
|
|
||||||
<div class="li" v-for="(item,index) in tabList">
|
|
||||||
<span :class="index==tabIndex?'active':''" @click="tabsClick(index)">{{item}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 视频算法 -->
|
|
||||||
<div class="formsbox" v-if="tabIndex == 0">
|
|
||||||
<a-form
|
|
||||||
:model="formState"
|
|
||||||
ref="formRef"
|
|
||||||
:label-col="{ span: 6 }"
|
|
||||||
:wrapper-col="{ span: 18 }"
|
|
||||||
autocomplete="off"
|
|
||||||
>
|
|
||||||
<a-form-item
|
|
||||||
label="算法名称"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="概要描述"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-textarea v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="算力名称"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="推流地址"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="拉流地址"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="服务地址"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="秘钥"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
<!-- 图片算法 -->
|
|
||||||
<div class="formsbox" v-if="tabIndex == 1">
|
|
||||||
<a-form
|
|
||||||
:model="formState"
|
|
||||||
ref="formRef"
|
|
||||||
:label-col="{ span: 6 }"
|
|
||||||
:wrapper-col="{ span: 18 }"
|
|
||||||
autocomplete="off"
|
|
||||||
>
|
|
||||||
<a-form-item
|
|
||||||
label="算法名称"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="概要描述"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-textarea v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="算力名称"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="服务地址"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
label="秘钥"
|
|
||||||
name="username"
|
|
||||||
:rules="[{ required: true, message: '请输入' }]"
|
|
||||||
>
|
|
||||||
<a-input v-model:value="formState.username" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</div>
|
|
||||||
</BasicModal>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, defineEmits, reactive, toRaw } from 'vue';
|
|
||||||
import { BasicModal, useModalInner } from '@/components/Modal';
|
|
||||||
const tabIndex = ref(0);
|
|
||||||
const tabList = ["视频算法","图片算法"];
|
|
||||||
const tabsClick = (index) =>{
|
|
||||||
tabIndex.value = index
|
|
||||||
}
|
|
||||||
const formRef = ref();
|
|
||||||
interface FormState {
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
remember: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formState = reactive<FormState>({
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
remember: true,
|
|
||||||
});
|
|
||||||
const submitClick = ()=>{
|
|
||||||
console.log('submit')
|
|
||||||
formRef.value.validate().then(() => {
|
|
||||||
console.log('values', formState, toRaw(formState));
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log('error', error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const [registerModal, { closeModal }] = useModalInner((data: any) => {
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
.titlesbox{
|
|
||||||
width: 92%;
|
|
||||||
margin-left: 4%;
|
|
||||||
line-height: 40px;
|
|
||||||
border-bottom: 1px solid #F5F6FA;
|
|
||||||
.li{
|
|
||||||
width: 50%;
|
|
||||||
text-align: center;
|
|
||||||
span{
|
|
||||||
color: #222738;
|
|
||||||
cursor: pointer;
|
|
||||||
line-height: 40px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.active{
|
|
||||||
border-bottom: 3px solid #3A57E8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.formsbox{
|
|
||||||
width: 92%;
|
|
||||||
margin-left: 4%;
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -495,7 +495,15 @@
|
||||||
const searchParams = ref();
|
const searchParams = ref();
|
||||||
const [
|
const [
|
||||||
registerTable,
|
registerTable,
|
||||||
{ reload, getDataSource, getSelectRows, setSelectedRows, clearSelectedRowKeys },
|
{
|
||||||
|
reload,
|
||||||
|
getDataSource,
|
||||||
|
getSelectRows,
|
||||||
|
setSelectedRows,
|
||||||
|
clearSelectedRowKeys,
|
||||||
|
getPaginationRef,
|
||||||
|
setPagination,
|
||||||
|
},
|
||||||
] = useTable({
|
] = useTable({
|
||||||
api: GetMediaFile,
|
api: GetMediaFile,
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
|
|
@ -585,6 +593,11 @@
|
||||||
nowParentKey.value = f.id;
|
nowParentKey.value = f.id;
|
||||||
floders.value = floders.value.splice(0, index + 1);
|
floders.value = floders.value.splice(0, index + 1);
|
||||||
clearSelectedRowKeys();
|
clearSelectedRowKeys();
|
||||||
|
if (current) {
|
||||||
|
setPagination({
|
||||||
|
current: current,
|
||||||
|
});
|
||||||
|
}
|
||||||
reload().then((res) => {
|
reload().then((res) => {
|
||||||
showTableData.value = res;
|
showTableData.value = res;
|
||||||
});
|
});
|
||||||
|
|
@ -719,6 +732,7 @@
|
||||||
// 目前展示图片的列表
|
// 目前展示图片的列表
|
||||||
const previewRecordList: any = ref([]);
|
const previewRecordList: any = ref([]);
|
||||||
// 查看-打开这个文件夹或者展示这个图片
|
// 查看-打开这个文件夹或者展示这个图片
|
||||||
|
let current = 1;
|
||||||
async function lookRecord(record) {
|
async function lookRecord(record) {
|
||||||
// 展示这个图片后者视频
|
// 展示这个图片后者视频
|
||||||
if (record.objectKey) {
|
if (record.objectKey) {
|
||||||
|
|
@ -751,6 +765,8 @@
|
||||||
id: nowParentKey.value,
|
id: nowParentKey.value,
|
||||||
name: record.name,
|
name: record.name,
|
||||||
});
|
});
|
||||||
|
current = getPaginationRef().current;
|
||||||
|
setPagination({ current: 1 });
|
||||||
reload().then((res) => {
|
reload().then((res) => {
|
||||||
showTableData.value = res;
|
showTableData.value = res;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ import {ref,watch,onMounted,defineEmits} from 'vue';
|
||||||
import airLineList from '../workplan/components/airLineList.vue';
|
import airLineList from '../workplan/components/airLineList.vue';
|
||||||
import createAirLine from '../workplan/components/createAirLine.vue'
|
import createAirLine from '../workplan/components/createAirLine.vue'
|
||||||
import importAirLine from '../workplan/components/importAirLine.vue'
|
import importAirLine from '../workplan/components/importAirLine.vue'
|
||||||
|
|
||||||
|
|
||||||
import Map from '../workplan/components/map.vue'
|
import Map from '../workplan/components/map.vue'
|
||||||
import AirPolygon from './components/airPolygon.vue';
|
import AirPolygon from './components/airPolygon.vue';
|
||||||
import {getAirLine} from '@/api/sys/workplan';
|
import {getAirLine} from '@/api/sys/workplan';
|
||||||
|
|
@ -47,10 +49,19 @@ import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
||||||
|
|
||||||
const emits = defineEmits(["updateAirLineLise"])
|
const emits = defineEmits(["updateAirLineLise"])
|
||||||
|
|
||||||
// 模式 add edit detail
|
// 当前目录
|
||||||
|
const currentFolder = ref(null);
|
||||||
|
|
||||||
|
// 更新当前目录
|
||||||
|
const setCurrentFolder = (folder)=>{
|
||||||
|
currentFolder.value = folder;
|
||||||
|
importAirLineShow.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 航线模式 add edit detail
|
||||||
const editMode = ref("add");
|
const editMode = ref("add");
|
||||||
|
|
||||||
// airLine form
|
// 航线表单数据
|
||||||
const airLineForm = ref({
|
const airLineForm = ref({
|
||||||
"id": null,
|
"id": null,
|
||||||
"airLineName": null,
|
"airLineName": null,
|
||||||
|
|
@ -74,197 +85,11 @@ const airLineForm = ref({
|
||||||
// "lineData":null,
|
// "lineData":null,
|
||||||
});
|
});
|
||||||
|
|
||||||
// template.kml
|
// 航线template.kml
|
||||||
const templateKmlConfig = ref({
|
const templateKmlConfig = ref({})
|
||||||
"author": 17861857725,
|
|
||||||
"createTime": 1749689844431,
|
|
||||||
"updateTime": 1753241338101,
|
|
||||||
"missionConfig": {
|
|
||||||
"flyToWaylineMode": "pointToPoint",
|
|
||||||
"finishAction": "goHome",
|
|
||||||
"exitOnRCLost": "goContinue",
|
|
||||||
"executeRCLostAction": "goBack",
|
|
||||||
"takeOffSecurityHeight": 20,
|
|
||||||
"takeOffRefPoint": "",
|
|
||||||
"takeOffRefPointAGLHeight": 4.169064385,
|
|
||||||
"globalTransitionalSpeed": 15,
|
|
||||||
"globalRTHHeight": 100,
|
|
||||||
"droneInfo": {
|
|
||||||
"droneEnumValue": 100,
|
|
||||||
"droneSubEnumValue": 1
|
|
||||||
},
|
|
||||||
"autoRerouteInfo": {
|
|
||||||
"transitionalAutoRerouteMode": 1,
|
|
||||||
"missionAutoRerouteMode": 1
|
|
||||||
},
|
|
||||||
"waylineAvoidLimitAreaMode": 0,
|
|
||||||
"payloadInfo": {
|
|
||||||
"payloadEnumValue": 99,
|
|
||||||
"payloadSubEnumValue": 0,
|
|
||||||
"payloadPositionIndex": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Folder": {
|
|
||||||
"templateType": "mapping2d",
|
|
||||||
"templateId": 0,
|
|
||||||
"waylineCoordinateSysParam": {
|
|
||||||
"coordinateMode": "WGS84",
|
|
||||||
"heightMode": "EGM96",
|
|
||||||
"globalShootHeight": 90,
|
|
||||||
"surfaceFollowModeEnable": 1,
|
|
||||||
"isRealtimeSurfaceFollow": 0,
|
|
||||||
"surfaceRelativeHeight": 90,
|
|
||||||
"dsmFile": "wpmz/res/dsm/wgs84_ASTGTMV003_N35E118_dem_7.tif"
|
|
||||||
},
|
|
||||||
"autoFlightSpeed": 12.7,
|
|
||||||
"Placemark": {
|
|
||||||
"caliFlightEnable": 0,
|
|
||||||
"elevationOptimizeEnable": 1,
|
|
||||||
"smartObliqueEnable": 0,
|
|
||||||
"quickOrthoMappingEnable": 0,
|
|
||||||
"facadeWaylineEnable": 0,
|
|
||||||
"isLookAtSceneSet": 0,
|
|
||||||
"shootType": "time",
|
|
||||||
"direction": 83,
|
|
||||||
"margin": 0,
|
|
||||||
"efficiencyFlightModeEnable": 0,
|
|
||||||
"overlap": {
|
|
||||||
"orthoCameraOverlapH": 80,
|
|
||||||
"orthoCameraOverlapW": 70,
|
|
||||||
"inclinedCameraOverlapH": 80,
|
|
||||||
"inclinedCameraOverlapW": 70
|
|
||||||
},
|
|
||||||
"Polygon": {
|
|
||||||
"outerBoundaryIs": {
|
|
||||||
"LinearRing": {
|
|
||||||
"coordinates": "118.293794766158,35.1353688096117,0\n 118.295429169407,35.1353304409052,0\n 118.295487507293,35.1332925168381,0\n 118.293672196844,35.1331918267775,0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ellipsoidHeight": 90,
|
|
||||||
"height": 90
|
|
||||||
},
|
|
||||||
"payloadParam": {
|
|
||||||
"payloadPositionIndex": 0,
|
|
||||||
"focusMode": "firstPoint",
|
|
||||||
"meteringMode": "average",
|
|
||||||
"returnMode": "singleReturnStrongest",
|
|
||||||
"samplingRate": 240000,
|
|
||||||
"scanningMode": "repetitive",
|
|
||||||
"imageFormat": "visable",
|
|
||||||
"photoSize": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// wayline.wpml
|
// 航线wayline.wpml
|
||||||
const waylineWpmlConfig = ref({
|
const waylineWpmlConfig = ref({})
|
||||||
"missionConfig": {
|
|
||||||
"flyToWaylineMode": "pointToPoint",
|
|
||||||
"finishAction": "goHome",
|
|
||||||
"exitOnRCLost": "goContinue",
|
|
||||||
"executeRCLostAction": "goBack",
|
|
||||||
"takeOffSecurityHeight": 20,
|
|
||||||
"globalTransitionalSpeed": 15,
|
|
||||||
"globalRTHHeight": 100,
|
|
||||||
"droneInfo": {
|
|
||||||
"droneEnumValue": 100,
|
|
||||||
"droneSubEnumValue": 1
|
|
||||||
},
|
|
||||||
"autoRerouteInfo": {
|
|
||||||
"transitionalAutoRerouteMode": 1,
|
|
||||||
"missionAutoRerouteMode": 1
|
|
||||||
},
|
|
||||||
"waylineAvoidLimitAreaMode": 0,
|
|
||||||
"payloadInfo": {
|
|
||||||
"payloadEnumValue": 99,
|
|
||||||
"payloadSubEnumValue": 0,
|
|
||||||
"payloadPositionIndex": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Folder": {
|
|
||||||
"templateId": 0,
|
|
||||||
"executeHeightMode": "WGS84",
|
|
||||||
"waylineId": 0,
|
|
||||||
"distance": 1259.17163085938,
|
|
||||||
"duration": 145.652896165848,
|
|
||||||
"autoFlightSpeed": 12.7,
|
|
||||||
"startActionGroup": {
|
|
||||||
"action": [
|
|
||||||
{
|
|
||||||
"actionId": 0,
|
|
||||||
"actionActuatorFunc": "gimbalRotate",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"gimbalHeadingYawBase": "aircraft",
|
|
||||||
"gimbalRotateMode": "absoluteAngle",
|
|
||||||
"gimbalPitchRotateEnable": 1,
|
|
||||||
"gimbalPitchRotateAngle": -90,
|
|
||||||
"gimbalRollRotateEnable": 0,
|
|
||||||
"gimbalRollRotateAngle": 0,
|
|
||||||
"gimbalYawRotateEnable": 1,
|
|
||||||
"gimbalYawRotateAngle": 0,
|
|
||||||
"gimbalRotateTimeEnable": 0,
|
|
||||||
"gimbalRotateTime": 10,
|
|
||||||
"payloadPositionIndex": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actionId": 1,
|
|
||||||
"actionActuatorFunc": "hover",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"hoverTime": 0.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actionId": 2,
|
|
||||||
"actionActuatorFunc": "setFocusType",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"cameraFocusType": "manual",
|
|
||||||
"payloadPositionIndex": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actionId": 3,
|
|
||||||
"actionActuatorFunc": "focus",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"focusX": 0,
|
|
||||||
"focusY": 0,
|
|
||||||
"focusRegionWidth": 0,
|
|
||||||
"focusRegionHeight": 0,
|
|
||||||
"isPointFocus": 0,
|
|
||||||
"isInfiniteFocus": 1,
|
|
||||||
"payloadPositionIndex": 0,
|
|
||||||
"isCalibrationFocus": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actionId": 4,
|
|
||||||
"actionActuatorFunc": "hover",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"hoverTime": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Placemark": []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 当前目录
|
|
||||||
const currentFolder = ref(null);
|
|
||||||
|
|
||||||
// 更新当前目录
|
|
||||||
const setCurrentFolder = (folder)=>{
|
|
||||||
currentFolder.value = folder;
|
|
||||||
importAirLineShow.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const flyToTherePosition = ref({
|
|
||||||
lng:null,
|
|
||||||
lat:null,
|
|
||||||
alt:null,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const flyToThere = (e)=>{
|
const flyToThere = (e)=>{
|
||||||
|
|
@ -278,22 +103,6 @@ const aircraftShow = ref(false);
|
||||||
const createAirLineShow = ref(false);
|
const createAirLineShow = ref(false);
|
||||||
const importAirLineShow = ref(false);
|
const importAirLineShow = ref(false);
|
||||||
|
|
||||||
const selectAriLine = ()=> {
|
|
||||||
ariLineShow.value = true;
|
|
||||||
aircraftShow.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectAircraft = ()=>{
|
|
||||||
aircraftShow.value = true;
|
|
||||||
ariLineShow.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cancleCraete = ()=>{
|
|
||||||
workPlanFormShow.value = false;
|
|
||||||
ariLineShow.value = false;
|
|
||||||
aircraftShow.value = false;
|
|
||||||
planListShow.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkedAriLine = ref({});
|
const checkedAriLine = ref({});
|
||||||
|
|
||||||
|
|
@ -306,23 +115,11 @@ const checkAriLine = (item)=>{
|
||||||
|
|
||||||
const checkedDronePort = ref({});
|
const checkedDronePort = ref({});
|
||||||
|
|
||||||
const checkDronePort = (item)=>{
|
|
||||||
if(item){
|
|
||||||
aircraftShow.value = false;
|
|
||||||
checkedDronePort.value = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formData = ref(null);
|
const formData = ref(null);
|
||||||
|
|
||||||
const toCreateWorkPlan = (data)=> {
|
|
||||||
formData.value = data;
|
|
||||||
planListShow.value = false;
|
|
||||||
workPlanFormShow.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建航线
|
|
||||||
const globalFolder = ref(null);
|
const globalFolder = ref(null);
|
||||||
|
|
||||||
const handlerCreateAirLine = (folder)=>{
|
const handlerCreateAirLine = (folder)=>{
|
||||||
globalFolder.value = folder;
|
globalFolder.value = folder;
|
||||||
createAirLineShow.value = true;
|
createAirLineShow.value = true;
|
||||||
|
|
@ -337,21 +134,33 @@ const cancleImportAirLine = ()=>{
|
||||||
importAirLineShow.value = false;
|
importAirLineShow.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlerCreateAirLineForm = (form)=>{
|
// 创建航线
|
||||||
|
const handlerCreateAirLineForm =async (form)=>{
|
||||||
|
|
||||||
|
console.log("form",form);
|
||||||
|
|
||||||
|
// 根据航线类型处理设置template.kml、wayline.wpml
|
||||||
|
if(form.airLineType == 'waypoint'){
|
||||||
|
const {templateKml,waylineWpml} = await import("../workplan/waylineConfig/waypointConfig");
|
||||||
|
templateKmlConfig.value = templateKml;
|
||||||
|
waylineWpmlConfig.value = waylineWpml;
|
||||||
|
}else if(form.airLineType == 'mapping2d'){
|
||||||
|
const {templateKml,waylineWpml} = await import("../workplan/waylineConfig/mapping2dConfig");
|
||||||
|
templateKmlConfig.value = templateKml;
|
||||||
|
waylineWpmlConfig.value = waylineWpml;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("templateKmlConfig999",templateKmlConfig.value);
|
||||||
|
|
||||||
// 关闭全部窗口
|
// 关闭全部窗口
|
||||||
workPlanFormShow.value = false;
|
|
||||||
ariLineShow.value = false;
|
ariLineShow.value = false;
|
||||||
aircraftShow.value = false;
|
|
||||||
planListShow.value = false;
|
|
||||||
createAirLineShow.value = false;
|
createAirLineShow.value = false;
|
||||||
|
|
||||||
// 航线表单
|
// 更新航线表单
|
||||||
airLineForm.value = form
|
airLineForm.value = form
|
||||||
airLineForm.value.folder = globalFolder.value;
|
|
||||||
|
|
||||||
console.log("airLineFor121m",airLineForm.value);
|
|
||||||
|
|
||||||
|
// 更新目录参数
|
||||||
|
airLineForm.value.folder = globalFolder.value ? globalFolder.value : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const successCreatePlan = ()=>{
|
const successCreatePlan = ()=>{
|
||||||
|
|
@ -370,8 +179,6 @@ const exitDraw = ()=>{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 预览航线
|
// 预览航线
|
||||||
const wayline = ref({});
|
const wayline = ref({});
|
||||||
const waylineInfo = ref(null)
|
const waylineInfo = ref(null)
|
||||||
|
|
@ -400,7 +207,6 @@ const planDetail =async (item) => {
|
||||||
|
|
||||||
|
|
||||||
// 获取wpml文件
|
// 获取wpml文件
|
||||||
|
|
||||||
const currentPreviewWayLine = ref(null);
|
const currentPreviewWayLine = ref(null);
|
||||||
|
|
||||||
const airLineDetail =async (item) => {
|
const airLineDetail =async (item) => {
|
||||||
|
|
@ -441,10 +247,8 @@ const extractKmz = async (kmzBlob)=>{
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
|
let element = window.document.getElementsByClassName("mars3d-locationbar")[0] as HTMLElement;
|
||||||
let element = window.document.getElementsByClassName("mars3d-locationbar")[0] as HTMLElement;
|
element.style.bottom = '40px';
|
||||||
element.style.bottom = '40px';
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -483,6 +287,7 @@ const importSuccess = () => {
|
||||||
airLineListRef.value.getAirList();
|
airLineListRef.value.getAirList();
|
||||||
importAirLineShow.value = false;
|
importAirLineShow.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.map-out-container{
|
.map-out-container{
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,11 @@
|
||||||
<div class="params-item">
|
<div class="params-item">
|
||||||
<div class="params-label">俯仰角度:</div>
|
<div class="params-label">俯仰角度:</div>
|
||||||
<div class="params-value">
|
<div class="params-value">
|
||||||
<a-slider v-model:value="props.params.gimbalPitchRotateAngle" :min="-180" :max="180" :step="0.01" />
|
<a-slider
|
||||||
|
v-model:value="props.params.gimbalPitchRotateAngle"
|
||||||
|
:min="-90" :max="30" :step="0.01"
|
||||||
|
@change="paramChagne"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="params-value-text">
|
<div class="params-value-text">
|
||||||
{{ props.params.gimbalPitchRotateAngle }} °
|
{{ props.params.gimbalPitchRotateAngle }} °
|
||||||
|
|
@ -14,13 +18,16 @@
|
||||||
|
|
||||||
import {defineProps,defineComponent,defineOptions} from 'vue';
|
import {defineProps,defineComponent,defineOptions} from 'vue';
|
||||||
|
|
||||||
const props = defineProps(["params"])
|
const props = defineProps(["params","info"])
|
||||||
|
const emits = defineEmits(["paramChagne"])
|
||||||
|
|
||||||
defineComponent({
|
defineComponent({
|
||||||
name: 'gimbalRotate'
|
name: 'gimbalRotate'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const paramChagne = ()=> {
|
||||||
|
emits("paramChagne",props.info);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
<div class="params-value">
|
<div class="params-value">
|
||||||
<a-input-number v-model:value="props.params.hoverTime"></a-input-number>
|
<a-input-number v-model:value="props.params.hoverTime"></a-input-number>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="params-unit">秒</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -35,6 +36,10 @@ defineComponent({
|
||||||
flex:1;
|
flex:1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.params-item .params-unit{
|
||||||
|
line-height:30px;
|
||||||
|
padding:0px 5px 0px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
::v-deep .ant-input-number{
|
::v-deep .ant-input-number{
|
||||||
color:#fff!important;
|
color:#fff!important;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<div class="params-item">
|
||||||
|
<div class="params-label">间隔时间:</div>
|
||||||
|
<div class="params-value">
|
||||||
|
<a-input-number v-model:value="props.params.hoverTime"></a-input-number>
|
||||||
|
</div>
|
||||||
|
<div class="params-unit">秒</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {defineProps,defineComponent,defineOptions} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps(["params"])
|
||||||
|
|
||||||
|
|
||||||
|
defineComponent({
|
||||||
|
name: 'multipleTiming'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.params-item{
|
||||||
|
width:100%;
|
||||||
|
display: flex;
|
||||||
|
gap:20px;
|
||||||
|
}
|
||||||
|
.params-item .params-label{
|
||||||
|
line-height:30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-item .params-value{
|
||||||
|
flex:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-item .params-unit{
|
||||||
|
line-height:30px;
|
||||||
|
padding:0px 5px 0px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .ant-input-number{
|
||||||
|
color:#fff!important;
|
||||||
|
background:#3F4150!important;
|
||||||
|
border:0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .ant-input-number-input{
|
||||||
|
color:#fff!important;
|
||||||
|
border:0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="params-item">
|
<div class="params-item">
|
||||||
<div class="params-label">偏航角度</div>
|
<div class="params-label">偏航角度:</div>
|
||||||
<div class="params-value">
|
<div class="params-value">
|
||||||
<a-slider v-model:value="props.params.aircraftHeading" :min="-180" :max="180" :step="0.01" />
|
<a-slider
|
||||||
|
v-model:value="props.params.aircraftHeading"
|
||||||
|
:min="-180" :max="180" :step="0.01"
|
||||||
|
@change="paramChagne" />
|
||||||
</div>
|
</div>
|
||||||
<div class="params-value-text">
|
<div class="params-value-text">
|
||||||
{{ props.params.aircraftHeading }} °
|
{{ props.params.aircraftHeading }} °
|
||||||
|
|
@ -12,16 +15,20 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
import {defineProps,defineComponent,defineOptions} from 'vue';
|
import {defineProps,defineComponent,defineEmits} from 'vue';
|
||||||
|
|
||||||
const props = defineProps(["params"])
|
|
||||||
|
|
||||||
|
const props = defineProps(["params","info"])
|
||||||
|
const emits = defineEmits(["paramChagne"])
|
||||||
|
|
||||||
defineComponent({
|
defineComponent({
|
||||||
name: 'rotateYaw'
|
name: 'rotateYaw'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const paramChagne = ()=> {
|
||||||
|
emits("paramChagne",props.info);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pagenation">
|
<div class="pagenation">
|
||||||
<a-pagination v-model:current="pageQuery.page" :total="ariLineCount" show-less-items @change="onPageChange" />
|
<a-pagination size="small" v-model:current="pageQuery.page"
|
||||||
|
v-model:page-size="pageQuery.limit" :total="ariLineCount"
|
||||||
|
:defaultPageSize="10" show-less-items show-size-changer @change="onPageChange" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -245,7 +247,7 @@
|
||||||
|
|
||||||
const props = defineProps(["title"])
|
const props = defineProps(["title"])
|
||||||
|
|
||||||
import {templateTypeOptions} from '../waylineConfig/index';
|
import {templateTypeOptions} from '../waylineConfig/waylineParamsOptions';
|
||||||
|
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,16 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<LeftOutlined @click="backPage" />
|
<LeftOutlined @click="backPage" />
|
||||||
<div>航点航线</div>
|
<div style="flex:1;">
|
||||||
<SaveOutlined @click="saveAirLine"/>
|
<a-input v-model:value="props.airLineForm.airLineName" size="middle" placeholder="航线名称" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<a-button type="primary" size="middle" @click="areaOptionsShow = !areaOptionsShow">
|
<a-button type="primary" size="middle" @click="areaOptionsShow = !areaOptionsShow">
|
||||||
航线设置
|
航线设置
|
||||||
<ControlOutlined />
|
<ControlOutlined />
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<div style="flex:1;">
|
<SaveOutlined @click="saveAirLine" style="font-size:20px;" />
|
||||||
<a-input v-model:value="props.airLineForm.airLineName" size="middle" placeholder="航线名称" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 航线信息 -->
|
<!-- 航线信息 -->
|
||||||
|
|
@ -165,7 +163,7 @@
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="label">全局航线飞行速度</div>
|
<div class="label">全局航线飞行速度</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<a-input style="width:100px;" placeholder="" v-model:value="missionConfig.globalTransitionalSpeed"></a-input>
|
<a-input style="width:100px;" placeholder="" v-model:value="props.templateKmlConfig.Folder.autoFlightSpeed"></a-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="unit"> m/s</div>
|
<div class="unit"> m/s</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -343,12 +341,14 @@ import {ref,defineEmits,defineProps} from 'vue'
|
||||||
import { SaveOutlined,LeftOutlined,AppstoreOutlined,DownOutlined,ControlOutlined,InfoCircleOutlined} from '@ant-design/icons-vue';
|
import { SaveOutlined,LeftOutlined,AppstoreOutlined,DownOutlined,ControlOutlined,InfoCircleOutlined} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
// 航点动作汇总
|
// 航点动作汇总
|
||||||
import { airPointActions } from '../waylineConfig/action'
|
import { airPointActions } from '../waylineConfig/actionConfig'
|
||||||
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
||||||
|
|
||||||
import {uploadXmlFile,addAirLine} from '@/api/sys/workplan';
|
import {uploadXmlFile,addAirLine,editAirLine} from '@/api/sys/workplan';
|
||||||
import { Modal, message } from 'ant-design-vue';
|
import { Modal, message } from 'ant-design-vue';
|
||||||
import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/index.ts';
|
import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/waylineParamsOptions.ts';
|
||||||
|
import JSZip from "jszip";
|
||||||
|
import { saveAs } from "file-saver";
|
||||||
|
|
||||||
const emits = defineEmits(["setTakeOffPoint","checkPoint","exitDraw","addAction"])
|
const emits = defineEmits(["setTakeOffPoint","checkPoint","exitDraw","addAction"])
|
||||||
|
|
||||||
|
|
@ -520,93 +520,11 @@ const pointInfo = ref({
|
||||||
|
|
||||||
// 处理航点数据
|
// 处理航点数据
|
||||||
const handlerPointInfo = ()=>{
|
const handlerPointInfo = ()=>{
|
||||||
|
|
||||||
if(props.airPoints?.length<=0){
|
if(props.airPoints?.length<=0){
|
||||||
message.warning("请添加航点!");
|
message.warning("请添加航点!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
props.airPoints?.forEach((item,index)=>{
|
|
||||||
|
|
||||||
console.log("item123",item);
|
|
||||||
|
|
||||||
let point = {
|
|
||||||
"Point": {
|
|
||||||
"coordinates": item.lng+","+item.lat
|
|
||||||
},
|
|
||||||
"index": index,
|
|
||||||
"executeHeight": item.alt,
|
|
||||||
"waypointSpeed": 10,
|
|
||||||
"waypointHeadingParam": {
|
|
||||||
"waypointHeadingMode": "followWayline", // 飞行器偏航角模式 :
|
|
||||||
"waypointHeadingAngle": item.aircraftHorizontalAngle, // 飞行器偏航角 [-180, 180] 当且仅当“wpml:waypointHeadingMode”为“smoothTransition”时必需
|
|
||||||
"waypointPoiPoint": "0.000000,0.000000,0.000000", // 兴趣点 仅当wpml:waypointHeadingMode为towardPOI时必需
|
|
||||||
"waypointHeadingAngleEnable": 0,
|
|
||||||
"waypointHeadingPathMode": "followBadArc", // 飞行器偏航角转动方向
|
|
||||||
"waypointHeadingPoiIndex": 0
|
|
||||||
},
|
|
||||||
"waypointTurnParam": {
|
|
||||||
"waypointTurnMode": "toPointAndStopWithDiscontinuityCurvature",
|
|
||||||
"waypointTurnDampingDist": 0
|
|
||||||
},
|
|
||||||
"useStraightLine": 1,
|
|
||||||
"actionGroup": {
|
|
||||||
"actionGroupId": 0,
|
|
||||||
"actionGroupStartIndex": 0,
|
|
||||||
"actionGroupEndIndex": 0,
|
|
||||||
"actionGroupMode": "sequence",
|
|
||||||
"actionTrigger": {
|
|
||||||
"actionTriggerType": "reachPoint"
|
|
||||||
},
|
|
||||||
"action": [
|
|
||||||
{
|
|
||||||
"actionId": 0,
|
|
||||||
"actionActuatorFunc": "rotateYaw",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"aircraftHeading": 0,
|
|
||||||
"aircraftPathMode": "counterClockwise"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actionId": 1,
|
|
||||||
"actionActuatorFunc": "gimbalRotate",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"gimbalHeadingYawBase": "north",
|
|
||||||
"gimbalRotateMode": "absoluteAngle",
|
|
||||||
"gimbalPitchRotateEnable": 1,
|
|
||||||
"gimbalPitchRotateAngle": 0,
|
|
||||||
"gimbalRollRotateEnable": 0,
|
|
||||||
"gimbalRollRotateAngle": 0,
|
|
||||||
"gimbalYawRotateEnable": 0,
|
|
||||||
"gimbalYawRotateAngle": 0,
|
|
||||||
"gimbalRotateTimeEnable": 0,
|
|
||||||
"gimbalRotateTime": 0,
|
|
||||||
"payloadPositionIndex": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"actionId": 2,
|
|
||||||
"actionActuatorFunc": "zoom",
|
|
||||||
"actionActuatorFuncParam": {
|
|
||||||
"focalLength": 24,
|
|
||||||
"isUseFocalFactor": 0,
|
|
||||||
"payloadPositionIndex": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"waypointGimbalHeadingParam": {
|
|
||||||
"waypointGimbalPitchAngle": item.cameraVerticalAngle, // 云台 垂直俯仰角参数 [-90, -30]
|
|
||||||
"waypointGimbalYawAngle": 0 // 云台 水平偏航角度
|
|
||||||
},
|
|
||||||
"isRisky": 0,
|
|
||||||
"waypointWorkType": 0
|
|
||||||
}
|
|
||||||
folder.value.Placemark.push(point);
|
|
||||||
})
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// waylines.json 数据
|
// waylines.json 数据
|
||||||
|
|
@ -626,52 +544,194 @@ const waylinesJson = ref(
|
||||||
// 保存航线
|
// 保存航线
|
||||||
const saveAirLine = ()=>{
|
const saveAirLine = ()=>{
|
||||||
|
|
||||||
|
// 处理template.json
|
||||||
|
handlerTemplateKml();
|
||||||
|
|
||||||
|
// 处理航点
|
||||||
|
handlerWaylineWpml();
|
||||||
|
|
||||||
|
|
||||||
let handlerResult = handlerPointInfo();
|
let handlerResult = handlerPointInfo();
|
||||||
|
|
||||||
if(handlerResult){
|
if(handlerResult){
|
||||||
const builder = new XMLBuilder();
|
|
||||||
|
|
||||||
let lineData = {...waylinesJson.value}
|
// 将template中的 missionConfig 赋值 给wayline
|
||||||
|
props.waylineWpmlConfig.missionConfig = JSON.parse(JSON.stringify(props.templateKmlConfig.missionConfig))
|
||||||
|
|
||||||
let obj = handlerPrefixWpml(lineData);
|
const builder = new XMLBuilder({
|
||||||
|
format: true, // 启用换行和缩进
|
||||||
|
indentBy: " ", // 缩进字符(默认2空格,可自定义为 \t 等)
|
||||||
|
suppressEmptyNode: true, // 可选:是否忽略空节点
|
||||||
|
});
|
||||||
|
|
||||||
let xmlString = builder.build(obj);
|
// 带wpml前缀的 template json数据
|
||||||
|
let templateJson = {kml:{Document:props.templateKmlConfig}}
|
||||||
|
let templateWpmlJson = handlerPrefixWpml(templateJson);
|
||||||
|
let templateXmlStr = builder.build(templateWpmlJson);
|
||||||
|
let templateXmlStrTemp = templateXmlStr.replace(/<\/?\d+>/g, "")
|
||||||
|
let templateXml = templateXmlStrTemp.replace("<kml>",`<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">`)
|
||||||
|
|
||||||
let xmlString2 = xmlString.replace(/<\/?\d+>/g, "")
|
// 带wpml前缀的 wayline json数据
|
||||||
|
// delete props.waylineWpmlConfig.missionConfig.takeOffRefPoint
|
||||||
|
// delete props.waylineWpmlConfig.missionConfig.takeOffRefPointAGLHeight
|
||||||
|
// delete props.waylineWpmlConfig.missionConfig.autoRerouteInfo
|
||||||
|
|
||||||
let xmlString3 = xmlString2.replace("<kml>",`<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">`)
|
let waylineJosn = {kml:{Document:props.waylineWpmlConfig}}
|
||||||
|
let waylienWpmlJson = handlerPrefixWpml(waylineJosn);
|
||||||
|
let waylineXmlStr = builder.build(waylienWpmlJson);
|
||||||
|
let waylineXmlStrTemp = waylineXmlStr.replace(/<\/?\d+>/g, "")
|
||||||
|
let waylineXml = waylineXmlStrTemp.replace("<kml>",`<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">`)
|
||||||
|
|
||||||
console.log("xmlString3",xmlString3);
|
// 创建压缩文件
|
||||||
return null;
|
handlerCreateFile(templateXml,waylineXml);
|
||||||
handlerCreateFile(xmlString3);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理wmpl:前缀
|
// 处理生成template.json
|
||||||
const handlerPrefixWpml = (obj) => {
|
const handlerTemplateKml = () => {
|
||||||
for (const key in obj) {
|
|
||||||
|
|
||||||
// 如果是对象
|
// 处理时间和日期
|
||||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
handlerCreateOrUpdateTime();
|
||||||
|
|
||||||
handlerPrefixWpml(obj[key]); // 递归处理嵌套对象
|
// 计算数据处理
|
||||||
|
// handlerAirLineHeight();
|
||||||
|
|
||||||
const newAttrs = {};
|
|
||||||
for (const attrName in obj[key]) {
|
|
||||||
|
|
||||||
// 检查属性名是否首字母小写
|
}
|
||||||
if (/^[a-z]/.test(attrName)) {
|
|
||||||
newAttrs[`wmpl:${attrName}`] = obj[key][attrName];
|
// 处理创建时间 编辑时间
|
||||||
} else {
|
const handlerCreateOrUpdateTime = () => {
|
||||||
newAttrs[attrName] = obj[key][attrName];
|
|
||||||
}
|
let date = new Date();
|
||||||
|
|
||||||
|
if(props.editModel == 'add'){
|
||||||
|
props.templateKmlConfig.createTime = date.getTime();
|
||||||
|
props.templateKmlConfig.updateTime = date.getTime();
|
||||||
|
}else if(props.editModel == 'edit'){
|
||||||
|
props.templateKmlConfig.updateTime = date.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 处理生成wayline.json
|
||||||
|
const handlerWaylineWpml = () => {
|
||||||
|
|
||||||
|
// 处理基础配置
|
||||||
|
props.waylineWpmlConfig.missionConfig = JSON.parse(JSON.stringify(props.templateKmlConfig.missionConfig));
|
||||||
|
|
||||||
|
// 处理统计数据
|
||||||
|
handlerStatistics();
|
||||||
|
|
||||||
|
// 处理航点
|
||||||
|
handelrAirPoint();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlerStatistics = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理航点 和 绑定动作信息
|
||||||
|
const handelrAirPoint = () => {
|
||||||
|
props.airPoints?.forEach((item,index)=>{
|
||||||
|
let point = {
|
||||||
|
"Point": {
|
||||||
|
"coordinates": item.lng+","+item.lat
|
||||||
|
},
|
||||||
|
"index": index,
|
||||||
|
"executeHeight": 172.948304450636,
|
||||||
|
"waypointSpeed": props.templateKmlConfig.Folder.autoFlightSpeed,
|
||||||
|
"waypointHeadingParam": {
|
||||||
|
"waypointHeadingMode": "followWayline",
|
||||||
|
"waypointHeadingAngle": 0,
|
||||||
|
"waypointPoiPoint": "0.000000,0.000000,0.000000",
|
||||||
|
"waypointHeadingAngleEnable": 0,
|
||||||
|
"waypointHeadingPathMode": "followBadArc",
|
||||||
|
"waypointHeadingPoiIndex": 0
|
||||||
|
},
|
||||||
|
"waypointTurnParam": {
|
||||||
|
"waypointTurnMode": "toPointAndStopWithDiscontinuityCurvature",
|
||||||
|
"waypointTurnDampingDist": 0
|
||||||
|
},
|
||||||
|
"useStraightLine": 1,
|
||||||
|
"waypointGimbalHeadingParam": {
|
||||||
|
"waypointGimbalPitchAngle": 0,
|
||||||
|
"waypointGimbalYawAngle": 0
|
||||||
|
},
|
||||||
|
"isRisky": 0,
|
||||||
|
"waypointWorkType": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item.actions.length>0){
|
||||||
|
point.actionGroup = {
|
||||||
|
"actionGroupId": 0,
|
||||||
|
"actionGroupStartIndex": index,
|
||||||
|
"actionGroupEndIndex": index,
|
||||||
|
"actionGroupMode": "sequence",
|
||||||
|
"actionTrigger": {
|
||||||
|
"actionTriggerType": "reachPoint"
|
||||||
|
},
|
||||||
|
"action": []
|
||||||
|
};
|
||||||
|
item.actions.forEach((action,idx)=>{
|
||||||
|
let actor = action.config;
|
||||||
|
actor.actionId = idx
|
||||||
|
point.actionGroup.action.push(actor);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
props.waylineWpmlConfig.Folder.Placemark.push(point);
|
||||||
|
props.templateKmlConfig.Folder.Placemark.push(point);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 处理wpml:前缀
|
||||||
|
const handlerPrefixWpml = (obj) => {
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { // 如果是对象
|
||||||
|
|
||||||
|
handlerPrefixWpml(obj[key]); // 递归处理嵌套对象
|
||||||
|
|
||||||
|
const newAttrs = {};
|
||||||
|
|
||||||
|
for (const attrName in obj[key] ) {
|
||||||
|
|
||||||
|
// 检查属性名是否首字母小写
|
||||||
|
if (/^[a-z]/.test(attrName) && attrName != 'outerBoundaryIs' && attrName != 'coordinates') {
|
||||||
|
newAttrs[`wpml:${attrName}`] = obj[key][attrName];
|
||||||
|
} else {
|
||||||
|
newAttrs[attrName] = obj[key][attrName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj[key] = newAttrs;
|
||||||
|
|
||||||
|
}else if(typeof obj[key] === 'object' && obj[key] !== null && Array.isArray(obj[key])){ // 如果是数组
|
||||||
|
|
||||||
|
handlerPrefixWpml(obj[key]); // 递归处理嵌套对象
|
||||||
|
|
||||||
|
const newAttrs = [];
|
||||||
|
|
||||||
|
for (const attrName in obj[key]) {
|
||||||
|
// 检查属性名是否首字母小写
|
||||||
|
if (/^[a-z]/.test(attrName)) {
|
||||||
|
newAttrs[`wpml:${attrName}`] = obj[key][attrName];
|
||||||
|
} else {
|
||||||
|
newAttrs[attrName] = obj[key][attrName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj[key] = newAttrs;
|
||||||
}
|
}
|
||||||
obj[key] = newAttrs;
|
|
||||||
}
|
}
|
||||||
}
|
return obj;
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -695,15 +755,35 @@ const submitForm = ref({
|
||||||
})
|
})
|
||||||
|
|
||||||
// 生成xml文件,创建航线
|
// 生成xml文件,创建航线
|
||||||
const handlerCreateFile =async (content)=>{
|
const handlerCreateFile =async (templateXml,waylineXml)=>{
|
||||||
const blob = new Blob([content], { type: 'wmpl/plain' });
|
|
||||||
|
console.log("waylineXml",templateXml,waylineXml);
|
||||||
|
|
||||||
|
const blob =await convertXmlToKmz(templateXml,waylineXml);
|
||||||
|
|
||||||
// 创建FormData对象用于上传
|
// 创建FormData对象用于上传
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('xmlFile', blob);
|
|
||||||
let res = await uploadXmlFile(formData);
|
formData.append('xmlFile', blob,"航点航线.kmz");
|
||||||
|
|
||||||
|
let res = await uploadXmlFile(props.airLineForm.folder,formData);
|
||||||
|
|
||||||
if(res){
|
if(res){
|
||||||
submitForm.value.wpml = res.path;
|
props.airLineForm.wpml = res.path;
|
||||||
let addAirLineRes =await addAirLine(submitForm.value);
|
// props.airLineForm.lineData = {type:2}
|
||||||
|
|
||||||
|
let addAirLineRes = null;
|
||||||
|
|
||||||
|
if(props.editModel == 'add'){
|
||||||
|
|
||||||
|
addAirLineRes =await addAirLine(props.airLineForm);
|
||||||
|
|
||||||
|
}else if(props.editModel == 'edit'){
|
||||||
|
|
||||||
|
addAirLineRes =await editAirLine(props.airLineForm);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if(addAirLineRes){
|
if(addAirLineRes){
|
||||||
message.success("操作成功!");
|
message.success("操作成功!");
|
||||||
backPage();
|
backPage();
|
||||||
|
|
@ -715,6 +795,28 @@ const handlerCreateFile =async (content)=>{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xml文本转换为wpml和kml文件
|
||||||
|
const convertXmlToKmz =async (templateXml,waylineXml)=>{
|
||||||
|
|
||||||
|
|
||||||
|
const zip = new JSZip();
|
||||||
|
|
||||||
|
// 1. 创建 "wmpz" 文件夹
|
||||||
|
const wmpzFolder = zip.folder("wpmz");
|
||||||
|
|
||||||
|
// 2. 向文件夹中添加文件
|
||||||
|
wmpzFolder.file("waylines.wpml", waylineXml);
|
||||||
|
wmpzFolder.file("template.kml", templateXml);
|
||||||
|
|
||||||
|
// 3. 生成 KMZ (ZIP) 文件
|
||||||
|
const kmzBlob = await zip.generateAsync({ type: "blob" });
|
||||||
|
|
||||||
|
// 下载航线文件
|
||||||
|
// saveAs(kmzBlob, "output.kmz");
|
||||||
|
|
||||||
|
return kmzBlob;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 退出绘制
|
// 退出绘制
|
||||||
const backPage = ()=>{
|
const backPage = ()=>{
|
||||||
|
|
@ -728,7 +830,6 @@ const addAirPointAction = (action) => {
|
||||||
// 处理动作添加逻辑
|
// 处理动作添加逻辑
|
||||||
emits("addAction",action);
|
emits("addAction",action);
|
||||||
|
|
||||||
|
|
||||||
if(action.value == ""){
|
if(action.value == ""){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,19 +127,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-content">
|
<div class="item-content">
|
||||||
<component :is="componentMap[item.value]" :params="item.config.actionActuatorFuncParam" :key="index"></component>
|
<component
|
||||||
|
:is="componentMap[item.value]"
|
||||||
|
:params="item.config.actionActuatorFuncParam"
|
||||||
|
:info="item"
|
||||||
|
:key="index"
|
||||||
|
@paramChagne="paramChagne"
|
||||||
|
></component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {ref,defineProps,watch,shallowRef,defineAsyncComponent,defineOptions } from 'vue';
|
import {ref,defineProps,watch,shallowRef,defineAsyncComponent,defineOptions,defineEmits} from 'vue';
|
||||||
|
|
||||||
import { DeleteOutlined,LeftOutlined,RightOutlined } from '@ant-design/icons-vue'
|
import { DeleteOutlined,LeftOutlined,RightOutlined } from '@ant-design/icons-vue'
|
||||||
|
|
||||||
|
|
@ -163,8 +167,11 @@ const componentMap = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const props = defineProps(['currentAirPoint','airPoints'])
|
const props = defineProps(['currentAirPoint','airPoints'])
|
||||||
|
const emits = defineEmits(["paramChagne"])
|
||||||
|
|
||||||
|
const paramChagne = (info) => {
|
||||||
|
emits("paramChagne",info);
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
()=>props.currentAirPoint,
|
()=>props.currentAirPoint,
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {ref,defineEmits,defineProps,watch} from 'vue'
|
import {ref,defineEmits,defineProps,watch} from 'vue'
|
||||||
import { SaveOutlined,LeftOutlined,InfoCircleOutlined } from '@ant-design/icons-vue';
|
import { SaveOutlined,LeftOutlined,InfoCircleOutlined } from '@ant-design/icons-vue';
|
||||||
import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/index.ts';
|
import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/waylineParamsOptions.ts';
|
||||||
import {uploadXmlFile,addAirLine,editAirLine} from '@/api/sys/workplan';
|
import {uploadXmlFile,addAirLine,editAirLine} from '@/api/sys/workplan';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
||||||
|
|
@ -771,7 +771,6 @@ const handlerPrefixWpml = (obj) => {
|
||||||
|
|
||||||
// 检查属性名是否首字母小写
|
// 检查属性名是否首字母小写
|
||||||
if (/^[a-z]/.test(attrName) && attrName != 'outerBoundaryIs' && attrName != 'coordinates') {
|
if (/^[a-z]/.test(attrName) && attrName != 'outerBoundaryIs' && attrName != 'coordinates') {
|
||||||
console.log("attrName",attrName);
|
|
||||||
newAttrs[`wpml:${attrName}`] = obj[key][attrName];
|
newAttrs[`wpml:${attrName}`] = obj[key][attrName];
|
||||||
} else {
|
} else {
|
||||||
newAttrs[attrName] = obj[key][attrName];
|
newAttrs[attrName] = obj[key][attrName];
|
||||||
|
|
@ -814,7 +813,7 @@ const handlerCreateFile =async (templateXml,waylineXml)=>{
|
||||||
|
|
||||||
formData.append('xmlFile', blob,"面状航线.kmz");
|
formData.append('xmlFile', blob,"面状航线.kmz");
|
||||||
|
|
||||||
let res = await uploadXmlFile("默认文件夹/面状航线",formData);
|
let res = await uploadXmlFile(props.airLineForm.folder,formData);
|
||||||
|
|
||||||
if(res){
|
if(res){
|
||||||
props.airLineForm.wpml = res.path;
|
props.airLineForm.wpml = res.path;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
</div>
|
</div>
|
||||||
</a-form-item> -->
|
</a-form-item> -->
|
||||||
|
|
||||||
<a-form-item ref="workspaceId" label="选择项目" name="workspaceId">
|
<!-- <a-form-item ref="workspaceId" label="选择项目" name="workspaceId">
|
||||||
<div class="">
|
<div class="">
|
||||||
<a-select
|
<a-select
|
||||||
v-model:value="submitForm.workspaceId"
|
v-model:value="submitForm.workspaceId"
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
</a-form-item>
|
</a-form-item> -->
|
||||||
|
|
||||||
|
|
||||||
<a-form-item ref="name" label="选择航线" name="name">
|
<a-form-item ref="name" label="选择航线" name="name">
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
<airPointConfig
|
<airPointConfig
|
||||||
:currentAirPoint="currentAirPoint"
|
:currentAirPoint="currentAirPoint"
|
||||||
:airPoints="airPoints"
|
:airPoints="airPoints"
|
||||||
|
@paramChagne="paramChagne"
|
||||||
></airPointConfig>
|
></airPointConfig>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -66,7 +67,6 @@
|
||||||
import airPolygon from './airPolygon.vue';
|
import airPolygon from './airPolygon.vue';
|
||||||
import airPointConfig from './airPointConfig.vue';
|
import airPointConfig from './airPointConfig.vue';
|
||||||
|
|
||||||
|
|
||||||
// const props = defineProps([
|
// const props = defineProps([
|
||||||
// 'airLineForm',
|
// 'airLineForm',
|
||||||
// 'flyToTherePosition',
|
// 'flyToTherePosition',
|
||||||
|
|
@ -301,7 +301,6 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 航线预览:生成点
|
// 航线预览:生成点
|
||||||
const generatePreviewPoint = (placemark)=>{
|
const generatePreviewPoint = (placemark)=>{
|
||||||
|
|
||||||
|
|
@ -358,24 +357,30 @@ const generatePreviewPoint = (placemark)=>{
|
||||||
let moveTool: mars3d.thing.MatrixMove2;
|
let moveTool: mars3d.thing.MatrixMove2;
|
||||||
|
|
||||||
// 监听航点变化
|
// 监听航点变化
|
||||||
watch(
|
// watch(
|
||||||
currentAirPoint,
|
// currentAirPoint,
|
||||||
(newVal, oldVal) => {
|
// (newVal, oldVal) => {
|
||||||
// 更新航点
|
// // console.log("newVal123",newVal);
|
||||||
updateAirPoint(newVal);
|
// // 更新航点
|
||||||
// 更新镜头
|
// // updateAirPoint(newVal);
|
||||||
handlerDrawCamera(newVal);
|
// // 更新镜头
|
||||||
},
|
// // handlerDrawCamera(newVal);
|
||||||
{ deep: true },
|
// },
|
||||||
);
|
// { deep: true },
|
||||||
|
// );
|
||||||
|
|
||||||
const clickPoint = (id) => {
|
const clickPoint = (id) => {
|
||||||
|
|
||||||
airPoints.value?.forEach((item, index) => {
|
airPoints.value?.forEach((item, index) => {
|
||||||
if (item.id == id) {
|
if (item.id == id) {
|
||||||
currentAirPoint.value = item;
|
currentAirPoint.value = item;
|
||||||
|
// 更新镜头
|
||||||
|
handlerDrawCamera(currentAirPoint.value);
|
||||||
airPointConfigShow.value = true;
|
airPointConfigShow.value = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkPoint = (e) => {
|
const checkPoint = (e) => {
|
||||||
|
|
@ -686,7 +691,6 @@ const initMap = () => {
|
||||||
// 绘制航线
|
// 绘制航线
|
||||||
graphicLayer.on(mars3d.EventType.click, (e) => {
|
graphicLayer.on(mars3d.EventType.click, (e) => {
|
||||||
// 设置当前选中点
|
// 设置当前选中点
|
||||||
|
|
||||||
clickPoint(e.graphic.options.id);
|
clickPoint(e.graphic.options.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1576,6 +1580,7 @@ const handlerDrawLine = () => {
|
||||||
// lineInfo.value.length = turf.length(lineString).toFixed(2);
|
// lineInfo.value.length = turf.length(lineString).toFixed(2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 全局航点数组
|
||||||
const uavPoints = ref([]);
|
const uavPoints = ref([]);
|
||||||
|
|
||||||
// 绘制航点
|
// 绘制航点
|
||||||
|
|
@ -1584,37 +1589,29 @@ const handlerDrawPoint = (e) => {
|
||||||
moveTool.destroy();
|
moveTool.destroy();
|
||||||
moveTool = null;
|
moveTool = null;
|
||||||
}
|
}
|
||||||
|
// 设置航线默认高度
|
||||||
let position = mars3d.LngLatPoint.fromCartesian(e.position);
|
let position = mars3d.LngLatPoint.fromCartesian(e.position);
|
||||||
|
|
||||||
let uuid = buildUUID();
|
let uuid = buildUUID();
|
||||||
|
|
||||||
|
// 获取默认航线高度
|
||||||
|
let globalHeight = props.templateKmlConfig.Folder.globalHeight;
|
||||||
|
|
||||||
// 航点三维模型
|
// 航点三维模型
|
||||||
let uavAngleGraphic = new mars3d.graphic.ModelEntity({
|
let uavAngleGraphic = new mars3d.graphic.ModelEntity({
|
||||||
id:uuid,
|
id:uuid,
|
||||||
name: "航向",
|
name: "航向",
|
||||||
position: [position._lng, position._lat, position._alt],
|
position: [position._lng, position._lat, globalHeight],
|
||||||
style: {
|
style: {
|
||||||
url: "/map/uav-angle.gltf",
|
url: "/map/uav-angle.gltf",
|
||||||
scale: 0.1,
|
scale: 0.1,
|
||||||
heading: 90,
|
heading:90,
|
||||||
distanceDisplayCondition: true,
|
distanceDisplayCondition: true,
|
||||||
distanceDisplayCondition_near: 0,
|
distanceDisplayCondition_near: 0,
|
||||||
distanceDisplayPoint: {
|
distanceDisplayPoint: {
|
||||||
color: "#00ff00",
|
color: "#00ff00",
|
||||||
pixelSize: 8
|
pixelSize: 8
|
||||||
},
|
|
||||||
label: {
|
|
||||||
text: "",
|
|
||||||
font_size: 18,
|
|
||||||
color: "#ffffff",
|
|
||||||
pixelOffsetY: -50,
|
|
||||||
distanceDisplayCondition: true,
|
|
||||||
distanceDisplayCondition_far: 10000,
|
|
||||||
distanceDisplayCondition_near: 0
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
attr: { remark: "示例1" }
|
|
||||||
})
|
})
|
||||||
graphicLayer.addGraphic(uavAngleGraphic)
|
graphicLayer.addGraphic(uavAngleGraphic)
|
||||||
|
|
||||||
|
|
@ -1637,8 +1634,8 @@ const handlerDrawPoint = (e) => {
|
||||||
let lineGraphic = new mars3d.graphic.PolylineEntity({
|
let lineGraphic = new mars3d.graphic.PolylineEntity({
|
||||||
id: 'line' + uuid,
|
id: 'line' + uuid,
|
||||||
positions: [
|
positions: [
|
||||||
[position._lng, position._lat, position._alt],
|
[position._lng, position._lat, globalHeight],
|
||||||
[position._lng, position._lat, 0],
|
[position._lng, position._lat, 0],
|
||||||
],
|
],
|
||||||
style: {
|
style: {
|
||||||
color: '#f5f5f5',
|
color: '#f5f5f5',
|
||||||
|
|
@ -1653,27 +1650,76 @@ const handlerDrawPoint = (e) => {
|
||||||
name: '航点',
|
name: '航点',
|
||||||
lng: position._lng,
|
lng: position._lng,
|
||||||
lat: position._lat,
|
lat: position._lat,
|
||||||
alt: position._alt,
|
alt: globalHeight,
|
||||||
aircraftHorizontalAngle: 0,
|
aircraftHorizontalAngle: 0,
|
||||||
cameraHorizontalAngle: 0,
|
cameraHorizontalAngle: 0,
|
||||||
cameraVerticalAngle: 0,
|
cameraVerticalAngle: 0,
|
||||||
focalLength: 2,
|
focalLength: 2,
|
||||||
actions:[],
|
actions:[
|
||||||
|
{ // 设置无人机偏航角
|
||||||
|
"name":"飞行器偏航角",
|
||||||
|
"value":"rotateYaw",
|
||||||
|
"type":"action",
|
||||||
|
"config":{
|
||||||
|
"actionId": null,
|
||||||
|
"actionActuatorFunc": "rotateYaw",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"aircraftHeading": 0,
|
||||||
|
"aircraftPathMode": "counterClockwise"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},{ // 设置旋转云台俯仰角
|
||||||
|
"name":"云台俯仰角",
|
||||||
|
"value":"gimbalRotate",
|
||||||
|
"type":"action",
|
||||||
|
"config":{
|
||||||
|
"actionId": 3,
|
||||||
|
"actionActuatorFunc": "gimbalRotate",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"gimbalHeadingYawBase": "north",
|
||||||
|
"gimbalRotateMode": "absoluteAngle",
|
||||||
|
"gimbalPitchRotateEnable": 1,
|
||||||
|
"gimbalPitchRotateAngle": 0,
|
||||||
|
"gimbalRollRotateEnable": 0,
|
||||||
|
"gimbalRollRotateAngle": 0,
|
||||||
|
"gimbalYawRotateEnable": 0,
|
||||||
|
"gimbalYawRotateAngle": 0,
|
||||||
|
"gimbalRotateTimeEnable": 0,
|
||||||
|
"gimbalRotateTime": 0,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},{ // 调整相机焦距
|
||||||
|
"name":"相机焦距",
|
||||||
|
"value":"zoom",
|
||||||
|
"type":"action",
|
||||||
|
"config":{
|
||||||
|
"actionId": null,
|
||||||
|
"actionActuatorFunc": "zoom",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"focalLength": 24,
|
||||||
|
"isUseFocalFactor": 0,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
};
|
};
|
||||||
airPoints.value?.push(airPointInfo);
|
airPoints.value?.push(airPointInfo);
|
||||||
|
|
||||||
uavPoints.value.push(graphic);
|
uavPoints.value.push(graphic);
|
||||||
|
|
||||||
// 当前航点
|
// 当前航点
|
||||||
currentAirPoint.value = airPoints.value[airPoints.value?.length - 1];
|
currentAirPoint.value = airPoints.value[airPoints.value?.length - 1];
|
||||||
|
|
||||||
|
// 更新镜头
|
||||||
|
handlerDrawCamera(airPointInfo);
|
||||||
|
|
||||||
// 更新航线
|
// 更新航线
|
||||||
handlerDrawLine();
|
handlerDrawLine();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 绘制镜头
|
// 绘制镜头
|
||||||
const handlerDrawCamera = (e) => {
|
const handlerDrawCamera = (e) => {
|
||||||
|
|
||||||
// 判断是否已经添加
|
// 判断是否已经添加
|
||||||
const graphic = graphicLayer.getGraphicById("cameraGraphic");
|
const graphic = graphicLayer.getGraphicById("cameraGraphic");
|
||||||
if(graphic){ // 如果存在更新数据
|
if(graphic){ // 如果存在更新数据
|
||||||
|
|
@ -1692,8 +1738,8 @@ const handlerDrawCamera = (e) => {
|
||||||
topSteps: 2,
|
topSteps: 2,
|
||||||
flat: true,
|
flat: true,
|
||||||
cameraHpr: true,
|
cameraHpr: true,
|
||||||
heading:e.aircraftHorizontalAngle,
|
heading:e.aircraftHorizontalAngle - 90, // 偏航角
|
||||||
pitch: e.cameraVerticalAngle+90, // 俯仰角 0 - 360度
|
pitch: e.cameraVerticalAngle - 90, // 俯仰角 0 - 360度
|
||||||
roll: 0,
|
roll: 0,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -1712,8 +1758,8 @@ const handlerDrawCamera = (e) => {
|
||||||
topShow: true,
|
topShow: true,
|
||||||
topSteps: 2,
|
topSteps: 2,
|
||||||
cameraHpr: true,
|
cameraHpr: true,
|
||||||
heading:e.aircraftHorizontalAngle,
|
heading:e.aircraftHorizontalAngle - 90,
|
||||||
pitch: e.cameraVerticalAngle+90, // 俯仰角 0 - 360度
|
pitch: e.cameraVerticalAngle - 90, // 俯仰角 0 - 360度
|
||||||
roll: 0,
|
roll: 0,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -1733,24 +1779,14 @@ const updateAirPoint = (e) => {
|
||||||
style: {
|
style: {
|
||||||
url: "/map/uav-angle.gltf",
|
url: "/map/uav-angle.gltf",
|
||||||
scale: 0.1,
|
scale: 0.1,
|
||||||
heading: e.aircraftHorizontalAngle,
|
heading: e.aircraftHorizontalAngle + 90,
|
||||||
distanceDisplayCondition: true,
|
distanceDisplayCondition: true,
|
||||||
distanceDisplayCondition_near: 0,
|
distanceDisplayCondition_near: 0,
|
||||||
distanceDisplayPoint: {
|
distanceDisplayPoint: {
|
||||||
color: "#00ff00",
|
color: "#00ff00",
|
||||||
pixelSize: 8
|
pixelSize: 8
|
||||||
},
|
|
||||||
label: {
|
|
||||||
text: "",
|
|
||||||
font_size: 18,
|
|
||||||
color: "#ffffff",
|
|
||||||
pixelOffsetY: -50,
|
|
||||||
distanceDisplayCondition: true,
|
|
||||||
distanceDisplayCondition_far: 10000,
|
|
||||||
distanceDisplayCondition_near: 0
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
attr: { remark: "示例1" }
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1816,27 +1852,73 @@ const updateAirPoint = (e) => {
|
||||||
handlerDrawLine();
|
handlerDrawLine();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 航点动作参数改变
|
||||||
|
const paramChagne = (info) => {
|
||||||
|
console.log("info1232",info);
|
||||||
|
|
||||||
|
// 判断事件类型
|
||||||
|
if(info.value == 'rotateYaw'){ // 飞行器偏航角
|
||||||
|
|
||||||
|
// 设置参数
|
||||||
|
currentAirPoint.value.aircraftHorizontalAngle = info.config.actionActuatorFuncParam.aircraftHeading;
|
||||||
|
|
||||||
|
// 更新镜头
|
||||||
|
handlerDrawCamera(currentAirPoint.value);
|
||||||
|
|
||||||
|
// 更新航点
|
||||||
|
updateAirPoint(currentAirPoint.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(info.value == "gimbalRotate"){ // 云台俯仰角
|
||||||
|
|
||||||
|
// 设置参数
|
||||||
|
currentAirPoint.value.cameraVerticalAngle = info.config.actionActuatorFuncParam.gimbalPitchRotateAngle
|
||||||
|
// 更新镜头
|
||||||
|
handlerDrawCamera(currentAirPoint.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 事件处理
|
||||||
|
const updateCamera = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// 删除航点
|
// 删除航点
|
||||||
const deleteAirPoint = (e) => {
|
const deleteAirPoint = (e) => {
|
||||||
let id = e.graphic.id;
|
let id = e.graphic.id;
|
||||||
|
|
||||||
// 删除航点
|
// 删除航点
|
||||||
let point = graphicLayer.getGraphicById(id);
|
let uavModel = graphicLayer.getGraphicById(id);
|
||||||
if (point) {
|
if (uavModel) {
|
||||||
graphicLayer.removeGraphic(point);
|
graphicLayer.removeGraphic(uavModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除相机
|
// 删除相机
|
||||||
let camera = graphicLayer.getGraphicById('camera' + id);
|
let camera = graphicLayer.getGraphicById("cameraGraphic");
|
||||||
if (camera) {
|
if (camera) {
|
||||||
graphicLayer.removeGraphic(camera);
|
graphicLayer.removeGraphic(camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除贴地点
|
||||||
|
let point = lineGroundPointLayer.getGraphicById("line"+id);
|
||||||
|
if (point) {
|
||||||
|
lineGroundPointLayer.removeGraphic(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除连接线
|
||||||
|
let line = stickGroundPointLayer.getGraphicById("stick"+id);
|
||||||
|
if (line) {
|
||||||
|
stickGroundPointLayer.removeGraphic(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除数据
|
// 删除数据
|
||||||
airPoints.value?.forEach((item, index) => {
|
airPoints.value?.forEach((item, index) => {
|
||||||
if (item.id == id) {
|
if (item.id == id) {
|
||||||
airPoints.value?.splice(index, 1);
|
airPoints.value?.splice(index, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 更新航线
|
// 更新航线
|
||||||
|
|
@ -2511,11 +2593,9 @@ function addRectSensor(route) {
|
||||||
|
|
||||||
/////////////////////////////////动作处理//////////////////////////////////////
|
/////////////////////////////////动作处理//////////////////////////////////////
|
||||||
const addAction = (action) => {
|
const addAction = (action) => {
|
||||||
// 当前航点添加动作
|
|
||||||
|
|
||||||
console.log("action",action);
|
// 当前航点添加动作
|
||||||
currentAirPoint.value.actions.push(action);
|
currentAirPoint.value.actions.push(JSON.parse(JSON.stringify(action)));
|
||||||
console.log("currentAirPoint",currentAirPoint.value)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<template>
|
||||||
|
<div class="params-item">
|
||||||
|
<div class="params-label">间隔距离:</div>
|
||||||
|
<div class="params-value">
|
||||||
|
<a-input-number v-model:value="props.params.hoverTime"></a-input-number>
|
||||||
|
</div>
|
||||||
|
<div class="params-unit">米</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {defineProps,defineComponent,defineOptions} from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps(["params"])
|
||||||
|
|
||||||
|
|
||||||
|
defineComponent({
|
||||||
|
name: 'multipleDistance'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.params-item{
|
||||||
|
width:100%;
|
||||||
|
display: flex;
|
||||||
|
gap:20px;
|
||||||
|
}
|
||||||
|
.params-item .params-label{
|
||||||
|
line-height:30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-item .params-value{
|
||||||
|
flex:1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.params-item .params-unit{
|
||||||
|
line-height:30px;
|
||||||
|
padding:0px 5px 0px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .ant-input-number{
|
||||||
|
color:#fff!important;
|
||||||
|
background:#3F4150!important;
|
||||||
|
border:0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .ant-input-number-input{
|
||||||
|
color:#fff!important;
|
||||||
|
border:0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -226,13 +226,11 @@
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
const onPageChange = (e)=>{
|
const onPageChange = (e)=>{
|
||||||
pageQuery.value.page = e;
|
pageQuery.value.page = e;
|
||||||
getTaskList();
|
getTaskList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 任务状态
|
// 任务状态
|
||||||
const planStatusOptions = ref([
|
const planStatusOptions = ref([
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,10 @@ export const calculateHeight = (gsd,uavModel) => {
|
||||||
|
|
||||||
// 飞行高度= GSD(cm)×实际焦距(mm)/像元尺寸(um)
|
// 飞行高度= GSD(cm)×实际焦距(mm)/像元尺寸(um)
|
||||||
|
|
||||||
let abc = (gsd * uavModel['focalLength'] / uavModel['pixelLength']);
|
height = (gsd * uavModel['focalLength'] / uavModel['pixelLength']);
|
||||||
|
|
||||||
console.log("abc",abc);
|
|
||||||
|
|
||||||
height = ( (gsd / 100) * (uavModel['focalLength'] / 1000) * uavModel['imageWidth'] ) / ( uavModel['sensorLength'] / 1000 );
|
// height = ( (gsd / 100) * (uavModel['focalLength'] / 1000) * uavModel['imageWidth'] ) / ( uavModel['sensorLength'] / 1000 );
|
||||||
|
|
||||||
return height.toFixed(2);
|
return height.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
@ -30,8 +29,16 @@ export const calculateHeight = (gsd,uavModel) => {
|
||||||
|
|
||||||
// 输入高度计算gsd
|
// 输入高度计算gsd
|
||||||
export const calculateGsd = (height,uavModel) => {
|
export const calculateGsd = (height,uavModel) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let gsd = 0;
|
let gsd = 0;
|
||||||
gsd = ( (height*1000) * uavModel['sensorLength'] ) / (uavModel['focalLength'] * uavModel['imageWidth']) / 10;
|
|
||||||
|
gsd = (uavModel['pixelLength'] * height) / uavModel['focalLength'] ;
|
||||||
|
|
||||||
|
|
||||||
|
// gsd = ( (height*1000) * uavModel['sensorLength'] ) / (uavModel['focalLength'] * uavModel['imageWidth']) / 10;
|
||||||
|
|
||||||
return gsd.toFixed(2);
|
return gsd.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export const airPointActions = {
|
||||||
"gimbalHeadingYawBase": "north",
|
"gimbalHeadingYawBase": "north",
|
||||||
"gimbalRotateMode": "absoluteAngle",
|
"gimbalRotateMode": "absoluteAngle",
|
||||||
"gimbalPitchRotateEnable": 1,
|
"gimbalPitchRotateEnable": 1,
|
||||||
"gimbalPitchRotateAngle": -65.7,
|
"gimbalPitchRotateAngle": 0,
|
||||||
"gimbalRollRotateEnable": 0,
|
"gimbalRollRotateEnable": 0,
|
||||||
"gimbalRollRotateAngle": 0,
|
"gimbalRollRotateAngle": 0,
|
||||||
"gimbalYawRotateEnable": 0,
|
"gimbalYawRotateEnable": 0,
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
|
||||||
|
// 面状航线默认template.kml数据
|
||||||
|
export const templateKml = {
|
||||||
|
"author": 17861857725,
|
||||||
|
"createTime": 1749689844431,
|
||||||
|
"updateTime": 1753241338101,
|
||||||
|
"missionConfig": {
|
||||||
|
"flyToWaylineMode": "pointToPoint",
|
||||||
|
"finishAction": "goHome",
|
||||||
|
"exitOnRCLost": "goContinue",
|
||||||
|
"executeRCLostAction": "goBack",
|
||||||
|
"takeOffSecurityHeight": 20,
|
||||||
|
"takeOffRefPoint": "",
|
||||||
|
"takeOffRefPointAGLHeight": 4.169064385,
|
||||||
|
"globalTransitionalSpeed": 15,
|
||||||
|
"globalRTHHeight": 100,
|
||||||
|
"droneInfo": {
|
||||||
|
"droneEnumValue": 100,
|
||||||
|
"droneSubEnumValue": 1
|
||||||
|
},
|
||||||
|
"autoRerouteInfo": {
|
||||||
|
"transitionalAutoRerouteMode": 1,
|
||||||
|
"missionAutoRerouteMode": 1
|
||||||
|
},
|
||||||
|
"waylineAvoidLimitAreaMode": 0,
|
||||||
|
"payloadInfo": {
|
||||||
|
"payloadEnumValue": 99,
|
||||||
|
"payloadSubEnumValue": 0,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Folder": {
|
||||||
|
"templateType": "mapping2d",
|
||||||
|
"templateId": 0,
|
||||||
|
"waylineCoordinateSysParam": {
|
||||||
|
"coordinateMode": "WGS84",
|
||||||
|
"heightMode": "EGM96",
|
||||||
|
"globalShootHeight": 90,
|
||||||
|
"surfaceFollowModeEnable": 1,
|
||||||
|
"isRealtimeSurfaceFollow": 0,
|
||||||
|
"surfaceRelativeHeight": 90,
|
||||||
|
"dsmFile": "wpmz/res/dsm/wgs84_ASTGTMV003_N35E118_dem_7.tif"
|
||||||
|
},
|
||||||
|
"autoFlightSpeed": 12.7,
|
||||||
|
"Placemark": {
|
||||||
|
"caliFlightEnable": 0,
|
||||||
|
"elevationOptimizeEnable": 1,
|
||||||
|
"smartObliqueEnable": 0,
|
||||||
|
"quickOrthoMappingEnable": 0,
|
||||||
|
"facadeWaylineEnable": 0,
|
||||||
|
"isLookAtSceneSet": 0,
|
||||||
|
"shootType": "time",
|
||||||
|
"direction": 83,
|
||||||
|
"margin": 0,
|
||||||
|
"efficiencyFlightModeEnable": 0,
|
||||||
|
"overlap": {
|
||||||
|
"orthoCameraOverlapH": 80,
|
||||||
|
"orthoCameraOverlapW": 70,
|
||||||
|
"inclinedCameraOverlapH": 80,
|
||||||
|
"inclinedCameraOverlapW": 70
|
||||||
|
},
|
||||||
|
"Polygon": {
|
||||||
|
"outerBoundaryIs": {
|
||||||
|
"LinearRing": {
|
||||||
|
"coordinates": "118.293794766158,35.1353688096117,0\n 118.295429169407,35.1353304409052,0\n 118.295487507293,35.1332925168381,0\n 118.293672196844,35.1331918267775,0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ellipsoidHeight": 90,
|
||||||
|
"height": 90
|
||||||
|
},
|
||||||
|
"payloadParam": {
|
||||||
|
"payloadPositionIndex": 0,
|
||||||
|
"focusMode": "firstPoint",
|
||||||
|
"meteringMode": "average",
|
||||||
|
"returnMode": "singleReturnStrongest",
|
||||||
|
"samplingRate": 240000,
|
||||||
|
"scanningMode": "repetitive",
|
||||||
|
"imageFormat": "visable",
|
||||||
|
"photoSize": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 面状航线默认wayline.wpml数据
|
||||||
|
export const waylineWpml = {
|
||||||
|
"missionConfig": {
|
||||||
|
"flyToWaylineMode": "pointToPoint",
|
||||||
|
"finishAction": "goHome",
|
||||||
|
"exitOnRCLost": "goContinue",
|
||||||
|
"executeRCLostAction": "goBack",
|
||||||
|
"takeOffSecurityHeight": 20,
|
||||||
|
"globalTransitionalSpeed": 15,
|
||||||
|
"globalRTHHeight": 100,
|
||||||
|
"droneInfo": {
|
||||||
|
"droneEnumValue": 100,
|
||||||
|
"droneSubEnumValue": 1
|
||||||
|
},
|
||||||
|
"autoRerouteInfo": {
|
||||||
|
"transitionalAutoRerouteMode": 1,
|
||||||
|
"missionAutoRerouteMode": 1
|
||||||
|
},
|
||||||
|
"waylineAvoidLimitAreaMode": 0,
|
||||||
|
"payloadInfo": {
|
||||||
|
"payloadEnumValue": 99,
|
||||||
|
"payloadSubEnumValue": 0,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Folder": {
|
||||||
|
"templateId": 0,
|
||||||
|
"executeHeightMode": "WGS84",
|
||||||
|
"waylineId": 0,
|
||||||
|
"distance": 1259.17163085938,
|
||||||
|
"duration": 145.652896165848,
|
||||||
|
"autoFlightSpeed": 12.7,
|
||||||
|
"startActionGroup": {
|
||||||
|
"action": [
|
||||||
|
{
|
||||||
|
"actionId": 0,
|
||||||
|
"actionActuatorFunc": "gimbalRotate",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"gimbalHeadingYawBase": "aircraft",
|
||||||
|
"gimbalRotateMode": "absoluteAngle",
|
||||||
|
"gimbalPitchRotateEnable": 1,
|
||||||
|
"gimbalPitchRotateAngle": -90,
|
||||||
|
"gimbalRollRotateEnable": 0,
|
||||||
|
"gimbalRollRotateAngle": 0,
|
||||||
|
"gimbalYawRotateEnable": 1,
|
||||||
|
"gimbalYawRotateAngle": 0,
|
||||||
|
"gimbalRotateTimeEnable": 0,
|
||||||
|
"gimbalRotateTime": 10,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionId": 1,
|
||||||
|
"actionActuatorFunc": "hover",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"hoverTime": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionId": 2,
|
||||||
|
"actionActuatorFunc": "setFocusType",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"cameraFocusType": "manual",
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionId": 3,
|
||||||
|
"actionActuatorFunc": "focus",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"focusX": 0,
|
||||||
|
"focusY": 0,
|
||||||
|
"focusRegionWidth": 0,
|
||||||
|
"focusRegionHeight": 0,
|
||||||
|
"isPointFocus": 0,
|
||||||
|
"isInfiniteFocus": 1,
|
||||||
|
"payloadPositionIndex": 0,
|
||||||
|
"isCalibrationFocus": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"actionId": 4,
|
||||||
|
"actionActuatorFunc": "hover",
|
||||||
|
"actionActuatorFuncParam": {
|
||||||
|
"hoverTime": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Placemark": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -97,6 +97,18 @@ export const missionConfigOptions = {
|
||||||
label:"悬停",
|
label:"悬停",
|
||||||
value:"hover"
|
value:"hover"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
globalWaypointTurnMode:[
|
||||||
|
{
|
||||||
|
label:"不过点,提前转弯",
|
||||||
|
value:"coordinateTurn"
|
||||||
|
},{
|
||||||
|
label:"直线飞行,到点停",
|
||||||
|
value:"toPointAndStopWithDiscontinuityCurvature"
|
||||||
|
},{
|
||||||
|
label:"平滑过点,提前转弯",
|
||||||
|
value:"toPointAndStopWithContinuityCurvature"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
|
||||||
|
// 航点航线默认template.kml数据
|
||||||
|
export const templateKml = {
|
||||||
|
"author": 17861857725,
|
||||||
|
"createTime": 1753927747220,
|
||||||
|
"updateTime": 1753928575789,
|
||||||
|
"missionConfig": {
|
||||||
|
"flyToWaylineMode": "safely",
|
||||||
|
"finishAction": "goHome",
|
||||||
|
"exitOnRCLost": "goContinue",
|
||||||
|
"executeRCLostAction": "goBack",
|
||||||
|
"takeOffSecurityHeight": 20,
|
||||||
|
"takeOffRefPoint": "35.134614,118.296656,77.867669",
|
||||||
|
"takeOffRefPointAGLHeight": 0,
|
||||||
|
"globalTransitionalSpeed": 15,
|
||||||
|
"globalRTHHeight": 100,
|
||||||
|
"droneInfo": {
|
||||||
|
"droneEnumValue": 100,
|
||||||
|
"droneSubEnumValue": 1
|
||||||
|
},
|
||||||
|
"waylineAvoidLimitAreaMode": 0,
|
||||||
|
"payloadInfo": {
|
||||||
|
"payloadEnumValue": 99,
|
||||||
|
"payloadSubEnumValue": 2,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Folder": {
|
||||||
|
"templateType": "waypoint",
|
||||||
|
"templateId": 0,
|
||||||
|
"waylineCoordinateSysParam": {
|
||||||
|
"coordinateMode": "WGS84",
|
||||||
|
"heightMode": "EGM96"
|
||||||
|
},
|
||||||
|
"autoFlightSpeed": 10,
|
||||||
|
"globalHeight": 124,
|
||||||
|
"caliFlightEnable": 0,
|
||||||
|
"gimbalPitchMode": "manual",
|
||||||
|
"globalWaypointHeadingParam": {
|
||||||
|
"waypointHeadingMode": "followWayline",
|
||||||
|
"waypointHeadingAngle": 0,
|
||||||
|
"waypointPoiPoint": "0.000000,0.000000,0.000000",
|
||||||
|
"waypointHeadingPathMode": "followBadArc",
|
||||||
|
"waypointHeadingPoiIndex": 0
|
||||||
|
},
|
||||||
|
"globalWaypointTurnMode": "toPointAndStopWithDiscontinuityCurvature",
|
||||||
|
"globalUseStraightLine": 1,
|
||||||
|
"Placemark": [],
|
||||||
|
"payloadParam": {
|
||||||
|
"payloadPositionIndex": 0,
|
||||||
|
"focusMode": "firstPoint",
|
||||||
|
"meteringMode": "average",
|
||||||
|
"returnMode": "singleReturnStrongest",
|
||||||
|
"samplingRate": 240000,
|
||||||
|
"scanningMode": "repetitive",
|
||||||
|
"imageFormat": "visable,ir",
|
||||||
|
"photoSize": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 航点航线默认wayline.wpml数据
|
||||||
|
export const waylineWpml = {
|
||||||
|
"missionConfig": {
|
||||||
|
"flyToWaylineMode": "safely",
|
||||||
|
"finishAction": "goHome",
|
||||||
|
"exitOnRCLost": "goContinue",
|
||||||
|
"executeRCLostAction": "goBack",
|
||||||
|
"takeOffSecurityHeight": 20,
|
||||||
|
"globalTransitionalSpeed": 15,
|
||||||
|
"globalRTHHeight": 100,
|
||||||
|
"droneInfo": {
|
||||||
|
"droneEnumValue": 100,
|
||||||
|
"droneSubEnumValue": 1
|
||||||
|
},
|
||||||
|
"waylineAvoidLimitAreaMode": 0,
|
||||||
|
"payloadInfo": {
|
||||||
|
"payloadEnumValue": 99,
|
||||||
|
"payloadSubEnumValue": 2,
|
||||||
|
"payloadPositionIndex": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Folder": {
|
||||||
|
"templateId": 0,
|
||||||
|
"executeHeightMode": "WGS84",
|
||||||
|
"waylineId": 0,
|
||||||
|
"distance": 4453.73876953125,
|
||||||
|
"duration": 636.023902893066,
|
||||||
|
"autoFlightSpeed": 10,
|
||||||
|
"Placemark": []
|
||||||
|
}
|
||||||
|
}
|
||||||