<template> <div class="analysis-com"> <div class="draw-edit" v-if="cusTransfer.draw.center"> <div class="draw-edit-content"> 周边范围: <div class="radius-min __hover" @click="cusTransfer.draw.radius > 1 ? (cusTransfer.draw.radius--, handleRangeInput(cusTransfer.draw.radius)) : undefined">-</div> <CusFormColumn link="number" label="" :clearable="false" v-model:param="cusTransfer.draw.radius" @input="handleRangeInput"/> <div class="radius-max __hover" @click="cusTransfer.draw.radius < 60 ? (cusTransfer.draw.radius++, handleRangeInput(cusTransfer.draw.radius)) : undefined">+</div> <div class="tips" v-if="cusTransfer.draw.radiusTips">请输入1~60的正整数!</div> km </div> <div class="__cus-buttons-3"> <div class="__cus-button-submit __hover" :style="`cursor: ${cusTransfer.draw.radiusTips ? 'not-allowed' : ''};`" @click="initData">确定</div> <div class="__cus-button-cancel __hover" @click="onCancel">取消</div> </div> </div> <div class="content __box-shadow" v-if="cusTransfer.result.isInit" v-loading="$store.state.gis.analysis.loading"> <div class="head-tab"> <div class="head-tab-item __hover" :class="{active: cusTransfer.switchType === 'power'}" @click="cusTransfer.switchType = 'power'"> <SvgIcon name="search"/>处置力量({{ $store.state.gis.analysis.power.length }}人) </div> <div class="head-tab-item __hover" :class="{active: cusTransfer.switchType === 'device'}" @click="cusTransfer.switchType = 'device'"> <SvgIcon name="search"/>设备({{ $store.state.gis.analysis.device.length }}台) </div> <div class="head-tab-close __hover" @click="$emit('cancel')"> <SvgIcon name="close_2" color="#0069FF" size="14"/> </div> </div> <div class="result"> <template v-if="cusTransfer.switchType === 'power'"> <div class="form"> <CusFormColumn labelWidth="50" :span="24" label="搜索:" v-model:param="cusTransfer.result.power.tempForm.text" /> <div class="__cus-buttons-2"> <div class="__cus-button-submit __hover" @click="onSearchPower">搜索</div> <div class="__cus-button-cancel __hover" @click="onResetPower">重置</div> </div> </div> <div class="table"> <CusTable :tableData="powerTableDataCpt" :tableHead="cusTransfer.result.power.head" :total="powerTableFilterCpt.length" :page="cusTransfer.result.power.pageNum" :pageSize="cusTransfer.result.power.pageSize" @handlePage="handlePagePower" > </CusTable> </div> </template> <template v-else> <div class="form"> <CusFormColumn labelWidth="50" :span="24" label="搜索:" v-model:param="cusTransfer.result.device.tempForm.text" /> <div class="__cus-buttons-2"> <div class="__cus-button-submit __hover" @click="onSearchDevice">搜索</div> <div class="__cus-button-cancel __hover" @click="onResetDevice">重置</div> </div> </div> <div class="table"> <CusTable :tableData="deviceTableDataCpt" :tableHead="cusTransfer.result.device.head" :total="deviceTableFilterCpt.length" :page="cusTransfer.result.device.pageNum" :pageSize="cusTransfer.result.device.pageSize" @handlePage="handlePageDevice" :row-class-name="deviceTableRowClassName" @row-click="deviceHandleRowClick" > </CusTable> </div> </template> </div> </div> </div> </template> <script lang="ts"> import { defineComponent, computed, onMounted, ref, reactive, watch, getCurrentInstance, ComponentInternalInstance, toRefs, nextTick, onUnmounted } from 'vue' import {useStore} from 'vuex' import {useRouter, useRoute} from 'vue-router' import {ElMessage, ElMessageBox} from "element-plus"; import * as interaction from "ol/interaction"; import * as geom from 'ol/geom'; import * as style from "ol/style"; import * as ol from "ol"; import SelectChartCom from "@/views/gis/layout/tools/select-chart.vue"; import * as turf from "@turf/turf"; export default defineComponent({ name: '', components: {SelectChartCom}, props: { map: { required: true, default: <any>{} }, mapFunc: { required: true }, transfer: {} }, setup(props, {emit}) { const store = useStore(); const router = useRouter(); const route = useRoute(); const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties const state = reactive({ transfer: <any>props.transfer, cusTransfer: <any>{ draw: { center: null, radius: 5, wkt: '', radiusTips: false }, analysisDraw: <any>null, switchType: 'power', result: { isInit: false, power: { head: [ {value: "name", label: "姓名", show: true,}, {value: "phone", label: "联系电话", show: true, width: 120}, {value: "area", label: "管辖区域", show: true,}, {value: "distance", label: "距离", show: true}, ], data: <any>[], pageNum: 1, pageSize: 20, form: {}, tempForm: { text: '' } }, device: { head: [ {value: "name", label: "名称", show: true,}, {value: "status", label: "状态", show: true, width: 60}, {value: "type", label: "类型", show: true, width: 90}, {value: "distance", label: "距离", show: true, width: 90}, ], data: <any>[], pageNum: 1, pageSize: 20, form: {}, tempForm: { text: '' } } }, analysisDrawHelpTooltipElement: null, }, }) const handleRangeInput = (v) => { const nV = Number(v) if (!isNaN(Number(nV))) { if (nV < 1 || nV > 60) { state.cusTransfer.draw.radiusTips = true } else { state.cusTransfer.draw.radiusTips = false state.cusTransfer.draw.radius = nV setCircle() } } } const initLayer = () => { store.state.gis.analysis.layer.setVisible(true) if (store.state.gis.analysis.wkt) { if (state.cusTransfer.analysisDraw) { props.map.addInteraction(state.cusTransfer.analysisDraw); } } else { let sketch; let helpTooltip; const createHelpTooltip = () => { const id = 'analysisDrawHelpTooltipElementId' if (state.cusTransfer.analysisDrawHelpTooltipElement) { props.map.removeOverlay(props.map.getOverlayById(id)) state.cusTransfer.analysisDrawHelpTooltipElement.parentNode?.removeChild(state.cusTransfer.analysisDrawHelpTooltipElement); } state.cusTransfer.analysisDrawHelpTooltipElement = document.createElement('div'); state.cusTransfer.analysisDrawHelpTooltipElement.className = 'tooltip hidden'; helpTooltip = new ol.Overlay({ id, element: state.cusTransfer.analysisDrawHelpTooltipElement, offset: [15, 0], positioning: 'center-left' }); props.map.addOverlay(helpTooltip); } createHelpTooltip(); //创建帮助提示框 // 标绘 state.cusTransfer.analysisDraw = new interaction.Draw({ source: store.state.gis.analysis.source,//测量绘制层数据源 type: 'Circle', //几何图形类型 style: new style.Style({ stroke: new style.Stroke({ color: '#2860F1', width: 2, lineDash: [10, 10] }), fill: new style.Fill({ color: 'rgba(20, 129, 241, 0.1)', }), }) }); // @ts-ignore props.map.addInteraction(state.cusTransfer.analysisDraw); const drawstartHandle = (evt) => { sketch = evt.feature; //绘制的要素 } state.cusTransfer.analysisDraw.on('drawstart', drawstartHandle); const drawendHandle = (evt) => { // 标绘的时候不需要最终结果dom props.map.removeOverlay(helpTooltip) sketch = null; //置空当前绘制的要素对象 state.cusTransfer.analysisDrawHelpTooltipElement.parentNode.removeChild(state.cusTransfer.analysisDrawHelpTooltipElement); state.cusTransfer.analysisDrawHelpTooltipElement = null; //置空测量工具提示框对象 state.cusTransfer.analysisDraw.un('drawstart', drawstartHandle); state.cusTransfer.analysisDraw.un('drawend', drawendHandle); props.map.removeInteraction(state.cusTransfer.analysisDraw); props.map.un('pointermove', pointerMoveHandler) state.cusTransfer.analysisDraw = null store.state.gis.analysis.feature = evt.feature store.state.gis.analysis.feature.set('featureType', 'analysisCircle') getCircleParams(evt.feature.getGeometry()) } state.cusTransfer.analysisDraw.on('drawend', drawendHandle); const getCircleParams = (circle) => { const sourceProj = props.map.getView().getProjection(); let radius = Math.round(circle.getRadius() * sourceProj.getMetersPerUnit() / 1000) if (radius > 60) { radius = 60 } state.cusTransfer.draw.center = circle.getCenter() state.cusTransfer.draw.radius = radius setCircle() } const pointerMoveHandler = (evt) => { if (evt.dragging) { return; } let helpMsg = '单击开始标绘';//当前默认提示信息 //判断绘制几何类型设置相应的帮助提示信息 if (sketch) { helpMsg = '双击结束标绘'; } if (state.cusTransfer.analysisDrawHelpTooltipElement) { state.cusTransfer.analysisDrawHelpTooltipElement.innerHTML = helpMsg; //将提示信息设置到对话框中显示 helpTooltip.setPosition(evt.coordinate);//设置帮助提示框的位置 state.cusTransfer.analysisDrawHelpTooltipElement.classList.remove('hidden');//移除帮助提示框的隐藏样式进行显示 } }; props.map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件,动态显示帮助提示框内容 } } const setCircle = () => { const circle = turf.circle(state.cusTransfer.draw.center, state.cusTransfer.draw.radius, {steps: 32, units: 'kilometers'}) store.state.gis.analysis.feature.setGeometry(new geom.Polygon(circle.geometry.coordinates)) state.cusTransfer.draw.wkt = that.$easyMap.formatPosition.cpnTwpn(store.state.gis.analysis.feature.getGeometry().getCoordinates()) } const initData = () => { if (!state.cusTransfer.draw.radiusTips) { state.cusTransfer.result.isInit = true state.cusTransfer.result.power.pageNum = 1 state.cusTransfer.result.device.pageNum = 1 store.dispatch('gis/LOAD_GIS_ANALYSIS', { center: state.cusTransfer.draw.center, wkt: state.cusTransfer.draw.wkt }) that.$easyMap.getShapeView(props.map, that.$easyMap.formatPosition.wpnTcpn(state.cusTransfer.draw.wkt)[0]) } } const powerTableFilterCpt = computed(() => { return store.state.gis.analysis.power.filter(v => v.name.includes(state.cusTransfer.result.power.form.text)) }) const powerTableDataCpt = computed(() => { return powerTableFilterCpt.value.slice((state.cusTransfer.result.power.pageNum - 1) * state.cusTransfer.result.power.pageSize, state.cusTransfer.result.power.pageNum * state.cusTransfer.result.power.pageSize) }) const handlePagePower = ({page, pageSize}: any) => { state.cusTransfer.result.power.pageNum = page state.cusTransfer.result.power.pageSize = pageSize } const onSearchPower = () => { state.cusTransfer.result.power.pageNum = 1 state.cusTransfer.result.power.form = JSON.parse(JSON.stringify(state.cusTransfer.result.power.tempForm)) } const onResetPower = () => { state.cusTransfer.result.power.tempForm = { text: '', } onSearchPower() } const deviceTableFilterCpt = computed(() => { return store.state.gis.analysis.device.filter(v => v.name.includes(state.cusTransfer.result.device.form.text)) }) const deviceTableDataCpt = computed(() => { return deviceTableFilterCpt.value.slice((state.cusTransfer.result.device.pageNum - 1) * state.cusTransfer.result.device.pageSize, state.cusTransfer.result.device.pageNum * state.cusTransfer.result.device.pageSize) }) const handlePageDevice = ({page, pageSize}: any) => { state.cusTransfer.result.device.pageNum = page state.cusTransfer.result.device.pageSize = pageSize } const onSearchDevice = () => { state.cusTransfer.result.device.pageNum = 1 state.cusTransfer.result.device.form = JSON.parse(JSON.stringify(state.cusTransfer.result.device.tempForm)) } const onResetDevice = () => { state.cusTransfer.result.device.tempForm = { text: '', } onSearchDevice() } const onCancel = () => { emit('cancel') } const deviceTableRowClassName = ({row}) => { if (row.id === store.state.gis.gisParams.default.feature?.getId()) { return 'row-active' } return '' } const deviceHandleRowClick = (row) => { if (row.id === store.state.gis.gisParams.default.feature?.getId()) { store.dispatch('gis/LOAD_GIS_PARAMS_DEFAULT_RESET') } else { store.dispatch('gis/LOAD_GIS_PARAMS_DEFAULT_SB', { wkt: row.wkt, id: row.id, info: row.info }) } } watch(() => state.cusTransfer, () => { emit('update:transfer', state.cusTransfer) }, { deep: true }) onMounted(() => { if (store.state.gis.gisParams.qy.analysisWKT) { emit('cancel') ElMessage.warning('请先关闭企业周边设备!') } else { if (props.transfer) { state.cusTransfer = props.transfer } else { emit('update:transfer', state.cusTransfer) } state.cusTransfer.result.power.form = JSON.parse(JSON.stringify(state.cusTransfer.result.power.tempForm)) state.cusTransfer.result.device.form = JSON.parse(JSON.stringify(state.cusTransfer.result.device.tempForm)) initLayer() } }) onUnmounted(() => { state.cusTransfer.result.isInit = false store.state.gis.analysis.layer.setVisible(false) if (state.cusTransfer.analysisDraw) { props.map.removeInteraction(state.cusTransfer.analysisDraw); } state.cusTransfer.analysisDrawHelpTooltipElement?.parentNode.removeChild(state.cusTransfer.analysisDrawHelpTooltipElement); store.dispatch('gis/LOAD_GIS_ANALYSIS_RESET') }) return { ...toRefs(state), handleRangeInput, initData, setCircle, powerTableFilterCpt, powerTableDataCpt, handlePagePower, onSearchPower, onResetPower, deviceTableFilterCpt, deviceTableDataCpt, handlePageDevice, onSearchDevice, onResetDevice, onCancel, deviceTableRowClassName, deviceHandleRowClick, } }, }) </script> <style scoped lang="scss"> .draw-edit { width: 160px; height: 66px; background: #FFFFFF; opacity: 0.8; border-radius: 5px; position: fixed; bottom: 68px; left: calc((100% - 160px) / 2); display: flex; flex-direction: column; justify-content: space-between; padding: 9px 0; .draw-edit-content { display: flex; align-items: center; justify-content: center; font-size: 12px; font-family: Microsoft YaHei; font-weight: 400; color: #808080; .radius-min, .radius-max { margin: 0 3px; &:hover { color: #409EFF; } } :deep(.cus-form-column) { max-width: unset; width: 44px; flex: unset; .el-form-item { margin: 0; .el-form-item__content { height: 20px; .el-input { .el-input__wrapper { padding: 0; border-radius: 5px; .el-input__inner { height: 100%; text-align: center; border: 1px solid #808080; border-radius: 5px; &::placeholder { font-size: 12px; font-family: Microsoft YaHei; } } } } } } } .tips { $footH: 6px; $bgColor: rgba(255, 255, 255, 0.8); position: absolute; top: -28px; right: -10px; font-size: 12px; font-family: Microsoft YaHei; font-weight: 400; color: #E60012; background: $bgColor; border-radius: 4px; padding: 6px 8px; display: flex; align-items: center; justify-content: center; &:after { content: ''; position: absolute; bottom: -$footH; border-top: $footH solid $bgColor; border-left: $footH solid transparent; border-right: $footH solid transparent; } } } } .content { position: fixed; width: 404px; height: calc(100% - 100px); background-color: #FFFFFF; box-sizing: border-box; display: flex; flex-direction: column; .head-tab { height: 40px; width: 100%; border-bottom: 1px solid #EEEEEE; display: flex; align-items: center; box-sizing: border-box; padding-left: 12px; padding-right: 22px; .head-tab-item { height: 100%; display: flex; align-items: center; justify-content: center; position: relative; font-size: 14px; font-family: Microsoft YaHei; font-weight: 400; color: #757575; padding: 0 4px; min-width: 60px; margin-right: 10px; &:last-child { margin-right: 0; } &.active { color: #0069FF; &:after { content: ''; position: absolute; width: 100%; height: 3px; bottom: -1px; background-color: #0062E9; } } } .head-tab-close { margin-left: auto; } } .result { flex: 1; display: flex; flex-direction: column; padding: 0 10px 10px 10px; .form { display: flex; align-items: center; margin: 10px 0; :deep(.el-form-item) { margin-bottom: 0px; } .cus-form-column { flex: 1; margin-right: 8px; } } .table { flex: 1; :deep(.row-active) { >td { background: rgba(16,140,243,0.1); } } } } } </style>