diff --git a/ruoyi-ui/src/views/childRoom/RightPanel.vue b/ruoyi-ui/src/views/childRoom/RightPanel.vue index fe63cf0..d035038 100644 --- a/ruoyi-ui/src/views/childRoom/RightPanel.vue +++ b/ruoyi-ui/src/views/childRoom/RightPanel.vue @@ -26,98 +26,79 @@ 新建方案 -
+
+
- -
-
{{ plan.name }}
-
{{ plan.routes.length }}个航线
-
-
- -
-
-
-
- -
-
-
航线列表
- - 新建航线 - -
- -
-
- -
-
{{ route.name }}
-
{{ route.points }}个航点
-
- - 冲突 - -
- -
-
-
-
- -
-
航点列表
-
-
- -
-
{{ point.name }}
-
高度: {{ point.altitude }}m | 速度: {{ point.speed }}
+
+ +
+
{{ plan.name }}
+
{{ routes.filter(r => r.scenarioId === plan.id).length }}个航线
+
+
+ + + +
-
- - + +
+
+
+ +
+
{{ route.name }}
+
{{ route.points }}个航点
+
+ + 冲突 + +
+ + + +
+
+ +
+
+
+ +
+
{{ point.name }}
+
高度: {{ point.altitude }}m | 速度: {{ point.speed }}
+
+
+ +
+
+
+
+
- -
- - 添加航点 - - - 取消 - -
-
-
@@ -187,7 +167,6 @@
-
-
-1) { + // 折叠方案时,取消选中该方案的所有航线 + this.expandedPlans.splice(index, 1) + const planRoutes = this.routes.filter(r => r.scenarioId === planId) + planRoutes.forEach(route => { + if (this.activeRouteIds.includes(route.id)) { + // 触发航线隐藏 + this.handleToggleRouteVisibility(route) + } + }) + // 折叠方案时,取消选中方案 + this.$emit('select-plan', { id: null }) + } else { + // 展开方案时,选中该方案 + this.expandedPlans.push(planId) + const plan = this.plans.find(p => p.id === planId) + if (plan) { + this.$emit('select-plan', plan) + } + // 选中该方案的所有航线 + const planRoutes = this.routes.filter(r => r.scenarioId === planId) + planRoutes.forEach(route => { + if (!this.activeRouteIds.includes(route.id)) { + this.handleSelectRoute(route) + } + }) + } + }, + + // 切换航线展开/折叠 + toggleRoute(routeId) { + const route = this.routes.find(r => r.id === routeId) + if (!route) return + + 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) + } + } else { + // 航线未选中,点击则选中并显示航线和航点 + this.handleSelectRoute(route) + // 选中后自动展开航点 + this.$nextTick(() => { + if (!this.expandedRoutes.includes(routeId)) { + this.expandedRoutes.push(routeId) + } + }) + } + }, + handleHide() { this.$emit('hide') }, @@ -314,6 +364,7 @@ export default { }, handleSelectRoute(route) { + // 确保航线有航点数据 this.$emit('select-route', route) }, @@ -325,6 +376,14 @@ export default { this.$emit('create-route') }, + handleCreateRouteForPlan(plan) { + this.$emit('create-route', plan) + }, + + handleDeletePlan(plan) { + // 暂时留空,后续实现 + }, + handleOpenPlanDialog(plan) { this.$emit('open-plan-dialog', plan) }, @@ -333,16 +392,27 @@ export default { this.$emit('open-route-dialog', route) }, - handleOpenWaypointDialog(point) { - this.$emit('open-waypoint-dialog', point) + handleToggleRouteVisibility(route) { + this.$emit('toggle-route-visibility', route) + // 当隐藏航线时,自动收回航点列表 + const routeIndex = this.expandedRoutes.indexOf(route.id) + if (routeIndex > -1) { + this.expandedRoutes.splice(routeIndex, 1) + } }, - handleAddWaypoint() { - this.$emit('add-waypoint') + getRouteClasses(routeId) { + return { + active: this.activeRouteIds.includes(routeId) + } }, - handleCancelRoute() { - this.$emit('cancel-route') + handleDeleteRoute(route) { + // 暂时留空,后续实现 + }, + + handleOpenWaypointDialog(point) { + this.$emit('open-waypoint-dialog', point) }, handleViewConflict(conflict) { @@ -466,115 +536,90 @@ export default { opacity: 0.9; } -.route-list { +.tree-list { display: flex; flex-direction: column; gap: 8px; } -.route-item { +.tree-item { + border-radius: 6px; + transition: all 0.3s; + border: 1px solid rgba(0, 138, 255, 0.1); +} + +.tree-item-header { display: flex; align-items: center; gap: 10px; padding: 10px; background: rgba(255, 255, 255, 0.8); - border-radius: 6px; cursor: pointer; transition: all 0.3s; - border: 1px solid rgba(0, 138, 255, 0.1); - position: relative; + border-radius: 6px; } -.route-item:hover { +.tree-item-header:hover { background: rgba(0, 138, 255, 0.1); transform: translateX(-2px); box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15); } -.route-item.active { - background: rgba(0, 138, 255, 0.15); - border-color: rgba(0, 138, 255, 0.3); - box-shadow: 0 2px 10px rgba(0, 138, 255, 0.25); -} - -.route-info { - flex: 1; -} - -.route-name { - font-size: 14px; - font-weight: 500; - color: #333; -} - -.route-meta { - font-size: 12px; - color: #999; +.tree-item.plan-item .tree-item-header { + background: rgba(255, 255, 255, 0.9) !important; } -.route-actions { - display: flex; - gap: 8px; +.tree-item.route-item .tree-item-header { + background: rgba(255, 255, 255, 0.8) !important; } -.route-actions i { - cursor: pointer; - color: #008aff; - font-size: 14px; - padding: 4px; - border-radius: 4px; - transition: all 0.2s; +.tree-item.route-item:not(.active) .tree-item-header { + background: rgba(255, 255, 255, 0.8) !important; } -.route-actions i:hover { - background: rgba(0, 138, 255, 0.1); - transform: scale(1.2); +.tree-item.waypoint-item .tree-item-header { + background: rgba(224, 238, 255, 0.8); } -.waypoint-list { - display: flex; - flex-direction: column; - gap: 8px; +.tree-item.active .tree-item-header { + background: rgba(0, 138, 255, 0.15) !important; + border-color: rgba(0, 138, 255, 0.3); + box-shadow: 0 2px 10px rgba(0, 138, 255, 0.25); } -.waypoint-item { - display: flex; - align-items: center; - gap: 10px; - padding: 10px; - background: rgba(255, 255, 255, 0.8); - border-radius: 6px; - transition: all 0.3s; - border: 1px solid rgba(0, 138, 255, 0.1); +.tree-item.selected .tree-item-header { + background: rgba(0, 138, 255, 0.1) !important; + border-color: rgba(0, 138, 255, 0.2); } -.waypoint-item:hover { - background: rgba(0, 138, 255, 0.1); - transform: translateX(-2px); - box-shadow: 0 2px 8px rgba(0, 138, 255, 0.15); +.tree-icon { + font-size: 16px; + color: #008aff; + flex-shrink: 0; } -.waypoint-info { +.tree-item-info { flex: 1; } -.waypoint-name { +.tree-item-name { font-size: 14px; font-weight: 500; color: #333; } -.waypoint-meta { +.tree-item-meta { font-size: 12px; color: #999; } -.waypoint-actions { +.tree-item-actions { display: flex; gap: 8px; + flex-shrink: 0; } -.waypoint-actions i { +.tree-item-actions i { cursor: pointer; color: #008aff; font-size: 14px; @@ -583,11 +628,27 @@ export default { transition: all 0.2s; } -.waypoint-actions i:hover { +.tree-item-actions i:hover { background: rgba(0, 138, 255, 0.1); transform: scale(1.2); } +.tree-children { + margin-left: 20px; + margin-top: 4px; + display: flex; + flex-direction: column; + gap: 4px; +} + +.route-children { + margin-left: 25px; +} + +.waypoint-children { + margin-left: 50px; +} + .action-buttons { display: flex; gap: 10px; diff --git a/ruoyi-ui/src/views/childRoom/index.vue b/ruoyi-ui/src/views/childRoom/index.vue index eaf2c72..72a0ef6 100644 --- a/ruoyi-ui/src/views/childRoom/index.vue +++ b/ruoyi-ui/src/views/childRoom/index.vue @@ -106,6 +106,7 @@ ({ @@ -1139,56 +1147,92 @@ export default { const minutes = (val % 4) * 15; return `K+${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:00`; }, + + createPlan() { + this.$message.success('创建方案'); + }, + + openPlanDialog(plan) { + this.$message.success('打开方案编辑对话框'); + }, + selectPlan(plan) { - this.selectedPlanId = plan.id; - this.selectedPlanDetails = plan; + if (plan && plan.id) { + this.selectedPlanId = plan.id; + this.selectedPlanDetails = plan; + } else { + this.selectedPlanId = null; + this.selectedPlanDetails = null; + } this.selectedRouteId = null; this.selectedRouteDetails = null; }, - /** 切换航线:实现多选/开关逻辑 */ + /** 切换航线:实现复杂的交互逻辑 */ 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) { - this.activeRouteIds.splice(index, 1); - if (this.$refs.cesiumMap) { - this.$refs.cesiumMap.removeRouteById(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.selectedRouteDetails = { - id: res.data.id, - name: res.data.callSign, - waypoints: res.data.waypoints || [] - }; + if (isRouteExpanded) { + // 航线已展开,点击则收回航点(不取消选中) + // 这个逻辑在 RightPanel 的 toggleRoute 中处理 + return; + } else { + // 航线未展开,点击则取消选中(从地图移除) + this.activeRouteIds.splice(index, 1); + if (this.$refs.cesiumMap) { + this.$refs.cesiumMap.removeRouteById(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); } - } catch (e) { - console.error("回显剩余航线失败", e); + } else { + this.selectedRouteId = null; + this.selectedRouteDetails = null; } - } else { - this.selectedRouteDetails = null; } + this.$message.info(`已取消航线: ${route.name}`); + return; } - this.$message.info(`已移除航线: ${route.name}`); - return; } - // 航线未被选中 + + // 航线未被选中,点击则选中并显示航线和航点 try { const response = await getRoutes(route.id); if (response.code === 200 && response.data) { const fullRouteData = response.data; const waypoints = fullRouteData.waypoints || []; this.activeRouteIds.push(route.id); - this.selectedRouteDetails = { - id: fullRouteData.id, - name: fullRouteData.callSign, - waypoints: waypoints - }; + this.selectedRouteId = fullRouteData.id; + this.selectedRouteDetails = { + id: fullRouteData.id, + name: fullRouteData.callSign, + waypoints: waypoints + }; + + // 更新 routes 数组中对应航线的 waypoints 字段 + const routeIndex = this.routes.findIndex(r => r.id === route.id); + if (routeIndex > -1) { + this.$set(this.routes, routeIndex, { + ...this.routes[routeIndex], + waypoints: waypoints + }); + } + if (waypoints.length > 0) { // 通知地图渲染 if (this.$refs.cesiumMap) { @@ -1229,6 +1273,44 @@ export default { this.$message.info('已清空所有选中航线'); }, + // 切换航线显示/隐藏 + toggleRouteVisibility(route) { + const index = this.activeRouteIds.indexOf(route.id); + + if (index > -1) { + // 航线已显示,隐藏它 + // 使用过滤创建新数组,确保 Vue 能够检测到变化 + this.activeRouteIds = this.activeRouteIds.filter(id => id !== route.id); + if (this.$refs.cesiumMap) { + this.$refs.cesiumMap.removeRouteById(route.id); + } + if (this.selectedRouteDetails && this.selectedRouteDetails.id === route.id) { + if (this.activeRouteIds.length > 0) { + const lastId = this.activeRouteIds[this.activeRouteIds.length - 1]; + getRoutes(lastId).then(res => { + 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); + }); + } else { + this.selectedRouteId = null; + this.selectedRouteDetails = null; + } + } + this.$message.info(`已隐藏航线: ${route.name}`); + } else { + // 航线已隐藏,显示它 + this.selectRoute(route); + } + }, + // 冲突操作 runConflictCheck() { this.conflictCount = 2;