Merge remote-tracking branch 'origin/master'
5 files modified
7 files added
| | |
| | | # ws地址 |
| | | VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws |
| | | |
| | | # 航线文件地址 |
| | | VITE_APP_AIRLINE_URL = https://wrj.shuixiongit.com/minio/cloud-bucket |
| | | |
| | |
| | | "js-base64": "^3.7.4", |
| | | "js-cookie": "^3.0.0", |
| | | "js-md5": "^0.7.3", |
| | | "jszip": "^3.10.1", |
| | | "lodash": "^4.17.21", |
| | | "nprogress": "^0.2.0", |
| | | "postcss-pxtorem": "^6.1.0", |
| | |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/core-util-is": { |
| | | "version": "1.0.3", |
| | | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", |
| | | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" |
| | | }, |
| | | "node_modules/cors": { |
| | | "version": "2.8.5", |
| | | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", |
| | |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/immediate": { |
| | | "version": "3.0.6", |
| | | "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", |
| | | "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" |
| | | }, |
| | | "node_modules/immer": { |
| | | "version": "9.0.21", |
| | | "resolved": "https://registry.npmmirror.com/immer/-/immer-9.0.21.tgz", |
| | |
| | | "node_modules/inherits": { |
| | | "version": "2.0.4", |
| | | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", |
| | | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", |
| | | "dev": true |
| | | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" |
| | | }, |
| | | "node_modules/inherits-browser": { |
| | | "version": "0.1.0", |
| | |
| | | "node_modules/isarray": { |
| | | "version": "1.0.0", |
| | | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", |
| | | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", |
| | | "dev": true |
| | | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" |
| | | }, |
| | | "node_modules/isobject": { |
| | | "version": "2.1.0", |
| | |
| | | "graceful-fs": "^4.1.6" |
| | | } |
| | | }, |
| | | "node_modules/jszip": { |
| | | "version": "3.10.1", |
| | | "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", |
| | | "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", |
| | | "dependencies": { |
| | | "lie": "~3.3.0", |
| | | "pako": "~1.0.2", |
| | | "readable-stream": "~2.3.6", |
| | | "setimmediate": "^1.0.5" |
| | | } |
| | | }, |
| | | "node_modules/jszip/node_modules/pako": { |
| | | "version": "1.0.11", |
| | | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", |
| | | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" |
| | | }, |
| | | "node_modules/jszip/node_modules/readable-stream": { |
| | | "version": "2.3.8", |
| | | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", |
| | | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", |
| | | "dependencies": { |
| | | "core-util-is": "~1.0.0", |
| | | "inherits": "~2.0.3", |
| | | "isarray": "~1.0.0", |
| | | "process-nextick-args": "~2.0.0", |
| | | "safe-buffer": "~5.1.1", |
| | | "string_decoder": "~1.1.1", |
| | | "util-deprecate": "~1.0.1" |
| | | } |
| | | }, |
| | | "node_modules/jszip/node_modules/safe-buffer": { |
| | | "version": "5.1.2", |
| | | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", |
| | | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" |
| | | }, |
| | | "node_modules/jszip/node_modules/string_decoder": { |
| | | "version": "1.1.1", |
| | | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", |
| | | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", |
| | | "dependencies": { |
| | | "safe-buffer": "~5.1.0" |
| | | } |
| | | }, |
| | | "node_modules/kdbush": { |
| | | "version": "4.0.2", |
| | | "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", |
| | |
| | | "version": "2.0.0", |
| | | "resolved": "https://registry.npmjs.org/lerc/-/lerc-2.0.0.tgz", |
| | | "integrity": "sha512-7qo1Mq8ZNmaR4USHHm615nEW2lPeeWJ3bTyoqFbd35DLx0LUH7C6ptt5FDCTAlbIzs3+WKrk5SkJvw8AFDE2hg==" |
| | | }, |
| | | "node_modules/lie": { |
| | | "version": "3.3.0", |
| | | "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", |
| | | "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", |
| | | "dependencies": { |
| | | "immediate": "~3.0.5" |
| | | } |
| | | }, |
| | | "node_modules/loader-utils": { |
| | | "version": "1.4.2", |
| | |
| | | "node": ">=6" |
| | | } |
| | | }, |
| | | "node_modules/process-nextick-args": { |
| | | "version": "2.0.1", |
| | | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", |
| | | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" |
| | | }, |
| | | "node_modules/protobufjs": { |
| | | "version": "7.4.0", |
| | | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", |
| | |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/setimmediate": { |
| | | "version": "1.0.5", |
| | | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", |
| | | "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" |
| | | }, |
| | | "node_modules/side-channel": { |
| | | "version": "1.1.0", |
| | |
| | | "node_modules/util-deprecate": { |
| | | "version": "1.0.2", |
| | | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", |
| | | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", |
| | | "dev": true |
| | | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" |
| | | }, |
| | | "node_modules/vary": { |
| | | "version": "1.1.2", |
| | |
| | | }) |
| | | } |
| | | |
| | | // 获取航线列表 |
| | | export const getWaylineList = (params) => { |
| | | return request({ |
| | | url: `/drone-device-core/wayline/api/v1/workspaces/getWaylineFileListByArea`, |
| | | method: 'get', |
| | | params |
| | | }) |
| | | } |
| | | |
| | | // 获取可飞行机巢列表 |
| | | export const getFlyingNestBy = (data) => { |
| | | return request({ |
| | | url: `/drone-device-core/manage/api/v1/devices/getFlyingNestBy?current=${data.page}&size=${data.limit}`, |
| | | method: 'post', |
| | | data: { |
| | | wayline_id: data.wayline_id, |
| | | type: data.type |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | // 机场发布功能 |
| | | export const createTask = (data) => { |
| | | return request({ |
| | | url: `/drone-device-core/wayline/waylineJobInfo/createTask`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="任务算法"> |
| | | <el-select v-model="searchForm.ai_type" placeholder="请选择算法" clearable> |
| | | <!-- <el-select v-model="searchForm.ai_type" placeholder="请选择算法" clearable> |
| | | <el-option v-for="item in taskAlgorithm" :key="item.id" :label="item.dictValue" :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-select> --> |
| | | <TaskAlgorithmBusiness :showAlgorithm="true" @algorithmChange="algorithmChange"/> |
| | | </el-form-item> |
| | | </div> |
| | | <div class="search-row"> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="任务类型"> |
| | | <el-select v-model="searchForm.industry_type" placeholder="请选择类型" clearable> |
| | | <!-- <el-select v-model="searchForm.industry_type" placeholder="请选择类型" clearable> |
| | | <el-option v-for="item in taskBusiness" :key="item.id" :label="item.dictValue" :value="item.dictKey" /> |
| | | </el-select> |
| | | </el-select> --> |
| | | <TaskAlgorithmBusiness :showBusiness="true" @businessChange="businessChange"/> |
| | | </el-form-item> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </template> |
| | | <script setup> |
| | | import { getDictionary, deptsByAreaCode, getDockInfo } from '@/api/home/common'; |
| | | import { deptsByAreaCode, getDockInfo } from '@/api/home/common'; |
| | | import TaskAlgorithmBusiness from './components/TaskAlgorithmBusiness.vue'; |
| | | |
| | | const isExpand = ref(false); |
| | | const toggleExpand = () => { |
| | |
| | | { label: '执行失败', value: 5 } |
| | | ]; |
| | | |
| | | const emit = defineEmits(['search']); |
| | | const emit = defineEmits(['search','addTask']); |
| | | |
| | | const handleSearch = () => { |
| | | emit('search', { |
| | |
| | | |
| | | // 新增任务 |
| | | const addTask = () => { |
| | | // 跳转新增任务页面 |
| | | window.open('/#/task/add'); |
| | | emit('addTask'); |
| | | }; |
| | | |
| | | let taskAlgorithm = ref([]); |
| | | let taskBusiness = ref([]); |
| | | // let taskAlgorithm = ref([]); |
| | | // let taskBusiness = ref([]); |
| | | |
| | | // 请求字典字段 |
| | | const requestDictionary = () => { |
| | | getDictionary('SF,HYLB').then((res) => { |
| | | if (res.code !== 0) { |
| | | // 处理数据 |
| | | taskAlgorithm.value = res.data.data['SF']; |
| | | taskBusiness.value = res.data.data['HYLB']; |
| | | } |
| | | }); |
| | | // const requestDictionary = () => { |
| | | // getDictionary('SF,HYLB').then((res) => { |
| | | // if (res.code !== 0) { |
| | | // // 处理数据 |
| | | // taskAlgorithm.value = res.data.data['SF']; |
| | | // taskBusiness.value = res.data.data['HYLB']; |
| | | // } |
| | | // }); |
| | | // }; |
| | | const algorithmChange = (val) => { |
| | | searchForm.ai_type = val; |
| | | }; |
| | | |
| | | const businessChange = (val) => { |
| | | searchForm.industry_type = val; |
| | | }; |
| | | |
| | | let deptData = ref([]); |
| | | // 所属部门信息 |
| | |
| | | |
| | | |
| | | onMounted(() => { |
| | | requestDictionary(); |
| | | // requestDictionary(); |
| | | getDeptsByAreaCode(); |
| | | requestDockInfo(); |
| | | }); |
| New file |
| | |
| | | <!-- 机巢列表详情 --> |
| | | <template> |
| | | <el-dialog |
| | | modal-class="add-task" |
| | | v-model="isShowAddTask" |
| | | title="新建任务" |
| | | :width="pxToRem(1500)" |
| | | :close-on-click-modal="false" |
| | | :destroy-on-close="true"> |
| | | <!-- <el-divider content-position="left">新建任务</el-divider> --> |
| | | <div class="task-contain"> |
| | | <div class="left"> |
| | | <div class="search"> |
| | | <div class="item">任务名称:<el-input v-model="searchForm.name" placeholder="请输入任务名称"></el-input></div> |
| | | <div class="item">任务日期: |
| | | <el-date-picker |
| | | v-model="searchForm.begin_time" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </div> |
| | | <div class="item">任务时间: |
| | | <!-- <el-time-picker |
| | | v-model="searchForm.execute_time_arr" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm"/> --> |
| | | </div> |
| | | <div class="item">选择航线: |
| | | <el-select |
| | | v-model="searchForm.file_id" |
| | | @change="getWayLineFile" |
| | | placeholder="请选择航线" |
| | | clearable> |
| | | <el-option |
| | | v-for="item in routeOptions" |
| | | :key="item.wayline_id" |
| | | :label="item.name" |
| | | :value="item.wayline_id"/> |
| | | </el-select> |
| | | </div> |
| | | <div class="item">关联算法: |
| | | <TaskAlgorithmBusiness :showAlgorithm="true" @algorithmChange="algorithmChange"/> |
| | | </div> |
| | | <div class="item">任务描述:<el-input v-model="searchForm.remark" placeholder="请输入任务名称"></el-input></div> |
| | | </div> |
| | | <div class="lines"> |
| | | <div class="wayline-type"> |
| | | <el-radio-group v-model="searchForm.wayline_type"> |
| | | <el-radio label="1">单点航线</el-radio> |
| | | <el-radio label="2">智能规划选区</el-radio> |
| | | </el-radio-group> |
| | | </div> |
| | | <TaskMap class="wayline-map" :wayLineFile="wayLineFile"/> |
| | | </div> |
| | | </div> |
| | | <div class="right"> |
| | | <TaskTable :waylineId="waylineId" :waylineType="waylineType" @update:selected="handleSelected" /> |
| | | <div class="btn"> |
| | | <el-button type="primary" @click="cancel">取消</el-button> |
| | | <el-button type="primary" @click="submitClick">发布</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { pxToRem } from '@/utils/rem'; |
| | | import { getWaylineList, createTask } from '@/api/home/task'; |
| | | import TaskAlgorithmBusiness from '../components/TaskAlgorithmBusiness.vue'; |
| | | import TaskMap from './TaskMap.vue'; |
| | | import TaskTable from './TaskTable.vue'; |
| | | |
| | | const rangDate = ref([]); |
| | | // 航线ID |
| | | let waylineId = ref(''); |
| | | // 航线文件 |
| | | let wayLineFile = ref(''); |
| | | // 航线类型 |
| | | let waylineType = ref(0); |
| | | |
| | | const searchForm = reactive({ |
| | | name: '', |
| | | ai_type: [], |
| | | file_id: '', |
| | | begin_time: '', |
| | | end_time: '', |
| | | execute_time_arr: '', |
| | | remark: '', |
| | | type: waylineType.value, |
| | | dock_sns: [], |
| | | }); |
| | | const isShowAddTask = defineModel('show'); |
| | | |
| | | // 获取航线列表数据 |
| | | const routeOptions = ref([]); |
| | | const getRouteList = async () => { |
| | | const res = await getWaylineList(); |
| | | if (res.data.code === 0) { |
| | | routeOptions.value = res.data.data; |
| | | } |
| | | }; |
| | | const algorithmChange = (val) => { |
| | | searchForm.ai_type = val; |
| | | }; |
| | | |
| | | // 获取航线文件 |
| | | const getWayLineFile = async (val) => { |
| | | waylineId.value = val; |
| | | const currentRoute = routeOptions.value.find(item => item.wayline_id === val); |
| | | wayLineFile.value = currentRoute.object_key; |
| | | }; |
| | | // 获取选中机场列表数据,并且发布 |
| | | const handleSelected = (val) => { |
| | | searchForm.dock_sns = val.map(item => item.device_sn); |
| | | }; |
| | | const emit = defineEmits(['refresh']); |
| | | // 提交 |
| | | const submitClick = () => { |
| | | searchForm.end_time = `${searchForm.begin_time} 23:59:59`; |
| | | searchForm.begin_time = `${searchForm.begin_time} 00:00:00`; |
| | | |
| | | createTask(searchForm).then((res) => { |
| | | console.log(res); |
| | | if (res.code === 0) { |
| | | ElMessage.success('任务创建成功'); |
| | | // 关闭当前窗口,刷新任务管理列表 |
| | | isShowAddTask.value = false; |
| | | emit('refresh'); |
| | | } |
| | | }); |
| | | }; |
| | | const cancel = () => { |
| | | isShowAddTask.value = false; |
| | | // 清除搜索数据 |
| | | searchForm.name = ''; |
| | | searchForm.ai_type = []; |
| | | searchForm.file_id = ''; |
| | | searchForm.begin_time = ''; |
| | | searchForm.end_time = ''; |
| | | searchForm.execute_time_arr = ''; |
| | | searchForm.remark = ''; |
| | | searchForm.dock_sns = []; |
| | | rangDate.value = []; |
| | | waylineId.value = ''; |
| | | wayLineFile.value = ''; |
| | | }; |
| | | onMounted(() => { |
| | | getRouteList(); |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .add-task{ |
| | | .el-pagination { |
| | | text-align: left; |
| | | padding: 20px; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-contain { |
| | | display: flex; |
| | | .left { |
| | | width: 70%; |
| | | .search { |
| | | display: grid; |
| | | grid-template-columns: repeat(3, 1fr); |
| | | grid-template-rows: repeat(2, 1fr); |
| | | gap: 30px; // 增加间距使布局更合理 |
| | | margin-bottom: 8px; // 添加底部间距 |
| | | .item { |
| | | display: flex; |
| | | align-items: center; |
| | | :deep(.el-input), |
| | | :deep(.el-select), |
| | | :deep(.el-date-picker), |
| | | :deep(.el-time-picker) { |
| | | width: 240px; |
| | | margin-left: 10px; |
| | | } |
| | | :deep(.el-date-editor.el-input__wrapper) { |
| | | width: 200px; // 调整日期选择器宽度 |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .right { |
| | | width: 30%; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <!-- 任务统计表格 --> |
| | | <template> |
| | | <SearchBox @search="searchClick"></SearchBox> |
| | | <SearchBox @search="searchClick" @addTask="handleAddTask"></SearchBox> |
| | | <div class="task-intermediate-content"> |
| | | <el-table :data="jobListData" style="width: 100%" height="calc(100vh - 180px)"> |
| | | <el-table-column label="序号" width="60"> |
| | |
| | | /> |
| | | </div> |
| | | </div> |
| | | <AddTask v-model:show="isShowAddTask" @refresh="searchClick"/> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import SearchBox from '../SearchBox.vue'; |
| | | import AddTask from './AddTask.vue'; |
| | | import { jobList } from '@/api/home/task'; |
| | | |
| | | const jobListParams = reactive({ |
| | |
| | | getJobList(); |
| | | }; |
| | | |
| | | // 新建任务 |
| | | const isShowAddTask = ref(false); |
| | | const handleAddTask = () => { |
| | | isShowAddTask.value = true; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getJobList(); |
| | | }); |
| New file |
| | |
| | | <template> |
| | | <div id="taskMap" /> |
| | | </template> |
| | | <script setup> |
| | | import * as Cesium from 'cesium' |
| | | import { Cartesian3, Math as CesiumMath, Terrain, Viewer } from 'cesium' |
| | | import AmapMercatorTilingScheme from '@/utils/cesium/AmapMercatorTilingScheme' |
| | | import { analyzeKmzFile, removeTextKey, XMLToJSON } from '@/utils/cesium/kmz' |
| | | import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial' |
| | | import lineImg from '@/assets/images/arrow-right-blue.png'; |
| | | import Startingpointicon from '@/assets/images/Startingpointicon.png'; |
| | | import EndPointicon from '@/assets/images/EndPointicon.png'; |
| | | import uavImg from '@/assets/images/home/useUavHome/uavImg.png' |
| | | import { getCenterPoint } from '@/utils/cesium/mapUtil' |
| | | |
| | | const props = defineProps(['wayLineFile']) |
| | | |
| | | |
| | | const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({ |
| | | url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', |
| | | layer: 'tdtVecBasicLayer', |
| | | style: 'default', |
| | | format: 'image/png', |
| | | tileMatrixSetID: 'GoogleMapsCompatible', |
| | | subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], |
| | | maximumLevel: 18, |
| | | tilingScheme: new AmapMercatorTilingScheme(), |
| | | credit: 'amap_SL', |
| | | }) |
| | | let viewer = null |
| | | const init = () => { |
| | | viewer = new Viewer('taskMap', { |
| | | terrain: Terrain.fromWorldTerrain(), |
| | | infoBox: false, // 禁用沙箱,解决控制台报错 |
| | | animation: false, // 左下角的动画仪表盘 |
| | | baseLayerPicker: false, // 右上角的图层选择按钮 |
| | | geocoder: false, // 搜索框 |
| | | homeButton: false, // home按钮 |
| | | sceneModePicker: false, // 模式切换按钮 |
| | | timeline: false, // 底部的时间轴 |
| | | navigationHelpButton: false, // 右上角的帮助按钮, |
| | | selectionIndicator: false, // 是否显示选择指示器 |
| | | baseLayer: false, |
| | | fullscreenButton: false, |
| | | // sceneMode: Cesium.SceneMode.COLUMBUS_VIEW, |
| | | }) |
| | | viewer.imageryLayers.addImageryProvider(imageryProvider_ammapSL) |
| | | viewer.scene.morphTo2D(0); |
| | | } |
| | | |
| | | // 渲染线和点 |
| | | const renderingLine = lineObj => { |
| | | const positions = lineObj.Placemark.map(item => { |
| | | const [lon, lat] = item.Point.coordinates.split(',') |
| | | return Cartesian3.fromDegrees(Number(lon), Number(lat)) |
| | | }) |
| | | // viewer.entities.add({ |
| | | // position: positions[0], |
| | | // billboard: { |
| | | // image: new Cesium.ConstantProperty(uavImg), |
| | | // width: 24, |
| | | // height: 24, |
| | | // }, |
| | | // }); |
| | | viewer.entities.add({ |
| | | polyline: { |
| | | width: 4, |
| | | positions: positions, |
| | | material: new ImageTrailMaterial({ |
| | | color: { alpha: 1, blue: 1, green: 1, red: 1 }, |
| | | speed: 20, |
| | | image: lineImg, |
| | | repeat: { x: Math.floor(40), y: 1 }, |
| | | }), |
| | | clampToGround: false, |
| | | }, |
| | | }) |
| | | console.log('positions',positions) |
| | | positions.forEach((point, index) => { |
| | | let setting = {}; |
| | | if (index === 0) { |
| | | //TODO |
| | | } else if (index === 1) { |
| | | setting = { |
| | | position: point, |
| | | id: `point_${index}`, |
| | | billboard: { |
| | | image: Startingpointicon, |
| | | outlineWidth: 0, |
| | | width: 20, |
| | | height: 20, |
| | | scale: 1.0, |
| | | }, |
| | | } |
| | | } else if (index === positions.length - 1) { |
| | | setting = { |
| | | position: point, |
| | | id: `point_${index}`, |
| | | billboard: { |
| | | image: EndPointicon, |
| | | outlineWidth: 0, |
| | | width: 20, |
| | | height: 20, |
| | | scale: 1.0, |
| | | }, |
| | | } |
| | | } else { |
| | | setting = { |
| | | position: point, |
| | | id: `point_${index}`, |
| | | label: { |
| | | text: `${index}`, |
| | | font: 'bold 14px serif', |
| | | style: Cesium.LabelStyle.FILL, |
| | | verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直居中 |
| | | horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 水平居中 |
| | | pixelOffset: new Cesium.Cartesian2(0, 0), // 根据需要调整偏移量 |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -10) // 使标签在点的上方 |
| | | }, |
| | | |
| | | point: { |
| | | pixelSize: 24, |
| | | color: new Cesium.Color.fromBytes(255, 186, 0, 255), |
| | | }, |
| | | |
| | | offset: new Cesium.Cartesian2(10, 30), |
| | | } |
| | | } |
| | | viewer.entities.add(setting) |
| | | }); |
| | | } |
| | | |
| | | // 飞到中心点 |
| | | function flyToPoints(lngLatArr) { |
| | | if (!Array.isArray(lngLatArr) || lngLatArr.length === 0) return |
| | | const positions = lngLatArr.map(([lon, lat]) => |
| | | Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat)) |
| | | ) |
| | | // 计算包围盒 BoundingSphere(所有点的外接球) |
| | | const boundingSphere = Cesium.BoundingSphere.fromPoints(positions) |
| | | viewer.camera.flyToBoundingSphere(boundingSphere, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange(0, 0, boundingSphere.radius * 2), |
| | | }) |
| | | } |
| | | |
| | | // const drawLine = () => { |
| | | // console.log('尽量么'); |
| | | // // props.wayLineFile.way_lines.forEach(item => { |
| | | // // let prexUrl = ref(import.meta.env.VITE_APP_AIRLINE_URL+ props.wayLineFile); |
| | | // let prexUrl2 = ref('https://wrj.shuixiongit.com/minio/cloud-bucket/wayline/20241224/wayline_1735032173222.kmz'); |
| | | |
| | | // analyzeKmzFile(`${prexUrl2.value}?_t=${new Date().getTime()}`).then(async res => { |
| | | // const templateXML = await res.fileInfoObj['wpmz/template.kml'] |
| | | // const templateXMLJSON = XMLToJSON(templateXML)?.['Document'] |
| | | // const templateXMLObj = removeTextKey(templateXMLJSON.Folder) |
| | | // renderingLine(templateXMLObj) |
| | | // }) |
| | | // // }) |
| | | // } |
| | | |
| | | // 异步解析kmz文件 |
| | | const analysis = async url => { |
| | | return new Promise(async resolve => { |
| | | const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`) |
| | | const templateXML = await res.fileInfoObj['wpmz/template.kml'] |
| | | const templateXMLJSON = XMLToJSON(templateXML)?.['Document'] |
| | | const templateXMLObj = removeTextKey(templateXMLJSON.Folder) |
| | | resolve(templateXMLObj) |
| | | }) |
| | | } |
| | | |
| | | // 绘制线和飞行 |
| | | const drawLine = async () => { |
| | | let prexUrl = ref(import.meta.env.VITE_APP_AIRLINE_URL+ props.wayLineFile); |
| | | const res = await analysis(prexUrl.value); |
| | | renderingLine(res); |
| | | const points = res.Placemark.map(item => item.Point.coordinates.split(',')) |
| | | flyToPoints(points) |
| | | } |
| | | |
| | | watch(() => props.wayLineFile, async (newValue, oldValue) => { |
| | | if(newValue){ |
| | | await removeMap(); |
| | | await init(); |
| | | await drawLine(); |
| | | } |
| | | }) |
| | | |
| | | const removeMap = () => { |
| | | viewer.entities.removeAll() |
| | | viewer.destroy() |
| | | } |
| | | |
| | | |
| | | onBeforeUnmount(() => { |
| | | removeMap() |
| | | }) |
| | | |
| | | onMounted(() => { |
| | | nextTick(() => { |
| | | init() |
| | | }) |
| | | }) |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | #taskMap { |
| | | height: 100%; |
| | | |
| | | :deep() { |
| | | .cesium-viewer { |
| | | height: 100%; |
| | | overflow: hidden; |
| | | |
| | | .cesium-viewer-cesiumWidgetContainer { |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | .cesium-widget { |
| | | width: 100%; |
| | | height: 100%; |
| | | |
| | | canvas { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .cesium-viewer-bottom { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <el-table :data="tableData" style="width: 100%" height="400" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="index" label="序号" width="60" /> |
| | | <el-table-column prop="nickname" label="机巢名称" /> |
| | | <el-table-column prop="estimated_arrival_time" label="预计到达时间" /> |
| | | <el-table-column prop="exe_distance" label="执行里程" /> |
| | | </el-table> |
| | | <div class="pagination"> |
| | | <el-pagination |
| | | v-model:current-page="pageParams.page" |
| | | v-model:page-size="pageParams.limit" |
| | | :page-sizes="[10, 20, 30]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getFlyingNestBy } from '@/api/home/task'; |
| | | |
| | | const props = defineProps({ |
| | | waylineId: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | waylineType: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }); |
| | | |
| | | // 选中的数据 |
| | | const selectedRows = ref([]); |
| | | // 分页参数 |
| | | let pageParams = reactive({ |
| | | wayline_id: props.waylineId, |
| | | type: props.waylineType, |
| | | page: 1, |
| | | limit: 10 |
| | | }); |
| | | // 获取可用机巢列表数据 |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | | const getNestList = async () => { |
| | | tableData.value = []; |
| | | const res = await getFlyingNestBy(pageParams); |
| | | if (res.data.code === 0) { |
| | | tableData.value = res.data.data; |
| | | } |
| | | }; |
| | | // 分页大小改变 |
| | | const handleSizeChange = (val) => { |
| | | pageParams.limit = val; |
| | | getNestList(); |
| | | }; |
| | | |
| | | // 页码改变 |
| | | const handleCurrentChange = (val) => { |
| | | pageParams.page = val; |
| | | getNestList(); |
| | | }; |
| | | const emit = defineEmits(['update:selected']); |
| | | const handleSelectionChange = (val) => { |
| | | selectedRows.value = val; |
| | | // 可以通过emit将选中数据传给父组件 |
| | | emit('update:selected', val); |
| | | }; |
| | | // 监听航线ID变化 |
| | | watch(() => props.waylineId, (newVal) => { |
| | | pageParams.wayline_id = newVal; |
| | | if (newVal) { |
| | | pageParams.page = 1; |
| | | getNestList(); |
| | | } |
| | | }, { immediate: true }); |
| | | onMounted(() => { |
| | | // getNestList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | </style> |
| New file |
| | |
| | | <!-- 关联算法和综合业务 --> |
| | | <template> |
| | | <div class="task-algorithm" v-if="showAlgorithm"> |
| | | <el-select v-model="ai_type" multiple collapse-tags collapse-tags-tooltip placeholder="请选择算法" clearable @change="handleAlgorithmChange"> |
| | | <el-option v-for="item in taskAlgorithm" :key="item.id" :label="item.dictValue" :value="item.dictKey" /> |
| | | </el-select> |
| | | </div> |
| | | <div class="task-business" v-if="showBusiness"> |
| | | <el-select v-model="industry_type" placeholder="请选择类型" clearable @change="handleBusinessChange"> |
| | | <el-option v-for="item in taskBusiness" :key="item.id" :label="item.dictValue" :value="item.dictKey" /> |
| | | </el-select> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getDictionary } from '@/api/home/common'; |
| | | |
| | | // 接收父组件传参 |
| | | const props = defineProps({ |
| | | showAlgorithm: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | showBusiness: { |
| | | type: Boolean, |
| | | default: false |
| | | } |
| | | }); |
| | | |
| | | // 算法 |
| | | let ai_type = ref(''); |
| | | let taskAlgorithm = ref([]); |
| | | // 综合业务 |
| | | let industry_type = ref(''); |
| | | let taskBusiness = ref([]); |
| | | |
| | | // 请求字典字段 |
| | | const requestDictionary = () => { |
| | | getDictionary('SF,HYLB').then((res) => { |
| | | if (res.code !== 0) { |
| | | // 处理数据 |
| | | taskAlgorithm.value = res.data.data['SF']; |
| | | taskBusiness.value = res.data.data['HYLB']; |
| | | } |
| | | }); |
| | | }; |
| | | const emit = defineEmits(['algorithmChange', 'businessChange']); |
| | | // 算法选择事件 |
| | | const handleAlgorithmChange = (value) => { |
| | | emit('algorithmChange', value); |
| | | }; |
| | | // 业务选择事件 |
| | | const handleBusinessChange = (value) => { |
| | | emit('businessChange', value); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | requestDictionary(); |
| | | }); |
| | | </script> |