|
|
@@ -1,302 +1,479 @@
|
|
|
<template>
|
|
|
- <el-container class="h-screen flex-row overflow-hidden situation-container">
|
|
|
- <!-- 左侧栏:20%宽 + 右侧蓝色边框(区分中间区域) -->
|
|
|
- <el-aside
|
|
|
- width="20%"
|
|
|
- class="p-4 min-w-[150px] border-blue-500 sidebar"
|
|
|
- >
|
|
|
- <!-- 引入任务信息子组件 -->
|
|
|
- <TaskInfo :task-data="taskData" />
|
|
|
-
|
|
|
- <!-- 引入装备信息子组件 -->
|
|
|
- <EquipmentSidebar :equipment-tree="equipmentTree" />
|
|
|
-
|
|
|
- <!-- 引入临机调整建议组件 -->
|
|
|
- <AdjustmentAdvice
|
|
|
- v-if="currentView !== 'now'"
|
|
|
- :advices="adjustmentAdvices"
|
|
|
- :expanded="expandedSections.临机调整建议"
|
|
|
- @send-to-interference="handleSendToInterference"
|
|
|
- @send-to-measurement="handleSendToMeasurement"
|
|
|
- />
|
|
|
- <!-- 引入弹目信息子组件 -->
|
|
|
- <ProjectileInfo v-if="currentView === 'model' || currentView === 'now'" :operation-info="operationInfo" />
|
|
|
- <!-- 关键事件组件 -->
|
|
|
- <KeyEvent
|
|
|
- :key-event="keyEvent"
|
|
|
- :expanded="expandedSections.关键事件"
|
|
|
- @toggle="expandedSections.关键事件 = $event"
|
|
|
- />
|
|
|
-
|
|
|
- </el-aside>
|
|
|
-
|
|
|
- <!-- 中间主区域:左右红色边框(区分左右栏) + 垂直布局 -->
|
|
|
- <el-main class="p-6 flex flex-col gap-4 h-full map-container">
|
|
|
- <div class="flex-1 overflow-hidden p-4 map-view-container">
|
|
|
- <!-- 画面切换按钮容器 -->
|
|
|
- <div
|
|
|
- class="view-toggle-container"
|
|
|
- @mouseenter="showToggleButton = true"
|
|
|
- @mouseleave="showToggleButton = false"
|
|
|
- >
|
|
|
- <el-button
|
|
|
- v-show="true"
|
|
|
- class="view-toggle-btn"
|
|
|
- @click="handleViewToggle"
|
|
|
- >
|
|
|
- <i :class="getToggleIcon()"></i>
|
|
|
- {{ getToggleText() }}
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
+ <div class="task-setting-container">
|
|
|
+ <!-- 背景网格装饰 -->
|
|
|
+ <div class="grid-bg"></div>
|
|
|
+
|
|
|
+ <!-- 头部区域:军事风格 - 庄重威严 -->
|
|
|
+ <div class="header">
|
|
|
+ <div class="header-logo flex items-center">
|
|
|
+ <i class="el-icon-shield text-red-500 mr-2 text-xl"></i>
|
|
|
+ <h1>导弹打击试验任务想定系统</h1>
|
|
|
+ </div>
|
|
|
+ <div class="header-controls">
|
|
|
+ <el-button type="success" icon="el-icon-back" @click="goBack" class="btn军事">
|
|
|
+ 返回
|
|
|
+ </el-button>
|
|
|
+ <el-button type="primary" icon="el-icon-save" @click="saveTask" class="btn军事">
|
|
|
+ 保存任务
|
|
|
+ </el-button>
|
|
|
+ <el-button type="warning" icon="el-icon-refresh" @click="resetTask" class="btn军事">
|
|
|
+ 重置
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 主布局容器:大屏分区明确 -->
|
|
|
+ <el-container class="h-[calc(100vh-60px)] flex-row overflow-hidden">
|
|
|
+ <!-- 左侧栏:任务配置 -->
|
|
|
+ <el-aside width="20%" class="min-w-[240px] border-right border-[#0c4a6e] relative">
|
|
|
+ <div class="aside-border-decoration"></div>
|
|
|
+ <div class="task-panel h-full">
|
|
|
+ <div class="task-content">
|
|
|
+ <!-- 基本信息:大屏简洁风格 -->
|
|
|
+ <div class="section-card mb-6">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ 基本信息
|
|
|
+ </h4>
|
|
|
+ </div>
|
|
|
+ <el-form :model="taskForm" label-width="100px" size="small" class="p-4">
|
|
|
+ <el-form-item label="任务名称" class="mb-3">
|
|
|
+ <el-input v-model="taskForm.name" placeholder="请输入任务名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="任务类别" class="mb-3">
|
|
|
+ <el-select v-model="taskForm.category" placeholder="请选择任务类别">
|
|
|
+ <el-option label="保障任务" value="support" />
|
|
|
+ <el-option label="实战任务" value="combat" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="任务类型" class="mb-3">
|
|
|
+ <el-select v-model="taskForm.type" placeholder="请选择任务类型">
|
|
|
+ <el-option label="防空作战" value="air-defense" />
|
|
|
+ <el-option label="对海作战" value="sea-combat" />
|
|
|
+ <el-option label="对地打击" value="ground-strike" />
|
|
|
+ <el-option label="电子对抗" value="electronic-warfare" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="导弹类型" class="mb-3">
|
|
|
+ <el-select v-model="taskForm.missileType" placeholder="请选择导弹类型" @change="updateTargetsByMissileType">
|
|
|
+ <el-option label="地空导弹" value="surface-to-air" />
|
|
|
+ <el-option label="空地导弹" value="air-to-surface" />
|
|
|
+ <el-option label="反舰导弹" value="anti-ship" />
|
|
|
+ <el-option label="巡航导弹" value="cruise" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="导弹数量" class="mb-3">
|
|
|
+ <el-input-number v-model="taskForm.missileCount" :min="1" :max="100" size="small" @change="updateTargetsByMissileCount" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="执行时间" class="mb-3">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="taskForm.executeTime"
|
|
|
+ type="datetime"
|
|
|
+ placeholder="选择执行时间"
|
|
|
+ format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="任务描述">
|
|
|
+ <el-input
|
|
|
+ v-model="taskForm.description"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ placeholder="请输入任务描述"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 目标设置 -->
|
|
|
+ <div class="section-card mb-6">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <i class="el-icon-location"></i>
|
|
|
+ 目标设置
|
|
|
+ </h4>
|
|
|
+ <el-button type="text" icon="el-icon-plus" @click="addTarget" class="text-green-400" :disabled="!canAddMoreTargets">
|
|
|
+ 添加目标
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="target-list p-4">
|
|
|
+ <div class="target-hint text-xs text-yellow-400 mb-2" v-if="taskForm.targets.length < taskForm.missileCount">
|
|
|
+ 提示:可添加 {{ taskForm.missileCount - taskForm.targets.length }} 个目标
|
|
|
+ </div>
|
|
|
+ <div class="target-hint text-xs text-red-400 mb-2" v-if="taskForm.targets.length > taskForm.missileCount">
|
|
|
+ 警告:目标数量超过导弹数量 {{ taskForm.targets.length - taskForm.missileCount }} 个
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="target-item p-3 mb-3"
|
|
|
+ v-for="target in taskForm.targets"
|
|
|
+ :key="target.id"
|
|
|
+ >
|
|
|
+ <div class="target-header flex justify-between items-center mb-2">
|
|
|
+ <span class="target-name font-bold truncate max-w-[150px]">{{ target.name }}</span>
|
|
|
+ <div class="target-actions flex">
|
|
|
+ <el-button type="text" icon="el-icon-edit" @click="editTarget(target)" class="p-1 text-blue-400" />
|
|
|
+ <el-button type="text" icon="el-icon-delete" @click="removeTarget(target)" class="p-1 text-red-400" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="target-info flex justify-between text-sm">
|
|
|
+ <span class="target-type">{{ target.type }}</span>
|
|
|
+ <span class="target-coord truncate max-w-[120px]">{{ target.coordinates }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="target-threat mt-2 flex items-center text-xs">
|
|
|
+ <span class="mr-2">威胁等级:</span>
|
|
|
+ <div class="threat-bars flex gap-1">
|
|
|
+ <div
|
|
|
+ class="threat-bar"
|
|
|
+ v-for="n in 5"
|
|
|
+ :key="n"
|
|
|
+ :class="{ 'active': n <= target.threatLevel }"
|
|
|
+ ></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="target-equipment mt-2 text-xs text-gray-400">
|
|
|
+ <span>负责装备:</span>
|
|
|
+ <el-select v-model="target.equipmentId" placeholder="选择装备" size="mini" @change="updateTargetEquipment(target.id, $event)">
|
|
|
+ <el-option
|
|
|
+ v-for="equip in allEquipment"
|
|
|
+ :key="equip.id"
|
|
|
+ :label="equip.label"
|
|
|
+ :value="equip.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
- <WeatherInfo class="weather-info" :telemetry="telemetry" />
|
|
|
- <!-- 事件时间线 -->
|
|
|
- <EventTimeline
|
|
|
- style="z-index: 200;"
|
|
|
- :events="events"
|
|
|
- :current-event-index="currentEventIndex"
|
|
|
- @jump-to-event="jumpToEvent"
|
|
|
- />
|
|
|
- <!-- 第一个视图:before -->
|
|
|
- <template v-if="currentView === 'before'">
|
|
|
- <MapContainer
|
|
|
- :events="events"
|
|
|
- :current-event-index="currentEventIndex"
|
|
|
- :show-red-line="showRedLine"
|
|
|
- :show-blue-line="showBlueLine"
|
|
|
- :is-legend-expanded="isLegendExpanded"
|
|
|
- :pip-image="pipImage"
|
|
|
- :pip-visible.sync="pipVisible"
|
|
|
- :pip-preview-visible.sync="pipPreviewVisible"
|
|
|
- @toggle-line="toggleLine"
|
|
|
- @toggle-legend="isLegendExpanded = !isLegendExpanded"
|
|
|
- @jump-to-event="jumpToEvent"
|
|
|
- />
|
|
|
- </template>
|
|
|
-
|
|
|
- <!-- 第二个视图:model -->
|
|
|
- <template v-else-if="currentView === 'model'">
|
|
|
- <!-- 地图控制按钮 -->
|
|
|
- <div class="map-controls">
|
|
|
- <div class="map-control-group">
|
|
|
- <el-button
|
|
|
- v-for="control in mapControls"
|
|
|
- :key="control.key"
|
|
|
- :icon="control.icon"
|
|
|
- :title="control.tooltip"
|
|
|
- class="map-control-btn"
|
|
|
- @click="handleMapControl(control.key)"
|
|
|
- />
|
|
|
+ <!-- 装备配置:树形结构 -->
|
|
|
+ <div class="section-card">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <i class="el-icon-cpu"></i>
|
|
|
+ 装备配置
|
|
|
+ </h4>
|
|
|
+ </div>
|
|
|
+ <div class="equipment-tree p-4">
|
|
|
+ <el-tree
|
|
|
+ :data="equipmentTree"
|
|
|
+ :props="defaultProps"
|
|
|
+ node-key="id"
|
|
|
+ @node-click="handleEquipmentClick"
|
|
|
+ :expand-on-click-node="false"
|
|
|
+ :highlight-current="true"
|
|
|
+ >
|
|
|
+ <span slot-scope="{ node, data }" class="custom-tree-node">
|
|
|
+ <span class="tree-node-content flex items-center">
|
|
|
+ <i :class="getEquipmentIcon(data)" class="mr-2"></i>
|
|
|
+ <span>{{ node.label }}</span>
|
|
|
+ <span v-if="data.indicatorClass" class="ml-2 w-2 h-2 rounded-full" :class="data.indicatorClass"></span>
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </el-tree>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-aside>
|
|
|
+
|
|
|
+ <!-- 中间主区域:策略设置和装备详情 -->
|
|
|
+ <el-main class="p-0 h-full flex flex-col relative">
|
|
|
+ <div class="main-border-decoration"></div>
|
|
|
+
|
|
|
+ <!-- 策略内容区 -->
|
|
|
+ <div class="strategy-content-box flex-1 overflow-y-auto p-4">
|
|
|
+ <!-- 作战策略 -->
|
|
|
+ <div class="section-card mb-6">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <i class="el-icon-s-operation mr-2"></i>
|
|
|
+ 作战想定策略
|
|
|
+ </h4>
|
|
|
+ </div>
|
|
|
+ <div class="strategy-grid p-4">
|
|
|
+ <div
|
|
|
+ class="strategy-card p-3 cursor-pointer transition-all"
|
|
|
+ v-for="strategy in strategies"
|
|
|
+ :key="strategy.id"
|
|
|
+ :class="{ selected: selectedStrategy === strategy.id }"
|
|
|
+ @click="selectStrategy(strategy)"
|
|
|
+ >
|
|
|
+ <div class="strategy-icon w-10 h-10 rounded-full flex items-center justify-center text-lg mb-3">
|
|
|
+ <i :class="strategy.icon"></i>
|
|
|
+ </div>
|
|
|
+ <div class="strategy-info min-w-0">
|
|
|
+ <div class="strategy-name font-bold mb-2 truncate">{{ strategy.name }}</div>
|
|
|
+ <div class="strategy-desc text-sm line-clamp-2">{{ strategy.description }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 罗盘 -->
|
|
|
- <div class="map-compass">
|
|
|
- <div class="compass-inner">
|
|
|
- <div :style="{ transform: `rotate(${compassAngle}deg)` }" class="compass-needle"></div>
|
|
|
- <div class="compass-direction compass-n">N</div>
|
|
|
- <div class="compass-direction compass-e">E</div>
|
|
|
- <div class="compass-direction compass-s">S</div>
|
|
|
- <div class="compass-direction compass-w">W</div>
|
|
|
+ <!-- 选中装备详情编辑 -->
|
|
|
+ <div class="section-card mb-6" v-if="selectedEquipment">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <i :class="getEquipmentIcon(selectedEquipment)" class="mr-2"></i>
|
|
|
+ {{ selectedEquipment.label }} - 配置详情
|
|
|
+ </h4>
|
|
|
+ </div>
|
|
|
+ <div class="equipment-detail p-4">
|
|
|
+ <div class="grid grid-cols-2 gap-4">
|
|
|
+ <div v-for="(item, index) in selectedEquipment.details" :key="index" class="detail-item">
|
|
|
+ <div class="detail-label text-sm text-gray-400">{{ item.label }}</div>
|
|
|
+ <div class="detail-value font-medium">{{ item.value }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="mt-4 pt-4 border-t border-blue-900/30">
|
|
|
+ <el-form :model="selectedEquipment" label-width="100px" size="small">
|
|
|
+ <el-form-item label="工作状态">
|
|
|
+ <el-select
|
|
|
+ v-model="selectedEquipment.status"
|
|
|
+ placeholder="选择工作状态"
|
|
|
+ size="small"
|
|
|
+ @change="updateEquipmentStatus"
|
|
|
+ >
|
|
|
+ <el-option label="待命" value="standby" />
|
|
|
+ <el-option label="就绪" value="ready" />
|
|
|
+ <el-option label="维护中" value="maintenance" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="部署位置">
|
|
|
+ <el-select
|
|
|
+ v-model="selectedEquipment.position"
|
|
|
+ placeholder="选择部署位置"
|
|
|
+ size="small"
|
|
|
+ @change="updateEquipmentPosition"
|
|
|
+ >
|
|
|
+ <el-option label="左翼" value="left" />
|
|
|
+ <el-option label="右翼" value="right" />
|
|
|
+ <el-option label="中央" value="center" />
|
|
|
+ <el-option label="前沿" value="front" />
|
|
|
+ <el-option label="后方" value="rear" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注信息">
|
|
|
+ <el-input
|
|
|
+ v-model="selectedEquipment.notes"
|
|
|
+ type="textarea"
|
|
|
+ :rows="2"
|
|
|
+ placeholder="请输入备注信息"
|
|
|
+ @change="updateEquipmentNotes"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 地图视图 -->
|
|
|
- <div class="map-view">
|
|
|
- <div class="map-grid"></div>
|
|
|
- <img alt="态势地图" class="map-image" src="/img/banner.jpg"/>
|
|
|
- <!-- 设备标记 -->
|
|
|
- <div
|
|
|
- v-for="device in filteredDevices"
|
|
|
- :key="device.id"
|
|
|
- :class="['device-marker', device.type, device.subType, { active: selectedDevice && selectedDevice.id === device.id }]"
|
|
|
- :style="{
|
|
|
- left: device.position.x + '%',
|
|
|
- top: device.position.y + '%'
|
|
|
- }"
|
|
|
- :title="device.name"
|
|
|
- @click="selectDevice(device)"
|
|
|
- >
|
|
|
- <div class="device-label">{{ device.name }}</div>
|
|
|
+ <!-- 装备策略 -->
|
|
|
+ <div class="section-card mb-6">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4 class="section-title">
|
|
|
+ <i class="el-icon-setting mr-2"></i>
|
|
|
+ 装备想定策略
|
|
|
+ </h4>
|
|
|
</div>
|
|
|
- <!-- 图例 -->
|
|
|
- <div class="map-legend">
|
|
|
- <h4>设备图例</h4>
|
|
|
+ <div class="equipment-strategy p-4">
|
|
|
<div
|
|
|
- v-for="type in deviceTypes"
|
|
|
- :key="type.key"
|
|
|
- class="legend-item"
|
|
|
- @click="toggleDeviceVisibility(type.key)"
|
|
|
+ class="equipment-strategy-item p-3 mb-3"
|
|
|
+ v-for="item in equipmentStrategies"
|
|
|
+ :key="item.id"
|
|
|
>
|
|
|
- <span :class="['legend-icon', type.key]"></span>
|
|
|
- <span>{{ type.name }}</span>
|
|
|
- <el-checkbox
|
|
|
- v-model="visibleDeviceTypes[type.key]"
|
|
|
- @change="toggleDeviceVisibility(type.key)"
|
|
|
- />
|
|
|
+ <div class="strategy-header flex justify-between items-center mb-3">
|
|
|
+ <span class="equipment-name font-bold truncate max-w-[120px]">{{ item.equipment }}</span>
|
|
|
+ <el-select v-model="item.strategy" placeholder="选择策略" size="small" class="w-[140px]">
|
|
|
+ <el-option
|
|
|
+ v-for="option in item.options"
|
|
|
+ :key="option.value"
|
|
|
+ :label="option.label"
|
|
|
+ :value="option.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="strategy-params border-t pt-3" v-if="item.params">
|
|
|
+ <el-form :model="item.params" label-width="80px" size="mini">
|
|
|
+ <el-form-item label="优先级" class="mb-2">
|
|
|
+ <el-input-number v-model="item.params.priority" :min="1" :max="10" size="mini" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="响应时间">
|
|
|
+ <el-input-number v-model="item.params.responseTime" :min="1" size="mini" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <!-- 画中画 -->
|
|
|
- <div v-if="showPIP" class="pip-container">
|
|
|
- <div class="view-label">画中画</div>
|
|
|
- <img alt="画中画" class="pip-image" src="/img/map.png" @click="linkToPage">
|
|
|
- </div>
|
|
|
</div>
|
|
|
- </template>
|
|
|
|
|
|
- <!-- 第三个视图:now(预留内容) -->
|
|
|
- <template v-else-if="currentView === 'now'">
|
|
|
- <div class="now-view-container">
|
|
|
+ </div>
|
|
|
+ </el-main>
|
|
|
+
|
|
|
+ <!-- 右侧栏:任务预览(大屏风格优化) -->
|
|
|
+ <el-aside width="20%" class="min-w-[240px] border-left border-[#0c4a6e] relative">
|
|
|
+ <div class="aside-border-decoration"></div>
|
|
|
+ <div class="preview-panel h-full">
|
|
|
+ <div class="preview-content p-4">
|
|
|
+ <!-- 任务概览:大屏数据突出 - 横向展示 -->
|
|
|
+ <div class="preview-section mb-6">
|
|
|
+ <h4 class="p-3 font-medium border-b m-0">任务概览</h4>
|
|
|
+ <div class="overview-stats p-4">
|
|
|
+ <div class="stat-row flex gap-2 mb-2">
|
|
|
+ <div class="stat-item flex-1 p-3">
|
|
|
+ <div class="stat-label text-sm">目标数量</div>
|
|
|
+ <div class="stat-value text-2xl font-bold">{{ taskForm.targets.length }}</div>
|
|
|
+ <div class="stat-desc text-xs mt-1">
|
|
|
+ {{ taskForm.targets.length > 0 ? '已配置目标' : '暂无目标' }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item flex-1 p-3">
|
|
|
+ <div class="stat-label text-sm">导弹数量</div>
|
|
|
+ <div class="stat-value text-2xl font-bold">{{ taskForm.missileCount || 0 }}</div>
|
|
|
+ <div class="stat-desc text-xs mt-1">
|
|
|
+ {{ missileTypeName || '未选择类型' }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-row flex gap-2 mb-2">
|
|
|
+ <div class="stat-item flex-1 p-3">
|
|
|
+ <div class="stat-label text-sm">装备总数</div>
|
|
|
+ <div class="stat-value text-2xl font-bold">{{ totalEquipment }}</div>
|
|
|
+ <div class="stat-desc text-xs mt-1">
|
|
|
+ 各类装备总和
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item flex-1 p-3">
|
|
|
+ <div class="stat-label text-sm">任务类型</div>
|
|
|
+ <div class="stat-value text-lg font-bold truncate">{{ taskTypeName }}</div>
|
|
|
+ <div class="stat-desc text-xs mt-1">
|
|
|
+ {{ taskCategoryName }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-row">
|
|
|
+ <div class="stat-item w-full p-3">
|
|
|
+ <div class="stat-label text-sm">执行时间</div>
|
|
|
+ <div class="stat-value text-lg font-bold">{{ taskForm.executeTime || '未指定' }}</div>
|
|
|
+ <div class="stat-desc text-xs mt-1">
|
|
|
+ {{ formattedCountdown }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
+ <!-- 执行时间轴:大屏清晰展示 -->
|
|
|
+ <div class="preview-section">
|
|
|
+ <h4 class="p-3 font-medium border-b m-0">执行时间轴</h4>
|
|
|
+ <div class="timeline-container p-4 relative">
|
|
|
+ <div class="timeline-line absolute top-0 bottom-0 left-3 w-0.5"></div>
|
|
|
+ <div
|
|
|
+ class="timeline-item relative mb-6 pl-8"
|
|
|
+ v-for="event in sortedEvents"
|
|
|
+ :key="event.id"
|
|
|
+ >
|
|
|
+ <div class="timeline-dot absolute left-0 top-1 w-6 h-6 rounded-full flex items-center justify-center z-10" :class="dotClassMap[event.dotClass]">
|
|
|
+ <div class="w-2 h-2 rounded-full bg-white"></div>
|
|
|
+ </div>
|
|
|
+ <div class="timeline-content p-3">
|
|
|
+ <div class="flex justify-between items-start mb-1">
|
|
|
+ <div class="timeline-time font-bold text-sm">{{ event.time }}</div>
|
|
|
+ <div class="timeline-status text-xs px-2 py-0.5 rounded" :class="statusClassMap[event.dotClass]">{{ event.status }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="timeline-title font-bold text-sm mb-2">{{ event.title }}</div>
|
|
|
+ <div class="timeline-description text-xs">{{ event.description }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
- </el-main>
|
|
|
-
|
|
|
- <!--右侧-->
|
|
|
- <el-aside
|
|
|
- width="20%"
|
|
|
- class="p-4 min-w-[120px] border-l-2 right-panel"
|
|
|
+ </div>
|
|
|
+ </el-aside>
|
|
|
+ </el-container>
|
|
|
+
|
|
|
+ <!-- 添加目标对话框:大屏简洁风格 -->
|
|
|
+ <el-dialog
|
|
|
+ title="添加目标"
|
|
|
+ :visible.sync="showTargetDialog"
|
|
|
+ width="50%"
|
|
|
+ custom-class="target-dialog"
|
|
|
>
|
|
|
- <PlanContent v-if="currentView === 'model'" @scheme-type-change="onSchemeTypeChange" />
|
|
|
- <ViewSelector
|
|
|
- v-if="currentView === 'before' || currentView ==='now'"
|
|
|
- :views="currentImageList"
|
|
|
- :expanded="expandedSections.视角选择"
|
|
|
- @select-view="handleImageClick"
|
|
|
- />
|
|
|
- </el-aside>
|
|
|
- </el-container>
|
|
|
+ <el-form :model="targetForm" label-width="100px">
|
|
|
+ <el-form-item label="目标名称">
|
|
|
+ <el-input v-model="targetForm.name" placeholder="请输入目标名称"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="目标类型">
|
|
|
+ <el-select v-model="targetForm.type" placeholder="请选择目标类型">
|
|
|
+ <el-option label="空中目标" value="空中目标" :disabled="!isAirTargetAllowed"></el-option>
|
|
|
+ <el-option label="海上目标" value="海上目标" :disabled="!isSeaTargetAllowed"></el-option>
|
|
|
+ <el-option label="地面目标" value="地面目标" :disabled="!isGroundTargetAllowed"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="坐标位置">
|
|
|
+ <el-input v-model="targetForm.coordinates" placeholder="格式:东经XX°XX′,北纬XX°XX′"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="威胁等级">
|
|
|
+ <el-slider v-model="targetForm.threatLevel" :min="1" :max="5" show-input />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="负责装备">
|
|
|
+ <el-select v-model="targetForm.equipmentId" placeholder="选择负责装备">
|
|
|
+ <el-option
|
|
|
+ v-for="equip in allEquipment"
|
|
|
+ :key="equip.id"
|
|
|
+ :label="equip.label"
|
|
|
+ :value="equip.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="showTargetDialog = false" class="btn军事">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmAddTarget" class="btn军事">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import EquipmentSidebar from '../components/EquipmentSidebar.vue'
|
|
|
-import ProjectileInfo from "../components/ProjectileInfo.vue"
|
|
|
-import TaskInfo from "../components/TaskInfo.vue"
|
|
|
-import PlanContent from "../components/PlanContent.vue"
|
|
|
-import EventTimeline from "../components/EventTimeline.vue";
|
|
|
-import MapContainer from '../components/MapContainer.vue';
|
|
|
-import ViewSelector from "../components/ViewSelector.vue";
|
|
|
-import AdjustmentAdvice from "../components/AdjustmentAdvice.vue";
|
|
|
-import KeyEvent from "../components/KeyEvent.vue";
|
|
|
-import WeatherInfo from "../components/WeatherInfo.vue";
|
|
|
export default {
|
|
|
- components: {
|
|
|
- WeatherInfo,
|
|
|
- KeyEvent,
|
|
|
- AdjustmentAdvice,
|
|
|
- ViewSelector,
|
|
|
- EventTimeline,
|
|
|
- EquipmentSidebar,
|
|
|
- ProjectileInfo,
|
|
|
- TaskInfo,
|
|
|
- PlanContent,
|
|
|
- MapContainer
|
|
|
- },
|
|
|
+ components: {},
|
|
|
data() {
|
|
|
return {
|
|
|
- showRedLine: true,
|
|
|
- showBlueLine: true,
|
|
|
- isLegendExpanded: false,
|
|
|
- pipImage: '/img/banner.jpg',
|
|
|
- pipVisible: false,
|
|
|
- pipPreviewVisible: false,
|
|
|
- currentView: 'before', // 视图状态:before, model, now,默认展示before
|
|
|
- showToggleButton: false, // 控制按钮显示状态
|
|
|
-
|
|
|
- // 气象数据
|
|
|
- telemetry: {
|
|
|
- windSpeed: '12.8',
|
|
|
- windDirection: '东北',
|
|
|
- temperature: '25.3',
|
|
|
- visibility: '10.0',
|
|
|
- humidity: '65',
|
|
|
- pressure: '1013'
|
|
|
- },
|
|
|
-
|
|
|
- // 关键事件
|
|
|
- keyEvent: {
|
|
|
- title: '红方装备集群接近',
|
|
|
- time: 'T+00:05:10',
|
|
|
- description: '红方装备A集群正以35m/s的速度接近我方指挥中心,距离约8km。',
|
|
|
- status: '警告: 即将进入警戒区域'
|
|
|
- },
|
|
|
-
|
|
|
- // 事件进度相关
|
|
|
- events: [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- title: '观测装置部署完成',
|
|
|
- time: 'T-00:05:00',
|
|
|
- description: '完成高空观测装置A1、地面观测装置B2和移动观测装置C3的部署。',
|
|
|
- status: '覆盖率: 92%',
|
|
|
- dotClass: 'info',
|
|
|
- position: 10
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- title: '干扰装备启动',
|
|
|
- time: 'T-00:02:30',
|
|
|
- description: '干扰装备D1和D2开始启动,进入待命状态。',
|
|
|
- status: '功率: 60%',
|
|
|
- dotClass: 'info',
|
|
|
- position: 30
|
|
|
- },
|
|
|
- {
|
|
|
- id: 3,
|
|
|
- title: '装备A侦察活动开始',
|
|
|
- time: 'T+00:00:00',
|
|
|
- description: '装备类型A开始进入监视区域,执行侦察任务。',
|
|
|
- status: '目标: 指挥中心',
|
|
|
- dotClass: 'warning',
|
|
|
- position: 50
|
|
|
- },
|
|
|
- {
|
|
|
- id: 4,
|
|
|
- title: '发现可疑目标',
|
|
|
- time: 'T+00:01:45',
|
|
|
- description: '观测装置A1发现可疑目标,正在进行识别确认。',
|
|
|
- status: '识别中...',
|
|
|
- dotClass: 'warning',
|
|
|
- position: 70
|
|
|
- },
|
|
|
- {
|
|
|
- id: 5,
|
|
|
- title: '目标确认',
|
|
|
- time: 'T+00:03:20',
|
|
|
- description: '确认发现红方装备A集群,数量约5个单位。',
|
|
|
- status: '已确认',
|
|
|
- dotClass: 'danger',
|
|
|
- position: 90
|
|
|
- }
|
|
|
- ],
|
|
|
-
|
|
|
- // 视角数据
|
|
|
- views: [
|
|
|
- { value: '1', label: '主视角' ,img: '/img/x01.png'},
|
|
|
- { value: '2', label: '俯视图', img: '/img/x02.png' },
|
|
|
- { value: '3', label: '侧视图' ,img: '/img/x03.png'},
|
|
|
- { value: '4', label: '红外视角', img: '/img/x04.png' },
|
|
|
- { value: '5', label: '红外视角2', img: '/img/x03.png' }
|
|
|
- ],
|
|
|
- whenFight:[
|
|
|
- {value: '1', img: '/img/zha5.png', label: '靶场视角视角1'},
|
|
|
- {value: '2', img: '/img/zha3.png', label: '靶场视角视角2'},
|
|
|
- {value: '3', img: '/img/zha2.png', label: '靶场视角视角'},
|
|
|
- {value: '4', img: '/img/zha.png', label: '靶场视角视角3'},
|
|
|
- {value: '5', img: '/img/zha4.png', label: '靶场视角视角4'},
|
|
|
- ],
|
|
|
- // 面板展开/折叠控制
|
|
|
- expandedSections: {
|
|
|
- weather: true,
|
|
|
- '关键事件': true,
|
|
|
- '视角选择': true,
|
|
|
- '临机调整建议': true
|
|
|
+ // 时间显示
|
|
|
+ 天文时间: '',
|
|
|
+ 绝对时间: '',
|
|
|
+
|
|
|
+ // 任务表单数据
|
|
|
+ taskForm: {
|
|
|
+ name: '新型导弹打击试验',
|
|
|
+ category: 'combat', // 任务类别:support-保障任务,combat-实战任务
|
|
|
+ type: 'air-defense',
|
|
|
+ missileType: '', // 新增导弹类型字段
|
|
|
+ missileCount: 8, // 导弹数量
|
|
|
+ executeTime: '2025-10-01 09:00:00',
|
|
|
+ description: '',
|
|
|
+ targets: [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ name: '敌机编队A',
|
|
|
+ type: '空中目标',
|
|
|
+ coordinates: '东经120°15′,北纬30°20′',
|
|
|
+ threatLevel: 4,
|
|
|
+ equipmentId: 'A1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ name: '敌舰编队B',
|
|
|
+ type: '海上目标',
|
|
|
+ coordinates: '东经120°30′,北纬30°10′',
|
|
|
+ threatLevel: 3,
|
|
|
+ equipmentId: 'B2'
|
|
|
+ }
|
|
|
+ ]
|
|
|
},
|
|
|
|
|
|
- currentEventIndex: 0,
|
|
|
-
|
|
|
- // 树形结构装备数据(传给子组件)
|
|
|
+ // 装备树形结构数据 - 两级结构
|
|
|
equipmentTree: [
|
|
|
{
|
|
|
id: 'category1',
|
|
|
@@ -306,7 +483,10 @@ export default {
|
|
|
id: 'A1',
|
|
|
label: '高空观测装置A1',
|
|
|
side: '',
|
|
|
- indicatorClass: 'blue',
|
|
|
+ indicatorClass: 'bg-blue-500',
|
|
|
+ status: 'ready',
|
|
|
+ position: 'front',
|
|
|
+ notes: '',
|
|
|
details: [
|
|
|
{ label: '状态', value: '运行中' },
|
|
|
{ label: '覆盖范围', value: '3500米' },
|
|
|
@@ -322,7 +502,10 @@ export default {
|
|
|
id: 'B2',
|
|
|
label: '地面观测装置B2',
|
|
|
side: '',
|
|
|
- indicatorClass: 'blue',
|
|
|
+ indicatorClass: 'bg-blue-500',
|
|
|
+ status: 'ready',
|
|
|
+ position: 'center',
|
|
|
+ notes: '',
|
|
|
details: [
|
|
|
{ label: '状态', value: '运行中' },
|
|
|
{ label: '覆盖范围', value: '1200米' },
|
|
|
@@ -333,6 +516,25 @@ export default {
|
|
|
{ label: '发现目标', value: '2个' },
|
|
|
{ label: '数据链路', value: '稳定' }
|
|
|
]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 'C3',
|
|
|
+ label: '移动观测装置C3',
|
|
|
+ side: '',
|
|
|
+ indicatorClass: 'bg-blue-500',
|
|
|
+ status: 'standby',
|
|
|
+ position: 'rear',
|
|
|
+ notes: '',
|
|
|
+ details: [
|
|
|
+ { label: '状态', value: '待命' },
|
|
|
+ { label: '覆盖范围', value: '800米' },
|
|
|
+ { label: '速度', value: '40km/h' },
|
|
|
+ { label: '观测精度', value: '85%' },
|
|
|
+ { label: '功率', value: '70%' },
|
|
|
+ { label: '电量', value: '95%' },
|
|
|
+ { label: '发现目标', value: '0个' },
|
|
|
+ { label: '数据链路', value: '稳定' }
|
|
|
+ ]
|
|
|
}
|
|
|
]
|
|
|
},
|
|
|
@@ -342,15 +544,38 @@ export default {
|
|
|
children: [
|
|
|
{
|
|
|
id: 'D1',
|
|
|
- label: '干扰装备D1',
|
|
|
+ label: '雷达干扰器D1',
|
|
|
side: '',
|
|
|
- indicatorClass: 'purple',
|
|
|
+ indicatorClass: 'bg-purple-500',
|
|
|
+ status: 'standby',
|
|
|
+ position: 'left',
|
|
|
+ notes: '',
|
|
|
details: [
|
|
|
{ label: '状态', value: '待命' },
|
|
|
{ label: '功率', value: '60%' },
|
|
|
{ label: '高度', value: '50米' },
|
|
|
{ label: '覆盖范围', value: '2000米' },
|
|
|
{ label: '电量', value: '95%' },
|
|
|
+ { label: '干扰类型', value: '雷达波' },
|
|
|
+ { label: '有效距离', value: '5km' },
|
|
|
+ { label: '数据链路', value: '稳定' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 'E2',
|
|
|
+ label: '光电干扰器E2',
|
|
|
+ side: '',
|
|
|
+ indicatorClass: 'bg-purple-500',
|
|
|
+ status: 'ready',
|
|
|
+ position: 'right',
|
|
|
+ notes: '',
|
|
|
+ details: [
|
|
|
+ { label: '状态', value: '运行中' },
|
|
|
+ { label: '功率', value: '80%' },
|
|
|
+ { label: '干扰波段', value: '可见光-红外' },
|
|
|
+ { label: '覆盖范围', value: '1500米' },
|
|
|
+ { label: '电量', value: '88%' },
|
|
|
+ { label: '干扰强度', value: '强' },
|
|
|
{ label: '数据链路', value: '稳定' }
|
|
|
]
|
|
|
}
|
|
|
@@ -362,1442 +587,1291 @@ export default {
|
|
|
children: [
|
|
|
{
|
|
|
id: 'redA',
|
|
|
- label: '装备A集群',
|
|
|
+ label: '空中靶标A集群',
|
|
|
side: '',
|
|
|
- indicatorClass: 'red',
|
|
|
+ indicatorClass: 'bg-red-500',
|
|
|
+ status: 'ready',
|
|
|
+ position: 'front',
|
|
|
+ notes: '',
|
|
|
details: [
|
|
|
- { label: '状态', value: '行进中' },
|
|
|
+ { label: '状态', value: '就绪' },
|
|
|
{ label: '数量', value: '5' },
|
|
|
- { label: '速度', value: '35 m/s' },
|
|
|
+ { label: '速度', value: '350m/s' },
|
|
|
{ label: '高度', value: '2000米' },
|
|
|
- { label: '数据链路', value: '未知' }
|
|
|
+ { label: '机动能力', value: '高' },
|
|
|
+ { label: '雷达反射面积', value: '0.1-5㎡' },
|
|
|
+ { label: '数据链路', value: '可控' }
|
|
|
]
|
|
|
},
|
|
|
{
|
|
|
- id: 'command',
|
|
|
- label: '指挥中心',
|
|
|
- side: '目标',
|
|
|
- indicatorClass: 'blue',
|
|
|
+ id: 'redB',
|
|
|
+ label: '海上靶标B',
|
|
|
+ side: '',
|
|
|
+ indicatorClass: 'bg-red-500',
|
|
|
+ status: 'ready',
|
|
|
+ position: 'front',
|
|
|
+ notes: '',
|
|
|
details: [
|
|
|
- { label: '状态', value: '完好' },
|
|
|
- { label: '经度', value: 'E117°26\'38"' },
|
|
|
- { label: '纬度', value: 'N39°54\'15"' },
|
|
|
- { label: '防护等级', value: 'A级' },
|
|
|
- { label: '高度', value: '50米' },
|
|
|
- { label: '功率', value: '100%' },
|
|
|
- { label: '数据链路', value: '稳定' }
|
|
|
+ { label: '状态', value: '就绪' },
|
|
|
+ { label: '排水量', value: '500吨' },
|
|
|
+ { label: '速度', value: '30节' },
|
|
|
+ { label: '雷达反射面积', value: '500㎡' },
|
|
|
+ { label: '机动能力', value: '中' },
|
|
|
+ { label: '数据链路', value: '可控' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 'redC',
|
|
|
+ label: '地面靶标C',
|
|
|
+ side: '',
|
|
|
+ indicatorClass: 'bg-red-500',
|
|
|
+ status: 'standby',
|
|
|
+ position: 'front',
|
|
|
+ notes: '',
|
|
|
+ details: [
|
|
|
+ { label: '状态', value: '待命' },
|
|
|
+ { label: '类型', value: '固定建筑' },
|
|
|
+ { label: '尺寸', value: '50×30m' },
|
|
|
+ { label: '雷达反射面积', value: '1000㎡' },
|
|
|
+ { label: '防护等级', value: 'B级' },
|
|
|
+ { label: '数据链路', value: '可控' }
|
|
|
]
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
],
|
|
|
-
|
|
|
- // 选中的设备
|
|
|
- selectedDevice: {
|
|
|
- id: 1,
|
|
|
- name: '发烟罐烟幕生成模拟系统',
|
|
|
- type: 'interference',
|
|
|
- subType: 'optical',
|
|
|
- position: {x: 17, y: 72},
|
|
|
- status: '正常',
|
|
|
- details: {
|
|
|
- power: '220V',
|
|
|
- coverage: '500m²',
|
|
|
- duration: '30min',
|
|
|
- material: '环保烟雾剂'
|
|
|
- }
|
|
|
+ defaultProps: {
|
|
|
+ children: 'children',
|
|
|
+ label: 'label'
|
|
|
},
|
|
|
|
|
|
- devices: [
|
|
|
+ // 策略数据 - 更贴合想定编辑业务
|
|
|
+ strategies: [
|
|
|
{
|
|
|
id: 1,
|
|
|
- name: '发烟罐烟幕生成模拟系统',
|
|
|
- type: 'interference',
|
|
|
- subType: 'optical',
|
|
|
- position: {x: 17, y: 72},
|
|
|
- status: '正常',
|
|
|
- details: {
|
|
|
- power: '220V',
|
|
|
- coverage: '500m²',
|
|
|
- duration: '30min',
|
|
|
- material: '环保烟雾剂'
|
|
|
- }
|
|
|
+ name: '饱和攻击想定',
|
|
|
+ description: '集中优势火力,在短时间内发射大量导弹,形成饱和攻击态势,突破敌方防御系统',
|
|
|
+ icon: 'el-icon-swords'
|
|
|
},
|
|
|
{
|
|
|
id: 2,
|
|
|
- name: '726-4无源电子干扰系统',
|
|
|
- type: 'interference',
|
|
|
- subType: 'optical',
|
|
|
- position: {x: 40, y: 50},
|
|
|
- status: '警告',
|
|
|
- details: {
|
|
|
- frequency: '2.4GHz',
|
|
|
- range: '1km',
|
|
|
- battery: '80%',
|
|
|
- deploymentTime: '5min'
|
|
|
- }
|
|
|
+ name: '分层拦截想定',
|
|
|
+ description: '根据目标高度和距离,分层次部署防御力量,形成多层次拦截网,提高拦截成功率',
|
|
|
+ icon: 'el-icon-shield'
|
|
|
},
|
|
|
{
|
|
|
id: 3,
|
|
|
- name: '陆基雷达辐射源及有源诱饵干扰系统',
|
|
|
- type: 'interference',
|
|
|
- subType: 'electromagnetic',
|
|
|
- position: {x: 60, y: 43},
|
|
|
- status: '正常',
|
|
|
- details: {
|
|
|
- power: '380V',
|
|
|
- frequencyRange: '1-18GHz',
|
|
|
- responseTime: '<0.1s',
|
|
|
- channels: '8'
|
|
|
- }
|
|
|
+ name: '精确打击想定',
|
|
|
+ description: '利用高精度制导技术,对高价值目标实施精确打击,减少附带损伤,提高作战效能',
|
|
|
+ icon: 'el-icon-cross'
|
|
|
},
|
|
|
{
|
|
|
id: 4,
|
|
|
- name: '试验实况航拍无人机',
|
|
|
- type: 'measurement',
|
|
|
- subType: 'aerial',
|
|
|
- position: {x: 70, y: 70},
|
|
|
- status: '运行中',
|
|
|
- details: {
|
|
|
- altitude: '500m',
|
|
|
- speed: '60km/h',
|
|
|
- battery: '45%',
|
|
|
- resolution: '4K',
|
|
|
- model: 'DJI M300'
|
|
|
- }
|
|
|
+ name: '电子压制想定',
|
|
|
+ description: '先使用电子干扰装备压制敌方雷达和通信系统,再实施导弹打击,降低被拦截概率',
|
|
|
+ icon: 'el-icon-wifi'
|
|
|
},
|
|
|
{
|
|
|
id: 5,
|
|
|
- name: '导弹过靶高速摄录系统',
|
|
|
- type: 'measurement',
|
|
|
- subType: 'camera',
|
|
|
- position: {x: 30, y: 80},
|
|
|
- status: '待机',
|
|
|
- details: {
|
|
|
- frameRate: '1000fps',
|
|
|
- resolution: '1080p',
|
|
|
- storage: '2TB',
|
|
|
- triggerMode: '自动'
|
|
|
- }
|
|
|
- },
|
|
|
- {
|
|
|
- id: 6,
|
|
|
- name: '模拟机/油库',
|
|
|
- type: 'target',
|
|
|
- subType: 'structure',
|
|
|
- position: {x: 50, y: 40},
|
|
|
- status: '就绪',
|
|
|
- details: {
|
|
|
- size: '10m×15m',
|
|
|
- material: '复合材料',
|
|
|
- rcs: '5m²',
|
|
|
- heatSignature: '模拟'
|
|
|
- }
|
|
|
+ name: '机动突防想定',
|
|
|
+ description: '利用导弹机动能力和变轨技术,规避敌方防御系统,提高突防成功率',
|
|
|
+ icon: 'el-icon-refresh-left'
|
|
|
}
|
|
|
],
|
|
|
|
|
|
- deviceTypes: [
|
|
|
- {key: 'measurement', name: '测量设备'},
|
|
|
- {key: 'interference', name: '干扰设备'},
|
|
|
- {key: 'target', name: '靶标设备'}
|
|
|
- ],
|
|
|
-
|
|
|
- visibleDeviceTypes: {
|
|
|
- measurement: true,
|
|
|
- interference: true,
|
|
|
- target: true
|
|
|
- },
|
|
|
-
|
|
|
- selectedTarget: null,
|
|
|
- showPIP: true,
|
|
|
- compassAngle: 0,
|
|
|
- currentTime: new Date().toLocaleString(),
|
|
|
-
|
|
|
- operationInfo: {
|
|
|
- operationTime: '00:05:31.770',
|
|
|
- operationZeroTime: '08:00:00.000',
|
|
|
- remainingTime: '3494.0',
|
|
|
- projectileTargetDistance: '65485.33',
|
|
|
- altitude: '519.3',
|
|
|
- ballisticDeviation: '78.5',
|
|
|
- longitude: '98°26\'75\"E',
|
|
|
- latitude: '39°54\'15\"N',
|
|
|
- targetStatus: '锁定',
|
|
|
- windSpeed: '12.7',
|
|
|
- windDirection: '东北',
|
|
|
- visibility: '10.0',
|
|
|
- temperature: '25.5'
|
|
|
- },
|
|
|
-
|
|
|
- // 临机调整建议数据
|
|
|
- adjustmentAdvices: [
|
|
|
+ // 装备策略数据
|
|
|
+ equipmentStrategies: [
|
|
|
{
|
|
|
- content: '建议调整观测装置A1的监测角度,扩大西北方向的监测范围。',
|
|
|
- impact: '可提高对红方装备A集群的跟踪精度',
|
|
|
- timestamp: 'T+00:03:45',
|
|
|
- title: '观测角度调整建议',
|
|
|
- detailContent: '根据当前红方装备A集群的移动轨迹分析,建议将高空观测装置A1的监测角度向西偏转15度,扩大西北方向的监测范围,以确保持续跟踪目标。',
|
|
|
- parameters: {
|
|
|
- angle: { label: '偏转角度', value: '15° 向西' },
|
|
|
- range: { label: '监测范围', value: '扩大20%' }
|
|
|
+ id: 1,
|
|
|
+ equipment: '雷达干扰器D1',
|
|
|
+ strategy: 'auto',
|
|
|
+ options: [
|
|
|
+ { label: '自动干扰模式', value: 'auto' },
|
|
|
+ { label: '手动干扰模式', value: 'manual' },
|
|
|
+ { label: '前置干扰模式', value: 'preemptive' }
|
|
|
+ ],
|
|
|
+ params: {
|
|
|
+ priority: 5,
|
|
|
+ responseTime: 30
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
- content: '建议启动干扰装备D1,对红方通信频段进行干扰。',
|
|
|
- impact: '可降低红方集群协同作战能力',
|
|
|
- timestamp: 'T+00:04:10',
|
|
|
- title: '通信干扰建议',
|
|
|
- detailContent: '红方装备集群正处于通信频繁期,建议立即启动干扰装备D1,对其常用通信频段进行干扰,扰乱其指挥系统。',
|
|
|
- parameters: {
|
|
|
- device: { label: '干扰装备', value: 'D1' },
|
|
|
- frequency: { label: '干扰频段', value: '150-170MHz' },
|
|
|
- power: { label: '干扰功率', value: '80%' }
|
|
|
+ id: 2,
|
|
|
+ equipment: '高空观测装置A1',
|
|
|
+ strategy: 'track',
|
|
|
+ options: [
|
|
|
+ { label: '持续跟踪', value: 'track' },
|
|
|
+ { label: '重点跟踪', value: 'focus' },
|
|
|
+ { label: '扫描跟踪', value: 'scan' }
|
|
|
+ ],
|
|
|
+ params: {
|
|
|
+ priority: 3,
|
|
|
+ responseTime: 10
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
- content: '建议指挥中心提高防护等级,启动应急预案。',
|
|
|
- impact: '提高指挥中心生存能力',
|
|
|
- timestamp: 'T+00:04:50',
|
|
|
- title: '防护等级提升建议',
|
|
|
- detailContent: '鉴于红方装备集群接近,建议指挥中心立即提升防护等级至A级,启动全面应急预案,准备应对可能的攻击。',
|
|
|
- parameters: {
|
|
|
- level: { label: '防护等级', value: 'A级' },
|
|
|
- response: { label: '应急响应', value: '全面启动' }
|
|
|
+ id: 3,
|
|
|
+ equipment: '空中靶标A集群',
|
|
|
+ strategy: 'evade',
|
|
|
+ options: [
|
|
|
+ { label: '规避模式', value: 'evade' },
|
|
|
+ { label: '突防模式', value: 'penetrate' },
|
|
|
+ { label: '佯动模式', value: 'feint' }
|
|
|
+ ],
|
|
|
+ params: {
|
|
|
+ priority: 4,
|
|
|
+ responseTime: 5
|
|
|
}
|
|
|
}
|
|
|
],
|
|
|
|
|
|
- taskData: {
|
|
|
- schemeName: '2023年度东海靶场导弹测量保障方案',
|
|
|
- taskName: '东风-17导弹飞行轨迹测量任务',
|
|
|
- taskCode: 'DF17-2023-001',
|
|
|
- startTime: '2023-06-15 08:00:00',
|
|
|
- endTime: '2023-06-15 18:00:00',
|
|
|
- status: '进行中',
|
|
|
- securityLevel: '机密',
|
|
|
- securityYears: 10,
|
|
|
- taskBasis: '根据《XXXXX试验计划》和《XXXX靶场测量保障要求》开展本次测量任务',
|
|
|
- taskRequirements: '1. 全程跟踪dd飞行轨迹\n2. 记录关键节点数据\n3. 确保测量精度误差不超过0.5%\n4. 实时传输测量数据至指挥中心',
|
|
|
- blueSideRequirements: '1. 提供dd发射前30分钟预警\n2. 确保测量设备不受电子干扰\n3. 提供靶场安全区域坐标\n4. 配合完成测量数据校验'
|
|
|
- },
|
|
|
-
|
|
|
- targets: [
|
|
|
- {id: 1, name: '目标A', status: '已锁定', icon: 'el-icon-location'},
|
|
|
- {id: 2, name: '目标B', status: '跟踪中', icon: 'el-icon-location'},
|
|
|
- {id: 3, name: '目标C', status: '待确认', icon: 'el-icon-location'}
|
|
|
- ],
|
|
|
-
|
|
|
- mapControls: [
|
|
|
- {key: 'show-all', icon: 'el-icon-menu', tooltip: '显示所有层'},
|
|
|
- {key: 'observation', icon: 'el-icon-view', tooltip: '观测装置'},
|
|
|
- {key: 'interference', icon: 'el-icon-mobile', tooltip: '干扰装备'},
|
|
|
- {key: 'protection-target', icon: 'el-icon-location-outline', tooltip: '防护目标'},
|
|
|
- {key: 'red-equipment', icon: 'el-icon-aim', tooltip: '装备'},
|
|
|
- {key: 'fullscreen', icon: 'el-icon-refresh-left', tooltip: '全屏'},
|
|
|
- {key: 'reset', icon: 'el-icon-refresh', tooltip: '重置视图'},
|
|
|
- {key: 'zoom-in', icon: 'el-icon-plus', tooltip: '放大'},
|
|
|
- {key: 'zoom-out', icon: 'el-icon-minus', tooltip: '缩小'},
|
|
|
- {key: 'hide-path', icon: 'el-icon-truck', tooltip: '隐藏路径'},
|
|
|
- {key: 'hide-coverage', icon: 'el-icon-map-location', tooltip: '隐藏覆盖范围'},
|
|
|
- {key: 'hide-effects', icon: 'el-icon-lightning', tooltip: '隐藏交战效果'},
|
|
|
- {key: 'normal-view', icon: 'el-icon-picture-outline', tooltip: '普通视图'}
|
|
|
- ],
|
|
|
-
|
|
|
- schemeData: {
|
|
|
- interference: {
|
|
|
- name: '2023年某靶场光电对抗干扰保障方案',
|
|
|
- taskRequirements: '1. 对来袭目标实施有效光电干扰\n2. 确保干扰成功率不低于95%\n3. 干扰持续时间不少于30分钟\n4. 不影响己方设备正常工作',
|
|
|
- equipmentName: '发烟罐烟幕生成模拟系统、726-4无源电子干扰系统',
|
|
|
- equipmentCount: '3套',
|
|
|
- overview: '本方案针对东海靶场试验任务,部署多层次光电对抗干扰系统,形成立体干扰网,有效屏蔽敌方光电探测设备,掩护我方目标安全。'
|
|
|
+ // 时间轴事件数据
|
|
|
+ events: [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ title: '观测装置部署完成',
|
|
|
+ time: 'T-00:05:00',
|
|
|
+ description: '完成高空观测装置A1、地面观测装置B2和移动观测装置C3的部署。',
|
|
|
+ status: '覆盖率: 92%',
|
|
|
+ dotClass: 'info',
|
|
|
+ position: 10
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ title: '干扰装备启动',
|
|
|
+ time: 'T-00:02:30',
|
|
|
+ description: '干扰装备D1和E2开始启动,进入待命状态。',
|
|
|
+ status: '功率: 60%',
|
|
|
+ dotClass: 'info',
|
|
|
+ position: 30
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 3,
|
|
|
+ title: '靶标装备就位',
|
|
|
+ time: 'T+00:00:00',
|
|
|
+ description: '所有靶标装备到达指定位置,准备就绪。',
|
|
|
+ status: '全部就位',
|
|
|
+ dotClass: 'warning',
|
|
|
+ position: 50
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ title: '导弹准备发射',
|
|
|
+ time: 'T+00:01:45',
|
|
|
+ description: '导弹系统进入发射准备阶段,各项参数检查中。',
|
|
|
+ status: '准备中...',
|
|
|
+ dotClass: 'warning',
|
|
|
+ position: 70
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 5,
|
|
|
+ title: '试验开始',
|
|
|
+ time: 'T+00:03:20',
|
|
|
+ description: '导弹发射,测量系统开始记录数据,干扰系统启动。',
|
|
|
+ status: '进行中',
|
|
|
+ dotClass: 'danger',
|
|
|
+ position: 90
|
|
|
},
|
|
|
- measurement: {
|
|
|
- name: '2023年度东海靶场测量保障方案',
|
|
|
- taskRequirements: '1. 全程跟踪导弹飞行轨迹\n2. 记录关键节点数据\n3. 确保测量精度误差不超过0.5%\n4. 实时传输测量数据至指挥中心',
|
|
|
- equipmentName: '试验实况航拍无人机、导弹过靶高速摄录系统',
|
|
|
- equipmentCount: '2套',
|
|
|
- overview: '本方案部署高精度测量设备,构建全方位测量网络,确保对试验全程进行精确测量和记录,为试验评估提供可靠数据支撑。'
|
|
|
+ {
|
|
|
+ id: 6,
|
|
|
+ title: '数据回收分析',
|
|
|
+ time: 'T+00:10:00',
|
|
|
+ description: '试验数据开始回收,初步分析系统启动。',
|
|
|
+ status: '分析中',
|
|
|
+ dotClass: 'info',
|
|
|
+ position: 110
|
|
|
}
|
|
|
- },
|
|
|
+ ],
|
|
|
|
|
|
- selectedSchemeType: 'interference',
|
|
|
-
|
|
|
- // 第三个视图(now)的实时数据
|
|
|
- realtimeData: {
|
|
|
- targetCount: 8,
|
|
|
- lockedTargets: 3,
|
|
|
- threatLevel: '中等',
|
|
|
- updateTime: new Date().toLocaleTimeString(),
|
|
|
- alarmEnabled: true,
|
|
|
- equipmentStatus: [
|
|
|
- { id: 1, name: '雷达系统', status: 'normal', statusText: '正常运行' },
|
|
|
- { id: 2, name: '干扰装置', status: 'warning', statusText: '功率偏低' },
|
|
|
- { id: 3, name: '通信系统', status: 'normal', statusText: '正常运行' },
|
|
|
- { id: 4, name: '监控设备', status: 'error', statusText: '部分离线' }
|
|
|
- ],
|
|
|
- recentLogs: [
|
|
|
- { id: 1, time: '10:23:45', content: '目标T-7进入警戒区域' },
|
|
|
- { id: 2, time: '10:22:18', content: '干扰装置D1功率调整至80%' },
|
|
|
- { id: 3, time: '10:21:05', content: '成功锁定目标T-5、T-6、T-7' },
|
|
|
- { id: 4, time: '10:20:33', content: '雷达系统完成自检' }
|
|
|
- ]
|
|
|
+ // 其他状态
|
|
|
+ showTargetDialog: false,
|
|
|
+ targetForm: {
|
|
|
+ name: '',
|
|
|
+ type: '',
|
|
|
+ coordinates: '',
|
|
|
+ threatLevel: 3,
|
|
|
+ equipmentId: ''
|
|
|
},
|
|
|
-
|
|
|
- // 选中的实时目标
|
|
|
- selectedRealtimeTarget: null
|
|
|
- }
|
|
|
- },
|
|
|
- computed: {
|
|
|
- //计算右侧图片数据
|
|
|
- currentImageList(){
|
|
|
- if(this.currentView === 'before'){
|
|
|
- return this.views;
|
|
|
- }else if(this.currentView === 'now') {
|
|
|
- return this.whenFight;
|
|
|
+ selectedStrategy: null,
|
|
|
+ selectedEquipment: null,
|
|
|
+
|
|
|
+ // 时间轴点颜色映射(大屏高对比度)
|
|
|
+ dotClassMap: {
|
|
|
+ info: 'bg-blue-500', // 信息蓝
|
|
|
+ warning: 'bg-yellow-500', // 警告黄
|
|
|
+ danger: 'bg-red-500' // 危险红
|
|
|
+ },
|
|
|
+ // 状态标签样式映射
|
|
|
+ statusClassMap: {
|
|
|
+ info: 'bg-blue-900/50 text-blue-300',
|
|
|
+ warning: 'bg-yellow-900/50 text-yellow-300',
|
|
|
+ danger: 'bg-red-900/50 text-red-300'
|
|
|
}
|
|
|
- },
|
|
|
- filteredDevices() {
|
|
|
- return this.devices.filter(device => this.visibleDeviceTypes[device.type]);
|
|
|
- },
|
|
|
- selectedScheme() {
|
|
|
- return this.schemeData[this.selectedSchemeType];
|
|
|
}
|
|
|
},
|
|
|
- methods: {
|
|
|
- // 获取切换按钮的图标
|
|
|
- getToggleIcon() {
|
|
|
- switch(this.currentView) {
|
|
|
- case 'before':
|
|
|
- return 'el-icon-arrow-right';
|
|
|
- case 'model':
|
|
|
- return 'el-icon-arrow-right';
|
|
|
- case 'now':
|
|
|
- return 'el-icon-arrow-left';
|
|
|
- default:
|
|
|
- return 'el-icon-arrow-right';
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 获取切换按钮的文本
|
|
|
- getToggleText() {
|
|
|
- switch(this.currentView) {
|
|
|
- case 'before':
|
|
|
- return '切换到模型视图';
|
|
|
- case 'model':
|
|
|
- return '切换到实时视图';
|
|
|
- case 'now':
|
|
|
- return '切换到初始视图';
|
|
|
- default:
|
|
|
- return '切换视图';
|
|
|
- }
|
|
|
- },
|
|
|
+ computed: {
|
|
|
+ totalEquipment() {
|
|
|
+ // 计算所有装备的总数
|
|
|
+ let count = 0;
|
|
|
|
|
|
- // 处理视图切换
|
|
|
- handleViewToggle() {
|
|
|
- // 循环切换视图:before → model → now → before...
|
|
|
- switch(this.currentView) {
|
|
|
- case 'before':
|
|
|
- this.currentView = 'model';
|
|
|
- break;
|
|
|
- case 'model':
|
|
|
- this.currentView = 'now';
|
|
|
- break;
|
|
|
- case 'now':
|
|
|
- this.currentView = 'before';
|
|
|
- break;
|
|
|
- default:
|
|
|
- this.currentView = 'before';
|
|
|
- }
|
|
|
- },
|
|
|
+ this.equipmentTree.forEach(category => {
|
|
|
+ if (category.children && category.children.length) {
|
|
|
+ count += category.children.length;
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- // 视角图片点击处理
|
|
|
- handleImageClick(imgSrc) {
|
|
|
- this.pipImage = imgSrc;
|
|
|
+ return count;
|
|
|
},
|
|
|
+ allEquipment() {
|
|
|
+ // 提取所有装备列表
|
|
|
+ let equipment = [];
|
|
|
|
|
|
- // 线切换处理
|
|
|
- toggleLine(type) {
|
|
|
- if (type === 'red') {
|
|
|
- this.showRedLine = !this.showRedLine;
|
|
|
- } else {
|
|
|
- this.showBlueLine = !this.showBlueLine;
|
|
|
- }
|
|
|
- },
|
|
|
+ this.equipmentTree.forEach(category => {
|
|
|
+ if (category.children && category.children.length) {
|
|
|
+ equipment = [...equipment, ...category.children];
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- // 事件进度控制
|
|
|
- jumpToEvent(index) {
|
|
|
- this.currentEventIndex = index;
|
|
|
+ return equipment;
|
|
|
},
|
|
|
-
|
|
|
- // 处理方案类型变化
|
|
|
- onSchemeTypeChange(type) {
|
|
|
- console.log('当前选中的方案类型:', type);
|
|
|
+ sortedEvents() {
|
|
|
+ // 按时间排序事件,从T0开始递增
|
|
|
+ return [...this.events].sort((a, b) => {
|
|
|
+ // 解析时间格式为秒数以便比较
|
|
|
+ const getSeconds = (timeStr) => {
|
|
|
+ const sign = timeStr.startsWith('T+') ? 1 : -1;
|
|
|
+ const timePart = timeStr.substring(2);
|
|
|
+ const [hours, minutes, seconds] = timePart.split(':').map(Number);
|
|
|
+ return sign * (hours * 3600 + minutes * 60 + seconds);
|
|
|
+ };
|
|
|
+
|
|
|
+ return getSeconds(a.time) - getSeconds(b.time);
|
|
|
+ });
|
|
|
},
|
|
|
-
|
|
|
- selectDevice(device) {
|
|
|
- this.selectedDevice = device;
|
|
|
+ taskTypeName() {
|
|
|
+ const typeMap = {
|
|
|
+ 'air-defense': '防空作战',
|
|
|
+ 'sea-combat': '对海作战',
|
|
|
+ 'ground-strike': '对地打击',
|
|
|
+ 'electronic-warfare': '电子对抗'
|
|
|
+ };
|
|
|
+ return typeMap[this.taskForm.type] || '未设置';
|
|
|
},
|
|
|
-
|
|
|
- getStatusTagType(status) {
|
|
|
- const map = {
|
|
|
- '正常': 'success',
|
|
|
- '警告': 'warning',
|
|
|
- '故障': 'danger',
|
|
|
- '运行中': 'primary',
|
|
|
- '待机': 'info',
|
|
|
- '就绪': 'success'
|
|
|
+ taskCategoryName() {
|
|
|
+ const categoryMap = {
|
|
|
+ 'support': '保障任务',
|
|
|
+ 'combat': '实战任务'
|
|
|
};
|
|
|
- return map[status] || 'info';
|
|
|
+ return categoryMap[this.taskForm.category] || '未设置';
|
|
|
},
|
|
|
-
|
|
|
- getDeviceTypeName(type) {
|
|
|
- const map = {
|
|
|
- 'measurement': '测量设备',
|
|
|
- 'interference': '干扰设备',
|
|
|
- 'target': '靶标设备'
|
|
|
+ missileTypeName() {
|
|
|
+ const missileTypeMap = {
|
|
|
+ 'surface-to-air': '地空导弹',
|
|
|
+ 'air-to-surface': '空地导弹',
|
|
|
+ 'anti-ship': '反舰导弹',
|
|
|
+ 'cruise': '巡航导弹'
|
|
|
};
|
|
|
- return map[type] || type;
|
|
|
+ return missileTypeMap[this.taskForm.missileType] || '';
|
|
|
},
|
|
|
-
|
|
|
- linkToPage() {
|
|
|
- this.$router.push('/showSituation/before')
|
|
|
+ canAddMoreTargets() {
|
|
|
+ // 控制是否可以添加更多目标
|
|
|
+ return this.taskForm.missileCount > 0 && this.taskForm.targets.length < this.taskForm.missileCount * 2;
|
|
|
},
|
|
|
-
|
|
|
- toggleDeviceVisibility(type) {
|
|
|
- this.visibleDeviceTypes[type] = !this.visibleDeviceTypes[type];
|
|
|
+ // 根据导弹类型判断允许的目标类型
|
|
|
+ isAirTargetAllowed() {
|
|
|
+ return ['surface-to-air', 'air-to-surface', 'cruise'].includes(this.taskForm.missileType);
|
|
|
},
|
|
|
-
|
|
|
- handleMapControl(key) {
|
|
|
- switch (key) {
|
|
|
- case 'zoom-in':
|
|
|
- console.log('放大地图');
|
|
|
- break;
|
|
|
- case 'zoom-out':
|
|
|
- console.log('缩小地图');
|
|
|
- break;
|
|
|
- case 'reset':
|
|
|
- console.log('重置视图');
|
|
|
- break;
|
|
|
- case 'fullscreen':
|
|
|
- console.log('切换全屏');
|
|
|
- break;
|
|
|
- case 'show-all':
|
|
|
- console.log('显示所有层');
|
|
|
- break;
|
|
|
- case 'observation':
|
|
|
- console.log('切换观测装置显示');
|
|
|
- break;
|
|
|
- case 'interference':
|
|
|
- console.log('切换干扰装备显示');
|
|
|
- break;
|
|
|
- case 'protection-target':
|
|
|
- console.log('切换防护目标显示');
|
|
|
- break;
|
|
|
- case 'red-equipment':
|
|
|
- console.log('切换装备显示');
|
|
|
- break;
|
|
|
- case 'hide-path':
|
|
|
- console.log('隐藏路径');
|
|
|
- break;
|
|
|
- case 'hide-coverage':
|
|
|
- console.log('隐藏覆盖范围');
|
|
|
- break;
|
|
|
- case 'hide-effects':
|
|
|
- console.log('隐藏交战效果');
|
|
|
- break;
|
|
|
- case 'normal-view':
|
|
|
- console.log('切换普通视图');
|
|
|
- break;
|
|
|
- default:
|
|
|
- console.log('未知控制按钮:', key);
|
|
|
- }
|
|
|
+ isSeaTargetAllowed() {
|
|
|
+ return ['anti-ship', 'cruise'].includes(this.taskForm.missileType);
|
|
|
},
|
|
|
-
|
|
|
- handleSchemeTypeChange(type) {
|
|
|
- this.selectedSchemeType = type;
|
|
|
+ isGroundTargetAllowed() {
|
|
|
+ return ['air-to-surface', 'cruise'].includes(this.taskForm.missileType);
|
|
|
},
|
|
|
+ formattedCountdown() {
|
|
|
+ // 计算倒计时
|
|
|
+ if (!this.taskForm.executeTime) return '未设置执行时间';
|
|
|
|
|
|
- // 处理临机调整建议发送
|
|
|
- handleSendToInterference(adjustment) {
|
|
|
- console.log('发送至干扰席:', adjustment);
|
|
|
- },
|
|
|
+ const executeTime = new Date(this.taskForm.executeTime).getTime();
|
|
|
+ const now = new Date().getTime();
|
|
|
+ const diff = executeTime - now;
|
|
|
|
|
|
- handleSendToMeasurement(adjustment) {
|
|
|
- console.log('发送至测量席:', adjustment);
|
|
|
- },
|
|
|
+ if (diff < 0) return '已过期';
|
|
|
|
|
|
- // 实时视图相关方法
|
|
|
- refreshRealtimeData() {
|
|
|
- // 模拟数据刷新
|
|
|
- this.realtimeData.updateTime = new Date().toLocaleTimeString();
|
|
|
- this.realtimeData.targetCount = Math.floor(Math.random() * 5) + 5;
|
|
|
- this.realtimeData.lockedTargets = Math.floor(Math.random() * this.realtimeData.targetCount);
|
|
|
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
|
+ const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
|
|
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
|
|
|
|
|
- // 随机改变一个设备状态
|
|
|
- const randomIndex = Math.floor(Math.random() * this.realtimeData.equipmentStatus.length);
|
|
|
- const statuses = ['normal', 'warning', 'error'];
|
|
|
- this.realtimeData.equipmentStatus[randomIndex].status = statuses[Math.floor(Math.random() * statuses.length)];
|
|
|
+ return `${days}天${hours}时${minutes}分后执行`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ startShow() {
|
|
|
+ this.$router.push('/Deduction/stratDeduction')
|
|
|
+ },
|
|
|
+ saveTask() {
|
|
|
+ this.$message.success('任务保存成功')
|
|
|
+ },
|
|
|
+ goBack(){
|
|
|
+ // 返回上一页逻辑
|
|
|
+ },
|
|
|
+ startSimulation() {
|
|
|
+ this.$message.info('开始任务推演...')
|
|
|
+ },
|
|
|
+ resetTask() {
|
|
|
+ this.$confirm('确定要重置任务配置吗?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ // 重置表单逻辑
|
|
|
+ this.$message.success('任务配置已重置');
|
|
|
+ }).catch(() => {
|
|
|
+ // 取消重置
|
|
|
+ });
|
|
|
+ },
|
|
|
+ addTarget() {
|
|
|
+ this.targetForm = {
|
|
|
+ name: '',
|
|
|
+ type: '',
|
|
|
+ coordinates: '',
|
|
|
+ threatLevel: 3,
|
|
|
+ equipmentId: ''
|
|
|
+ };
|
|
|
+ this.showTargetDialog = true;
|
|
|
+ },
|
|
|
+ confirmAddTarget() {
|
|
|
+ if (!this.targetForm.name || !this.targetForm.type || !this.targetForm.coordinates) {
|
|
|
+ this.$message.warning('请填写完整目标信息');
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // 添加新日志
|
|
|
- this.realtimeData.recentLogs.unshift({
|
|
|
+ this.taskForm.targets.push({
|
|
|
id: Date.now(),
|
|
|
- time: new Date().toLocaleTimeString(),
|
|
|
- content: '数据已刷新'
|
|
|
+ ...this.targetForm
|
|
|
});
|
|
|
|
|
|
- // 保持日志长度
|
|
|
- if (this.realtimeData.recentLogs.length > 5) {
|
|
|
- this.realtimeData.recentLogs.pop();
|
|
|
+ this.showTargetDialog = false;
|
|
|
+ this.$message.success('目标添加成功');
|
|
|
+ },
|
|
|
+ editTarget(target) {
|
|
|
+ this.targetForm = { ...target };
|
|
|
+ this.showTargetDialog = true;
|
|
|
+ },
|
|
|
+ removeTarget(target) {
|
|
|
+ this.$confirm(`确定要删除目标"${target.name}"吗?`, '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ this.taskForm.targets = this.taskForm.targets.filter(t => t.id !== target.id);
|
|
|
+ this.$message.success('目标已删除');
|
|
|
+ }).catch(() => {
|
|
|
+ // 取消删除
|
|
|
+ });
|
|
|
+ },
|
|
|
+ selectStrategy(strategy) {
|
|
|
+ this.selectedStrategy = strategy.id;
|
|
|
+ },
|
|
|
+ // 处理装备点击事件
|
|
|
+ handleEquipmentClick(data) {
|
|
|
+ // 只处理叶子节点(具体装备)
|
|
|
+ if (!data.children || data.children.length === 0) {
|
|
|
+ this.selectedEquipment = { ...data };
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
- startRecording() {
|
|
|
- console.log('开始录制实时数据');
|
|
|
- // 实际应用中这里会启动录制功能
|
|
|
+ // 更新装备状态
|
|
|
+ updateEquipmentStatus() {
|
|
|
+ this.updateEquipmentData();
|
|
|
+ },
|
|
|
+ // 更新装备位置
|
|
|
+ updateEquipmentPosition() {
|
|
|
+ this.updateEquipmentData();
|
|
|
+ },
|
|
|
+ // 更新装备备注
|
|
|
+ updateEquipmentNotes() {
|
|
|
+ this.updateEquipmentData();
|
|
|
},
|
|
|
+ // 更新树形结构中的装备数据
|
|
|
+ updateEquipmentData() {
|
|
|
+ if (!this.selectedEquipment) return;
|
|
|
+
|
|
|
+ const updateNode = (nodes) => {
|
|
|
+ for (let i = 0; i < nodes.length; i++) {
|
|
|
+ if (nodes[i].id === this.selectedEquipment.id) {
|
|
|
+ nodes[i] = { ...this.selectedEquipment };
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (nodes[i].children && nodes[i].children.length) {
|
|
|
+ if (updateNode(nodes[i].children)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ };
|
|
|
|
|
|
- toggleAlarm() {
|
|
|
- this.realtimeData.alarmEnabled = !this.realtimeData.alarmEnabled;
|
|
|
- console.log(`警报${this.realtimeData.alarmEnabled ? '已开启' : '已关闭'}`);
|
|
|
+ updateNode(this.equipmentTree);
|
|
|
+ },
|
|
|
+ // 更新目标关联的装备
|
|
|
+ updateTargetEquipment(targetId, equipmentId) {
|
|
|
+ const target = this.taskForm.targets.find(t => t.id === targetId);
|
|
|
+ if (target) {
|
|
|
+ target.equipmentId = equipmentId;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 根据导弹类型更新目标设置
|
|
|
+ updateTargetsByMissileType() {
|
|
|
+ // 根据选择的导弹类型过滤不兼容的目标
|
|
|
+ if (!this.taskForm.missileType) return;
|
|
|
+
|
|
|
+ const compatibleTypes = [];
|
|
|
+ if (this.isAirTargetAllowed) compatibleTypes.push('空中目标');
|
|
|
+ if (this.isSeaTargetAllowed) compatibleTypes.push('海上目标');
|
|
|
+ if (this.isGroundTargetAllowed) compatibleTypes.push('地面目标');
|
|
|
+
|
|
|
+ // 过滤不兼容的目标
|
|
|
+ this.taskForm.targets = this.taskForm.targets.filter(target =>
|
|
|
+ compatibleTypes.includes(target.type)
|
|
|
+ );
|
|
|
+
|
|
|
+ // 如果没有目标,自动创建一个兼容的目标
|
|
|
+ if (this.taskForm.targets.length === 0) {
|
|
|
+ this.taskForm.targets.push({
|
|
|
+ id: Date.now(),
|
|
|
+ name: `目标${compatibleTypes[0]}`,
|
|
|
+ type: compatibleTypes[0],
|
|
|
+ coordinates: '东经120°00′,北纬30°00′',
|
|
|
+ threatLevel: 3,
|
|
|
+ equipmentId: ''
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 根据导弹数量更新目标设置
|
|
|
+ updateTargetsByMissileCount() {
|
|
|
+ // 如果目标数量超过导弹数量的2倍,删除多余的目标
|
|
|
+ const maxTargets = this.taskForm.missileCount * 2;
|
|
|
+ if (this.taskForm.targets.length > maxTargets) {
|
|
|
+ this.taskForm.targets = this.taskForm.targets.slice(0, maxTargets);
|
|
|
+ this.$message.info(`目标数量已调整为${maxTargets}个(不超过导弹数量的2倍)`);
|
|
|
+ }
|
|
|
},
|
|
|
+ // 获取装备图标
|
|
|
+ getEquipmentIcon(data) {
|
|
|
+ // 判断是否为类别节点
|
|
|
+ if (data.children && data.children.length > 0) {
|
|
|
+ return 'el-icon-folder-opened';
|
|
|
+ }
|
|
|
|
|
|
- getThreatLevelClass() {
|
|
|
- switch(this.realtimeData.threatLevel) {
|
|
|
- case '低':
|
|
|
- return 'threat-low';
|
|
|
- case '中等':
|
|
|
- return 'threat-medium';
|
|
|
- case '高':
|
|
|
- return 'threat-high';
|
|
|
- default:
|
|
|
- return '';
|
|
|
+ // 根据装备类型返回不同图标
|
|
|
+ if (data.id.startsWith('A') || data.id.startsWith('B') || data.id.startsWith('C')) {
|
|
|
+ return 'el-icon-eye';
|
|
|
+ } else if (data.id.startsWith('D') || data.id.startsWith('E')) {
|
|
|
+ return 'el-icon-wifi';
|
|
|
+ } else if (data.id.startsWith('red')) {
|
|
|
+ return 'el-icon-target';
|
|
|
}
|
|
|
+
|
|
|
+ return 'el-icon-cpu';
|
|
|
+ },
|
|
|
+ // 更新时间显示
|
|
|
+ updateTime() {
|
|
|
+ const now = new Date();
|
|
|
+ this.天文时间 = now.toLocaleString('zh-CN', {
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit',
|
|
|
+ second: '2-digit',
|
|
|
+ hour12: false
|
|
|
+ }).replace(/\//g, '-');
|
|
|
+
|
|
|
+ // 模拟绝对时间(可以根据实际需求修改)
|
|
|
+ const epoch = new Date('2000-01-01T00:00:00Z');
|
|
|
+ const diff = Math.floor((now - epoch) / 1000);
|
|
|
+ this.绝对时间 = `J${diff}`;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ // 监听导弹类型变化,更新目标设置
|
|
|
+ 'taskForm.missileType': function() {
|
|
|
+ this.updateTargetsByMissileType();
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
|
- // 确保按钮初始状态是悬浮在左侧
|
|
|
- this.showToggleButton = false;
|
|
|
-
|
|
|
- // 更新当前时间
|
|
|
- setInterval(() => {
|
|
|
- this.currentTime = new Date().toLocaleString();
|
|
|
- }, 1000);
|
|
|
-
|
|
|
- // 罗盘旋转动画
|
|
|
- setInterval(() => {
|
|
|
- this.compassAngle = (this.compassAngle + 1) % 360;
|
|
|
- }, 1000);
|
|
|
-
|
|
|
- // 实时视图数据更新模拟
|
|
|
- const updateInterval = setInterval(() => {
|
|
|
- if (this.currentView === 'now') {
|
|
|
- this.realtimeData.updateTime = new Date().toLocaleTimeString();
|
|
|
- }
|
|
|
- }, 3000);
|
|
|
-
|
|
|
- // 组件销毁时清除定时器
|
|
|
- this.$on('hook:beforeDestroy', () => {
|
|
|
- clearInterval(updateInterval);
|
|
|
- });
|
|
|
+ // 初始化时间
|
|
|
+ this.updateTime();
|
|
|
+ // 每秒更新时间
|
|
|
+ setInterval(this.updateTime, 1000);
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-// 画面切换按钮样式
|
|
|
-.view-toggle-container {
|
|
|
- position: absolute;
|
|
|
- left: 0;
|
|
|
- top: 50%;
|
|
|
- transform: translateY(-50%);
|
|
|
- z-index: 1200;
|
|
|
- width: 30px; // 只显示按钮的一小部分宽度
|
|
|
- height: 100px;
|
|
|
+/* 军事风格大屏基础样式 - 深色背景,高对比度 */
|
|
|
+.task-setting-container {
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- overflow: visible;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100vh;
|
|
|
+ background-color: #050c1a; /* 深色军事背景 */
|
|
|
+ color: #e0f2fe; /* 主文本色 - 浅蓝色 */
|
|
|
+ font-family: "Microsoft YaHei", Arial, sans-serif;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
}
|
|
|
|
|
|
-.view-toggle-btn {
|
|
|
- width: 120px;
|
|
|
- height: 40px;
|
|
|
- background-color: rgba(37, 53, 68, 0.9);
|
|
|
- border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
- color: #ecf0f1;
|
|
|
- border-radius: 0 20px 20px 0;
|
|
|
- transition: all 0.3s ease-out; // 平滑过渡效果
|
|
|
- box-shadow: 2px 0 8px rgba(0, 0, 0, 0.3);
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 0;
|
|
|
+/* 军事网格背景 */
|
|
|
+.grid-bg {
|
|
|
position: absolute;
|
|
|
- left: -90px; // 默认只显示30px在外面
|
|
|
- opacity: 0.9;
|
|
|
-
|
|
|
- // 鼠标悬浮时完全显示
|
|
|
- &:hover {
|
|
|
- background-color: #253544;
|
|
|
- opacity: 1;
|
|
|
- box-shadow: 3px 0 12px rgba(0, 0, 0, 0.4);
|
|
|
- left: 0; // 完全显示
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-size: 40px 40px;
|
|
|
+ background-image:
|
|
|
+ linear-gradient(to right, rgba(14, 55, 107, 0.1) 1px, transparent 1px),
|
|
|
+ linear-gradient(to bottom, rgba(14, 55, 107, 0.1) 1px, transparent 1px);
|
|
|
+ pointer-events: none;
|
|
|
+ z-index: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 头部样式:军事风格 - 庄重威严 */
|
|
|
+.header {
|
|
|
+ flex: 0 0 60px;
|
|
|
+ background-color: #0f172a; /* 头部深色背景 */
|
|
|
+ background-image: linear-gradient(to right, #0f172a, #1e3a8a);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 0 20px;
|
|
|
+ justify-content: space-between;
|
|
|
+ border-bottom: 1px solid #0ea5e9;
|
|
|
+ box-shadow: 0 2px 10px rgba(14, 165, 233, 0.2);
|
|
|
+ position: relative;
|
|
|
+ z-index: 10;
|
|
|
+
|
|
|
+ .header-logo {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ h1 {
|
|
|
+ font-size: 1.5rem;
|
|
|
+ color: #bae6fd;
|
|
|
+ margin: 0;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-shadow: 0 0 5px rgba(14, 165, 233, 0.5);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- i {
|
|
|
- margin-right: 5px;
|
|
|
+ .header-time {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+ color: #93c5fd;
|
|
|
font-size: 14px;
|
|
|
+
|
|
|
+ .time-item {
|
|
|
+ padding: 5px 10px;
|
|
|
+ background-color: rgba(15, 23, 42, 0.7);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ border-radius: 3px;
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-/* 保留原有样式 */
|
|
|
-.situation-container {
|
|
|
- color: white;
|
|
|
- font-family: "Microsoft YaHei", Arial, sans-serif;
|
|
|
- height: 93vh;
|
|
|
+ .header-controls {
|
|
|
+ display: flex;
|
|
|
+ gap: 15px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.sidebar {
|
|
|
- background-color: #2c3e50;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- overflow-y: auto;
|
|
|
- padding: 15px;
|
|
|
-
|
|
|
- /* 自定义滚动条样式 */
|
|
|
- &::-webkit-scrollbar {
|
|
|
- width: 6px;
|
|
|
- }
|
|
|
+/* 军事风格按钮 */
|
|
|
+.btn军事 {
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.5) !important;
|
|
|
+ box-shadow: 0 0 5px rgba(14, 165, 233, 0.3);
|
|
|
|
|
|
- &::-webkit-scrollbar-track {
|
|
|
- background: #2c3e50;
|
|
|
- border-radius: 3px;
|
|
|
+ &:after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: -100%;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
|
|
+ transition: all 0.5s ease;
|
|
|
}
|
|
|
|
|
|
- &::-webkit-scrollbar-thumb {
|
|
|
- background: #253544;
|
|
|
- border-radius: 3px;
|
|
|
+ &:hover:after {
|
|
|
+ left: 100%;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- &::-webkit-scrollbar-thumb:hover {
|
|
|
- background: #253544;
|
|
|
- }
|
|
|
+/* 侧边栏装饰线 */
|
|
|
+.aside-border-decoration {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ right: 0;
|
|
|
+ width: 3px;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(to bottom,
|
|
|
+ rgba(14, 165, 233, 0) 0%,
|
|
|
+ rgba(14, 165, 233, 0.5) 50%,
|
|
|
+ rgba(14, 165, 233, 0) 100%);
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
|
|
|
- /* Firefox 滚动条样式 */
|
|
|
- scrollbar-width: thin;
|
|
|
- scrollbar-color: #253544 #2c3e50;
|
|
|
+/* 主区域装饰线 */
|
|
|
+.main-border-decoration {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 3px;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(to bottom,
|
|
|
+ rgba(14, 165, 233, 0) 0%,
|
|
|
+ rgba(14, 165, 233, 0.5) 50%,
|
|
|
+ rgba(14, 165, 233, 0) 100%);
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
|
|
|
- .sidebar-section {
|
|
|
- margin-bottom: 25px;
|
|
|
- background-color: rgba(0, 0, 0, 0.15);
|
|
|
- border-radius: 6px;
|
|
|
- padding: 15px;
|
|
|
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
|
+/* 左侧任务面板:军事风格分区明确 */
|
|
|
+.task-panel {
|
|
|
+ width: 100%;
|
|
|
+ background-color: rgba(15, 23, 42, 0.8);
|
|
|
+ backdrop-filter: blur(5px);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ border-right: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
|
|
|
+ .panel-header {
|
|
|
+ padding: 12px 15px;
|
|
|
+ border-bottom: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ flex-shrink: 0;
|
|
|
+ background-color: rgba(30, 58, 138, 0.6);
|
|
|
+ background-image: linear-gradient(to right, rgba(30, 58, 138, 0.8), rgba(15, 23, 42, 0.8));
|
|
|
|
|
|
h3 {
|
|
|
- color: #ecf0f1;
|
|
|
- margin-bottom: 15px;
|
|
|
+ color: #bae6fd;
|
|
|
font-size: 1rem;
|
|
|
- padding-bottom: 8px;
|
|
|
- border-bottom: 1px solid #34495e;
|
|
|
+ margin: 0;
|
|
|
+ font-weight: 500;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
-
|
|
|
- &:before {
|
|
|
- content: '';
|
|
|
- display: inline-block;
|
|
|
- width: 4px;
|
|
|
- height: 16px;
|
|
|
- background-color: #253544;
|
|
|
- margin-right: 8px;
|
|
|
- border-radius: 2px;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .info-list {
|
|
|
- .info-group {
|
|
|
- margin-bottom: 15px;
|
|
|
- padding-bottom: 10px;
|
|
|
- border-bottom: 1px dashed #34495e;
|
|
|
+ .task-content {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 15px;
|
|
|
+ min-height: 0;
|
|
|
|
|
|
- &:last-child {
|
|
|
- border-bottom: none;
|
|
|
- margin-bottom: 0;
|
|
|
- padding-bottom: 0;
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
}
|
|
|
- .info-item {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 8px 0;
|
|
|
-
|
|
|
- .info-label {
|
|
|
- color: #bdc3c7;
|
|
|
- font-size: 0.9rem;
|
|
|
- width: 45%;
|
|
|
- text-align: left;
|
|
|
- }
|
|
|
|
|
|
- .info-value {
|
|
|
- color: #ecf0f1;
|
|
|
- font-weight: bold;
|
|
|
- width: 55%;
|
|
|
- text-align: right;
|
|
|
- padding-left: 10px;
|
|
|
-
|
|
|
- &.status-locked {
|
|
|
- color: #2ecc71;
|
|
|
- }
|
|
|
-
|
|
|
- &.status-tracking {
|
|
|
- color: #3498db;
|
|
|
- }
|
|
|
-
|
|
|
- &.status-pending {
|
|
|
- color: #f39c12;
|
|
|
- }
|
|
|
-
|
|
|
- &.status-warning {
|
|
|
- color: #e67e22;
|
|
|
- }
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: rgba(15, 23, 42, 0.5);
|
|
|
}
|
|
|
- .task-info {
|
|
|
- padding: 8px 0;
|
|
|
-
|
|
|
- .task-info-label {
|
|
|
- color: #bdc3c7;
|
|
|
- font-size: 0.9rem;
|
|
|
- width: 45%;
|
|
|
- text-align: left;
|
|
|
- }
|
|
|
-
|
|
|
- .task-info-value {
|
|
|
- color: #ecf0f1;
|
|
|
- font-weight: bold;
|
|
|
- padding-top: 10px;
|
|
|
- white-space: pre-line;
|
|
|
-
|
|
|
- &.status-locked {
|
|
|
- color: #2ecc71;
|
|
|
- }
|
|
|
|
|
|
- &.status-tracking {
|
|
|
- color: #3498db;
|
|
|
- }
|
|
|
-
|
|
|
- &.status-pending {
|
|
|
- color: #f39c12;
|
|
|
- }
|
|
|
-
|
|
|
- &.status-warning {
|
|
|
- color: #e67e22;
|
|
|
- }
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background-color: rgba(59, 130, 246, 0.5);
|
|
|
+ border-radius: 3px;
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- .target-list {
|
|
|
- .target-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 10px;
|
|
|
- padding: 12px;
|
|
|
- border-radius: 4px;
|
|
|
- cursor: pointer;
|
|
|
- transition: background-color 0.3s;
|
|
|
- margin-bottom: 5px;
|
|
|
- background-color: rgba(0, 0, 0, 0.1);
|
|
|
-
|
|
|
- &:hover, &.active {
|
|
|
- background-color: #253544;
|
|
|
- }
|
|
|
-
|
|
|
- .target-icon {
|
|
|
- width: 32px;
|
|
|
- height: 32px;
|
|
|
- background-color: #34495e;
|
|
|
- border-radius: 50%;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- color: #253544;
|
|
|
- }
|
|
|
+/* 树形结构样式 */
|
|
|
+.equipment-tree {
|
|
|
+ max-height: 400px;
|
|
|
+ overflow-y: auto;
|
|
|
|
|
|
- .target-info {
|
|
|
- flex: 1;
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ }
|
|
|
|
|
|
- .target-name {
|
|
|
- font-weight: bold;
|
|
|
- color: #ecf0f1;
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: rgba(15, 23, 42, 0.5);
|
|
|
+ }
|
|
|
|
|
|
- .target-status {
|
|
|
- font-size: 0.8rem;
|
|
|
- color: #bdc3c7;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background-color: rgba(59, 130, 246, 0.5);
|
|
|
+ border-radius: 3px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.map-container {
|
|
|
- position: relative;
|
|
|
- background-color: #1e272e;
|
|
|
- overflow: hidden;
|
|
|
- padding: 0 !important;
|
|
|
- margin: 0 !important;
|
|
|
+.custom-tree-node {
|
|
|
+ width: 100%;
|
|
|
+ display: inline-block;
|
|
|
}
|
|
|
|
|
|
-.map-view-container {
|
|
|
- height: 100%;
|
|
|
- padding: 0 !important;
|
|
|
- margin: 0 !important;
|
|
|
+.tree-node-content {
|
|
|
+ width: 100%;
|
|
|
+ padding: 2px 0;
|
|
|
+ color: #e0f2fe;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #60a5fa;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.map-controls {
|
|
|
- position: absolute;
|
|
|
- top: 20px;
|
|
|
- right: 20px;
|
|
|
- z-index: 10;
|
|
|
+/* 中间策略区域:军事风格信息清晰 */
|
|
|
+.strategy-header {
|
|
|
+ background-color: rgba(30, 58, 138, 0.6);
|
|
|
+ background-image: linear-gradient(to right, rgba(30, 58, 138, 0.8), rgba(15, 23, 42, 0.8));
|
|
|
|
|
|
- .map-control-group {
|
|
|
- background-color: rgba(44, 62, 80, 0.8);
|
|
|
- border-radius: 4px;
|
|
|
- padding: 10px 10px 10px 0;
|
|
|
+ h3 {
|
|
|
+ color: #bae6fd;
|
|
|
+ margin: 0;
|
|
|
+ font-weight: 500;
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 5px;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- .map-control-btn {
|
|
|
- width: 36px;
|
|
|
- height: 36px;
|
|
|
- background-color: rgba(44, 62, 80, 0.7);
|
|
|
- border: none;
|
|
|
- color: white;
|
|
|
- cursor: pointer;
|
|
|
- transition: background-color 0.3s;
|
|
|
+.strategy-content-box {
|
|
|
+ background-color: rgba(5, 12, 26, 0.9);
|
|
|
+ min-height: 0;
|
|
|
|
|
|
- &:hover {
|
|
|
- background-color: #253544;
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
}
|
|
|
|
|
|
- .map-control-btn:first-child{
|
|
|
- margin-left: 10px;
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: rgba(15, 23, 42, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background-color: rgba(59, 130, 246, 0.5);
|
|
|
+ border-radius: 3px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.map-compass {
|
|
|
- position: absolute;
|
|
|
- top: 20px;
|
|
|
- left: 20px;
|
|
|
- width: 80px;
|
|
|
- height: 80px;
|
|
|
- background-color: rgba(44, 62, 80, 0.7);
|
|
|
- border-radius: 50%;
|
|
|
+/* 右侧预览面板:军事风格数据突出 */
|
|
|
+.preview-panel {
|
|
|
+ width: 100%;
|
|
|
+ background-color: rgba(15, 23, 42, 0.8);
|
|
|
+ backdrop-filter: blur(5px);
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- z-index: 5;
|
|
|
-
|
|
|
- .compass-inner {
|
|
|
- width: 60px;
|
|
|
- height: 60px;
|
|
|
- border-radius: 50%;
|
|
|
- border: 1px solid rgba(255, 255, 255, 0.3);
|
|
|
- position: relative;
|
|
|
+ flex-direction: column;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
+ border-left: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
+
|
|
|
+ .panel-header {
|
|
|
+ padding: 12px 15px;
|
|
|
+ border-bottom: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ flex-shrink: 0;
|
|
|
+ background-color: rgba(30, 58, 138, 0.6);
|
|
|
+ background-image: linear-gradient(to right, rgba(30, 58, 138, 0.8), rgba(15, 23, 42, 0.8));
|
|
|
}
|
|
|
|
|
|
- .compass-needle {
|
|
|
- position: absolute;
|
|
|
- top: 5px;
|
|
|
- left: 29px;
|
|
|
- width: 2px;
|
|
|
- height: 25px;
|
|
|
- background: linear-gradient(to bottom, #e74c3c 0%, #e74c3c 50%, #ecf0f1 50%, #ecf0f1 100%);
|
|
|
- transform-origin: bottom center;
|
|
|
- }
|
|
|
+ .preview-content {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ min-height: 0;
|
|
|
|
|
|
- .compass-direction {
|
|
|
- position: absolute;
|
|
|
- font-size: 10px;
|
|
|
- font-weight: bold;
|
|
|
- color: #ecf0f1;
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ }
|
|
|
|
|
|
- .compass-n {
|
|
|
- top: 5px;
|
|
|
- left: 27px;
|
|
|
- }
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: rgba(15, 23, 42, 0.5);
|
|
|
+ }
|
|
|
|
|
|
- .compass-e {
|
|
|
- top: 25px;
|
|
|
- right: 5px;
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background-color: rgba(59, 130, 246, 0.5);
|
|
|
+ border-radius: 3px;
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+/* 通用模块样式:军事风格简洁 */
|
|
|
+.section-card {
|
|
|
+ background-color: rgba(15, 23, 42, 0.7);
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
|
|
|
+ transition: all 0.3s ease;
|
|
|
|
|
|
- .compass-s {
|
|
|
- bottom: 5px;
|
|
|
- left: 27px;
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 3px 15px rgba(14, 165, 233, 0.2);
|
|
|
+ border-color: rgba(14, 165, 233, 0.5);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+.section-header {
|
|
|
+ background-color: rgba(30, 58, 138, 0.5);
|
|
|
+ padding: 8px 15px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ border-bottom: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
|
|
|
- .compass-w {
|
|
|
- top: 25px;
|
|
|
- left: 5px;
|
|
|
+ .section-title {
|
|
|
+ color: #bae6fd;
|
|
|
+ font-size: 14px;
|
|
|
+ margin: 0;
|
|
|
+ font-weight: 500;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.map-view {
|
|
|
+/* 表单样式:军事风格简洁易读 */
|
|
|
+.el-input__inner,
|
|
|
+.el-textarea__inner,
|
|
|
+.el-select .el-input__inner {
|
|
|
+ background-color: rgba(15, 23, 42, 0.8);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ color: #e0f2fe;
|
|
|
width: 100%;
|
|
|
- height: 100%;
|
|
|
- position: relative;
|
|
|
- overflow: hidden;
|
|
|
+ border-radius: 3px;
|
|
|
+ height: 32px;
|
|
|
+ font-size: 14px;
|
|
|
|
|
|
- .map-grid {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- background-image: linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
|
|
|
- linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
|
|
|
- background-size: 50px 50px;
|
|
|
- pointer-events: none;
|
|
|
- opacity: 0.5;
|
|
|
- z-index: 1;
|
|
|
+ &:focus {
|
|
|
+ border-color: #3b82f6;
|
|
|
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
|
}
|
|
|
|
|
|
- .map-image {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- object-fit: cover;
|
|
|
- z-index: 2;
|
|
|
+ &::placeholder {
|
|
|
+ color: #64748b;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- .pip-container {
|
|
|
- position: absolute;
|
|
|
- top: 20px;
|
|
|
- right: 10%;
|
|
|
- width: 200px;
|
|
|
- height: auto;
|
|
|
- z-index: 10;
|
|
|
- transform: scale(0.6);
|
|
|
- transform-origin: top right;
|
|
|
- border: 2px solid rgba(255, 255, 255, 0.3);
|
|
|
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
|
|
- background-color: rgba(0, 0, 0, 0.5);
|
|
|
-
|
|
|
- .view-label {
|
|
|
- position: absolute;
|
|
|
- top: 5px;
|
|
|
- left: 5px;
|
|
|
- background-color: rgba(0, 0, 0, 0.7);
|
|
|
- color: #fff;
|
|
|
- font-size: 0.7rem;
|
|
|
- padding: 2px 6px;
|
|
|
- border-radius: 2px;
|
|
|
- z-index: 2;
|
|
|
- white-space: nowrap;
|
|
|
+.el-textarea__inner {
|
|
|
+ min-height: 80px !important;
|
|
|
+ height: auto;
|
|
|
+ resize: vertical;
|
|
|
+}
|
|
|
+
|
|
|
+/* 下拉框样式:军事风格简洁 */
|
|
|
+::v-deep .el-select-dropdown {
|
|
|
+ background-color: rgba(15, 23, 42, 0.95);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ border-radius: 3px;
|
|
|
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
|
|
+
|
|
|
+ .el-select-dropdown__item {
|
|
|
+ color: #e0f2fe;
|
|
|
+ padding: 8px 16px;
|
|
|
+ font-size: 14px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(30, 58, 138, 0.5);
|
|
|
}
|
|
|
|
|
|
- .pip-image {
|
|
|
- width: 100%;
|
|
|
- height: auto;
|
|
|
- display: block;
|
|
|
- opacity: 0.5;
|
|
|
- transition: opacity 0.3s;
|
|
|
+ &.selected {
|
|
|
+ background-color: rgba(59, 130, 246, 0.5);
|
|
|
+ color: white;
|
|
|
}
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 输入框数字控件样式:军事风格简洁 */
|
|
|
+::v-deep .el-input-number {
|
|
|
+ .el-input-number__decrease,
|
|
|
+ .el-input-number__increase {
|
|
|
+ background-color: rgba(30, 58, 138, 0.5);
|
|
|
+ border-color: rgba(14, 165, 233, 0.3);
|
|
|
+ color: #e0f2fe;
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
|
|
|
- &:hover .pip-image {
|
|
|
- opacity: 1;
|
|
|
- transform: scale(2) translate(-20%, 20%);
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(30, 58, 138, 0.8);
|
|
|
+ color: white;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.right-panel {
|
|
|
- background-color: #2c3e50;
|
|
|
- overflow-y: auto;
|
|
|
- padding: 15px;
|
|
|
+/* 目标项样式:军事风格清晰 */
|
|
|
+.target-item {
|
|
|
+ background-color: rgba(15, 23, 42, 0.6);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
+ border-radius: 3px;
|
|
|
+ transition: all 0.2s;
|
|
|
|
|
|
- /* 自定义滚动条样式 */
|
|
|
- &::-webkit-scrollbar {
|
|
|
- width: 6px;
|
|
|
+ &:hover {
|
|
|
+ border-color: rgba(14, 165, 233, 0.5);
|
|
|
+ background-color: rgba(15, 23, 42, 0.8);
|
|
|
}
|
|
|
|
|
|
- &::-webkit-scrollbar-track {
|
|
|
- background: #2c3e50;
|
|
|
- border-radius: 3px;
|
|
|
+ .target-name {
|
|
|
+ color: #bae6fd;
|
|
|
}
|
|
|
|
|
|
- &::-webkit-scrollbar-thumb {
|
|
|
- background: #253544;
|
|
|
- border-radius: 3px;
|
|
|
+ .target-type {
|
|
|
+ color: #60a5fa;
|
|
|
}
|
|
|
|
|
|
- &::-webkit-scrollbar-thumb:hover {
|
|
|
- background: #253544;
|
|
|
+ .target-coord {
|
|
|
+ color: #94a3b8;
|
|
|
}
|
|
|
- /* Firefox 滚动条样式 */
|
|
|
- scrollbar-width: thin;
|
|
|
- scrollbar-color: #253544 #2c3e50;
|
|
|
|
|
|
- .panel-section {
|
|
|
- margin-bottom: 20px;
|
|
|
+ .target-threat {
|
|
|
+ color: #94a3b8;
|
|
|
|
|
|
- h3 {
|
|
|
- color: #ecf0f1;
|
|
|
- margin-bottom: 10px;
|
|
|
- font-size: 1rem;
|
|
|
+ .threat-bars {
|
|
|
+ height: 6px;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- .detail-content {
|
|
|
- .detail-item {
|
|
|
- padding: 8px 0;
|
|
|
- border-bottom: 1px solid #34495e;
|
|
|
|
|
|
- .detail-label {
|
|
|
- color: #bdc3c7;
|
|
|
- font-size: 0.9rem;
|
|
|
- }
|
|
|
+ .threat-bar {
|
|
|
+ width: 6px;
|
|
|
+ height: 100%;
|
|
|
+ background-color: rgba(100, 116, 139, 0.3);
|
|
|
+ border-radius: 1px;
|
|
|
|
|
|
- .detail-value {
|
|
|
- color: #ecf0f1;
|
|
|
- font-weight: bold;
|
|
|
- text-align: left;
|
|
|
- padding-top: 10px;
|
|
|
- white-space: pre-wrap;
|
|
|
- word-break: break-all;
|
|
|
+ &.active {
|
|
|
+ background-color: #f97316;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .log-list {
|
|
|
- .log-item {
|
|
|
- padding: 8px 0;
|
|
|
- border-bottom: 1px solid #34495e;
|
|
|
-
|
|
|
- .log-time {
|
|
|
- font-size: 0.8rem;
|
|
|
- color: #597A37;
|
|
|
- margin-bottom: 3px;
|
|
|
- }
|
|
|
-
|
|
|
- .log-content {
|
|
|
- color: #ecf0f1;
|
|
|
- font-size: 0.9rem;
|
|
|
- }
|
|
|
- }
|
|
|
+ .target-equipment {
|
|
|
+ margin-top: 4px;
|
|
|
+ padding-top: 4px;
|
|
|
+ border-top: 1px dashed rgba(14, 165, 233, 0.2);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*方案类型选择器样式*/
|
|
|
-.scheme-type-selector {
|
|
|
- margin-bottom: 20px;
|
|
|
- padding: 10px;
|
|
|
- background-color: rgba(0, 0, 0, 0.1);
|
|
|
- border-radius: 4px;
|
|
|
+.target-hint {
|
|
|
+ padding: 4px 6px;
|
|
|
+ border-radius: 3px;
|
|
|
+ background-color: rgba(15, 23, 42, 0.5);
|
|
|
+ border: 1px solid rgba(234, 179, 8, 0.3);
|
|
|
+}
|
|
|
|
|
|
- ::v-deep .el-radio-group {
|
|
|
- display: flex;
|
|
|
- justify-content: space-around;
|
|
|
- }
|
|
|
+/* 装备详情样式 */
|
|
|
+.equipment-detail {
|
|
|
+ background-color: rgba(15, 23, 42, 0.5);
|
|
|
+ border-radius: 3px;
|
|
|
+}
|
|
|
|
|
|
- ::v-deep .el-radio {
|
|
|
- color: #ecf0f1;
|
|
|
+.detail-item {
|
|
|
+ margin-bottom: 12px;
|
|
|
|
|
|
- &:hover {
|
|
|
- color: #597A37;
|
|
|
- }
|
|
|
+ .detail-label {
|
|
|
+ color: #94a3b8;
|
|
|
+ margin-bottom: 4px;
|
|
|
}
|
|
|
|
|
|
- ::v-deep .el-radio__input.is-checked .el-radio__inner {
|
|
|
- border-color: #597A37;
|
|
|
- background-color: #597A37;
|
|
|
+ .detail-value {
|
|
|
+ color: #e0f2fe;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- ::v-deep .el-radio__input.is-checked + .el-radio__label {
|
|
|
- color: #597A37;
|
|
|
- }
|
|
|
+/* 策略卡片样式:军事风格突出选择状态 */
|
|
|
+.strategy-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(3, 1fr);
|
|
|
+ gap: 15px;
|
|
|
}
|
|
|
|
|
|
-/*设备标记样式*/
|
|
|
-.device-marker {
|
|
|
- position: absolute;
|
|
|
- width: 12px;
|
|
|
- height: 12px;
|
|
|
- border-radius: 50%;
|
|
|
- transform: translate(-50%, -50%);
|
|
|
- z-index: 5;
|
|
|
- cursor: pointer;
|
|
|
+.strategy-card {
|
|
|
+ background-color: rgba(15, 23, 42, 0.6);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
+ border-radius: 3px;
|
|
|
transition: all 0.3s;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
|
|
|
- &.measurement {
|
|
|
- background-color: #3498db;
|
|
|
- box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.5);
|
|
|
+ &.selected {
|
|
|
+ border-color: #3b82f6;
|
|
|
+ background-color: rgba(30, 58, 138, 0.5);
|
|
|
+ box-shadow: 0 0 10px rgba(59, 130, 246, 0.3);
|
|
|
}
|
|
|
|
|
|
- &.interference {
|
|
|
- background-color: #e74c3c;
|
|
|
- box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.5);
|
|
|
+ &:hover {
|
|
|
+ border-color: rgba(14, 165, 233, 0.5);
|
|
|
+ transform: translateY(-2px);
|
|
|
}
|
|
|
|
|
|
- &.target {
|
|
|
- background-color: #2ecc71;
|
|
|
- box-shadow: 0 0 0 2px rgba(46, 204, 113, 0.5);
|
|
|
+ .strategy-icon {
|
|
|
+ background-color: rgba(30, 58, 138, 0.5);
|
|
|
+ color: #60a5fa;
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
}
|
|
|
|
|
|
- &:hover {
|
|
|
- transform: translate(-50%, -50%) scale(1.5);
|
|
|
-
|
|
|
- .device-label {
|
|
|
- display: block;
|
|
|
- }
|
|
|
+ .strategy-name {
|
|
|
+ color: #bae6fd;
|
|
|
}
|
|
|
|
|
|
- &.active {
|
|
|
- transform: translate(-50%, -50%) scale(2);
|
|
|
- z-index: 6;
|
|
|
-
|
|
|
- .device-label {
|
|
|
- display: block;
|
|
|
- }
|
|
|
+ .strategy-desc {
|
|
|
+ color: #94a3b8;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- // 干扰设备子类型
|
|
|
- &.optical {
|
|
|
- box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.7);
|
|
|
- }
|
|
|
+/* 装备策略项样式:军事风格清晰 */
|
|
|
+.equipment-strategy-item {
|
|
|
+ background-color: rgba(15, 23, 42, 0.6);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
+ border-radius: 3px;
|
|
|
+ transition: all 0.2s;
|
|
|
|
|
|
- &.electromagnetic {
|
|
|
- box-shadow: 0 0 0 3px rgba(155, 89, 182, 0.7);
|
|
|
+ &:hover {
|
|
|
+ border-color: rgba(14, 165, 233, 0.5);
|
|
|
}
|
|
|
|
|
|
- // 测量设备子类型
|
|
|
- &.aerial {
|
|
|
- box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.7);
|
|
|
+ .equipment-name {
|
|
|
+ color: #bae6fd;
|
|
|
}
|
|
|
|
|
|
- .device-label {
|
|
|
- position: absolute;
|
|
|
- top: 20px;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- background-color: rgba(0, 0, 0, 0.7);
|
|
|
- color: white;
|
|
|
- padding: 2px 8px;
|
|
|
- border-radius: 4px;
|
|
|
- font-size: 12px;
|
|
|
- white-space: nowrap;
|
|
|
- display: none;
|
|
|
- z-index: 10;
|
|
|
-
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: -5px;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- border-left: 5px solid transparent;
|
|
|
- border-right: 5px solid transparent;
|
|
|
- border-bottom: 5px solid rgba(0, 0, 0, 0.7);
|
|
|
- }
|
|
|
+ .strategy-params {
|
|
|
+ border-top-color: rgba(14, 165, 233, 0.2);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*右侧面板样式更新*/
|
|
|
-.detail-content {
|
|
|
- .detail-header {
|
|
|
- margin-bottom: 15px;
|
|
|
- padding-bottom: 10px;
|
|
|
- border-bottom: 1px solid #34495e;
|
|
|
+/* 任务概览样式:大屏横向展示 */
|
|
|
+.preview-section {
|
|
|
+ background-color: rgba(15, 23, 42, 0.7);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ border-radius: 3px;
|
|
|
+ overflow: hidden;
|
|
|
+ transition: all 0.3s;
|
|
|
|
|
|
- h4 {
|
|
|
- margin: 0;
|
|
|
- color: #ecf0f1;
|
|
|
- font-size: 1.1rem;
|
|
|
- }
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 3px 15px rgba(14, 165, 233, 0.1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*图例样式*/
|
|
|
-.map-legend {
|
|
|
- position: absolute;
|
|
|
- bottom: 20px;
|
|
|
- right: 20px;
|
|
|
- background-color: rgb(186 190 193 / 2%);
|
|
|
- border-radius: 4px;
|
|
|
- padding: 10px;
|
|
|
- z-index: 10;
|
|
|
- min-width: 150px;
|
|
|
-
|
|
|
- h4 {
|
|
|
- color: #ecf0f1;
|
|
|
- margin-bottom: 10px;
|
|
|
- font-size: 0.9rem;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
+.preview-section h4 {
|
|
|
+ color: #bae6fd;
|
|
|
+ border-bottom-color: rgba(14, 165, 233, 0.2);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
|
|
|
- .legend-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- padding: 5px 0;
|
|
|
- cursor: pointer;
|
|
|
- user-select: none;
|
|
|
+.overview-stats {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
|
|
|
- &:hover {
|
|
|
- background-color: rgba(255, 255, 255, 0.1);
|
|
|
- }
|
|
|
+.stat-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
|
|
|
- .legend-icon {
|
|
|
- display: inline-block;
|
|
|
- width: 12px;
|
|
|
- height: 12px;
|
|
|
- border-radius: 50%;
|
|
|
- margin-right: 8px;
|
|
|
+.stat-item {
|
|
|
+ flex: 1;
|
|
|
+ background-color: rgba(15, 23, 42, 0.6);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
+ border-radius: 3px;
|
|
|
+ transition: all 0.2s;
|
|
|
|
|
|
- &.measurement {
|
|
|
- background-color: #3498db;
|
|
|
- }
|
|
|
+ &:hover {
|
|
|
+ border-color: rgba(14, 165, 233, 0.5);
|
|
|
+ transform: translateY(-2px);
|
|
|
+ }
|
|
|
|
|
|
- &.interference {
|
|
|
- background-color: #e74c3c;
|
|
|
- }
|
|
|
+ .stat-label {
|
|
|
+ color: #94a3b8;
|
|
|
+ }
|
|
|
|
|
|
- &.target {
|
|
|
- background-color: #2ecc71;
|
|
|
- }
|
|
|
- }
|
|
|
+ .stat-value {
|
|
|
+ color: #60a5fa;
|
|
|
+ text-shadow: 0 0 5px rgba(59, 130, 246, 0.3);
|
|
|
+ }
|
|
|
|
|
|
- .el-checkbox {
|
|
|
- margin-left: auto;
|
|
|
- }
|
|
|
+ .stat-desc {
|
|
|
+ color: #64748b;
|
|
|
}
|
|
|
}
|
|
|
-.map-legend:hover {
|
|
|
- z-index: 300;
|
|
|
- background-color: rgba(44, 62, 80, 0.9);
|
|
|
-}
|
|
|
|
|
|
-/* 气象信息 */
|
|
|
-.weather-info {
|
|
|
- position: absolute;
|
|
|
- left: 15%;
|
|
|
- top: 0.3rem;
|
|
|
- z-index: 200;
|
|
|
+/* 时间轴样式:左侧有线,清晰表达时序 */
|
|
|
+.timeline-container {
|
|
|
+ padding-left: 10px;
|
|
|
}
|
|
|
|
|
|
-/* 第三个视图(now)样式 */
|
|
|
-.now-view-container {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 15px;
|
|
|
- padding: 10px;
|
|
|
- box-sizing: border-box;
|
|
|
- background-image: url("/img/zha2.png");
|
|
|
- background-repeat: no-repeat;
|
|
|
- background-size: 100% 100%;
|
|
|
+.timeline-line {
|
|
|
+ background-color: rgba(14, 165, 233, 0.3);
|
|
|
+ left: 8px;
|
|
|
}
|
|
|
|
|
|
-.now-view-title {
|
|
|
- color: #ecf0f1;
|
|
|
- margin: 0;
|
|
|
+.timeline-item {
|
|
|
+ position: relative;
|
|
|
+ transition: all 0.3s;
|
|
|
padding-bottom: 10px;
|
|
|
- border-bottom: 1px solid #34495e;
|
|
|
-}
|
|
|
|
|
|
-.realtime-data-panel {
|
|
|
- display: flex;
|
|
|
- gap: 15px;
|
|
|
- height: 200px;
|
|
|
+ &:hover {
|
|
|
+ transform: translateX(3px);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.data-card {
|
|
|
- flex: 1;
|
|
|
- background-color: rgba(44, 62, 80, 0.5);
|
|
|
- border-radius: 6px;
|
|
|
- padding: 15px;
|
|
|
- box-sizing: border-box;
|
|
|
+.timeline-content {
|
|
|
+ background-color: rgba(15, 23, 42, 0.6);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.2);
|
|
|
+ border-radius: 3px;
|
|
|
}
|
|
|
|
|
|
-.data-card h4 {
|
|
|
- color: #ecf0f1;
|
|
|
- margin-top: 0;
|
|
|
- margin-bottom: 15px;
|
|
|
- font-size: 0.9rem;
|
|
|
- padding-bottom: 5px;
|
|
|
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
|
+.timeline-time {
|
|
|
+ color: #60a5fa;
|
|
|
}
|
|
|
|
|
|
-.data-grid {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
- gap: 10px;
|
|
|
+.timeline-title {
|
|
|
+ color: #bae6fd;
|
|
|
}
|
|
|
|
|
|
-.data-item {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
+.timeline-description {
|
|
|
+ color: #94a3b8;
|
|
|
+ line-height: 1.5;
|
|
|
}
|
|
|
|
|
|
-.data-label {
|
|
|
- color: #bdc3c7;
|
|
|
- font-size: 0.8rem;
|
|
|
- margin-bottom: 5px;
|
|
|
+.timeline-dot {
|
|
|
+ box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.8);
|
|
|
}
|
|
|
|
|
|
-.data-value {
|
|
|
- color: #ecf0f1;
|
|
|
- font-weight: bold;
|
|
|
- font-size: 1.1rem;
|
|
|
-}
|
|
|
+/* 对话框样式:军事风格适配 */
|
|
|
+::v-deep .target-dialog, ::v-deep .equipment-dialog {
|
|
|
+ .el-dialog {
|
|
|
+ background-color: rgba(15, 23, 42, 0.95);
|
|
|
+ border: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
|
+ }
|
|
|
|
|
|
-.threat-low {
|
|
|
- color: #2ecc71;
|
|
|
-}
|
|
|
+ .el-dialog__header {
|
|
|
+ background-color: rgba(30, 58, 138, 0.6);
|
|
|
+ border-bottom: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
|
|
|
-.threat-medium {
|
|
|
- color: #f39c12;
|
|
|
-}
|
|
|
+ .el-dialog__title {
|
|
|
+ color: #bae6fd;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-.threat-high {
|
|
|
- color: #e74c3c;
|
|
|
-}
|
|
|
+ .el-dialog__body {
|
|
|
+ background-color: rgba(15, 23, 42, 0.95);
|
|
|
+ color: #e0f2fe;
|
|
|
+ }
|
|
|
|
|
|
-.equipment-status {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 8px;
|
|
|
+ .el-dialog__footer {
|
|
|
+ background-color: rgba(15, 23, 42, 0.95);
|
|
|
+ border-top: 1px solid rgba(14, 165, 233, 0.3);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.equipment-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
-}
|
|
|
+/* 按钮样式优化:军事风格突出 */
|
|
|
+::v-deep .el-button {
|
|
|
+ border-radius: 3px;
|
|
|
+ border: none;
|
|
|
|
|
|
-.equip-name {
|
|
|
- color: #ecf0f1;
|
|
|
- font-size: 0.9rem;
|
|
|
-}
|
|
|
+ &.el-button--primary {
|
|
|
+ background-color: #1e40af;
|
|
|
+ color: white;
|
|
|
|
|
|
-.status-indicator {
|
|
|
- width: 8px;
|
|
|
- height: 8px;
|
|
|
- border-radius: 50%;
|
|
|
- margin: 0 10px;
|
|
|
-}
|
|
|
+ &:hover {
|
|
|
+ background-color: #3b82f6;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-.status-indicator.normal {
|
|
|
- background-color: #2ecc71;
|
|
|
-}
|
|
|
+ &.el-button--success {
|
|
|
+ background-color: #065f46;
|
|
|
+ color: white;
|
|
|
|
|
|
-.status-indicator.warning {
|
|
|
- background-color: #f39c12;
|
|
|
-}
|
|
|
+ &:hover {
|
|
|
+ background-color: #16a34a;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-.status-indicator.error {
|
|
|
- background-color: #e74c3c;
|
|
|
-}
|
|
|
+ &.el-button--warning {
|
|
|
+ background-color: #92400e;
|
|
|
+ color: white;
|
|
|
|
|
|
-.equip-status {
|
|
|
- color: #bdc3c7;
|
|
|
- font-size: 0.8rem;
|
|
|
-}
|
|
|
+ &:hover {
|
|
|
+ background-color: #d97706;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-.realtime-map {
|
|
|
- flex: 1;
|
|
|
- position: relative;
|
|
|
- border-radius: 6px;
|
|
|
- overflow: hidden;
|
|
|
-}
|
|
|
+ &.el-button--text {
|
|
|
+ color: #94a3b8;
|
|
|
|
|
|
-.map-overlay {
|
|
|
- position: absolute;
|
|
|
- top: 10px;
|
|
|
- left: 10px;
|
|
|
- background-color: rgba(0, 0, 0, 0.7);
|
|
|
- color: white;
|
|
|
- padding: 3px 8px;
|
|
|
- border-radius: 3px;
|
|
|
- font-size: 0.8rem;
|
|
|
- z-index: 5;
|
|
|
+ &:hover {
|
|
|
+ color: #bae6fd;
|
|
|
+ background-color: rgba(148, 163, 184, 0.1);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.realtime-log {
|
|
|
- height: 150px;
|
|
|
- background-color: rgba(44, 62, 80, 0.5);
|
|
|
- border-radius: 6px;
|
|
|
- padding: 15px;
|
|
|
- box-sizing: border-box;
|
|
|
- overflow-y: auto;
|
|
|
-}
|
|
|
+/* 滑块样式:军事风格适配 */
|
|
|
+::v-deep .el-slider {
|
|
|
+ .el-slider__runway {
|
|
|
+ background-color: rgba(51, 65, 85, 0.5);
|
|
|
+ }
|
|
|
|
|
|
-.log-entry {
|
|
|
- margin-bottom: 10px;
|
|
|
- padding-bottom: 10px;
|
|
|
- border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
|
|
|
+ .el-slider__bar {
|
|
|
+ background-color: #3b82f6;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-slider__button {
|
|
|
+ border-color: #3b82f6;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.log-entry:last-child {
|
|
|
- margin-bottom: 0;
|
|
|
- padding-bottom: 0;
|
|
|
- border-bottom: none;
|
|
|
+/* 消息提示样式:军事风格适配 */
|
|
|
+::v-deep .el-message {
|
|
|
+ background-color: rgba(30, 58, 138, 0.8);
|
|
|
+ border-color: rgba(14, 165, 233, 0.3);
|
|
|
+ color: #e0f2fe;
|
|
|
}
|
|
|
|
|
|
-.log-time {
|
|
|
- color: #597A37;
|
|
|
- font-size: 0.8rem;
|
|
|
- margin-right: 10px;
|
|
|
+/* 确认框样式:军事风格适配 */
|
|
|
+::v-deep .el-dialog--confirm {
|
|
|
+ .el-dialog__body {
|
|
|
+ color: #e0f2fe;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.log-content {
|
|
|
- color: #ecf0f1;
|
|
|
- font-size: 0.9rem;
|
|
|
+/* 全局容器背景色确认 */
|
|
|
+::v-deep .el-container {
|
|
|
+ background: transparent;
|
|
|
}
|
|
|
|
|
|
-/* 实时视图右侧面板样式 */
|
|
|
-.now-right-panel {
|
|
|
- .operation-buttons {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 10px;
|
|
|
+/* 树形控件样式适配 */
|
|
|
+::v-deep .el-tree {
|
|
|
+ background-color: transparent;
|
|
|
+
|
|
|
+ .el-tree-node__content {
|
|
|
+ color: #e0f2fe;
|
|
|
+ height: 32px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(30, 58, 138, 0.3);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .target-details {
|
|
|
- margin-top: 10px;
|
|
|
+ .el-tree-node.is-current > .el-tree-node__content {
|
|
|
+ background-color: rgba(59, 130, 246, 0.2);
|
|
|
+ color: #60a5fa;
|
|
|
}
|
|
|
|
|
|
- .detail-item {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 8px 0;
|
|
|
- border-bottom: 1px solid #34495e;
|
|
|
+ .el-tree-node__expand-icon {
|
|
|
+ color: #94a3b8;
|
|
|
|
|
|
- .detail-label {
|
|
|
- color: #bdc3c7;
|
|
|
- font-size: 0.9rem;
|
|
|
+ &:hover {
|
|
|
+ color: #60a5fa;
|
|
|
}
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- .detail-value {
|
|
|
- color: #ecf0f1;
|
|
|
- font-weight: bold;
|
|
|
- }
|
|
|
+/* 大屏响应式优化 */
|
|
|
+@media (max-width: 1600px) {
|
|
|
+ .strategy-grid {
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- .no-selection {
|
|
|
- color: #bdc3c7;
|
|
|
- text-align: center;
|
|
|
- padding: 20px 0;
|
|
|
- font-style: italic;
|
|
|
+@media (max-width: 1200px) {
|
|
|
+ .strategy-grid {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
}
|
|
|
}
|
|
|
</style>
|