.env.development
@@ -2,18 +2,7 @@ #开发环境配置 VITE_APP_ENV = 'development' #接口地址 VITE_APP_API = /api VITE_APP_API_URL = https://wrj.shuixiongit.com/api #开发环境代理地址(推荐本地新建文件 .env.development.local 来进行覆盖) # VITE_APP_API_URL = https://wrj.shuixiongit.com/api # VITE_APP_API_URL = http://192.168.1.7 # 连接本地服务器 # VITE_APP_API_URL = http://192.168.1.204 #调试参数 VITE_APP_DEBUG_KEY = saber VITE_APP_DEBUG_SWITCH = false #页面基础路径 VITE_APP_BASE = /command-center-dashboard/ # ws地址 VITE_APP_WS_API_URL = wss://wrj.shuixiongit.com/drone-wss/api/v1/ws package.json
@@ -16,6 +16,7 @@ "@saber/nf-form-design-elp": "^1.4.1", "@saber/nf-form-elp": "^1.4.4", "@smallwei/avue": "^3.6.2", "@turf/turf": "^6.5.0", "animate.css": "^4.1.1", "avue-plugin-ueditor": "^1.0.4", "axios": "^1.8.3", pnpm-lock.yaml
Diff too large src/api/home/machineNest.js
@@ -46,3 +46,23 @@ params: {}, }) } // 设备-任务列表 export const getDeviceJobList = (data,params) => { return request({ url: `/drone-device-core/wayline/waylineJobInfo/jobList`, method: 'post', data, params }) } // 设备-事件列表 export const getDeviceEventList = (data,params) => { return request({ url: `/drone-device-core/jobEvent/eventPage`, method: 'post', data, params }) } src/views/Home/useMapAggregation/useMapAggregation.js
@@ -46,14 +46,11 @@ const store = useStore(); const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode); const selectedAreaCode = computed(() => store.state.user.selectedAreaCode); const listenerHeight = () => { determineScaling(); viewer.camera.moveEnd.addEventListener(determineScaling); }; // 确定缩放比例 const determineScaling = index => { console.log('确定缩放比例'); const determineScaling = () => { // console.log('确定缩放比例'); if (!viewer) return; let height = viewer.camera.positionCartographic.height; // 根据高度展示对应的 gJson @@ -64,13 +61,15 @@ active = item.name; removeEntities(); removeLabel(); item.gJson ? aggregation(item) : splashed(item); renderOutline(item); if (!item.gJson && !item.splashedList?.length) return; item.gJson ? aggregation(item) : splashed(item); break; } } }; // 转换为目录结构, 返回数组, function convertToHierarchy(code) { const codeStr = code.toString(); const provinceCode = codeStr.slice(0, 2) + '0000'; @@ -83,18 +82,20 @@ return [provinceCode, cityCode, code]; } // 获取设备聚合 function getDeviceCount(areaCode) { return getDeviceRegionCount({ areaCode }).then(res => { return (res?.data?.data || []).map(i=>({...i,type:'deviceAggregation'})); return (res?.data?.data || []) }); } // 获取设备散点 function getDeviceList(areaCode) { return getDeviceRegion({ areaCode }).then(res => { return (res?.data?.data || []).map(i =>({...i,type})); }); } // 事件散点 let eventList = [] function processChildren(childrens) { return (childrens || []).map(item => { @@ -106,7 +107,6 @@ total_device_count: item.number, region_code: item.id, region_name: item.name, type:'eventAggregation' }; if (arr.length !== 0) { returnObj.childrens = arr; @@ -115,6 +115,7 @@ }); } // 获取事件聚合 function getMapEventCount(areaCode) { return getMapEvents({ areaCode }).then(res => { const resData= res?.data?.data @@ -145,7 +146,10 @@ const injectData = (gJson, dataList) => { return { ...gJson, features: gJson.features.map(item => ({ ...item, data: dataList.find(item1 => findFun(item1, item)) })), features: gJson.features.map(item => { const findData = dataList.find(item1 => findFun(item1, item)) return { ...item, data: {...findData,type: type + 'Aggregation'} } }), }; }; @@ -165,23 +169,18 @@ scalingJudgment[0].gJson = null; scalingJudgment[0].splashedList = splashedList; active = null; // 轮廓 const outlineGJson = await getOutLine(jsonPathPre, hierarchy); scalingJudgment.forEach(item => item.show && (item.outline = outlineGJson)); // 省 if (hierarchy.length === 1) { const gJson1 = await getFiler(`${defaultDir}${jsonPath}/indexDistrict.json`); const gJson2 = await getFiler(`${defaultDir}${jsonPath}/index.json`); scalingJudgment[1].gJson = { ...gJson1, features: gJson1.features.map(item => ({ ...item, data: list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)), })), features: gJson1.features.map(item => { const findData = list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)) return { ...item, data: {...findData,type: type + 'Aggregation'} } }), }; scalingJudgment[2].gJson = injectData(gJson2, list); const { lng, lat } = getCenterPoint(gJson2.features.map(item => item.properties.center)); flyTo({ longitude: lng, latitude: lat }, 0, scalingJudgment[2].height); } // 市 if (hierarchy.length === 2) { @@ -189,8 +188,6 @@ scalingJudgment[2].show = false; const gJson1 = await getFiler(`${defaultDir}${jsonPath}/index.json`); scalingJudgment[1].gJson = injectData(gJson1, list); const center = getCenterPoint(gJson1.features.map(item => item.properties.center)); flyTo({ longitude: center.lng, latitude: center.lat }, 0, scalingJudgment[1].height); } // 区县 if (hierarchy.length === 3) { @@ -198,17 +195,22 @@ scalingJudgment[1].show = false; scalingJudgment[2].gJson = null; scalingJudgment[2].show = false; const outlineGJson = await getOutLine(jsonPathPre, hierarchy); const center = outlineGJson.features[0].properties.center; flyTo({ longitude: center[0], latitude: center[1] }, 0, scalingJudgment[0].height); } determineScaling() // 轮廓 const outlineGJson = await getOutLine(jsonPathPre, hierarchy); scalingJudgment.forEach(item => item.show && (item.outline = outlineGJson)); const [longitude,latitude] = outlineGJson.features[0].properties.centroid flyTo({ longitude, latitude }, 0, scalingJudgment[(hierarchy.length-3) * (-1)].height); }; watch( selectedAreaCode, async (newValue, oldValue) => { initMapData(newValue); if (!viewer) return viewer.scene.postRender.removeEventListener(determineScaling) initMapData(newValue).then(()=>{ viewer.scene.postRender.addEventListener(determineScaling) }) }, { deep: true } ); @@ -273,12 +275,15 @@ // 聚合机巢 const aggregation = (item, flyTo) => { if (!item.gJson) return; const featuresList = item.gJson.features.map(item => ({ name: item.properties.name, position: item.properties.center, data: item.data, id: item.region_code, })); const featuresList = item.gJson.features.map(item1 => { // const {lng,lat} = getCenterPoint(item1.geometry.coordinates[0][0]) return { name: item1.properties.name, position: item1.properties.centroid, data: item1.data, id: item1.region_code, } }); // 遍历特征并添加实体 featuresList.forEach(feature => { if (!feature.position) return; @@ -382,7 +387,7 @@ if (!positionC3) return; removeLabel(); const customData = entity.properties.customData._value.data; console.log('customData', customData); switch (customData.type) { case 'deviceAggregation': viewer.scene.postRender.addEventListener(labelBoxRender); @@ -423,7 +428,8 @@ const removeAll = () => { removeEntities(); removeLabel(); viewer.camera.moveEnd.removeEventListener(determineScaling); // viewer.camera.moveEnd.removeEventListener(determineScaling); viewer.scene.postRender.removeEventListener(determineScaling) handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler?.destroy(); viewer = null; @@ -433,11 +439,14 @@ currentEntity = null; }; const init = () => { initMapData(selectedAreaCode.value || userAreaCode.value); viewer = window.$viewer; viewer.scene.postRender.removeEventListener(determineScaling) initMapData(selectedAreaCode.value || userAreaCode.value).then(()=>{ viewer.scene.postRender.addEventListener(determineScaling) }) handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK); listenerHeight(); }; onBeforeUnmount(() => {}); // onMounted(() => { @@ -445,7 +454,6 @@ // viewer = window.$viewer; // handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); // handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK); // listenerHeight(); // }); // }); src/views/SignMachineNest/SignMachineNest.vue
@@ -31,7 +31,6 @@ const messageHandler = (result) => { let payload = JSON.parse(result) // 为了兼容聊天消息 // console.log('payload', payload) if (!payload) return switch (payload.biz_code) { case EBizCode.GatewayOsd: { @@ -83,6 +82,8 @@ getFlightStatistics(singleUavHome.value.device_sn).then(res => { if (res.data.code !== 0) return; const result = res.data.data; console.log(result); console.log(result); store.commit('setSingleTotal', result); }) }; @@ -95,4 +96,4 @@ onUnmounted(() => { connectWs?.value?.close(); }); </script> </script> src/views/SignMachineNest/components/MachineRight/MachineStatus.vue
@@ -66,7 +66,7 @@ </div> </div> </div> <!-- <MachineTableDetails :dialogVisible="isShowDetails" /> --> <MachineTableDetails v-model:show="isShowDetails"/> </template> <script setup> @@ -75,6 +75,7 @@ import { EModeCode, EDockModeText, EModeText } from '@/utils/staticData/device'; import { getLnglatAltitude } from '@/utils/cesium/mapUtil.js'; import { useStore } from 'vuex'; import MachineTableDetails from '@/views/SignMachineNest/components/MachineRight/MachineTableDetails/MachineTableDetails.vue'; const store = useStore(); // 获取机巢信息 @@ -269,7 +270,7 @@ ); opacity: 0.85; margin: 2px 0 13 0; padding: 8px 0px 20px 18px; .info { display: flex; @@ -323,16 +324,16 @@ color: #FFB26A; margin-right: 10px; } .wb { .wb { width: 60px; height: 20px; height: 20px; background: rgba(255,106,106,0.2); border-radius: 4px 4px 4px 4px; border: 1px solid #FF6A6A; color: #FF6A6A; } } } } .status { @@ -341,7 +342,7 @@ gap: 10px 20px; margin-top: 18px; .card { width: calc(33.33% - 14px); width: calc(33.33% - 14px); } img { width: 16px; @@ -370,4 +371,4 @@ } } } </style> </style> src/views/SignMachineNest/components/MachineRight/MachineTableDetails/DeviceEvent.vue
New file @@ -0,0 +1,66 @@ <template> <el-divider content-position="left">相关事件 {{total}}次</el-divider> <el-table :data="list" style="width: 100%"> <el-table-column prop="event_num" label="编号" /> <el-table-column prop="event_name" label="名称" /> <el-table-column prop="media_type" label="类型" /> <el-table-column prop="photo_url" label="图片url" /> <el-table-column prop="video_url" label="视频url" /> <el-table-column prop="remark" label="备注" /> <el-table-column prop="status" label="状态"> <template #default="scope"> <el-tag v-if="scope.row.status === 0" type="info">待处理</el-tag> <el-tag v-if="scope.row.status === 1" type="success">待分拨</el-tag> <el-tag v-if="scope.row.status === 2" type="warning">待处理</el-tag> <el-tag v-if="scope.row.status === 3" type="success">处理中</el-tag> <el-tag v-if="scope.row.status === 4" type="success">已完成</el-tag> <el-tag v-if="scope.row.status === 5" type="success">已完结</el-tag> </template> </el-table-column> <el-table-column prop="wayline_job_id" label=" 任务id" /> </el-table> <el-pagination background :page-sizes="[10, 20, 30, 50]" v-model:current-page="sizeParams.current" v-model:page-size="sizeParams.size" layout="total, sizes, prev, pager, next, jumper" :total="total" @change="pageChange" /> </template> <script setup> import { useStore } from 'vuex' import { getDeviceEventList } from '@/api/home/machineNest' const list = ref([]) const params = ref({ device_sn: null, }) const sizeParams = ref({ current: 1, size: 1, }) const store = useStore() const child_sn = computed(() => store.state.home.singleUavHome.child_sn) const total = ref(0) const getList = () => { params.value.device_sn = child_sn.value getDeviceEventList(params.value, sizeParams.value).then(res => { const resData = res?.data?.data || {} list.value = resData.records total.value = resData.total }) } const pageChange = val => { sizeParams.value.current = val getList() } onMounted(() => { getList() }) </script> <style scoped lang="scss"></style> src/views/SignMachineNest/components/MachineRight/MachineTableDetails/DeviceJob.vue
New file @@ -0,0 +1,58 @@ <template> <el-divider content-position="left">相关事件 {{ total }}次</el-divider> <el-table :data="list" style="width: 100%"> <el-table-column prop="id" label="id" /> <el-table-column prop="name" label="名称" /> <el-table-column prop="industry_type_str" label="任务类型" /> <el-table-column prop="ai_type_str" label="关联算法" /> <el-table-column prop="event_number" label="事件工单" /> <el-table-column prop="remark" label="备注" /> <el-table-column prop="area_code" label="地区代码" /> <el-table-column prop="begin_time" label="开始时间" /> <el-table-column prop="end_time" label="结束时间" /> <el-table-column prop="device_names" label="设备名称" /> <el-table-column prop="creator_name" label="创建者姓名" /> </el-table> <el-pagination background :page-sizes="[10, 20, 30, 50]" v-model:current-page="sizeParams.current" v-model:page-size="sizeParams.size" layout="total, sizes, prev, pager, next, jumper" :total="total" @change="pageChange" /> </template> <script setup> import { useStore } from 'vuex' import { getDeviceJobList } from '@/api/home/machineNest' const list = ref([]) const params = ref({ device_sn: null, }) const sizeParams = ref({ current: 1, size: 1, }) const store = useStore() const child_sn = computed(() => store.state.home.singleUavHome.child_sn) const total = ref(0) const getList = () => { params.value.device_sn = child_sn.value getDeviceJobList(params.value, sizeParams.value).then(res => { const resData = res?.data?.data || {} list.value = resData.records total.value = resData.total }) } const pageChange = val => { sizeParams.value.current = val getList() } onMounted(() => { getList() }) </script> <style scoped lang="scss"></style> src/views/SignMachineNest/components/MachineRight/MachineTableDetails/MachineTableDetails.vue
New file @@ -0,0 +1,75 @@ <!-- 机巢列表详情 --> <template> <el-dialog modal-class="machineTableDetails" v-model="isShowDetails" title="机巢详情" :width="pxToRem(1500)" :close-on-click-modal="false" :destroy-on-close="true" > <el-divider content-position="left">详情</el-divider> <div class="infoBox"> <div class="itemBox" v-for="item in infoList"> <div class="itemTitle">{{ item.name }}:</div> <div class="itemValue">{{ item.value }}</div> </div> </div> <DeviceJob v-if="isShowDetails" /> <DeviceEvent v-if="isShowDetails" /> </el-dialog> </template> <script setup> import DeviceEvent from '@/views/SignMachineNest/components/MachineRight/MachineTableDetails/DeviceEvent.vue' import DeviceJob from '@/views/SignMachineNest/components/MachineRight/MachineTableDetails/DeviceJob.vue' import { pxToRem } from '@/utils/rem'; const isShowDetails = defineModel('show') const infoList = ref([ { name: '机巢名称', value: 'xxx' }, { name: '机巢所属地区', value: 'xxx' }, { name: '机巢状态', value: 'xxx' }, { name: '任务成功', value: 'xxx' }, { name: '机巢位置', value: 'xxx' }, ]) onMounted(() => {}) </script> <style lang="scss"> .machineTableDetails { .el-pagination { text-align: left; padding: 20px; } } </style> <style lang="scss" scoped> .infoBox { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; // 列之间的间距 padding: 10px; .itemBox { background-color: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 15px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .itemTitle { font-weight: bold; color: #333; } .itemValue { margin-top: 5px; color: #666; } } </style> src/views/SignMachineNest/components/MachineRight/components/MachineTableDetails.vue
File was deleted