Browse Source

编辑航线弹窗样式修改、删除航点列表

mh
menghao 2 weeks ago
parent
commit
935cb97a2d
  1. 52
      ruoyi-ui/src/views/cesiumMap/index.vue
  2. 89
      ruoyi-ui/src/views/childRoom/RightPanel.vue
  3. 60
      ruoyi-ui/src/views/childRoom/index.vue
  4. 73
      ruoyi-ui/src/views/dialogs/RouteEditDialog.vue

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

@ -2588,56 +2588,8 @@ export default {
}).catch(() => {});
}
};
if (currentRoomId && platId && !hasZoneOnRoute) {
getPlatformStyle({ roomId: currentRoomId, routeId: 0, platformId: platId }).then(standRes => {
const stand = standRes.data;
if (stand) {
const normalizedStand = this.normalizeZonesFromStyle(stand)
const savedDetectionZones = normalizedStand.detectionZones || []
const savedPowerZones = normalizedStand.powerZones || []
if (savedDetectionZones.length > 0 || savedPowerZones.length > 0) {
const firstSavedDetection = savedDetectionZones[0] || null
const firstSavedPower = savedPowerZones[0] || null
style = Object.assign({}, style || {}, {
detectionZones: savedDetectionZones,
powerZones: savedPowerZones,
detectionZoneRadius: firstSavedDetection ? firstSavedDetection.radiusKm : stand.detectionZoneRadius,
detectionZoneColor: firstSavedDetection ? firstSavedDetection.color : stand.detectionZoneColor,
detectionZoneOpacity: firstSavedDetection ? firstSavedDetection.opacity : stand.detectionZoneOpacity,
detectionZoneVisible: firstSavedDetection ? firstSavedDetection.visible !== false : stand.detectionZoneVisible,
powerZoneRadius: firstSavedPower ? firstSavedPower.radiusKm : stand.powerZoneRadius,
powerZoneAngle: firstSavedPower ? firstSavedPower.angleDeg : stand.powerZoneAngle,
powerZoneColor: firstSavedPower ? firstSavedPower.color : stand.powerZoneColor,
powerZoneOpacity: firstSavedPower ? firstSavedPower.opacity : stand.powerZoneOpacity,
powerZoneVisible: firstSavedPower ? firstSavedPower.visible !== false : stand.powerZoneVisible
});
savePlatformStyle({
roomId: String(currentRoomId),
routeId: routeId,
platformId: platId,
platformName: (style.platformName || (platform && platform.name)) || undefined,
labelFontSize: style.labelFontSize,
labelFontColor: style.labelFontColor,
platformSize: style.platformSize,
platformColor: style.platformColor,
detectionZones: savedDetectionZones,
powerZones: savedPowerZones,
detectionZoneRadius: style.detectionZoneRadius,
detectionZoneColor: style.detectionZoneColor,
detectionZoneOpacity: style.detectionZoneOpacity,
detectionZoneVisible: style.detectionZoneVisible,
powerZoneRadius: style.powerZoneRadius,
powerZoneAngle: style.powerZoneAngle,
powerZoneColor: style.powerZoneColor,
powerZoneOpacity: style.powerZoneOpacity,
powerZoneVisible: style.powerZoneVisible
}).catch(() => {});
}
}
applyStyle(style);
}).catch(() => applyStyle(style));
return;
}
// 线使 routeId routeId=0/
// 线使线
applyStyle(style);
}).catch(() => {
addPlatformBillboard('#000000', 144);

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

@ -55,7 +55,7 @@
:class="getRouteClasses(route.id)"
>
<div class="tree-item-header" @click="toggleRoute(route.id)">
<i :class="expandedRoutes.includes(route.id) ? 'el-icon-map-location' : 'el-icon-map-location'" class="tree-icon"></i>
<i class="el-icon-map-location tree-icon"></i>
<div class="tree-item-info">
<div class="tree-item-name">{{ route.name }}</div>
<div class="tree-item-meta">{{ route.points }}{{ $t('rightPanel.points') }}</div>
@ -98,25 +98,6 @@
></i>
</div>
</div>
<!-- 航点列表 -->
<div v-if="expandedRoutes.includes(route.id)" class="tree-children waypoint-children">
<div
v-for="(point,index) in (expandedRoutes.includes(route.id) && route.waypoints ? route.waypoints : [])"
:key="point.name"
class="tree-item waypoint-item"
>
<div class="tree-item-header">
<i class="el-icon-location tree-icon"></i>
<div class="tree-item-info">
<div class="tree-item-name">{{ point.name }}</div>
<div class="tree-item-meta">高度: {{ point.alt }}m | 速度: {{ point.speed }}<template v-if="point.startTime"> | 相对K: {{ formatWaypointKTime(point.startTime) }}</template></div>
</div>
<div class="tree-item-actions">
<i class="el-icon-edit" title="编辑" @click.stop="handleOpenWaypointDialog(point, index, route.waypoints.length)"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@ -289,7 +270,7 @@ export default {
type: Object,
default: null
},
/** 父组件要求展开的航线 ID 列表(如冲突定位时),会展开对应方案与航线 */
/** 父组件要求展开的方案树(如冲突定位时),会展开对应方案以便看到航线行 */
expandRouteIds: {
type: Array,
default: () => []
@ -311,7 +292,6 @@ export default {
return {
activePlatformTab: 'air',
expandedPlans: [], //
expandedRoutes: [], // 线
platformJustDragged: false //
}
},
@ -323,9 +303,6 @@ export default {
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);
}
});
}
},
@ -346,17 +323,6 @@ export default {
}
},
methods: {
/** 航点 startTime(如 K+00:40:00)格式化为简短显示:K+40 或 K-15 */
formatWaypointKTime(startTime) {
if (!startTime || typeof startTime !== 'string') return '—';
const m = startTime.match(/K([+-])(\d{2}):(\d{2})/);
if (!m) return startTime;
const sign = m[1];
const h = parseInt(m[2], 10);
const min = parseInt(m[3], 10);
const totalMin = h * 60 + min;
return totalMin === 0 ? 'K+0' : `K${sign}${totalMin}`;
},
// /
togglePlan(planId) {
const index = this.expandedPlans.indexOf(planId)
@ -372,7 +338,6 @@ export default {
} else {
// 线线
this.expandedPlans = [];
this.expandedRoutes = [];
this.expandedPlans.push(planId)
const plan = this.plans.find(p => p.id === planId)
if (plan) {
@ -381,34 +346,19 @@ export default {
}
},
// 线/
// 线 selectRoute 线
toggleRoute(routeId) {
const route = this.routes.find(r => r.id === routeId)
if (!route) return
if (!route.waypoints) {
this.$set(route, 'waypoints', []); // 使 $set
this.$set(route, 'waypoints', [])
}
const isRouteSelected = this.activeRouteIds.includes(routeId)
const isRouteExpanded = this.expandedRoutes.includes(routeId)
if (isRouteSelected) {
if (isRouteExpanded) {
const index = this.expandedRoutes.indexOf(routeId)
this.expandedRoutes.splice(index, 1)
} else {
this.expandedRoutes.push(routeId)
this.handleSelectRoute(route)
this.$nextTick(() => {
if (route.scenarioId != null && !this.expandedPlans.includes(route.scenarioId)) {
this.expandedPlans.push(route.scenarioId)
}
} else {
this.handleSelectRoute(route)
this.$nextTick(() => {
// 线
if (!this.expandedPlans.includes(route.scenarioId)) {
this.expandedPlans.push(route.scenarioId);
}
if (!this.expandedRoutes.includes(routeId)) {
this.expandedRoutes.push(routeId)
}
})
}
})
},
//
@ -473,11 +423,6 @@ export default {
handleToggleRouteVisibility(route) {
this.$emit('toggle-route-visibility', route)
// 线
const routeIndex = this.expandedRoutes.indexOf(route.id)
if (routeIndex > -1) {
this.expandedRoutes.splice(routeIndex, 1)
}
},
getRouteClasses(routeId) {
@ -498,14 +443,6 @@ export default {
const e = this.routeLockedBy[routeId]
return (e && (e.nickName || e.userName)) || ''
},
handleOpenWaypointDialog(point,index,total) {
this.$emit('open-waypoint-dialog', {
...point,
currentIndex: index,
totalPoints: total
});
},
handleOpenPlatformDialog(platform) {
this.$emit('open-platform-dialog', platform)
},
@ -685,10 +622,6 @@ export default {
background: rgba(255, 255, 255, 0.8) !important;
}
.tree-item.waypoint-item .tree-item-header {
background: rgba(224, 238, 255, 0.8);
}
.tree-item.active .tree-item-header {
background: rgba(0, 138, 255, 0.15) !important;
border-color: rgba(0, 138, 255, 0.3);
@ -785,10 +718,6 @@ export default {
margin-left: 25px;
}
.waypoint-children {
margin-left: 50px;
}
.action-buttons {
display: flex;
gap: 10px;

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

@ -5812,45 +5812,37 @@ export default {
/** 切换航线:实现多选/开关逻辑 */
async selectRoute(route) {
const index = this.activeRouteIds.indexOf(route.id);
const isRouteExpanded = this.$refs.rightPanel ? this.$refs.rightPanel.expandedRoutes.includes(route.id) : false;
// 线
// 线线
if (index > -1) {
if (isRouteExpanded) {
return;
} else {
// 线
this.activeRouteIds.splice(index, 1);
if (this.$refs.cesiumMap) {
this.$refs.cesiumMap.removeRouteById(route.id);
// 线
this.$refs.cesiumMap.removeDetectionZoneByRouteId(route.id);
this.$refs.cesiumMap.removePowerZoneByRouteId(route.id);
}
if (this.selectedRouteDetails && this.selectedRouteDetails.id === route.id) {
if (this.activeRouteIds.length > 0) {
const lastId = this.activeRouteIds[this.activeRouteIds.length - 1];
try {
const res = await getRoutes(lastId);
if (res.code === 200 && res.data) {
this.selectedRouteId = res.data.id;
this.selectedRouteDetails = {
id: res.data.id,
name: res.data.callSign,
waypoints: res.data.waypoints || []
};
}
} catch (e) {
console.error("回显剩余航线失败", e);
this.activeRouteIds.splice(index, 1);
if (this.$refs.cesiumMap) {
this.$refs.cesiumMap.removeRouteById(route.id);
this.$refs.cesiumMap.removeDetectionZoneByRouteId(route.id);
this.$refs.cesiumMap.removePowerZoneByRouteId(route.id);
}
if (this.selectedRouteDetails && this.selectedRouteDetails.id === route.id) {
if (this.activeRouteIds.length > 0) {
const lastId = this.activeRouteIds[this.activeRouteIds.length - 1];
try {
const res = await getRoutes(lastId);
if (res.code === 200 && res.data) {
this.selectedRouteId = res.data.id;
this.selectedRouteDetails = {
id: res.data.id,
name: res.data.callSign,
waypoints: res.data.waypoints || []
};
}
} else {
this.selectedRouteId = null;
this.selectedRouteDetails = null;
} catch (e) {
console.error("回显剩余航线失败", e);
}
} else {
this.selectedRouteId = null;
this.selectedRouteDetails = null;
}
// 线
this.$message.info(`已取消航线: ${route.name}`);
return;
}
this.$message.info(`已取消航线: ${route.name}`);
return;
}
// 线线

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

@ -8,9 +8,26 @@
</div>
<div class="dialog-body-inner">
<div class="route-edit-tab-bar">
<button type="button" class="tab-bar-item" :class="{ active: activeTab === 'basic' }" @click="activeTab = 'basic'">基础</button>
<button type="button" class="tab-bar-item" :class="{ active: activeTab === 'platform' }" @click="activeTab = 'platform'">平台</button>
<button type="button" class="tab-bar-item" :class="{ active: activeTab === 'waypoints' }" @click="activeTab = 'waypoints'">航点</button>
<div class="tab-bar-tabs">
<button type="button" class="tab-bar-item" :class="{ active: activeTab === 'basic' }" @click="activeTab = 'basic'">基础</button>
<button type="button" class="tab-bar-item" :class="{ active: activeTab === 'platform' }" @click="activeTab = 'platform'">平台</button>
<button type="button" class="tab-bar-item" :class="{ active: activeTab === 'waypoints' }" @click="activeTab = 'waypoints'">航点</button>
</div>
<div class="tab-bar-actions">
<template v-if="activeTab === 'basic' || activeTab === 'platform'">
<el-button size="mini" @click="visible = false"> </el-button>
<el-button type="primary" size="mini" class="blue-btn" @click="handleSave"> </el-button>
</template>
<template v-else-if="activeTab === 'waypoints' && waypointsTableData.length">
<template v-if="!waypointsEditMode">
<el-button type="primary" size="mini" class="blue-btn" @click="waypointsEditMode = true"> </el-button>
</template>
<template v-else>
<el-button size="mini" @click="cancelWaypointsEdit"> </el-button>
<el-button type="primary" size="mini" class="blue-btn" @click="confirmWaypointsEdit"> </el-button>
</template>
</template>
</div>
</div>
<div v-show="activeTab === 'basic'" class="tab-pane-wrap">
<div class="tab-pane-body basic-tab-content">
@ -195,15 +212,6 @@
<div class="tab-pane-body waypoints-tab-content">
<div v-if="!waypointsTableData.length" class="empty-tip">该航线暂无航点数据</div>
<template v-else>
<div class="waypoints-table-actions">
<template v-if="!waypointsEditMode">
<el-button type="primary" size="mini" class="blue-btn" @click="waypointsEditMode = true"> </el-button>
</template>
<template v-else>
<el-button type="primary" size="mini" class="blue-btn" @click="confirmWaypointsEdit"> </el-button>
<el-button size="mini" @click="cancelWaypointsEdit"> </el-button>
</template>
</div>
<div class="waypoints-table-wrap">
<el-table :data="waypointsTableData" border size="small" max-height="340" class="waypoints-table">
<el-table-column type="index" label="序号" width="52" align="center" />
@ -311,11 +319,6 @@
</template>
</div>
</div>
<div class="dialog-footer">
<el-button size="mini" @click="visible = false"> </el-button>
<el-button type="primary" size="mini" class="blue-btn" @click="handleSave"> </el-button>
</div>
</div>
<div class="resize-handle" @mousedown="onResizeStart" title="拖动调整大小"></div>
</div>
@ -445,6 +448,7 @@ export default {
activeTab(val) {
if (val === 'platform' && this.visible) this.loadPlatforms()
if (val === 'waypoints' && this.panelWidth < 920) this.panelWidth = 920
if (val !== 'waypoints') this.waypointsEditMode = false
}
},
methods: {
@ -707,7 +711,7 @@ export default {
},
confirmWaypointsEdit() {
this.waypointsEditMode = false
this.$message.success('表格已保存,点击下方「确定」提交航线与航点')
this.$message.success('航点表格已保存,请切换到「基础」或「平台」后点击「确定」提交航线')
},
cancelWaypointsEdit() {
this.syncWaypointsTableData(this.route.waypoints || [])
@ -863,11 +867,6 @@ export default {
flex-direction: column;
min-height: 0;
}
.route-edit-dialog-wrap .dialog-footer {
padding: 10px 0 0;
margin-top: 8px;
border-top: 1px solid #ebeef5;
}
.route-edit-dialog-wrap .resize-handle {
position: absolute;
right: 0;
@ -886,11 +885,31 @@ export default {
<style scoped>
.route-edit-tab-bar {
display: flex;
gap: 24px;
align-items: flex-end;
justify-content: space-between;
gap: 16px;
margin-bottom: 0;
padding-bottom: 12px;
border-bottom: 1px solid #e4e7ed;
}
.tab-bar-tabs {
display: flex;
gap: 24px;
align-items: flex-end;
flex: 1;
min-width: 0;
}
.tab-bar-actions {
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
padding-bottom: 2px;
}
/* 标签栏操作区:仅胶囊形圆角,不改颜色与其它样式 */
.tab-bar-actions ::v-deep .el-button {
border-radius: 999px;
}
.tab-bar-item {
padding: 0;
border: none;
@ -1162,12 +1181,6 @@ export default {
padding: 0 16px;
background: #fff;
}
.waypoints-table-actions {
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.waypoints-table-wrap {
background: #fff;
border-radius: 8px;

Loading…
Cancel
Save