index.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <template>
  2. <div class="layer-list-panel" :class="{ 'fix-layer-list-panel': leftPanelHide }">
  3. <div class="layer-list-panel-title">
  4. <div class="title">
  5. <img src="@/assets/image/common/layerIcon.png" alt="" />
  6. <span style="margin-left: 0.08rem">资源列表</span>
  7. </div>
  8. <div @click="onExpandChange" style="cursor: pointer">
  9. <img v-show="isExpanded" src="@/assets/image/common/arrow-up.png" style="width: 14px; height: 12px" />
  10. <img v-show="!isExpanded" src="@/assets/image/common/arrow-up.png" style="transform: rotate(180deg); width: 14px; height: 12px" />
  11. </div>
  12. </div>
  13. <div class="layer-list-panel-content" v-show="isExpanded">
  14. <el-tree ref="treeRef" :data="treeData" show-checkbox node-key="id" :props="defaultProps" @check-change="onCheckChange" :default-expanded-keys="['1']">
  15. <template #default="{ node, data }">
  16. <span class="custom-tree-node">
  17. <span>{{ node.label }}</span>
  18. <i v-if="data.loading" class="el-icon-loading" style="margin-left: 4px; color: #409eff"></i>
  19. <i v-if="data.error" class="el-icon-warning" style="margin-left: 4px; color: #f56c6c" :title="data.error"></i>
  20. </span>
  21. </template>
  22. </el-tree>
  23. </div>
  24. </div>
  25. </template>
  26. <script>
  27. import * as mars3d from 'mars3d'
  28. let layerCache = {}
  29. export default {
  30. name: 'LayerListView',
  31. data() {
  32. return {
  33. leftPanelHide: false,
  34. isExpanded: true,
  35. defaultProps: { children: 'children', label: 'label' },
  36. treeData: [
  37. {
  38. id: '1',
  39. label: '综合信息',
  40. children: [
  41. {
  42. id: '1-1',
  43. label: '生态区',
  44. children: [
  45. { id: '1-1-1', label: '提防背河坡脚线', meta: { type: 'polyline', url: '/geojson/difangbeihe.geojson' } },
  46. { id: '1-1-2', label: '河道管理范围线', meta: { type: 'polyline', url: '/geojson/hedaoguanli.geojson' } },
  47. { id: '1-1-3', label: '一二级管控区界限', meta: { type: 'polyline', url: '/geojson/yijiguanxian.geojson' } },
  48. { id: '1-1-4', label: '生态区界限', meta: { type: 'polyline', url: '/geojson/shengtaiqu.geojson' } },
  49. { id: '1-1-5', label: '城市核心区', meta: { type: 'polyline', url: '/geojson/chengshihx.geojson' } },
  50. { id: '1-1-6', label: '农村区段', meta: { type: 'polyline', url: '/geojson/nongcunqd.geojson' } },
  51. { id: '1-1-7', label: '规划区', meta: { type: 'polyline', url: '/geojson/guihuaqu.geojson' } },
  52. { id: '1-1-8', label: '城市核心区(右岸)', meta: { type: 'polyline', url: '/geojson/chengshihx_r.geojson' } },
  53. { id: '1-1-9', label: '农村区段(右岸)', meta: { type: 'polyline', url: '/geojson/nongcunqd_r.geojson' } }
  54. ]
  55. },
  56. { id: '1-2', label: '监测设备' },
  57. { id: '1-3', label: '入河排水(污)口' },
  58. { id: '1-4', label: '河道管理站' }
  59. ]
  60. },
  61. {
  62. id: '2',
  63. label: '水文监测',
  64. children: [
  65. { id: '2-1', label: '水文监测点1', meta: { type: 'point', url: '/geojson/sw1.geojson' } },
  66. { id: '2-2', label: '水文监测点2', meta: { type: 'point', url: '/geojson/sw2.geojson' } }
  67. ]
  68. },
  69. {
  70. id: '3',
  71. label: '采砂区',
  72. children: [
  73. { id: '3-1', label: '兴平市宜空采砂区', meta: { type: 'polygon', url: '/geojson/yikong.geojson' } },
  74. { id: '3-2', label: '兴平市团结采砂区', meta: { type: 'polygon', url: '/geojson/tuanjie.geojson' } },
  75. { id: '3-3', label: '兴平市汤坊龙兴1区采砂区', meta: { type: 'polygon', url: '/geojson/longxing.geojson' } }
  76. ]
  77. }
  78. ],
  79. mainMenu: ''
  80. }
  81. },
  82. created() {
  83. this.mainMenu = this.$route.params.menu
  84. },
  85. mounted() {
  86. this.$globalEventBus.$on('toggleLeftPanel', (val) => {
  87. this.leftPanelHide = val
  88. })
  89. },
  90. watch: {
  91. mainMenu: {
  92. handler(val) {
  93. if (val === 'hydrologicInfo') {
  94. this.handleData(true)
  95. } else {
  96. this.handleData(false)
  97. }
  98. }
  99. }
  100. },
  101. methods: {
  102. onExpandChange() {
  103. this.isExpanded = !this.isExpanded
  104. },
  105. async onCheckChange(node, checked) {
  106. const id = node.id
  107. if (!node.meta?.url) {
  108. return
  109. }
  110. if (checked) {
  111. // 已缓存直接显示
  112. if (layerCache[id]) {
  113. layerCache[id].show = true
  114. return
  115. }
  116. // 开始加载
  117. this.$set(node, 'loading', true)
  118. this.$set(node, 'error', '')
  119. try {
  120. const layer = new mars3d.layer.GeoJsonLayer({
  121. id: node.id,
  122. name: node.label,
  123. url: node.meta.url,
  124. crs: 'EPSG:4326',
  125. clampToGround: true,
  126. symbol: this.getStyleByName(node.label)
  127. })
  128. console.log(window.map, 111111111)
  129. window.map.addLayer(layer)
  130. this.bindEvent(layer)
  131. layerCache[id] = layer
  132. // 父子关联:勾选子节点时,父节点作为 groupId
  133. const parent = this.$refs.treeRef.getNode(id).parent
  134. if (parent && parent.data.id) {
  135. layer.options.parentId = parent.data.id
  136. }
  137. } catch (e) {
  138. this.$set(node, 'error', e.message || '加载失败')
  139. } finally {
  140. this.$set(node, 'loading', false)
  141. }
  142. } else {
  143. // 取消勾选 -> 销毁
  144. if (layerCache[id]) {
  145. window.map.removeLayer(layerCache[id])
  146. delete layerCache[id]
  147. }
  148. }
  149. },
  150. getStyleByName(name) {
  151. if (name === '生态区界限') {
  152. return { type: 'polyline', styleOptions: { color: '#0c5b0f', width: 4 } }
  153. } else if (name === '河道管理范围线') {
  154. return {
  155. type: 'polyline',
  156. styleOptions: { width: 4, materialType: mars3d.MaterialType.PolylineDash, materialOptions: { color: '#0c5b0f', dashLength: 40 } }
  157. }
  158. } else if (name === '一二级管控区界限') {
  159. return { type: 'polyline', styleOptions: { color: '#db7f06', width: 4 } }
  160. } else if (name.indexOf('水文') > -1) {
  161. return {
  162. type: 'billboard',
  163. styleOptions: {
  164. image: require('./image/水文站.png'),
  165. scale: 1,
  166. clampToGround: true,
  167. horizontalOrigin: this.Cesium.HorizontalOrigin.CENTER,
  168. verticalOrigin: this.Cesium.VerticalOrigin.BOTTOM,
  169. pixelOffset: new this.Cesium.Cartesian2(0, -6), // 偏移量
  170. distanceDisplayCondition: new this.Cesium.DistanceDisplayCondition(0.0, 500000) // 按视距显示
  171. }
  172. }
  173. }
  174. },
  175. // 处理水文站数据
  176. handleData(isShow) {
  177. const nodeIds = ['2-1', '2-2']
  178. this.$nextTick(() => {
  179. nodeIds.forEach((id) => {
  180. this.$refs.treeRef.setChecked(id, isShow)
  181. const node = this.$refs.treeRef.getNode(id)
  182. this.onCheckChange(node.data, isShow)
  183. })
  184. })
  185. },
  186. // 绑定点击事件
  187. bindEvent(layer) {
  188. const _that = this
  189. if (layer.id === '2-1' || layer.id === '2-2') {
  190. layer.on(mars3d.EventType.click, function (event) {
  191. _that.$globalEventBus.$emit('clickWaterStation', event)
  192. })
  193. }
  194. }
  195. }
  196. }
  197. </script>
  198. <style lang="scss" scoped>
  199. .layer-list-panel {
  200. position: absolute;
  201. top: px-to-rem(80);
  202. left: px-to-rem(480);
  203. width: px-to-rem(240);
  204. padding: px-to-rem(10);
  205. background: #1b2535;
  206. border-radius: 6px;
  207. opacity: 0.85;
  208. z-index: 1000;
  209. transition: left 0.3s ease-in-out;
  210. .layer-list-panel-title {
  211. margin-bottom: px-to-rem(10);
  212. height: px-to-rem(30);
  213. line-height: px-to-rem(30);
  214. display: flex;
  215. justify-content: space-between;
  216. align-items: center;
  217. .title {
  218. display: flex;
  219. justify-content: center;
  220. align-items: center;
  221. font-size: px-to-rem(18);
  222. color: #eaf3fe;
  223. }
  224. }
  225. .layer-list-panel-content {
  226. margin: px-to-rem(-10);
  227. padding: px-to-rem(10);
  228. max-height: px-to-rem(340);
  229. overflow: auto;
  230. :deep(.el-tree) {
  231. background: transparent;
  232. color: #fff;
  233. .el-tree-node__content {
  234. height: unset;
  235. }
  236. .el-tree-node__content:hover,
  237. .el-upload-list__item:hover,
  238. .el-tree-node:focus > .el-tree-node__content {
  239. background-color: transparent;
  240. height: unset;
  241. }
  242. .el-tree-node__label {
  243. white-space: wrap;
  244. }
  245. }
  246. .custom-tree-node {
  247. white-space: wrap;
  248. font-size: px-to-rem(16);
  249. }
  250. }
  251. }
  252. .fix-layer-list-panel {
  253. left: px-to-rem(20);
  254. }
  255. </style>