diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/QUICK_START.md b/packages/screen/src/views/3DSituationalAwarenessRefactor/QUICK_START.md deleted file mode 100644 index e18974e..0000000 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/QUICK_START.md +++ /dev/null @@ -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 - - - -``` - ---- - -## 📞 需要帮助? - -查看详细文档: -- `README.md` - 完整使用指南 -- `REFACTORING_SUMMARY.md` - 重构详情 - ---- - -**重构完成!立即启动项目体验全新代码结构!** 🎉 diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/README.md b/packages/screen/src/views/3DSituationalAwarenessRefactor/README.md deleted file mode 100644 index 6757af5..0000000 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/README.md +++ /dev/null @@ -1,262 +0,0 @@ -# 3D态势感知应急驾驶舱 - 重构版 - -## 📋 项目概述 - -这是对从蓝湖导出的 `3DSituationalAwarenessCopy` 页面的完整重构版本,解决了原始代码的可维护性问题。 - -## ✨ 重构成果 - -### 改进前(原始代码) -- ❌ 792 行代码全在一个文件 -- ❌ 使用 `group_1`、`block_1` 等无意义命名 -- ❌ 硬编码像素值,不支持响应式 -- ❌ 深层嵌套的 div 结构 -- ❌ 绝对定位 + margin 混乱布局 - -### 改进后(重构代码) -- ✅ 拆分为 20+ 个独立组件 -- ✅ 语义化命名,一目了然 -- ✅ 使用 vw/vh/fs 响应式单位 -- ✅ 清晰的组件层次结构 -- ✅ CSS Grid + Flexbox 现代布局 -- ✅ Vue 3 Composition API + ` diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue index 917003b..adbf06b 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue @@ -707,22 +707,24 @@ const handleDeletePlan = (id) => { :deep(.el-textarea__inner) { 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); color: var(--text-white); font-size: fs(13); font-family: SourceHanSansCN-Regular, sans-serif; line-height: 1.6; padding: vh(8) vw(12); - transition: border-color 0.3s ease; + transition: box-shadow 0.3s ease; &:hover { - border-color: var(--primary-color) !important; + box-shadow: 0 0 0 1px var(--primary-color) inset !important; } - &:focus { - border-color: var(--primary-color) !important; - box-shadow: none !important; + &:focus, + &:focus-visible { + box-shadow: 0 0 0 1px var(--primary-color) inset !important; + outline: none !important; } &::placeholder { @@ -835,22 +837,24 @@ const handleDeletePlan = (id) => { .follow-up-textarea { :deep(.el-textarea__inner) { 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); color: var(--text-white); font-size: fs(13); font-family: SourceHanSansCN-Regular, sans-serif; line-height: 1.8; padding: vh(10) vw(14); - transition: border-color 0.3s ease; + transition: box-shadow 0.3s ease; &:hover { - border-color: var(--primary-color) !important; + box-shadow: 0 0 0 1px var(--primary-color) inset !important; } - &:focus { - border-color: var(--primary-color) !important; - box-shadow: none !important; + &:focus, + &:focus-visible { + box-shadow: 0 0 0 1px var(--primary-color) inset !important; + outline: none !important; } &::placeholder { diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/MapTooltip.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/MapTooltip.vue index ca7ff3d..f3d2427 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/MapTooltip.vue +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/MapTooltip.vue @@ -65,6 +65,20 @@ > {{ title }} + + @@ -197,6 +211,30 @@ const props = defineProps({ closable: { type: Boolean, 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 双向绑定 */ - 'update:visible' + 'update:visible', + /** + * 用户点击视频图标时触发 + */ + 'video-icon-click' ]) /** @@ -354,6 +396,47 @@ const handleClose = () => { 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 图标,避免额外的图片资源 diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue index 13a8ed7..6a57529 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue @@ -116,6 +116,9 @@ :title="mapTooltip.title" :icon="mapTooltip.icon" :z-index="mapTooltip.zIndex" + :show-video-icon="mapTooltip.data && mapTooltip.data.supportVideo" + :video-icon-src="mediaIcon" + @video-icon-click="handleVideoIconClick" @close="handleMapTooltipClose" > @@ -168,6 +171,14 @@ @close="showCenterDetail = false" /> + + + { let title = ''; const fields = []; 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') { // 应急人员 @@ -510,6 +526,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => { { label: '隶属单位', value: '交通公路部门' }, { label: '位置信息', value: `目前为止距离现场${distance}公里` } ); + supportVideo = true; + videoTitle = '应急中心'; } else { // 其他养护站显示 tooltip title = '养护站'; @@ -525,6 +543,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => { { label: '名称', value: properties.name?.getValue() || '-' }, { label: '位置信息', value: properties.location?.getValue() || '-' } ); + supportVideo = true; + videoTitle = '储备中心'; } else if (type === 'presetPoint') { // 预置点 title = '预置点'; @@ -532,6 +552,8 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => { { label: '名称', value: properties.name?.getValue() || '-' }, { label: '位置信息', value: properties.location?.getValue() || '-' } ); + supportVideo = true; + videoTitle = '预置点'; } // 显示 Tooltip,使用实体的屏幕坐标 @@ -540,7 +562,13 @@ const showMarkerTooltip = (viewer, entity, screenPosition, icon) => { y: canvasPosition.y, title, 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 showCenterDetail = ref(false); const showStretchableModal = ref(false); +const showVideoModal = ref(false); // 选中的数据 const selectedPersonnel = ref({ @@ -1007,6 +1036,16 @@ const selectedCenter = ref({ image: null, }); +const selectedVideoMonitor = ref({ + id: '', + title: '', + videoSrc: '', + dateRange: '', + hasMegaphone: false, + hasAudio: true, + hasDirectionControl: false +}); + // 返回驾驶舱 const handleBack = () => { console.log("返回驾驶舱"); @@ -1080,6 +1119,33 @@ const handleMapTooltipClose = () => { 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([]);