diff --git a/frontend/src/api/mapModal/index.ts b/frontend/src/api/mapModal/index.ts index cf193cee..7c950db1 100644 --- a/frontend/src/api/mapModal/index.ts +++ b/frontend/src/api/mapModal/index.ts @@ -549,3 +549,28 @@ export function getFlowDischargeList(code: string, data: any) { data }); } + +// 智慧装备 - 动物 鸟类 +export function getAnimalList(data: any) { + return request({ + url: '/wte/anml/run/GetKendoListCust', + method: 'post', + data + }); +} +// 智慧装备 - 钓鱼、违章监测、漂浮物识别装置、叠梁门运行识别装置 +export function getWarningList(data: any) { + return request({ + url: '/warn/ai/com/GetKendoListCust', + method: 'post', + data + }); +} +// 智慧装备 - 鱼类调查装置 鱼类智能识别装置 智能分拣装置 +export function getFishList(data: any) { + return request({ + url: '/wte/fp/ai/GetKendoListCust', + method: 'post', + data + }); +} diff --git a/frontend/src/api/sz/index.ts b/frontend/src/api/sz/index.ts index 1bc7f06c..13a3772d 100644 --- a/frontend/src/api/sz/index.ts +++ b/frontend/src/api/sz/index.ts @@ -69,7 +69,15 @@ export function stbprpGetStbprpYsByStcd(data: any) { return request({ url: '/wq/stbprp/GetStbprpYsByStcd', method: 'get', - params:data + params: data + }); +} +//水质监测工作开展情况 - wte接口 +export function vmsstbprptGetKendoListWte(data: any) { + return request({ + url: '/wte/vmsstbprpt/GetKendoList', + method: 'post', + data }); } //表格数据获取函数 @@ -86,4 +94,12 @@ export function NodataGetKendoListCust(data: any) { method: 'post', data }); -} \ No newline at end of file +} +// 各基地社保统计 +export function imeBaseDeviceStat(data: any) { + return request({ + url: '/ime/base/device/stat', + method: 'post', + data + }); +} diff --git a/frontend/src/assets/legend/map-dlmsb.svg b/frontend/src/assets/legend/map-dlmsb.svg new file mode 100644 index 00000000..bb690a54 --- /dev/null +++ b/frontend/src/assets/legend/map-dlmsb.svg @@ -0,0 +1,23 @@ + + + + +map-qixidi + + + + + + + + diff --git a/frontend/src/assets/legend/map-dwsb.svg b/frontend/src/assets/legend/map-dwsb.svg new file mode 100644 index 00000000..862d06db --- /dev/null +++ b/frontend/src/assets/legend/map-dwsb.svg @@ -0,0 +1,47 @@ + + + + +map-qixidi + + + + + + + + + + + + + + + diff --git a/frontend/src/assets/legend/map-dy.svg b/frontend/src/assets/legend/map-dy.svg new file mode 100644 index 00000000..141b2bf1 --- /dev/null +++ b/frontend/src/assets/legend/map-dy.svg @@ -0,0 +1,30 @@ + + + + +map-qixidi + + + + + + + + + + + diff --git a/frontend/src/assets/legend/map-hdsb.svg b/frontend/src/assets/legend/map-hdsb.svg new file mode 100644 index 00000000..0ede66a4 --- /dev/null +++ b/frontend/src/assets/legend/map-hdsb.svg @@ -0,0 +1,54 @@ + + + + +map-qixidi + + + + + + + + + + + diff --git a/frontend/src/assets/legend/map-nlsb.svg b/frontend/src/assets/legend/map-nlsb.svg new file mode 100644 index 00000000..d38f102e --- /dev/null +++ b/frontend/src/assets/legend/map-nlsb.svg @@ -0,0 +1,35 @@ + + + + +map-qixidi + + + + + + + + + diff --git a/frontend/src/assets/legend/map-pfwsb.svg b/frontend/src/assets/legend/map-pfwsb.svg new file mode 100644 index 00000000..73928127 --- /dev/null +++ b/frontend/src/assets/legend/map-pfwsb.svg @@ -0,0 +1,31 @@ + + + + +map-qixidi + + + + + + + + diff --git a/frontend/src/assets/legend/map-yldc.svg b/frontend/src/assets/legend/map-yldc.svg new file mode 100644 index 00000000..e21003f1 --- /dev/null +++ b/frontend/src/assets/legend/map-yldc.svg @@ -0,0 +1,49 @@ + + + + +map-qixidi + + + + + + + + + + + + + + + diff --git a/frontend/src/assets/legend/map-ylsb.svg b/frontend/src/assets/legend/map-ylsb.svg new file mode 100644 index 00000000..dbbf2fe8 --- /dev/null +++ b/frontend/src/assets/legend/map-ylsb.svg @@ -0,0 +1,44 @@ + + + + +map-qixidi + + + + + + + + + + + + diff --git a/frontend/src/assets/legend/map-znfj.svg b/frontend/src/assets/legend/map-znfj.svg new file mode 100644 index 00000000..c7065d1d --- /dev/null +++ b/frontend/src/assets/legend/map-znfj.svg @@ -0,0 +1,31 @@ + + + + +map-qixidi + + + + + + + + + + diff --git a/frontend/src/components/MapModal/column.config.ts b/frontend/src/components/MapModal/column.config.ts index 7af9f682..3ddcd021 100644 --- a/frontend/src/components/MapModal/column.config.ts +++ b/frontend/src/components/MapModal/column.config.ts @@ -2741,8 +2741,8 @@ const StinfoAiVidoPointColumns: Array = [ url: '' }, { - name: '监控内容类型', - filed: 'sttpName', + name: '监控方式', + filed: 'mwayName', visible: true, type: 'select', url: '' diff --git a/frontend/src/components/MapModal/components/BasicInfo.vue b/frontend/src/components/MapModal/components/BasicInfo.vue index 7c0a223b..75e2ac3d 100644 --- a/frontend/src/components/MapModal/components/BasicInfo.vue +++ b/frontend/src/components/MapModal/components/BasicInfo.vue @@ -344,7 +344,15 @@ const columnsConfig = ref([ { type: 'MM', columns: MMColumns - } + }, + { type: 'AI_FISH', columns: StinfoAiVidoPointColumns }, + { type: 'AI_ANML', columns: StinfoAiVidoPointColumns }, + { type: 'AI_BIRD', columns: StinfoAiVidoPointColumns }, + { type: 'AI_RIV', columns: StinfoAiVidoPointColumns }, + { type: 'AI_FISHING', columns: StinfoAiVidoPointColumns }, + { type: 'AI_5001', columns: StinfoAiVidoPointColumns }, + { type: 'AI_5005', columns: StinfoAiVidoPointColumns }, + { type: 'AI_SORTER', columns: StinfoAiVidoPointColumns } //DW_1 ]); diff --git a/frontend/src/components/MapModal/components/zhzbMonitorInfo.vue b/frontend/src/components/MapModal/components/zhzbMonitorInfo.vue new file mode 100644 index 00000000..1d1abe15 --- /dev/null +++ b/frontend/src/components/MapModal/components/zhzbMonitorInfo.vue @@ -0,0 +1,217 @@ + + + diff --git a/frontend/src/components/MapModal/index.vue b/frontend/src/components/MapModal/index.vue index fc6691b4..1b836bac 100644 --- a/frontend/src/components/MapModal/index.vue +++ b/frontend/src/components/MapModal/index.vue @@ -121,6 +121,12 @@ :is-active="currentActiveKey === 'DZGJ'" :tabs-items="getTabChildren('DZGJ')" /> + + + { eqtp: '', baseId: '', sttpCode: '', - sttpMap: '' + sttpMap: '', + dtinType: '', + bldstt: '', + bldsttCcode: '' }; // 清理状态,避免影响下次打开 modelStore.showStcdSelector = false; @@ -904,6 +914,7 @@ const handleClose = () => { modelStore.aiSites = []; modelStore.wtConfig = {}; modelStore.filter = { + year: '', stllgzlx: '', // 生态流量 - 规则类型 stllTmType: '', // 生态流量 - 时间类型 tm: '', diff --git a/frontend/src/components/MapModal/setting.config.ts b/frontend/src/components/MapModal/setting.config.ts index d60bcf96..06177e59 100644 --- a/frontend/src/components/MapModal/setting.config.ts +++ b/frontend/src/components/MapModal/setting.config.ts @@ -728,6 +728,17 @@ const DEVICETABS: Array = [ type: 'basic', url: '/eng/base/msstbprpt/getStcdInfo', default: true // 默认显示 + }, + { + name: '监测数据', + key: 'zhzbMonitorInfo', + type: 'zhzbMonitorInfo' + }, + { + name: '实时视频', + key: 'videoInfo', + type: 'video', + url: '/video/dataStcdFrame/getVideoMonitorList' } ]; // //电站告警 @@ -1232,6 +1243,16 @@ const handleTabs = (modaldata: any) => { // return WETabs case 'MM': return WeatherTabs; + case 'AI_FISH': // 智慧装备 + case 'AI_ANML': + case 'AI_BIRD': + case 'AI_RIV': + case 'AI_FISHING': + case 'AI_5001': + case 'AI_5005': + case 'AI_SORTER': + return DEVICETABS; + // case 'WARN': // return WaterQualityMonitoring // case 'AI': diff --git a/frontend/src/components/gis/map.ol.ts b/frontend/src/components/gis/map.ol.ts index bd58dd4b..100f4905 100644 --- a/frontend/src/components/gis/map.ol.ts +++ b/frontend/src/components/gis/map.ol.ts @@ -2013,10 +2013,10 @@ export class MapOl implements MapInterface { } /** * 获取当前应应用基地裁切的底图图层集合 - * @returns 当前可见底图图层列表 + * @returns 当前可见底图图层列表(包括底图栅格和栖息地图层、自然保护区图层等矢量图层) */ - private getCurrentMaskTargetLayers(): TileLayer[] { - const layers: TileLayer[] = []; + private getCurrentMaskTargetLayers(): (TileLayer | VectorLayer)[] { + const layers: (TileLayer | VectorLayer)[] = []; const baseLayer = this.layerRegistry.get(this.REGISTRY_KEY); if (baseLayer instanceof TileLayer) { @@ -2033,6 +2033,19 @@ export class MapOl implements MapInterface { } } + // 遍历所有图层注册表,收集所有可见的 TileLayer 和 VectorLayer + // 这会自动包括栖息地图层、自然保护区图层等已勾选显示的基础图层 + this.layerRegistry.forEach((layerInstance, layerKey) => { + if ( + (layerInstance instanceof TileLayer || + layerInstance instanceof VectorLayer) && + layerInstance.getVisible() && + !layers.includes(layerInstance) + ) { + layers.push(layerInstance); + } + }); + return layers; } /** @@ -2173,6 +2186,23 @@ export class MapOl implements MapInterface { if (this.isBatchPopupMode) { this.requestUpdateBatchPopups(true); } + // 如果当前处于基地裁切状态且图层显示,确保裁切事件已绑定 + if ( + this.currentClipGeoJson && + checked && + (layerInstance instanceof TileLayer || + layerInstance instanceof VectorLayer) + ) { + // 检查该图层是否已经绑定过裁切事件,如果没有则追加 + const hasBinding = + this.regionMaskManager.hasLayerBinding(layerInstance); + if (!hasBinding) { + this.regionMaskManager.appendMaskToLayer( + layerInstance, + this.currentClipGeoJson + ); + } + } } else { console.warn( `未找到标识为 [${registryKey}] 的图层实例,当前注册表 keys:`, diff --git a/frontend/src/components/gis/ol/region-mask-manager.ts b/frontend/src/components/gis/ol/region-mask-manager.ts index 10989037..24ffad82 100644 --- a/frontend/src/components/gis/ol/region-mask-manager.ts +++ b/frontend/src/components/gis/ol/region-mask-manager.ts @@ -1,11 +1,18 @@ import OlMap from 'ol/Map'; import View from 'ol/View'; import TileLayer from 'ol/layer/Tile'; +import VectorLayer from 'ol/layer/Vector'; import GeoJSON from 'ol/format/GeoJSON'; import VectorSource from 'ol/source/Vector'; import { fromLonLat } from 'ol/proj'; import { PointLayerManager } from './point-layer-manager'; +type MaskBinding = { + layer: TileLayer | VectorLayer; + prerender: (event: any) => void; + postrender: (event: any) => void; +}; + type RegionMaskManagerOptions = { map: OlMap | null; view: View | null; @@ -20,11 +27,7 @@ export class RegionMaskManager { private pointLayerManager: PointLayerManager; private defaultCenter: [number, number]; private defaultZoom: number; - private maskBindings: Array<{ - layer: TileLayer; - prerender: (event: any) => void; - postrender: (event: any) => void; - }> = []; + private maskBindings: Array = []; constructor(options: RegionMaskManagerOptions) { this.map = options.map; @@ -76,7 +79,10 @@ export class RegionMaskManager { return; } - feature.set('_regionVisible', this.isPointInPolygon(lon, lat, regionCoords)); + feature.set( + '_regionVisible', + this.isPointInPolygon(lon, lat, regionCoords) + ); feature.changed(); }); } @@ -114,12 +120,18 @@ export class RegionMaskManager { } // 备注:把 GeoJSON 边界绑定到底图 prerender/postrender 事件,实现区域裁切遮罩。 - applyMapMask(rasterLayer: TileLayer, clipGeoJson: any): void { + applyMapMask( + rasterLayer: TileLayer | VectorLayer, + clipGeoJson: any + ): void { this.applyMapMaskToLayers(rasterLayer ? [rasterLayer] : [], clipGeoJson); } - // 备注:把 GeoJSON 边界同时绑定到多个底图图层,保证多底图叠加场景下裁切边界保持一致。 - applyMapMaskToLayers(rasterLayers: TileLayer[] = [], clipGeoJson: any): void { + // 备注:把 GeoJSON 边界同时绑定到多个底图图层和矢量图层,保证多图层叠加场景下裁切边界保持一致。 + applyMapMaskToLayers( + rasterLayers: (TileLayer | VectorLayer)[] = [], + clipGeoJson: any + ): void { if (!clipGeoJson) return; const targetLayers = rasterLayers.filter(Boolean); @@ -162,7 +174,9 @@ export class RegionMaskManager { } } } else if (geometry.getType() === 'MultiPolygon') { - const polygons = (geometry as any).getCoordinates() as number[][][][]; + const polygons = ( + geometry as any + ).getCoordinates() as number[][][][]; for (const polygonRings of polygons) { for (const ring of polygonRings) { if (this.drawRingToContext(context, ring, frameState)) { @@ -208,6 +222,93 @@ export class RegionMaskManager { }); } + // 备注:给单个图层追加裁切,不破坏已有裁切绑定。用于新图层动态加入时复用当前裁切边界。 + appendMaskToLayer( + layer: TileLayer | VectorLayer, + clipGeoJson: any + ): void { + if (!clipGeoJson || !layer) return; + // 避免重复绑定 + if (this.hasLayerBinding(layer)) return; + + const features = new GeoJSON().readFeatures(clipGeoJson, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); + + if (!features.length) return; + + const maskPrerender = (event: any) => { + const context = event.context; + const frameState = event.frameState; + + if (!context || !frameState || !this.map) return; + + context.save(); + context.setTransform(1, 0, 0, 1, 0, 0); + context.beginPath(); + + let hasValidPath = false; + + for (const feature of features) { + const geometry = feature.getGeometry(); + if (!geometry) continue; + + if (geometry.getType() === 'Polygon') { + const rings = (geometry as any).getCoordinates() as number[][][]; + for (const ring of rings) { + if (this.drawRingToContext(context, ring, frameState)) { + hasValidPath = true; + } + } + } else if (geometry.getType() === 'MultiPolygon') { + const polygons = (geometry as any).getCoordinates() as number[][][][]; + for (const polygonRings of polygons) { + for (const ring of polygonRings) { + if (this.drawRingToContext(context, ring, frameState)) { + hasValidPath = true; + } + } + } + } + } + + if (!hasValidPath) return; + + context.save(); + context.lineWidth = 6; + context.strokeStyle = '#6D64DF'; + context.stroke(); + context.clip(); + context.strokeStyle = '#CCC9F4'; + context.lineWidth = 5; + context.stroke(); + context.clip(); + }; + + const maskPostrender = (event: any) => { + if (event.context) { + event.context.restore(); + event.context.restore(); + } + }; + + this.maskBindings.push({ + layer, + prerender: maskPrerender, + postrender: maskPostrender + }); + + layer.on('prerender', maskPrerender); + layer.on('postrender', maskPostrender); + layer.changed(); + } + + // 备注:检查某个图层是否已经绑定了裁切事件,避免重复绑定。 + hasLayerBinding(layer: TileLayer | VectorLayer): boolean { + return this.maskBindings.some(binding => binding.layer === layer); + } + // 备注:清除当前底图遮罩并按需恢复默认视野,供切换基地和异常兜底复用。 clearMapMask(resetView = true): void { const maskedLayers = this.maskBindings.map(binding => binding.layer); @@ -308,7 +409,9 @@ export class RegionMaskManager { continue; } - const cssPixel = this.map?.getPixelFromCoordinate(coord as [number, number]); + const cssPixel = this.map?.getPixelFromCoordinate( + coord as [number, number] + ); if (!cssPixel) continue; const canvasX = cssPixel[0] * pixelRatio; diff --git a/frontend/src/components/mapFilter/index.vue b/frontend/src/components/mapFilter/index.vue index 01b82033..30ee3610 100644 --- a/frontend/src/components/mapFilter/index.vue +++ b/frontend/src/components/mapFilter/index.vue @@ -1,8 +1,5 @@