chore: remove large file and update .gitignore
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,6 +1,7 @@ | ||||
| .DS_Store | ||||
| .history | ||||
| node_modules/ | ||||
| public/image/ | ||||
| dist/ | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
|  | ||||
| @ -39,6 +39,7 @@ | ||||
|     "ezuikit-js": "^8.1.10", | ||||
|     "file-saver": "2.0.5", | ||||
|     "fuse.js": "7.0.0", | ||||
|     "gcoord": "^1.0.7", | ||||
|     "geotiff": "^2.1.4-beta.0", | ||||
|     "highlight.js": "11.9.0", | ||||
|     "image-conversion": "2.1.1", | ||||
| @ -52,6 +53,7 @@ | ||||
|     "nprogress": "0.2.0", | ||||
|     "ol": "^10.5.0", | ||||
|     "pinia": "2.2.6", | ||||
|     "proj4": "^2.19.3", | ||||
|     "screenfull": "6.0.2", | ||||
|     "spark-md5": "^3.0.2", | ||||
|     "vue": "3.5.13", | ||||
| @ -73,6 +75,7 @@ | ||||
|     "@types/js-cookie": "3.0.6", | ||||
|     "@types/node": "18.18.2", | ||||
|     "@types/nprogress": "0.2.3", | ||||
|     "@types/proj4": "^2.5.6", | ||||
|     "@unocss/preset-attributify": "0.64.1", | ||||
|     "@unocss/preset-icons": "0.64.1", | ||||
|     "@unocss/preset-uno": "0.64.1", | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								public/image/clean_rgb_downsampled.tif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/image/clean_rgb_downsampled.tif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										55
									
								
								public/image/convert_tif.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								public/image/convert_tif.bat
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| @echo off | ||||
| setlocal | ||||
|  | ||||
| REM 源文件 | ||||
| set SRC=odm_orthophoto.tif | ||||
|  | ||||
| REM 中间文件:去掩膜 + 保留 4 波段 | ||||
| set TMP1=tmp_nomask.tif | ||||
|  | ||||
| REM 中间文件:gdalwarp 处理透明通道 | ||||
| set TMP2=tmp_nomask_alpha.tif | ||||
|  | ||||
| REM 最终输出文件(性能优化:缩放 + 压缩) | ||||
| set FINAL=clean_no_mask_optimized.tif | ||||
|  | ||||
| REM 配置参数 | ||||
| REM -tr 0.25x 分辨率控制(0.25 倍像素,或者每个像素大小扩大4倍),视你项目需要可调 | ||||
| REM -co 压缩参数:LZW 是无损压缩方式,TILED=YES 支持分块加载 | ||||
| REM -r average 使用平均值重采样可保持图像质量 | ||||
|  | ||||
| echo [1/4] gdal_translate:去除掩膜并保留RGBA四波段... | ||||
| gdal_translate -b 1 -b 2 -b 3 -b 4 -mask none -co PHOTOMETRIC=RGB -co ALPHA=YES %SRC% %TMP1% | ||||
| if errorlevel 1 ( | ||||
|     echo ❌ gdal_translate 失败 | ||||
|     exit /b 1 | ||||
| ) | ||||
|  | ||||
| echo [2/4] gdalwarp:强制生成 Alpha 通道... | ||||
| gdalwarp -dstalpha %TMP1% %TMP2% | ||||
| if errorlevel 1 ( | ||||
|     echo ❌ gdalwarp 失败 | ||||
|     exit /b 1 | ||||
| ) | ||||
|  | ||||
| echo [3/4] gdalwarp:降采样并启用压缩优化... | ||||
| gdalwarp ^ | ||||
|   -r average ^ | ||||
|   -tr 2 2 ^ | ||||
|   -co COMPRESS=LZW ^ | ||||
|   -co TILED=YES ^ | ||||
|   -co PHOTOMETRIC=RGB ^ | ||||
|   -co ALPHA=YES ^ | ||||
|   %TMP2% %FINAL% | ||||
| if errorlevel 1 ( | ||||
|     echo ❌ gdalwarp 压缩优化失败 | ||||
|     exit /b 1 | ||||
| ) | ||||
|  | ||||
| echo [4/4] 清理临时文件... | ||||
| del %TMP1% | ||||
| del %TMP2% | ||||
|  | ||||
| echo ✅ 完成!优化后的 GeoTIFF 已生成:%FINAL% | ||||
| endlocal | ||||
| pause | ||||
							
								
								
									
										63
									
								
								src/api/safety/violationLevel/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/api/safety/violationLevel/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| import request from '@/utils/request'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
| import { ViolationLevelVO, ViolationLevelForm, ViolationLevelQuery } from '@/api/safety/violationLevel/types'; | ||||
|  | ||||
| /** | ||||
|  * 查询违章等级列表 | ||||
|  * @param query | ||||
|  * @returns {*} | ||||
|  */ | ||||
|  | ||||
| export const listViolationLevel = (query?: ViolationLevelQuery): AxiosPromise<ViolationLevelVO[]> => { | ||||
|   return request({ | ||||
|     url: '/safety/violationLevel/list', | ||||
|     method: 'get', | ||||
|     params: query | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 查询违章等级详细 | ||||
|  * @param id | ||||
|  */ | ||||
| export const getViolationLevel = (id: string | number): AxiosPromise<ViolationLevelVO> => { | ||||
|   return request({ | ||||
|     url: '/safety/violationLevel/' + id, | ||||
|     method: 'get' | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 新增违章等级 | ||||
|  * @param data | ||||
|  */ | ||||
| export const addViolationLevel = (data: ViolationLevelForm) => { | ||||
|   return request({ | ||||
|     url: '/safety/violationLevel', | ||||
|     method: 'post', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 修改违章等级 | ||||
|  * @param data | ||||
|  */ | ||||
| export const updateViolationLevel = (data: ViolationLevelForm) => { | ||||
|   return request({ | ||||
|     url: '/safety/violationLevel', | ||||
|     method: 'put', | ||||
|     data: data | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * 删除违章等级 | ||||
|  * @param id | ||||
|  */ | ||||
| export const delViolationLevel = (id: string | number | Array<string | number>) => { | ||||
|   return request({ | ||||
|     url: '/safety/violationLevel/' + id, | ||||
|     method: 'delete' | ||||
|   }); | ||||
| }; | ||||
							
								
								
									
										87
									
								
								src/api/safety/violationLevel/types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/api/safety/violationLevel/types.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| export interface ViolationLevelVO { | ||||
|   /** | ||||
|    * 违章等级 | ||||
|    */ | ||||
|   violationLevel: string; | ||||
|   id: string | number | Array<string | number>; | ||||
|   /** | ||||
|    * 颜色 | ||||
|    */ | ||||
|   color: string; | ||||
|  | ||||
|   /** | ||||
|    * 风险等级 | ||||
|    */ | ||||
|   riskType: string; | ||||
|  | ||||
|   /** | ||||
|    * 违章类型(多个逗号分隔) | ||||
|    */ | ||||
|   violationType: string | Array<string | number>; | ||||
|  | ||||
|   /** | ||||
|    * 创建时间 | ||||
|    */ | ||||
|   createTime: string; | ||||
|   postList?: Array<string | number>; | ||||
|   postIdList?: Array<string | number>; | ||||
| } | ||||
|  | ||||
| export interface ViolationLevelForm extends BaseEntity { | ||||
|   /** | ||||
|    * 主键id | ||||
|    */ | ||||
|   id?: string | number; | ||||
|  | ||||
|   /** | ||||
|    * 项目id | ||||
|    */ | ||||
|   projectId?: string | number; | ||||
|  | ||||
|   /** | ||||
|    * 违章等级 | ||||
|    */ | ||||
|   violationLevel?: string; | ||||
|  | ||||
|   /** | ||||
|    * 颜色 | ||||
|    */ | ||||
|   color?: string; | ||||
|  | ||||
|   /** | ||||
|    * 风险等级 | ||||
|    */ | ||||
|   riskType?: string; | ||||
|  | ||||
|   /** | ||||
|    * 违章类型(多个逗号分隔) | ||||
|    */ | ||||
|   violationType?: string; | ||||
| } | ||||
|  | ||||
| export interface ViolationLevelQuery extends PageQuery { | ||||
|   /** | ||||
|    * 项目id | ||||
|    */ | ||||
|   projectId?: string | number; | ||||
|  | ||||
|   /** | ||||
|    * 违章等级 | ||||
|    */ | ||||
|   violationLevel?: string; | ||||
|  | ||||
|   /** | ||||
|    * 风险等级 | ||||
|    */ | ||||
|   riskType?: string; | ||||
|  | ||||
|   /** | ||||
|    * 违章类型(多个逗号分隔) | ||||
|    */ | ||||
|   violationType?: string; | ||||
|  | ||||
|   /** | ||||
|    * 日期范围参数 | ||||
|    */ | ||||
|   params?: any; | ||||
| } | ||||
| @ -3,7 +3,7 @@ import { PostForm, PostQuery, PostVO } from './types'; | ||||
| import { AxiosPromise } from 'axios'; | ||||
|  | ||||
| // 查询岗位列表 | ||||
| export function listPost(query: PostQuery): AxiosPromise<PostVO[]> { | ||||
| export function listPost(query: { pageNum: number; pageSize: number }): AxiosPromise<PostVO[]> { | ||||
|   return request({ | ||||
|     url: '/system/post/list', | ||||
|     method: 'get', | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 12 MiB | 
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										67
									
								
								src/utils/geoTiffLoader.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/utils/geoTiffLoader.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| import { fromUrl } from 'geotiff'; // 假设你用的是这个包 | ||||
| import { transform } from 'ol/proj'; | ||||
| import { fromLonLat } from 'ol/proj'; | ||||
| import ImageLayer from 'ol/layer/Image'; | ||||
| import Static from 'ol/source/ImageStatic'; | ||||
| import gcoord from 'gcoord'; | ||||
|  | ||||
| export class GeoTiffLoader { | ||||
|   imageExtent: number[] = []; | ||||
|   imageLayer: ImageLayer<Static> | null = null; | ||||
|   tiffUrl: string; | ||||
|  | ||||
|   constructor(tiffUrl: string) { | ||||
|     this.tiffUrl = tiffUrl; | ||||
|   } | ||||
|  | ||||
|   async init() { | ||||
|     const tiff = await fromUrl(this.tiffUrl); | ||||
|     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 })) as Uint8Array; | ||||
|  | ||||
|     // 创建 Canvas | ||||
|     const canvas = document.createElement('canvas'); | ||||
|     canvas.width = width; | ||||
|     canvas.height = height; | ||||
|     const ctx = canvas.getContext('2d')!; | ||||
|     const imageData = ctx.createImageData(width, height); | ||||
|  | ||||
|     // 设置 RGBA 数据 | ||||
|     imageData.data.set(rasters); | ||||
|     ctx.putImageData(imageData, 0, 0); | ||||
|  | ||||
|     // 转成 Data URL | ||||
|     const imageUrl = canvas.toDataURL(); | ||||
|  | ||||
|     // 坐标转换 | ||||
|     const minLonLat = transform([bbox[0], bbox[1]], 'EPSG:32648', 'EPSG:4326'); | ||||
|     const maxLonLat = transform([bbox[2], bbox[3]], 'EPSG:32648', 'EPSG:4326'); | ||||
|  | ||||
|     // 转为 GCJ02 坐标系 | ||||
|     // 这里断言为[number, number, number],补0做三维坐标 | ||||
|     const gcjMin = gcoord.transform([minLonLat[0], minLonLat[1], 0], gcoord.WGS84, gcoord.GCJ02); | ||||
|     const gcjMax = gcoord.transform([maxLonLat[0], maxLonLat[1], 0], gcoord.WGS84, gcoord.GCJ02); | ||||
|  | ||||
|     // 再转为 EPSG:3857 | ||||
|     const minXY = fromLonLat(gcjMin); | ||||
|     const maxXY = fromLonLat(gcjMax); | ||||
|  | ||||
|     this.imageExtent = [...minXY, ...maxXY]; | ||||
|  | ||||
|     this.imageLayer = new ImageLayer({ | ||||
|       source: new Static({ | ||||
|         url: imageUrl, | ||||
|         imageExtent: this.imageExtent, | ||||
|         projection: 'EPSG:3857' | ||||
|       }) | ||||
|     }); | ||||
|  | ||||
|     console.log('imageExtent', this.imageExtent); | ||||
|   } | ||||
| } | ||||
| @ -1,52 +1,54 @@ | ||||
| <template> | ||||
|   <div class="header flex justify-between"> | ||||
|     <div class="tips flex items-center justify-between"> | ||||
|       <div class="dot1">未提交</div> | ||||
|       <div class="dot2">已提交</div> | ||||
|       <div class="dot3">已选择,待提交</div> | ||||
|       <el-tooltip class="box-item" effect="dark" content="右键拖动生成套索区域选中/取消图形" placement="bottom"> | ||||
|         <i class="iconfont icon-wenhao"></i> | ||||
|       </el-tooltip> | ||||
|     </div> | ||||
|     <el-form :model="queryParams" ref="form" label-width="80px" inline class="flex items-center"> | ||||
|       <el-form-item label="请选择项目:" prop="pid" label-width="100" style="margin-bottom: 0; color: #fff"> | ||||
|         <el-select v-model="selectedProjectId" placeholder="请选择" @change="handleSelect" clearable> | ||||
|           <el-option v-for="item in ProjectList" :key="item.id" :label="item.name" :value="item.id" /> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="请选择方阵:" prop="pid" label-width="100" style="margin-bottom: 0"> | ||||
|         <!-- <el-select v-model="matrixValue" placeholder="请选择" @change="handleChange" clearable> | ||||
|   <div v-loading="geoTiffLoading" class="flex h100vh"> | ||||
|     <div class="header flex justify-between"> | ||||
|       <div class="tips flex items-center justify-between"> | ||||
|         <div class="dot1">未提交</div> | ||||
|         <div class="dot2">已提交</div> | ||||
|         <div class="dot3">已选择,待提交</div> | ||||
|         <el-tooltip class="box-item" effect="dark" content="右键拖动生成套索区域选中/取消图形" placement="bottom"> | ||||
|           <i class="iconfont icon-wenhao"></i> | ||||
|         </el-tooltip> | ||||
|       </div> | ||||
|       <el-form :model="queryParams" ref="form" label-width="80px" inline class="flex items-center"> | ||||
|         <el-form-item label="请选择项目:" prop="pid" label-width="100" style="margin-bottom: 0; color: #fff"> | ||||
|           <el-select v-model="selectedProjectId" placeholder="请选择" @change="handleSelect" clearable> | ||||
|             <el-option v-for="item in ProjectList" :key="item.id" :label="item.name" :value="item.id" /> | ||||
|           </el-select> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="请选择方阵:" prop="pid" label-width="100" style="margin-bottom: 0"> | ||||
|           <!-- <el-select v-model="matrixValue" placeholder="请选择" @change="handleChange" clearable> | ||||
|           <el-option v-for="item in matrixOptions" :key="item.id" :label="item.matrixName" :value="item.id" /> | ||||
|         </el-select> --> | ||||
|         <el-cascader | ||||
|           :options="matrixOptions" | ||||
|           placeholder="请选择" | ||||
|           @change="handleChange" | ||||
|           :props="{ value: 'matrixId', label: 'name' }" | ||||
|           v-model="queryParams.matrixId" | ||||
|           clearable | ||||
|         /> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|   </div> | ||||
|   <div class="ol-map" id="olMap"></div> | ||||
|   <div class="aside"> | ||||
|     <el-tree | ||||
|       style="max-width: 600px" | ||||
|       :data="progressCategoryList" | ||||
|       ref="treeRef" | ||||
|       @check-change="handleCheckChange" | ||||
|       :props="treeProps" | ||||
|       :load="loadNode" | ||||
|       node-key="id" | ||||
|       lazy | ||||
|       :render-content="renderContent" | ||||
|       check-strictly | ||||
|       :expand-on-click-node="false" | ||||
|     /> | ||||
|   </div> | ||||
|   <div class="submit"> | ||||
|     <el-button type="primary" size="default" @click="submit" :loading="loading">提交</el-button> | ||||
|           <el-cascader | ||||
|             :options="matrixOptions" | ||||
|             placeholder="请选择" | ||||
|             @change="handleChange" | ||||
|             :props="{ value: 'matrixId', label: 'name' }" | ||||
|             v-model="queryParams.matrixId" | ||||
|             clearable | ||||
|           /> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </div> | ||||
|     <div class="ol-map" id="olMap"></div> | ||||
|     <div class="aside"> | ||||
|       <el-tree | ||||
|         style="max-width: 600px" | ||||
|         :data="progressCategoryList" | ||||
|         ref="treeRef" | ||||
|         @check-change="handleCheckChange" | ||||
|         :props="treeProps" | ||||
|         :load="loadNode" | ||||
|         node-key="id" | ||||
|         lazy | ||||
|         :render-content="renderContent" | ||||
|         check-strictly | ||||
|         :expand-on-click-node="false" | ||||
|       /> | ||||
|     </div> | ||||
|     <div class="submit"> | ||||
|       <el-button type="primary" size="default" @click="submit" :loading="loading">提交</el-button> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @ -54,9 +56,9 @@ | ||||
| import Map from 'ol/Map'; // OpenLayers的主要类,用于创建和管理地图 | ||||
| import View from 'ol/View'; // OpenLayers的视图类,定义地图的视图属性 | ||||
| import { Tile as TileLayer, WebGLTile } from 'ol/layer'; // OpenLayers的瓦片图层类 | ||||
| import { GeoTIFF, Raster, XYZ } from 'ol/source'; // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源 | ||||
| import { Raster, XYZ } from 'ol/source'; // OpenLayers的瓦片数据源,包括XYZ格式和OpenStreetMap专用的数据源 | ||||
| import { defaults as defaultControls, defaults, FullScreen, MousePosition, ScaleLine } from 'ol/control'; | ||||
| import { fromLonLat } from 'ol/proj'; | ||||
| import { fromLonLat, toLonLat, transform, transformExtent } from 'ol/proj'; | ||||
| import { useUserStoreHook } from '@/store/modules/user'; | ||||
| import { getProjectSquare, listProgressCategory, addDaily, workScheduleListPosition } from '@/api/progress/plan'; | ||||
| import { ProgressCategoryVO, progressPlanDetailForm } from '@/api/progress/plan/types'; | ||||
| @ -73,10 +75,13 @@ import { FeatureCollection, Geometry } from 'geojson'; | ||||
| import { MapViewFitter } from '@/utils/setMapCenter'; | ||||
| import PointerInteraction from 'ol/interaction/Pointer'; | ||||
| import { Coordinate } from 'ol/coordinate'; | ||||
| import { fromBlob, fromUrl, fromArrayBuffer, Pool } from 'geotiff'; | ||||
|  | ||||
| import GeoTIFF, { fromBlob, fromUrl, fromArrayBuffer, Pool } from 'geotiff'; | ||||
| import GeoTIFFSource from 'ol/source/GeoTIFF'; | ||||
|  | ||||
| import ImageLayer from 'ol/layer/Image'; | ||||
| import Static from 'ol/source/ImageStatic'; | ||||
| import proj4 from 'proj4'; | ||||
| import { register } from 'ol/proj/proj4'; | ||||
| import gcoord from 'gcoord'; | ||||
| const { proxy } = getCurrentInstance() as ComponentInternalInstance; | ||||
| const orthophoto = '@/assets/images/orthophoto.tif'; | ||||
| const selector = ref<LassoSelector | null>(null); | ||||
| @ -100,6 +105,7 @@ const submitForm = ref<progressPlanDetailForm>({ | ||||
|   finishedDetailIdList: [] as string[] | ||||
| }); | ||||
| const loading = ref(false); | ||||
| const geoTiffLoading = ref(false); | ||||
| const matrixOptions = ref([]); | ||||
| const matrixValue = ref<number | undefined>(matrixOptions.value.length > 0 ? matrixOptions.value[0].id : undefined); | ||||
| const progressCategoryList = ref<ProgressCategoryVO[]>([]); | ||||
| @ -400,32 +406,55 @@ const getList = async () => { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const imageExtent = ref(null); | ||||
| const imageLayer = ref(null); | ||||
| 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 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); | ||||
| }; | ||||
|  | ||||
| let map: any = null; | ||||
| const layerData = reactive<any>({}); | ||||
| const centerPosition = ref(fromLonLat([107.12932403398425, 23.805564054229908])); | ||||
| const initOLMap = () => { | ||||
|   const source = new GeoTIFF({ | ||||
|     sources: [ | ||||
|       { | ||||
|         url: '../../../assets/images/orthophoto.tif' | ||||
|       } | ||||
|     ], | ||||
|     convertToRGB: true // 将色彩系统转换为RGB | ||||
|   }); | ||||
|   source.on('change', () => { | ||||
|     const state = source.getState(); | ||||
|     console.log('GeoTIFF 加载状态:', state); | ||||
|     if (state === 'ready') { | ||||
|       console.log('✅ GeoTIFF 加载成功'); | ||||
|     } else if (state === 'error') { | ||||
|       console.error('❌ GeoTIFF 加载失败'); | ||||
|     } | ||||
|   }); | ||||
|   const tiffLayer = new WebGLTile({ | ||||
|     source: source | ||||
|   }); | ||||
|  | ||||
|   // 创造地图实例 | ||||
|   const borderLayer = createExtentBorderLayer(imageExtent.value); | ||||
|   map = new Map({ | ||||
|     // 设置地图容器的ID | ||||
|     target: 'olMap', | ||||
| @ -444,7 +473,8 @@ 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 | ||||
|     ], | ||||
|     // 设置地图的视图参数 | ||||
|     // View表示地图的视图,它定义了地图的中心点、缩放级别、旋转角度等参数。 | ||||
| @ -463,12 +493,18 @@ const initOLMap = () => { | ||||
|       zoom: false, | ||||
|       rotate: false, | ||||
|       attribution: false | ||||
|     }), | ||||
|     }).extend([new ScaleLine()]), | ||||
|     interactions: defaultInteractions({ | ||||
|       doubleClickZoom: false // 禁用双击缩放 | ||||
|     }) | ||||
|   }); | ||||
|   map.on('click', (e: any) => { | ||||
|     var coordinate = e.coordinate; | ||||
|  | ||||
|     // 将投影坐标转换为经纬度坐标 | ||||
|     var lonLatCoordinate = toLonLat(coordinate); | ||||
|     // 输出转换后的经纬度坐标 | ||||
|     console.log('经纬度坐标:', lonLatCoordinate); | ||||
|     const zoom = map.getView().getZoom(); | ||||
|     const scale = Math.max(zoom / 10, 1); // 缩放比例,根据需要调整公式 | ||||
|     map.forEachFeatureAtPixel(e.pixel, (feature: Feature) => { | ||||
| @ -488,6 +524,12 @@ const initOLMap = () => { | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
|   map.on('moveend', (e: any) => { | ||||
|     // console.log('地图移动', e); | ||||
|     // 获取当前缩放级别 | ||||
|     var zoomLevel = map.getView().getZoom(); | ||||
|     console.log('当前缩放级别:', zoomLevel); | ||||
|   }); | ||||
|  | ||||
|   // 4. 添加 pointermove 鼠标悬停事件 | ||||
|   let lastFeature: Feature | null = null; | ||||
| @ -542,6 +584,38 @@ const initOLMap = () => { | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| // 你已有的 imageExtent 是 [minX, minY, maxX, maxY] | ||||
| const createExtentBorderLayer = (extent: number[]) => { | ||||
|   // 构造矩形坐标,闭合成环,顺序可以是顺时针或逆时针 | ||||
|   const coords = [ | ||||
|     [ | ||||
|       [extent[0], extent[1]], | ||||
|       [extent[0], extent[3]], | ||||
|       [extent[2], extent[3]], | ||||
|       [extent[2], extent[1]], | ||||
|       [extent[0], extent[1]] | ||||
|     ] | ||||
|   ]; | ||||
|  | ||||
|   const polygonFeature = new Feature(new Polygon(coords)); | ||||
|  | ||||
|   polygonFeature.setStyle( | ||||
|     new Style({ | ||||
|       stroke: new Stroke({ | ||||
|         color: 'red', // 你想要的边框颜色 | ||||
|         width: 3 // 线宽 | ||||
|       }), | ||||
|       fill: null // 不填充,纯边框 | ||||
|     }) | ||||
|   ); | ||||
|  | ||||
|   return new VectorLayer({ | ||||
|     source: new VectorSource({ | ||||
|       features: [polygonFeature] | ||||
|     }) | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const highlightStyle = (name, scale) => { | ||||
|   return new Style({ | ||||
|     stroke: new Stroke({ | ||||
| @ -714,9 +788,12 @@ const toggleFeatureHighlight = (feature: Feature, addIfNotExist = true) => { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| onMounted(() => { | ||||
| onMounted(async () => { | ||||
|   // 地图初始化 | ||||
|   geoTiffLoading.value = true; | ||||
|   await initGeoTiff(); | ||||
|   initOLMap(); | ||||
|   geoTiffLoading.value = false; | ||||
|   map.addLayer(sharedLayer); | ||||
|   selector.value = new LassoSelector(map, sharedSource, (features, isInvert = false) => { | ||||
|     features.forEach((feature) => { | ||||
| @ -736,6 +813,7 @@ onMounted(() => { | ||||
|  | ||||
|   enableMiddleMousePan(map); | ||||
|   getList(); | ||||
|   creatPoint(fromLonLat([107.13149145799198, 23.804125705140834]), 'Point', '1', '测试点1', '1'); | ||||
| }); | ||||
|  | ||||
| function enableMiddleMousePan(map: Map) { | ||||
| @ -758,9 +836,9 @@ function enableMiddleMousePan(map: Map) { | ||||
|   map.addInteraction(middleButtonDragPan); | ||||
|  | ||||
|   // 禁用中键点击默认滚动行为(浏览器可能会出现滚动箭头) | ||||
|   map.getViewport().addEventListener('mousedown', (e) => { | ||||
|     if (e.button === 1) e.preventDefault(); | ||||
|   }); | ||||
|   // map.getViewport().addEventListener('mousedown', (e) => { | ||||
|   //   if (e.button === 1) e.preventDefault(); | ||||
|   // }); | ||||
| } | ||||
| </script> | ||||
|  | ||||
|  | ||||
							
								
								
									
										190
									
								
								src/views/safety/violationLevel/component/add.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								src/views/safety/violationLevel/component/add.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,190 @@ | ||||
| <template> | ||||
|   <div class="system-busViolationLevel-add"> | ||||
|     <el-dialog v-model="isShowDialog" width="550px" :close-on-click-modal="false" :destroy-on-close="true"> | ||||
|       <template #header> | ||||
|         <div v-drag="['.system-busViolationLevel-add .el-dialog', '.system-busViolationLevel-add .el-dialog__header']">添加违章等级</div> | ||||
|       </template> | ||||
|       <el-form ref="formRef" size="large" :model="formData" :rules="rules" label-width="90px"> | ||||
|         <el-row> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="违章等级" prop="violationLevel"> | ||||
|               <el-input v-model="formData.violationLevel" placeholder="请输入违章等级" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="颜色" prop="color"> | ||||
|               <el-color-picker v-model="formData.color" show-alpha /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="24"> | ||||
|             <el-form-item label="风险等级" prop="riskType"> | ||||
|               <el-select v-model="formData.riskType" placeholder="请选择风险等级"> | ||||
|                 <el-option v-for="dict in risxList" :key="dict.value" :label="dict.label" :value="dict.value" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="24"> | ||||
|             <el-form-item label="岗位" prop="postIdList"> | ||||
|               <el-select v-model="formData.postIdList" placeholder="请选择岗位" multiple> | ||||
|                 <el-option v-for="dict in postListAll" :key="dict.postId" :label="dict.postName" :value="dict.postId" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="24"> | ||||
|             <el-form-item label="违章类型" prop="violationType"> | ||||
|               <el-select v-model="formData.violationType" placeholder="请选择违章类型" multiple> | ||||
|                 <el-option v-for="dict in tourTypeOptions" :key="dict.value" :label="dict.label" :value="dict.value" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button type="primary" @click="onSubmit">确 定</el-button> | ||||
|           <el-button @click="onCancel">取 消</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref, reactive, getCurrentInstance } from 'vue'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| import { addViolationLevel } from '@/api/safety/violationLevel'; | ||||
| import { useUserStoreHook } from '@/store/modules/user'; | ||||
| // 获取用户 store | ||||
| const userStore = useUserStoreHook(); | ||||
| // 从 store 中获取项目列表和当前选中的项目 | ||||
| const currentProject = computed(() => userStore.selectedProject); | ||||
|  | ||||
| // Props | ||||
| defineProps<{ | ||||
|   tourTypeOptions: any[]; | ||||
|   risxList: any[]; | ||||
|   postListAll: any[]; | ||||
| }>(); | ||||
|  | ||||
| const emit = defineEmits(['busViolationLevelList']); | ||||
| const { proxy } = getCurrentInstance()!; | ||||
|  | ||||
| const formRef = ref<any>(null); | ||||
| const menuRef = ref(); | ||||
|  | ||||
| const isShowDialog = ref(false); | ||||
| const loading = ref(false); | ||||
|  | ||||
| const formData = reactive({ | ||||
|   id: undefined, | ||||
|   violationLevel: undefined, | ||||
|   color: undefined, | ||||
|   violationType: undefined as any, | ||||
|   wxOrPc: undefined, | ||||
|   createBy: undefined, | ||||
|   updateBy: undefined, | ||||
|   createdAt: undefined, | ||||
|   updatedAt: undefined, | ||||
|   deletedAt: undefined, | ||||
|   projectId: currentProject.value?.id, | ||||
|   riskType: '', | ||||
|   postIdList: [] as any[] | ||||
| }); | ||||
|  | ||||
| const rules = { | ||||
|   id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }], | ||||
|   violationLevel: [ | ||||
|     { | ||||
|       required: true, | ||||
|       validator: (_rule: any, value: string) => /^[A-Z]*$/g.test(value), | ||||
|       message: '请输入A-Z的字母', | ||||
|       trigger: 'change' | ||||
|     } | ||||
|   ], | ||||
|   postIdList: [{ required: true, message: '岗位不能为空', trigger: 'blur' }] | ||||
| }; | ||||
|  | ||||
| // 打开弹窗 | ||||
| const openDialog = () => { | ||||
|   resetForm(); | ||||
|   isShowDialog.value = true; | ||||
| }; | ||||
|  | ||||
| // 关闭弹窗 | ||||
| const closeDialog = () => { | ||||
|   isShowDialog.value = false; | ||||
| }; | ||||
|  | ||||
| // 取消操作 | ||||
| const onCancel = () => { | ||||
|   closeDialog(); | ||||
| }; | ||||
|  | ||||
| // 表单重置 | ||||
| const resetForm = () => { | ||||
|   Object.assign(formData, { | ||||
|     id: undefined, | ||||
|     violationLevel: undefined, | ||||
|     color: undefined, | ||||
|     violationType: undefined, | ||||
|     wxOrPc: undefined, | ||||
|     createBy: undefined, | ||||
|     updateBy: undefined, | ||||
|     createdAt: undefined, | ||||
|     updatedAt: undefined, | ||||
|     deletedAt: undefined, | ||||
|     projectId: currentProject.value?.id, | ||||
|     riskType: '', | ||||
|     postIdList: [] | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| // 提交操作 | ||||
| const onSubmit = () => { | ||||
|   if (!formRef.value) return; | ||||
|  | ||||
|   formRef.value.validate((valid: boolean) => { | ||||
|     if (valid) { | ||||
|       loading.value = true; | ||||
|  | ||||
|       const param = JSON.parse(JSON.stringify(formData)); | ||||
|       if (param.violationType?.length) { | ||||
|         param.violationType = param.violationType.join(','); | ||||
|       } | ||||
|  | ||||
|       addViolationLevel(param) | ||||
|         .then(() => { | ||||
|           ElMessage.success('添加成功'); | ||||
|           closeDialog(); | ||||
|           emit('busViolationLevelList'); | ||||
|         }) | ||||
|         .finally(() => { | ||||
|           loading.value = false; | ||||
|         }); | ||||
|     } | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| defineExpose({ | ||||
|   openDialog, | ||||
|   closeDialog | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .system-busViolationLevel-add { | ||||
|   .el-col { | ||||
|     margin-top: 20px; | ||||
|   } | ||||
|   .el-select .el-input__wrapper { | ||||
|     width: 400px; | ||||
|   } | ||||
|   .el-select__tags { | ||||
|     white-space: nowrap; | ||||
|     text-overflow: ellipsis; | ||||
|     flex-wrap: nowrap; | ||||
|     overflow: hidden; | ||||
|     margin-left: 1px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										204
									
								
								src/views/safety/violationLevel/component/edit.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								src/views/safety/violationLevel/component/edit.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,204 @@ | ||||
| <template> | ||||
|   <div class="system-busViolationLevel-edit"> | ||||
|     <el-dialog v-model="isShowDialog" width="550px" :close-on-click-modal="false" :destroy-on-close="true" custom-class="busViolationLevel_edit"> | ||||
|       <template #header> | ||||
|         <div v-drag="['.system-busViolationLevel-edit .el-dialog', '.system-busViolationLevel-edit .el-dialog__header']"> | ||||
|           {{ (!formData.id || formData.id == 0 ? '添加' : '修改') + '违章等级' }} | ||||
|         </div> | ||||
|       </template> | ||||
|       <el-form ref="formRef" size="large" :model="formData" :rules="rules" label-width="90px"> | ||||
|         <el-row> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="违章等级" prop="violationLevel"> | ||||
|               <el-input v-model="formData.violationLevel" placeholder="请输入违章等级" /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="12"> | ||||
|             <el-form-item label="颜色" prop="color"> | ||||
|               <el-color-picker v-model="formData.color" show-alpha /> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="24"> | ||||
|             <el-form-item label="风险等级" prop="riskType"> | ||||
|               <el-select v-model="formData.riskType" placeholder="请选择风险等级"> | ||||
|                 <el-option v-for="dict in risxList" :key="dict.value" :label="dict.label" :value="dict.value" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="24"> | ||||
|             <el-form-item label="岗位" prop="postIdList"> | ||||
|               <el-select v-model="formData.postIdList" placeholder="请选择岗位" multiple> | ||||
|                 <el-option v-for="dict in postListAll" :key="dict.postId" :label="dict.postName" :value="dict.postId" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="24"> | ||||
|             <el-form-item label="违章类型" prop="violationType"> | ||||
|               <el-select v-model="formData.violationType" placeholder="请选择违章类型" multiple> | ||||
|                 <el-option v-for="dict in tourTypeOptions" :key="dict.value" :label="dict.label" :value="dict.value" /> | ||||
|               </el-select> | ||||
|             </el-form-item> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </el-form> | ||||
|       <template #footer> | ||||
|         <div class="dialog-footer"> | ||||
|           <el-button type="primary" @click="onSubmit">确 定</el-button> | ||||
|           <el-button @click="onCancel">取 消</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|     </el-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref, reactive, getCurrentInstance, unref, nextTick } from 'vue'; | ||||
| import { ElMessage, ElLoading } from 'element-plus'; | ||||
| import { getViolationLevel, addViolationLevel, updateViolationLevel } from '@/api/safety/violationLevel'; | ||||
| import { ViolationLevelForm, ViolationLevelVO } from '@/api/safety/violationLevel/types'; | ||||
|  | ||||
| defineProps<{ | ||||
|   tourTypeOptions: any[]; | ||||
|   risxList: any[]; | ||||
|   postListAll: any[]; | ||||
| }>(); | ||||
|  | ||||
| const emit = defineEmits(['busViolationLevelList']); | ||||
|  | ||||
| const { proxy } = getCurrentInstance()!; | ||||
| const formRef = ref<any>(null); | ||||
| const isShowDialog = ref(false); | ||||
| const loading = ref(false); | ||||
|  | ||||
| const formData = reactive< | ||||
|   Partial<ViolationLevelForm> & { | ||||
|     risx?: string[] | string; | ||||
|     tourType?: string[] | string; | ||||
|     postIdList: number[]; | ||||
|   } | ||||
| >({ | ||||
|   id: undefined, | ||||
|   violationLevel: undefined, | ||||
|   color: undefined, | ||||
|   riskType: undefined, | ||||
|   createBy: undefined, | ||||
|   updateBy: undefined, | ||||
|   risx: '', | ||||
|   postIdList: [] | ||||
| }); | ||||
|  | ||||
| const rules = { | ||||
|   id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }], | ||||
|   violationLevel: [ | ||||
|     { | ||||
|       required: true, | ||||
|       validator: (_rule: any, value: string) => /^[A-Z]*$/g.test(value), | ||||
|       message: '请输入A-Z的字母', | ||||
|       trigger: 'change' | ||||
|     } | ||||
|   ], | ||||
|   posts: [{ required: true, message: '岗位不能为空', trigger: 'blur' }] | ||||
| }; | ||||
|  | ||||
| const openDialog = (row?: ViolationLevelVO) => { | ||||
|   resetForm(); | ||||
|   if (row && row.id) { | ||||
|     nextTick(() => { | ||||
|       const loadingInstance = ElLoading.service({ | ||||
|         lock: true, | ||||
|         text: '正在加载中……', | ||||
|         background: 'rgba(0, 0, 0, 0.7)', | ||||
|         target: '.busViolationLevel_edit' | ||||
|       }); | ||||
|       getViolationLevel(row.id as string).then((res) => { | ||||
|         loadingInstance.close(); | ||||
|         const data = res.data; | ||||
|         data.postIdList = (data.postList || []).map((item: any) => item.postId); | ||||
|         data.violationType = data.violationType ? (data.violationType as string).split(',') : []; | ||||
|         Object.assign(formData, data); | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
|   isShowDialog.value = true; | ||||
| }; | ||||
|  | ||||
| const closeDialog = () => { | ||||
|   isShowDialog.value = false; | ||||
| }; | ||||
|  | ||||
| const onCancel = () => { | ||||
|   closeDialog(); | ||||
| }; | ||||
|  | ||||
| const onSubmit = () => { | ||||
|   const form = unref(formRef); | ||||
|   if (!form) return; | ||||
|  | ||||
|   form.validate((valid: boolean) => { | ||||
|     if (!valid) return; | ||||
|  | ||||
|     loading.value = true; | ||||
|  | ||||
|     const param = JSON.parse(JSON.stringify(formData)); | ||||
|     if (Array.isArray(param.violationType)) { | ||||
|       param.violationType = param.violationType.join(','); | ||||
|     } | ||||
|     if (Array.isArray(param.riskType)) { | ||||
|       param.riskType = param.riskType.join(','); | ||||
|     } | ||||
|  | ||||
|     const action = !param.id || param.id === 0 ? addViolationLevel : updateViolationLevel; | ||||
|     const successMsg = !param.id || param.id === 0 ? '添加成功' : '修改成功'; | ||||
|  | ||||
|     action(param) | ||||
|       .then(() => { | ||||
|         ElMessage.success(successMsg); | ||||
|         closeDialog(); | ||||
|         emit('busViolationLevelList'); | ||||
|       }) | ||||
|       .finally(() => { | ||||
|         loading.value = false; | ||||
|       }); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const resetForm = () => { | ||||
|   Object.assign(formData, { | ||||
|     id: undefined, | ||||
|     grade: undefined, | ||||
|     color: undefined, | ||||
|     tourType: undefined, | ||||
|     wxOrPc: undefined, | ||||
|     createBy: undefined, | ||||
|     updateBy: undefined, | ||||
|     createdAt: undefined, | ||||
|     updatedAt: undefined, | ||||
|     deletedAt: undefined, | ||||
|     risx: '', | ||||
|     posts: [] | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| defineExpose({ | ||||
|   openDialog, | ||||
|   closeDialog | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .system-busViolationLevel-edit { | ||||
|   .el-col { | ||||
|     margin-top: 20px; | ||||
|   } | ||||
|   .el-select .el-input__wrapper { | ||||
|     width: 400px; | ||||
|   } | ||||
|   .el-select__tags { | ||||
|     white-space: nowrap; | ||||
|     text-overflow: ellipsis; | ||||
|     flex-wrap: nowrap; | ||||
|     overflow: hidden; | ||||
|     margin-left: 1px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										290
									
								
								src/views/safety/violationLevel/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								src/views/safety/violationLevel/index.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,290 @@ | ||||
| <template> | ||||
|   <div class="system-busViolationLevel-container"> | ||||
|     <el-card shadow="hover"> | ||||
|       <div class="system-busViolationLevel-search mb15"> | ||||
|         <el-form :model="state.tableData.param" ref="queryRef" :inline="true" label-width="100px"> | ||||
|           <el-row> | ||||
|             <el-col :span="8" class="colBlock"> | ||||
|               <el-form-item label="违章类型" prop="tourType"> | ||||
|                 <el-select v-model="state.tableData.param.violationType" placeholder="请选择违章类型" clearable> | ||||
|                   <el-option v-for="dict in violation_level_type" :key="dict.value" :label="dict.label" :value="dict.value" /> | ||||
|                 </el-select> | ||||
|               </el-form-item> | ||||
|             </el-col> | ||||
|             <el-col :span="8" class="colBlock"> | ||||
|               <el-form-item> | ||||
|                 <el-button type="primary" @click="busViolationLevelList"> | ||||
|                   <el-icon><Search /></el-icon>搜索 | ||||
|                 </el-button> | ||||
|                 <el-button @click="resetQuery(queryRef)"> | ||||
|                   <el-icon><Refresh /></el-icon>重置 | ||||
|                 </el-button> | ||||
|               </el-form-item> | ||||
|             </el-col> | ||||
|           </el-row> | ||||
|         </el-form> | ||||
|         <el-row :gutter="10" class="mb8"> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="primary" @click="handleAdd" v-auth="'api/v1/system/busViolationLevel/add'"> | ||||
|               <el-icon><Plus /></el-icon>新增 | ||||
|             </el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="success" :disabled="single" @click="handleUpdate(null)" v-auth="'api/v1/system/busViolationLevel/edit'"> | ||||
|               <el-icon><Edit /></el-icon>修改 | ||||
|             </el-button> | ||||
|           </el-col> | ||||
|           <el-col :span="1.5"> | ||||
|             <el-button type="danger" :disabled="multiple" @click="handleDelete(null)" v-auth="'api/v1/system/busViolationLevel/delete'"> | ||||
|               <el-icon><Delete /></el-icon>删除 | ||||
|             </el-button> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|       </div> | ||||
|       <el-table v-loading="loading" :data="state.tableData.data" @selection-change="handleSelectionChange"> | ||||
|         <el-table-column type="selection" width="55" align="center" /> | ||||
|         <el-table-column label="序号" align="center" type="index" :index="indexMethod" width="60" /> | ||||
|         <el-table-column label="违章等级" align="center" prop="violationLevel" width="100px" /> | ||||
|         <el-table-column label="颜色" align="center" prop="color" width="100px"> | ||||
|           <template #default="scope"> | ||||
|             <div :style="`background: ${scope.row.color};width:15px;height:15px;margin:auto;`"></div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="风险等级" align="center" prop="riskType" width="150px"> | ||||
|           <template #default="scope"> | ||||
|             <span>{{ filterRiskLevelType(scope.row.riskType) }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="违章类型" show-overflow-tooltip align="center" prop="violationType" :formatter="tourTypeFormat" min-width="100px" /> | ||||
|         <el-table-column label="创建时间" align="center" prop="createTime" width="150px"> | ||||
|           <template #default="scope"> | ||||
|             <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" align="center" class-name="small-padding" width="160px" fixed="right"> | ||||
|           <template #default="scope"> | ||||
|             <el-button type="success" link @click="handleUpdate(scope.row)" v-auth="'api/v1/system/busViolationLevel/edit'"> | ||||
|               <el-icon><EditPen /></el-icon>修改 | ||||
|             </el-button> | ||||
|             <el-button type="danger" link @click="handleDelete(scope.row)" v-auth="'api/v1/system/busViolationLevel/delete'"> | ||||
|               <el-icon><DeleteFilled /></el-icon>删除 | ||||
|             </el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|       <pagination | ||||
|         v-show="state.tableData.total > 0" | ||||
|         :total="state.tableData.total" | ||||
|         v-model:page="state.tableData.param.pageNum" | ||||
|         v-model:limit="state.tableData.param.pageSize" | ||||
|         @pagination="busViolationLevelList" | ||||
|       /> | ||||
|     </el-card> | ||||
|  | ||||
|     <apiV1SystemBusViolationLevelAdd | ||||
|       ref="addRef" | ||||
|       :tourTypeOptions="violation_level_type" | ||||
|       :risxList="risk_level_type" | ||||
|       @busViolationLevelList="busViolationLevelList" | ||||
|       :postListAll="state.postListAll" | ||||
|     /> | ||||
|     <apiV1SystemBusViolationLevelEdit | ||||
|       ref="editRef" | ||||
|       :tourTypeOptions="violation_level_type" | ||||
|       :risxList="risk_level_type" | ||||
|       :postListAll="state.postListAll" | ||||
|       @busViolationLevelList="busViolationLevelList" | ||||
|     /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref, reactive, computed, onMounted, getCurrentInstance, toRaw } from 'vue'; | ||||
| import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'; | ||||
| import { listViolationLevel, delViolationLevel } from '@/api/safety/violationLevel'; | ||||
| import { ViolationLevelForm, ViolationLevelVO } from '@/api/safety/violationLevel/types'; | ||||
| import apiV1SystemBusViolationLevelAdd from '@/views/safety/violationLevel/component/add.vue'; | ||||
| import apiV1SystemBusViolationLevelEdit from '@/views/safety/violationLevel/component/edit.vue'; | ||||
| import { useUserStoreHook } from '@/store/modules/user'; | ||||
| import { listPost, optionselect } from '@/api/system/post'; | ||||
| // 获取用户 store | ||||
| const userStore = useUserStoreHook(); | ||||
| // 从 store 中获取项目列表和当前选中的项目 | ||||
| const currentProject = computed(() => userStore.selectedProject); | ||||
| const { proxy } = getCurrentInstance()!; | ||||
|  | ||||
| const loading = ref(false); | ||||
| const queryRef = ref<FormInstance>(); | ||||
| const addRef = ref<InstanceType<typeof apiV1SystemBusViolationLevelAdd>>(); | ||||
| const editRef = ref<InstanceType<typeof apiV1SystemBusViolationLevelEdit>>(); | ||||
| const detailRef = ref<any>(); | ||||
|  | ||||
| const showAll = ref(false); | ||||
| const single = ref(true); | ||||
| const multiple = ref(true); | ||||
|  | ||||
| const word = computed(() => (showAll.value === false ? '展开搜索' : '收起搜索')); | ||||
| const { violation_level_type, risk_level_type } = toRefs<any>(proxy?.useDict('violation_level_type', 'risk_level_type')); | ||||
|  | ||||
| const state = reactive<any>({ | ||||
|   ids: [], | ||||
|   tableData: { | ||||
|     data: [], | ||||
|     total: 0, | ||||
|     loading: false, | ||||
|     param: { | ||||
|       projectId: currentProject.value?.id, | ||||
|       pageNum: 1, | ||||
|       pageSize: 10, | ||||
|       tourType: undefined, | ||||
|       createdAt: undefined, | ||||
|       dateRange: [] | ||||
|     } | ||||
|   }, | ||||
|   postListAll: [] | ||||
| }); | ||||
|  | ||||
| const postList = () => { | ||||
|   listPost({ pageNum: 1, pageSize: 100 }).then((res) => { | ||||
|     state.postListAll = res.rows ?? []; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const initTableData = () => { | ||||
|   busViolationLevelList(); | ||||
| }; | ||||
|  | ||||
| const resetQuery = (formEl?: FormInstance) => { | ||||
|   if (!formEl) return; | ||||
|   formEl.resetFields(); | ||||
|   console.log(useUserStoreHook().selectedProject, currentProject.value?.id); | ||||
|  | ||||
|   busViolationLevelList(); | ||||
| }; | ||||
|  | ||||
| const busViolationLevelList = () => { | ||||
|   loading.value = true; | ||||
|   listViolationLevel(state.tableData.param).then((res: any) => { | ||||
|     const list = res.rows ?? []; | ||||
|     state.tableData.data = list; | ||||
|     state.tableData.total = res.total; | ||||
|     loading.value = false; | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const toggleSearch = () => { | ||||
|   showAll.value = !showAll.value; | ||||
| }; | ||||
|  | ||||
| const tourTypeFormat = (row: ViolationLevelVO) => { | ||||
|   const type: string[] = []; | ||||
|   if (row.violationType.includes(',')) { | ||||
|     (row.violationType as string).split(',').forEach((item) => { | ||||
|       type.push(proxy.selectDictLabel(violation_level_type.value, item)); | ||||
|     }); | ||||
|   } else { | ||||
|     type.push(proxy.selectDictLabel(violation_level_type.value, row.violationType as string)); | ||||
|   } | ||||
|   return type.join(','); | ||||
| }; | ||||
|  | ||||
| const handleSelectionChange = (selection: ViolationLevelForm[]) => { | ||||
|   state.ids = selection.map((item) => item.id); | ||||
|   single.value = selection.length !== 1; | ||||
|   multiple.value = selection.length === 0; | ||||
| }; | ||||
|  | ||||
| const handleAdd = () => { | ||||
|   addRef.value?.openDialog(); | ||||
| }; | ||||
|  | ||||
| const handleUpdate = (row: ViolationLevelVO | null) => { | ||||
|   if (!row) { | ||||
|     row = state.tableData.data.find((item) => item.id === state.ids[0]) ?? null; | ||||
|   } | ||||
|   if (row) { | ||||
|     editRef.value?.openDialog(toRaw(row)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const handleDelete = (row: ViolationLevelVO | null) => { | ||||
|   let msg = '你确定要删除所选数据?'; | ||||
|   let id: (string | number)[] = []; | ||||
|   if (row) { | ||||
|     msg = `此操作将永久删除数据,是否继续?`; | ||||
|     id = [row.id as string]; | ||||
|   } else { | ||||
|     id = state.ids; | ||||
|   } | ||||
|   if (id.length === 0) { | ||||
|     ElMessage.error('请选择要删除的数据。'); | ||||
|     return; | ||||
|   } | ||||
|   ElMessageBox.confirm(msg, '提示', { | ||||
|     confirmButtonText: '确认', | ||||
|     cancelButtonText: '取消', | ||||
|     type: 'warning' | ||||
|   }) | ||||
|     .then(() => { | ||||
|       delViolationLevel(id).then(() => { | ||||
|         ElMessage.success('删除成功'); | ||||
|         busViolationLevelList(); | ||||
|       }); | ||||
|     }) | ||||
|     .catch(() => {}); | ||||
| }; | ||||
|  | ||||
| const handleView = (row: ViolationLevelVO) => { | ||||
|   detailRef.value?.openDialog(toRaw(row)); | ||||
| }; | ||||
|  | ||||
| const indexMethod = (index: number) => { | ||||
|   const pageNum = state.tableData.param.pageNum - 1; | ||||
|   if (pageNum !== -1 && pageNum !== 0) { | ||||
|     return index + 1 + pageNum * state.tableData.param.pageSize; | ||||
|   } else { | ||||
|     return index + 1; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| const filterRiskLevelType = (val: any) => { | ||||
|   let label = ''; | ||||
|   if (val) { | ||||
|     if (risk_level_type.value.length) { | ||||
|       risk_level_type.value.forEach((item: any) => { | ||||
|         if (item.value == val) { | ||||
|           label = item.label; | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|   return label; | ||||
| }; | ||||
|  | ||||
| onMounted(() => { | ||||
|   postList(); | ||||
|   initTableData(); | ||||
| }); | ||||
|  | ||||
| //监听项目id刷新数据 | ||||
| const listeningProject = watch( | ||||
|   () => currentProject.value.id, | ||||
|   (nid, oid) => { | ||||
|     state.tableData.param.projectId = nid; | ||||
|     initTableData(); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| onUnmounted(() => { | ||||
|   listeningProject(); | ||||
| }); | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .colBlock { | ||||
|   display: block; | ||||
| } | ||||
| .colNone { | ||||
|   display: none; | ||||
| } | ||||
| </style> | ||||
| @ -15,7 +15,7 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => { | ||||
|         '~': path.resolve(__dirname, './'), | ||||
|         '@': path.resolve(__dirname, './src') | ||||
|       }, | ||||
|       extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] | ||||
|       extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue', '.tif'] | ||||
|     }, | ||||
|     // https://cn.vitejs.dev/config/#resolve-extensions | ||||
|     plugins: createPlugins(env, command === 'build'), | ||||
|  | ||||
		Reference in New Issue
	
	Block a user