Merge branch 'main' of ssh://git.wash-painting.cn:2222/cg/-----
This commit is contained in:
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@@ -201,7 +201,7 @@ packages:
|
||||
resolution: {integrity: sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
peerDependencies:
|
||||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||
vite: npm:rolldown-vite@7.2.5
|
||||
vue: ^3.2.25
|
||||
|
||||
'@vue/compiler-core@3.5.25':
|
||||
|
||||
175
src/App.vue
175
src/App.vue
@@ -88,8 +88,7 @@
|
||||
class="fence-item"
|
||||
>
|
||||
<span class="fence-info">
|
||||
<span class="fence-type">{{ getTypeName(fence.type) }}</span>
|
||||
#{{ fence.id.slice(0, 8) }}
|
||||
<span class="fence-name">{{ fence.name || '未命名围栏' }}</span>
|
||||
</span>
|
||||
<div class="fence-actions">
|
||||
<el-button
|
||||
@@ -164,7 +163,7 @@ const initMap = async () => {
|
||||
AMap = await AMapLoader.load({
|
||||
key: mapKey,
|
||||
version: '2.0',
|
||||
plugins: ['AMap.MouseTool', 'AMap.Polygon', 'AMap.Rectangle', 'AMap.Circle', 'AMap.Marker', 'AMap.Icon']
|
||||
plugins: ['AMap.MouseTool', 'AMap.Polygon', 'AMap.Rectangle', 'AMap.Circle', 'AMap.Marker', 'AMap.Icon', 'AMap.Text']
|
||||
})
|
||||
|
||||
// 创建地图实例
|
||||
@@ -520,25 +519,17 @@ const handleDrawComplete = (event) => {
|
||||
}
|
||||
|
||||
if (fence) {
|
||||
// 设置围栏样式
|
||||
if (fence.shape.setOptions) {
|
||||
fence.shape.setOptions({
|
||||
strokeColor: '#0066FF',
|
||||
strokeWeight: 2,
|
||||
strokeOpacity: 0.8,
|
||||
fillColor: '#0066FF',
|
||||
fillOpacity: 0.15,
|
||||
zIndex: 50
|
||||
})
|
||||
}
|
||||
|
||||
// 注意:使用MouseTool绘制的对象已经自动添加到地图上
|
||||
// 如果对象还没有添加到地图,则添加它
|
||||
if (!fence.shape.getMap()) {
|
||||
map.add(fence.shape)
|
||||
}
|
||||
|
||||
// 保存围栏
|
||||
// 先设置默认名称,确保列表能立即显示
|
||||
const defaultName = `${getTypeName(fence.type)}_${fences.value.length + 1}`
|
||||
fence.name = defaultName
|
||||
|
||||
// 保存围栏到列表(立即显示)
|
||||
fences.value.push(fence)
|
||||
|
||||
// 关闭绘制工具,确保不能再继续绘制
|
||||
@@ -547,10 +538,49 @@ const handleDrawComplete = (event) => {
|
||||
mouseTool.close() // 关闭绘制工具,但不删除已绘制的图形
|
||||
}
|
||||
|
||||
// 确保图形显示(延迟设置,确保mouseTool关闭后图形仍然存在)
|
||||
setTimeout(() => {
|
||||
if (fence.shape && fence.shape.getMap()) {
|
||||
// 重新设置样式确保显示
|
||||
// 先更新样式和标签(使用默认名称)
|
||||
updateFenceStyleAndLabel(fence)
|
||||
|
||||
// 获取当前围栏在数组中的索引,用于后续更新
|
||||
const fenceIndex = fences.value.length - 1
|
||||
|
||||
// 弹出输入框让用户输入围栏名称(异步,不阻塞列表显示)
|
||||
ElMessageBox.prompt('请输入围栏名称', '围栏命名', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPlaceholder: '请输入围栏名称',
|
||||
inputValue: defaultName,
|
||||
inputValidator: (value) => {
|
||||
if (!value || value.trim() === '') {
|
||||
return '围栏名称不能为空'
|
||||
}
|
||||
return true
|
||||
}
|
||||
}).then(({ value }) => {
|
||||
// 用户输入了名称,通过数组索引更新,确保Vue响应式系统能检测到变化
|
||||
const newName = value.trim()
|
||||
if (fences.value[fenceIndex]) {
|
||||
fences.value[fenceIndex].name = newName
|
||||
// 更新标签
|
||||
addFenceLabel(fences.value[fenceIndex])
|
||||
}
|
||||
}).catch(() => {
|
||||
// 用户取消,保持默认名称(已经在上面设置了)
|
||||
// 不需要额外操作,标签已经用默认名称创建了
|
||||
})
|
||||
|
||||
// 重置绘制状态
|
||||
isDrawing.value = false
|
||||
currentDrawType.value = null
|
||||
|
||||
console.log('围栏绘制完成:', fence)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新围栏样式和标签
|
||||
const updateFenceStyleAndLabel = (fence) => {
|
||||
// 设置围栏样式
|
||||
if (fence.shape.setOptions) {
|
||||
fence.shape.setOptions({
|
||||
strokeColor: '#0066FF',
|
||||
strokeWeight: 2,
|
||||
@@ -558,20 +588,98 @@ const handleDrawComplete = (event) => {
|
||||
fillColor: '#0066FF',
|
||||
fillOpacity: 0.15,
|
||||
zIndex: 50,
|
||||
visible: true // 确保可见
|
||||
visible: true
|
||||
})
|
||||
}
|
||||
|
||||
// 确保在地图上
|
||||
if (!fence.shape.getMap()) {
|
||||
map.add(fence.shape)
|
||||
}
|
||||
|
||||
// 添加围栏名称标签到地图上
|
||||
addFenceLabel(fence)
|
||||
}
|
||||
|
||||
// 添加围栏名称标签
|
||||
const addFenceLabel = (fence) => {
|
||||
if (!map || !AMap || !fence.name) return
|
||||
|
||||
// 移除旧的标签(如果存在)
|
||||
if (fence.label) {
|
||||
map.remove(fence.label)
|
||||
}
|
||||
}, 50)
|
||||
|
||||
// 重置绘制状态
|
||||
isDrawing.value = false
|
||||
currentDrawType.value = null
|
||||
// 计算标签位置
|
||||
let labelPosition = null
|
||||
|
||||
console.log('围栏绘制完成:', fence)
|
||||
if (fence.type === 'polygon') {
|
||||
// 多边形:使用bounds的右上角(东北角)
|
||||
const bounds = fence.shape.getBounds ? fence.shape.getBounds() : null
|
||||
if (bounds) {
|
||||
const ne = bounds.getNorthEast()
|
||||
labelPosition = [ne.getLng(), ne.getLat()]
|
||||
} else {
|
||||
// 如果没有bounds,使用第一个顶点
|
||||
const path = fence.shape.getPath ? fence.shape.getPath() : fence.path
|
||||
if (path && path.length > 0) {
|
||||
const firstPoint = path[0]
|
||||
if (Array.isArray(firstPoint)) {
|
||||
labelPosition = firstPoint
|
||||
} else if (firstPoint.getLng && firstPoint.getLat) {
|
||||
labelPosition = [firstPoint.getLng(), firstPoint.getLat()]
|
||||
} else {
|
||||
labelPosition = [firstPoint.lng || firstPoint[0], firstPoint.lat || firstPoint[1]]
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (fence.type === 'rectangle') {
|
||||
// 矩形:使用bounds的右上角(东北角)
|
||||
const bounds = fence.shape.getBounds ? fence.shape.getBounds() : fence.bounds
|
||||
if (bounds) {
|
||||
const ne = bounds.getNorthEast()
|
||||
labelPosition = [ne.getLng(), ne.getLat()]
|
||||
}
|
||||
} else if (fence.type === 'circle') {
|
||||
// 圆形:使用圆心,然后向上偏移到右上角位置
|
||||
const center = fence.shape.getCenter ? fence.shape.getCenter() : fence.center
|
||||
const radius = fence.shape.getRadius ? fence.shape.getRadius() : fence.radius
|
||||
if (center) {
|
||||
let centerLng, centerLat
|
||||
if (center.getLng && center.getLat) {
|
||||
centerLng = center.getLng()
|
||||
centerLat = center.getLat()
|
||||
} else {
|
||||
centerLng = center.lng || center[0]
|
||||
centerLat = center.lat || center[1]
|
||||
}
|
||||
// 计算右上角位置(圆心 + 半径的偏移)
|
||||
const offset = radius / 111320 // 转换为经纬度偏移
|
||||
labelPosition = [centerLng + offset, centerLat + offset]
|
||||
}
|
||||
}
|
||||
|
||||
if (labelPosition) {
|
||||
// 创建文本标签,位置在右上角
|
||||
const label = new AMap.Text({
|
||||
text: fence.name,
|
||||
position: labelPosition,
|
||||
offset: new AMap.Pixel(-10, -10), // 偏移到右上角
|
||||
style: {
|
||||
padding: '4px 8px',
|
||||
backgroundColor: 'rgba(0, 102, 255, 0.6)', // 半透明背景
|
||||
border: '1px solid rgba(0, 102, 255, 0.8)',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
color: '#fff',
|
||||
fontWeight: 'bold',
|
||||
whiteSpace: 'nowrap'
|
||||
},
|
||||
zIndex: 100
|
||||
})
|
||||
|
||||
map.add(label)
|
||||
fence.label = label
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,6 +911,10 @@ const removeFence = (fenceId) => {
|
||||
const currentMap = fence.shape.getMap ? fence.shape.getMap() : null
|
||||
if (currentMap) {
|
||||
currentMap.remove(fence.shape)
|
||||
// 同时移除标签
|
||||
if (fence.label) {
|
||||
currentMap.remove(fence.label)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除围栏时出错:', error)
|
||||
@@ -854,6 +966,10 @@ const clearAllFences = async () => {
|
||||
const currentMap = fence.shape.getMap ? fence.shape.getMap() : null
|
||||
if (currentMap) {
|
||||
currentMap.remove(fence.shape)
|
||||
// 同时移除标签
|
||||
if (fence.label) {
|
||||
currentMap.remove(fence.label)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('清除围栏时出错:', error)
|
||||
@@ -1025,6 +1141,13 @@ onUnmounted(() => {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.fence-name {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.drone-status-panel {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
Reference in New Issue
Block a user