diff --git a/.gitignore b/.gitignore index e286fb0..88d6df5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ npm-debug.log* yarn-debug.log* yarn-error.log* **/*.log +# 忽略所有 .tif 文件 +*.tif + tests/**/coverage/ tests/e2e/reports diff --git a/src/api/safety/recognizeRecord/index.ts b/src/api/safety/recognizeRecord/index.ts new file mode 100644 index 0000000..b197db7 --- /dev/null +++ b/src/api/safety/recognizeRecord/index.ts @@ -0,0 +1,63 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; +import { RecognizeRecordVO, RecognizeRecordForm, RecognizeRecordQuery } from '@/api/safety/recognizeRecord/types'; + +/** + * 查询识别记录列表 + * @param query + * @returns {*} + */ + +export const listRecognizeRecord = (query?: RecognizeRecordQuery): AxiosPromise => { + return request({ + url: '/safety/recognizeRecord/list', + method: 'get', + params: query + }); +}; + +/** + * 查询识别记录详细 + * @param id + */ +export const getRecognizeRecord = (id: string | number): AxiosPromise => { + return request({ + url: '/safety/recognizeRecord/' + id, + method: 'get' + }); +}; + +/** + * 新增识别记录 + * @param data + */ +export const addRecognizeRecord = (data: RecognizeRecordForm) => { + return request({ + url: '/safety/recognizeRecord', + method: 'post', + data: data + }); +}; + +/** + * 修改识别记录 + * @param data + */ +export const updateRecognizeRecord = (data: RecognizeRecordForm) => { + return request({ + url: '/safety/recognizeRecord', + method: 'put', + data: data + }); +}; + +/** + * 删除识别记录 + * @param id + */ +export const delRecognizeRecord = (id: string | number | Array) => { + return request({ + url: '/safety/recognizeRecord/' + id, + method: 'delete' + }); +}; diff --git a/src/api/safety/recognizeRecord/types.ts b/src/api/safety/recognizeRecord/types.ts new file mode 100644 index 0000000..ea92de7 --- /dev/null +++ b/src/api/safety/recognizeRecord/types.ts @@ -0,0 +1,125 @@ +export interface RecognizeRecordVO { + /** + * 设备名称 + */ + deviceName: string; + + /** + * 识别类别(1无人机识别 2监控拍摄) + */ + recordCategory: string; + + /** + * 违章类型(多个逗号分隔) + */ + violationType: string; + + /** + * 图片路径 + */ + picture: string; + + /** + * 图片路径Url + */ + pictureUrl: string; + /** + * 故障描述 + */ + describe: string; + + /** + * 创建时间 + */ + createTime: string; + +} + +export interface RecognizeRecordForm extends BaseEntity { + /** + * 主键id + */ + id?: string | number; + + /** + * 项目id + */ + projectId?: string | number; + + /** + * 设备序列号 + */ + deviceSerial?: string; + + /** + * 设备名称 + */ + deviceName?: string; + + /** + * 识别类别(1无人机识别 2监控拍摄) + */ + recordCategory?: string; + + /** + * 违章类型(多个逗号分隔) + */ + violationType?: string; + + /** + * 图片路径 + */ + picture?: string; + + /** + * 违规数量 + */ + num?: number; + + /** + * 故障描述 + */ + describe?: string; + + /** + * 备注 + */ + remark?: string; + +} + +export interface RecognizeRecordQuery extends PageQuery { + + /** + * 项目id + */ + projectId?: string | number; + + /** + * 设备名称 + */ + deviceName?: string; + + /** + * 识别类别(1无人机识别 2监控拍摄) + */ + recordCategory?: string; + + /** + * 违章类型(多个逗号分隔) + */ + violationType?: string; + + /** + * 创建时间 + */ + createTime?: string; + + /** + * 日期范围参数 + */ + params?: any; +} + + + diff --git a/src/views/progress/progressPaper/index.vue b/src/views/progress/progressPaper/index.vue index 25600e4..94f36f7 100644 --- a/src/views/progress/progressPaper/index.vue +++ b/src/views/progress/progressPaper/index.vue @@ -82,6 +82,7 @@ import Static from 'ol/source/ImageStatic'; import proj4 from 'proj4'; import { register } from 'ol/proj/proj4'; import gcoord from 'gcoord'; +import { createXYZ } from 'ol/tilegrid'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const orthophoto = '@/assets/images/orthophoto.tif'; const selector = ref(null); @@ -408,53 +409,109 @@ const getList = async () => { const imageExtent = ref(null); const imageLayer = ref(null); +import { get as getProjection } from 'ol/proj'; + const initGeoTiff = async () => { - const tiff = await fromUrl('/image/clean_rgba_cleaned.tif'); - const image = await tiff.getImage(); - const width = image.getWidth(); - const height = image.getHeight(); - const bbox = image.getBoundingBox(); // [minX, minY, maxX, maxY] - console.log('bbox', bbox); - const rasters = await image.readRasters({ interleave: true }); - // 创建 Canvas - const canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = height; - const ctx = canvas.getContext('2d')!; - const imageData: any = ctx.createImageData(width, height); - // 设置 RGBA 数据 - imageData.data.set(rasters); // ✅ 完整设置,不用手动循环 - ctx.putImageData(imageData, 0, 0); - // 将 canvas 转成 Data URL 用作图层 source - const imageUrl = canvas.toDataURL(); - // 转换为 WGS84 经纬度 - const minLonLat = transform([bbox[0], bbox[1]], 'EPSG:32648', 'EPSG:4326'); - const maxLonLat = transform([bbox[2], bbox[3]], 'EPSG:32648', 'EPSG:4326'); - // 转为 GCJ02(高德地图坐标系) - const gcjMin = gcoord.transform(minLonLat as [number, number, number], gcoord.WGS84, gcoord.GCJ02); - const gcjMax = gcoord.transform(maxLonLat as [number, number, number], gcoord.WGS84, gcoord.GCJ02); - // 再转 EPSG:3857 供 OpenLayers 使用 + // const tiff = await fromUrl('/image/clean_rgba_cleaned.tif'); + // const image = await tiff.getImage(); + // const width = image.getWidth(); + // const height = image.getHeight(); + // const bbox = image.getBoundingBox(); // [minX, minY, maxX, maxY] + // console.log('bbox', bbox); + // const rasters = await image.readRasters({ interleave: true }); + // // 创建 Canvas + // const canvas = document.createElement('canvas'); + // canvas.width = width; + // canvas.height = height; + // const ctx = canvas.getContext('2d')!; + // const imageData: any = ctx.createImageData(width, height); + // // 设置 RGBA 数据 + // imageData.data.set(rasters); // ✅ 完整设置,不用手动循环 + // ctx.putImageData(imageData, 0, 0); + // // 将 canvas 转成 Data URL 用作图层 source + // const imageUrl = canvas.toDataURL(); + // // 转换为 WGS84 经纬度 + // const minLonLat = transform([bbox[0], bbox[1]], 'EPSG:32648', 'EPSG:4326'); + // const maxLonLat = transform([bbox[2], bbox[3]], 'EPSG:32648', 'EPSG:4326'); + // // 转为 GCJ02(高德地图坐标系) + // const gcjMin = gcoord.transform(minLonLat as [number, number, number], gcoord.WGS84, gcoord.GCJ02); + // const gcjMax = gcoord.transform(maxLonLat as [number, number, number], gcoord.WGS84, gcoord.GCJ02); + // // 再转 EPSG:3857 供 OpenLayers 使用 + // const minXY = fromLonLat(gcjMin); + // const maxXY = fromLonLat(gcjMax); + + // imageExtent.value = [...minXY, ...maxXY]; + + // imageLayer.value = new ImageLayer({ + // source: new Static({ + // url: imageUrl, + // imageExtent: imageExtent.value, + // projection: 'EPSG:3857' + // }) + // }); + // console.log('imageExtent', imageExtent.value); + + // 1. 你的原始瓦片的边界(来自 .tfw 或你知道的数据) + + // 1. 你的 bbox 是 WGS84 经纬度 + const bbox = [107.13149481208748, 23.80411597354268, 107.13487254421389, 23.80801427852998]; + + // 2. 转成 GCJ02(高德坐标系) + const gcjMin = gcoord.transform([bbox[0], bbox[1]], gcoord.WGS84, gcoord.GCJ02); + const gcjMax = gcoord.transform([bbox[2], bbox[3]], gcoord.WGS84, gcoord.GCJ02); + + // 3. 再转换成 EPSG:3857,用于 OpenLayers const minXY = fromLonLat(gcjMin); const maxXY = fromLonLat(gcjMax); - imageExtent.value = [...minXY, ...maxXY]; + // 4. 组成瓦片范围 extent + const tileExtent = [...minXY, ...maxXY]; + console.log('tileExtent', tileExtent); - imageLayer.value = new ImageLayer({ - source: new Static({ - url: imageUrl, - imageExtent: imageExtent.value, - projection: 'EPSG:3857' + // 5. 创建 tileGrid + const tileGrid = createXYZ({ + extent: tileExtent, + tileSize: 256, + minZoom: 10, + maxZoom: 18 + }); + + // 6. 使用 Web Mercator 投影 EPSG:3857 + const projection = getProjection('EPSG:3857'); + + // 7. 创建瓦片图层 + imageLayer.value = new TileLayer({ + source: new XYZ({ + projection, + tileGrid, + tileUrlFunction: (tileCoord) => { + if (!tileCoord) return ''; + let [z, x, y] = tileCoord; + console.log(z, x, y); + y = Math.pow(2, z) - y - 1; + return `http://192.168.110.2:8000/api/projects/3/tasks/c2e3227f-343f-48b1-88c0-1432d6eab33f/orthophoto/tiles/${z}/${x}/${y}`; + } }) }); - console.log('imageExtent', imageExtent.value); + const source = imageLayer.value.getSource(); + const projections = source.getProjection(); + + console.log('图层使用的坐标系:', projections?.getCode()); }; let map: any = null; const layerData = reactive({}); const centerPosition = ref(fromLonLat([107.12932403398425, 23.805564054229908])); const initOLMap = () => { - // 创造地图实例 - const borderLayer = createExtentBorderLayer(imageExtent.value); + console.log(111); + // const scoure = new TileLayer({ + // // 设置图层的数据源为XYZ类型。XYZ是一个通用的瓦片图层源,它允许你通过URL模板来获取瓦片 + // source: new XYZ({ + // url: 'http://192.168.110.2:8000/api/projects/3/tasks/c2e3227f-343f-48b1-88c0-1432d6eab33f/orthophoto/tiles/{z}/{x}/{y}' + // }) + // }); + // console.log(scoure); + map = new Map({ // 设置地图容器的ID target: 'olMap', @@ -473,8 +530,9 @@ const initOLMap = () => { source: new XYZ({ url: 'http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8' }) - }), - imageLayer.value + }) + // imageLayer.value + // imageLayer.value ], // 设置地图的视图参数 // View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。 @@ -790,10 +848,10 @@ const toggleFeatureHighlight = (feature: Feature, addIfNotExist = true) => { onMounted(async () => { // 地图初始化 - geoTiffLoading.value = true; + // geoTiffLoading.value = true; await initGeoTiff(); initOLMap(); - geoTiffLoading.value = false; + // geoTiffLoading.value = false; map.addLayer(sharedLayer); selector.value = new LassoSelector(map, sharedSource, (features, isInvert = false) => { features.forEach((feature) => { diff --git a/src/views/safety/recognizeRecord/index.vue b/src/views/safety/recognizeRecord/index.vue new file mode 100644 index 0000000..5c6af09 --- /dev/null +++ b/src/views/safety/recognizeRecord/index.vue @@ -0,0 +1,283 @@ + + +