Merge branch 'dev' of http://222.212.85.86:8222/bdzl2/bxztApp into dev
This commit is contained in:
commit
6c56e0786a
@ -1,136 +0,0 @@
|
|||||||
# 🚀 快速开始指南
|
|
||||||
|
|
||||||
## ✅ 重构完成清单
|
|
||||||
|
|
||||||
- [x] 20 个 Vue 组件(模块化、语义化)
|
|
||||||
- [x] 3 个 Composables(状态管理)
|
|
||||||
- [x] 119 个图片资源(已复制并更新路径)
|
|
||||||
- [x] 公共样式和常量配置
|
|
||||||
- [x] 完整的项目文档
|
|
||||||
|
|
||||||
**总计:148 个文件,重构 100% 完成!** ✨
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 立即使用
|
|
||||||
|
|
||||||
### 1. 启动项目
|
|
||||||
```bash
|
|
||||||
cd bxztApp
|
|
||||||
pnpm dev:screen
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 添加路由(如果还未添加)
|
|
||||||
在路由配置文件中添加:
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
path: '/3d-situational-awareness',
|
|
||||||
component: () => import('@/views/3DSituationalAwarenessRefactor/index.vue')
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 访问页面
|
|
||||||
浏览器打开:`http://localhost:xxxx/3d-situational-awareness`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📂 核心文件位置
|
|
||||||
|
|
||||||
| 文件 | 路径 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| **主页面** | `index.vue` | 入口文件 |
|
|
||||||
| **左侧面板** | `components/LeftPanel/` | 5个组件 |
|
|
||||||
| **右侧面板** | `components/RightPanel/` | 5个组件 |
|
|
||||||
| **地图区域** | `components/MapViewer/` | 2个组件 |
|
|
||||||
| **公共组件** | `components/shared/` | 3个组件 |
|
|
||||||
| **状态管理** | `composables/` | 3个JS文件 |
|
|
||||||
| **图片资源** | `assets/images/` | 119个PNG |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 文档导航
|
|
||||||
|
|
||||||
1. **📖 完整项目说明**
|
|
||||||
→ `README.md`(组件使用、样式规范、开发指南)
|
|
||||||
|
|
||||||
2. **📊 重构总结报告**
|
|
||||||
→ `REFACTORING_SUMMARY.md`(对比分析、最佳实践)
|
|
||||||
|
|
||||||
3. **🖼️ 图片资源说明**
|
|
||||||
→ `assets/images/README.md`(图片使用方式)
|
|
||||||
|
|
||||||
4. **🗺️ 图片路径映射**
|
|
||||||
→ `assets/images/IMAGE_MAPPING.md`(文件名对照表)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔥 核心改进
|
|
||||||
|
|
||||||
| 指标 | 原始代码 | 重构后 |
|
|
||||||
|------|----------|---------|
|
|
||||||
| 文件数量 | 1个 | 148个 |
|
|
||||||
| 单文件行数 | 792行 | <200行 |
|
|
||||||
| 命名方式 | `group_1` | `DisasterAnalysis` |
|
|
||||||
| 响应式 | 固定像素 | vw/vh/fs |
|
|
||||||
| 可维护性 | ❌ 差 | ✅ 优秀 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚡ 快速定位问题
|
|
||||||
|
|
||||||
### 如果页面不显示
|
|
||||||
1. 检查路由配置是否正确
|
|
||||||
2. 确认图片路径是否正确
|
|
||||||
3. 查看浏览器控制台错误
|
|
||||||
|
|
||||||
### 如果图片不显示
|
|
||||||
1. 确认图片文件已复制(119个)
|
|
||||||
2. 检查图片路径(使用 SketchPng... 格式)
|
|
||||||
3. 查看 `assets/images/IMAGE_MAPPING.md`
|
|
||||||
|
|
||||||
### 如果样式错误
|
|
||||||
1. 确认 `@/styles/mixins.scss` 存在
|
|
||||||
2. 检查 vw/vh/fs 函数定义
|
|
||||||
3. 查看 `assets/styles/common.scss`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 组件使用示例
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<script setup>
|
|
||||||
import { useDisasterData } from './composables/useDisasterData'
|
|
||||||
|
|
||||||
// 使用状态管理
|
|
||||||
const { disasterInfo, forcePreset } = useDisasterData()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<!-- 使用公共组件 -->
|
|
||||||
<PanelHeader title="快速感知" subtitle="「灾害分析」" />
|
|
||||||
|
|
||||||
<DataField
|
|
||||||
label="灾害类型"
|
|
||||||
:value="disasterInfo.type"
|
|
||||||
color-type="danger"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ActionButton
|
|
||||||
text="一键启动"
|
|
||||||
type="primary"
|
|
||||||
@click="handleStart"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 需要帮助?
|
|
||||||
|
|
||||||
查看详细文档:
|
|
||||||
- `README.md` - 完整使用指南
|
|
||||||
- `REFACTORING_SUMMARY.md` - 重构详情
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**重构完成!立即启动项目体验全新代码结构!** 🎉
|
|
||||||
@ -1,262 +0,0 @@
|
|||||||
# 3D态势感知应急驾驶舱 - 重构版
|
|
||||||
|
|
||||||
## 📋 项目概述
|
|
||||||
|
|
||||||
这是对从蓝湖导出的 `3DSituationalAwarenessCopy` 页面的完整重构版本,解决了原始代码的可维护性问题。
|
|
||||||
|
|
||||||
## ✨ 重构成果
|
|
||||||
|
|
||||||
### 改进前(原始代码)
|
|
||||||
- ❌ 792 行代码全在一个文件
|
|
||||||
- ❌ 使用 `group_1`、`block_1` 等无意义命名
|
|
||||||
- ❌ 硬编码像素值,不支持响应式
|
|
||||||
- ❌ 深层嵌套的 div 结构
|
|
||||||
- ❌ 绝对定位 + margin 混乱布局
|
|
||||||
|
|
||||||
### 改进后(重构代码)
|
|
||||||
- ✅ 拆分为 20+ 个独立组件
|
|
||||||
- ✅ 语义化命名,一目了然
|
|
||||||
- ✅ 使用 vw/vh/fs 响应式单位
|
|
||||||
- ✅ 清晰的组件层次结构
|
|
||||||
- ✅ CSS Grid + Flexbox 现代布局
|
|
||||||
- ✅ Vue 3 Composition API + `<script setup>`
|
|
||||||
|
|
||||||
## 📁 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
3DSituationalAwarenessRefactor/
|
|
||||||
├── index.vue # 主页面入口
|
|
||||||
├── components/ # 组件目录
|
|
||||||
│ ├── PageHeader.vue # 顶部导航栏
|
|
||||||
│ ├── LeftPanel/ # 左侧面板
|
|
||||||
│ │ ├── index.vue # 面板容器
|
|
||||||
│ │ ├── DisasterAnalysis.vue # 灾害分析
|
|
||||||
│ │ ├── ForcePreset.vue # 力量预置
|
|
||||||
│ │ ├── ForceDispatch.vue # 力量调度
|
|
||||||
│ │ └── CollaborationInfo.vue # 协同信息
|
|
||||||
│ ├── MapViewer/ # 地图区域
|
|
||||||
│ │ ├── index.vue # 地图容器
|
|
||||||
│ │ └── MapControls.vue # 地图控制工具
|
|
||||||
│ ├── RightPanel/ # 右侧面板
|
|
||||||
│ │ ├── index.vue # 面板容器
|
|
||||||
│ │ ├── DispatchCommand.vue # 调度指挥
|
|
||||||
│ │ ├── VideoMonitorGrid.vue # 视频监控网格
|
|
||||||
│ │ ├── VideoMonitorItem.vue # 视频监控卡片
|
|
||||||
│ │ └── DispatchSuggestion.vue # 调度建议
|
|
||||||
│ ├── shared/ # 公共组件
|
|
||||||
│ │ ├── PanelHeader.vue # 面板标题
|
|
||||||
│ │ ├── DataField.vue # 数据字段
|
|
||||||
│ │ └── ActionButton.vue # 操作按钮
|
|
||||||
│ └── Popups/ # 弹窗组件
|
|
||||||
│ ├── PersonnelDetail.vue # 应急人员详情
|
|
||||||
│ └── EmergencyCenterDetail.vue # 应急中心详情
|
|
||||||
├── composables/ # 组合式函数
|
|
||||||
│ ├── useDisasterData.js # 灾害数据管理
|
|
||||||
│ ├── useForceDispatch.js # 力量调度逻辑
|
|
||||||
│ └── useVideoMonitor.js # 视频监控状态
|
|
||||||
├── assets/ # 资源文件
|
|
||||||
│ ├── styles/
|
|
||||||
│ │ └── common.scss # 公共样式
|
|
||||||
│ └── images/ # 图片资源(需从Copy目录迁移)
|
|
||||||
├── constants.js # 常量定义
|
|
||||||
└── README.md # 本文档
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎯 核心功能模块
|
|
||||||
|
|
||||||
### 1. 顶部导航栏
|
|
||||||
- 返回驾驶舱按钮
|
|
||||||
- 系统标题
|
|
||||||
- 灾后现场实景入口
|
|
||||||
- 设置按钮
|
|
||||||
|
|
||||||
### 2. 左侧面板(灾害分析与调度)
|
|
||||||
- **快速感知(灾害分析)**:灾害类型、损坏方量、滑坡体尺寸、人员伤亡等
|
|
||||||
- **快速匹配(力量预置)**:应急装备、基地、人员统计,附近养护站列表
|
|
||||||
- **快速响应(力量调度)**:响应等级、智能应急方案、预计抢通时间
|
|
||||||
- **协同信息**:气象预警、公安部门、融媒体中心的实时信息
|
|
||||||
|
|
||||||
### 3. 中央地图区域
|
|
||||||
- 3D 地图展示(支持接入 Cesium、Mapbox GL JS 等)
|
|
||||||
- 地图标记点(应急人员、应急中心)
|
|
||||||
- 测量工具栏(模型对比、测量方量、测量位置/距离)
|
|
||||||
|
|
||||||
### 4. 右侧面板(现场处置)
|
|
||||||
- **调度指挥**:现场单兵/设备/无人机列表(标签页切换)
|
|
||||||
- **视频监控网格**:4 视角视频监控(单兵、无人机、指挥车外部/会议)
|
|
||||||
- **调度建议**:智能调度力量建议卡片
|
|
||||||
|
|
||||||
### 5. 弹窗组件
|
|
||||||
- **应急人员详情**:姓名、部门、位置、预计到达时间、联动操作
|
|
||||||
- **应急中心详情**:名称、行政等级、隶属单位、位置信息
|
|
||||||
|
|
||||||
## 🔧 技术栈
|
|
||||||
|
|
||||||
- **Vue 3**:Composition API + `<script setup>` 语法
|
|
||||||
- **SCSS**:样式预处理器
|
|
||||||
- **响应式设计**:vw/vh/fs 函数(项目统一方案)
|
|
||||||
- **状态管理**:Composables(组合式函数)
|
|
||||||
- **组件通信**:Props/Emits + Provide/Inject
|
|
||||||
|
|
||||||
## 📦 安装与使用
|
|
||||||
|
|
||||||
### 1. 图片资源迁移
|
|
||||||
|
|
||||||
**重要**:由于图片资源仍在原始目录,需要手动迁移或更新引用路径:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 方案 1:复制图片到新目录
|
|
||||||
cp -r ../3DSituationalAwarenessCopy/assets/img/* ./assets/images/
|
|
||||||
|
|
||||||
# 方案 2:创建符号链接(开发环境)
|
|
||||||
ln -s ../3DSituationalAwarenessCopy/assets/img ./assets/images
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 图片命名优化(可选)
|
|
||||||
|
|
||||||
原始图片命名为 `SketchPng...`,建议重命名为语义化名称:
|
|
||||||
|
|
||||||
```
|
|
||||||
SketchPng6e14... → map-background.png
|
|
||||||
SketchPng7ba5... → left-panel-bg.png
|
|
||||||
SketchPng9eb4... → disaster-type-icon.png
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
可以使用脚本批量重命名,或手动整理。
|
|
||||||
|
|
||||||
### 3. 启动项目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在项目根目录
|
|
||||||
pnpm dev:screen
|
|
||||||
```
|
|
||||||
|
|
||||||
访问路由:`/3d-situational-awareness-refactor`
|
|
||||||
|
|
||||||
## 🎨 样式规范
|
|
||||||
|
|
||||||
### CSS 变量(定义在 common.scss)
|
|
||||||
```scss
|
|
||||||
--primary-color: rgba(28, 161, 255, 1); // 主色
|
|
||||||
--bg-dark: rgba(9, 22, 40, 1); // 深色背景
|
|
||||||
--bg-panel: rgba(20, 53, 118, 1); // 面板背景
|
|
||||||
--text-white: rgba(255, 255, 255, 1); // 白色文字
|
|
||||||
--success-color: rgba(17, 187, 119, 1); // 成功色
|
|
||||||
--warning-color: rgba(255, 128, 11, 1); // 警告色
|
|
||||||
--danger-color: rgba(255, 6, 36, 1); // 危险色
|
|
||||||
```
|
|
||||||
|
|
||||||
### 响应式单位
|
|
||||||
```scss
|
|
||||||
width: vw(564); // 宽度
|
|
||||||
height: vh(200); // 高度
|
|
||||||
font-size: fs(16); // 字体大小
|
|
||||||
```
|
|
||||||
|
|
||||||
### BEM 命名规范
|
|
||||||
```scss
|
|
||||||
.disaster-analysis {
|
|
||||||
&__content { } // 元素
|
|
||||||
&__row { } // 元素
|
|
||||||
&--active { } // 修饰符
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 后续工作
|
|
||||||
|
|
||||||
### 必须完成
|
|
||||||
1. **图片资源迁移**:将原始图片复制到新目录并更新引用
|
|
||||||
2. **真实图片替换**:替换占位图片为设计稿中的实际图片
|
|
||||||
3. **API 对接**:实现真实数据接口对接
|
|
||||||
|
|
||||||
### 建议优化
|
|
||||||
1. **3D 地图集成**:接入 Cesium 或 Mapbox GL JS
|
|
||||||
2. **视频流接入**:实现真实视频流播放
|
|
||||||
3. **动画效果**:添加过渡动画和交互反馈
|
|
||||||
4. **性能优化**:按需加载、虚拟滚动等
|
|
||||||
5. **单元测试**:编写组件单元测试
|
|
||||||
|
|
||||||
## 📝 组件使用示例
|
|
||||||
|
|
||||||
### 使用 DataField 组件
|
|
||||||
```vue
|
|
||||||
<DataField
|
|
||||||
label="灾害类型"
|
|
||||||
value="边坡垮塌"
|
|
||||||
icon="path/to/icon.png"
|
|
||||||
color-type="danger"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用 ActionButton 组件
|
|
||||||
```vue
|
|
||||||
<ActionButton
|
|
||||||
text="一键启动"
|
|
||||||
type="primary"
|
|
||||||
size="medium"
|
|
||||||
icon="path/to/icon.png"
|
|
||||||
@click="handleClick"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用 PanelHeader 组件
|
|
||||||
```vue
|
|
||||||
<PanelHeader title="快速感知" subtitle="「灾害分析」">
|
|
||||||
<template #extra>
|
|
||||||
<button>额外操作</button>
|
|
||||||
</template>
|
|
||||||
</PanelHeader>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔍 对比原始代码
|
|
||||||
|
|
||||||
### 原始代码片段(不可维护)
|
|
||||||
```vue
|
|
||||||
<div class="group_3 flex-col">
|
|
||||||
<div class="section_1 flex-row">
|
|
||||||
<div class="block_1 flex-row justify-between">
|
|
||||||
<img class="thumbnail_1" src="..." />
|
|
||||||
<span class="text_1">返回驾驶舱</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 重构后代码(清晰可维护)
|
|
||||||
```vue
|
|
||||||
<PageHeader @back="handleBack">
|
|
||||||
<template #left>
|
|
||||||
<button class="back-btn">
|
|
||||||
<img class="back-icon" src="..." />
|
|
||||||
<span class="back-text">返回驾驶舱</span>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
</PageHeader>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 重构统计
|
|
||||||
|
|
||||||
| 指标 | 改进前 | 改进后 | 提升 |
|
|
||||||
|------|--------|--------|------|
|
|
||||||
| 单文件行数 | 792 行 | < 200 行/组件 | 75% ↓ |
|
|
||||||
| 组件数量 | 1 个 | 20+ 个 | - |
|
|
||||||
| 样式可读性 | 低 | 高 | 显著提升 |
|
|
||||||
| 代码可维护性 | 差 | 优 | 显著提升 |
|
|
||||||
| 响应式支持 | 无 | 完整 | 新增 |
|
|
||||||
|
|
||||||
## 👥 团队协作建议
|
|
||||||
|
|
||||||
1. **组件开发**:每个组件由独立开发者维护
|
|
||||||
2. **样式规范**:严格遵循 BEM 命名和响应式单位
|
|
||||||
3. **代码审查**:确保组件职责单一,可复用性高
|
|
||||||
4. **文档更新**:新增组件或修改 API 时及时更新文档
|
|
||||||
|
|
||||||
## 📞 联系方式
|
|
||||||
|
|
||||||
如有问题或建议,请联系项目负责人。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**重构完成日期**:2025-11-14
|
|
||||||
**重构版本**:v1.0.0
|
|
||||||
@ -1,323 +0,0 @@
|
|||||||
# 🎉 3D态势感知应急驾驶舱 - 重构完成总结
|
|
||||||
|
|
||||||
## ✅ 完成情况
|
|
||||||
|
|
||||||
**重构状态:已完成 100%**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 重构成果统计
|
|
||||||
|
|
||||||
### 1. 文件创建
|
|
||||||
|
|
||||||
| 类别 | 数量 | 说明 |
|
|
||||||
|------|------|------|
|
|
||||||
| **组件文件** | 20 个 | Vue 组件(.vue) |
|
|
||||||
| **Composables** | 3 个 | 状态管理逻辑(.js) |
|
|
||||||
| **样式文件** | 1 个 | 公共样式(common.scss) |
|
|
||||||
| **配置文件** | 1 个 | 常量配置(constants.js) |
|
|
||||||
| **文档文件** | 3 个 | README.md × 3 |
|
|
||||||
| **图片资源** | 119 个 | PNG 图片 |
|
|
||||||
| **总计** | **147 个文件** | 完整的重构项目 |
|
|
||||||
|
|
||||||
### 2. 代码质量提升
|
|
||||||
|
|
||||||
| 指标 | 改进前 | 改进后 | 提升幅度 |
|
|
||||||
|------|--------|--------|----------|
|
|
||||||
| **文件数量** | 1 个巨型文件 | 26 个模块化文件 | ↑ 2500% |
|
|
||||||
| **单文件代码行数** | 792 行 | < 200 行/文件 | ↓ 75% |
|
|
||||||
| **命名可读性** | 0% (group_1) | 100% (语义化) | ↑ 100% |
|
|
||||||
| **响应式支持** | 0% (固定像素) | 100% (vw/vh) | ↑ 100% |
|
|
||||||
| **组件复用性** | 0% | 高(公共组件) | 新增 |
|
|
||||||
| **可维护性** | 差 | 优秀 | 显著提升 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 完整目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
3DSituationalAwarenessRefactor/
|
|
||||||
├── index.vue # ✅ 主页面入口
|
|
||||||
├── README.md # ✅ 项目文档
|
|
||||||
│
|
|
||||||
├── components/ # ✅ 组件目录(20个组件)
|
|
||||||
│ ├── PageHeader.vue # ✅ 顶部导航栏
|
|
||||||
│ │
|
|
||||||
│ ├── LeftPanel/ # ✅ 左侧面板(5个文件)
|
|
||||||
│ │ ├── index.vue # 面板容器
|
|
||||||
│ │ ├── DisasterAnalysis.vue # 灾害分析
|
|
||||||
│ │ ├── ForcePreset.vue # 力量预置
|
|
||||||
│ │ ├── ForceDispatch.vue # 力量调度
|
|
||||||
│ │ └── CollaborationInfo.vue # 协同信息
|
|
||||||
│ │
|
|
||||||
│ ├── MapViewer/ # ✅ 地图区域(2个文件)
|
|
||||||
│ │ ├── index.vue # 地图容器
|
|
||||||
│ │ └── MapControls.vue # 地图控制工具
|
|
||||||
│ │
|
|
||||||
│ ├── RightPanel/ # ✅ 右侧面板(5个文件)
|
|
||||||
│ │ ├── index.vue # 面板容器
|
|
||||||
│ │ ├── DispatchCommand.vue # 调度指挥
|
|
||||||
│ │ ├── VideoMonitorGrid.vue # 视频监控网格
|
|
||||||
│ │ ├── VideoMonitorItem.vue # 视频监控卡片
|
|
||||||
│ │ └── DispatchSuggestion.vue # 调度建议
|
|
||||||
│ │
|
|
||||||
│ ├── shared/ # ✅ 公共组件(3个文件)
|
|
||||||
│ │ ├── PanelHeader.vue # 面板标题
|
|
||||||
│ │ ├── DataField.vue # 数据字段
|
|
||||||
│ │ └── ActionButton.vue # 操作按钮
|
|
||||||
│ │
|
|
||||||
│ └── Popups/ # ✅ 弹窗组件(2个文件)
|
|
||||||
│ ├── PersonnelDetail.vue # 应急人员详情
|
|
||||||
│ └── EmergencyCenterDetail.vue # 应急中心详情
|
|
||||||
│
|
|
||||||
├── composables/ # ✅ 组合式函数(3个文件)
|
|
||||||
│ ├── useDisasterData.js # 灾害数据管理
|
|
||||||
│ ├── useForceDispatch.js # 力量调度逻辑
|
|
||||||
│ └── useVideoMonitor.js # 视频监控状态
|
|
||||||
│
|
|
||||||
├── assets/ # ✅ 资源文件
|
|
||||||
│ ├── styles/
|
|
||||||
│ │ └── common.scss # ✅ 公共样式
|
|
||||||
│ └── images/ # ✅ 图片资源(119个)
|
|
||||||
│ ├── index.js # ✅ 图片索引文件
|
|
||||||
│ ├── README.md # ✅ 图片说明文档
|
|
||||||
│ ├── IMAGE_MAPPING.md # ✅ 图片映射文档
|
|
||||||
│ └── *.png # ✅ 119 个图片文件
|
|
||||||
│
|
|
||||||
└── constants.js # ✅ 常量定义
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 核心改进点
|
|
||||||
|
|
||||||
### 1. **组件化架构**
|
|
||||||
- ❌ 原始:792行代码堆在一个文件
|
|
||||||
- ✅ 重构:20+个独立组件,职责清晰
|
|
||||||
|
|
||||||
### 2. **语义化命名**
|
|
||||||
- ❌ 原始:`group_1`, `block_1`, `text_1`
|
|
||||||
- ✅ 重构:`DisasterAnalysis`, `ForcePreset`, `PanelHeader`
|
|
||||||
|
|
||||||
### 3. **响应式设计**
|
|
||||||
- ❌ 原始:硬编码 1920px × 1080px
|
|
||||||
- ✅ 重构:vw(564), vh(200), fs(16)
|
|
||||||
|
|
||||||
### 4. **现代化技术栈**
|
|
||||||
- ❌ 原始:Options API + 混乱结构
|
|
||||||
- ✅ 重构:Composition API + `<script setup>`
|
|
||||||
|
|
||||||
### 5. **状态管理**
|
|
||||||
- ❌ 原始:无状态管理
|
|
||||||
- ✅ 重构:3 个 Composables + Provide/Inject
|
|
||||||
|
|
||||||
### 6. **样式规范**
|
|
||||||
- ❌ 原始:内联样式 + 绝对定位
|
|
||||||
- ✅ 重构:BEM 命名 + CSS Grid/Flexbox
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 技术实现亮点
|
|
||||||
|
|
||||||
### 1. **图片资源管理**
|
|
||||||
✅ 119 个图片文件已复制
|
|
||||||
✅ 创建图片索引文件(images/index.js)
|
|
||||||
✅ 所有组件路径已更新
|
|
||||||
✅ 提供图片映射文档
|
|
||||||
|
|
||||||
### 2. **可复用组件**
|
|
||||||
```vue
|
|
||||||
<!-- PanelHeader:统一的面板标题样式 -->
|
|
||||||
<PanelHeader title="快速感知" subtitle="「灾害分析」" />
|
|
||||||
|
|
||||||
<!-- DataField:统一的数据字段展示 -->
|
|
||||||
<DataField label="灾害类型" value="边坡垮塌" color-type="danger" />
|
|
||||||
|
|
||||||
<!-- ActionButton:统一的操作按钮 -->
|
|
||||||
<ActionButton text="一键启动" type="primary" @click="handleStart" />
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. **组合式函数(Composables)**
|
|
||||||
```javascript
|
|
||||||
// 灾害数据管理
|
|
||||||
const { disasterInfo, forcePreset, forceDispatch } = useDisasterData()
|
|
||||||
|
|
||||||
// 视频监控状态
|
|
||||||
const { monitors, activeMonitor, toggleMegaphone } = useVideoMonitor()
|
|
||||||
|
|
||||||
// 力量调度逻辑
|
|
||||||
const { activeTab, currentList, changeTab } = useForceDispatch()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. **响应式单位系统**
|
|
||||||
```scss
|
|
||||||
// 宽度:基于 1920px
|
|
||||||
width: vw(564); // → calc(564 / 1920 * 100vw)
|
|
||||||
|
|
||||||
// 高度:基于 982px
|
|
||||||
height: vh(200); // → calc(200 / 982 * 100vh)
|
|
||||||
|
|
||||||
// 字体:跟随宽度
|
|
||||||
font-size: fs(16); // → vw(16)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 使用指南
|
|
||||||
|
|
||||||
### 1. 启动项目
|
|
||||||
```bash
|
|
||||||
cd bxztApp
|
|
||||||
pnpm dev:screen
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 访问页面
|
|
||||||
浏览器访问:`http://localhost:xxxx/3d-situational-awareness-refactor`
|
|
||||||
|
|
||||||
### 3. 开发建议
|
|
||||||
- 单个组件 < 200 行代码
|
|
||||||
- 遵循 BEM 命名规范
|
|
||||||
- 使用 vw/vh/fs 响应式单位
|
|
||||||
- 通过 Composables 管理状态
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 后续工作清单
|
|
||||||
|
|
||||||
### 必须完成(P0)
|
|
||||||
- [ ] **路由配置**:在 router.js 中添加页面路由
|
|
||||||
- [ ] **API 对接**:实现真实数据接口
|
|
||||||
- [ ] **测试验证**:启动项目,验证页面渲染
|
|
||||||
|
|
||||||
### 建议优化(P1)
|
|
||||||
- [ ] **3D 地图集成**:接入 Cesium 或 Mapbox GL JS
|
|
||||||
- [ ] **视频流接入**:实现真实视频播放
|
|
||||||
- [ ] **图片优化**:压缩图片(预计减少 30-50% 体积)
|
|
||||||
- [ ] **图片重命名**:将 SketchPng... 重命名为语义化名称
|
|
||||||
|
|
||||||
### 可选增强(P2)
|
|
||||||
- [ ] 添加过渡动画效果
|
|
||||||
- [ ] 实现虚拟滚动(长列表优化)
|
|
||||||
- [ ] 编写组件单元测试
|
|
||||||
- [ ] 实现暗黑模式切换
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 相关文档
|
|
||||||
|
|
||||||
1. **项目主文档**
|
|
||||||
`3DSituationalAwarenessRefactor/README.md`
|
|
||||||
包含完整的项目说明、组件使用示例、样式规范等
|
|
||||||
|
|
||||||
2. **图片资源文档**
|
|
||||||
`3DSituationalAwarenessRefactor/assets/images/README.md`
|
|
||||||
图片使用方式、分类说明、优化建议
|
|
||||||
|
|
||||||
3. **图片映射文档**
|
|
||||||
`3DSituationalAwarenessRefactor/assets/images/IMAGE_MAPPING.md`
|
|
||||||
占位符名称与实际文件名的映射关系
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 代码对比示例
|
|
||||||
|
|
||||||
### 原始代码(不可维护)
|
|
||||||
```vue
|
|
||||||
<div class="group_3 flex-col">
|
|
||||||
<div class="section_1 flex-row">
|
|
||||||
<div class="block_1 flex-row justify-between">
|
|
||||||
<img class="thumbnail_1" src="..." />
|
|
||||||
<span class="text_1">返回驾驶舱</span>
|
|
||||||
</div>
|
|
||||||
<div class="block_2 flex-col"></div>
|
|
||||||
<span class="text_2">渝路智管-公路安全畅通运行管理</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.group_3 {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 564px;
|
|
||||||
height: 1080px;
|
|
||||||
}
|
|
||||||
.block_1 {
|
|
||||||
width: 136px;
|
|
||||||
height: 44px;
|
|
||||||
margin: 60px 0 0 21px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 重构后代码(清晰可维护)
|
|
||||||
```vue
|
|
||||||
<PageHeader @back="handleBack">
|
|
||||||
<template #left>
|
|
||||||
<button class="back-btn">
|
|
||||||
<img class="back-icon" :src="images.backArrow" />
|
|
||||||
<span class="back-text">返回驾驶舱</span>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
<template #center>
|
|
||||||
<h1 class="page-title">渝路智管-公路安全畅通运行管理</h1>
|
|
||||||
</template>
|
|
||||||
</PageHeader>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@use '@/styles/mixins.scss' as *;
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 vw(21);
|
|
||||||
|
|
||||||
.back-btn {
|
|
||||||
display: flex;
|
|
||||||
gap: vw(10);
|
|
||||||
padding: vh(12) vw(24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 最佳实践总结
|
|
||||||
|
|
||||||
### 组件设计原则
|
|
||||||
1. **单一职责**:每个组件只负责一个功能
|
|
||||||
2. **高内聚低耦合**:减少组件间依赖
|
|
||||||
3. **可复用性**:提取公共组件和逻辑
|
|
||||||
4. **可测试性**:逻辑与 UI 分离
|
|
||||||
|
|
||||||
### 命名规范
|
|
||||||
1. **组件名**:PascalCase(如 `DisasterAnalysis`)
|
|
||||||
2. **文件名**:kebab-case 或 PascalCase
|
|
||||||
3. **CSS 类名**:BEM 规范(`.block__element--modifier`)
|
|
||||||
4. **变量名**:camelCase(如 `disasterInfo`)
|
|
||||||
|
|
||||||
### 样式规范
|
|
||||||
1. 使用 vw/vh/fs 响应式单位
|
|
||||||
2. 通过 CSS 变量管理颜色
|
|
||||||
3. 采用 Flexbox/Grid 现代布局
|
|
||||||
4. Scoped 样式避免污染
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 重构成功!
|
|
||||||
|
|
||||||
**重构前后对比:**
|
|
||||||
- 代码可读性:0% → 100%
|
|
||||||
- 可维护性:差 → 优秀
|
|
||||||
- 响应式支持:无 → 完整
|
|
||||||
- 组件复用:无 → 丰富
|
|
||||||
|
|
||||||
**项目已经完全重构完成,可以正常使用!** 🚀
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**重构完成日期**:2025-11-14
|
|
||||||
**重构版本**:v1.0.0
|
|
||||||
**总文件数**:147 个
|
|
||||||
**代码行数**:约 4000+ 行(模块化分布)
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 863 B |
@ -53,9 +53,9 @@ defineProps({
|
|||||||
|
|
||||||
// 地理位置信息数据
|
// 地理位置信息数据
|
||||||
const locationInfo = [
|
const locationInfo = [
|
||||||
{ label: '线路编号', value: 'S710', icon: lineCodeIcon },
|
{ label: '线路编号', value: 'S204', icon: lineCodeIcon },
|
||||||
{ label: '路线班号', value: 'S199', icon: classNumberIcon },
|
{ label: '灾害桩号', value: 'K130 + 800', icon: classNumberIcon },
|
||||||
{ label: '路段巡查员', value: '张强', icon: inspectorIcon },
|
{ label: '路段巡路员', value: '张强', icon: inspectorIcon },
|
||||||
{ label: '联系电话', value: '13987657892', icon: phoneIcon },
|
{ label: '联系电话', value: '13987657892', icon: phoneIcon },
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -707,22 +707,24 @@ const handleDeletePlan = (id) => {
|
|||||||
|
|
||||||
:deep(.el-textarea__inner) {
|
:deep(.el-textarea__inner) {
|
||||||
background: #052044 !important;
|
background: #052044 !important;
|
||||||
border: 1px solid rgba(28, 161, 255, 0.3) !important;
|
border: none !important;
|
||||||
|
box-shadow: 0 0 0 1px rgba(28, 161, 255, 0.3) inset !important;
|
||||||
border-radius: vw(4);
|
border-radius: vw(4);
|
||||||
color: var(--text-white);
|
color: var(--text-white);
|
||||||
font-size: fs(13);
|
font-size: fs(13);
|
||||||
font-family: SourceHanSansCN-Regular, sans-serif;
|
font-family: SourceHanSansCN-Regular, sans-serif;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
padding: vh(8) vw(12);
|
padding: vh(8) vw(12);
|
||||||
transition: border-color 0.3s ease;
|
transition: box-shadow 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--primary-color) !important;
|
box-shadow: 0 0 0 1px var(--primary-color) inset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus,
|
||||||
border-color: var(--primary-color) !important;
|
&:focus-visible {
|
||||||
box-shadow: none !important;
|
box-shadow: 0 0 0 1px var(--primary-color) inset !important;
|
||||||
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
@ -835,22 +837,24 @@ const handleDeletePlan = (id) => {
|
|||||||
.follow-up-textarea {
|
.follow-up-textarea {
|
||||||
:deep(.el-textarea__inner) {
|
:deep(.el-textarea__inner) {
|
||||||
background: #052044 !important;
|
background: #052044 !important;
|
||||||
border: 1px solid rgba(28, 161, 255, 0.3) !important;
|
border: none !important;
|
||||||
|
box-shadow: 0 0 0 1px rgba(28, 161, 255, 0.3) inset !important;
|
||||||
border-radius: vw(4);
|
border-radius: vw(4);
|
||||||
color: var(--text-white);
|
color: var(--text-white);
|
||||||
font-size: fs(13);
|
font-size: fs(13);
|
||||||
font-family: SourceHanSansCN-Regular, sans-serif;
|
font-family: SourceHanSansCN-Regular, sans-serif;
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
padding: vh(10) vw(14);
|
padding: vh(10) vw(14);
|
||||||
transition: border-color 0.3s ease;
|
transition: box-shadow 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--primary-color) !important;
|
box-shadow: 0 0 0 1px var(--primary-color) inset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus,
|
||||||
border-color: var(--primary-color) !important;
|
&:focus-visible {
|
||||||
box-shadow: none !important;
|
box-shadow: 0 0 0 1px var(--primary-color) inset !important;
|
||||||
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
|
|||||||
@ -65,6 +65,20 @@
|
|||||||
>
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
|
<!-- 视频图标按钮 -->
|
||||||
|
<button
|
||||||
|
v-if="showVideoIcon && videoIconSrc"
|
||||||
|
type="button"
|
||||||
|
class="map-tooltip__video-btn"
|
||||||
|
:aria-label="videoIconAriaLabel"
|
||||||
|
@click.stop="emit('video-icon-click')"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="videoIconSrc"
|
||||||
|
alt=""
|
||||||
|
class="map-tooltip__video-icon"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
@ -197,6 +211,30 @@ const props = defineProps({
|
|||||||
closable: {
|
closable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在标题右侧显示视频图标
|
||||||
|
*/
|
||||||
|
showVideoIcon: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频图标的图片路径
|
||||||
|
*/
|
||||||
|
videoIconSrc: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频图标的无障碍标签
|
||||||
|
*/
|
||||||
|
videoIconAriaLabel: {
|
||||||
|
type: String,
|
||||||
|
default: '打开视频监控'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -211,7 +249,11 @@ const emit = defineEmits([
|
|||||||
/**
|
/**
|
||||||
* 支持 v-model:visible 双向绑定
|
* 支持 v-model:visible 双向绑定
|
||||||
*/
|
*/
|
||||||
'update:visible'
|
'update:visible',
|
||||||
|
/**
|
||||||
|
* 用户点击视频图标时触发
|
||||||
|
*/
|
||||||
|
'video-icon-click'
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -354,6 +396,47 @@ const handleClose = () => {
|
|||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频图标按钮
|
||||||
|
* 显示在标题右侧,用于打开视频监控
|
||||||
|
*/
|
||||||
|
.map-tooltip__video-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: vw(24);
|
||||||
|
height: vw(24);
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.15);
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--primary-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-tooltip__video-icon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
display: block;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭按钮
|
* 关闭按钮
|
||||||
* 使用纯 CSS 实现 X 图标,避免额外的图片资源
|
* 使用纯 CSS 实现 X 图标,避免额外的图片资源
|
||||||
|
|||||||
@ -116,6 +116,9 @@
|
|||||||
:title="mapTooltip.title"
|
:title="mapTooltip.title"
|
||||||
:icon="mapTooltip.icon"
|
:icon="mapTooltip.icon"
|
||||||
:z-index="mapTooltip.zIndex"
|
:z-index="mapTooltip.zIndex"
|
||||||
|
:show-video-icon="mapTooltip.data && mapTooltip.data.supportVideo"
|
||||||
|
:video-icon-src="mediaIcon"
|
||||||
|
@video-icon-click="handleVideoIconClick"
|
||||||
@close="handleMapTooltipClose"
|
@close="handleMapTooltipClose"
|
||||||
>
|
>
|
||||||
<!-- Tooltip 内容插槽 - 根据实际业务数据渲染 -->
|
<!-- Tooltip 内容插槽 - 根据实际业务数据渲染 -->
|
||||||
@ -168,6 +171,14 @@
|
|||||||
@close="showCenterDetail = false"
|
@close="showCenterDetail = false"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 视频监控弹窗 -->
|
||||||
|
<VideoModal
|
||||||
|
v-if="showVideoModal"
|
||||||
|
:visible="showVideoModal"
|
||||||
|
:monitor="selectedVideoMonitor"
|
||||||
|
@close="handleVideoModalClose"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 智能应急方案弹窗 -->
|
<!-- 智能应急方案弹窗 -->
|
||||||
<StretchableModal
|
<StretchableModal
|
||||||
v-model:visible="showStretchableModal"
|
v-model:visible="showStretchableModal"
|
||||||
@ -203,6 +214,7 @@ import MapViewer from "./components/MapViewer/index.vue";
|
|||||||
import RightPanel from "./components/RightPanel/index.vue";
|
import RightPanel from "./components/RightPanel/index.vue";
|
||||||
import PersonnelDetail from "./components/Popups/PersonnelDetail.vue";
|
import PersonnelDetail from "./components/Popups/PersonnelDetail.vue";
|
||||||
import EmergencyCenterDetail from "./components/Popups/EmergencyCenterDetail.vue";
|
import EmergencyCenterDetail from "./components/Popups/EmergencyCenterDetail.vue";
|
||||||
|
import VideoModal from "./components/RightPanel/VideoModal.vue";
|
||||||
import MapTooltip from "./components/shared/MapTooltip.vue";
|
import MapTooltip from "./components/shared/MapTooltip.vue";
|
||||||
import SceneLabel from "./components/SceneLabel.vue";
|
import SceneLabel from "./components/SceneLabel.vue";
|
||||||
import StretchableModal from "./components/shared/StretchableModal.vue";
|
import StretchableModal from "./components/shared/StretchableModal.vue";
|
||||||
@ -224,6 +236,7 @@ import soldierIcon from "./assets/images/SketchPngfbec927027ff9e49207749ebaafd22
|
|||||||
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
|
import deviceIcon from "./assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png";
|
||||||
import emergencyBaseIcon from "./assets/images/应急基地.png";
|
import emergencyBaseIcon from "./assets/images/应急基地.png";
|
||||||
import reserveCenterIcon from "./assets/images/储备中心.png";
|
import reserveCenterIcon from "./assets/images/储备中心.png";
|
||||||
|
import mediaIcon from "./assets/images/media.png";
|
||||||
|
|
||||||
// 折叠按钮图标
|
// 折叠按钮图标
|
||||||
import collapseLeftArrow from "./assets/images/折叠面板左箭头.png";
|
import collapseLeftArrow from "./assets/images/折叠面板左箭头.png";
|
||||||
@ -459,6 +472,9 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
let title = '';
|
let title = '';
|
||||||
const fields = [];
|
const fields = [];
|
||||||
const actions = [];
|
const actions = [];
|
||||||
|
let supportVideo = false;
|
||||||
|
let videoTitle = '';
|
||||||
|
const videoSrc = 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4';
|
||||||
|
|
||||||
if (type === 'soldier') {
|
if (type === 'soldier') {
|
||||||
// 应急人员
|
// 应急人员
|
||||||
@ -510,6 +526,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
{ label: '隶属单位', value: '交通公路部门' },
|
{ label: '隶属单位', value: '交通公路部门' },
|
||||||
{ label: '位置信息', value: `目前为止距离现场${distance}公里` }
|
{ label: '位置信息', value: `目前为止距离现场${distance}公里` }
|
||||||
);
|
);
|
||||||
|
supportVideo = true;
|
||||||
|
videoTitle = '应急中心';
|
||||||
} else {
|
} else {
|
||||||
// 其他养护站显示 tooltip
|
// 其他养护站显示 tooltip
|
||||||
title = '养护站';
|
title = '养护站';
|
||||||
@ -525,6 +543,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
{ label: '名称', value: properties.name?.getValue() || '-' },
|
{ label: '名称', value: properties.name?.getValue() || '-' },
|
||||||
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
||||||
);
|
);
|
||||||
|
supportVideo = true;
|
||||||
|
videoTitle = '储备中心';
|
||||||
} else if (type === 'presetPoint') {
|
} else if (type === 'presetPoint') {
|
||||||
// 预置点
|
// 预置点
|
||||||
title = '预置点';
|
title = '预置点';
|
||||||
@ -532,6 +552,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
{ label: '名称', value: properties.name?.getValue() || '-' },
|
{ label: '名称', value: properties.name?.getValue() || '-' },
|
||||||
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
{ label: '位置信息', value: properties.location?.getValue() || '-' }
|
||||||
);
|
);
|
||||||
|
supportVideo = true;
|
||||||
|
videoTitle = '预置点';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示 Tooltip,使用实体的屏幕坐标
|
// 显示 Tooltip,使用实体的屏幕坐标
|
||||||
@ -540,7 +562,13 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => {
|
|||||||
y: canvasPosition.y,
|
y: canvasPosition.y,
|
||||||
title,
|
title,
|
||||||
icon,
|
icon,
|
||||||
data: { fields, actions: actions.length > 0 ? actions : undefined }
|
data: {
|
||||||
|
fields,
|
||||||
|
actions: actions.length > 0 ? actions : undefined,
|
||||||
|
supportVideo,
|
||||||
|
videoTitle,
|
||||||
|
videoSrc
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 保存当前实体,用于相机移动时更新位置
|
// 保存当前实体,用于相机移动时更新位置
|
||||||
@ -989,6 +1017,7 @@ const handleMapToolChange = async ({ tool, active }) => {
|
|||||||
const showPersonnelDetail = ref(false);
|
const showPersonnelDetail = ref(false);
|
||||||
const showCenterDetail = ref(false);
|
const showCenterDetail = ref(false);
|
||||||
const showStretchableModal = ref(false);
|
const showStretchableModal = ref(false);
|
||||||
|
const showVideoModal = ref(false);
|
||||||
|
|
||||||
// 选中的数据
|
// 选中的数据
|
||||||
const selectedPersonnel = ref({
|
const selectedPersonnel = ref({
|
||||||
@ -1007,6 +1036,16 @@ const selectedCenter = ref({
|
|||||||
image: null,
|
image: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const selectedVideoMonitor = ref({
|
||||||
|
id: '',
|
||||||
|
title: '',
|
||||||
|
videoSrc: '',
|
||||||
|
dateRange: '',
|
||||||
|
hasMegaphone: false,
|
||||||
|
hasAudio: true,
|
||||||
|
hasDirectionControl: false
|
||||||
|
});
|
||||||
|
|
||||||
// 返回驾驶舱
|
// 返回驾驶舱
|
||||||
const handleBack = () => {
|
const handleBack = () => {
|
||||||
console.log("返回驾驶舱");
|
console.log("返回驾驶舱");
|
||||||
@ -1080,6 +1119,33 @@ const handleMapTooltipClose = () => {
|
|||||||
mapTooltip.value.visible = false;
|
mapTooltip.value.visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频图标点击事件
|
||||||
|
* 打开视频弹窗并设置视频源
|
||||||
|
*/
|
||||||
|
const handleVideoIconClick = () => {
|
||||||
|
const { data } = mapTooltip.value;
|
||||||
|
if (data && data.supportVideo) {
|
||||||
|
selectedVideoMonitor.value = {
|
||||||
|
id: Date.now().toString(),
|
||||||
|
title: data.videoTitle || '视频监控',
|
||||||
|
videoSrc: data.videoSrc || '',
|
||||||
|
dateRange: new Date().toLocaleDateString(),
|
||||||
|
hasMegaphone: false,
|
||||||
|
hasAudio: true,
|
||||||
|
hasDirectionControl: false
|
||||||
|
};
|
||||||
|
showVideoModal.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理视频弹窗关闭事件
|
||||||
|
*/
|
||||||
|
const handleVideoModalClose = () => {
|
||||||
|
showVideoModal.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
// 路径线实体引用
|
// 路径线实体引用
|
||||||
const pathLineEntities = ref([]);
|
const pathLineEntities = ref([]);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user