You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1913 lines
46 KiB
1913 lines
46 KiB
|
3 months ago
|
<template>
|
||
|
|
<!-- 以地图为绝对定位背景,所有组件浮动其上 -->
|
||
|
|
<div class="mission-planning-container">
|
||
|
|
<!-- 地图背景 -->
|
||
|
|
<div id="gis-map-background" class="map-background">
|
||
|
|
<div class="map-overlay-text">
|
||
|
|
<i class="el-icon-location-outline text-3xl mb-2 block"></i>
|
||
|
|
<p>二维GIS地图区域</p>
|
||
|
|
<p class="text-sm mt-1">支持标绘/航线/空域/实时态势</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 地图中间的浮动红点(触发左侧菜单) -->
|
||
|
|
<div
|
||
|
|
class="floating-red-dot left-red-dot"
|
||
|
|
:class="{ hidden: !isMenuHidden }"
|
||
|
|
@click="showMenu"
|
||
|
|
title="显示左侧菜单"
|
||
|
|
>
|
||
|
|
<div class="red-dot"></div>
|
||
|
|
<i class="el-icon-s-unfold icon-inside"></i>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 地图中间的浮动红点(触发右侧面板) -->
|
||
|
|
<div
|
||
|
|
class="floating-red-dot right-red-dot"
|
||
|
|
:class="{ hidden: !isRightPanelHidden }"
|
||
|
|
@click="showRightPanel"
|
||
|
|
title="显示右侧面板"
|
||
|
|
>
|
||
|
|
<div class="red-dot"></div>
|
||
|
|
<i class="el-icon-s-fold icon-inside"></i>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 顶部浮动导航栏 - 重新设计 -->
|
||
|
|
<div class="floating-header blue-theme">
|
||
|
|
<!-- 左侧:Logo和系统名称 -->
|
||
|
|
<div class="header-left">
|
||
|
|
<div class="system-logo">
|
||
|
|
<i class="el-icon-s-promotion logo-icon"></i>
|
||
|
|
<span class="system-name">联合作战筹划系统</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 导航菜单 -->
|
||
|
|
<div class="nav-menu">
|
||
|
|
<div
|
||
|
|
v-for="item in navMenuItems"
|
||
|
|
:key="item.id"
|
||
|
|
class="nav-menu-item"
|
||
|
|
:class="{ active: activeNavMenu === item.id }"
|
||
|
|
@click="selectNavMenu(item)"
|
||
|
|
>
|
||
|
|
<span class="nav-text">{{ item.name }}</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 右侧:作战信息和用户状态 -->
|
||
|
|
<div class="header-right">
|
||
|
|
<!-- 作战信息 -->
|
||
|
|
<div class="combat-info">
|
||
|
|
<div class="info-item">
|
||
|
|
<i class="el-icon-time info-icon"></i>
|
||
|
|
<div class="info-content">
|
||
|
|
<div class="info-label">作战时间</div>
|
||
|
|
<div class="info-value">{{ combatTime }}</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<i class="el-icon-sunny info-icon"></i>
|
||
|
|
<div class="info-content">
|
||
|
|
<div class="info-label">天文时间</div>
|
||
|
|
<div class="info-value">{{ astroTime }}</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<i class="el-icon-office-building info-icon"></i>
|
||
|
|
<div class="info-content">
|
||
|
|
<div class="info-label">房间编号</div>
|
||
|
|
<div class="info-value">{{ roomCode }}</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="info-item">
|
||
|
|
<i class="el-icon-user info-icon"></i>
|
||
|
|
<div class="info-content">
|
||
|
|
<div class="info-label">在线人数</div>
|
||
|
|
<div class="info-value">{{ onlineCount }}人</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 用户状态区域 -->
|
||
|
|
<div class="user-status">
|
||
|
|
<!-- 导入按钮 -->
|
||
|
|
<el-button
|
||
|
|
type="primary"
|
||
|
|
size="mini"
|
||
|
|
icon="el-icon-upload2"
|
||
|
|
class="blue-btn import-btn"
|
||
|
|
@click="importData"
|
||
|
|
>
|
||
|
|
导入
|
||
|
|
</el-button>
|
||
|
|
|
||
|
|
<!-- 导出按钮 -->
|
||
|
|
<el-button
|
||
|
|
type="primary"
|
||
|
|
size="mini"
|
||
|
|
icon="el-icon-download"
|
||
|
|
class="blue-btn export-btn"
|
||
|
|
@click="exportReport"
|
||
|
|
>
|
||
|
|
导出
|
||
|
|
</el-button>
|
||
|
|
|
||
|
|
<!-- 用户头像 -->
|
||
|
|
<el-avatar :size="32" :src="userAvatar" class="user-avatar" />
|
||
|
|
|
||
|
|
<!-- 在线状态 -->
|
||
|
|
<div class="online-status">
|
||
|
|
<span class="dot online"></span>
|
||
|
|
<span class="text">在线</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 左侧折叠菜单栏 - 蓝色主题 -->
|
||
|
|
<div
|
||
|
|
class="floating-left-menu"
|
||
|
|
:class="{ 'hidden': isMenuHidden }"
|
||
|
|
@mouseenter="showMenuTooltip = true"
|
||
|
|
@mouseleave="showMenuTooltip = false"
|
||
|
|
>
|
||
|
|
<!-- 隐藏按钮(>箭头) -->
|
||
|
|
<div class="hide-btn" @click="hideMenu" title="隐藏菜单" >
|
||
|
|
<i class="el-icon-arrow-left"></i>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 一级菜单 -->
|
||
|
|
<div class="menu-icons">
|
||
|
|
<div
|
||
|
|
v-for="item in menuItems"
|
||
|
|
:key="item.id"
|
||
|
|
class="menu-item"
|
||
|
|
:class="{ active: activeMenu === item.id }"
|
||
|
|
@click="selectMenu(item)"
|
||
|
|
@mouseenter="showTooltip(item)"
|
||
|
|
@mouseleave="hideTooltip"
|
||
|
|
>
|
||
|
|
<i :class="item.icon"></i>
|
||
|
|
<!-- 悬浮提示 -->
|
||
|
|
<div v-if="showMenuTooltip && hoverMenu === item.id" class="menu-tooltip">
|
||
|
|
{{ item.name }}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 菜单工具提示层(解决遮挡) -->
|
||
|
|
<div v-if="showMenuTooltip && hoverMenu" class="menu-tooltip-layer">
|
||
|
|
<div class="tooltip-content">{{ getMenuName(hoverMenu) }}</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 右侧外部隐藏按钮 -->
|
||
|
|
<div
|
||
|
|
class="right-external-hide-btn"
|
||
|
|
:class="{ hidden: isRightPanelHidden }"
|
||
|
|
@click="hideRightPanel"
|
||
|
|
title="隐藏右侧面板"
|
||
|
|
>
|
||
|
|
<i class="el-icon-arrow-right"></i>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 右侧实体列表(浮动)- 蓝色主题 -->
|
||
|
|
<div
|
||
|
|
class="floating-right-panel blue-theme"
|
||
|
|
:class="{ 'hidden': isRightPanelHidden }"
|
||
|
|
>
|
||
|
|
<!-- 移除面板内部的隐藏按钮 -->
|
||
|
|
|
||
|
|
<div class="right-tabs">
|
||
|
|
<!-- 方案 -->
|
||
|
|
<div
|
||
|
|
class="right-tab-item"
|
||
|
|
:class="{ active: activeRightTab === 'plan' }"
|
||
|
|
@click="activeRightTab = 'plan'"
|
||
|
|
>
|
||
|
|
<i class="el-icon-s-operation"></i>
|
||
|
|
<span>方案</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 冲突 -->
|
||
|
|
<div
|
||
|
|
class="right-tab-item"
|
||
|
|
:class="{ active: activeRightTab === 'conflict' }"
|
||
|
|
@click="activeRightTab = 'conflict'"
|
||
|
|
>
|
||
|
|
<i class="el-icon-warning-outline"></i>
|
||
|
|
<span>冲突</span>
|
||
|
|
<span v-if="conflictCount > 0" class="badge blue-badge">{{ conflictCount }}</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 平台 -->
|
||
|
|
<div
|
||
|
|
class="right-tab-item"
|
||
|
|
:class="{ active: activeRightTab === 'platform' }"
|
||
|
|
@click="activeRightTab = 'platform'"
|
||
|
|
>
|
||
|
|
<i class="el-icon-ship"></i>
|
||
|
|
<span>平台</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 方案内容 -->
|
||
|
|
<div v-if="activeRightTab === 'plan'" class="tab-content plan-content">
|
||
|
|
<div class="section">
|
||
|
|
<div class="section-title">航线列表</div>
|
||
|
|
<div class="route-list">
|
||
|
|
<div
|
||
|
|
v-for="route in routes"
|
||
|
|
:key="route.id"
|
||
|
|
class="route-item"
|
||
|
|
:class="{ selected: selectedRouteId === route.id }"
|
||
|
|
@click="selectRoute(route)"
|
||
|
|
>
|
||
|
|
<i class="el-icon-map-location"></i>
|
||
|
|
<div class="route-info">
|
||
|
|
<div class="route-name">{{ route.name }}</div>
|
||
|
|
<div class="route-meta">{{ route.points }}个航点</div>
|
||
|
|
</div>
|
||
|
|
<el-tag
|
||
|
|
v-if="route.conflict"
|
||
|
|
size="mini"
|
||
|
|
type="danger"
|
||
|
|
class="conflict-tag"
|
||
|
|
>
|
||
|
|
冲突
|
||
|
|
</el-tag>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-if="selectedRouteDetails" class="section">
|
||
|
|
<div class="section-title">航点列表</div>
|
||
|
|
<div class="waypoint-list">
|
||
|
|
<div
|
||
|
|
v-for="point in selectedRouteDetails.waypoints"
|
||
|
|
:key="point.name"
|
||
|
|
class="waypoint-item"
|
||
|
|
>
|
||
|
|
<i class="el-icon-location"></i>
|
||
|
|
<div class="waypoint-info">
|
||
|
|
<div class="waypoint-name">{{ point.name }}</div>
|
||
|
|
<div class="waypoint-meta">高度: {{ point.altitude }}m | 速度: {{ point.speed }}</div>
|
||
|
|
</div>
|
||
|
|
<div class="waypoint-actions">
|
||
|
|
<i class="el-icon-edit" title="编辑"></i>
|
||
|
|
<i class="el-icon-delete" title="删除"></i>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="action-buttons">
|
||
|
|
<el-button type="primary" size="mini" icon="el-icon-circle-plus" class="blue-btn" @click="addWaypoint">
|
||
|
|
添加航点
|
||
|
|
</el-button>
|
||
|
|
<el-button size="mini" class="blue-btn" @click="cancelRoute">
|
||
|
|
取消
|
||
|
|
</el-button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 冲突内容 -->
|
||
|
|
<div v-if="activeRightTab === '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">严重</el-tag>
|
||
|
|
</div>
|
||
|
|
<div class="conflict-details">
|
||
|
|
<div class="detail-item">
|
||
|
|
<span class="label">涉及航线:</span>
|
||
|
|
<span class="value">{{ conflict.routes.join('、') }}</span>
|
||
|
|
</div>
|
||
|
|
<div class="detail-item">
|
||
|
|
<span class="label">冲突时间:</span>
|
||
|
|
<span class="value">{{ conflict.time }}</span>
|
||
|
|
</div>
|
||
|
|
<div class="detail-item">
|
||
|
|
<span class="label">冲突位置:</span>
|
||
|
|
<span class="value">{{ conflict.position }}</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="conflict-actions">
|
||
|
|
<el-button type="text" size="mini" class="blue-text-btn" @click="viewConflict(conflict)">
|
||
|
|
查看详情
|
||
|
|
</el-button>
|
||
|
|
<el-button type="text" size="mini" class="blue-text-btn" @click="resolveConflict(conflict)">
|
||
|
|
解决冲突
|
||
|
|
</el-button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div v-else class="no-conflict">
|
||
|
|
<i class="el-icon-success" style="color: #67c23a; font-size: 24px;"></i>
|
||
|
|
<p>暂无冲突</p>
|
||
|
|
<el-button size="mini" class="blue-btn" @click="runConflictCheck">
|
||
|
|
重新检测
|
||
|
|
</el-button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 平台内容 -->
|
||
|
|
<div v-if="activeRightTab === 'platform'" class="tab-content platform-content">
|
||
|
|
<div class="platform-categories">
|
||
|
|
<el-tabs v-model="activePlatformTab" type="card" size="mini" class="blue-tabs">
|
||
|
|
<el-tab-pane label="空中" name="air">
|
||
|
|
<div class="platform-list">
|
||
|
|
<div
|
||
|
|
v-for="platform in airPlatforms"
|
||
|
|
:key="platform.id"
|
||
|
|
class="platform-item"
|
||
|
|
>
|
||
|
|
<div class="platform-icon" :style="{ color: platform.color }">
|
||
|
|
<i :class="platform.icon"></i>
|
||
|
|
</div>
|
||
|
|
<div class="platform-info">
|
||
|
|
<div class="platform-name">{{ platform.name }}</div>
|
||
|
|
<div class="platform-type">{{ platform.type }}</div>
|
||
|
|
</div>
|
||
|
|
<div class="platform-status">
|
||
|
|
<span class="status-dot" :class="platform.status"></span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
|
||
|
|
<el-tab-pane label="海上" name="sea">
|
||
|
|
<div class="platform-list">
|
||
|
|
<div
|
||
|
|
v-for="platform in seaPlatforms"
|
||
|
|
:key="platform.id"
|
||
|
|
class="platform-item"
|
||
|
|
>
|
||
|
|
<div class="platform-icon" :style="{ color: platform.color }">
|
||
|
|
<i :class="platform.icon"></i>
|
||
|
|
</div>
|
||
|
|
<div class="platform-info">
|
||
|
|
<div class="platform-name">{{ platform.name }}</div>
|
||
|
|
<div class="platform-type">{{ platform.type }}</div>
|
||
|
|
</div>
|
||
|
|
<div class="platform-status">
|
||
|
|
<span class="status-dot" :class="platform.status"></span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
|
||
|
|
<el-tab-pane label="地面" name="ground">
|
||
|
|
<div class="platform-list">
|
||
|
|
<div
|
||
|
|
v-for="platform in groundPlatforms"
|
||
|
|
:key="platform.id"
|
||
|
|
class="platform-item"
|
||
|
|
>
|
||
|
|
<div class="platform-icon" :style="{ color: platform.color }">
|
||
|
|
<i :class="platform.icon"></i>
|
||
|
|
</div>
|
||
|
|
<div class="platform-info">
|
||
|
|
<div class="platform-name">{{ platform.name }}</div>
|
||
|
|
<div class="platform-type">{{ platform.type }}</div>
|
||
|
|
</div>
|
||
|
|
<div class="platform-status">
|
||
|
|
<span class="status-dot" :class="platform.status"></span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
</el-tabs>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 底部时间轴(最初版本的样式)- 蓝色主题 -->
|
||
|
|
<div
|
||
|
|
class="floating-timeline blue-theme"
|
||
|
|
:class="{ 'show': showKTimePopup }"
|
||
|
|
>
|
||
|
|
<!-- 隐藏按钮(向下箭头) -->
|
||
|
|
<div class="popup-hide-btn" @click="hideKTimePopup" title="隐藏K时">
|
||
|
|
<i class="el-icon-arrow-down"></i>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="timeline-controls">
|
||
|
|
<div class="current-time blue-time">
|
||
|
|
<i class="el-icon-time"></i>
|
||
|
|
<span class="time-text">{{ currentTime }}</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="timeline-slider">
|
||
|
|
<el-slider
|
||
|
|
v-model="timeProgress"
|
||
|
|
:max="100"
|
||
|
|
:format-tooltip="formatTimeTooltip"
|
||
|
|
class="compact-slider blue-slider"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="timeline-marks">
|
||
|
|
<span class="mark">K-02:00</span>
|
||
|
|
<span class="mark">K-01:00</span>
|
||
|
|
<span class="mark current blue-mark">K时</span>
|
||
|
|
<span class="mark">K+01:00</span>
|
||
|
|
<span class="mark">K+02:00</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="system-status">
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">网络延迟:</span>
|
||
|
|
<span class="status-value success blue-success">< 200ms</span>
|
||
|
|
</div>
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">数据同步:</span>
|
||
|
|
<span class="status-value success blue-success">正常</span>
|
||
|
|
</div>
|
||
|
|
<div class="status-item">
|
||
|
|
<span class="status-label">检测告警:</span>
|
||
|
|
<span class="status-value warning blue-warning">2处</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
name: 'MissionPlanningView',
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
// 导航菜单
|
||
|
|
activeNavMenu: 'file',
|
||
|
|
navMenuItems: [
|
||
|
|
{ id: 'file', name: '文件' },
|
||
|
|
{ id: 'edit', name: '编辑' },
|
||
|
|
{ id: 'view', name: '视图' },
|
||
|
|
{ id: 'map', name: '地图' },
|
||
|
|
{ id: 'airspace', name: '空域' },
|
||
|
|
{ id: 'tools', name: '工具' },
|
||
|
|
{ id: 'options', name: '选项' },
|
||
|
|
{ id: 'favorites', name: '收藏' }
|
||
|
|
],
|
||
|
|
|
||
|
|
// 作战信息
|
||
|
|
combatTime: 'K+01:15:30',
|
||
|
|
astroTime: '2023-10-15 14:30:00',
|
||
|
|
roomCode: 'CMD-ALPHA-01',
|
||
|
|
onlineCount: 5,
|
||
|
|
|
||
|
|
// 左侧菜单栏
|
||
|
|
isMenuHidden: true, // 是否完全隐藏左侧菜单
|
||
|
|
activeMenu: 'file',
|
||
|
|
hoverMenu: '',
|
||
|
|
showMenuTooltip: false,
|
||
|
|
|
||
|
|
// 右侧面板控制
|
||
|
|
isRightPanelHidden: true, // 是否完全隐藏右侧面板
|
||
|
|
|
||
|
|
// K时弹出框控制
|
||
|
|
showKTimePopup: false,
|
||
|
|
|
||
|
|
menuItems: [
|
||
|
|
{ id: 'file', name: '文件', icon: 'el-icon-document' },
|
||
|
|
{ id: 'start', name: '开始', icon: 'el-icon-caret-right' },
|
||
|
|
{ id: 'insert', name: '插入', icon: 'el-icon-plus' },
|
||
|
|
{ id: 'pattern', name: '图案', icon: 'el-icon-picture-outline' },
|
||
|
|
{ id: 'deduction', name: '推演', icon: 'el-icon-video-play' },
|
||
|
|
{ id: 'modify', name: '修改', icon: 'el-icon-edit' },
|
||
|
|
{ id: 'refresh', name: '刷新', icon: 'el-icon-refresh' },
|
||
|
|
{ id: 'basemap', name: '底图', icon: 'el-icon-map-location' },
|
||
|
|
{ id: 'import', name: '导入', icon: 'el-icon-upload2' },
|
||
|
|
{ id: 'export', name: '导出', icon: 'el-icon-download' }
|
||
|
|
],
|
||
|
|
|
||
|
|
// 右侧面板
|
||
|
|
activeRightTab: 'plan',
|
||
|
|
selectedRouteId: 101,
|
||
|
|
selectedRouteDetails: null,
|
||
|
|
|
||
|
|
// 冲突数据
|
||
|
|
conflictCount: 2,
|
||
|
|
conflicts: [
|
||
|
|
{
|
||
|
|
id: 1,
|
||
|
|
title: '航线空间冲突',
|
||
|
|
routes: ['Alpha进场航线', 'Beta巡逻航线'],
|
||
|
|
time: 'K+01:20:00',
|
||
|
|
position: 'E116° N39°',
|
||
|
|
severity: 'high'
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: 2,
|
||
|
|
title: '时间窗口重叠',
|
||
|
|
routes: ['侦察覆盖区', '无人机巡逻'],
|
||
|
|
time: 'K+02:15:00',
|
||
|
|
position: 'E117° N38°',
|
||
|
|
severity: 'medium'
|
||
|
|
}
|
||
|
|
],
|
||
|
|
|
||
|
|
// 平台数据
|
||
|
|
activePlatformTab: 'air',
|
||
|
|
airPlatforms: [
|
||
|
|
{ id: 1, name: 'J-20 歼击机', type: '战斗机', icon: 'el-icon-fighter', color: '#52c41a', status: 'ready' },
|
||
|
|
{ id: 2, name: 'KJ-2000 预警机', type: '预警机', icon: 'el-icon-s-promotion', color: '#1890ff', status: 'flying' },
|
||
|
|
{ id: 3, name: 'UAV-01 无人机', type: '侦察无人机', icon: 'el-icon-drone', color: '#fa8c16', status: 'scouting' },
|
||
|
|
{ id: 4, name: 'H-6K 轰炸机', type: '轰炸机', icon: 'el-icon-bomb', color: '#722ed1', status: 'ready' },
|
||
|
|
],
|
||
|
|
seaPlatforms: [
|
||
|
|
{ id: 5, name: '辽宁舰', type: '航空母舰', icon: 'el-icon-ship', color: '#1890ff', status: 'sailing' },
|
||
|
|
{ id: 6, name: '055型驱逐舰', type: '驱逐舰', icon: 'el-icon-ship', color: '#52c41a', status: 'patrol' },
|
||
|
|
{ id: 7, name: '093型潜艇', type: '核潜艇', icon: 'el-icon-ship', color: '#333', status: 'hidden' },
|
||
|
|
],
|
||
|
|
groundPlatforms: [
|
||
|
|
{ id: 8, name: 'HQ-9防空系统', type: '防空导弹', icon: 'el-icon-mic', color: '#f5222d', status: 'alert' },
|
||
|
|
{ id: 9, name: 'PLZ-05自行火炮', type: '自行火炮', icon: 'el-icon-aim', color: '#fa8c16', status: 'ready' },
|
||
|
|
{ id: 10, name: '指挥控制车', type: '指挥车', icon: 'el-icon-monitor', color: '#1890ff', status: 'operating' },
|
||
|
|
],
|
||
|
|
|
||
|
|
// 航线数据
|
||
|
|
routes: [
|
||
|
|
{ id: 101, name: 'Alpha进场航线', points: 8, conflict: true },
|
||
|
|
{ id: 102, name: 'Beta巡逻航线', points: 6, conflict: false },
|
||
|
|
{ id: 103, name: '侦察覆盖区', points: 4, conflict: false },
|
||
|
|
],
|
||
|
|
|
||
|
|
// 时间控制
|
||
|
|
timeProgress: 45,
|
||
|
|
currentTime: 'K+01:15:30',
|
||
|
|
|
||
|
|
// 用户
|
||
|
|
userAvatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
||
|
|
};
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
// 初始化时选中第一条航线
|
||
|
|
this.selectRoute(this.routes[0]);
|
||
|
|
// 初始化时左侧菜单隐藏
|
||
|
|
this.isMenuHidden = true;
|
||
|
|
// 初始化时右侧面板隐藏
|
||
|
|
this.isRightPanelHidden = true;
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
// 导航菜单操作
|
||
|
|
selectNavMenu(item) {
|
||
|
|
this.activeNavMenu = item.id;
|
||
|
|
this.$message.info(`选择菜单: ${item.name}`);
|
||
|
|
},
|
||
|
|
|
||
|
|
// 左侧菜单栏操作
|
||
|
|
showMenu() {
|
||
|
|
this.isMenuHidden = false;
|
||
|
|
this.$message.info('显示左侧菜单');
|
||
|
|
},
|
||
|
|
|
||
|
|
hideMenu() {
|
||
|
|
this.isMenuHidden = true;
|
||
|
|
this.$message.info('隐藏左侧菜单');
|
||
|
|
},
|
||
|
|
|
||
|
|
// 右侧面板操作
|
||
|
|
showRightPanel() {
|
||
|
|
this.isRightPanelHidden = false;
|
||
|
|
this.$message.info('显示右侧面板');
|
||
|
|
},
|
||
|
|
|
||
|
|
hideRightPanel() {
|
||
|
|
this.isRightPanelHidden = true;
|
||
|
|
this.$message.info('隐藏右侧面板');
|
||
|
|
},
|
||
|
|
|
||
|
|
selectMenu(item) {
|
||
|
|
this.activeMenu = item.id;
|
||
|
|
|
||
|
|
if (item.id === 'deduction') {
|
||
|
|
// 点击推演按钮,显示/隐藏K时弹出框
|
||
|
|
this.showKTimePopup = !this.showKTimePopup;
|
||
|
|
if (this.showKTimePopup) {
|
||
|
|
this.$message.info('显示推演时钟控制');
|
||
|
|
} else {
|
||
|
|
this.$message.info('隐藏推演时钟控制');
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// 其他菜单的原有逻辑
|
||
|
|
this.$message.info(`选择菜单: ${item.name}`);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
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;
|
||
|
|
this.$message.info('隐藏推演时钟控制');
|
||
|
|
},
|
||
|
|
|
||
|
|
// 时间控制(保留用于底部时间轴)
|
||
|
|
play() {
|
||
|
|
this.$message.success('推演开始');
|
||
|
|
},
|
||
|
|
|
||
|
|
pause() {
|
||
|
|
this.$message.info('推演暂停');
|
||
|
|
},
|
||
|
|
|
||
|
|
reset() {
|
||
|
|
this.timeProgress = 0;
|
||
|
|
this.currentTime = 'K+00:00:00';
|
||
|
|
this.$message.info('推演已重置');
|
||
|
|
},
|
||
|
|
|
||
|
|
formatTimeTooltip(val) {
|
||
|
|
const hours = Math.floor(val / 4);
|
||
|
|
const minutes = (val % 4) * 15;
|
||
|
|
return `K+${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:00`;
|
||
|
|
},
|
||
|
|
|
||
|
|
// 航线操作
|
||
|
|
selectRoute(route) {
|
||
|
|
this.selectedRouteId = route.id;
|
||
|
|
// 模拟获取航点数据
|
||
|
|
this.selectedRouteDetails = {
|
||
|
|
name: route.name,
|
||
|
|
waypoints: [
|
||
|
|
{ name: 'WP1', altitude: 5000, speed: '800km/h', eta: 'K+00:40:00' },
|
||
|
|
{ name: 'WP2', altitude: 6000, speed: '850km/h', eta: 'K+00:55:00' },
|
||
|
|
{ name: 'WP3', altitude: 5500, speed: '820km/h', eta: 'K+01:10:00' },
|
||
|
|
{ name: 'WP4', altitude: 5800, speed: '830km/h', eta: 'K+01:25:00' },
|
||
|
|
]
|
||
|
|
};
|
||
|
|
},
|
||
|
|
|
||
|
|
addWaypoint() {
|
||
|
|
if (this.selectedRouteDetails) {
|
||
|
|
const count = this.selectedRouteDetails.waypoints.length + 1;
|
||
|
|
this.selectedRouteDetails.waypoints.push({
|
||
|
|
name: `WP${count}`,
|
||
|
|
altitude: 5000,
|
||
|
|
speed: '800km/h',
|
||
|
|
eta: `K+01:${(count * 15).toString().padStart(2, '0')}:00`
|
||
|
|
});
|
||
|
|
this.$message.success('添加航点成功');
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
cancelRoute() {
|
||
|
|
this.selectedRouteId = null;
|
||
|
|
this.selectedRouteDetails = null;
|
||
|
|
this.$message.info('已取消选中');
|
||
|
|
},
|
||
|
|
|
||
|
|
// 冲突操作
|
||
|
|
runConflictCheck() {
|
||
|
|
this.conflictCount = 2;
|
||
|
|
this.$message.warning('检测到2处航线冲突');
|
||
|
|
},
|
||
|
|
|
||
|
|
viewConflict(conflict) {
|
||
|
|
this.$message.info(`查看冲突:${conflict.title}`);
|
||
|
|
},
|
||
|
|
|
||
|
|
resolveConflict(conflict) {
|
||
|
|
this.$message.success(`解决冲突:${conflict.title}`);
|
||
|
|
// 移除已解决的冲突
|
||
|
|
this.conflicts = this.conflicts.filter(c => c.id !== conflict.id);
|
||
|
|
this.conflictCount = this.conflicts.length;
|
||
|
|
},
|
||
|
|
|
||
|
|
// 系统功能
|
||
|
|
exportReport() {
|
||
|
|
this.$message.success('作战报表导出成功');
|
||
|
|
},
|
||
|
|
|
||
|
|
// 新增导入功能
|
||
|
|
importData() {
|
||
|
|
this.$message.success('导入数据成功');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.mission-planning-container {
|
||
|
|
position: relative;
|
||
|
|
width: 100vw;
|
||
|
|
height: 100vh;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 地图背景 - 保持不变 */
|
||
|
|
.map-background {
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
background: linear-gradient(135deg, #1a2f4b 0%, #2c3e50 100%);
|
||
|
|
background-image: url('~@/assets/map-background.png');
|
||
|
|
background-size: cover;
|
||
|
|
background-position: center;
|
||
|
|
z-index: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
.map-overlay-text {
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translate(-50%, -50%);
|
||
|
|
color: rgba(255, 255, 255, 0.3);
|
||
|
|
text-align: center;
|
||
|
|
font-size: 18px;
|
||
|
|
pointer-events: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 地图中间的浮动红点 - 通用样式 */
|
||
|
|
.floating-red-dot {
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
width: 40px;
|
||
|
|
height: 40px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: rgba(255, 255, 255, 0.3);
|
||
|
|
backdrop-filter: blur(5px);
|
||
|
|
border: 2px solid rgba(255, 0, 0, 0.8);
|
||
|
|
box-shadow: 0 0 20px rgba(255, 0, 0, 0.6);
|
||
|
|
cursor: pointer;
|
||
|
|
z-index: 80;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
animation: pulse-red 2s infinite;
|
||
|
|
}
|
||
|
|
|
||
|
|
.floating-red-dot:hover {
|
||
|
|
transform: translateY(-50%) scale(1.1);
|
||
|
|
box-shadow: 0 0 25px rgba(255, 0, 0, 0.8);
|
||
|
|
}
|
||
|
|
|
||
|
|
.floating-red-dot.hidden {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 左侧红点 */
|
||
|
|
.left-red-dot {
|
||
|
|
left: 20px;
|
||
|
|
transform: translateY(-50%);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 右侧红点 */
|
||
|
|
.right-red-dot {
|
||
|
|
right: 20px;
|
||
|
|
transform: translateY(-50%);
|
||
|
|
}
|
||
|
|
|
||
|
|
.red-dot {
|
||
|
|
width: 20px;
|
||
|
|
height: 20px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: radial-gradient(circle at 30% 30%, #ff4444, #cc0000);
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
.icon-inside {
|
||
|
|
position: absolute;
|
||
|
|
color: white;
|
||
|
|
font-size: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes pulse-red {
|
||
|
|
0% {
|
||
|
|
box-shadow: 0 0 20px rgba(255, 0, 0, 0.6);
|
||
|
|
}
|
||
|
|
50% {
|
||
|
|
box-shadow: 0 0 25px rgba(255, 0, 0, 0.8);
|
||
|
|
}
|
||
|
|
100% {
|
||
|
|
box-shadow: 0 0 20px rgba(255, 0, 0, 0.6);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 蓝色主题通用类 */
|
||
|
|
.blue-theme {
|
||
|
|
background: rgba(255, 255, 255, 0.3);
|
||
|
|
backdrop-filter: blur(10px);
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.1);
|
||
|
|
box-shadow: 0 4px 12px rgba(0, 138, 255, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-btn {
|
||
|
|
background: rgba(0, 138, 255, 0.8);
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.9);
|
||
|
|
color: white;
|
||
|
|
transition: all 0.3s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-btn:hover {
|
||
|
|
background: rgba(0, 138, 255, 0.9);
|
||
|
|
border-color: rgba(0, 138, 255, 1);
|
||
|
|
transform: translateY(-1px);
|
||
|
|
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-text-btn {
|
||
|
|
color: #008aff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-text-btn:hover {
|
||
|
|
color: #0066cc;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-badge {
|
||
|
|
background: rgba(0, 138, 255, 0.8);
|
||
|
|
color: white;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-tag {
|
||
|
|
background: rgba(0, 138, 255, 0.2);
|
||
|
|
color: #008aff;
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-time {
|
||
|
|
background: rgba(0, 138, 255, 0.1);
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.3);
|
||
|
|
color: #008aff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-success {
|
||
|
|
color: #008aff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-warning {
|
||
|
|
color: #ff9900;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-mark {
|
||
|
|
color: #008aff;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 顶部导航栏 - 重新设计 */
|
||
|
|
.floating-header {
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
right: 0;
|
||
|
|
height: 70px;
|
||
|
|
padding: 0 25px;
|
||
|
|
border-radius: 0 0 12px 12px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
z-index: 100;
|
||
|
|
backdrop-filter: blur(20px);
|
||
|
|
border: none;
|
||
|
|
box-shadow: 0 4px 20px rgba(0, 138, 255, 0.25);
|
||
|
|
background: rgba(255, 255, 255, 0.95);
|
||
|
|
border-bottom: 2px solid rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.header-left {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 40px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.system-logo {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 12px;
|
||
|
|
padding-right: 25px;
|
||
|
|
border-right: 1px solid rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.logo-icon {
|
||
|
|
font-size: 28px;
|
||
|
|
color: #008aff;
|
||
|
|
text-shadow: 0 0 10px rgba(0, 138, 255, 0.5);
|
||
|
|
background: linear-gradient(135deg, #008aff, #0066cc);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
}
|
||
|
|
|
||
|
|
.system-name {
|
||
|
|
font-size: 22px;
|
||
|
|
font-weight: 800;
|
||
|
|
color: #008aff;
|
||
|
|
text-shadow: 0 2px 4px rgba(0, 138, 255, 0.2);
|
||
|
|
letter-spacing: 1px;
|
||
|
|
background: linear-gradient(135deg, #008aff, #0066cc);
|
||
|
|
-webkit-background-clip: text;
|
||
|
|
-webkit-text-fill-color: transparent;
|
||
|
|
background-clip: text;
|
||
|
|
}
|
||
|
|
|
||
|
|
.nav-menu {
|
||
|
|
display: flex;
|
||
|
|
gap: 0;
|
||
|
|
background: rgba(255, 255, 255, 0.9);
|
||
|
|
border-radius: 8px;
|
||
|
|
padding: 4px;
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.2);
|
||
|
|
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.1);
|
||
|
|
backdrop-filter: blur(5px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.nav-menu-item {
|
||
|
|
padding: 8px 20px;
|
||
|
|
cursor: pointer;
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 600;
|
||
|
|
color: #555;
|
||
|
|
transition: all 0.3s;
|
||
|
|
border-radius: 6px;
|
||
|
|
position: relative;
|
||
|
|
text-align: center;
|
||
|
|
min-width: 70px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.nav-menu-item:hover {
|
||
|
|
color: #008aff;
|
||
|
|
background: rgba(0, 138, 255, 0.1);
|
||
|
|
transform: translateY(-1px);
|
||
|
|
box-shadow: 0 2px 6px rgba(0, 138, 255, 0.15);
|
||
|
|
}
|
||
|
|
|
||
|
|
.nav-menu-item.active {
|
||
|
|
color: #008aff;
|
||
|
|
background: linear-gradient(135deg, rgba(0, 138, 255, 0.15), rgba(0, 138, 255, 0.25));
|
||
|
|
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.nav-menu-item.active::after {
|
||
|
|
content: '';
|
||
|
|
position: absolute;
|
||
|
|
bottom: -2px;
|
||
|
|
left: 20%;
|
||
|
|
width: 60%;
|
||
|
|
height: 2px;
|
||
|
|
background: linear-gradient(90deg, #008aff, #0066cc);
|
||
|
|
border-radius: 1px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.nav-text {
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 右侧区域 */
|
||
|
|
.header-right {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 30px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.combat-info {
|
||
|
|
display: flex;
|
||
|
|
gap: 25px;
|
||
|
|
background: rgba(255, 255, 255, 0.9);
|
||
|
|
border-radius: 10px;
|
||
|
|
padding: 8px 20px;
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.2);
|
||
|
|
box-shadow: 0 2px 10px rgba(0, 138, 255, 0.15);
|
||
|
|
backdrop-filter: blur(5px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 10px;
|
||
|
|
padding: 0 10px;
|
||
|
|
border-right: 1px solid rgba(0, 138, 255, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-item:last-child {
|
||
|
|
border-right: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-icon {
|
||
|
|
font-size: 18px;
|
||
|
|
color: #008aff;
|
||
|
|
background: rgba(0, 138, 255, 0.1);
|
||
|
|
padding: 6px;
|
||
|
|
border-radius: 6px;
|
||
|
|
box-shadow: 0 2px 6px rgba(0, 138, 255, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-content {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-label {
|
||
|
|
font-size: 11px;
|
||
|
|
color: #666;
|
||
|
|
font-weight: 500;
|
||
|
|
margin-bottom: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-value {
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 700;
|
||
|
|
color: #333;
|
||
|
|
font-family: 'Courier New', monospace;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 用户状态区域 */
|
||
|
|
.user-status {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 15px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.import-btn {
|
||
|
|
background: linear-gradient(135deg, rgba(82, 196, 26, 0.8), rgba(64, 158, 20, 0.8));
|
||
|
|
border: 1px solid rgba(82, 196, 26, 0.9);
|
||
|
|
}
|
||
|
|
|
||
|
|
.import-btn:hover {
|
||
|
|
background: linear-gradient(135deg, rgba(82, 196, 26, 0.9), rgba(64, 158, 20, 0.9));
|
||
|
|
border-color: rgba(82, 196, 26, 1);
|
||
|
|
box-shadow: 0 2px 8px rgba(82, 196, 26, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.export-btn {
|
||
|
|
background: linear-gradient(135deg, rgba(0, 138, 255, 0.8), rgba(0, 102, 204, 0.8));
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.9);
|
||
|
|
}
|
||
|
|
|
||
|
|
.export-btn:hover {
|
||
|
|
background: linear-gradient(135deg, rgba(0, 138, 255, 0.9), rgba(0, 102, 204, 0.9));
|
||
|
|
border-color: rgba(0, 138, 255, 1);
|
||
|
|
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.user-avatar {
|
||
|
|
border: 2px solid rgba(0, 138, 255, 0.3);
|
||
|
|
box-shadow: 0 2px 8px rgba(0, 138, 255, 0.2);
|
||
|
|
transition: all 0.3s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.user-avatar:hover {
|
||
|
|
transform: scale(1.1);
|
||
|
|
box-shadow: 0 4px 12px rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.online-status {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
color: #52c41a;
|
||
|
|
font-size: 12px;
|
||
|
|
font-weight: 600;
|
||
|
|
padding: 6px 12px;
|
||
|
|
background: rgba(82, 196, 26, 0.1);
|
||
|
|
border-radius: 6px;
|
||
|
|
border: 1px solid rgba(82, 196, 26, 0.3);
|
||
|
|
box-shadow: 0 2px 6px rgba(82, 196, 26, 0.15);
|
||
|
|
transition: all 0.3s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.online-status:hover {
|
||
|
|
transform: translateY(-1px);
|
||
|
|
box-shadow: 0 4px 10px rgba(82, 196, 26, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.dot {
|
||
|
|
width: 8px;
|
||
|
|
height: 8px;
|
||
|
|
border-radius: 50%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.dot.online {
|
||
|
|
background: #52c41a;
|
||
|
|
animation: pulse 2s infinite;
|
||
|
|
box-shadow: 0 0 8px rgba(82, 196, 26, 0.8);
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes pulse {
|
||
|
|
0% {
|
||
|
|
opacity: 1;
|
||
|
|
box-shadow: 0 0 8px rgba(82, 196, 26, 0.8);
|
||
|
|
}
|
||
|
|
50% {
|
||
|
|
opacity: 0.7;
|
||
|
|
box-shadow: 0 0 12px rgba(82, 196, 26, 1);
|
||
|
|
}
|
||
|
|
100% {
|
||
|
|
opacity: 1;
|
||
|
|
box-shadow: 0 0 8px rgba(82, 196, 26, 0.8);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 左侧菜单栏 - 蓝色主题 */
|
||
|
|
.floating-left-menu {
|
||
|
|
position: absolute;
|
||
|
|
top: 80px;
|
||
|
|
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: 10px;
|
||
|
|
right: 13px;
|
||
|
|
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: 80px;
|
||
|
|
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: 80px;
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
.status-dot.operating {
|
||
|
|
background: #008aff;
|
||
|
|
animation: pulse 2s infinite;
|
||
|
|
box-shadow: 0 0 10px rgba(0, 138, 255, 0.8);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 蓝色主题标签页 */
|
||
|
|
.blue-tabs >>> .el-tabs__item {
|
||
|
|
color: #666;
|
||
|
|
transition: all 0.3s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-tabs >>> .el-tabs__item:hover {
|
||
|
|
color: #008aff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-tabs >>> .el-tabs__item.is-active {
|
||
|
|
color: #008aff;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-tabs >>> .el-tabs__active-bar {
|
||
|
|
background-color: #008aff;
|
||
|
|
box-shadow: 0 0 6px rgba(0, 138, 255, 0.5);
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-tabs >>> .el-tabs__nav-wrap::after {
|
||
|
|
background-color: rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 底部时间轴(最初版本的样式)- 蓝色主题 */
|
||
|
|
.floating-timeline {
|
||
|
|
position: absolute;
|
||
|
|
bottom: 20px;
|
||
|
|
left: 50%;
|
||
|
|
transform: translateX(-50%) translateY(100%);
|
||
|
|
width: 80%;
|
||
|
|
border-radius: 12px;
|
||
|
|
z-index: 95;
|
||
|
|
padding: 20px;
|
||
|
|
color: #333;
|
||
|
|
transition: all 0.3s ease;
|
||
|
|
opacity: 0;
|
||
|
|
pointer-events: none;
|
||
|
|
backdrop-filter: blur(15px);
|
||
|
|
background: rgba(255, 255, 255, 0.95);
|
||
|
|
box-shadow: 0 8px 32px rgba(0, 138, 255, 0.25);
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
.floating-timeline.show {
|
||
|
|
transform: translateX(-50%) translateY(0);
|
||
|
|
opacity: 1;
|
||
|
|
pointer-events: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.popup-hide-btn {
|
||
|
|
position: absolute;
|
||
|
|
top: -28px;
|
||
|
|
left: 50%;
|
||
|
|
transform: translateX(-50%);
|
||
|
|
width: 56px;
|
||
|
|
height: 28px;
|
||
|
|
background: rgba(255, 255, 255, 0.3);
|
||
|
|
backdrop-filter: blur(10px);
|
||
|
|
border: 1px solid rgba(0, 138, 255, 0.4);
|
||
|
|
border-bottom: none;
|
||
|
|
border-radius: 12px 12px 0 0;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
cursor: pointer;
|
||
|
|
color: #008aff;
|
||
|
|
font-size: 18px;
|
||
|
|
transition: all 0.3s;
|
||
|
|
z-index: 10;
|
||
|
|
}
|
||
|
|
|
||
|
|
.popup-hide-btn:hover {
|
||
|
|
background: rgba(0, 138, 255, 0.2);
|
||
|
|
color: #0066cc;
|
||
|
|
height: 32px;
|
||
|
|
top: -32px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-controls {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
margin-bottom: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.current-time {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
font-family: monospace;
|
||
|
|
font-size: 14px;
|
||
|
|
font-weight: 500;
|
||
|
|
padding: 4px 12px;
|
||
|
|
border-radius: 4px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-slider {
|
||
|
|
flex: 1;
|
||
|
|
margin: 0 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.compact-slider {
|
||
|
|
width: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-slider >>> .el-slider__bar {
|
||
|
|
background-color: rgba(0, 138, 255, 0.8);
|
||
|
|
}
|
||
|
|
|
||
|
|
.blue-slider >>> .el-slider__button {
|
||
|
|
border-color: rgba(0, 138, 255, 0.8);
|
||
|
|
background-color: rgba(0, 138, 255, 0.8);
|
||
|
|
}
|
||
|
|
|
||
|
|
.timeline-marks {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
font-size: 11px;
|
||
|
|
color: #666;
|
||
|
|
margin-top: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.mark.current {
|
||
|
|
font-weight: bold;
|
||
|
|
}
|
||
|
|
|
||
|
|
.system-status {
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
gap: 30px;
|
||
|
|
font-size: 12px;
|
||
|
|
margin-top: 10px;
|
||
|
|
padding-top: 10px;
|
||
|
|
border-top: 1px solid rgba(0, 138, 255, 0.4);
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-label {
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-value.success {
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-value.warning {
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 滚动条样式 */
|
||
|
|
::-webkit-scrollbar {
|
||
|
|
width: 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
::-webkit-scrollbar-track {
|
||
|
|
background: rgba(0, 138, 255, 0.1);
|
||
|
|
border-radius: 3px;
|
||
|
|
backdrop-filter: blur(5px);
|
||
|
|
}
|
||
|
|
|
||
|
|
::-webkit-scrollbar-thumb {
|
||
|
|
background: linear-gradient(135deg, rgba(0, 138, 255, 0.5), rgba(0, 138, 255, 0.7));
|
||
|
|
border-radius: 3px;
|
||
|
|
box-shadow: 0 0 6px rgba(0, 138, 255, 0.4);
|
||
|
|
}
|
||
|
|
|
||
|
|
::-webkit-scrollbar-thumb:hover {
|
||
|
|
background: linear-gradient(135deg, rgba(0, 138, 255, 0.7), rgba(0, 138, 255, 0.9));
|
||
|
|
}
|
||
|
|
|
||
|
|
.ml-3 {
|
||
|
|
margin-left: 10px;
|
||
|
|
}
|
||
|
|
</style>
|