diff --git a/frontend/.env.development b/frontend/.env.development index 0eca7e7f..b2b28071 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -7,14 +7,14 @@ VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台' VITE_APP_PORT = 3000 VITE_APP_BASE_API = '/dev-api' # 本地环境 -# VITE_APP_BASE_URL = 'http://10.84.121.127:8093' +VITE_APP_BASE_URL = 'http://localhost:8093' # 测试环境 # VITE_APP_BASE_URL = 'http://172.16.21.142:8093' # VITE_APP_BASE_URL = 'http://172.16.21.142:8096' # 汤伟 -# VITE_APP_BASE_URL = 'http://10.84.111.235:8093' +VITE_APP_BASE_URL = 'http://10.84.111.235:8093' # 李林 -VITE_APP_BASE_URL = 'http://10.84.111.25:8093' +# VITE_APP_BASE_URL = 'http://10.84.111.25:8093' # 测试环境线上10.84.121.122: VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122' diff --git a/frontend/docs/地图模块-3D Cesium实施计划.md b/frontend/docs/地图模块-3D Cesium实施计划.md index 404e6040..9b22b1b0 100644 --- a/frontend/docs/地图模块-3D Cesium实施计划.md +++ b/frontend/docs/地图模块-3D Cesium实施计划.md @@ -132,7 +132,7 @@ ## 5. 分步骤实施计划 -### Step 1:修正 3D 初始化并默认定位中国 +### Step 1:修正 3D 初始化并默认定位中国 ✅️ 目标: @@ -157,7 +157,7 @@ - 首屏有加载过渡。 - 进入后稳定落在中国。 -### Step 2:展示 3D 基础底图 +### Step 2:展示 3D 基础底图 ✅️ 目标: @@ -171,6 +171,10 @@ - 实现 `addBaseDataLayer(layer, isShow)`: - 对 `customBaseLayer` 使用 `url_3d` - 对 `BASEMAP-img`、`BASEMAP-white` 预留兼容能力 + - **必须处理 `wmts` 类型图层**:2D 通过 `WMTS` source 加载,3D 使用 `Cesium.WebMapTileServiceImageryProvider`,从 URL 参数中提取 LAYER/TILEMATRIXSET + - **必须提供 `tileMatrixLabels`**:Cesium 默认用纯数字作为 tileMatrix 参数值,但本系统 WMTS 服务器要求 `TileMatrixSet:zoom` 格式(如 `EPSG:3857_hbb_zrbhq_l13:4`)。需构建 `["TileMatrixSet:0", "TileMatrixSet:1", ...]` 传入 `tileMatrixLabels`。 + - 其他类型:`raster-dem`→XYZ、MapServer→ArcGIS、其余 →WMS +- **注意**:还存在一个 `key = "powerBaseStation"` 的基地底图图层,该图层**初始化时不加载**(已在 `IGNORED_BASE_LAYER_KEYS` 中忽略),但后续可通过图层树手动勾选显示。 - 实现 `controlBaseLayerTreeShowAndHidden()`: - 让图层树勾选能控制 3D 底图显隐 - 根据你的要求,UI 层先不开放 `BaseLayerSwitcher` 的 3D 切换行为,只保留默认基础底图加载。 @@ -180,7 +184,7 @@ - 切到 3D 后可稳定看到基础底图。 - 图层初始化时 `addBaseDataLayer(this.baseLayerConfig, checked, true)` 的思路在 3D 可落地。 -### Step 3:打通 3D 锚点展示 +### Step 3:打通 3D 锚点展示 ✅️ 目标: @@ -189,13 +193,14 @@ 计划: -- 在 `MapCesium` 内建立点位图层注册结构,建议按 `layerKey -> entity[]` 或 `CustomDataSource` 管理。 +- 在 `MapCesium` 内建立点位图层注册结构,按 `layerKey -> entity[]` 管理。 - 实现 `addInitDataLayer(pointData, layerType)`: - 复用当前点位数据结构 - 解析 `lgtd/lttd/iconCode/titleName/stnm/anchoPointState/popupHtml` - 复用现有图标资源路径 + - Entity ID 使用 `${layerKey}:${item._id || `${iconType || 'point'}_${stcd}`}`,与 2D 对齐,确保同 stcd 不同 sttpMap 的点不被覆盖 - 确保 `eng_point` 仍按现有 `mapStore` 过滤后的数据展示,中型站点只在 `7.5` 以上层级出现 - - 为后续缩放驱动的增量显示预留运行态字段,不把所有点简单一次性硬渲染 + - 为后续缩放驱动的增量显示预留运行态字段(`_legendVisible`、`_regionVisible`、`_densityVisible`),不把所有点简单一次性硬渲染 - 实现 `mdLayerTreeShowOrHidden(layerType, checked)`: - 图层树控制整个点图层显隐 - 实现 `removePointLayer()` / `hasLayer()` @@ -208,7 +213,34 @@ - 取消勾选图层后,对应锚点消失。 - `eng_point` 在低于 `7.5` 时不显示中型水电站,高于 `7.5` 时正常显示。 -### Step 4:打通 3D popup 与 hover +### Step 4:打通 3D 基地裁切(jdPanelControlShowAndHidden) ✅️ + +目标: + +- 3D 点击基地面板后,与 2D 行为一致。 +- 加载基地边界 GeoJSON,只显示区域内锚点,隐藏区域外锚点。 +- 取消基地时恢复显示所有锚点。 + +计划: + +- 在 `MapCesium` 中捕获 `hydropBase` 配置,与 2D 一样在 `addBaseDataLayer` 中记录。 +- 实现 `jdPanelControlShowAndHidden(baseid, isAll)`: + - `isAll=false`:清除 3D 球面遮罩实体、恢复所有锚点区域可见性、清除裁切状态。 + - `isAll=true`:先隐藏所有锚点,异步加载基地边界 GeoJSON,执行点在面判断后仅显示区域内锚点,同时在球面绘制裁切边界多边形(`applyRegionMask`),最后飞行到区域视野。 +- 在 `createEntityPropertiesBag` 中新增 `_regionVisible` 属性,初始为 `true`。 +- 在 `applyPointVisibilityRefresh` 中跳过 `_regionVisible !== false` 的实体,确保裁切后碰撞检测不会把区域外锚点重新显示出来。 +- 复用 `extractPolygonCoords` / `isPointInRing` 射线法判断逻辑(与 `region-mask-manager.ts` 一致)。 +- 支持 `AbortController` 取消前一次未完成的请求,避免响应顺序错乱。 +- `applyRegionMask` 将 GeoJSON 多边形转换为 Cesium `PolygonHierarchy`,在球面绘制半透明填充 + 可见边界的区域多边形,模拟 2D 底图 Canvas 裁切遮罩的视觉效果。 + +验收: + +- 点击基地后,3D 只显示该基地区域内的锚点,区域外锚点隐藏。 +- 取消基地后,所有锚点恢复正常显示。 +- 快速切换基地不会出现旧数据覆盖新数据的问题。 +- 多次切换 2D/3D 后基地裁切行为正常。 + +### Step 5:打通 3D popup 与 hover ✅️ 目标: @@ -233,7 +265,7 @@ - 样式和 2D 保持一致。 - 移出后 popup 正常消失。 -### Step 5:补齐缩放驱动显示与碰撞检测 +### Step 6:补齐缩放驱动显示与碰撞检测 目标: @@ -263,7 +295,7 @@ - 放大到具体层级后会看到更多锚点逐步出现。 - 标签和锚点不会大面积重叠到不可读。 -### Step 6:打通 3D 锚点点击详情 +### Step 7:打通 3D 锚点点击详情 ✅️ 目标: @@ -287,7 +319,7 @@ - `ylfb` 和普通锚点分支行为一致。 - 点击空白区域不会误触发弹框。 -### Step 7:打通图例联动 +### Step 8:打通图例联动 ✅️ 目标: @@ -305,7 +337,7 @@ - 图例单项勾选/取消时,3D 对应类别锚点同步显隐。 - 图例分组勾选/取消时,3D 行为与 2D 保持一致。 -### Step 8:补足收口与稳定性 +### Step 9:补足收口与稳定性 ✅️ 目标: @@ -329,7 +361,7 @@ 1. 默认定位到中国 + 启动动画 2. 展示基础底图 -3. 展示锚点 +3. 展示锚点 3.5. 补基地裁切(jdPanelControlShowAndHidden) 4. 补 hover popup 5. 补缩放驱动显示与碰撞检测 6. 补锚点点击详情 @@ -337,64 +369,6 @@ 8. 补图例联动 9. 做切换稳定性收口 -## 9. 必须补齐的隐藏逻辑清单 - -下面这些逻辑不是表面接口能直接看出来的,但如果 `3D` 不补,最终效果就会和 `2D` 明显不一致。 - -### 9.1 图层与菜单切换 - -- 菜单切换时,只隐藏旧页点图层,不隐藏底图。 -- 图层树勾选前要先经过互斥规则归一化: - - `rare_fish_point` 与 `fish_along_point` 互斥 - - `stinfo/stinfo_video_point` 与 `stinfo_ai_video_point` 互斥 - - `facilities` 与 `facilities_built` 两个分支互斥 -- 点图层取消勾选时只隐藏,不删除缓存;重新勾选时优先从缓存恢复。 - -### 9.2 图例与点内显隐 - -- 图例控制的是图层内部锚点是否可见,不是图层本身是否可见。 -- 图层恢复显示时,图例要先整层全关,再按当前 checked 状态逐项恢复。 -- 环保设施图例组当前是只展示不交互。 - -### 9.3 缩放驱动显示 - -- `eng_point` 的中型水电站只在 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上显示。 -- 水电开发页缩放跨过 `12` 级时,会自动补开一批动态图层;缩回去时再自动收口。 -- `2D` 存在“缩放越大显示越多”的行为,不是所有锚点在所有层级都等量显示。 -- `2D` 还存在 hover、批量 popup、密度控制等缩放阈值: - - hover 低于一定缩放不触发 - - 高缩放会进入批量 popup 模式 - - 点位会随着缩放提升逐步放开显示限制 - -### 9.4 锚点碰撞与控量 - -- `2D` 中锚点是否可见,不只受图层开关控制,还受以下门闩共同影响: - - 图例可见性 - - 区域裁切可见性 - - 密度阈值 - - 图标碰撞结果 - - 标签碰撞结果 -- 低缩放下,为避免堆叠,部分锚点或标签会被主动隐藏。 -- 高缩放下,会逐步放开图标/标签限制,显示更多内容。 -- 因此 `3D` 不能简单把所有 entity 永久全开,否则视觉密度会明显失控。 - -### 9.5 Popup 与点击 - -- hover popup 不是全时开启的,有缩放门槛。 -- 点击和 hover 的命中对象是图标本体,不是任意文字区域。 -- `ylfb` 与普通锚点的点击详情弹框走不同业务分支。 - -### 9.6 基地与区域裁切 - -- 基地切换不仅影响搜索候选,还会影响地图上的点位可见范围。 -- 区域裁切会直接把区域外点位隐藏,不是只改底图遮罩。 - -### 9.7 筛选器特殊逻辑 - -- 装机容量筛选本质是批量切 `eng_point` 图例状态,不是简单切图层。 -- 鱼类分布模式会接管 `ylfb_point` 的数据、缓存、图例与显隐。 -- 时间筛选当前只重载指定时间相关图层,不是全量重载。 - ## 7. 预计修改文件 - `src/components/gis/map.cesium.ts` @@ -415,3 +389,91 @@ - 默认飞到中国 这一步最小、最容易验证,也能先把“打开 3D 看起来不对”的核心问题解决掉。 + +## 9. 必须补齐的隐藏逻辑清单 + +下面这些逻辑不是表面接口能直接看出来的,但如果 `3D` 不补,最终效果就会和 `2D` 明显不一致。 + +### 9.1 图层与菜单切换 ✅️ + +- ✅ 菜单切换时,只隐藏旧页点图层,不隐藏底图。(编排器 `handlePageChange` 控制,Cesium 被动接收数据) +- ✅ 图层树勾选前要先经过互斥规则归一化:(store 层 `updateLayerData` 处理,Cesium 不感知) + - `rare_fish_point` 与 `fish_along_point` 互斥 + - `stinfo/stinfo_video_point` 与 `stinfo_ai_video_point` 互斥 + - `facilities` 与 `facilities_built` 两个分支互斥 +- ✅ 点图层取消勾选时只隐藏,不删除缓存;重新勾选时优先从缓存恢复。`mdLayerTreeShowOrHidden` 设置 `_layerVisible` 标志,不删除 `pointLayerRegistry` 条目。 +- ✅ **图层树勾选时按 `type` 字段走不同分支**(见 `updateLayerData`,store 层处理): + - `type === 'pointMap'` → 走 `handlePointMapLayer` → 调用 `mdLayerTreeShowOrHidden`(已实现,L1624) + - `type === 'GISMap'` → 走 `controlBaseLayerTreeShowAndHidden`(已实现,L1345) + - 3D Cesium 已同时实现这两个方法。 + +### 9.2 图例与点内显隐 ✅️ + +- ✅ 图例控制的是图层内部锚点是否可见,不是图层本身是否可见。`setLegendPointVisible` 使用 `_legendVisible` 标志,与 `_layerVisible` 独立。 +- ✅ 图层恢复显示时,图例要先整层全关,再按当前 checked 状态逐项恢复。支持 `anchoPointState=''` 全关 → 逐项 `(state, true)` 恢复两步模式(L1764-1787)。 +- ✅ 环保设施图例组当前是只展示不交互。(编排器层面控制,Cesium 不感知) + +### 9.3 缩放驱动显示 ✅️ + +- ✅ `eng_point` 的中型水电站只在 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上显示。(store `filterPointLayerDataForDisplay` 在数据进入 Cesium 前过滤) +- ✅ 水电开发页缩放跨过 `12` 级时,会自动补开一批动态图层;缩回去时再自动收口。(编排器层面处理) +- ✅ `2D` 存在"缩放越大显示越多"的行为。碰撞检测中密度门控逐级放开。 +- ✅ `2D` 还存在 hover、批量 popup、密度控制等缩放阈值: + - hover 低于 ~zoom 4.5 不触发(`HOVER_POPUP_MAX_HEIGHT = 9_000_000`) + - 高缩放进入批量 popup 模式(`BATCH_POPUP_MODE_ZOOM = 14.9`) + - 点位随着缩放提升逐步放开密度限制(密度门控 + `DENSITY_ISOLATION_THRESHOLD`) +- ✅ **图标动态缩放**:`CallbackProperty` 实现 `billboard.scale`,公式 `clamp(0.7 + (zoom - 4.5) * 0.035, 0.4, 1.2)`(L1522)。 +- ✅ **字体动态大小**:`CallbackProperty` 实现 `label.font`,钳位 `[10, 20]`(L1535)。 +- ✅ **文字在图标上方**:`CallbackProperty` 实现 `label.pixelOffset`,负 Y 偏移(L1549)。 +- ✅ **Cesium 中必须使用 `CallbackProperty` 实现动态缩放**:已使用 3 个 `CallbackProperty`(scale/font/offset),`isConstant=false` 每帧重算。 + +### 9.4 锚点碰撞与控量 ✅️ + +- ✅ `2D` 中锚点是否可见,不只受图层开关控制,还受以下门闩共同影响: + - 图例可见性 `_legendVisible` + - 区域裁切可见性 `_regionVisible` + - 密度阈值(碰撞循环中 inline 计算,逐级放开) + - 图标碰撞结果 `_iconCollisionVisible` + - 标签碰撞结果 `_labelCollisionVisible` +- ✅ 低缩放下,为避免堆叠,部分锚点或标签会被主动隐藏。(`refreshPointLabelVisibility` 碰撞检测,L2117-2455) +- ✅ 高缩放下,会逐步放开图标/标签限制,显示更多内容。(密度门控 + 碰撞容差随 zoom 调整) +- ✅ 因此 `3D` 不能简单把所有 entity 永久全开。所有 entity 初始 `_iconCollisionVisible = _labelCollisionVisible = true`,碰撞检测运行后动态调整。 + +### 9.5 Popup 与点击 ✅️ + +- ✅ hover popup 不是全时开启的,有缩放门槛。相机高度 > `HOVER_POPUP_MAX_HEIGHT` 时不触发 hover。 +- ✅ 点击和 hover 的命中对象是图标本体,不是任意文字区域。`ScreenSpaceEventHandler` 基于 `scene.pick` 命中 entity。 +- ✅ `ylfb` 与普通锚点的点击详情弹框走不同业务分支。`sttpMap === 'ylfb'` 打开 `ylfbModalVisible`,其他走 `modalVisible`(L366-375)。 + +### 9.6 基地与区域裁切 ✅️ + +- ✅ 基地切换不仅影响搜索候选,还会影响地图上的点位可见范围。`jdPanelControlShowAndHidden` 实现(L1684-1748)。 +- ✅ 区域裁切会直接把区域外点位隐藏,不是只改底图遮罩。`filterPointsByRegion` 设置 `_regionVisible = false`(L1824-1848),遮罩多边形 + 裁剪双重处理。 + +### 9.7 筛选器特殊逻辑 ✅️ + +- ✅ 装机容量筛选本质是批量切 `eng_point` 图例状态,不是简单切图层。(store 层处理,Cesium 通过 `setLegendPointVisible` 响应) +- ✅ 鱼类分布模式会接管 `ylfb_point` 的数据、缓存、图例与显隐。(store 层处理) +- ✅ 时间筛选当前只重载指定时间相关图层,不是全量重载。(store 层处理) + +### 9.8 数据进入 addInitDataLayer 前的预处理 ✅️ + +- ✅ 所有点位数据在进入 `addInitDataLayer` 前会经过 `normalizePointLayerItems()` 过滤:(store 层 `map.ts` 执行,Cesium 接收时已过滤) + - 没有 `iconCode` 且 `code !== 'colorLayer'` 的项会被抛弃 + - `baseId == 'all'` 且 `anchoPointState` 结尾为 `_nbuilt` 的项会被抛弃 +- ✅ `_id` 默认值生成规则:store 层生成 `${sttpMap || iconType || 'point'}_${stcd}`。 +- ✅ **stcd+经纬度重复锚点处理**:Cesium entity ID 使用 `${layerKey}:${item._id}`,与 2D 对齐,同 stcd 不同 sttpMap 的点不会互相覆盖。 + +### 9.9 图标渐进加载机制 + +- ❌ 2D 中图标不是一次性全加载完。有 `loading → loaded → error` 三种状态跟踪。 +- ❌ 只有 `loaded` 状态的图标才参与样式渲染,loader 失败的不渲染。 +- ❌ 如果在图标加载过程中就触发了样式刷新,需要通过 `requestAnimationFrame` 回刷。 +- ❌ 3D Cesium 中当前所有 entity 同步创建,billboard `image` URL 直接赋值,无渐进加载。Cesium 内部纹理加载无显式状态跟踪。 + +### 9.10 密度分档与近邻点元数据 ✅️ + +- ✅ 每个锚点的 `distance` 字段表示密度分档值(不是物理距离),值越大表示越稀疏。(已使用 `getEntityDensityValue` 从 `_rawData.distance` 读取,L2460) +- ✅ 不同 density 值对应不同的 `minZoom` 显示门槛。`getEntityDensityMinZoom` 映射 `nearby-point-rules.ts` 的 `densityDisplayRules`(L2491)。 +- ✅ 全量数据加载后,store 会调用 `attachNearbyPointRuntimeMeta()` 给所有点打上 `_nearbyRule`、`_nearbyGroupId`、`_nearbyPriority` 等元数据。(store 层处理,Cesium 碰撞检测中读取) +- ✅ **孤立点例外规则**:如果一个点在当前视口内 ~56px 范围内没有同 layerKey 的其他可见点,它可以绕过密度门槛直接显示。`DENSITY_ISOLATION_THRESHOLD = 56` + `shouldBypassDensityGateForIsolatedEntity`(L2506-2556)。 diff --git a/frontend/src/api/home/index.ts b/frontend/src/api/home/index.ts index 1f2ac831..0c450a18 100644 --- a/frontend/src/api/home/index.ts +++ b/frontend/src/api/home/index.ts @@ -79,6 +79,16 @@ export function vmsstbprptGetKendoList(data: any) { data: data }); } +// 环保自动监测工作开展情弹窗 +export function overviewvmsstbprptGetKendoList(data: any) { + return request({ + url: '/overview/vmsstbprpt/GetKendoList', + method: 'post', + data: data + }); +} + + // 获取基本信息 export function baseMsstbprptGetKendoList(data: any) { diff --git a/frontend/src/api/system/map/TiltPhotoManagement/index.ts b/frontend/src/api/system/map/TiltPhotoManagement/index.ts index b6ee61fc..5b041a97 100644 --- a/frontend/src/api/system/map/TiltPhotoManagement/index.ts +++ b/frontend/src/api/system/map/TiltPhotoManagement/index.ts @@ -1,9 +1,9 @@ import request from '@/utils/request'; - + // 获取所有倾斜摄影 export function getAllTiltPhotoTree(data: any) { return request({ - url: '/api/wmp-sys-server/sys/oblique/GetKendoListCust', + url: '/sys/oblique/GetKendoListCust', method: 'post', data: data }); @@ -11,7 +11,7 @@ export function getAllTiltPhotoTree(data: any) { // 保存倾斜摄影 export function saveTiltPhoto(data: any) { return request({ - url: '/api/wmp-sys-server/sys/oblique/addOrUpdate', + url: '/sys/oblique/addOrUpdate', method: 'post', data: data }); @@ -19,7 +19,7 @@ export function saveTiltPhoto(data: any) { // 删除倾斜摄影 export function deleteTiltPhoto(data: any) { return request({ - url: '/api/wmp-sys-server/sys/oblique/delete', + url: '/sys/oblique/delete', method: 'get', params: data }); diff --git a/frontend/src/components/BasicSearch/index.vue b/frontend/src/components/BasicSearch/index.vue index 1a500565..1df4f7c2 100644 --- a/frontend/src/components/BasicSearch/index.vue +++ b/frontend/src/components/BasicSearch/index.vue @@ -468,7 +468,7 @@ const triggerManualValuesChange = (changedKey: string, newValue: any) => { emit('valuesChange', changedValues, { ...formData }); }; -const dataDimensionDataChange = (value: any, fieldName: string = 'baseId') => { +const dataDimensionDataChange = (value: any, fieldName = 'baseId') => { formData[fieldName] = value; formData.rstcd = ""; shuJuTianBaoStore.getEngOption(value,'baseId'); diff --git a/frontend/src/components/BasicTable/index.vue b/frontend/src/components/BasicTable/index.vue index 5f5d7990..716cc092 100644 --- a/frontend/src/components/BasicTable/index.vue +++ b/frontend/src/components/BasicTable/index.vue @@ -192,6 +192,7 @@ const getList = async (filter?: Record) => { total.value = 0; if (filter !== undefined) { lastFilter.value = filter; + page.value = 1; } try { // 合并排序参数:优先使用用户手动排序,否则使用 searchParams 中的默认排序 diff --git a/frontend/src/components/carouselIntroduce/ArtsDetail.vue b/frontend/src/components/carouselIntroduce/ArtsDetail.vue index b0d95b82..e2e1de19 100644 --- a/frontend/src/components/carouselIntroduce/ArtsDetail.vue +++ b/frontend/src/components/carouselIntroduce/ArtsDetail.vue @@ -5,7 +5,7 @@