| src/views/resource/components/DrawPolygon.vue | ●●●●● patch | view | raw | blame | history | |
| src/views/resource/components/spotDetails.vue | ●●●●● patch | view | raw | blame | history |
src/views/resource/components/DrawPolygon.vue
@@ -3,56 +3,56 @@ </template> <script setup> import * as Cesium from 'cesium' import * as Cesium from 'cesium'; import { ElMessage } from 'element-plus' import { sdfwUpdate } from '@/api/home/territory' import { ElMessage } from 'element-plus'; import { sdfwUpdate } from '@/api/home/territory'; let curPolygonPosition = [] let savePolygonPosition = [] let curPolygon = null let curPolygonEntity = null let curPolygonObj = null let curPolygonPosition = []; let savePolygonPosition = []; let curPolygon = null; let curPolygonEntity = null; let curPolygonObj = null; let menuPanel = null let saveMenuPanel = null let menuPanel = null; let saveMenuPanel = null; const selectionIds = inject('selectionIds') const clearSelect = inject('clearSelect') // const getTableList = inject('getTableList') const selectionIds = inject('selectionIds'); const clearSelect = inject('clearSelect'); const getTableList = inject('getTableList') const viewInstance = inject('viewInstance') const homeViewer = inject('homeViewer') const viewInstance = inject('viewInstance'); const homeViewer = inject('homeViewer'); function preventDefault(event) { event.preventDefault() event.preventDefault(); return return; } function init() { // let draw = new Draw(homeViewer.value); // draw.drawPlane(); curPolygon = new Cesium.PolygonHierarchy() curPolygonEntity = new Cesium.Entity() homeViewer.value.scene.globe.depthTestAgainstTerrain = true curPolygon = new Cesium.PolygonHierarchy(); curPolygonEntity = new Cesium.Entity(); homeViewer.value.scene.globe.depthTestAgainstTerrain = true; viewInstance.value.addLeftClickEvent(null, addPlanerPointEvent, 'drawCustomPolygon') viewInstance.value.addRightClickEvent(null, addPlanarMenuEvent, 'drawCustomPolygon') viewInstance.value.addMouseHandler(null, mouseMoveEvent, 'drawCustomPolygon') viewInstance.value.addLeftClickEvent(null, addPlanerPointEvent, 'drawCustomPolygon'); viewInstance.value.addRightClickEvent(null, addPlanarMenuEvent, 'drawCustomPolygon'); viewInstance.value.addMouseHandler(null, mouseMoveEvent, 'drawCustomPolygon'); } function mouseMoveEvent(movement, viewer) { const mouseInfo = viewInstance.value.getMouseInfoAll(movement.endPosition) const mouseInfo = viewInstance.value.getMouseInfoAll(movement.endPosition); const { x, y } = mouseInfo.windowPosition const { x, y } = mouseInfo.windowPosition; if (!menuPanel) { menuPanel = createMenuPanel() viewer.container.appendChild(menuPanel) menuPanel = createMenuPanel(); viewer.container.appendChild(menuPanel); } menuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)` menuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`; if ( curPolygonObj && @@ -60,169 +60,169 @@ mouseInfo.surfacePosition != null && curPolygonPosition.length >= 1 ) { curPolygonPosition.pop() curPolygonPosition.push(mouseInfo.surfacePosition) curPolygonPosition.pop(); curPolygonPosition.push(mouseInfo.surfacePosition); curPolygon.positions.pop() curPolygon.positions.push(mouseInfo.surfacePosition) curPolygon.positions.pop(); curPolygon.positions.push(mouseInfo.surfacePosition); } } function addPlanerPointEvent(click, pick) { const { position } = click const { position } = click; const mouseInfo = viewInstance.value.getMouseInfoAll(position) const mouseInfo = viewInstance.value.getMouseInfoAll(position); if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo) if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo); } function addPlanarMenuEvent(click, pick, viewer) { if (savePolygonPosition.length <= 2) { ElMessage.warning('当前绘制无法形成面,请继续绘制或取消绘制!!') ElMessage.warning('当前绘制无法形成面,请继续绘制或取消绘制!!'); return return; } const { position } = click const { position } = click; const mouseInfo = viewInstance.value.getMouseInfoAll(position) const mouseInfo = viewInstance.value.getMouseInfoAll(position); remove() removeMenuPanel() remove(); removeMenuPanel(); if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo) if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo); const { x, y } = position saveMenuPanel = createSaveMenuPanel() saveMenuPanel.addEventListener('click', saveMenuClickEvent) saveMenuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)` viewer.container.appendChild(saveMenuPanel) const { x, y } = position; saveMenuPanel = createSaveMenuPanel(); saveMenuPanel.addEventListener('click', saveMenuClickEvent); saveMenuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`; viewer.container.appendChild(saveMenuPanel); } function createSaveMenuPanel() { const menuPanel = document.createElement('div') menuPanel.className = 'planar-menu-panel' const menuPanel = document.createElement('div'); menuPanel.className = 'planar-menu-panel'; const arr = [ { title: '提交绘制', class: 'save-draw' }, { title: '重新绘制', class: 'anew-draw' }, ] ]; arr.forEach(item => { const title = document.createElement('div') title.innerText = item.title title.className = item.class menuPanel.appendChild(title) }) const title = document.createElement('div'); title.innerText = item.title; title.className = item.class; menuPanel.appendChild(title); }); return menuPanel return menuPanel; } function saveMenuClickEvent(e) { const className = e.target.className const className = e.target.className; if (className === 'save-draw') { updatePolygon() updatePolygon(); } if (className == 'anew-draw') { cancel() cancel(); } removeSaveMenuPanel() removeSaveMenuPanel(); } function removeSaveMenuPanel() { if (saveMenuPanel) { homeViewer.value.container?.removeChild(saveMenuPanel) saveMenuPanel.removeEventListener('click', saveMenuClickEvent) saveMenuPanel = null homeViewer.value.container?.removeChild(saveMenuPanel); saveMenuPanel.removeEventListener('click', saveMenuClickEvent); saveMenuPanel = null; } } function createMenuPanel() { const menuPanel = document.createElement('div') menuPanel.className = 'planar-menu-panel' const menuPanel = document.createElement('div'); menuPanel.className = 'planar-menu-panel'; const title = document.createElement('div') title.innerText = '左击选择点位,右击结束' title.className = 'proof-custom-add-polygon' menuPanel.appendChild(title) const title = document.createElement('div'); title.innerText = '左击选择点位,右击结束'; title.className = 'proof-custom-add-polygon'; menuPanel.appendChild(title); return menuPanel return menuPanel; } function removeMenuPanel() { if (menuPanel) { homeViewer.value.container?.removeChild(menuPanel) menuPanel = null homeViewer.value.container?.removeChild(menuPanel); menuPanel = null; } } function drawCustomPolygon(point) { if (curPolygonPosition.length == 0) { curPolygonPosition.push(point.surfacePosition.clone()) curPolygon.positions.push(point.surfacePosition.clone()) curPolygonPosition.push(point.surfacePosition.clone()); curPolygon.positions.push(point.surfacePosition.clone()); } savePolygonPosition.push(point.wgs84SurfacePosition) curPolygonPosition.push(point.surfacePosition.clone()) curPolygon.positions.push(point.surfacePosition.clone()) savePolygonPosition.push(point.wgs84SurfacePosition); curPolygonPosition.push(point.surfacePosition.clone()); curPolygon.positions.push(point.surfacePosition.clone()); if (!curPolygonObj) { curPolygonEntity.polyline = { width: 2, material: Cesium.Color.WHITE, clampToGround: false, } }; curPolygonEntity.polyline.positions = new Cesium.CallbackProperty(function () { return curPolygonPosition }, false) return curPolygonPosition; }, false); curPolygonEntity.polygon = { hierarchy: new Cesium.CallbackProperty(function () { return curPolygon return curPolygon; }, false), material: Cesium.Color.fromCssColorString('#00ffff').withAlpha(0.4), clampToGround: false, } curPolygonEntity.name = 'customProofPolygon' }; curPolygonEntity.name = 'customProofPolygon'; curPolygonEntity._id = 'customProofPolygon' curPolygonObj = homeViewer.value.entities.add(curPolygonEntity) curPolygonEntity._id = 'customProofPolygon'; curPolygonObj = homeViewer.value.entities.add(curPolygonEntity); } } function clearPlanar() { homeViewer.value.entities.remove(curPolygonObj) curPolygonObj = null curPolygon = null curPolygonEntity = null curPolygonPosition = [] savePolygonPosition = [] homeViewer.value.entities.remove(curPolygonObj); curPolygonObj = null; curPolygon = null; curPolygonEntity = null; curPolygonPosition = []; savePolygonPosition = []; } function remove() { viewInstance.value.removeLeftClickEvent('drawCustomPolygon') viewInstance.value.removeRightClickEvent('drawCustomPolygon') viewInstance.value.removeMouseHandler('drawCustomPolygon') viewInstance.value.removeLeftClickEvent('drawCustomPolygon'); viewInstance.value.removeRightClickEvent('drawCustomPolygon'); viewInstance.value.removeMouseHandler('drawCustomPolygon'); } const emit = defineEmits(['upDateDrawState']) const emit = defineEmits(['upDateDrawState']); function updatePolygon() { let polygon = savePolygonPosition.reduce((pre, cur) => { pre.push(`${cur.lng} ${cur.lat}`) return pre }, []) polygon.push(polygon[0]) pre.push(`${cur.lng} ${cur.lat}`); return pre; }, []); polygon.push(polygon[0]); console.log('绘制',`POLYGON((${polygon.join(',')}))`); ElMessage.success('重新绘制图斑成功!!') ElMessage.success('重新绘制图斑成功!!'); if (selectionIds.value) { emit('upDateDrawState') selectionIds.value = null clearSelect() emit('upDateDrawState'); selectionIds.value = null; clearSelect(); } getTableList() // 接口 // sdfwUpdate({ // ids: selectionIds.value, @@ -246,29 +246,29 @@ } function cancel() { remove() removeMenuPanel() clearPlanar() remove(); removeMenuPanel(); clearPlanar(); init() init(); } onMounted(() => { document.addEventListener('contextmenu', preventDefault) document.addEventListener('contextmenu', preventDefault); init() }) init(); }); onBeforeUnmount(() => { document.removeEventListener('contextmenu', preventDefault) document.removeEventListener('contextmenu', preventDefault); remove() removeMenuPanel() removeSaveMenuPanel() clearPlanar() remove(); removeMenuPanel(); removeSaveMenuPanel(); clearPlanar(); homeViewer.value.scene.globe.depthTestAgainstTerrain = false }) homeViewer.value.scene.globe.depthTestAgainstTerrain = false; }); </script> <style lang="scss" scoped> @@ -291,7 +291,7 @@ .proof-custom-add-polygon { position: absolute; left: 20px; background: rgba(0, 0, 0, .6); background: rgba(0, 0, 0, 0.6); white-space: nowrap; border-radius: 4px; @@ -302,8 +302,8 @@ top: calc(50% - 2px); width: 0; height: 0; border-top: 4px solid rgba(0, 0, 0, .6); border-left: 4px solid rgba(0, 0, 0, .6); border-top: 4px solid rgba(0, 0, 0, 0.6); border-left: 4px solid rgba(0, 0, 0, 0.6); border-right: 4px solid transparent; border-bottom: 4px solid transparent; transform: rotate(-45deg); src/views/resource/components/spotDetails.vue
@@ -1,5 +1,11 @@ <template> <el-dialog :title="props.title" append-to-body v-model="uploadPatchDialog" width="80%" align-center> <el-dialog :title="props.title" append-to-body v-model="uploadPatchDialog" width="80%" align-center > <div class="container"> <!-- 信息展示区 --> <div class="infoBox"> @@ -7,7 +13,32 @@ <div v-for="(item, index) in infoList" :key="index" class="itemCon"> <div class="itemBox"> <div class="itemTitle">{{ item.name }}:</div> <div class="itemContent"> <template v-if="props.title === '图斑编辑' && item.editable"> <template v-if="item.name === '图斑类型'"> <el-select v-model="item.value" size="small" placeholder="请选择图斑类型" style="width: 100%" > <el-option v-for="opt in spotTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </template> <template v-else-if="item.name === '文件名称'"> <el-input v-model="item.value" size="small" /> </template> </template> <template v-else> <div class="itemValue">{{item.value}}</div> </template> </div> </div> </div> </div> @@ -19,7 +50,14 @@ <div class="table-overlay"> <div class="table-content"> <div class="tabname">图斑列表</div> <el-table ref="polygonTableEle" highlight-current-row :data="tableData" border style="width: 100%" @row-click="handleLocationPolygon"> <el-table ref="polygonTableEle" highlight-current-row :data="tableData" border style="width: 100%" @row-click="handleLocationPolygon" > <el-table-column type="index" label="序号" width="80"> <template #default="{ $index }"> {{ ($index + 1).toString().padStart(2, '0') }} @@ -27,10 +65,12 @@ </el-table-column> <el-table-column prop="dkbh" label="图斑名称" /> <el-table-column prop="investigate" label="图斑状态" /> <el-table-column label="操作" width="100" align="center"> <el-table-column label="操作" width="100" align="center" v-if="props.title === '图斑编辑'"> <template #default="scope"> <el-button type="text">删除</el-button> <el-button type="text" @click.stop="handleSelectionChange(scope.row)">编辑</el-button> <el-button type="text" @click.stop="handleSelectionChange(scope.row)" >编辑</el-button > </template> </el-table-column> </el-table> @@ -46,7 +86,11 @@ </div> </div> <!--绘制按钮--> <FunButton ref="funButtonEle" v-model:isBoxSelect="isBoxSelect" v-model:isDrawPolygon="isDrawPolygon" ></FunButton> <FunButton ref="funButtonEle" v-model:isBoxSelect="isBoxSelect" v-model:isDrawPolygon="isDrawPolygon" ></FunButton> <!-- 地图 --> <div id="spotMap" class="ztzf-cesium" v-show="uploadPatchDialog"></div> </div> @@ -62,42 +106,47 @@ getPolygonMaxHeight, cartesian3Convert, getWaylineShowHeight, } from '@/utils/cesium/mapUtil.js' } from '@/utils/cesium/mapUtil.js'; import { getPatchesSpotList } from '@/api/patchManagement/index'; import * as Cesium from 'cesium'; import { PublicCesium } from '@/utils/cesium/publicCesium'; import { ref, watch, onBeforeUnmount } from 'vue'; import FunButton from '@/views/resource/components/FunButton.vue'; const uploadPatchDialog = defineModel('show'); const props=defineProps(['title']) const polygonTableEle = ref(null) const props = defineProps(['title']); const polygonTableEle = ref(null); let publicCesiumInstance = null; let viewer = null; const viewInstance = shallowRef(null); const homeViewer = shallowRef(null); let tbJwdList = []; let total = ref(0) let total = ref(0); // 当前选中的图斑面数据 let nowSelectObj = ref({}) let nowSelectObj = ref({}); // 记录上一次点击高亮 let lastHighlightRow = null let lastHighlightRow = null; // 功能按钮区域相关:编辑图斑等 const funButtonEle = ref(null) const isBoxSelect = ref(false) const isDrawPolygon = ref(false) const funButtonEle = ref(null); const isBoxSelect = ref(false); const isDrawPolygon = ref(false); // 选中了哪些图斑 const selectionIds = ref(null) const selectionIds = ref(null); // 当前在编辑状态的异常图斑 let curCustomPolygon = null let curCustomPolygon = null; const spotTypeOptions = ref([ { value: '1', label: '综合类' }, { value: '2', label: '矿山类' }, { value: '3', label: '农田类' }, ]); const infoList = ref([ { name: '文件名称', value: '55', field: 'job_info_num' }, { name: '图斑类型', value: 'ee', field: 'name' }, { name: '图斑数量', value: '', field: 'industry_type_str' }, { name: '异常图斑数量', value: '', field: 'event_number' }, { name: '行政区划', value: '', field: 'device_names' }, { name: '数据来源', value: '', field: 'dept_name' }, { name: '创建时间', value: '', field: 'cycle_time_value' }, { name: '创建人', value: '', field: 'ai_type_str' }, { name: '文件名称', value: '55', field: 'job_info_num', editable: true }, { name: '图斑类型', value: 'ee', field: 'name', editable: true }, { name: '图斑数量', value: '', field: 'industry_type_str', editable: false }, { name: '异常图斑数量', value: '', field: 'event_number', editable: false }, { name: '行政区划', value: '', field: 'device_names', editable: false }, { name: '数据来源', value: '', field: 'dept_name', editable: false }, { name: '创建时间', value: '', field: 'cycle_time_value', editable: false }, { name: '创建人', value: '', field: 'ai_type_str', editable: false }, ]); const params = ref({ current: 1, @@ -129,7 +178,7 @@ ...item, dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw, })); total.value = res.data.data.pagination.total total.value = res.data.data.pagination.total; // 先清空地图现有图斑 tbJwdList = []; viewer.entities.removeAll(); // 清除所有实体 @@ -188,92 +237,95 @@ const positions = tbJwdList.flatMap(item => Cesium.Cartesian3.fromDegreesArray(item.grouped)); homeViewer.value.camera.flyToBoundingSphere(new Cesium.BoundingSphere.fromPoints(positions)); } viewInstance.value.removeLeftClickEvent('spotHighlighting') viewInstance.value.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting') viewInstance.value.removeLeftClickEvent('spotHighlighting'); viewInstance.value.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting'); }); }; // 高亮当前选中图斑,并定位 const handleLocationPolygon = (data, Deselect) => { heightlightSpot(data) } heightlightSpot(data); }; // 鼠标触发点击图斑高亮 pick:可以获取当前图斑数据 const spotHighlighting = (click, pick, viewer) => { if (!pick || !(pick.id?.customType == 'pattern_spot_polygon')) return if (!pick || !(pick.id?.customType == 'pattern_spot_polygon')) return; // 表格也对应选中数据 TODO const data = pick.id?.customInfo const data = pick.id?.customInfo; // 高亮图斑 heightlightSpot(data) } heightlightSpot(data); }; // 选中列表或者点击地图内的图斑 高亮图斑 const heightlightSpot = data => { nowSelectObj.value = data nowSelectObj.value = data; if (!data) { clearSelect() return clearSelect(); return; } // 保存当前选中图斑 // 取出当中经纬度 const numbersWithCommas = data.dkfw.match(/\d+(\.\d+)?/g) const numbersWithCommas = data.dkfw.match(/\d+(\.\d+)?/g); // 转换为二维数组 const groupedArr = numbersWithCommas.reduce((acc, val, index, src) => { if (index % 2 === 0) acc.push(src.slice(index, index + 2)) return acc }, []) if (index % 2 === 0) acc.push(src.slice(index, index + 2)); return acc; }, []); // 求出中心点 const polygonCenter = getCenterPoint(groupedArr) const polygonCenter = getCenterPoint(groupedArr); if (viewInstance.value.getEntityById('polygon_center')) { viewInstance.value.removeById('polygon_center') viewInstance.value.removeById('polygon_center'); } // 高亮当前图斑,将上一个高亮图斑恢复 if (lastHighlightRow) { let lastentity = homeViewer.value.entities?.getById('polygon_dk' + lastHighlightRow.id) let lastentity = homeViewer.value.entities?.getById('polygon_dk' + lastHighlightRow.id); if (lastentity && lastentity.polygon) { lastentity.polygon.material = Cesium.Color.YELLOW.withAlpha(0.5) lastentity.polygon.outlineColor = Cesium.Color.YELLOW lastentity.polygon.material = Cesium.Color.YELLOW.withAlpha(0.5); lastentity.polygon.outlineColor = Cesium.Color.YELLOW; } } let Nowentity = homeViewer.value.entities?.getById('polygon_dk' + data.id) let Nowentity = homeViewer.value.entities?.getById('polygon_dk' + data.id); if (Nowentity && Nowentity.polygon) { Nowentity.polygon.material = Cesium.Color.RED.withAlpha(0.3) Nowentity.polygon.outlineColor = Cesium.Color.RED Nowentity.polygon.material = Cesium.Color.RED.withAlpha(0.3); Nowentity.polygon.outlineColor = Cesium.Color.RED; } homeViewer.value.scene.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(Number(polygonCenter.lng), Number(polygonCenter.lat), 2500.0), }) lastHighlightRow = data } destination: Cesium.Cartesian3.fromDegrees( Number(polygonCenter.lng), Number(polygonCenter.lat), 2500.0 ), }); lastHighlightRow = data; }; // 清空选中的数据 const clearSelect =()=>{ lastHighlightRow = null selectionIds.value = null } lastHighlightRow = null; selectionIds.value = null; }; // 编辑 const handleSelectionChange =(row)=>{ const handleSelectionChange = row => { console.log('编辑',row); let curRowIsSelect = row selectionIds.value = row.id curRowIsSelect && handleLocationPolygon(row) let curRowIsSelect = row; selectionIds.value = row.id; curRowIsSelect && handleLocationPolygon(row); if (row.is_exception == 2 && curRowIsSelect) { isDrawPolygon.value = true funButtonEle.value.upDateDrawState(true) handleLocationPolygon(row) isDrawPolygon.value = true; funButtonEle.value.upDateDrawState(true); handleLocationPolygon(row); // clearSelect() // curCustomPolygon = row // ElMessage.warning('该图斑数据异常,请在地图区域重新绘制!!') }else{ isDrawPolygon.value = false isDrawPolygon.value = false; } } provide('selectionIds', selectionIds) provide('homeViewer', homeViewer) provide('viewInstance', viewInstance) provide('clearSelect', clearSelect) }; provide('selectionIds', selectionIds); provide('homeViewer', homeViewer); provide('viewInstance', viewInstance); provide('clearSelect', clearSelect); provide('getTableList', getTableList) // 销毁 const destroyMap = () => { if (viewer) { @@ -319,27 +371,22 @@ padding: 10px; font-size: 14px; .itemCon:nth-last-child(-n + 2) { border-bottom: 2px solid #efefef; } } .itemBox { display: flex; align-items: center; background: #fff; height: 33px; border-top: 2px solid #efefef; } } .itemCon:nth-last-child(-n + 2) { border-bottom: 2px solid #efefef; } .itemBox:nth-last-child(-n + 2) .itemTitle { border-bottom: 1px solid #efefef; } .itemTitle { flex: 0 0 150px; color: #0b1d38; width: 26%; text-align: right; text-align: center; background: #f3f6ff; height: 33px; line-height: 33px; @@ -347,23 +394,29 @@ border-top: 1px solid #efefef; } .itemContent { flex: 1; padding-left: 10px; .el-input { width: 100%; :deep(.el-input__inner) { height: 28px; line-height: 28px; background: transparent; border: none; padding: 0 10px; color: #747e91; } } .itemValue { font-size: 14px; color: #747e91; text-align: center; width: 74%; text-align: left; line-height: 33px; } .flightEvents { display: flex; flex-wrap: wrap; gap: 10px 10px; width: 74%; justify-content: center; img { width: 30px; height: 30px; } } } @@ -391,7 +444,8 @@ flex-direction: column; height: 95%; .tabname { color: #102441;} color: #102441; } } .pagination-container { @@ -412,5 +466,4 @@ height: 100%; width: 100%; } </style>