|
@@ -0,0 +1,687 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="mapBox">
|
|
|
|
|
+ <div
|
|
|
|
|
+ id="map"
|
|
|
|
|
+ @dragover="e => e.preventDefault()"
|
|
|
|
|
+ @dragleave="isCheck = false"
|
|
|
|
|
+ @dragenter="isCheck = true"
|
|
|
|
|
+ />
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="isEdit"
|
|
|
|
|
+ class="mapBox-menu"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-tree-select
|
|
|
|
|
+ v-model:value="selected"
|
|
|
|
|
+ :options="options"
|
|
|
|
|
+ label-field="name"
|
|
|
|
|
+ key-field="uuid"
|
|
|
|
|
+ children-field="childList"
|
|
|
|
|
+ check-strategy="child"
|
|
|
|
|
+ placeholder="请选择车站"
|
|
|
|
|
+ @update:value="changeMap"
|
|
|
|
|
+ />
|
|
|
|
|
+ <div class="mapBox-menu-content">
|
|
|
|
|
+ <n-scrollbar>
|
|
|
|
|
+ <template
|
|
|
|
|
+ v-for="(item, index) in iconList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="mapBox-menu-content-item"
|
|
|
|
|
+ draggable="true"
|
|
|
|
|
+ @dragstart="currentItem = item"
|
|
|
|
|
+ @dragend="itemDragEnd"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img
|
|
|
|
|
+ :src="item.icon"
|
|
|
|
|
+ alt=""
|
|
|
|
|
+ srcset=""
|
|
|
|
|
+ draggable="false"
|
|
|
|
|
+ >
|
|
|
|
|
+ <p>
|
|
|
|
|
+ {{ item.name }}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </n-scrollbar>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="isEdit && showPoup"
|
|
|
|
|
+ class="mapBox-poup"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-form
|
|
|
|
|
+ ref="formRef"
|
|
|
|
|
+ :model="formMode"
|
|
|
|
|
+ label-placement="left"
|
|
|
|
|
+ label-width="auto"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ :rules="rules"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="元素编号"
|
|
|
|
|
+ path="uuid"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-input
|
|
|
|
|
+ v-model:value="formMode.uuid"
|
|
|
|
|
+ disabled
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="资产编号"
|
|
|
|
|
+ path="guid"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-select
|
|
|
|
|
+ v-model:value="formMode.guid"
|
|
|
|
|
+ placeholder="请选择"
|
|
|
|
|
+ label-field="name"
|
|
|
|
|
+ value-field="guid"
|
|
|
|
|
+ :options="assetOption"
|
|
|
|
|
+ @update:value="selectChange"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="元素类型"
|
|
|
|
|
+ path="type"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-input
|
|
|
|
|
+ v-model:value="formMode.type"
|
|
|
|
|
+ disabled
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="x 坐 标 "
|
|
|
|
|
+ path="x"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-input-number
|
|
|
|
|
+ v-model:value="formMode.x"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ :show-button="false"
|
|
|
|
|
+ @blur="resetMarker('lng', formMode.x)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="y 坐 标 "
|
|
|
|
|
+ path="y"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-input-number
|
|
|
|
|
+ v-model:value="formMode.y"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ :show-button="false"
|
|
|
|
|
+ @blur="resetMarker('lat', formMode.y)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="横向缩放"
|
|
|
|
|
+ path="scaleX"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-input-number
|
|
|
|
|
+ v-model:value="formMode.scaleX"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ :min="0.1"
|
|
|
|
|
+ :show-button="false"
|
|
|
|
|
+ @blur="resetMarker('scaleX', formMode.scaleX, '0')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="纵向缩放"
|
|
|
|
|
+ path="scaleY"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-input-number
|
|
|
|
|
+ v-model:value="formMode.scaleY"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ :min="0.1"
|
|
|
|
|
+ :show-button="false"
|
|
|
|
|
+ @blur="resetMarker('scaleY', formMode.scaleY, '1')"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="水平翻转"
|
|
|
|
|
+ path="flipX"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-switch
|
|
|
|
|
+ v-model:value="formMode.flipX"
|
|
|
|
|
+ @update:value="resetMarker('flipX', formMode.flipX)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ <n-form-item
|
|
|
|
|
+ label="垂直翻转"
|
|
|
|
|
+ path="flipY"
|
|
|
|
|
+ >
|
|
|
|
|
+ <n-switch
|
|
|
|
|
+ v-model:value="formMode.flipY"
|
|
|
|
|
+ @update:value="resetMarker('flipY', formMode.flipY)"
|
|
|
|
|
+ />
|
|
|
|
|
+ </n-form-item>
|
|
|
|
|
+ </n-form>
|
|
|
|
|
+ <div class="mapBox-poup-btns">
|
|
|
|
|
+ <n-button
|
|
|
|
|
+ type="error"
|
|
|
|
|
+ ghost
|
|
|
|
|
+ @click="del"
|
|
|
|
|
+ >
|
|
|
|
|
+ 删除
|
|
|
|
|
+ </n-button>
|
|
|
|
|
+ <n-button
|
|
|
|
|
+ type="primary"
|
|
|
|
|
+ @click="save"
|
|
|
|
|
+ >
|
|
|
|
|
+ 保存
|
|
|
|
|
+ </n-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <script setup lang='ts'>
|
|
|
|
|
+ import * as L from 'leaflet'
|
|
|
|
|
+ import {
|
|
|
|
|
+ onMounted,
|
|
|
|
|
+ onUnmounted,
|
|
|
|
|
+ Ref, ref, watch
|
|
|
|
|
+ } from 'vue'
|
|
|
|
|
+ import '@/../node_modules/leaflet/dist/leaflet.css'
|
|
|
|
|
+ import SocketService from '@/services/socket.service'
|
|
|
|
|
+ import { v1 as uuid } from 'uuid'
|
|
|
|
|
+ import useStore from '@/pages/store'
|
|
|
|
|
+ // ----- 修复L 增加tooltip 缩放报错 重要!!
|
|
|
|
|
+
|
|
|
|
|
+ (L.Tooltip as any).prototype._animateZoom = function (e: { zoom: any; center: any; }) {
|
|
|
|
|
+ if (!(this as any)._map) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const pos = (this as any)._map._latLngToNewLayerPoint((this as any)._latlng, e.zoom, e.center) as any
|
|
|
|
|
+ (this as any)._setPosition(pos)
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ (L.Tooltip as any).prototype._updatePosition = function () {
|
|
|
|
|
+ if (!(this as any)._map) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const pos = (this as any)._map.latLngToLayerPoint((this as any)._latlng) as any
|
|
|
|
|
+ (this as any)._setPosition(pos)
|
|
|
|
|
+ }
|
|
|
|
|
+ // ---------
|
|
|
|
|
+
|
|
|
|
|
+ export interface Item {
|
|
|
|
|
+ icon: string,
|
|
|
|
|
+ x?: number,
|
|
|
|
|
+ y?: number,
|
|
|
|
|
+ scaleX?: number,
|
|
|
|
|
+ scaleY?: number,
|
|
|
|
|
+ guid?: string,
|
|
|
|
|
+ type?: string,
|
|
|
|
|
+ uuid?: string,
|
|
|
|
|
+ item?: string,
|
|
|
|
|
+ isAdd?: boolean,
|
|
|
|
|
+ deviceId?: string,
|
|
|
|
|
+ itemName?: string
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ export interface BaseMap {
|
|
|
|
|
+ DID?: number,
|
|
|
|
|
+ width: number,
|
|
|
|
|
+ height: number,
|
|
|
|
|
+ mapId: string,
|
|
|
|
|
+ name?: string
|
|
|
|
|
+ imgUrl: string,
|
|
|
|
|
+ trackType?: number, // 1电扶梯 2给排水 3通风 4照明 5车站环境检测 6车站暖通 7车站动环
|
|
|
|
|
+ showTip?: boolean
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const socketService = new SocketService()
|
|
|
|
|
+ const props = withDefaults(defineProps<{
|
|
|
|
|
+ isEdit?: boolean, // 是否编辑
|
|
|
|
|
+ baseMap?: BaseMap
|
|
|
|
|
+ }>(), {
|
|
|
|
|
+ isEdit: false,
|
|
|
|
|
+ baseMap: () => ({
|
|
|
|
|
+ imgUrl: '', width: 0, height: 0, mapId: '', showTip: false
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ const emit = defineEmits<{(evt: 'markerClick', value: Item): void }>()
|
|
|
|
|
+ const Map = ref()
|
|
|
|
|
+ const iconList = ref([] as { icon: string, name: string }[])
|
|
|
|
|
+ const currentItem: Ref<Item | undefined> = ref()
|
|
|
|
|
+ const isCheck = ref(false)
|
|
|
|
|
+ const options = ref([] as BaseMap[])
|
|
|
|
|
+ const selected = ref('')
|
|
|
|
|
+ const assetOption = ref([])
|
|
|
|
|
+ const formRef = ref()
|
|
|
|
|
+ const formMode = ref({
|
|
|
|
|
+ uuid: '',
|
|
|
|
|
+ guid: '',
|
|
|
|
|
+ type: '',
|
|
|
|
|
+ x: 0,
|
|
|
|
|
+ y: 0,
|
|
|
|
|
+ scaleX: 1,
|
|
|
|
|
+ scaleY: 1,
|
|
|
|
|
+ flipX: false,
|
|
|
|
|
+ flipY: false,
|
|
|
|
|
+ icon: '',
|
|
|
|
|
+ tip: '',
|
|
|
|
|
+ isAdd: false
|
|
|
|
|
+ })
|
|
|
|
|
+ const rules = { guid: { required: true, message: '请选择资产' } }
|
|
|
|
|
+ const showPoup = ref(false)
|
|
|
|
|
+ const currentMap: Ref<BaseMap | undefined> = ref()
|
|
|
|
|
+ const currentMarker = ref()
|
|
|
|
|
+ const allMarker = ref([] as L.Marker[])
|
|
|
|
|
+ const store = useStore()
|
|
|
|
|
+
|
|
|
|
|
+ // 资产下拉
|
|
|
|
|
+ function selectChange(_: string, option: Item) {
|
|
|
|
|
+ formMode.value.type = option.type || ''
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 重置marker样式
|
|
|
|
|
+ function resetMarker(type: string, num: number | boolean, id?: string) {
|
|
|
|
|
+ if (type === 'lat' || type === 'lng') {
|
|
|
|
|
+ const obj = currentMarker.value.getLatLng()
|
|
|
|
|
+ obj[type] = num
|
|
|
|
|
+ currentMarker.value.setLatLng(obj)
|
|
|
|
|
+ console.log('位置更新', obj)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const newIcon = currentMarker.value.getIcon()
|
|
|
|
|
+ if (type === 'scaleX' || type === 'scaleY') {
|
|
|
|
|
+ newIcon.options.iconSize[id!] = newIcon.options.iconSize[id!] * (num as number)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const newHtml = newIcon.options.html.replace(/style="[^=>]*"/g, (s: string) => {
|
|
|
|
|
+ const a = s.split(' ')
|
|
|
|
|
+ const c = type === 'flipY' ? 'rotateX' : 'rotateY'
|
|
|
|
|
+ const n = type === 'flipY' ? 1 : 2
|
|
|
|
|
+ a[n] = num ? `${c}(180deg)${n === 2 ? ';"' : ''}` : `${c}(0deg)${n === 2 ? ';"' : ''}`
|
|
|
|
|
+ const b = a.join(' ')
|
|
|
|
|
+ return b
|
|
|
|
|
+ })
|
|
|
|
|
+ newIcon.options.html = newHtml
|
|
|
|
|
+ }
|
|
|
|
|
+ currentMarker.value.setIcon(newIcon)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // marker选中状态
|
|
|
|
|
+ function selectMaker(marker: L.Marker) {
|
|
|
|
|
+ for (let k = 0; k < allMarker.value.length; k++) {
|
|
|
|
|
+ const el = allMarker.value[k]
|
|
|
|
|
+ const dom = el.getElement()
|
|
|
|
|
+ if ((el as Any)._leaflet_id === (marker as Any)._leaflet_id) {
|
|
|
|
|
+ dom!.style.boxShadow = '0 0 4px 2px #ff891a'
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dom!.style.boxShadow = 'none'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ currentMarker.value = marker
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询设备列表+设置poup
|
|
|
|
|
+ function setPoupData(marker: L.Marker, option: Item) {
|
|
|
|
|
+ // 查询设备列表
|
|
|
|
|
+ socketService.send('item.query', { itemtype: option.deviceId, isPaging: 0, region: selected.value }).then((res) => {
|
|
|
|
|
+ const { success, data: { list } } = res
|
|
|
|
|
+ if (success && list) {
|
|
|
|
|
+ assetOption.value = list
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ formMode.value.uuid = option.uuid || uuid()
|
|
|
|
|
+ formMode.value.guid = option.guid || option.item || ''
|
|
|
|
|
+ formMode.value.type = option.type || ''
|
|
|
|
|
+ formMode.value.x = option.x || 0
|
|
|
|
|
+ formMode.value.y = option.y || 0
|
|
|
|
|
+ formMode.value.isAdd = option.isAdd || false
|
|
|
|
|
+ // 移除其它选中状态
|
|
|
|
|
+ selectMaker(marker)
|
|
|
|
|
+ showPoup.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 添加marker
|
|
|
|
|
+ function addMarker(option: Item) {
|
|
|
|
|
+ if (!Map.value) throw 'Map 未初始化'
|
|
|
|
|
+ if (!option.icon) return console.log('缺少参数')
|
|
|
|
|
+
|
|
|
|
|
+ // 自定义图标
|
|
|
|
|
+ const img = `<img src="${option.icon}" style="width:100%;height:100%;transform: rotateX(0deg) rotateY(0deg);"/>`
|
|
|
|
|
+ const ICON = L.divIcon({
|
|
|
|
|
+ iconSize: [ (option.scaleX || 1) * 30, (option.scaleY || 1) * 30 ],
|
|
|
|
|
+ html: img
|
|
|
|
|
+ })
|
|
|
|
|
+ const marker = L.marker([ option.y || 0, option.x || 0 ], {
|
|
|
|
|
+ icon: ICON,
|
|
|
|
|
+ draggable: props.isEdit, // 是否可通过鼠标/触摸拖动。
|
|
|
|
|
+ riseOnHover: true
|
|
|
|
|
+ }).addTo(Map.value)
|
|
|
|
|
+ // add
|
|
|
|
|
+ allMarker.value.push(marker)
|
|
|
|
|
+ // 显示tip
|
|
|
|
|
+ if (props.baseMap.showTip && option.itemName) marker.bindTooltip(option.itemName, { direction: 'top', className: 'resetTips' })
|
|
|
|
|
+ // 显示poup
|
|
|
|
|
+ if (isCheck.value) {
|
|
|
|
|
+ console.log('添加marker', option)
|
|
|
|
|
+ setPoupData(marker, option)
|
|
|
|
|
+ }
|
|
|
|
|
+ // 事件
|
|
|
|
|
+ marker.addEventListener('click', () => {
|
|
|
|
|
+ console.log('marker点击', option)
|
|
|
|
|
+ setPoupData(marker, option)
|
|
|
|
|
+ emit('markerClick', option)
|
|
|
|
|
+ })
|
|
|
|
|
+ marker.addEventListener('dragend', (e) => {
|
|
|
|
|
+ console.log('marker拖动', option)
|
|
|
|
|
+ const { lat, lng } = e.target.getLatLng()
|
|
|
|
|
+ option.x = lng
|
|
|
|
|
+ option.y = lat
|
|
|
|
|
+ setPoupData(marker, option)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 拖拽=>添加marker
|
|
|
|
|
+ function itemDragEnd(e: DragEvent) {
|
|
|
|
|
+ e.preventDefault()
|
|
|
|
|
+ const point = Map.value.containerPointToLayerPoint([ e.layerX, e.layerY ]) // 给定相对于origin pixel的相应像素坐标
|
|
|
|
|
+ const lnglat = Map.value.layerPointToLatLng(point) // 给定地理坐标,转换为相对于origin pixel的相应像素坐标
|
|
|
|
|
+ if (isCheck.value) {
|
|
|
|
|
+ addMarker({
|
|
|
|
|
+ ...currentItem.value, x: lnglat.lng, y: lnglat.lat, isAdd: true
|
|
|
|
|
+ } as Item)
|
|
|
|
|
+ }
|
|
|
|
|
+ isCheck.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询marker+绑定
|
|
|
|
|
+ async function bindMarker(mapId: string) {
|
|
|
|
|
+ if (!mapId) return
|
|
|
|
|
+ // 清除
|
|
|
|
|
+ if (allMarker.value.length) {
|
|
|
|
|
+ for (let k = 0; k < allMarker.value.length; k++) {
|
|
|
|
|
+ const marker = allMarker.value[k]
|
|
|
|
|
+ marker.remove()
|
|
|
|
|
+ }
|
|
|
|
|
+ allMarker.value = []
|
|
|
|
|
+ }
|
|
|
|
|
+ // 添加
|
|
|
|
|
+ let page = 1
|
|
|
|
|
+ let pages = 0
|
|
|
|
|
+ do {
|
|
|
|
|
+ const obj = {
|
|
|
|
|
+ map: mapId,
|
|
|
|
|
+ pageSize: 100,
|
|
|
|
|
+ isPaging: 0,
|
|
|
|
|
+ page: page++
|
|
|
|
|
+ } as { trackType?: number }
|
|
|
|
|
+ if (props.baseMap.trackType) obj.trackType = props.baseMap.trackType
|
|
|
|
|
+ const { data } = await socketService.send('monitor.itemQuery', obj)
|
|
|
|
|
+ store.setObtainedDevices(data.list)
|
|
|
|
|
+ console.log('底图关联的marker', data.list)
|
|
|
|
|
+ if (data.list) {
|
|
|
|
|
+ for (let k = 0; k < data.list.length; k++) {
|
|
|
|
|
+ const el = data.list[k]
|
|
|
|
|
+ const obj = {
|
|
|
|
|
+ parent: el,
|
|
|
|
|
+ ...el.mapElement,
|
|
|
|
|
+ icon: import.meta.env.VITE_IMG_URL + el.icon,
|
|
|
|
|
+ showTip: props.baseMap.showTip
|
|
|
|
|
+ }
|
|
|
|
|
+ addMarker(obj)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ pages = data.pages
|
|
|
|
|
+ } while (page <= pages)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 切换底图
|
|
|
|
|
+ async function changeMap(_: string, option: BaseMap) {
|
|
|
|
|
+ console.log('切换底图', option)
|
|
|
|
|
+ if (!Map.value) return
|
|
|
|
|
+ // 清除layer
|
|
|
|
|
+ Map.value.eachLayer((layer: L.Layer) => {
|
|
|
|
|
+ Map.value.removeLayer(layer)
|
|
|
|
|
+ })
|
|
|
|
|
+ // 添加底图
|
|
|
|
|
+ if (!option.imgUrl || !option.width || !option.height || !option.mapId) return window.$notification.error({ content: '底图缺少相关参数', duration: 3000, keepAliveOnHover: true })
|
|
|
|
|
+ currentMap.value = option
|
|
|
|
|
+ L.imageOverlay(import.meta.env.VITE_IMG_URL + option.imgUrl, [ [ 0, 0 ], [ option.height, option.width ] ]).addTo(Map.value)
|
|
|
|
|
+ Map.value.setView([ option.height / 2, option.width / (props.isEdit ? 3.5 : 2) ], 0)
|
|
|
|
|
+ // 获取底图绑定的maker
|
|
|
|
|
+ bindMarker(option.mapId)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化底图
|
|
|
|
|
+ function initMap(option: BaseMap) {
|
|
|
|
|
+ if (!option) return
|
|
|
|
|
+ Map.value = L.map('map', {
|
|
|
|
|
+ zoom: 0,
|
|
|
|
|
+ maxZoom: 1,
|
|
|
|
|
+ minZoom: 0,
|
|
|
|
|
+ zoomSnap: 0.1,
|
|
|
|
|
+ center: [ option.height / 2, option.width / (props.isEdit ? 3.5 : 2) ],
|
|
|
|
|
+ crs: L.CRS.Simple,
|
|
|
|
|
+ attributionControl: false,
|
|
|
|
|
+ zoomControl: false
|
|
|
|
|
+ }).addEventListener('click', (e) => {
|
|
|
|
|
+ console.log('map点击', e)
|
|
|
|
|
+ if (currentMarker.value) currentMarker.value.getElement().style.boxShadow = 'none'
|
|
|
|
|
+ formMode.value.flipX = false
|
|
|
|
|
+ formMode.value.flipY = false
|
|
|
|
|
+ formMode.value.scaleX = 1
|
|
|
|
|
+ formMode.value.scaleY = 1
|
|
|
|
|
+ formMode.value.uuid = ''
|
|
|
|
|
+ showPoup.value = false
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 获取底图列表
|
|
|
|
|
+ socketService.send('region.map').then((res) => {
|
|
|
|
|
+ const { success, data } = res
|
|
|
|
|
+ if (success && data.length) {
|
|
|
|
|
+ options.value = data.map((el: { childList: Any[]; }) => {
|
|
|
|
|
+ if (el.childList) {
|
|
|
|
|
+ el.childList.forEach((es) => {
|
|
|
|
|
+ if (es.mapId === props.baseMap.mapId) selected.value = es.id
|
|
|
|
|
+ try {
|
|
|
|
|
+ const { width, height, imgUrl } = JSON.parse(es.mapConfig)
|
|
|
|
|
+ es.width = width
|
|
|
|
|
+ es.height = height
|
|
|
|
|
+ es.imgUrl = imgUrl
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.log('底图配置数据格式错误')
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ return el
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 获取所有maker类型
|
|
|
|
|
+ socketService.send('itemType.search', { belongs: '3' }).then((res) => {
|
|
|
|
|
+ const { success, data } = res
|
|
|
|
|
+ if (success && data.length) iconList.value = data.map((el: { imageUrl: string; name: string; guid: string }) => ({ icon: import.meta.env.VITE_IMG_URL + el.imageUrl, name: el.name, deviceId: el.guid }))
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ if (props.isEdit) { window.$notification.warning({ content: '请选择车站', duration: 3000, keepAliveOnHover: true }) } else {
|
|
|
|
|
+ changeMap('', option)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 保存->更新marker
|
|
|
|
|
+ async function save() {
|
|
|
|
|
+ await formRef.value.validate()
|
|
|
|
|
+ const mapElementList = [ {
|
|
|
|
|
+ flipX: formMode.value.flipX,
|
|
|
|
|
+ flipY: formMode.value.flipY,
|
|
|
|
|
+ item: formMode.value.guid,
|
|
|
|
|
+ map: currentMap.value!.mapId,
|
|
|
|
|
+ scaleX: formMode.value.scaleX,
|
|
|
|
|
+ scaleY: formMode.value.scaleY,
|
|
|
|
|
+ type: formMode.value.type,
|
|
|
|
|
+ uuid: formMode.value.uuid,
|
|
|
|
|
+ visiable: true,
|
|
|
|
|
+ x: formMode.value.x,
|
|
|
|
|
+ y: formMode.value.y
|
|
|
|
|
+ } ]
|
|
|
|
|
+ console.log('保存', mapElementList, formMode.value.isAdd)
|
|
|
|
|
+ const url = formMode.value.isAdd ? 'mapElement.insert' : 'mapElement.update'
|
|
|
|
|
+ const { success } = await socketService.send(url, { mapElementList })
|
|
|
|
|
+ if (success) {
|
|
|
|
|
+ bindMarker(currentMap.value!.mapId)
|
|
|
|
|
+ window.$notification.success({ content: formMode.value.isAdd ? '添加成功' : '修改成功', duration: 2000 })
|
|
|
|
|
+ showPoup.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 删除当前
|
|
|
|
|
+ async function del() {
|
|
|
|
|
+ if (!currentMarker.value) return
|
|
|
|
|
+ const fdid = allMarker.value.findIndex((el: Any) => el._leaflet_id === currentMarker.value._leaflet_id)
|
|
|
|
|
+ if (fdid !== -1) {
|
|
|
|
|
+ if (!formMode.value.isAdd) {
|
|
|
|
|
+ const { success } = await socketService.send('mapElement.delete', [ formMode.value.uuid ])
|
|
|
|
|
+ if (success) window.$notification.success({ content: '删除成功', duration: 2000 })
|
|
|
|
|
+ }
|
|
|
|
|
+ allMarker.value.splice(fdid, 1)
|
|
|
|
|
+ currentMarker.value.remove()
|
|
|
|
|
+ showPoup.value = false
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw '删除失败!'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 销毁
|
|
|
|
|
+ function destory() {
|
|
|
|
|
+ if (!Map.value) return
|
|
|
|
|
+ console.log('销毁')
|
|
|
|
|
+ Map.value.eachLayer((layer: L.Layer) => {
|
|
|
|
|
+ Map.value.removeLayer(layer)
|
|
|
|
|
+ })
|
|
|
|
|
+ allMarker.value = []
|
|
|
|
|
+ currentMarker.value = undefined
|
|
|
|
|
+ currentMap.value = undefined
|
|
|
|
|
+ Map.value = null
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(() => {
|
|
|
|
|
+ if (Object.keys(store.currentStratum).length) {
|
|
|
|
|
+ if (Map.value) {
|
|
|
|
|
+ changeMap('', store.currentStratum)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ initMap(store.currentStratum)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ watch(() => props.baseMap, (v) => {
|
|
|
|
|
+ if (Map.value) {
|
|
|
|
|
+ changeMap('', v)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ initMap(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ }, { deep: true })
|
|
|
|
|
+
|
|
|
|
|
+ onUnmounted(() => destory())
|
|
|
|
|
+ </script>
|
|
|
|
|
+ <style lang="scss" scoped>
|
|
|
|
|
+ .mapBox {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background: none;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+
|
|
|
|
|
+ #map {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background: #011719;
|
|
|
|
|
+
|
|
|
|
|
+ :deep(.leaflet-div-icon) {
|
|
|
|
|
+ background: none;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ border-radius: 6px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ :deep(.resetTips) {
|
|
|
|
|
+ height: 33px;
|
|
|
|
|
+ background: #06353A;
|
|
|
|
|
+ border: 1px solid #34C0AE;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+
|
|
|
|
|
+ &::before {
|
|
|
|
|
+ border-top-color: #34C0AE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ p {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-menu {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ z-index: 601;
|
|
|
|
|
+ background: white;
|
|
|
|
|
+ width: 380px;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ padding: 10px;
|
|
|
|
|
+
|
|
|
|
|
+ &-content {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: calc(100% - 44px);
|
|
|
|
|
+ :deep(.n-scrollbar-content) {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ align-content: flex-start;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-item {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ width: 78px;
|
|
|
|
|
+ height: 78px;
|
|
|
|
|
+ padding: 10px 0;
|
|
|
|
|
+ border: 1px solid #C9D3DD;
|
|
|
|
|
+ cursor: grab;
|
|
|
|
|
+ margin-top: 16px;
|
|
|
|
|
+
|
|
|
|
|
+ &:not(:nth-child(4n)) {
|
|
|
|
|
+ margin-right: 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 50px;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ p {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ color: #2c3e50;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-poup {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ width: 334px;
|
|
|
|
|
+ background: #FFFFFF;
|
|
|
|
|
+ box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.1);
|
|
|
|
|
+ backdrop-filter: blur(29.99999943901511px);
|
|
|
|
|
+ z-index: 601;
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+
|
|
|
|
|
+ &-btns {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+
|
|
|
|
|
+ &>button:first-child {
|
|
|
|
|
+ margin-right: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ </style>
|