3 files renamed
8 files modified
6 files added
| New file |
| | |
| | | <!-- 量尺模式 --> |
| | | <template> |
| | | <div class="container"></div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cesiumOperation from '@/utils/cesium-tsa' |
| | | import cpoint from '@/assets/images/cpoint.png' |
| | | const { |
| | | addLeftClickEvent, |
| | | removeLeftClickEvent, |
| | | removeById, |
| | | addRightClickEvent, |
| | | removeRightClickEvent, |
| | | globalCesium |
| | | } = cesiumOperation() |
| | | |
| | | export default { |
| | | data () { |
| | | return { |
| | | positions: [], |
| | | menuPopup: null, |
| | | temporaryPointsDeleted: null, |
| | | alldistance: 0, |
| | | } |
| | | }, |
| | | methods: { |
| | | // Prevent default Event |
| | | preventDefault (event) { |
| | | event.preventDefault() |
| | | }, |
| | | init () { |
| | | addLeftClickEvent(null, this.handleMapClick) |
| | | addRightClickEvent(null, this.RightClickEvent) |
| | | let cesium = document.getElementById('cesium') |
| | | cesium.addEventListener('contextmenu', this.preventDefault) |
| | | }, |
| | | remove () { |
| | | removeLeftClickEvent() |
| | | let cesium = document.getElementById('cesium') |
| | | cesium.removeEventListener('contextmenu', this.preventDefault) |
| | | if (this.menuPopup) { |
| | | window.$viewer.container.removeChild(this.menuPopup) |
| | | } |
| | | removeRightClickEvent() |
| | | removeById('route_planning') |
| | | removeById('alldistanceshow') |
| | | this.positions.forEach((_position, index) => { |
| | | removeById('created_point_' + index) |
| | | removeById('distance_' + index) |
| | | }) |
| | | }, |
| | | // 左键点击事件 |
| | | handleMapClick (click) { |
| | | if (this.menuPopup) { |
| | | window.$viewer.container.removeChild(this.menuPopup) |
| | | this.menuPopup = null |
| | | } |
| | | const { position } = click |
| | | const ellipsoid = window.$viewer.scene.globe.ellipsoid |
| | | const c3Position = window.$viewer.scene.globe.pick( |
| | | window.$viewer.camera.getPickRay(position), |
| | | window.$viewer.scene, |
| | | ) |
| | | const c2Postion = ellipsoid.cartesianToCartographic(c3Position) |
| | | const longitude = globalCesium.Math.toDegrees(c2Postion.longitude) |
| | | const latitude = globalCesium.Math.toDegrees(c2Postion.latitude) |
| | | this.positions.push({ longitude, latitude }) |
| | | this.createWayline(this.positions) |
| | | }, |
| | | // 创建点位 |
| | | createWayline (positions) { |
| | | this.alldistance = 0 |
| | | const cartesian3Arr = [] |
| | | positions.forEach((position, index) => { |
| | | removeById('created_point_' + index) |
| | | removeById('distance_' + index) |
| | | const cartesian3 = globalCesium.Cartesian3.fromDegrees( |
| | | Number(position.longitude), |
| | | Number(position.latitude), |
| | | 0, |
| | | ) |
| | | cartesian3Arr.push(cartesian3) |
| | | window.$viewer.entities.add({ |
| | | id: 'created_point_' + index, |
| | | position: cartesian3, |
| | | billboard: { |
| | | image: cpoint, |
| | | pixelOffset: new globalCesium.Cartesian2(0, -13), |
| | | outlineWidth: 0, |
| | | width: 30, |
| | | height: 30, |
| | | scale: 1.0, |
| | | }, |
| | | }) |
| | | // 给最后一个点增加总长度展示 |
| | | if (this.positions.length == index + 1 && this.alldistance != 0) { |
| | | removeById('alldistanceshow') |
| | | window.$viewer.entities.add({ |
| | | position: cartesian3, |
| | | id: 'alldistanceshow', |
| | | label: { |
| | | text: `总长度:${this.alldistance}m`, |
| | | font: '12px monospace', |
| | | showBackground: true, |
| | | horizontalOrigin: globalCesium.HorizontalOrigin.CENTER, |
| | | verticalOrigin: globalCesium.VerticalOrigin.BOTTOM, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | pixelOffset: new globalCesium.Cartesian2(40, 20), |
| | | }, |
| | | }) |
| | | } |
| | | //给每个点增加右击事件 |
| | | addRightClickEvent('created_point_' + index, this.RightClickEvent) |
| | | |
| | | if (positions[index + 1]) { |
| | | const next = positions[index + 1] |
| | | const { longitude: nextLng, latitude: nextLat } = next |
| | | const nextPoint = globalCesium.Cartesian3.fromDegrees(nextLng, nextLat, 0) |
| | | // 获取中心点 |
| | | const centerPoint = globalCesium.Cartesian3.lerp( |
| | | cartesian3, |
| | | nextPoint, |
| | | 0.5, |
| | | new globalCesium.Cartesian3(), |
| | | ) |
| | | // 获取两个点之间的距离并展示 |
| | | let distance = globalCesium.Cartesian3.distance(cartesian3, nextPoint) |
| | | distance = Math.round(distance) |
| | | this.alldistance = this.alldistance + distance |
| | | if (positions.length < 1 || distance === 0) return |
| | | this.createDistanceLabel(centerPoint, distance, index) |
| | | } |
| | | }) |
| | | removeById('route_planning') |
| | | window.$viewer.entities.add({ |
| | | id: 'route_planning', |
| | | polyline: { |
| | | width: 7, |
| | | positions: cartesian3Arr, |
| | | material: new globalCesium.PolylineOutlineMaterialProperty({ |
| | | color: globalCesium.Color.WHITE, |
| | | outlineWidth: 2, |
| | | outlineColor: globalCesium.Color.BLUE, |
| | | }), |
| | | clampToGround: false, |
| | | }, |
| | | }) |
| | | }, |
| | | createDistanceLabel (position, dist, index) { |
| | | return window.$viewer.entities.add({ |
| | | position: position, |
| | | id: 'distance_' + index, |
| | | label: { |
| | | text: `${dist}m`, |
| | | font: '12px monospace', |
| | | showBackground: true, |
| | | horizontalOrigin: globalCesium.HorizontalOrigin.CENTER, |
| | | verticalOrigin: globalCesium.VerticalOrigin.BOTTOM, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | pixelOffset: new globalCesium.Cartesian2(0, -0), |
| | | }, |
| | | }) |
| | | }, |
| | | // 添加右键菜单 |
| | | RightClickEvent (click, pick, viewer) { |
| | | if (this.menuPopup) { |
| | | window.$viewer.container.removeChild(this.menuPopup) |
| | | this.menuPopup = null |
| | | } |
| | | if (this.positions.length == 0) return |
| | | const { position } = click |
| | | const { x, y } = position |
| | | this.menuPopup = this.createMenuPopup(pick) |
| | | this.menuPopup.addEventListener('click', this.appendPoint) |
| | | this.menuPopup.style.transform = `translate3d(${x}px, ${y}px, 0)` |
| | | window.$viewer.container.appendChild(this.menuPopup) |
| | | if (!pick) return |
| | | this.temporaryPointsDeleted = pick.id._id |
| | | }, |
| | | // 创建弹窗 |
| | | createMenuPopup (pick) { |
| | | const menuPopup = document.createElement('div') |
| | | menuPopup.className = 'create-wayline-menu' |
| | | const arr = [ |
| | | { title: '删除点位', class: 'del-wayline' }, |
| | | { title: '清空', class: 'remove-all' }, |
| | | ] |
| | | // 只有对点位进行右击时,才能单独进行点位删除 |
| | | if (!pick || ['route_planning', 'drone_dock'].includes(pick.id._id)) { |
| | | arr.splice(0, 1) |
| | | } |
| | | arr.forEach((item) => { |
| | | const title = document.createElement('div') |
| | | title.innerText = item.title |
| | | title.style.fontSize = '14px' |
| | | title.style.padding = '5px' |
| | | title.className = item.class |
| | | menuPopup.appendChild(title) |
| | | }) |
| | | return menuPopup |
| | | }, |
| | | // 对航点增加点击事件 |
| | | appendPoint (e) { |
| | | const className = e.target.className |
| | | window.$viewer.container.removeChild(this.menuPopup) |
| | | this.menuPopup = null |
| | | removeById('route_planning') |
| | | removeById('alldistanceshow') |
| | | this.positions.forEach((_position, index) => { |
| | | removeById('created_point_' + index) |
| | | removeById('distance_' + index) |
| | | }) |
| | | // 清空 |
| | | if (className === 'remove-all') { |
| | | this.positions = [] |
| | | } |
| | | // 单点删除 |
| | | else { |
| | | this.positions.splice(this.temporaryPointsDeleted.split('_')[2], 1) |
| | | this.createWayline(this.positions) |
| | | } |
| | | }, |
| | | }, |
| | | mounted () { |
| | | this.init() |
| | | }, |
| | | beforeUnmount () { |
| | | this.remove() |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .create-wayline-menu { |
| | | width: 'fit-content'; |
| | | background: url('@/assets/images/newcon_box.png') no-repeat center / 100% 100%; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | color: #fff; |
| | | font-size: 16px; |
| | | |
| | | div { |
| | | padding: 5px 10px; |
| | | cursor: pointer; |
| | | font-weight: bold; |
| | | |
| | | &:hover { |
| | | background-color: rgba(0, 0, 0, 0.3); |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | .userOperate { |
| | | position: absolute; |
| | | right: 27px; |
| | | top: -30px; |
| | | top: -35px; |
| | | width: 132px; |
| | | height: 38px; |
| | | display: flex; |
| | |
| | | import RSide from '@/views/Home/RSide.vue'; |
| | | import { onMounted } from 'vue'; |
| | | import cesiumOperation from '@/utils/cesium-tsa'; |
| | | import MeasuringDistance from '@/components/MeasuringDistance.vue'; |
| | | const store = useStore(); |
| | | const { _init,viewerDestory } = cesiumOperation(); |
| | | |
| | |
| | | |
| | | onUnmounted(()=>{ |
| | | store.commit('setSingleUavHome',null); |
| | | console.log('home销毁') |
| | | viewerDestory() |
| | | }) |
| | | |
| | |
| | | <template> |
| | | <div class="ai-chat"> |
| | | |
| | | <el-popover |
| | | placement="bottom" |
| | | :visible="visible" |
| | |
| | | <el-input/> |
| | | </div> |
| | | </el-popover> |
| | | |
| | | |
| | | <img class="chat-bottom" src="../../assets/images/chat-bottom.png" alt=""> |
| | | </div> |
| | | <div class="r-side"> |
| | | <img class="positioning" src="../../assets/images/self-positioning.png" alt="" @mouseenter="enterHover(0)" @mouseleave="logIndex=3"> |
| | | <img class="measuring-scale" src="../../assets/images/measuring-scale.png" alt="" @mouseenter="enterHover(1)" @mouseleave="logIndex=3"> |
| | | <img class="layer" src="../../assets/images/layer.png" alt="" @mouseenter="enterHover(2)" @mouseleave="logIndex=3"> |
| | | <img v-for="(item, index) in images" |
| | | :key="index" :class="item.class" |
| | | :src="activeIndex === index ? item.activeSrc : item.src" alt="" |
| | | @click="activeChange(index)" |
| | | @mouseenter="enterHover(index)" |
| | | @mouseleave="logIndex=3" |
| | | > |
| | | </div> |
| | | <div v-if="logIndex===0" class="r-side-positioning">切换地图模式</div> |
| | | <div v-if="logIndex===0" class="r-side-positioning">返回当前位置</div> |
| | | <div v-if="logIndex===1" class="r-side-measuring">量尺</div> |
| | | <div v-if="logIndex===2" class="r-side-layer">返回当前位置</div> |
| | | <div v-if="logIndex===2" class="r-side-layer">切换地图模式</div> |
| | | <MeasuringDistance v-if="activeIndex === 1"/> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import vDrag from '@/directive/drag' |
| | | import MeasuringDistance from '@/components/MeasuringDistance.vue' |
| | | import dw from '@/assets/images/rSide/dw.png' |
| | | import dw1 from '@/assets/images/rSide/dw1.png' |
| | | import lc from '@/assets/images/rSide/lc.png' |
| | | import lc1 from '@/assets/images/rSide/lc1.png' |
| | | import tc from '@/assets/images/rSide/tc.png' |
| | | import tc1 from '@/assets/images/rSide/tc1.png' |
| | | |
| | | let logIndex = ref(3); |
| | | const enterHover = (value) => { |
| | | logIndex.value = value; |
| | | logIndex.value = value; |
| | | } |
| | | |
| | | let activeIndex = ref(null); |
| | | const activeChange = (value) => { |
| | | if (value === 1){ |
| | | activeIndex.value = activeIndex.value === 1 ? null : value; |
| | | } |
| | | } |
| | | const visible = ref(false); |
| | | let pressStart = 0; |
| | |
| | | visible.value = !visible.value; |
| | | } |
| | | }; |
| | | |
| | | // 添加: 定义图片数组 |
| | | const images = [ |
| | | { class: 'positioning', src: dw,activeSrc:dw1 }, |
| | | { class: 'measuring-scale', src: lc,activeSrc:lc1 }, |
| | | { class: 'layer', src: tc,activeSrc:tc1 } |
| | | ]; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | height: 68px; |
| | | display: block; |
| | | }; |
| | | |
| | | |
| | | .chat { |
| | | position: fixed; |
| | | bottom: 330px; |
| | |
| | | .r-side-layer { |
| | | bottom: 122px; |
| | | } |
| | | |
| | | </style> |
| | | |
| | |
| | | const splashedList = type === 'device' |
| | | ? await getDeviceList(areaCode) |
| | | : eventList.map(i=>({eventId:i.id,latitude:Number(i.latitude),longitude:Number(i.longitude),type:'event'})) |
| | | console.log(list, 'list'); |
| | | console.log(splashedList, 'splashedList'); |
| | | const hierarchy = convertToHierarchy(areaCode.slice(0, 6)); |
| | | const jsonPath = hierarchy.join('/'); |
| | | const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/'); |
| | |
| | | id: feature.id, |
| | | position: position, |
| | | label: { |
| | | text: feature.data.total_device_count.toString(), |
| | | text: (feature.data.total_device_count || 0).toString(), |
| | | font: '12pt Source Han Sans CN', |
| | | fillColor: Cesium.Color.BLACK, |
| | | outlineColor: Cesium.Color.BLACK, |
| | | style: Cesium.LabelStyle.FILL_AND_OUTLINE, |
| | | eyeOffset: new Cesium.Cartesian3(0, 0, -10), // 让label "浮" 在广告牌前面 |
| | | }, |
| | |
| | | |
| | | // 移除所有监听事件,变量置空 |
| | | const removeAll = () => { |
| | | if (!viewer) return |
| | | removeEntities(); |
| | | removeLabel(); |
| | | // viewer.camera.moveEnd.removeEventListener(determineScaling); |
| | |
| | | } |
| | | const getDetails = () => { |
| | | getJobDetails({ wayLineJobInfoId: wayLineJodInfoId.value }).then(res => { |
| | | console.log(res.data.data, 666) |
| | | detailsData.value = res.data.data |
| | | infoList.value.forEach(item => { |
| | | item.value = detailsData.value?.[item.field] || '' |
| | |
| | | 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) |
| | | const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml'] |
| | | const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document'] |
| | | const templateXMLObj = removeTextKey(waylinesXMLJSON.Folder) |
| | | resolve(templateXMLObj) |
| | | }) |
| | | } |
| | |
| | | const drawLine = async () => { |
| | | const res = await Promise.all(props.detailsData.way_lines.map(item => analysis(item.url))) |
| | | res.map(item => renderingLine(item)) |
| | | console.log(res,'jiexi') |
| | | const allPoint = res |
| | | .flatMap(item => item.Placemark) |
| | | .map(item => item.Point.coordinates.split(',')) |
| | |
| | | } |
| | | |
| | | const removeMap = () => { |
| | | console.log('yichu') |
| | | viewer.entities.removeAll() |
| | | viewer.destroy() |
| | | } |
| | |
| | | import DeviceEvent from '@/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceEvent.vue' |
| | | import DeviceJob from '@/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJob.vue' |
| | | import { pxToRem } from '@/utils/rem'; |
| | | import { useStore } from 'vuex' |
| | | |
| | | const isShowDetails = defineModel('show') |
| | | |
| | | const infoList = ref([ |
| | | { name: '机巢名称', value: 'xxx' }, |
| | | { name: '机巢所属地区', value: 'xxx' }, |
| | | { name: '机巢状态', value: 'xxx' }, |
| | | { name: '任务成功', value: 'xxx' }, |
| | | { name: '机巢位置', value: 'xxx' }, |
| | | { name: '机巢名称', value: '',field:'nickname' }, |
| | | { name: '机巢所属地区', value: '',field:'device_area' }, |
| | | { name: '机巢状态', value: '',field:'status' }, |
| | | { name: '任务成功', value: '',field:'result_num' }, |
| | | { name: '机巢位置', value: '',field:'address' }, |
| | | ]) |
| | | |
| | | onMounted(() => {}) |
| | | const store = useStore(); |
| | | // state必须带上.home |
| | | const singleTotal = computed(() => store.state.home.singleTotal); |
| | | watch(singleTotal, (val) => { |
| | | if (val?.device_info){ |
| | | infoList.value.forEach(item => { |
| | | item.value = val.device_info?.[item.field] || '' |
| | | }) |
| | | } |
| | | }) |
| | | onMounted(() => { |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | |
| | | import { useStore } from 'vuex'; |
| | | |
| | | const store = useStore(); |
| | | |
| | | // state必须带上.home |
| | | const singleUavHome = computed(() => store.state.home.singleUavHome); |
| | | // getters不需要带.home |
| | | const test = computed(() => store.getters.test); |
| | | |
| | | onMounted(() => { |
| | | // commit dispatch 不需要带.home |
| | | store.commit('xxxx', '同步步修改啦'); |