Browse Source

冲突1.0

mh
menghao 3 weeks ago
parent
commit
bffabd80f8
  1. 7
      ruoyi-ui/src/lang/en.js
  2. 7
      ruoyi-ui/src/lang/zh.js
  3. 41
      ruoyi-ui/src/views/cesiumMap/index.vue
  4. 159
      ruoyi-ui/src/views/childRoom/RightPanel.vue
  5. 247
      ruoyi-ui/src/views/childRoom/index.vue
  6. 8
      ruoyi-ui/src/views/dialogs/RouteEditDialog.vue

7
ruoyi-ui/src/lang/en.js

@ -118,9 +118,16 @@ export default {
conflictTime: 'Conflict Time',
conflictPosition: 'Conflict Position',
viewDetails: 'View Details',
locate: 'Locate',
resolveConflict: 'Resolve Conflict',
noConflict: 'No Conflict',
noMatchFilter: 'No matches for current filter',
recheck: 'Recheck',
conflictFilter: 'Type',
conflictTypeAll: 'All',
conflictTypeTime: 'Time',
conflictTypeSpace: 'Space',
conflictTypeSpectrum: 'Spectrum',
air: 'Air',
sea: 'Sea',
ground: 'Ground'

7
ruoyi-ui/src/lang/zh.js

@ -118,9 +118,16 @@ export default {
conflictTime: '冲突时间',
conflictPosition: '冲突位置',
viewDetails: '查看详情',
locate: '定位',
resolveConflict: '解决冲突',
noConflict: '暂无冲突',
noMatchFilter: '当前筛选无匹配项',
recheck: '重新检测',
conflictFilter: '类型筛选',
conflictTypeAll: '全部',
conflictTypeTime: '时间',
conflictTypeSpace: '空间',
conflictTypeSpectrum: '频谱',
air: '空中',
sea: '海上',
ground: '地面'

41
ruoyi-ui/src/views/cesiumMap/index.vue

@ -9975,6 +9975,43 @@ export default {
.map(e => this.serializeEntityForSave(e))
return { version: '1.0', date: new Date().toISOString(), entities }
},
/** 供冲突检测用:返回当前地图上所有平台图标位置 [{ id, lng, lat, name }] */
getPlatformIconPositions() {
if (!this.allEntities) return []
return this.allEntities
.filter(e => e && e.type === 'platformIcon')
.map(e => {
let lng = e.lng
let lat = e.lat
if (lng == null || lat == null) {
try {
const pos = e.entity && e.entity.position && e.entity.position.getValue
? e.entity.position.getValue(Cesium.JulianDate.now())
: null
if (pos) {
const ll = this.cartesianToLatLng(pos)
if (ll) { lng = ll.lng; lat = ll.lat }
}
} catch (_) {}
}
return { id: e.id, lng: Number(lng), lat: Number(lat), name: e.label || e.platformName || e.name || `平台${e.id}` }
})
.filter(p => Number.isFinite(p.lng) && Number.isFinite(p.lat))
},
/** 供冲突定位用:相机飞至指定经纬度与高度 */
flyToPosition(lng, lat, alt, duration = 1.5) {
if (!this.viewer || !this.viewer.camera) return
const height = alt != null && Number.isFinite(Number(alt)) ? Number(alt) : 50000
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(Number(lng), Number(lat), Math.max(1000, height)),
orientation: {
heading: 0,
pitch: Cesium.Math.toRadians(-60),
roll: 0
},
duration: duration
})
},
/** 仅清除空域/威力区图形(不删平台图标、航线) */
clearDrawingEntities() {
if (!this.allEntities || !this.viewer) return
@ -11017,12 +11054,12 @@ export default {
} else {
coordinateText = `${lng.toFixed(6)}${lat.toFixed(6)}`
}
this.$message.success(`已定位到经度 ${coordinateText}`)
this.$message({ message: `已定位到经度 ${coordinateText}`, type: 'success', duration: 2000 })
}
},
handleLocateCancel() {
this.$message.info('已取消定位')
this.$message({ message: '已取消定位', type: 'info', duration: 2000 })
},
updateSelectOptions(refName, dataList, labelField) {
const select = document.querySelector(`select[ref="${refName}"]`)

159
ruoyi-ui/src/views/childRoom/RightPanel.vue

@ -123,58 +123,6 @@
</div>
</div>
</div>
<div v-if="activeTab === 'conflict'" class="tab-content conflict-content">
<div v-if="conflicts.length > 0" class="conflict-list">
<div
v-for="conflict in conflicts"
:key="conflict.id"
class="conflict-item"
>
<div class="conflict-header">
<i class="el-icon-warning" style="color: #f56c6c;"></i>
<span class="conflict-title">{{ conflict.title }}</span>
<el-tag size="mini" type="danger">{{ $t('rightPanel.serious') }}</el-tag>
</div>
<div class="conflict-details">
<div class="detail-item">
<span class="label">{{ $t('rightPanel.involvedRoutes') }}</span>
<span class="value">{{ conflict.routeName || (conflict.routes && conflict.routes.join('、')) }}</span>
</div>
<div v-if="conflict.fromWaypoint && conflict.toWaypoint" class="detail-item">
<span class="label">问题航段</span>
<span class="value">{{ conflict.fromWaypoint }} {{ conflict.toWaypoint }}</span>
</div>
<div v-if="conflict.time" class="detail-item">
<span class="label">{{ $t('rightPanel.conflictTime') }}</span>
<span class="value">{{ conflict.time }}</span>
</div>
<div v-if="conflict.position" class="detail-item">
<span class="label">{{ $t('rightPanel.conflictPosition') }}</span>
<span class="value">{{ conflict.position }}</span>
</div>
<div v-if="conflict.suggestion" class="detail-item suggestion">
<span class="label">建议</span>
<span class="value">{{ conflict.suggestion }}</span>
</div>
</div>
<div class="conflict-actions">
<el-button type="text" size="mini" class="blue-text-btn" @click="handleViewConflict(conflict)">
{{ $t('rightPanel.viewDetails') }}
</el-button>
<el-button type="text" size="mini" class="blue-text-btn" @click="handleResolveConflict(conflict)">
{{ $t('rightPanel.resolveConflict') }}
</el-button>
</div>
</div>
</div>
<div v-else class="no-conflict">
<i class="el-icon-success" style="color: #67c23a; font-size: 24px;"></i>
<p>{{ $t('rightPanel.noConflict') }}</p>
<el-button size="mini" class="blue-btn" @click="handleRunConflictCheck">
{{ $t('rightPanel.recheck') }}
</el-button>
</div>
</div>
<div v-if="activeTab === 'platform'" class="tab-content platform-content">
<div class="section-header" style="padding: 10px 0; display: flex; justify-content: space-between; align-items: center;">
<div class="section-title">平台列表</div>
@ -341,14 +289,11 @@ export default {
type: Object,
default: null
},
conflicts: {
/** 父组件要求展开的航线 ID 列表(如冲突定位时),会展开对应方案与航线 */
expandRouteIds: {
type: Array,
default: () => []
},
conflictCount: {
type: Number,
default: 0
},
airPlatforms: {
type: Array,
default: () => []
@ -371,6 +316,19 @@ export default {
}
},
watch: {
expandRouteIds(newVal) {
if (newVal && newVal.length) {
newVal.forEach(routeId => {
const r = this.routes.find(route => route.id === routeId);
if (r && r.scenarioId != null && !this.expandedPlans.includes(r.scenarioId)) {
this.expandedPlans.push(r.scenarioId);
}
if (routeId != null && !this.expandedRoutes.includes(routeId)) {
this.expandedRoutes.push(routeId);
}
});
}
},
selectedPlanId(newId) {
if (newId) {
console.log('>>> [子组件同步] 检测到方案切换,自动展开 ID:', newId);
@ -548,18 +506,6 @@ export default {
});
},
handleViewConflict(conflict) {
this.$emit('view-conflict', conflict)
},
handleResolveConflict(conflict) {
this.$emit('resolve-conflict', conflict)
},
handleRunConflictCheck() {
this.$emit('run-conflict-check')
},
handleOpenPlatformDialog(platform) {
this.$emit('open-platform-dialog', platform)
},
@ -849,81 +795,6 @@ export default {
padding: 10px 0;
}
.conflict-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.conflict-item {
background: rgba(255, 255, 255, 0.8);
border-radius: 6px;
padding: 12px;
border: 1px solid rgba(245, 108, 108, 0.2);
transition: all 0.3s;
}
.conflict-item:hover {
background: rgba(245, 108, 108, 0.1);
box-shadow: 0 2px 8px rgba(245, 108, 108, 0.15);
}
.conflict-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
}
.conflict-title {
flex: 1;
font-weight: 600;
color: #f56c6c;
}
.conflict-details {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 10px;
}
.detail-item {
display: flex;
gap: 8px;
font-size: 13px;
}
.detail-item .label {
color: #999;
min-width: 70px;
}
.detail-item .value {
color: #333;
font-weight: 500;
}
.detail-item.suggestion .value {
white-space: normal;
word-break: break-word;
color: #008aff;
}
.conflict-actions {
display: flex;
gap: 10px;
}
.no-conflict {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
padding: 40px 20px;
color: #999;
}
.platform-categories {
height: 100%;
}

247
ruoyi-ui/src/views/childRoom/index.vue

@ -194,8 +194,7 @@
:route-locked-by="routeLockedBy"
:current-user-id="currentUserId"
:selected-route-details="selectedRouteDetails"
:conflicts="conflicts"
:conflict-count="conflictCount"
:expand-route-ids="expandRouteIdsForPanel"
:air-platforms="airPlatforms"
:sea-platforms="seaPlatforms"
:ground-platforms="groundPlatforms"
@ -213,9 +212,6 @@
@cancel-route="cancelRoute"
@toggle-route-visibility="(route, opts) => toggleRouteVisibility(route, opts)"
@toggle-route-lock="handleToggleRouteLockFromPanel"
@view-conflict="viewConflict"
@resolve-conflict="resolveConflict"
@run-conflict-check="runConflictCheck"
@open-platform-dialog="openPlatformDialog"
@delete-platform="handleDeletePlatform"
@open-import-dialog="showImportDialog = true"
@ -338,6 +334,7 @@
v-model="showRouteDialog"
:route="selectedRoute"
:room-id="currentRoomId"
:initial-tab="routeEditInitialTab"
@save="updateRoute"
/>
@ -415,6 +412,15 @@
:room-id="currentRoomId"
/>
<!-- 冲突列表弹窗可拖动可调整大小分页点击左侧冲突按钮即打开并自动检测 -->
<conflict-drawer
v-if="!screenshotMode"
:visible.sync="showConflictDrawer"
:conflicts="conflicts"
@view-conflict="viewConflict"
@resolve-conflict="resolveConflict"
/>
<!-- 白板面板底部 -->
<whiteboard-panel
v-show="showWhiteboardPanel && !screenshotMode"
@ -496,6 +502,7 @@ import RightPanel from './RightPanel'
import BottomLeftPanel from './BottomLeftPanel'
import TopHeader from './TopHeader'
import FourTPanel from './FourTPanel'
import ConflictDrawer from './ConflictDrawer'
import WhiteboardPanel from './WhiteboardPanel'
import { createRoomWebSocket } from '@/utils/websocket';
import { listScenario, addScenario, delScenario } from "@/api/system/scenario";
@ -510,6 +517,18 @@ import PlatformImportDialog from "@/views/dialogs/PlatformImportDialog.vue";
import ExportRoutesDialog from "@/views/dialogs/ExportRoutesDialog.vue";
import ImportRoutesDialog from "@/views/dialogs/ImportRoutesDialog.vue";
import GanttDrawer from './GanttDrawer.vue';
import {
CONFLICT_TYPE,
defaultConflictConfig,
detectTimeWindowOverlap,
detectTrackSeparation,
detectPlatformPlacementTooClose,
detectRestrictedZoneIntrusion,
parseRestrictedZonesFromDrawings,
detectSpectrumConflicts,
createSpectrumLedgerEntry,
normalizeConflictList
} from '@/utils/conflictDetection';
export default {
name: 'MissionPlanningView',
components: {
@ -531,6 +550,7 @@ export default {
BottomLeftPanel,
TopHeader,
FourTPanel,
ConflictDrawer,
WhiteboardPanel
},
data() {
@ -685,6 +705,12 @@ export default {
showKTimePopup: false,
// 4T4T/
show4TPanel: false,
/** 冲突列表弹窗(点击左侧冲突按钮即打开并自动执行检测) */
showConflictDrawer: false,
/** 定位冲突时让右侧面板展开的航线 ID 列表 */
expandRouteIdsForPanel: [],
/** 打开航线编辑弹窗时默认选中的 tab(解决冲突时传 'waypoints' 直接打开航点列表) */
routeEditInitialTab: null,
//
showWhiteboardPanel: false,
@ -715,6 +741,10 @@ export default {
// runConflictCheck 线
conflictCount: 0,
conflicts: [],
/** 冲突检测配置(时间缓冲、航迹最小间隔、平台摆放最小距离、禁限区关键词、频谱邻频保护等) */
conflictConfig: { ...defaultConflictConfig },
/** 频谱资源台账(用于频谱冲突检测),可后续从接口或界面维护 */
spectrumLedger: [],
//
activePlatformTab: 'air',
@ -2075,6 +2105,7 @@ export default {
// 线
openRouteDialog(route) {
this.selectedRoute = route;
this.routeEditInitialTab = null;
this.showRouteDialog = true;
// 线广
if (this.wsConnection && this.wsConnection.sendObjectEditLock && route && route.id != null) {
@ -3777,13 +3808,9 @@ export default {
// /退
this.toggleWhiteboardMode();
} else if (item.id === 'start') {
//
if (this.activeRightTab === 'conflict' && !this.isRightPanelHidden) {
this.isRightPanelHidden = true;
} else {
this.activeRightTab = 'conflict';
this.isRightPanelHidden = false;
}
//
this.showConflictDrawer = true;
this.$nextTick(() => { this.runConflictCheck(); });
} else if (item.id === 'insert') {
//
if (this.activeRightTab === 'platform' && !this.isRightPanelHidden) {
@ -5025,13 +5052,16 @@ export default {
}
},
// 线
// 线
runConflictCheck() {
const list = [];
let id = 1;
const routeIds = this.activeRouteIds && this.activeRouteIds.length > 0 ? this.activeRouteIds : this.routes.map(r => r.id);
const { minMinutes, maxMinutes } = this.getDeductionTimeRange();
const config = this.conflictConfig || defaultConflictConfig;
const waypointStartTimeToMinutes = (s) => this.waypointStartTimeToMinutes(s);
const allRaw = [];
// ---------- 线----------
routeIds.forEach(routeId => {
const route = this.routes.find(r => r.id === routeId);
if (!route || !route.waypoints || route.waypoints.length < 2) return;
@ -5043,65 +5073,208 @@ export default {
}
}
const { earlyArrivalLegs, lateArrivalLegs, holdDelayConflicts } = this.buildRouteTimeline(route.waypoints, minMinutes, maxMinutes, pathData);
const routeName = route.name || `航线${route.id}`;
(earlyArrivalLegs || []).forEach(leg => {
list.push({
id: id++,
// /
allRaw.push({
type: CONFLICT_TYPE.TIME,
subType: 'early_arrival',
title: '提前到达',
routeName,
routeIds: [routeId],
fromWaypoint: leg.fromName,
toWaypoint: leg.toName,
time: this.minutesToStartTime(leg.actualArrival),
suggestion: '该航段将提前到达下一航点,建议在此段加入盘旋或延后下一航点计划时间。',
suggestion: '该航段将提前到达下一航点。可选措施:① 适当降低本段巡航速度;② 在本段或下一航点前增加盘旋等待;③ 视任务需要调整下一航点相对K时/计划时间。若存在定速点或定时点,请优先调整未受约束的速度或时间。',
severity: 'high'
});
});
(lateArrivalLegs || []).forEach(leg => {
list.push({
id: id++,
// /
allRaw.push({
type: CONFLICT_TYPE.TIME,
subType: 'late_arrival',
title: '无法按时到达',
routeName,
routeIds: [routeId],
fromWaypoint: leg.fromName,
toWaypoint: leg.toName,
suggestion: `当前速度不足,建议将本段速度提升至 ≥${leg.requiredSpeedKmh} km/h,或延后下一航点计划时间`,
suggestion: `当前速度不足,理论上需将本段速度提升至 ≥${leg.requiredSpeedKmh} km/h 才能按时到达。可选措施:① 在安全范围内提高本段或前一段速度;② 适当提前下一航点相对K时/计划时间;③ 结合任务需要调整上游航段或加入盘旋缓冲。若存在定速点或定时点,请优先从未锁定的速度或时间入手`,
severity: 'high'
});
});
(holdDelayConflicts || []).forEach(conf => {
list.push({
id: id++,
// /
allRaw.push({
type: CONFLICT_TYPE.TIME,
subType: 'hold_delay',
title: '盘旋时间不足',
routeName,
routeIds: [routeId],
fromWaypoint: conf.fromName,
toWaypoint: conf.toName,
time: this.minutesToStartTime(conf.setExitTime),
position: conf.holdCenter ? `经度 ${conf.holdCenter.lng.toFixed(5)}°, 纬度 ${conf.holdCenter.lat.toFixed(5)}°` : undefined,
suggestion: `警告:设定的盘旋时间不足以支撑战斗机完成最后一圈,实际切出将延迟 ${conf.delaySeconds} 秒。`,
suggestion: `警告:设定的盘旋时间不足以支撑战斗机完成最后一圈,实际切出将延迟 ${conf.delaySeconds} 秒。可选措施:① 增加盘旋圈数或调整盘旋结束时间;② 在允许范围内调整盘旋段速度;③ 结合上下游航段,微调相关航点的相对K时/计划时间。若存在定速点或定时点,请优先调整未受约束的参数。`,
severity: 'high',
holdCenter: conf.holdCenter
holdCenter: conf.holdCenter,
positionLng: conf.holdCenter && conf.holdCenter.lng,
positionLat: conf.holdCenter && conf.holdCenter.lat,
positionAlt: conf.holdCenter && conf.holdCenter.alt
});
});
});
this.conflicts = list;
this.conflictCount = list.length;
if (list.length > 0) {
this.$message.warning(`检测到 ${list.length} 处航线时间问题`);
// /
// detectTimeWindowOverlap
// ---------- ----------
const getPositionAtMinutesForConflict = (routeId, minutesFromK) => {
const route = this.routes.find(r => r.id === routeId);
if (!route || !route.waypoints || route.waypoints.length === 0) return null;
const { position } = this.getPositionAtMinutesFromK(route.waypoints, minutesFromK, minMinutes, maxMinutes, routeId);
return position;
};
const trackConflicts = detectTrackSeparation(routeIds, minMinutes, maxMinutes, getPositionAtMinutesForConflict, config);
trackConflicts.forEach(c => allRaw.push(c));
// ---------- ----------
const platformIcons = this.$refs.cesiumMap && this.$refs.cesiumMap.getPlatformIconPositions ? this.$refs.cesiumMap.getPlatformIconPositions() : [];
const placementConflicts = detectPlatformPlacementTooClose(platformIcons, config);
placementConflicts.forEach(c => allRaw.push(c));
// ---------- ----------
let restrictedZones = [];
if (this.$refs.cesiumMap && this.$refs.cesiumMap.getFrontendDrawingsData) {
const drawings = this.$refs.cesiumMap.getFrontendDrawingsData();
const entities = (drawings && drawings.entities) || [];
restrictedZones = parseRestrictedZonesFromDrawings(entities, config.restrictedZoneNameKeywords || defaultConflictConfig.restrictedZoneNameKeywords);
restrictedZones = restrictedZones.map(z => ({ ...z, points: z.points || (z.data && z.data.points) || [] })).filter(z => z.points && z.points.length >= 3);
}
const restrictedConflicts = detectRestrictedZoneIntrusion(routeIds, minMinutes, maxMinutes, getPositionAtMinutesForConflict, restrictedZones, config);
restrictedConflicts.forEach(c => allRaw.push(c));
// ---------- ----------
if (this.spectrumLedger && this.spectrumLedger.length >= 2) {
const spectrumConflicts = detectSpectrumConflicts(this.spectrumLedger, config);
spectrumConflicts.forEach(c => allRaw.push(c));
}
this.conflicts = normalizeConflictList(allRaw, 1);
this.conflictCount = this.conflicts.length;
if (this.conflicts.length > 0) {
this.$message.warning(`检测到 ${this.conflicts.length} 处冲突`);
} else {
this.$message.success('未发现航线时间冲突');
this.$message.success('未发现冲突');
}
},
/** 查看冲突:展开问题航线、显示右侧方案树、定位到冲突位置并跳转时间轴 */
viewConflict(conflict) {
this.$message.info(`查看冲突:${conflict.title}`);
const routeIds = conflict.routeIds || [];
if (routeIds.length > 0) {
// 线线
const prevActive = this.activeRouteIds || [];
this.activeRouteIds = [...new Set([...prevActive, ...routeIds])];
this.isRightPanelHidden = false;
this.activeRightTab = 'plan';
this.expandRouteIdsForPanel = [...routeIds];
// 线
if (this.$refs.cesiumMap) {
routeIds.forEach(async (routeId) => {
const route = this.routes.find(r => r.id === routeId);
if (!route) return;
//
let waypoints = Array.isArray(route.waypoints) ? route.waypoints : [];
if (!waypoints.length) {
try {
const res = await getRoutes(route.id);
if (res && res.code === 200 && res.data && Array.isArray(res.data.waypoints)) {
waypoints = res.data.waypoints;
// routes
const idx = this.routes.findIndex(r => r.id === route.id);
if (idx > -1) {
this.$set(this.routes, idx, {
...this.routes[idx],
waypoints
});
}
}
} catch (e) {
console.warn('viewConflict: 获取航线航点失败', e);
}
}
if (waypoints.length > 0) {
// 线
const roomId = this.currentRoomId;
if (roomId && route.platformId) {
try {
const styleRes = await getPlatformStyle({ roomId, routeId, platformId: route.platformId });
if (styleRes && styleRes.data) {
this.$refs.cesiumMap.setPlatformStyle(routeId, styleRes.data);
}
} catch (_) {}
}
this.$refs.cesiumMap.renderRouteWaypoints(
waypoints,
routeId,
route.platformId,
route.platform,
this.parseRouteStyle(route.attributes)
);
}
});
}
}
if (conflict.positionLng != null && conflict.positionLat != null && this.$refs.cesiumMap && this.$refs.cesiumMap.flyToPosition) {
this.$refs.cesiumMap.flyToPosition(conflict.positionLng, conflict.positionLat, conflict.positionAlt, 1.5);
}
if (conflict.minutesFromK != null && Number.isFinite(conflict.minutesFromK)) {
const { minMinutes, maxMinutes } = this.getDeductionTimeRange();
const span = Math.max(0, maxMinutes - minMinutes) || 120;
const progress = Math.max(0, Math.min(100, ((conflict.minutesFromK - minMinutes) / span) * 100));
this.timeProgress = progress;
}
this.$message({ message: `已定位:${conflict.title}`, type: 'info', duration: 2000 });
},
resolveConflict(conflict) {
this.$message.success(`解决冲突:${conflict.title}`);
//
this.conflicts = this.conflicts.filter(c => c.id !== conflict.id);
this.conflictCount = this.conflicts.length;
/** 解决冲突:根据建议打开该航线的航点列表(编辑航线弹窗-航点 tab),由用户修改盘旋/速度/相对K时等,不直接删除冲突 */
async resolveConflict(conflict) {
const routeId = conflict.routeIds && conflict.routeIds[0];
if (!routeId) {
this.$message.warning('无法确定关联航线');
return;
}
let route = this.routes.find(r => r.id === routeId);
if (!route) {
this.$message.warning('未找到该航线');
return;
}
if (!route.waypoints || route.waypoints.length === 0) {
try {
const res = await getRoutes(routeId);
if (res.data && res.data.waypoints) {
route = { ...route, waypoints: res.data.waypoints };
const idx = this.routes.findIndex(r => r.id === routeId);
if (idx !== -1) this.routes.splice(idx, 1, route);
}
} catch (e) {
console.warn('获取航线航点失败', e);
}
}
this.selectedRouteId = routeId;
this.selectedRouteDetails = route.waypoints ? { ...route } : null;
this.selectedRoute = route.waypoints ? { ...route } : route;
this.routeEditInitialTab = 'waypoints';
this.showRouteDialog = true;
if (this.wsConnection && this.wsConnection.sendObjectEditLock && route && route.id != null) {
this.wsConnection.sendObjectEditLock('route', route.id);
this.routeEditLockedId = route.id;
}
this.$message.info('请根据建议在航点列表中修改(如加入盘旋或调整相对K时/速度)');
},
//

8
ruoyi-ui/src/views/dialogs/RouteEditDialog.vue

@ -331,7 +331,9 @@ export default {
props: {
value: { type: Boolean, default: false },
route: { type: Object, default: () => ({}) },
roomId: { type: [String, Number], default: null }
roomId: { type: [String, Number], default: null },
/** 打开时默认选中的 tab:'basic' | 'platform' | 'waypoints',解决冲突时传 'waypoints' 直接打开航点列表 */
initialTab: { type: String, default: '' }
},
data() {
return {
@ -416,7 +418,11 @@ export default {
visible(val) {
if (val) {
this.loadPosition()
if (this.initialTab === 'waypoints' || this.initialTab === 'platform') {
this.activeTab = this.initialTab
}
if (this.activeTab === 'platform') this.loadPlatforms()
if (this.activeTab === 'waypoints' && this.panelWidth < 920) this.panelWidth = 920
this.skipBasicStyleSyncOnce = true
}
},

Loading…
Cancel
Save