Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard
3 files modified
4 files added
| | |
| | | import { createRouter, createWebHistory } from 'vue-router'; |
| | | import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'; |
| | | import ExtRouter from './ext/'; |
| | | import PageRouter from './page/'; |
| | | import ViewsRouter from './views/'; |
| | |
| | | //创建路由 |
| | | const Router = createRouter({ |
| | | base: import.meta.env.VITE_APP_BASE, |
| | | history: createWebHistory(import.meta.env.VITE_APP_BASE), |
| | | history: createWebHashHistory(import.meta.env.VITE_APP_BASE), |
| | | routes: [...ExtRouter, ...PageRouter, ...ViewsRouter], |
| | | }); |
| | | AvueRouter.install({ |
| | |
| | | |
| | | export function resetRouter() { |
| | | // 重置路由 比如用于身份验证失败,需要重新登录时 先清空当前的路有权限 |
| | | const newRouter = createRouter(); |
| | | const newRouter = createRouter({ |
| | | history: createWebHashHistory(import.meta.env.VITE_APP_BASE), |
| | | }); |
| | | Router.matcher = newRouter.matcher; // reset router |
| | | AvueRouter.install(Vue, { |
| | | router: Router, |
| | |
| | | import HomeLeft from '@/views/Home/components/HomeLeft/HomeLeft.vue'; |
| | | import SearchBox from '@/views/Home/SearchBox.vue'; |
| | | import { useAggregation } from '@/views/Home/useAggregation'; |
| | | import MapPopUpBox from '@/views/Home/MapPopUpBox.vue'; |
| | | import { render } from 'vue'; |
| | | |
| | | |
| | | useAggregation() |
| | | </script> |
| New file |
| | |
| | | <script setup> |
| | | import { Close } from '@element-plus/icons-vue'; |
| | | |
| | | const list = [ |
| | | { name: '执行中', value: '1', color: '#FFA768' }, |
| | | { name: '在线', value: '20', color: '#8EFFAC' }, |
| | | { name: '离线', value: '14', color: '#FFFFFF' }, |
| | | { name: '异常', value: '25', color: '#FF6262' }, |
| | | ]; |
| | | |
| | | const props = defineProps(['data', 'removeLabel']); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="mapPopUpBox"> |
| | | <div class="header"> |
| | | <div class="headerLeft"> |
| | | <img class="header-image" src="@/assets/images/home/MapPopUpBox/titleImg.png" alt="" /> |
| | | <div class="header-title">安义县机场</div> |
| | | </div> |
| | | <el-icon class="header-close" @click="props.removeLabel"> |
| | | <Close /> |
| | | </el-icon> |
| | | </div> |
| | | <div class="info"> |
| | | <div class="info-item"> |
| | | 机巢数: |
| | | <div class="num">10</div> |
| | | </div> |
| | | <div class="info-item"> |
| | | 任务数: |
| | | <div class="num">32</div> |
| | | </div> |
| | | </div> |
| | | <div class="status-title">机巢状态</div> |
| | | <div class="status-list"> |
| | | <div v-for="item in list" :key="item.name" class="status-item"> |
| | | <div class="status-value" :style="{ color: item.color }">{{ item.value }}</div> |
| | | <div class="status-name">{{ item.name }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="scss"> |
| | | .mapPopUpBox { |
| | | width: 418px; |
| | | height: 240px; |
| | | background: url('@/assets/images/home/MapPopUpBox/mapPopUpBg.png') no-repeat center / 100% 100%; |
| | | padding-left: 98px; |
| | | |
| | | .header { |
| | | padding: 0 12px; |
| | | width: 320px; |
| | | height: 51px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | |
| | | .headerLeft { |
| | | display: flex; |
| | | } |
| | | |
| | | img { |
| | | width: 26px; |
| | | height: 26px; |
| | | } |
| | | |
| | | &-title { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; |
| | | font-weight: 400; |
| | | font-size: 26px; |
| | | line-height: 30px; |
| | | letter-spacing: 2px; |
| | | text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25); |
| | | background: linear-gradient(180deg, #ffffff 41%, #35d0ff 86%); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | margin-left: 4px; |
| | | } |
| | | |
| | | &-close { |
| | | width: 25px; |
| | | height: 100%; |
| | | line-height: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | color: #9cd5ff; |
| | | pointer-events: all; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | .info { |
| | | height: 34px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN, serif; |
| | | font-weight: 400; |
| | | font-size: 16px; |
| | | color: #ffffff; |
| | | line-height: 19px; |
| | | display: flex; |
| | | align-items: center; |
| | | padding-left: 15px; |
| | | gap: 0 20px; |
| | | margin: 18px 0; |
| | | |
| | | .info-item { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .num { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; |
| | | font-weight: 400; |
| | | font-size: 26px; |
| | | color: #ffffff; |
| | | line-height: 30px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .status-title { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; |
| | | font-weight: 400; |
| | | font-size: 20px; |
| | | color: #ffffff; |
| | | line-height: 23px; |
| | | text-shadow: 0px 0px 12px rgba(68, 105, 255, 0.67); |
| | | padding-left: 15px; |
| | | margin-bottom: 14px; |
| | | } |
| | | |
| | | .status-list { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | |
| | | .status-item { |
| | | width: 66px; |
| | | height: 54px; |
| | | background: url('@/assets/images/home/MapPopUpBox/itembg.png') no-repeat center / 100% 100%; |
| | | text-align: center; |
| | | |
| | | .status-value { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif; |
| | | font-weight: 400; |
| | | font-size: 26px; |
| | | color: #ffa768; |
| | | line-height: 17px; |
| | | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); |
| | | position: relative; |
| | | top: -3px; |
| | | } |
| | | |
| | | .status-name { |
| | | font-family: Source Han Sans CN, Source Han Sans CN, serif; |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #ffffff; |
| | | line-height: 16px; |
| | | position: relative; |
| | | top: -3px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | import jiangxishi from '@/assets/geojson/jiangxishi.json'; |
| | | import jiangxi from '@/assets/geojson/jiangxi.json'; |
| | | import zg from '@/assets/geojson/zg.json'; |
| | | import MapPopUpBox from '@/views/Home/MapPopUpBox.vue'; |
| | | import { render } from 'vue'; |
| | | |
| | | /** |
| | | * 机巢聚合功能 |
| | | */ |
| | | export const useAggregation = () => { |
| | | let viewer = null; |
| | | const scalingJudgment = [ |
| | | { name: '县', value: [0, 48651], gJson: null }, |
| | | { name: '市', value: [48651, 314863], gJson: jiangxishi }, |
| | | { name: '省', value: [314863, 1169651], gJson: jiangxi }, |
| | | { name: '国', value: [1169651, 37962800], gJson: zg }, |
| | | ]; |
| | | let viewer = null; |
| | | const active = ref(''); |
| | | let handler = null; |
| | | let labelDiv = null; |
| | | let positionC3 = null; |
| | | const init = () => { |
| | | determineScaling(); |
| | | viewer.camera.moveEnd.addEventListener(() => { |
| | |
| | | }); |
| | | }; |
| | | |
| | | const removeFun = () => { |
| | | viewer.dataSources.removeAll(true); |
| | | viewer.entities.removeAll(); |
| | | }; |
| | | |
| | | // 确定缩放比例 |
| | | const determineScaling = () => { |
| | | let height = viewer.camera.positionCartographic.height; |
| | | // 根据高度展示对应的 gJson |
| | | for (let item of scalingJudgment) { |
| | | if (height > item.value[0] && height <= item.value[1]) { |
| | | if (active.value !== item.name) { |
| | | removeFun(); |
| | | removeEntities(); |
| | | removeLabel(); |
| | | active.value = item.name; |
| | | item.gJson ? aggregation(item) : splashed(); |
| | | } |
| | |
| | | if (!feature.position) return; |
| | | const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1]); |
| | | viewer.entities.add({ |
| | | id: feature.id, |
| | | position: position, |
| | | label: { |
| | | // 随机整数 |
| | |
| | | image: new Cesium.ConstantProperty(data2), |
| | | width: 24, |
| | | height: 24, |
| | | }, |
| | | properties: { |
| | | id: feature.id, |
| | | customData: { |
| | | name: feature.name, |
| | | }, |
| | | }, |
| | | }); |
| | | }); |
| | |
| | | }); |
| | | }; |
| | | |
| | | const getLabelDom = () => { |
| | | const vNode = h(MapPopUpBox, { data: '参数',removeLabel }); |
| | | const tooltipContainer = document.createElement('div'); |
| | | tooltipContainer.style.position = 'absolute'; |
| | | tooltipContainer.style.transform = 'translateY(-50%)'; |
| | | tooltipContainer.style.pointerEvents = 'none'; |
| | | document.querySelector('.page-index').append(tooltipContainer); |
| | | render(vNode, tooltipContainer); |
| | | return tooltipContainer; |
| | | }; |
| | | |
| | | const labelBox = () => { |
| | | if (!labelDiv) { |
| | | labelDiv = getLabelDom(); |
| | | } |
| | | const screenPosition = viewer.scene.cartesianToCanvasCoordinates(positionC3); |
| | | if (screenPosition) { |
| | | labelDiv.style.left = `${screenPosition.x}px`; |
| | | labelDiv.style.top = `${screenPosition.y}px`; |
| | | } |
| | | }; |
| | | |
| | | const clickFun = click => { |
| | | const pickedObject = viewer.scene.pick(click.position); |
| | | if (Cesium.defined(pickedObject) && pickedObject.id) { |
| | | const entity = pickedObject.id; |
| | | positionC3 = entity.position._value; |
| | | viewer.scene.postRender.addEventListener(labelBox); |
| | | } |
| | | }; |
| | | |
| | | const removeEntities = () => { |
| | | viewer.dataSources.removeAll(true); |
| | | viewer.entities.removeAll(); |
| | | }; |
| | | const removeLabel = () => { |
| | | viewer.scene.postRender.removeEventListener(labelBox); |
| | | if (labelDiv && labelDiv.parentNode) { |
| | | labelDiv.parentNode.removeChild(labelDiv); |
| | | labelDiv = null; |
| | | } |
| | | }; |
| | | |
| | | onUnmounted(() => { |
| | | console.log('xiezai'); |
| | | removeFun(); |
| | | removeEntities(); |
| | | removeLabel(); |
| | | handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | console.log('触发'); |
| | | nextTick(() => { |
| | | viewer = window.$viewer; |
| | | handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); |
| | | handler.setInputAction(clickFun, Cesium.ScreenSpaceEventType.LEFT_CLICK); |
| | | init(); |
| | | }); |
| | | }); |