You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
680 lines
22 KiB
680 lines
22 KiB
|
1 month ago
|
<template>
|
||
|
|
<div>
|
||
|
|
<div class="parent">
|
||
|
|
<div class="mapParent">
|
||
|
|
<div :id="defaultData.mapName" class="my-map"></div>
|
||
|
|
</div>
|
||
|
|
<div class="child">
|
||
|
|
<div class="text-title">状态图示</div>
|
||
|
|
<div>
|
||
|
|
<div class="circle circle-green"></div>
|
||
|
|
<div class="text-info text-info-green">正在使用岸电</div>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<div class="circle circle-yellow"></div>
|
||
|
|
<div class="text-info text-info-yellow">船方原因未使用岸电</div>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<div class="circle circle-red"></div>
|
||
|
|
<div class="text-info text-info-red">岸方原因未使用岸电</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<!-- <div class="child" v-if="showButton && usingData.status === 2">-->
|
||
|
|
<!-- <el-button class="text-title" style="width:100%;background-color: rgba(255, 255, 255, 0);text-align: center;border: none;" @click="updateStatus">确认该事件</el-button>-->
|
||
|
|
<!-- </div>-->
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup lang="ts">
|
||
|
|
import interface_red from '@/assets/svgs/svg/岸电箱-维护保养.png'
|
||
|
|
import interface_yellow from '@/assets/svgs/svg/用电接口-黄色.gif'
|
||
|
|
import interface_blue from '@/assets/svgs/svg/岸电箱-正常.png'
|
||
|
|
import interface_green from '@/assets/svgs/svg/用电接口-绿色.svg'
|
||
|
|
import ship_red from '@/assets/svgs/svg/船-红色.gif'
|
||
|
|
import ship_yellow from '@/assets/svgs/svg/船-黄色.svg'
|
||
|
|
import ship_blue from '@/assets/svgs/svg/船-蓝色.svg'
|
||
|
|
import ship_green from '@/assets/svgs/svg/船-绿色.png'
|
||
|
|
import ship_brown from '@/assets/svgs/svg/船-棕色.svg'
|
||
|
|
import ship_problem from '@/assets/svgs/svg/船-问号.gif'
|
||
|
|
import shorepower_blue from '@/assets/svgs/svg/配电室.png'
|
||
|
|
import shorepower_green from '@/assets/svgs/svg/岸电设施-绿色.svg'
|
||
|
|
import problem from '@/assets/svgs/svg/问号-棕色.svg'
|
||
|
|
import problem_red from '@/assets/svgs/svg/问号-红色.svg'
|
||
|
|
|
||
|
|
import L from "leaflet";
|
||
|
|
import "leaflet/dist/leaflet.css";
|
||
|
|
import "leaflet-rotatedmarker";
|
||
|
|
import {MapApi} from "@/api/shorepower/map";
|
||
|
|
import baseInfo from "@/views/shorepower/map/baseMapInfo";
|
||
|
|
|
||
|
|
defineOptions({ name: 'PublicMapComponents' })
|
||
|
|
|
||
|
|
|
||
|
|
// const getShorePowerEquipmentStr = (icon: any) => {
|
||
|
|
// return `<div class="table-message">
|
||
|
|
// <div class="table-name">${icon.info.name}</div>
|
||
|
|
// <div class="table-line"></div>
|
||
|
|
// <div class="base-table-info">
|
||
|
|
// <span class='table-info'>名称 :${icon.info.name}</span></br>
|
||
|
|
// <span class='table-info'>容量:${icon.info.installedPower}</span></br>
|
||
|
|
// <span class='table-info'>电压 :${icon.info.voltage}</span></br>
|
||
|
|
// <span class='table-info'>频率:${icon.info.frequency}</span></br>
|
||
|
|
// <span class='table-info'>接口数量 :${icon.info.interfaceCount}</span></br>
|
||
|
|
// <span class='table-info'>同时可用数量:${icon.info.simultaneouslyInterfaceCount}</span></br>
|
||
|
|
// </div>
|
||
|
|
// </div>`
|
||
|
|
// }
|
||
|
|
// const getBerthStr = (icon: any) => {
|
||
|
|
// return `
|
||
|
|
// <div class="table-message">
|
||
|
|
// <div class="table-name">${icon.info.berthName}</div>
|
||
|
|
// <div class="table-line"></div>
|
||
|
|
// <div class="base-table-info">
|
||
|
|
// <span class='table-info'>泊位 :${icon.info.berthName}</span></br>
|
||
|
|
// <span class='table-info'>总电量:${icon.info.totalPower}</span></br>
|
||
|
|
// <span class='table-info'>更新时间 :${icon.info.updateTime}</span></br>
|
||
|
|
// <span class='table-info'>状态:${icon.info.status}</span></br>
|
||
|
|
// <span class='table-info'>接口规格 :${icon.info.InterfaceType}</span></br>
|
||
|
|
// <span class='table-info'>泊位水深:${icon.info.berthDepth}</span></br>
|
||
|
|
// </div>
|
||
|
|
// </div>`
|
||
|
|
// }
|
||
|
|
// const getShipStr = (icon: any) => {
|
||
|
|
// return `
|
||
|
|
// <div class="table-message">
|
||
|
|
// <div class="table-name">${icon.info.shipName}</div>
|
||
|
|
// <div class="table-line"></div>
|
||
|
|
// <div class="base-table-info">
|
||
|
|
// <span class='table-info'>船名 :${icon.info.shipName}</span></br>
|
||
|
|
// <span class='table-info'>呼号:${icon.info.callSign}</span></br>
|
||
|
|
// <span class="table-info">船公司:${icon.info.shipCompany}</span></br>
|
||
|
|
// <span class="table-info">联系电话:${icon.info.phone}</span></br>
|
||
|
|
// <span class='table-info'>长度 :${icon.info.length}</span></br>
|
||
|
|
// <span class='table-info'>宽度:${icon.info.width}</span></br>
|
||
|
|
// <span class='table-info'>吨位 :${icon.info.tonnage}</span></br>
|
||
|
|
// <span class='table-info'>类型:${icon.info.type}</span></br>
|
||
|
|
// <span class='table-info'>货物名称:${icon.info.CommodityName}</span></br>
|
||
|
|
// <span class='table-info'>货物吨数:${icon.info.cargoWeight}</span></br>
|
||
|
|
// ${icon.reason == 9 ? `<span class='table-info'>岸电接入时间:${icon.info.startUsingTime}</span></br>` : `<span class='table-info'>岸电未使用原因:${reason.value[icon.reason]}</span></br>`}
|
||
|
|
// <span class='table-info'>计划离泊时间:${icon.info.scheduledDepartureTime}</span></br>
|
||
|
|
// ${icon.reason == 9 ? `<span class='table-info'>岸电用量:${icon.info.shorePowerConsumption}</span></br>` : ''}
|
||
|
|
// <span class='table-info'>辅机总功率:${icon.info.totalAuxiliaryPower}</span></br>
|
||
|
|
// </div>
|
||
|
|
// </div>
|
||
|
|
// `
|
||
|
|
// }
|
||
|
|
// const getProblemStr = (icon: any) => {
|
||
|
|
// return `
|
||
|
|
// <div class="table-message">
|
||
|
|
// <div class="table-name">${icon.parent.info.shipName}</div>
|
||
|
|
// <div class="table-line"></div>
|
||
|
|
// <div class="base-table-info">
|
||
|
|
// <span class='table-info'>船名 :${icon.parent.info.shipName}</span></br>
|
||
|
|
// <span class='table-info'>岸电未使用原因:${reason.value[icon.parent.reason]}</span></br>
|
||
|
|
// <span class='table-info'>计划离泊时间:${icon.parent.info.scheduledDepartureTime}</span></br>
|
||
|
|
// </div>
|
||
|
|
// </div>
|
||
|
|
// `
|
||
|
|
// }
|
||
|
|
|
||
|
|
let mapNum = 1
|
||
|
|
const usingAlarm = ref([])
|
||
|
|
const removeAlarm = () => {
|
||
|
|
for (let ships of usingAlarm.value) {
|
||
|
|
for (const alarm of usingAlarm.value[ships]) {
|
||
|
|
alarm.remove()
|
||
|
|
}
|
||
|
|
usingAlarm.value[ships] = []
|
||
|
|
}
|
||
|
|
}
|
||
|
|
const buildAlarm = (icon:any, nowMapNum: number, radius: number = 1, timeOutTime: number = 50, color: string = Math.random() > 0.95 ? `rgba(255, 50, 50, 1)` :`rgba(50, 255, 20, 0.13)`) => {
|
||
|
|
setTimeout(() => {
|
||
|
|
if (nowMapNum !== mapNum) return
|
||
|
|
if (_map.value.getZoom() <= 15) {
|
||
|
|
const alarm = L.circle(icon.xy, {
|
||
|
|
radius: 50 * radius,
|
||
|
|
color: color,
|
||
|
|
stroke: false,
|
||
|
|
interactive: false,
|
||
|
|
}).addTo(_map.value);
|
||
|
|
if (!usingAlarm.value[icon.id]) usingAlarm.value[icon.id] = []
|
||
|
|
usingAlarm.value[icon.id].push(alarm)
|
||
|
|
}
|
||
|
|
|
||
|
|
if (radius > (6 * 18 / _map.value.getZoom())) {
|
||
|
|
for (let nowAlarm of usingAlarm.value[icon.id]) {
|
||
|
|
nowAlarm.remove()
|
||
|
|
}
|
||
|
|
usingAlarm.value[icon.id] = []
|
||
|
|
buildAlarm(icon, nowMapNum, 1, 50, color)
|
||
|
|
} else (
|
||
|
|
buildAlarm(icon, nowMapNum, radius + 1, timeOutTime + 2 ** radius / 2 , color)
|
||
|
|
)
|
||
|
|
}, timeOutTime)
|
||
|
|
}
|
||
|
|
|
||
|
|
const svgs = {
|
||
|
|
interface_red: interface_red,
|
||
|
|
interface_yellow: interface_yellow,
|
||
|
|
interface_blue: interface_blue,
|
||
|
|
interface_green: interface_green,
|
||
|
|
ship_red: ship_red,
|
||
|
|
ship_yellow: ship_yellow,
|
||
|
|
ship_blue: ship_blue,
|
||
|
|
ship_green: ship_green,
|
||
|
|
ship_brown: ship_brown,
|
||
|
|
ship_problem: ship_problem,
|
||
|
|
shorepower_blue: shorepower_blue,
|
||
|
|
shorepower_green: shorepower_green,
|
||
|
|
problem: problem,
|
||
|
|
problem_red: problem_red
|
||
|
|
}
|
||
|
|
// 计算图标尺寸【不同缩放比例下】
|
||
|
|
const countIconSize = (icon: any): [number, number] => {
|
||
|
|
let zoomRatio = 2 ** (20 - _map.value.getZoom())
|
||
|
|
return [icon.width * icon.ratio / zoomRatio, icon.height * icon.ratio / zoomRatio]
|
||
|
|
}
|
||
|
|
// 计算图标中心点【不同缩放比例下】
|
||
|
|
const countIconAnchor = (icon: any): [number, number] => {
|
||
|
|
let zoomRatio = 2 ** (21 - _map.value.getZoom())
|
||
|
|
return [icon.width * icon.ratio / zoomRatio, icon.height * icon.ratio / zoomRatio]
|
||
|
|
}
|
||
|
|
// 计算文本尺寸【不同缩放比例下】
|
||
|
|
const countFontSize = (text: any) => {
|
||
|
|
return text.fontSize / (1.7 ** (20 - _map.value.getZoom())) * 10
|
||
|
|
}
|
||
|
|
// 构建绘制options
|
||
|
|
const buildOptions = (data: any) => {
|
||
|
|
try {
|
||
|
|
|
||
|
|
if ((data.type && data.type === 'gon') || (data.type && data.type === 'line') || (!data.type && (type.value == 'gon' || type.value == 'line'))) return data
|
||
|
|
|
||
|
|
if ((data.type && data.type === 'icon') || (!data.type && type.value == 'icon')) {
|
||
|
|
return {
|
||
|
|
icon: L.icon({
|
||
|
|
iconAnchor: countIconAnchor(data),
|
||
|
|
iconSize: countIconSize(data),
|
||
|
|
iconUrl: svgs[data.icon]
|
||
|
|
}),
|
||
|
|
rotationAngle: data.rotationAngle,
|
||
|
|
rotationOrigin: "center center"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if ((data.type && data.type === 'text') || (!data.type && type.value == 'text')) {
|
||
|
|
const fontSize = countFontSize(data)
|
||
|
|
let textWidth = fontSize * data.name.length
|
||
|
|
for (let i = 0; i < data.name.length; i++) {
|
||
|
|
if ((data.name[i]) in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#']) textWidth = textWidth - 0.5 * fontSize
|
||
|
|
}
|
||
|
|
textWidth = textWidth * 1.2
|
||
|
|
const tagAnchor = data.tagAnchorType === 1 ? [0, 0] : data.tagAnchorType === 2 ? [textWidth, 0] : data.tagAnchorType === 3 ? [0, fontSize] : data.tagAnchorType === 4 ? [textWidth, fontSize] : [textWidth / 2, fontSize / 2]
|
||
|
|
const style = `
|
||
|
|
background-color:${data.background};border-radius: 5px;text-align: center;
|
||
|
|
color: ${data.color};
|
||
|
|
width: ${textWidth}px;
|
||
|
|
font-size: ${fontSize}px;
|
||
|
|
font-style: oblique;
|
||
|
|
font-weight: ${data.fontSize * 33};
|
||
|
|
cursor: grab;`
|
||
|
|
return {
|
||
|
|
icon: L.divIcon({
|
||
|
|
className: data.name,
|
||
|
|
iconAnchor: tagAnchor,
|
||
|
|
html: `<div style="${style}">${data.name}</div>`
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
console.log(e, data)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const _map = ref<any>({_zoom: 14,_animateToCenter: {lat: 0, lng: 0}})
|
||
|
|
const mapRef = ref(null);
|
||
|
|
const defaultData = ref({
|
||
|
|
defCenter: {lat: 38.8422480135733, lng: 118.4933866580094},
|
||
|
|
defZoom: 12,
|
||
|
|
mapName: 'map',
|
||
|
|
illustration: true
|
||
|
|
})
|
||
|
|
const center = ref(defaultData.value.defCenter)
|
||
|
|
const zoom = ref(defaultData.value.defZoom)
|
||
|
|
const mouse = ref(defaultData.value.defCenter)
|
||
|
|
const type = ref('gon') // 1: 绘制区域 2: 绘制线 3: 绘制图标 4: 绘制文本
|
||
|
|
|
||
|
|
// 【区域】绘制参数
|
||
|
|
const polygon = ref({
|
||
|
|
stroke: true,
|
||
|
|
color:`rgb(50, 50, 50)`,
|
||
|
|
weight:1,
|
||
|
|
opacity:1,
|
||
|
|
fill:true,
|
||
|
|
fillColor:`rgb(255, 255, 200)`,
|
||
|
|
fillOpacity:1,
|
||
|
|
interactive:false,
|
||
|
|
smoothFactor:1,
|
||
|
|
xy:[]
|
||
|
|
})
|
||
|
|
const usingPolygon = ref()
|
||
|
|
const drawingPolygon = () => {
|
||
|
|
if (usingPolygon.value) usingPolygon.value.remove()
|
||
|
|
usingPolygon.value = L.polygon(polygon.value.xy, buildOptions(polygon.value)).addTo(_map.value)
|
||
|
|
usingPolygon.value.on('click', () => {
|
||
|
|
type.value = 'text'
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 【线】绘制参数
|
||
|
|
const polyline = ref({
|
||
|
|
interactive: false,
|
||
|
|
color: `rgb(50, 50, 50)`, // 描边颜色
|
||
|
|
dashArray: [10, 5],
|
||
|
|
weight: 1,// 描边宽度
|
||
|
|
smoothFactor: 0,
|
||
|
|
xy: [],
|
||
|
|
})
|
||
|
|
const usingPolyline = ref()
|
||
|
|
const drawingPolyline = () => {
|
||
|
|
if (usingPolyline.value) usingPolyline.value.remove()
|
||
|
|
usingPolyline.value = L.polyline(polyline.value.xy, buildOptions(polyline.value)).addTo(_map.value);
|
||
|
|
usingPolygon.value.on('click', () => {
|
||
|
|
type.value = 'text'
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 【图标】绘制参数
|
||
|
|
const marker = ref({
|
||
|
|
rotationAngle: 0,
|
||
|
|
width: 1000,
|
||
|
|
height: 5200,
|
||
|
|
ratio: 1,
|
||
|
|
iconType: 'ship',
|
||
|
|
icon: 'ship_green',
|
||
|
|
anchor: 'left',
|
||
|
|
xy: [],
|
||
|
|
})
|
||
|
|
const usingMarker = ref()
|
||
|
|
const drawingMarker = () => {
|
||
|
|
if (usingMarker.value) usingMarker.value.remove()
|
||
|
|
if (marker.value.xy.length !== 2) return
|
||
|
|
usingMarker.value = L.marker(marker.value.xy, buildOptions(marker.value)).addTo(_map.value);
|
||
|
|
usingPolygon.value.on('click', () => {
|
||
|
|
type.value = 'text'
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 【文本】绘制参数
|
||
|
|
const textType = ref('ship')
|
||
|
|
const text = ref({
|
||
|
|
name: '浙能2',
|
||
|
|
xy: [38.94212905193746, 118.4492737054825],
|
||
|
|
// type: 0,
|
||
|
|
fontSize: 16,
|
||
|
|
tagAnchorType: 1,
|
||
|
|
background: 'rgba(255, 255, 255, 0.7)',
|
||
|
|
color: 'rgba(50, 50, 50, 1)',
|
||
|
|
anchor: 'left',
|
||
|
|
})
|
||
|
|
const usingText = ref()
|
||
|
|
const drawingText = () => {
|
||
|
|
if (usingText.value) usingText.value.remove()
|
||
|
|
if (text.value.xy.length !== 2) return
|
||
|
|
usingText.value = L.marker(text.value.xy, buildOptions(text.value)).addTo(_map.value)
|
||
|
|
usingPolygon.value.on('click', () => {
|
||
|
|
type.value = 'text'
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
const getDrawingInfo = () => {
|
||
|
|
if (type.value === 'gon') {
|
||
|
|
return {type: type.value, ...polygon.value}
|
||
|
|
} else if (type.value === 'line') {
|
||
|
|
return {type: type.value, ...polyline.value}
|
||
|
|
} else if (type.value === 'icon') {
|
||
|
|
return {type: type.value, ...marker.value}
|
||
|
|
} else if (type.value === 'text') {
|
||
|
|
if (textType.value !== 'ship') {
|
||
|
|
const { anchor, ...textInfo} = text.value
|
||
|
|
return {type: type.value, ...textInfo}
|
||
|
|
} else {
|
||
|
|
return {type: type.value, ...text.value}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
const doCopy = async () => {
|
||
|
|
const str = JSON.stringify(getDrawingInfo())
|
||
|
|
try {
|
||
|
|
// 尝试使用现代API
|
||
|
|
await navigator.clipboard.writeText(str);
|
||
|
|
// console.log('复制成功!',str);
|
||
|
|
return
|
||
|
|
} catch (err) {
|
||
|
|
// 降级处理
|
||
|
|
const textArea = document.createElement("textarea");
|
||
|
|
textArea.value = str;
|
||
|
|
textArea.style.cssText = "position: fixed; top: -1000px; opacity: 0;";
|
||
|
|
document.body.appendChild(textArea);
|
||
|
|
textArea.select();
|
||
|
|
try {
|
||
|
|
document.execCommand('copy');
|
||
|
|
// console.log('复制成功!',str);
|
||
|
|
} catch (err) {
|
||
|
|
alert('复制失败,请手动复制')
|
||
|
|
// console.log('复制失败,请手动复制');
|
||
|
|
}
|
||
|
|
document.body.removeChild(textArea);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
const copyData = async () => {
|
||
|
|
await doCopy()
|
||
|
|
}
|
||
|
|
const addDrawingList = async (event) => {
|
||
|
|
if (event.keyCode === 32 || event.key === ' ') {
|
||
|
|
event.preventDefault();
|
||
|
|
if (type.value === 'gon') {
|
||
|
|
polygon.value.xy.push([mouse.value.lat, mouse.value.lng])
|
||
|
|
drawingPolygon()
|
||
|
|
} else if (type.value === 'line') {
|
||
|
|
polyline.value.xy.push([mouse.value.lat, mouse.value.lng])
|
||
|
|
drawingPolyline()
|
||
|
|
} else if (type.value === 'icon') {
|
||
|
|
marker.value.xy = [mouse.value.lat, mouse.value.lng]
|
||
|
|
drawingMarker()
|
||
|
|
} else if (type.value === 'text') {
|
||
|
|
text.value.xy = [mouse.value.lat, mouse.value.lng]
|
||
|
|
drawingText()
|
||
|
|
}
|
||
|
|
} else if (event.keyCode === 46 || event.key === 'Delete') {
|
||
|
|
event.preventDefault();
|
||
|
|
if (type.value === 'gon') {
|
||
|
|
polygon.value.xy.pop()
|
||
|
|
drawingPolygon()
|
||
|
|
} else if (type.value === 'line') {
|
||
|
|
polyline.value.xy.pop()
|
||
|
|
drawingPolyline()
|
||
|
|
} else if (type.value === 'icon') {
|
||
|
|
marker.value.xy = []
|
||
|
|
drawingMarker()
|
||
|
|
} else if (type.value === 'text') {
|
||
|
|
text.value.xy = []
|
||
|
|
drawingText()
|
||
|
|
}
|
||
|
|
} else if (event.keyCode === 13 || event.key === 'Enter') {
|
||
|
|
await copyData()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
const doDrawing = () => {
|
||
|
|
if (type.value === 'gon') {
|
||
|
|
drawingPolygon()
|
||
|
|
} else if (type.value === 'line') {
|
||
|
|
drawingPolyline()
|
||
|
|
} else if (type.value === 'icon') {
|
||
|
|
drawingMarker()
|
||
|
|
} else if (type.value === 'text') {
|
||
|
|
drawingText()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const history = ref()
|
||
|
|
const usingHistory = ref([])
|
||
|
|
const doHistory = ref(false)
|
||
|
|
const removeHistory = () => {
|
||
|
|
if (usingHistory.value) {
|
||
|
|
for (const item of usingHistory.value) {
|
||
|
|
item.remove()
|
||
|
|
}
|
||
|
|
usingHistory.value = []
|
||
|
|
}
|
||
|
|
}
|
||
|
|
const drawingHistoryPolygon = (data: any) => {
|
||
|
|
if (_map.value.getZoom() < 12) return
|
||
|
|
const usingInfo = L.polygon(data.xy, buildOptions(data)).addTo(_map.value)
|
||
|
|
usingInfo.on('click', async () => {
|
||
|
|
if (doHistory.value) await drawingHistory(doHistory.value)
|
||
|
|
doHistory.value = true
|
||
|
|
polygon.value = data
|
||
|
|
type.value = 'gon'
|
||
|
|
usingInfo.remove()
|
||
|
|
doDrawing()
|
||
|
|
})
|
||
|
|
usingHistory.value.push(usingInfo)
|
||
|
|
}
|
||
|
|
const drawingHistoryPolyline = (data: any) => {
|
||
|
|
if (_map.value.getZoom() < 12) return
|
||
|
|
const usingInfo = L.polyline(data.xy, buildOptions(data)).addTo(_map.value)
|
||
|
|
usingInfo.on('click', async () => {
|
||
|
|
if (doHistory.value) await drawingHistory(doHistory.value)
|
||
|
|
doHistory.value = true
|
||
|
|
polyline.value = data
|
||
|
|
type.value = 'line'
|
||
|
|
usingInfo.remove()
|
||
|
|
doDrawing()
|
||
|
|
})
|
||
|
|
usingHistory.value.push(usingInfo)
|
||
|
|
}
|
||
|
|
const drawingHistoryMarker = (data: any) => {
|
||
|
|
if (data.iconType === 'ship') {
|
||
|
|
const nowMapNum = JSON.parse(JSON.stringify(mapNum))
|
||
|
|
buildAlarm(data, nowMapNum)
|
||
|
|
}
|
||
|
|
if (_map.value.getZoom() < 12) return
|
||
|
|
const usingInfo = L.marker(data.xy, buildOptions(data)).addTo(_map.value)
|
||
|
|
usingInfo.on('click', async () => {
|
||
|
|
if (doHistory.value) await drawingHistory(doHistory.value)
|
||
|
|
doHistory.value = true
|
||
|
|
marker.value = data
|
||
|
|
type.value = 'icon'
|
||
|
|
usingInfo.remove()
|
||
|
|
doDrawing()
|
||
|
|
})
|
||
|
|
usingHistory.value.push(usingInfo)
|
||
|
|
}
|
||
|
|
const drawingHistoryTest = (data: any) => {
|
||
|
|
if (_map.value.getZoom() < 12) return
|
||
|
|
const usingInfo = L.marker(data.xy, buildOptions(data)).addTo(_map.value)
|
||
|
|
usingInfo.on('click', async () => {
|
||
|
|
if (doHistory.value) await drawingHistory(doHistory.value)
|
||
|
|
doHistory.value = true
|
||
|
|
text.value = data
|
||
|
|
type.value = 'text'
|
||
|
|
usingInfo.remove()
|
||
|
|
doDrawing()
|
||
|
|
})
|
||
|
|
usingHistory.value.push(usingInfo)
|
||
|
|
}
|
||
|
|
const drawingHistoryInfo = (data: any) => {
|
||
|
|
if (data.type === 'gon') {
|
||
|
|
drawingHistoryPolygon(data)
|
||
|
|
} else if (data.type === 'line') {
|
||
|
|
drawingHistoryPolyline(data)
|
||
|
|
} else if (data.type === 'icon') {
|
||
|
|
drawingHistoryMarker(data)
|
||
|
|
} else if (data.type === 'text') {
|
||
|
|
drawingHistoryTest(data)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
const drawingHistory = async (justOne: boolean = false) => {
|
||
|
|
// if (!history.value) {
|
||
|
|
// history.value = await MapApi.getAllData()
|
||
|
|
// }
|
||
|
|
const dataInfo = history.value ? history.value : await MapApi.getAllData()
|
||
|
|
if (justOne) {
|
||
|
|
drawingHistoryInfo(getDrawingInfo())
|
||
|
|
} else {
|
||
|
|
for (const item of dataInfo) {
|
||
|
|
if (!item.data) continue
|
||
|
|
const data = JSON.parse(item.data)
|
||
|
|
if (!data.xy) continue
|
||
|
|
drawingHistoryInfo(data)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const buildMap = () => {
|
||
|
|
_map.value = L.map(defaultData.value.mapName, {
|
||
|
|
center: defaultData.value.defCenter,
|
||
|
|
zoom: defaultData.value.defZoom,
|
||
|
|
zoomControl: false,
|
||
|
|
attributionControl: false,
|
||
|
|
})
|
||
|
|
L.tileLayer(
|
||
|
|
// 'http://150.138.79.224:8000/seamap/allmap/{z}/{y}/{x}.png',
|
||
|
|
// 'https://api.shipxy.com/h5s/api/3.5/sample?key=0cd1a6224aaa4b5ab1f3d0e79bb543cc&projection_type=wm&x={x}&y={y}&z={z}',
|
||
|
|
// 'https://m12.shipxy.com/tile.c?l=Na&m=o&x={x}&y={y}&z={z}',
|
||
|
|
'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
|
||
|
|
// '',
|
||
|
|
{
|
||
|
|
maxZoom: 19,
|
||
|
|
minZoom: 5,
|
||
|
|
attribution: ''
|
||
|
|
}).addTo(_map.value);
|
||
|
|
|
||
|
|
// 设置地图的最大边界
|
||
|
|
const southWest = L.latLng(38.30071455572194, 117.07885023513526); // 西南角的坐标
|
||
|
|
const northEast = L.latLng( 40.32351403031131, 119.9161164758117); // 东北角的坐标
|
||
|
|
_map.value.setMaxBounds(L.latLngBounds(southWest, northEast));
|
||
|
|
|
||
|
|
|
||
|
|
// 监听鼠标位置坐标
|
||
|
|
_map.value.on('mousemove', (e) => {
|
||
|
|
mouse.value = e.latlng;
|
||
|
|
});
|
||
|
|
|
||
|
|
// 监听缩放级别变化
|
||
|
|
_map.value.on('zoomend', async () => {
|
||
|
|
zoom.value = _map.value.getZoom();
|
||
|
|
removeHistory()
|
||
|
|
removeAlarm()
|
||
|
|
mapNum++
|
||
|
|
await drawingHistory()
|
||
|
|
doDrawing()
|
||
|
|
})
|
||
|
|
|
||
|
|
// 监听当前中心点坐标变化
|
||
|
|
_map.value.on('moveend', () => {
|
||
|
|
center.value = _map.value.getCenter();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
const buildBaseInfo = () => {
|
||
|
|
for (const item of baseInfo) {
|
||
|
|
if (item.xy) L.polygon(item.xy, item).addTo(_map.value)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const exportImage = async () => {
|
||
|
|
try {
|
||
|
|
alert('功能暂不可用!')
|
||
|
|
} catch (error) {
|
||
|
|
console.error('地图导出失败:', error)
|
||
|
|
alert('地图导出失败,请重试')
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/** 初始化 **/
|
||
|
|
onMounted(() => {
|
||
|
|
buildMap()
|
||
|
|
buildBaseInfo()
|
||
|
|
window.addEventListener('keyup', addDrawingList)
|
||
|
|
drawingHistory()
|
||
|
|
})
|
||
|
|
|
||
|
|
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style >
|
||
|
|
.parent {
|
||
|
|
position: relative; /* 启用Grid布局 */
|
||
|
|
}
|
||
|
|
|
||
|
|
.child {
|
||
|
|
position: absolute;
|
||
|
|
top: 10px;
|
||
|
|
left: 20px;
|
||
|
|
z-index: 1;
|
||
|
|
width: 200px;
|
||
|
|
height: 150px;
|
||
|
|
background-color: rgba(30, 30, 30, 0.7);
|
||
|
|
border: 1px solid rgba(30, 30, 30, 0.4);
|
||
|
|
border-radius: 15px;
|
||
|
|
|
||
|
|
}
|
||
|
|
.text-title {
|
||
|
|
margin-top: 10px;
|
||
|
|
font-size: 16px;
|
||
|
|
color: rgba(20, 200, 255, 1);
|
||
|
|
text-align: center;
|
||
|
|
font-weight: bold;
|
||
|
|
line-height: 30px;
|
||
|
|
text-shadow: 0 0 5px rgba(0, 0, 0, 1), 0 0 6px rgba(20, 200, 255, 0.3), 0 0 7px rgba(20, 200, 255, 0.2), 0 0 8px rgba(20, 200, 255, 0.1);
|
||
|
|
|
||
|
|
}
|
||
|
|
.circle {
|
||
|
|
width: 10px;
|
||
|
|
height: 10px;
|
||
|
|
border-radius: 5px;
|
||
|
|
margin-left: 15px;
|
||
|
|
display: inline-block;
|
||
|
|
}
|
||
|
|
.circle-green {
|
||
|
|
background-color: rgba(50, 255, 100, 1);
|
||
|
|
}
|
||
|
|
.circle-yellow {
|
||
|
|
background-color: rgba(255, 150, 0, 1);
|
||
|
|
}
|
||
|
|
.circle-red {
|
||
|
|
background-color: rgba(255, 70, 70, 1);
|
||
|
|
}
|
||
|
|
.text-info {
|
||
|
|
margin-left: 8px;
|
||
|
|
margin-top: 8px;
|
||
|
|
display: inline-block;
|
||
|
|
}
|
||
|
|
.text-info-green {
|
||
|
|
color: rgba(50, 255, 100, 1);
|
||
|
|
}
|
||
|
|
.text-info-yellow {
|
||
|
|
color: rgba(255, 150, 0, 1);
|
||
|
|
}
|
||
|
|
.text-info-red {
|
||
|
|
color: rgba(255, 70, 70, 1);
|
||
|
|
}
|
||
|
|
.mapParent {
|
||
|
|
max-width: 100%;
|
||
|
|
max-height: 100%;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
.my-map {
|
||
|
|
height: 100vh;
|
||
|
|
background-color: #A3CCFF;
|
||
|
|
//transform: scale(1.4);
|
||
|
|
}
|
||
|
|
|
||
|
|
.table-message {
|
||
|
|
width: 300px;
|
||
|
|
margin-top: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.table-name {
|
||
|
|
margin-top: 25px;
|
||
|
|
font-size: 20px;
|
||
|
|
color: rgb(0, 200, 255);
|
||
|
|
}
|
||
|
|
.table-line {
|
||
|
|
min-height: 3px;
|
||
|
|
width: 100%;
|
||
|
|
margin-top: 10px;
|
||
|
|
margin-bottom: 10px;
|
||
|
|
background-color: rgb(0, 200, 255);
|
||
|
|
}
|
||
|
|
.base-table-info {
|
||
|
|
}
|
||
|
|
.table-info {
|
||
|
|
margin-top: 10px;
|
||
|
|
font-size: 16px;
|
||
|
|
line-height: 25px;
|
||
|
|
color: rgba(50, 50, 50, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
</style>
|