diff --git a/ruoyi-ui/src/views/cesiumMap/index.vue b/ruoyi-ui/src/views/cesiumMap/index.vue index 30e2a09..7ce9d22 100644 --- a/ruoyi-ui/src/views/cesiumMap/index.vue +++ b/ruoyi-ui/src/views/cesiumMap/index.vue @@ -1002,31 +1002,34 @@ export default { return entity }, addCircleEntity(center, radius) { - this.entityCounter++ - const id = `circle_${this.entityCounter}` + // 确保半径有效 + const validRadius = Math.max(radius, 1) + + this.entityCounter++ + const id = `circle_${this.entityCounter}` - const entity = this.viewer.entities.add({ - id: id, - name: `圆形 ${this.entityCounter}`, - position: center, // 圆心位置 - - // 【优化】使用 ellipse (椭圆) 绘制圆形 - ellipse: { - semiMinorAxis: radius, // 半短轴 = 半径 - semiMajorAxis: radius, // 半长轴 = 半径 - material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color) - .withAlpha(this.defaultStyles.circle.opacity), - outline: true, - outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color), - outlineWidth: this.defaultStyles.circle.width - } - }) + const entity = this.viewer.entities.add({ + id: id, + name: `圆形 ${this.entityCounter}`, + position: center, // 圆心位置 - // 【重要修改】直接把 entity 推入数组 - this.allEntities.push(entity) + // 【优化】使用 ellipse (椭圆) 绘制圆形 + ellipse: { + semiMinorAxis: validRadius, // 半短轴 = 半径 + semiMajorAxis: validRadius, // 半长轴 = 半径 + material: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color) + .withAlpha(this.defaultStyles.circle.opacity), + outline: true, + outlineColor: Cesium.Color.fromCssColorString(this.defaultStyles.circle.color), + outlineWidth: this.defaultStyles.circle.width + } + }) - return entity -}, + // 【重要修改】直接把 entity 推入数组 + this.allEntities.push(entity) + + return entity + }, // ================== 工具方法 ================== @@ -1418,11 +1421,17 @@ export default { break case 'circle': + // 检查半径是否有效 + const radius = entityData.data.radius || 1000 + if (radius <= 0) { + this.$message.error('圆形半径必须大于0') + return + } entity = this.viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(entityData.data.center.lng, entityData.data.center.lat), ellipse: { - semiMinorAxis: entityData.data.radius, - semiMajorAxis: entityData.data.radius, + semiMinorAxis: radius, + semiMajorAxis: radius, material: Cesium.Color.fromCssColorString(color).withAlpha(0.5), outline: true, outlineColor: Cesium.Color.fromCssColorString(color), diff --git a/ruoyi-ui/src/views/childRoom/BottomLeftPanel.vue b/ruoyi-ui/src/views/childRoom/BottomLeftPanel.vue index 177a63a..57bae6e 100644 --- a/ruoyi-ui/src/views/childRoom/BottomLeftPanel.vue +++ b/ruoyi-ui/src/views/childRoom/BottomLeftPanel.vue @@ -31,7 +31,7 @@

时间线

-
+
{{ item.time }}
@@ -78,11 +78,11 @@ export default { dialogTitle: '', activeTab: '', timelineData: [ - { time: 'K-02:00', event: '任务准备阶段' }, - { time: 'K-01:00', event: '资源调配' }, - { time: 'K时', event: '任务执行' }, - { time: 'K+01:00', event: '任务监控' }, - { time: 'K+02:00', event: '任务完成' } + { time: 'K-02:00', event: '任务准备阶段', current: false }, + { time: 'K-01:00', event: '资源调配', current: false }, + { time: 'K时', event: '任务执行', current: true }, + { time: 'K+01:00', event: '任务监控', current: false }, + { time: 'K+02:00', event: '任务完成', current: false } ], progressData: [ { label: '任务准备', percentage: 100, status: 'success' }, @@ -233,6 +233,43 @@ export default { position: relative; } +.timeline-item.current { + background: rgba(64, 158, 255, 0.1); + border-radius: 6px; + padding: 8px; +} + +.timeline-item.current .timeline-dot { + background: #ff6600; + box-shadow: 0 0 0 4px rgba(255, 102, 0, 0.3); + animation: pulse 2s infinite; +} + +.timeline-item.current .timeline-time { + color: #ff6600; + font-weight: 700; +} + +.timeline-item.current .timeline-event { + color: #333; + font-weight: 600; +} + +@keyframes pulse { + 0% { + transform: scale(1); + opacity: 1; + } + 50% { + transform: scale(1.2); + opacity: 0.7; + } + 100% { + transform: scale(1); + opacity: 1; + } +} + .timeline-item::before { content: ''; position: absolute; diff --git a/ruoyi-ui/src/views/childRoom/TopHeader.vue b/ruoyi-ui/src/views/childRoom/TopHeader.vue new file mode 100644 index 0000000..870d0ad --- /dev/null +++ b/ruoyi-ui/src/views/childRoom/TopHeader.vue @@ -0,0 +1,768 @@ + + + + + diff --git a/ruoyi-ui/src/views/childRoom/index.vue b/ruoyi-ui/src/views/childRoom/index.vue index 5334101..684bbb5 100644 --- a/ruoyi-ui/src/views/childRoom/index.vue +++ b/ruoyi-ui/src/views/childRoom/index.vue @@ -2,13 +2,7 @@
-
+
@@ -16,85 +10,6 @@

二维GIS地图区域

支持标绘/航线/空域/实时态势

-
- - 正在绘制: {{ pendingRoute.name }} - | - 已添加航点: {{ pendingRoute.points.length }} - 左键点击添加航点,右键结束 -
- - - - - - - - - - - - 取 消 - 开始绘制 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 取消该点 - 确 定 - - - - - - - -
- -
-
-
- - 网络化任务规划系统 -
- - -
-
- - {{ item.name }} - - - - - - 新建计划 - 打开 - 保存 - - - - 导入 - - - - 导入计划 - 导入ACD - 导入ATO - 导入图层 - 导入航线 - - - - - 导出 - - - - - - - - 航线编辑 - 军事标绘 - 图标编辑 - 属性修改 - - - - 推演编辑 - - - - 时间设置 - 机型设置 - 关键事件编辑 - 导弹发射 - - - - - - - - - - - 2D/3D切换 - 显示/隐藏标尺 - 网格 - 比例尺 - 指北针 - - - - - - - - 加载/切换地形 - 投影 - 航空图 - - - - - - - - 航线计算 - 冲突显示 - 数据资料 - 坐标换算 - - - - - - - - 设置 - 系统说明 - - - - - - - - 图层收藏 - 航线收藏 - - -
-
-
- -
- -
- -
- -
-
房间编号
-
{{ roomCode }}
-
-
- - -
- -
-
在线人数
-
{{ onlineCount }}人
-
-
- - -
- -
-
作战时间
-
{{ combatTime }}
-
-
- - -
- -
-
天文时间
-
{{ astroTime }}
-
-
-
- - -
- - -
-
-
+ + - - - - - - - - - - - - 取 消 - 开始绘制 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 取消该点 - 确 定 - -
@@ -508,9 +200,10 @@ import OnlineMembersDialog from '@/views/dialogs/OnlineMembersDialog' import PlatformEditDialog from '@/views/dialogs/PlatformEditDialog' import RouteEditDialog from '@/views/dialogs/RouteEditDialog' import WaypointEditDialog from '@/views/dialogs/WaypointEditDialog' -import LeftMenu from './LeftMenu.vue' +import LeftMenu from './LeftMenu' import RightPanel from './RightPanel' import BottomLeftPanel from './BottomLeftPanel' +import TopHeader from './TopHeader' export default { name: 'MissionPlanningView', components: { @@ -521,7 +214,8 @@ export default { WaypointEditDialog, LeftMenu, RightPanel, - BottomLeftPanel + BottomLeftPanel, + TopHeader }, data() { return { @@ -535,47 +229,6 @@ export default { selectedRoute: null, showWaypointDialog: false, selectedWaypoint: null, - //航线绘制相关数据 - isDrawing: false, // 是否处于地图绘制模式 - showCreateRouteDialog: false, // 是否显示"新建航线"弹窗 - showWaypointDialog: false, // 是否显示"航点信息"弹窗 - - // 暂存正在创建的航线对象 - pendingRoute: { - id: null, - name: '', - startTime: '', - points: [] - }, - // 暂存当前点击地图生成的临时航点坐标 - tempClickPosition: null, - - // 航点表单数据 - waypointForm: { - name: '', - altitude: 0, - speed: 0, - time: '', - radius: 0 - }, - - // 航点表单校验规则(可选) - waypointRules: { - name: [{ required: true, message: '请输入名称', trigger: 'blur' }], - altitude: [{ required: true, message: '请输入高度', trigger: 'blur' }] - }, - // 顶部导航 - activeTopNav: 'file', - topNavItems: [ - { id: 'file', name: '文件', icon: 'el-icon-document' }, - { id: 'edit', name: '编辑', icon: 'el-icon-edit' }, - { id: 'view', name: '视图', icon: 'el-icon-view' }, - { id: 'map', name: '地图', icon: 'el-icon-map-location' }, - { id: 'airspace', name: '空域', icon: 'el-icon-s-grid' }, - { id: 'tools', name: '工具', icon: 'el-icon-setting' }, - { id: 'options', name: '选项', icon: 'el-icon-s-tools' }, - { id: 'favorites', name: '收藏', icon: 'el-icon-star-on' } - ], // 作战信息 roomCode: 'JTF-7-ALPHA', @@ -586,8 +239,6 @@ export default { // 左侧菜单栏 isMenuHidden: true, // 是否完全隐藏左侧菜单 activeMenu: 'file', - hoverMenu: '', - showMenuTooltip: false, // 右侧面板控制 isRightPanelHidden: true, // 是否完全隐藏右侧面板 @@ -595,6 +246,11 @@ export default { // K时弹出框控制 showKTimePopup: false, + // 显示/隐藏控制 + showAirport: true, + showLandmark: true, + showRoute: true, + menuItems: [ { id: 'file', name: '方案', icon: 'el-icon-s-operation' }, { id: 'start', name: '冲突', icon: 'el-icon-warning-outline' }, @@ -691,85 +347,6 @@ export default { } }, methods: { -// 添加新航线 - addRoute() { - this.pendingRoute = { - id: Date.now(), // 生成唯一ID - name: '新建计划航线', - startTime: '', - points: [] - }; - this.showCreateRouteDialog = true; - }, - // 2. 确认航线基本信息,进入“绘图模式” - confirmCreateRoute() { - if (!this.pendingRoute.name) { - this.$message.warning('请输入航线名称'); - return; - } - this.showCreateRouteDialog = false; - this.isDrawing = true; - this.$message.info('进入绘制模式:左键点击地图添加航点,右键结束绘制'); - }, - // 3. 【核心】地图点击事件处理 - // 注意:这个方法需要绑定到地图容器的 @click 上,或者在你的 cesiumMap 组件回调里调用 - handleMapClick(event) { - if (!this.isDrawing) return; - - // 模拟获取点击的经纬度,实际项目中请从 cesium 事件中获取 - // const position = event.position || { lat: 30, lng: 120 }; - - // 暂存位置,打开航点录入弹窗 - // this.tempClickPosition = position; - - // 重置表单,自动生成默认值 - const nextIndex = this.pendingRoute.points.length + 1; - this.waypointForm = { - name: `WP-${nextIndex}`, - altitude: 5000, - speed: 800, - time: '', - radius: 5 - }; - - this.showWaypointDialog = true; - }, - // 4. 确认添加一个航点 - confirmWaypoint() { - // 将表单数据和位置信息合并 - const newPoint = { - ...this.waypointForm, - // ...this.tempClickPosition // 这里存入真实的经纬度 - }; - - this.pendingRoute.points.push(newPoint); - this.showWaypointDialog = false; - this.$message.success(`已添加第 ${this.pendingRoute.points.length} 个航点`); - }, - // 5. 右键结束绘制 - finishDrawing() { - if (!this.isDrawing) return; - - if (this.pendingRoute.points.length < 2) { - this.$message.warning('航线至少需要2个航点'); - return; - } - - // 构造最终数据格式,推入主数组 - const finalRoute = { - id: this.pendingRoute.id, - name: this.pendingRoute.name, - points: this.pendingRoute.points.length, // 显示航点数量 - conflict: false, - detailData: this.pendingRoute // 保存完整数据以便后续使用 - }; - - this.routes.push(finalRoute); - this.isDrawing = false; - this.selectRoute(finalRoute); // 选中新航线 - this.$message.success('航线绘制完成!'); - }, - // 显示在线成员弹窗 showOnlineMembersDialog() { this.showOnlineMembers = true; @@ -845,27 +422,10 @@ export default { }, // 文件下拉菜单方法 - newPlan() { - this.$message.success('新建计划'); - // 这里可以添加新建计划的逻辑 - }, - - openPlan() { - this.$message.success('打开计划'); - // 这里可以添加打开计划的逻辑 - }, - savePlan() { this.$message.success('保存计划'); - // 这里可以添加保存计划的逻辑 - }, - - importPlan() { - this.$message.success('导入计划'); - // 这里可以添加导入计划的逻辑 }, - // 导入二级菜单方法 importPlanFile() { this.$message.success('导入计划'); // 这里可以添加导入计划文件的逻辑 @@ -914,15 +474,8 @@ export default { attributeEdit() { this.$message.success('属性修改'); - // 这里可以添加属性修改的逻辑 - }, - - deductionEdit() { - this.$message.success('推演编辑'); - // 这里可以添加推演编辑的逻辑 }, - // 推演编辑二级菜单方法 timeSettings() { this.$message.success('时间设置'); // 这里可以添加时间设置的逻辑 @@ -964,11 +517,6 @@ export default { // 这里可以添加比例尺显示/隐藏的逻辑 }, - toggleCompass() { - this.$message.success('显示/隐藏指北针'); - // 这里可以添加指北针显示/隐藏的逻辑 - }, - // 地图下拉菜单方法 loadTerrain() { this.$message.success('加载/切换地形'); @@ -982,7 +530,15 @@ export default { loadAeroChart() { this.$message.success('航空图'); - // 这里可以添加航空图加载的逻辑 + }, + + // 空域下拉菜单方法 + powerZone() { + this.$message.success('威力区'); + }, + + threatZone() { + this.$message.success('威胁区'); }, // 工具下拉菜单方法 @@ -1007,9 +563,31 @@ export default { }, // 选项下拉菜单方法 - settings() { - this.$message.success('设置'); - // 这里可以添加系统设置的逻辑 + pageLayout() { + this.$message.success('页面布局'); + }, + + dataStoragePath() { + this.$message.success('数据存储路径'); + }, + + externalParams() { + this.$message.success('外部参数'); + }, + + toggleAirport() { + this.showAirport = !this.showAirport; + this.$message.success(this.showAirport ? '显示机场' : '隐藏机场'); + }, + + toggleLandmark() { + this.showLandmark = !this.showLandmark; + this.$message.success(this.showLandmark ? '显示地标' : '隐藏地标'); + }, + + toggleRoute() { + this.showRoute = !this.showRoute; + this.$message.success(this.showRoute ? '显示航线' : '隐藏航线'); }, systemDescription() { @@ -1025,7 +603,6 @@ export default { routeFavorites() { this.$message.success('航线收藏'); - // 这里可以添加航线收藏的逻辑 }, hideRightPanel() { @@ -1080,19 +657,6 @@ export default { } }, - showTooltip(item) { - this.hoverMenu = item.id; - }, - - hideTooltip() { - this.hoverMenu = ''; - }, - - getMenuName(id) { - const menu = this.menuItems.find(item => item.id === id); - return menu ? menu.name : ''; - }, - // K时弹出框操作 hideKTimePopup() { this.showKTimePopup = false; @@ -1402,929 +966,6 @@ background: url('~@/assets/map-background.png'); color: #008aff; } -/* 顶部导航栏 - 最终优化设计 */ -.floating-header { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 60px; - padding: 0 20px; - display: flex; - align-items: center; - justify-content: space-between; - z-index: 100; - backdrop-filter: blur(15px); - background: rgba(255, 255, 255, 0.85); - border-bottom: 1px solid rgba(0, 138, 255, 0.2); - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); -} - -.header-left { - display: flex; - align-items: center; - gap: 25px; - flex: 1; -} - -.system-title { - display: flex; - align-items: center; - font-size: 18px; - font-weight: bold; - min-width: 180px; -} - -.system-title i { - font-size: 24px; - color: #008aff; -} - -.blue-title { - color: #008aff !important; -} - -/* 顶部导航菜单 - 优化为简洁文字效果 */ -.top-nav-menu { - display: flex; - gap: 0; - flex: 1; - overflow-x: auto; - max-width: 800px; - padding: 5px 0; - scrollbar-width: thin; -} - -.top-nav-menu::-webkit-scrollbar { - height: 3px; -} - -.top-nav-menu::-webkit-scrollbar-track { - background: rgba(0, 138, 255, 0.1); - border-radius: 2px; -} - -.top-nav-menu::-webkit-scrollbar-thumb { - background: rgba(0, 138, 255, 0.3); - border-radius: 2px; -} - -.top-nav-item { - display: flex; - align-items: center; - gap: 6px; - padding: 8px 12px; - cursor: pointer; - font-size: 13px; - font-weight: 600; - color: #333; - transition: all 0.3s; - border-radius: 4px; - white-space: nowrap; - min-width: 60px; - justify-content: center; - margin: 0 1px; - position: relative; - flex-shrink: 0; -} - -.top-nav-item:hover { - color: #008aff; -} - -.top-nav-item.active { - color: #008aff; - font-weight: 700; -} - -/* 移除了蓝色指示条 */ -.top-nav-item.active::after { - display: none; -} - -.nav-icon { - font-size: 14px; - color: #333; - transition: all 0.3s; -} - -.top-nav-item:hover .nav-icon, -.top-nav-item.active .nav-icon { - color: #008aff; -} - -.nav-text { - display: block; -} - -/* 右侧区域 */ -.header-right { - display: flex; - align-items: center; - gap: 15px; -} - -/* 作战信息组 */ -.combat-info-group { - display: flex; - gap: 12px; -} - -.info-box { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 10px; - border-radius: 6px; - transition: all 0.3s; - background: rgba(255, 255, 255, 0.7); - border: 1px solid rgba(0, 138, 255, 0.2); - box-shadow: 0 2px 6px rgba(0, 138, 255, 0.1); - min-width: 120px; -} - -.info-box:hover { - background: rgba(255, 255, 255, 0.9); - transform: translateY(-1px); - box-shadow: 0 4px 10px rgba(0, 138, 255, 0.2); - border-color: rgba(0, 138, 255, 0.3); -} - -.info-icon { - font-size: 16px; - color: #008aff; - min-width: 20px; - text-align: center; -} - -.info-content { - display: flex; - flex-direction: column; - flex: 1; -} - -.info-label { - font-size: 11px; - color: #666; - font-weight: 500; - margin-bottom: 2px; - white-space: nowrap; -} - -.info-value { - font-size: 13px; - font-weight: 700; - color: #333; - white-space: nowrap; - font-family: 'Courier New', monospace; - letter-spacing: 0.5px; -} - -/* 作战时间和天文时间的特殊样式 */ -.combat-info-group .info-box:nth-child(3) .info-value { - color: #008aff; -} - -.combat-info-group .info-box:nth-child(4) .info-value { - color: #52c41a; -} - -/* 用户状态区域 */ -.user-status-area { - display: flex; - align-items: center; -} - -.user-avatar { - border: 2px solid rgba(0, 138, 255, 0.3); - box-shadow: 0 2px 6px rgba(0, 138, 255, 0.15); - transition: all 0.3s; - background: rgba(255, 255, 255, 0.9); -} - -.user-avatar:hover { - transform: scale(1.1); - box-shadow: 0 4px 10px rgba(0, 138, 255, 0.25); - border-color: rgba(0, 138, 255, 0.6); -} - -/* 左侧菜单栏 - 蓝色主题 */ -.floating-left-menu { - position: absolute; - top: 70px; - left: 20px; - width: 40px; - background: rgba(255, 255, 255, 0.3); - backdrop-filter: blur(10px); - border: 1px solid rgba(0, 138, 255, 0.1); - border-radius: 8px; - z-index: 90; - box-shadow: 0 4px 12px rgba(0, 138, 255, 0.2); - padding: 15px 5px; - transition: all 0.3s ease; - overflow: hidden; - opacity: 1; - transform: translateX(0); -} - -.floating-left-menu.hidden { - opacity: 0; - transform: translateX(-100%); - pointer-events: none; -} - -.hide-btn { - position: absolute; - top: 15px; - left: 50%; - transform: translateX(-50%); - width: 24px; - height: 24px; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - color: #008aff; - font-size: 16px; - transition: all 0.3s; - background: rgba(255, 255, 255, 0.5); - border-radius: 4px; - z-index: 10; -} - -.hide-btn:hover { - color: #0066cc; - background: rgba(0, 138, 255, 0.1); - transform: scale(1.1); -} - -.menu-icons { - display: flex; - flex-direction: column; - gap: 10px; - margin-top: 30px; -} - -.menu-item { - display: flex; - justify-content: center; - align-items: center; - height: 40px; - cursor: pointer; - color: #555; - font-size: 20px; - position: relative; - transition: all 0.3s; - border-radius: 4px; - padding: 0 5px; - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(5px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} - -.menu-item:hover { - background: rgba(0, 138, 255, 0.1); - color: #008aff; - transform: translateY(-2px); - box-shadow: 0 4px 10px rgba(0, 138, 255, 0.2); -} - -.menu-item.active { - background: linear-gradient(135deg, rgba(0, 138, 255, 0.2), rgba(0, 138, 255, 0.3)); - color: #008aff; - box-shadow: 0 4px 12px rgba(0, 138, 255, 0.25); -} - -.menu-tooltip { - position: absolute; - left: 100%; - top: 50%; - transform: translateY(-50%); - background: linear-gradient(135deg, rgba(0, 138, 255, 0.95), rgba(0, 102, 204, 0.95)); - color: white; - padding: 8px 14px; - border-radius: 6px; - font-size: 12px; - white-space: nowrap; - z-index: 1000; - margin-left: 10px; - box-shadow: 0 4px 12px rgba(0, 138, 255, 0.3); - pointer-events: none; - backdrop-filter: blur(5px); -} - -.menu-tooltip-layer { - position: absolute; - top: 0; - left: 100%; - width: 200px; - height: 100%; - z-index: 999; - pointer-events: none; -} - -.tooltip-content { - position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - background: linear-gradient(135deg, rgba(0, 138, 255, 0.95), rgba(0, 102, 204, 0.95)); - color: white; - padding: 8px 14px; - border-radius: 6px; - font-size: 12px; - white-space: nowrap; - margin-left: 10px; - box-shadow: 0 4px 12px rgba(0, 138, 255, 0.3); - backdrop-filter: blur(5px); -} - -/* 右侧外部隐藏按钮 */ -.right-external-hide-btn { - position: absolute; - top: 70px; - right: 320px; /* 面板宽度300px + 外边距20px */ - width: 28px; - height: 40px; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - color: white; - font-size: 16px; - transition: all 0.3s; - background: rgba(0, 138, 255, 0.9); - border-radius: 8px 0 0 8px; - z-index: 91; - border: 1px solid rgba(0, 138, 255, 1); - border-right: none; - box-shadow: -2px 0 8px rgba(0, 138, 255, 0.3); - opacity: 1; - transform: translateX(0); -} - -.right-external-hide-btn:hover { - background: rgba(0, 138, 255, 1); - transform: translateX(-2px); - box-shadow: -4px 0 12px rgba(0, 138, 255, 0.5); -} - -.right-external-hide-btn.hidden { - opacity: 0; - pointer-events: none; - transform: translateX(20px); -} - -/* 右侧浮动面板 - 蓝色主题 */ -.floating-right-panel { - position: absolute; - top: 70px; - right: 20px; - width: 300px; - border-radius: 0 8px 8px 8px; - z-index: 90; - color: #333; - overflow: hidden; - box-shadow: 0 4px 20px rgba(0, 138, 255, 0.2); - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(15px); - transition: all 0.3s ease; - opacity: 1; - transform: translateX(0); -} - -.floating-right-panel.hidden { - opacity: 0; - transform: translateX(100%); - pointer-events: none; -} - -.right-tabs { - display: flex; - border-bottom: 1px solid rgba(0, 138, 255, 0.3); - background: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(5px); -} - -.right-tab-item { - flex: 1; - text-align: center; - padding: 12px 0; - cursor: pointer; - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - transition: all 0.3s; - position: relative; - border-bottom: 3px solid transparent; - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(5px); -} - -.right-tab-item i { - font-size: 18px; - color: #666; - transition: all 0.3s; -} - -.right-tab-item span { - font-size: 12px; - color: #666; - transition: all 0.3s; -} - -.right-tab-item:hover { - background: rgba(0, 138, 255, 0.1); - box-shadow: 0 2px 6px rgba(0, 138, 255, 0.15); -} - -.right-tab-item.active { - background: rgba(255, 255, 255, 0.95); - border-bottom: 3px solid rgba(0, 138, 255, 0.8); - box-shadow: 0 2px 8px rgba(0, 138, 255, 0.2); -} - -.right-tab-item.active i, -.right-tab-item.active span { - color: #008aff; - font-weight: 600; - text-shadow: 0 0 2px rgba(0, 138, 255, 0.3); -} - -.badge { - position: absolute; - top: 8px; - right: 20px; - border-radius: 10px; - padding: 2px 8px; - font-size: 10px; - min-width: 16px; - text-align: center; - backdrop-filter: blur(5px); - box-shadow: 0 2px 4px rgba(0, 138, 255, 0.3); -} - -.tab-content { - padding: 15px; - max-height: 500px; - overflow-y: auto; - background: rgba(255, 255, 255, 0.95); - backdrop-filter: blur(10px); -} - -.section { - margin-bottom: 20px; -} - -.section-title { - font-size: 12px; - color: #666; - margin-bottom: 10px; - padding-bottom: 6px; - border-bottom: 1px solid rgba(0, 138, 255, 0.3); - font-weight: 600; -} - -.route-list { - margin-bottom: 20px; -} - -.route-item { - display: flex; - align-items: center; - padding: 10px; - border-radius: 6px; - margin-bottom: 6px; - cursor: pointer; - transition: all 0.3s; - border: 1px solid transparent; - background: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(5px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} - -.route-item:hover { - background: rgba(0, 138, 255, 0.1); - border-color: rgba(0, 138, 255, 0.3); - transform: translateY(-1px); - box-shadow: 0 4px 10px rgba(0, 138, 255, 0.15); -} - -.route-item.selected { - background: linear-gradient(135deg, rgba(0, 138, 255, 0.15), rgba(0, 138, 255, 0.25)); - border-color: rgba(0, 138, 255, 0.4); - box-shadow: 0 4px 12px rgba(0, 138, 255, 0.2); -} - -.route-item i { - font-size: 18px; - color: #008aff; - margin-right: 10px; - text-shadow: 0 0 4px rgba(0, 138, 255, 0.3); -} - -.route-info { - flex: 1; -} - -.route-name { - font-size: 13px; - color: #333; - margin-bottom: 3px; - font-weight: 600; -} - -.route-meta { - font-size: 11px; - color: #666; -} - -.conflict-tag { - background: linear-gradient(135deg, #f56c6c, #c45656); - border: none; - color: white; - backdrop-filter: blur(5px); - box-shadow: 0 2px 4px rgba(245, 108, 108, 0.3); -} - -.waypoint-list { - margin-bottom: 15px; -} - -.waypoint-item { - display: flex; - align-items: center; - padding: 10px; - border-radius: 6px; - margin-bottom: 6px; - background: rgba(255, 255, 255, 0.9); - border: 1px solid rgba(0, 138, 255, 0.3); - backdrop-filter: blur(5px); - box-shadow: 0 2px 4px rgba(0, 138, 255, 0.1); - transition: all 0.3s; -} - -.waypoint-item:hover { - transform: translateY(-1px); - box-shadow: 0 4px 10px rgba(0, 138, 255, 0.15); -} - -.waypoint-item i { - font-size: 18px; - color: #52c41a; - margin-right: 10px; - text-shadow: 0 0 4px rgba(82, 196, 26, 0.3); -} - -.waypoint-info { - flex: 1; -} - -.waypoint-name { - font-size: 13px; - color: #333; - margin-bottom: 3px; - font-weight: 600; -} - -.waypoint-meta { - font-size: 11px; - color: #666; -} - -.waypoint-actions { - display: flex; - gap: 10px; - color: #666; -} - -.waypoint-actions i { - cursor: pointer; - font-size: 14px; - transition: all 0.3s; - padding: 4px; - border-radius: 4px; - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(5px); -} - -.waypoint-actions i:hover { - color: #008aff; - transform: scale(1.1); - box-shadow: 0 2px 6px rgba(0, 138, 255, 0.2); -} - -.action-buttons { - display: flex; - gap: 10px; - justify-content: center; -} - -/* 按钮样式调整 */ -.el-button { - backdrop-filter: blur(5px); - transition: all 0.3s; -} - -/* 冲突内容样式 */ -.conflict-list { - display: flex; - flex-direction: column; - gap: 15px; -} - -.conflict-item { - background: linear-gradient(135deg, rgba(245, 108, 108, 0.1), rgba(245, 108, 108, 0.05)); - border: 1px solid rgba(245, 108, 108, 0.3); - border-radius: 8px; - padding: 14px; - backdrop-filter: blur(5px); - box-shadow: 0 4px 10px rgba(245, 108, 108, 0.15); - transition: all 0.3s; -} - -.conflict-item:hover { - transform: translateY(-2px); - box-shadow: 0 6px 15px rgba(245, 108, 108, 0.2); -} - -.conflict-header { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 10px; -} - -.conflict-title { - flex: 1; - font-size: 13px; - color: #333; - font-weight: 700; -} - -.conflict-details { - background: rgba(255, 255, 255, 0.8); - border-radius: 6px; - padding: 10px; - margin-bottom: 10px; - border: 1px solid rgba(255, 255, 255, 0.4); - backdrop-filter: blur(5px); - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); -} - -.detail-item { - display: flex; - margin-bottom: 5px; - font-size: 12px; -} - -.detail-item:last-child { - margin-bottom: 0; -} - -.detail-item .label { - color: #666; - min-width: 70px; - font-weight: 500; -} - -.detail-item .value { - color: #333; - flex: 1; - font-weight: 600; -} - -.conflict-actions { - display: flex; - justify-content: flex-end; - gap: 15px; -} - -.no-conflict { - text-align: center; - padding: 40px 20px; - color: #666; -} - -.no-conflict p { - margin: 10px 0 15px; -} - -/* 平台内容样式 */ -.platform-list { - display: flex; - flex-direction: column; - gap: 10px; -} - -.platform-item { - display: flex; - align-items: center; - padding: 12px; - border-radius: 6px; - background: rgba(255, 255, 255, 0.9); - border: 1px solid rgba(0, 138, 255, 0.3); - transition: all 0.3s; - backdrop-filter: blur(5px); - box-shadow: 0 2px 6px rgba(0, 138, 255, 0.1); -} - -.platform-item:hover { - background: rgba(0, 138, 255, 0.1); - border-color: rgba(0, 138, 255, 0.4); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 138, 255, 0.2); -} - -.platform-icon { - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - font-size: 22px; - margin-right: 12px; - border-radius: 6px; - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(5px); - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); -} - -.platform-info { - flex: 1; -} - -.platform-name { - font-size: 13px; - color: #333; - margin-bottom: 3px; - font-weight: 600; -} - -.platform-type { - font-size: 11px; - color: #666; -} - -.platform-status { - margin-left: 10px; -} - -.status-dot { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 50%; - box-shadow: 0 0 6px currentColor; -} - -.status-dot.ready { - background: #52c41a; - box-shadow: 0 0 8px rgba(82, 196, 26, 0.8); -} -.status-dot.flying { - background: #008aff; - animation: pulse 2s infinite; - box-shadow: 0 0 10px rgba(0, 138, 255, 0.8); -} -.status-dot.scouting { - background: #fa8c16; - animation: pulse 1.5s infinite; - box-shadow: 0 0 10px rgba(250, 140, 22, 0.8); -} -.status-dot.sailing { - background: #008aff; - box-shadow: 0 0 8px rgba(0, 138, 255, 0.8); -} -.status-dot.patrol { - background: #52c41a; - animation: pulse 2s infinite; - box-shadow: 0 0 10px rgba(82, 196, 26, 0.8); -} -.status-dot.hidden { - background: #333; - box-shadow: 0 0 6px rgba(51, 51, 51, 0.8); -} -.status-dot.alert { - background: #f5222d; - animation: pulse 1s infinite; - box-shadow: 0 0 10px rgba(245, 34, 45, 0.8); -} -/* 二级菜单样式 */ -.submenu-item { - position: relative; -} - -.submenu-dropdown { - position: absolute; - top: 0; - right: 0; - width: 100%; - height: 100%; -} - -.submenu-trigger { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; -} - -.submenu { - margin-left: 5px; - margin-bottom: 0; - border: none; - border-radius: 6px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); - backdrop-filter: blur(15px); - background: rgba(255, 255, 255, 0.85); - border: 1px solid rgba(0, 138, 255, 0.2); - padding: 0; - min-width: auto; - width: fit-content; -} - -.submenu .el-dropdown-menu__item { - padding: 8px 16px; - font-size: 14px; - color: #333; - transition: all 0.2s ease; - margin: 0; -} - -.submenu .el-dropdown-menu__item:hover { - background: rgba(0, 138, 255, 0.1); - color: #008aff; -} - -.submenu .el-dropdown-menu__item:not(:last-child) { - border-bottom: 1px solid rgba(0, 138, 255, 0.1); -} - -.submenu .el-dropdown-menu__item:last-child { - border-bottom: none; -} - -/* 文件下拉菜单样式 */ -.file-dropdown { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -.dropdown-trigger { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - cursor: pointer; -} - -.file-dropdown-menu { - margin-top: 5px; - margin-bottom: 0; - border: none; - border-radius: 6px; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); - backdrop-filter: blur(15px); - background: rgba(255, 255, 255, 0.85); - border: 1px solid rgba(0, 138, 255, 0.2); - padding: 0; - min-width: auto; - width: fit-content; -} - -.file-dropdown-menu .el-dropdown-menu__item { - padding: 8px 16px; - font-size: 14px; - color: #333; - transition: all 0.2s ease; - margin: 0; -} - -.file-dropdown-menu .el-dropdown-menu__item:hover { - background: rgba(0, 138, 255, 0.1); - color: #008aff; -} - -.file-dropdown-menu .el-dropdown-menu__item:not(:last-child) { - border-bottom: 1px solid rgba(0, 138, 255, 0.1); -} - -.file-dropdown-menu .el-dropdown-menu__item:last-child { - border-bottom: none; -} - -/* 顶部导航菜单调整,为下拉菜单留出空间 */ -.top-nav-item { - position: relative; -} - .status-dot.operating { background: #008aff; animation: pulse 2s infinite;