|
|
|
@ -15,6 +15,7 @@ |
|
|
|
:coordinateFormat="coordinateFormat" |
|
|
|
:bottomPanelVisible="bottomPanelVisible" |
|
|
|
:route-locked="routeLocked" |
|
|
|
:route-locked-by-other-ids="routeLockedByOtherRouteIds" |
|
|
|
:deduction-time-minutes="deductionMinutesFromK" |
|
|
|
:room-id="currentRoomId" |
|
|
|
@draw-complete="handleMapDrawComplete" |
|
|
|
@ -176,7 +177,6 @@ |
|
|
|
:routes="routes" |
|
|
|
:active-route-ids="activeRouteIds" |
|
|
|
:route-locked="routeLocked" |
|
|
|
:route-viewing-by="routeViewingBy" |
|
|
|
:route-locked-by="routeLockedBy" |
|
|
|
:current-user-id="currentUserId" |
|
|
|
:selected-route-details="selectedRouteDetails" |
|
|
|
@ -514,8 +514,7 @@ export default { |
|
|
|
screenshotDataUrl: '', |
|
|
|
screenshotFileName: '', |
|
|
|
|
|
|
|
// 协作:谁正在查看/编辑哪条航线(来自 WebSocket 广播) |
|
|
|
routeViewingBy: {}, // routeId -> { userId, userName, nickName, sessionId } |
|
|
|
// 协作:谁正在编辑(锁定)哪条航线(来自 WebSocket 广播) |
|
|
|
routeLockedBy: {}, // routeId -> { userId, userName, nickName, sessionId } |
|
|
|
routeEditLockedId: null, // 本端当前编辑锁定的航线 ID,关闭弹窗时发送解锁 |
|
|
|
|
|
|
|
@ -688,14 +687,6 @@ export default { |
|
|
|
}); |
|
|
|
} |
|
|
|
}, |
|
|
|
/** 选中航线变化时:广播“正在查看”或取消查看,供其他成员显示 */ |
|
|
|
selectedRouteId: { |
|
|
|
handler(newId, oldId) { |
|
|
|
if (!this.wsConnection || !this.wsConnection.sendObjectViewClear || !this.wsConnection.sendObjectView) return; |
|
|
|
if (oldId != null) this.wsConnection.sendObjectViewClear('route', oldId); |
|
|
|
if (newId != null) this.wsConnection.sendObjectView('route', newId); |
|
|
|
} |
|
|
|
}, |
|
|
|
/** 航线编辑弹窗关闭时:发送编辑解锁,让其他成员可编辑 */ |
|
|
|
showRouteDialog(visible) { |
|
|
|
if (visible) return; |
|
|
|
@ -744,6 +735,17 @@ export default { |
|
|
|
if (!this.addHoldContext) return ''; |
|
|
|
if (this.addHoldContext.mode === 'drawing') return '在最后两航点之间插入盘旋,保存航线时生效。'; |
|
|
|
return `在 ${this.addHoldContext.fromName} 与 ${this.addHoldContext.toName} 之间添加盘旋,到计划时间后沿切线飞往下一航点(原「下一格」航点将被移除)。`; |
|
|
|
}, |
|
|
|
/** 被其他成员编辑锁定的航线 ID 列表,供地图禁止拖拽等 */ |
|
|
|
routeLockedByOtherRouteIds() { |
|
|
|
const myId = this.currentUserId; |
|
|
|
if (myId == null) return Object.keys(this.routeLockedBy).map(id => Number(id)); |
|
|
|
const ids = []; |
|
|
|
Object.keys(this.routeLockedBy).forEach(rid => { |
|
|
|
const editor = this.routeLockedBy[rid]; |
|
|
|
if (editor && Number(editor.userId) !== Number(myId)) ids.push(Number(rid)); |
|
|
|
}); |
|
|
|
return ids; |
|
|
|
} |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
@ -784,6 +786,10 @@ export default { |
|
|
|
}, |
|
|
|
// 处理从地图点击传来的编辑请求(支持 wpId 或 waypointIndex,如右键盘旋弧时仅有 waypointIndex) |
|
|
|
async handleOpenWaypointEdit(wpId, routeId, waypointIndex) { |
|
|
|
if (routeId != null && this.isRouteLockedByOther(routeId)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法修改航点'); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (waypointIndex != null && (wpId == null || wpId === undefined)) { |
|
|
|
try { |
|
|
|
const response = await getRoutes(routeId); |
|
|
|
@ -866,18 +872,22 @@ export default { |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
/** 该航线是否被其他成员编辑锁定(非自己) */ |
|
|
|
isRouteLockedByOther(routeId) { |
|
|
|
const lockedBy = this.routeLockedBy[routeId]; |
|
|
|
if (!lockedBy) return false; |
|
|
|
const myId = this.currentUserId != null ? Number(this.currentUserId) : null; |
|
|
|
const uid = lockedBy.userId != null ? Number(lockedBy.userId) : null; |
|
|
|
return myId !== uid; |
|
|
|
}, |
|
|
|
// 处理从地图点击传来的航线编辑请求 |
|
|
|
async handleOpenRouteEdit(routeId) { |
|
|
|
console.log(`>>> [父组件接收] 航线 ID: ${routeId}`); |
|
|
|
const lockedBy = this.routeLockedBy[routeId]; |
|
|
|
if (lockedBy) { |
|
|
|
const myId = this.currentUserId != null ? Number(this.currentUserId) : null; |
|
|
|
const uid = lockedBy.userId != null ? Number(lockedBy.userId) : null; |
|
|
|
if (myId !== uid) { |
|
|
|
const name = lockedBy.nickName || lockedBy.userName || '其他成员'; |
|
|
|
this.$message.warning(`${name} 正在编辑该航线,请稍后再试`); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (this.isRouteLockedByOther(routeId)) { |
|
|
|
const lockedBy = this.routeLockedBy[routeId]; |
|
|
|
const name = lockedBy && (lockedBy.nickName || lockedBy.userName) || '其他成员'; |
|
|
|
this.$message.warning(`${name} 正在编辑该航线,请稍后再试`); |
|
|
|
return; |
|
|
|
} |
|
|
|
try { |
|
|
|
const response = await getRoutes(routeId); |
|
|
|
@ -905,6 +915,10 @@ export default { |
|
|
|
|
|
|
|
/** 右键航点“向前/向后增加航点”:进入放置模式,传入 waypoints 给地图预览 */ |
|
|
|
handleAddWaypointAt({ routeId, waypointIndex, mode }) { |
|
|
|
if (this.isRouteLockedByOther(routeId)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法添加航点'); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (this.routeLocked[routeId]) { |
|
|
|
this.$message.info('该航线已上锁,请先解锁'); |
|
|
|
return; |
|
|
|
@ -1032,6 +1046,10 @@ export default { |
|
|
|
|
|
|
|
/** 右键航点“切换盘旋航点”:普通航点设为盘旋(圆形默认),盘旋航点设为普通;支持首尾航点 */ |
|
|
|
async handleToggleWaypointHold({ routeId, dbId, waypointIndex }) { |
|
|
|
if (this.isRouteLockedByOther(routeId)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法修改'); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (this.routeLocked[routeId]) { |
|
|
|
this.$message.info('该航线已上锁,请先解锁'); |
|
|
|
return; |
|
|
|
@ -1168,6 +1186,10 @@ export default { |
|
|
|
|
|
|
|
/** 地图上拖拽航点结束:将新位置写回数据库并刷新显示 */ |
|
|
|
async handleWaypointPositionChanged({ dbId, routeId, lat, lng, alt }) { |
|
|
|
if (this.isRouteLockedByOther(routeId)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法拖拽修改'); |
|
|
|
return; |
|
|
|
} |
|
|
|
let waypoints = null; |
|
|
|
let route = null; |
|
|
|
if (this.selectedRouteDetails && this.selectedRouteDetails.id === routeId) { |
|
|
|
@ -1337,27 +1359,13 @@ export default { |
|
|
|
this.wsOnlineMembers = this.wsOnlineMembers.filter(m => m.id !== sessionId && m.id !== member.sessionId); |
|
|
|
this.onlineCount = this.wsOnlineMembers.length; |
|
|
|
this.mySyncSessionIds = this.mySyncSessionIds.filter(s => s !== sessionId && s !== member.sessionId); |
|
|
|
// 该成员离开后清除其查看/编辑状态 |
|
|
|
Object.keys(this.routeViewingBy).forEach(rid => { |
|
|
|
if (this.routeViewingBy[rid] && this.routeViewingBy[rid].sessionId === sessionId) { |
|
|
|
this.$delete(this.routeViewingBy, rid); |
|
|
|
} |
|
|
|
}); |
|
|
|
// 该成员离开后清除其编辑锁定状态 |
|
|
|
Object.keys(this.routeLockedBy).forEach(rid => { |
|
|
|
if (this.routeLockedBy[rid] && this.routeLockedBy[rid].sessionId === sessionId) { |
|
|
|
this.$delete(this.routeLockedBy, rid); |
|
|
|
} |
|
|
|
}); |
|
|
|
}, |
|
|
|
onObjectViewing: (msg) => { |
|
|
|
if (msg.objectType !== 'route' || msg.objectId == null) return; |
|
|
|
this.$set(this.routeViewingBy, msg.objectId, msg.viewer); |
|
|
|
}, |
|
|
|
onObjectViewClear: (msg) => { |
|
|
|
if (msg.objectType !== 'route' || msg.objectId == null) return; |
|
|
|
const cur = this.routeViewingBy[msg.objectId]; |
|
|
|
if (cur && cur.sessionId === msg.sessionId) this.$delete(this.routeViewingBy, msg.objectId); |
|
|
|
}, |
|
|
|
onObjectEditLock: (msg) => { |
|
|
|
if (msg.objectType !== 'route' || msg.objectId == null) return; |
|
|
|
this.$set(this.routeLockedBy, msg.objectId, msg.editor); |
|
|
|
@ -1416,7 +1424,6 @@ export default { |
|
|
|
this.mySyncSessionIds = []; |
|
|
|
this.chatMessages = []; |
|
|
|
this.privateChatMessages = {}; |
|
|
|
this.routeViewingBy = {}; |
|
|
|
this.routeLockedBy = {}; |
|
|
|
}, |
|
|
|
onError: (err) => { |
|
|
|
@ -1694,6 +1701,10 @@ export default { |
|
|
|
}, |
|
|
|
// 更新航线数据(含航点表编辑后的批量持久化) |
|
|
|
async updateRoute(updatedRoute) { |
|
|
|
if (this.isRouteLockedByOther(updatedRoute.id)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法保存'); |
|
|
|
return; |
|
|
|
} |
|
|
|
const index = this.routes.findIndex(r => r.id === updatedRoute.id); |
|
|
|
if (index === -1) return; |
|
|
|
try { |
|
|
|
@ -1802,6 +1813,10 @@ export default { |
|
|
|
} |
|
|
|
}, |
|
|
|
async handleDeleteRoute(route) { |
|
|
|
if (this.isRouteLockedByOther(route.id)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法删除'); |
|
|
|
return; |
|
|
|
} |
|
|
|
try { |
|
|
|
// 二次确认,防止误删 |
|
|
|
await this.$confirm(`确定要彻底删除航线 "${route.name}" 吗?`, '提示', { |
|
|
|
@ -2059,6 +2074,10 @@ export default { |
|
|
|
// 航点编辑弹窗相关方法 |
|
|
|
openWaypointDialog(data) { |
|
|
|
console.log(">>> [父组件接收] 编辑航点详情:", data); |
|
|
|
if (data && data.routeId != null && this.isRouteLockedByOther(data.routeId)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法修改'); |
|
|
|
return; |
|
|
|
} |
|
|
|
// 将整个对象赋值给弹窗绑定的变量 |
|
|
|
this.selectedWaypoint = data; |
|
|
|
this.showWaypointDialog = true; |
|
|
|
@ -2066,6 +2085,11 @@ export default { |
|
|
|
/** 航点编辑保存:更新数据库并同步地图显示 */ |
|
|
|
async updateWaypoint(updatedWaypoint) { |
|
|
|
if (!this.selectedRouteDetails || !this.selectedRouteDetails.waypoints) return; |
|
|
|
const routeId = updatedWaypoint.routeId != null ? updatedWaypoint.routeId : this.selectedRouteDetails.id; |
|
|
|
if (this.isRouteLockedByOther(routeId)) { |
|
|
|
this.$message.warning('该航线正被其他成员编辑,无法保存'); |
|
|
|
return; |
|
|
|
} |
|
|
|
try { |
|
|
|
if (this.$refs.cesiumMap && updatedWaypoint.turnAngle > 0) { |
|
|
|
updatedWaypoint.turnRadius = this.$refs.cesiumMap.getWaypointRadius(updatedWaypoint); |
|
|
|
|