analysis.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <template>
  2. <div class="analysis-com">
  3. <div class="draw-edit" v-if="cusTransfer.draw.center">
  4. <div class="draw-edit-content">
  5. 周边范围:
  6. <div class="radius-min __hover" @click="cusTransfer.draw.radius > 1 ? (cusTransfer.draw.radius--, setCircle()) : undefined">-</div>
  7. <CusFormColumn
  8. link="number"
  9. label=""
  10. :min="1"
  11. :clearable="false"
  12. v-model:param="cusTransfer.draw.radius"
  13. @blur="handleRangeBlur"/>
  14. <div class="radius-max __hover" @click="cusTransfer.draw.radius++, setCircle()">+</div>
  15. km
  16. </div>
  17. <div class="__cus-buttons-3">
  18. <div class="__cus-button-submit __hover" @click="initData">确定</div>
  19. <div class="__cus-button-cancel __hover" @click="onCancel">取消</div>
  20. </div>
  21. </div>
  22. <div class="content __box-shadow" v-if="cusTransfer.result.isInit" v-loading="$store.state.gis.analysis.loading">
  23. <div class="head-tab">
  24. <div class="head-tab-item __hover" :class="{active: cusTransfer.switchType === 'power'}" @click="cusTransfer.switchType = 'power'">
  25. <SvgIcon name="search"/>处置力量({{ $store.state.gis.analysis.power.length }}人)
  26. </div>
  27. <div class="head-tab-item __hover" :class="{active: cusTransfer.switchType === 'device'}" @click="cusTransfer.switchType = 'device'">
  28. <SvgIcon name="search"/>设备({{ $store.state.gis.analysis.device.length }}台)
  29. </div>
  30. <div class="head-tab-close __hover" @click="$emit('cancel')">
  31. <SvgIcon name="close_2" color="#0069FF" size="14"/>
  32. </div>
  33. </div>
  34. <div class="result">
  35. <template v-if="cusTransfer.switchType === 'power'">
  36. <div class="form">
  37. <CusFormColumn
  38. labelWidth="50"
  39. :span="24"
  40. label="搜索:"
  41. v-model:param="cusTransfer.result.power.tempForm.text"
  42. />
  43. <div class="__cus-buttons-2">
  44. <div class="__cus-button-submit __hover" @click="onSearchPower">搜索</div>
  45. <div class="__cus-button-cancel __hover" @click="onResetPower">重置</div>
  46. </div>
  47. </div>
  48. <div class="table">
  49. <CusTable
  50. :tableData="powerTableDataCpt"
  51. :tableHead="cusTransfer.result.power.head"
  52. :total="powerTableFilterCpt.length"
  53. :page="cusTransfer.result.power.pageNum"
  54. :pageSize="cusTransfer.result.power.pageSize"
  55. @handlePage="handlePagePower"
  56. >
  57. </CusTable>
  58. </div>
  59. </template>
  60. <template v-else>
  61. <div class="form">
  62. <CusFormColumn
  63. labelWidth="50"
  64. :span="24"
  65. label="搜索:"
  66. v-model:param="cusTransfer.result.device.tempForm.text"
  67. />
  68. <div class="__cus-buttons-2">
  69. <div class="__cus-button-submit __hover" @click="onSearchDevice">搜索</div>
  70. <div class="__cus-button-cancel __hover" @click="onResetDevice">重置</div>
  71. </div>
  72. </div>
  73. <div class="table">
  74. <CusTable
  75. :tableData="deviceTableDataCpt"
  76. :tableHead="cusTransfer.result.device.head"
  77. :total="deviceTableFilterCpt.length"
  78. :page="cusTransfer.result.device.pageNum"
  79. :pageSize="cusTransfer.result.device.pageSize"
  80. @handlePage="handlePageDevice"
  81. >
  82. </CusTable>
  83. </div>
  84. </template>
  85. </div>
  86. </div>
  87. </div>
  88. </template>
  89. <script lang="ts">
  90. import {
  91. defineComponent,
  92. computed,
  93. onMounted,
  94. ref,
  95. reactive,
  96. watch,
  97. getCurrentInstance,
  98. ComponentInternalInstance,
  99. toRefs,
  100. nextTick, onUnmounted
  101. } from 'vue'
  102. import {useStore} from 'vuex'
  103. import {useRouter, useRoute} from 'vue-router'
  104. import {ElMessage, ElMessageBox} from "element-plus";
  105. import * as interaction from "ol/interaction";
  106. import * as geom from 'ol/geom';
  107. import * as style from "ol/style";
  108. import * as ol from "ol";
  109. import SelectChartCom from "@/views/gis/layout/tools/select-chart.vue";
  110. import * as turf from "@turf/turf";
  111. import axios from "axios";
  112. import {formatPosition} from "@/utils/easyMap";
  113. export default defineComponent({
  114. name: '',
  115. components: {SelectChartCom},
  116. props: {
  117. map: {
  118. required: true,
  119. default: <any>{}
  120. },
  121. mapFunc: {
  122. required: true
  123. },
  124. transfer: {}
  125. },
  126. setup(props, {emit}) {
  127. const store = useStore();
  128. const router = useRouter();
  129. const route = useRoute();
  130. const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
  131. const state = reactive({
  132. transfer: <any>props.transfer,
  133. cusTransfer: <any>{
  134. draw: {
  135. center: null,
  136. radius: 5,
  137. wkt: ''
  138. },
  139. analysisDraw: <any>null,
  140. switchType: 'power',
  141. result: {
  142. isInit: false,
  143. power: {
  144. head: [
  145. {value: "name", label: "姓名", show: true,},
  146. {value: "phone", label: "联系电话", show: true, width: 120},
  147. {value: "area", label: "管辖区域", show: true,},
  148. {value: "distance", label: "距离", show: true},
  149. ],
  150. data: <any>[],
  151. pageNum: 1,
  152. pageSize: 20,
  153. form: {},
  154. tempForm: {
  155. text: ''
  156. }
  157. },
  158. device: {
  159. head: [
  160. {value: "name", label: "名称", show: true,},
  161. {value: "status", label: "状态", show: true, width: 60},
  162. {value: "type", label: "类型", show: true, width: 90},
  163. {value: "distance", label: "距离", show: true, width: 90},
  164. ],
  165. data: <any>[],
  166. pageNum: 1,
  167. pageSize: 20,
  168. form: {},
  169. tempForm: {
  170. text: ''
  171. }
  172. }
  173. },
  174. analysisDrawHelpTooltipElement: null,
  175. },
  176. })
  177. const handleRangeBlur = () => {
  178. if (!state.cusTransfer.draw.radius) {
  179. state.cusTransfer.draw.radius = 5
  180. }
  181. setCircle()
  182. }
  183. const initLayer = () => {
  184. store.state.gis.analysis.layer.setVisible(true)
  185. if (store.state.gis.analysis.wkt) {
  186. if (state.cusTransfer.analysisDraw) {
  187. props.map.addInteraction(state.cusTransfer.analysisDraw);
  188. }
  189. } else {
  190. let sketch;
  191. let helpTooltip;
  192. const createHelpTooltip = () => {
  193. const id = 'analysisDrawHelpTooltipElementId'
  194. if (state.cusTransfer.analysisDrawHelpTooltipElement) {
  195. props.map.removeOverlay(props.map.getOverlayById(id))
  196. state.cusTransfer.analysisDrawHelpTooltipElement.parentNode.removeChild(state.cusTransfer.analysisDrawHelpTooltipElement);
  197. }
  198. state.cusTransfer.analysisDrawHelpTooltipElement = document.createElement('div');
  199. state.cusTransfer.analysisDrawHelpTooltipElement.className = 'tooltip hidden';
  200. helpTooltip = new ol.Overlay({
  201. id,
  202. element: state.cusTransfer.analysisDrawHelpTooltipElement,
  203. offset: [15, 0],
  204. positioning: 'center-left'
  205. });
  206. props.map.addOverlay(helpTooltip);
  207. }
  208. createHelpTooltip(); //创建帮助提示框
  209. // 标绘
  210. state.cusTransfer.analysisDraw = new interaction.Draw({
  211. source: store.state.gis.analysis.source,//测量绘制层数据源
  212. type: 'Circle', //几何图形类型
  213. style: new style.Style({
  214. stroke: new style.Stroke({
  215. color: '#2860F1',
  216. width: 2,
  217. lineDash: [10, 10]
  218. }),
  219. fill: new style.Fill({
  220. color: 'rgba(20, 129, 241, 0.1)',
  221. }),
  222. })
  223. });
  224. // @ts-ignore
  225. props.map.addInteraction(state.cusTransfer.analysisDraw);
  226. const drawstartHandle = (evt) => {
  227. sketch = evt.feature; //绘制的要素
  228. }
  229. state.cusTransfer.analysisDraw.on('drawstart', drawstartHandle);
  230. const drawendHandle = (evt) => {
  231. // 标绘的时候不需要最终结果dom
  232. props.map.removeOverlay(helpTooltip)
  233. sketch = null; //置空当前绘制的要素对象
  234. state.cusTransfer.analysisDrawHelpTooltipElement.parentNode.removeChild(state.cusTransfer.analysisDrawHelpTooltipElement);
  235. state.cusTransfer.analysisDrawHelpTooltipElement = null; //置空测量工具提示框对象
  236. state.cusTransfer.analysisDraw.un('drawstart', drawstartHandle);
  237. state.cusTransfer.analysisDraw.un('drawend', drawendHandle);
  238. props.map.removeInteraction(state.cusTransfer.analysisDraw);
  239. props.map.un('pointermove', pointerMoveHandler)
  240. state.cusTransfer.analysisDraw = null
  241. store.state.gis.analysis.feature = evt.feature
  242. getCircleParams(evt.feature.getGeometry())
  243. }
  244. state.cusTransfer.analysisDraw.on('drawend', drawendHandle);
  245. const getCircleParams = (circle) => {
  246. const sourceProj = props.map.getView().getProjection();
  247. const radius = Math.round(circle.getRadius() * sourceProj.getMetersPerUnit() / 1000)
  248. state.cusTransfer.draw.center = circle.getCenter()
  249. state.cusTransfer.draw.radius = radius
  250. setCircle()
  251. }
  252. const pointerMoveHandler = (evt) => {
  253. if (evt.dragging) {
  254. return;
  255. }
  256. let helpMsg = '单击开始标绘';//当前默认提示信息
  257. //判断绘制几何类型设置相应的帮助提示信息
  258. if (sketch) {
  259. helpMsg = '双击结束标绘';
  260. }
  261. state.cusTransfer.analysisDrawHelpTooltipElement.innerHTML = helpMsg; //将提示信息设置到对话框中显示
  262. helpTooltip.setPosition(evt.coordinate);//设置帮助提示框的位置
  263. state.cusTransfer.analysisDrawHelpTooltipElement.classList.remove('hidden');//移除帮助提示框的隐藏样式进行显示
  264. };
  265. props.map.on('pointermove', pointerMoveHandler); //地图容器绑定鼠标移动事件,动态显示帮助提示框内容
  266. }
  267. }
  268. const setCircle = () => {
  269. const circle = turf.circle(state.cusTransfer.draw.center, state.cusTransfer.draw.radius, {steps: 32, units: 'kilometers'})
  270. store.state.gis.analysis.feature.setGeometry(new geom.Polygon(circle.geometry.coordinates))
  271. state.cusTransfer.draw.wkt = that.$easyMap.formatPosition.cpnTwpn(store.state.gis.analysis.feature.getGeometry().getCoordinates())
  272. }
  273. const initData = () => {
  274. state.cusTransfer.result.isInit = true
  275. state.cusTransfer.result.power.pageNum = 1
  276. state.cusTransfer.result.device.pageNum = 1
  277. store.commit('gis/SET_GIS_ANALYSIS', {
  278. center: state.cusTransfer.draw.center,
  279. wkt: state.cusTransfer.draw.wkt
  280. })
  281. }
  282. const powerTableFilterCpt = computed(() => {
  283. return store.state.gis.analysis.power.filter(v => v.name.includes(state.cusTransfer.result.power.form.text))
  284. })
  285. const powerTableDataCpt = computed(() => {
  286. 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)
  287. })
  288. const handlePagePower = ({page, pageSize}: any) => {
  289. state.cusTransfer.result.power.pageNum = page
  290. state.cusTransfer.result.power.pageSize = pageSize
  291. }
  292. const onSearchPower = () => {
  293. state.cusTransfer.result.power.pageNum = 1
  294. state.cusTransfer.result.power.form = JSON.parse(JSON.stringify(state.cusTransfer.result.power.tempForm))
  295. }
  296. const onResetPower = () => {
  297. state.cusTransfer.result.power.tempForm = {
  298. text: '',
  299. }
  300. onSearchPower()
  301. }
  302. const deviceTableFilterCpt = computed(() => {
  303. return store.state.gis.analysis.device.filter(v => v.name.includes(state.cusTransfer.result.device.form.text))
  304. })
  305. const deviceTableDataCpt = computed(() => {
  306. 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)
  307. })
  308. const handlePageDevice = ({page, pageSize}: any) => {
  309. state.cusTransfer.result.device.pageNum = page
  310. state.cusTransfer.result.device.pageSize = pageSize
  311. }
  312. const onSearchDevice = () => {
  313. state.cusTransfer.result.device.pageNum = 1
  314. state.cusTransfer.result.device.form = JSON.parse(JSON.stringify(state.cusTransfer.result.device.tempForm))
  315. }
  316. const onResetDevice = () => {
  317. state.cusTransfer.result.device.tempForm = {
  318. text: '',
  319. }
  320. onSearchDevice()
  321. }
  322. const onCancel = () => {
  323. emit('cancel')
  324. }
  325. watch(() => state.cusTransfer, () => {
  326. emit('update:transfer', state.cusTransfer)
  327. }, { deep: true })
  328. onMounted(() => {
  329. if (store.state.gis.gisParams.qy.analysisWKT) {
  330. emit('cancel')
  331. ElMessage.warning('请先关闭企业周边设备!')
  332. } else {
  333. if (props.transfer) {
  334. state.cusTransfer = props.transfer
  335. } else {
  336. emit('update:transfer', state.cusTransfer)
  337. }
  338. state.cusTransfer.result.power.form = JSON.parse(JSON.stringify(state.cusTransfer.result.power.tempForm))
  339. state.cusTransfer.result.device.form = JSON.parse(JSON.stringify(state.cusTransfer.result.device.tempForm))
  340. initLayer()
  341. }
  342. })
  343. onUnmounted(() => {
  344. state.cusTransfer.result.isInit = false
  345. store.state.gis.analysis.layer.setVisible(false)
  346. if (state.cusTransfer.analysisDraw) {
  347. props.map.removeInteraction(state.cusTransfer.analysisDraw);
  348. }
  349. store.commit('gis/SET_GIS_ANALYSIS_RESET')
  350. })
  351. return {
  352. ...toRefs(state),
  353. handleRangeBlur,
  354. initData,
  355. setCircle,
  356. powerTableFilterCpt,
  357. powerTableDataCpt,
  358. handlePagePower,
  359. onSearchPower,
  360. onResetPower,
  361. deviceTableFilterCpt,
  362. deviceTableDataCpt,
  363. handlePageDevice,
  364. onSearchDevice,
  365. onResetDevice,
  366. onCancel
  367. }
  368. },
  369. })
  370. </script>
  371. <style scoped lang="scss">
  372. .draw-edit {
  373. width: 160px;
  374. height: 66px;
  375. background: #FFFFFF;
  376. opacity: 0.8;
  377. border-radius: 5px;
  378. position: fixed;
  379. bottom: 68px;
  380. left: calc((100% - 160px) / 2);
  381. display: flex;
  382. flex-direction: column;
  383. justify-content: space-between;
  384. padding: 9px 0;
  385. .draw-edit-content {
  386. display: flex;
  387. align-items: center;
  388. justify-content: center;
  389. font-size: 12px;
  390. font-family: Microsoft YaHei;
  391. font-weight: 400;
  392. color: #808080;
  393. .radius-min, .radius-max {
  394. margin: 0 3px;
  395. &:hover {
  396. color: #409EFF;
  397. }
  398. }
  399. :deep(.cus-form-column) {
  400. max-width: unset;
  401. width: 44px;
  402. flex: unset;
  403. .el-form-item {
  404. margin: 0;
  405. .el-form-item__content {
  406. height: 20px;
  407. .el-input {
  408. .el-input__wrapper {
  409. padding: 0;
  410. border-radius: 5px;
  411. .el-input__inner {
  412. height: 100%;
  413. text-align: center;
  414. border: 1px solid #808080;
  415. border-radius: 5px;
  416. &::placeholder {
  417. font-size: 12px;
  418. font-family: Microsoft YaHei;
  419. }
  420. }
  421. }
  422. }
  423. }
  424. }
  425. }
  426. }
  427. }
  428. .content {
  429. position: fixed;
  430. width: 404px;
  431. height: calc(100% - 100px);
  432. background-color: #FFFFFF;
  433. box-sizing: border-box;
  434. display: flex;
  435. flex-direction: column;
  436. .head-tab {
  437. height: 40px;
  438. width: 100%;
  439. border-bottom: 1px solid #EEEEEE;
  440. display: flex;
  441. align-items: center;
  442. box-sizing: border-box;
  443. padding-left: 12px;
  444. padding-right: 22px;
  445. .head-tab-item {
  446. height: 100%;
  447. display: flex;
  448. align-items: center;
  449. justify-content: center;
  450. position: relative;
  451. font-size: 14px;
  452. font-family: Microsoft YaHei;
  453. font-weight: 400;
  454. color: #757575;
  455. padding: 0 4px;
  456. min-width: 60px;
  457. margin-right: 10px;
  458. &:last-child {
  459. margin-right: 0;
  460. }
  461. &.active {
  462. color: #0069FF;
  463. &:after {
  464. content: '';
  465. position: absolute;
  466. width: 100%;
  467. height: 3px;
  468. bottom: -1px;
  469. background-color: #0062E9;
  470. }
  471. }
  472. }
  473. .head-tab-close {
  474. margin-left: auto;
  475. }
  476. }
  477. .result {
  478. flex: 1;
  479. display: flex;
  480. flex-direction: column;
  481. padding: 0 10px 10px 10px;
  482. .form {
  483. display: flex;
  484. align-items: center;
  485. margin: 10px 0;
  486. :deep(.el-form-item) {
  487. margin-bottom: 0px;
  488. }
  489. .cus-form-column {
  490. flex: 1;
  491. margin-right: 8px;
  492. }
  493. }
  494. .table {
  495. flex: 1;
  496. }
  497. }
  498. }
  499. </style>