diff --git a/BACKEND_SEARCH_API.md b/BACKEND_SEARCH_API.md new file mode 100644 index 0000000..6f72e1b --- /dev/null +++ b/BACKEND_SEARCH_API.md @@ -0,0 +1,91 @@ +# 制度类型搜索接口实现指南 + +## 接口定义 + +### 请求接口 +``` +GET /api/regulation/types +Content-Type: application/json +``` + +### 请求参数 +```json +{ + "page": number, // 页码(可选,默认1) + "size": number, // 每页大小(可选,默认10) + "typeName": "string", // 类型名称(模糊搜索,可选) + "status": "string", // 状态筛选("1"启用,"0"禁用,可选) + "remark": "string" // 备注内容(模糊搜索,可选) +} +``` + +### 响应格式 +```json +{ + "code": 200, + "message": "success", + "data": { + "records": [ + { + "typeId": "string", + "typeName": "string", + "sortOrder": number, + "isEnabled": "string", + "remark": "string", + "createBy": "string", + "createTime": "string", + "updateBy": "string", + "updateTime": "string", + "delFlag": "string" + } + ], + "total": number, // 总记录数 + "current": number, // 当前页码 + "size": number, // 每页大小 + "pages": number // 总页数 + } +} +``` + +## 后端实现说明 + +后端已实现以下接口: +```java +@ApiOperation(value = "获取制度类型列表", httpMethod = "GET") +@GetMapping +public Result getRegulationTypes( + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false) String typeName, + @RequestParam(required = false) String status, + @RequestParam(required = false) String remark +) { + return regulationTypeService.getRegulationTypes(page, size, typeName, status, remark); +} +``` + +## 前端集成说明 + +前端已完成以下功能: +1. ✅ 调整为GET请求接口 +2. ✅ 参数名匹配后端接口(isEnabled → status) +3. ✅ 移除排序参数(后端不支持) +4. ✅ 简化搜索表单,只支持手动搜索 +5. ✅ 保持原有功能不受影响 + +## 搜索流程 + +1. 用户在搜索表单中输入条件 +2. 点击"搜索"按钮触发搜索 +3. 调用后端GET接口 `/api/regulation/types` +4. 后端返回搜索结果 +5. 前端展示搜索结果 + +## 参数说明 + +- **page**: 页码,默认1 +- **size**: 每页大小,默认10 +- **typeName**: 类型名称,支持模糊搜索 +- **status**: 状态筛选,"1"表示启用,"0"表示禁用 +- **remark**: 备注内容,支持模糊搜索 + diff --git a/REGULATION_ANNOUNCEMENT_SEARCH_API.md b/REGULATION_ANNOUNCEMENT_SEARCH_API.md new file mode 100644 index 0000000..600d403 --- /dev/null +++ b/REGULATION_ANNOUNCEMENT_SEARCH_API.md @@ -0,0 +1,125 @@ +# 制度公告搜索接口实现指南 + +## 接口定义 + +### 请求接口 +``` +GET /api/regulation +Content-Type: application/json +``` + +### 请求参数 +```json +{ + "page": number, // 页码(可选,默认1) + "size": number, // 每页大小(可选,默认10) + "status": "string", // 状态筛选(精确匹配,固定为"PUBLISHED") + "title": "string", // 制度标题(模糊搜索,可选) + "proposer": "string", // 公示人(模糊搜索,可选) + "confirmStatus": "string" // 确认状态(精确匹配,可选) +} +``` + +### 响应格式 +```json +{ + "code": 200, + "message": "success", + "data": { + "records": [ + { + "regulationId": "string", + "title": "string", + "content": "string", + "regulationType": "string", + "status": "string", + "publishTime": "string", + "effectiveTime": "string", + "expireTime": "string", + "scope": "string", + "level": "string", + "version": "string", + "remark": "string", + "createBy": "string", + "updateBy": "string", + "createTime": "string", + "updateTime": "string", + "delFlag": "string", + "confirmStatus": "string" + } + ], + "total": number, // 总记录数 + "current": number, // 当前页码 + "size": number, // 每页大小 + "pages": number // 总页数 + } +} +``` + +## 后端实现说明 + +后端已实现以下接口: +```java +@ApiOperation(value = "获取制度列表", httpMethod = "GET") +@GetMapping +public Result getRegulationList( + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false) String status, + @RequestParam(required = false) String type, + @RequestParam(required = false) String title, + @RequestParam(required = false) String proposer, + @RequestParam(required = false) String confirmStatus +) { + return regulationService.getRegulationList(page, size, status, type, title, proposer, confirmStatus); +} +``` + +## 前端集成说明 + +前端已完成以下功能: +1. ✅ 删除前端搜索逻辑(防抖、实时搜索等) +2. ✅ 调整为GET请求接口 +3. ✅ 参数名匹配后端接口(createByName → proposer) +4. ✅ 简化搜索表单,只支持手动搜索 +5. ✅ 移除前端过滤逻辑,由后端处理状态筛选 +6. ✅ 保持原有功能不受影响 + +## 搜索流程 + +1. 用户在搜索表单中输入条件 +2. 点击"搜索"按钮触发搜索 +3. 调用后端GET接口 `/api/regulation` +4. 后端返回搜索结果(已过滤为PUBLISHED状态的制度) +5. 前端展示搜索结果 + +## 参数说明 + +- **page**: 页码,默认1 +- **size**: 每页大小,默认10 +- **status**: 状态筛选,固定为"PUBLISHED"(已公告状态) +- **title**: 制度标题,支持模糊搜索 +- **proposer**: 公示人,支持模糊搜索 +- **confirmStatus**: 确认状态,精确匹配(如:confirmed、pending) + +## 搜索功能特性 + +- **模糊搜索**:title 和 proposer 字段支持模糊匹配 +- **精确筛选**:confirmStatus 字段精确匹配 +- **分页查询**:支持分页和排序 +- **状态过滤**:后端自动过滤为PUBLISHED状态的制度 +- **性能优化**:使用数据库索引提升查询性能 + +## 业务逻辑说明 + +制度公告页面专门用于展示已经公告的制度,因此: +- 后端需要自动过滤为 `status = 'PUBLISHED'` 的制度 +- 支持按确认状态(confirmStatus)进行筛选 +- 前端不再需要手动过滤,完全依赖后端处理 +- 用户可以查看制度详情、下载PDF文件、确认知晓制度 + +## 确认状态说明 + +- **confirmed**: 已确认 - 用户已确认知晓并遵守该制度 +- **pending**: 待确认 - 用户尚未确认知晓该制度 +- 空值: 全部 - 显示所有确认状态的制度 \ No newline at end of file diff --git a/REGULATION_DISPLAY_SEARCH_API.md b/REGULATION_DISPLAY_SEARCH_API.md new file mode 100644 index 0000000..a2d600f --- /dev/null +++ b/REGULATION_DISPLAY_SEARCH_API.md @@ -0,0 +1,117 @@ +# 制度公示搜索接口实现指南 + +## 接口定义 + +### 请求接口 +``` +GET /api/regulation +Content-Type: application/json +``` + +### 请求参数 +```json +{ + "page": number, // 页码(可选,默认1) + "size": number, // 每页大小(可选,默认10) + "status": "string", // 状态筛选(精确匹配,可选) + "type": "string", // 提案类型(精确匹配,可选) + "title": "string", // 提案标题(模糊搜索,可选) + "proposer": "string" // 提案人(模糊搜索,可选) +} +``` + +### 响应格式 +```json +{ + "code": 200, + "message": "success", + "data": { + "records": [ + { + "regulationId": "string", + "title": "string", + "content": "string", + "regulationType": "string", + "status": "string", + "publishTime": "string", + "effectiveTime": "string", + "expireTime": "string", + "scope": "string", + "level": "string", + "version": "string", + "remark": "string", + "createBy": "string", + "updateBy": "string", + "createTime": "string", + "updateTime": "string", + "delFlag": "string", + "confirmStatus": "string" + } + ], + "total": number, // 总记录数 + "current": number, // 当前页码 + "size": number, // 每页大小 + "pages": number // 总页数 + } +} +``` + +## 后端实现说明 + +后端已实现以下接口: +```java +@ApiOperation(value = "获取制度列表", httpMethod = "GET") +@GetMapping +public Result getRegulationList( + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false) String status, + @RequestParam(required = false) String type, + @RequestParam(required = false) String title, + @RequestParam(required = false) String proposer +) { + return regulationService.getRegulationList(page, size, status, type, title, proposer); +} +``` + +## 前端集成说明 + +前端已完成以下功能: +1. ✅ 删除前端搜索逻辑(防抖、实时搜索等) +2. ✅ 调整为GET请求接口 +3. ✅ 参数名匹配后端接口(createByName → proposer, regulationType → type) +4. ✅ 简化搜索表单,只支持手动搜索 +5. ✅ 移除前端过滤逻辑,由后端处理状态筛选 +6. ✅ 保持原有功能不受影响 + +## 搜索流程 + +1. 用户在搜索表单中输入条件 +2. 点击"搜索"按钮触发搜索 +3. 调用后端GET接口 `/api/regulation` +4. 后端返回搜索结果(已过滤掉草稿状态的提案) +5. 前端展示搜索结果 + +## 参数说明 + +- **page**: 页码,默认1 +- **size**: 每页大小,默认10 +- **status**: 状态筛选,精确匹配(如:PUBLISHED、APPROVED等) +- **type**: 提案类型,精确匹配(如:管理规范、操作流程、安全制度、其他) +- **title**: 提案标题,支持模糊搜索 +- **proposer**: 提案人,支持模糊搜索 + +## 搜索功能特性 + +- **模糊搜索**:title 和 proposer 字段支持模糊匹配 +- **精确筛选**:type 和 status 字段精确匹配 +- **分页查询**:支持分页和排序 +- **状态过滤**:后端自动过滤掉草稿状态的提案,只显示已公示及以上的提案 +- **性能优化**:使用数据库索引提升查询性能 + +## 业务逻辑说明 + +制度公示页面专门用于展示已经公示或已通过的制度提案,因此: +- 后端需要自动过滤掉 `status = 'DRAFT'` 的提案 +- 只返回 `status = 'PUBLISHED'` 或 `status = 'APPROVED'` 的提案 +- 前端不再需要手动过滤,完全依赖后端处理 \ No newline at end of file diff --git a/REGULATION_PROPOSAL_SEARCH_API.md b/REGULATION_PROPOSAL_SEARCH_API.md new file mode 100644 index 0000000..add5ee1 --- /dev/null +++ b/REGULATION_PROPOSAL_SEARCH_API.md @@ -0,0 +1,108 @@ +# 制度提案搜索接口实现指南 + +## 接口定义 + +### 请求接口 +``` +GET /api/regulation +Content-Type: application/json +``` + +### 请求参数 +```json +{ + "page": number, // 页码(可选,默认1) + "size": number, // 每页大小(可选,默认10) + "status": "string", // 状态筛选(精确匹配,可选) + "type": "string", // 提案类型(精确匹配,可选) + "title": "string", // 提案标题(模糊搜索,可选) + "proposer": "string" // 提案人(模糊搜索,可选) +} +``` + +### 响应格式 +```json +{ + "code": 200, + "message": "success", + "data": { + "records": [ + { + "regulationId": "string", + "title": "string", + "content": "string", + "regulationType": "string", + "status": "string", + "publishTime": "string", + "effectiveTime": "string", + "expireTime": "string", + "scope": "string", + "level": "string", + "version": "string", + "remark": "string", + "createBy": "string", + "updateBy": "string", + "createTime": "string", + "updateTime": "string", + "delFlag": "string", + "confirmStatus": "string" + } + ], + "total": number, // 总记录数 + "current": number, // 当前页码 + "size": number, // 每页大小 + "pages": number // 总页数 + } +} +``` + +## 后端实现说明 + +后端已实现以下接口: +```java +@ApiOperation(value = "获取制度列表", httpMethod = "GET") +@GetMapping +public Result getRegulationList( + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false) String status, + @RequestParam(required = false) String type, + @RequestParam(required = false) String title, + @RequestParam(required = false) String proposer +) { + return regulationService.getRegulationList(page, size, status, type, title, proposer); +} +``` + +## 前端集成说明 + +前端已完成以下功能: +1. ✅ 删除前端搜索逻辑(防抖、实时搜索等) +2. ✅ 调整为GET请求接口 +3. ✅ 参数名匹配后端接口(createByName → proposer, regulationType → type) +4. ✅ 简化搜索表单,只支持手动搜索 +5. ✅ 保持原有功能不受影响 + +## 搜索流程 + +1. 用户在搜索表单中输入条件 +2. 点击"搜索"按钮触发搜索 +3. 调用后端GET接口 `/api/regulation` +4. 后端返回搜索结果 +5. 前端展示搜索结果 + +## 参数说明 + +- **page**: 页码,默认1 +- **size**: 每页大小,默认10 +- **status**: 状态筛选,精确匹配(如:DRAFT、PUBLISHED、APPROVED等) +- **type**: 提案类型,精确匹配(如:管理规范、操作流程、安全制度、其他) +- **title**: 提案标题,支持模糊搜索 +- **proposer**: 提案人,支持模糊搜索 + +## 搜索功能特性 + +- **模糊搜索**:title 和 proposer 字段支持模糊匹配 +- **精确筛选**:type 和 status 字段精确匹配 +- **分页查询**:支持分页和排序 +- **性能优化**:使用数据库索引提升查询性能 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bc2b071..9de5c1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,9 @@ "crypto-js": "^4.2.0", "dayjs": "^1.11.4", "echarts": "^5.4.2", + "html2canvas": "^1.4.1", "jsencrypt": "^3.3.2", + "jspdf": "^3.0.1", "lint-staged": "^15.2.10", "lodash-es": "^4.17.21", "mitt": "^3.0.0", @@ -3278,6 +3280,13 @@ "query-string": "*" } }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/sortablejs": { "version": "1.15.8", "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.8.tgz", @@ -3295,6 +3304,13 @@ "@types/node": "*" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -4869,7 +4885,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, "license": "(MIT OR Apache-2.0)", "bin": { "atob": "bin/atob.js" @@ -4952,6 +4967,15 @@ "node": ">=0.10.0" } }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -5075,6 +5099,18 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -5244,6 +5280,26 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvg": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", + "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/capital-case": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", @@ -5972,6 +6028,15 @@ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", "license": "MIT" }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -6423,6 +6488,16 @@ "domelementtype": "1" } }, + "node_modules/dompurify": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", + "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optional": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", @@ -8296,6 +8371,12 @@ "integrity": "sha512-V1PWovkspxQfssq/NnxoEyQo1DV+MRK/laPuPblIZmSjMN8P5u46OhlFQznSr9p/t0Sp8Uc6SbM3yCMfr0KU8g==", "license": "MIT" }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/figures": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", @@ -9054,6 +9135,19 @@ "dev": true, "license": "ISC" }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -10079,6 +10173,24 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jspdf": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.1.tgz", + "integrity": "sha512-qaGIxqxetdoNnFQQXxTKUD9/Z7AloLaw94fFsOiJMxbfYdBbrBuhWmbzI8TVjrw7s3jBY1PFHofBKMV/wZPapg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.7", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.8.1" + }, + "optionalDependencies": { + "canvg": "^3.0.11", + "core-js": "^3.6.0", + "dompurify": "^3.2.4", + "html2canvas": "^1.0.0-rc.5" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -11669,6 +11781,13 @@ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "license": "MIT" }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT", + "optional": true + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -12225,6 +12344,16 @@ ], "license": "MIT" }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "license": "MIT", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12411,6 +12540,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "optional": true + }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -12679,6 +12815,16 @@ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, "node_modules/rollup": { "version": "4.46.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.1.tgz", @@ -13629,6 +13775,16 @@ "node": ">=12.0.0" } }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -14216,6 +14372,16 @@ "node": ">=0.10.0" } }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -14338,6 +14504,15 @@ "license": "MIT", "peer": true }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/tinyexec": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", @@ -15284,6 +15459,15 @@ "node": ">= 0.4.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/v-viewer": { "version": "3.0.22", "resolved": "https://registry.npmjs.org/v-viewer/-/v-viewer-3.0.22.tgz", diff --git a/package.json b/package.json index 8c1b06b..623060d 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,9 @@ "crypto-js": "^4.2.0", "dayjs": "^1.11.4", "echarts": "^5.4.2", + "html2canvas": "^1.4.1", "jsencrypt": "^3.3.2", + "jspdf": "^3.0.1", "lint-staged": "^15.2.10", "lodash-es": "^4.17.21", "mitt": "^3.0.0", diff --git a/src/apis/attach-info/index.ts b/src/apis/attach-info/index.ts index 47539ce..89aab94 100644 --- a/src/apis/attach-info/index.ts +++ b/src/apis/attach-info/index.ts @@ -24,7 +24,7 @@ export function batchAddAttachment(businessType: string, formData: FormData) { * @param businessType 业务类型 * @param formData 表单数据 */ -export function addAttachment(formData: FormData) { +export function addAttachment(formData: FormData) { return request({ url: `/attach-info/model`, method: 'post', @@ -39,7 +39,7 @@ export function addAttachment(formData: FormData) { * @param businessType 业务类型 * @param formData 表单数据 */ -export function addAttachmentByDefectMarkPic(formData: FormData) { +export function addAttachmentByDefectMarkPic(formData: FormData) { return request({ url: `/attach-info/defect_mark_pic`, method: 'post', @@ -54,7 +54,7 @@ export function addAttachmentByDefectMarkPic(formData: FormData) { * @param businessType 业务类型 * @param formData 表单数据 */ -export function addAttachInsurance(formData: FormData) { +export function addAttachInsurance(formData: FormData) { return request({ url: `/attach-info/insurance_file`, method: 'post', diff --git a/src/apis/regulation/index.ts b/src/apis/regulation/index.ts index 3812ff9..8a3bacb 100644 --- a/src/apis/regulation/index.ts +++ b/src/apis/regulation/index.ts @@ -1,12 +1,22 @@ import http from '@/utils/http' +import { + type RegulationTypeSearchRequest, + type RegulationTypeSearchResponse, + type RegulationProposalSearchRequest, + type RegulationProposalSearchResponse +} from './type' // 制度管理API接口 export const regulationApi = { // 获取制度列表 getRegulationList: (params: { - page: number - size: number - }) => { + page?: number + size?: number + status?: string + type?: string + title?: string + proposer?: string + }): Promise => { return http.get('/regulation', params) }, @@ -23,6 +33,7 @@ export const regulationApi = { scope: string level: string remark?: string + createBy?: string }) => { return http.post('/regulation/proposal', data) }, @@ -32,17 +43,22 @@ export const regulationApi = { return http.put(`/regulation/proposal/${regulationId}`, data) }, + // 公示提案 + publishProposal: (regulationId: string) => { + return http.post(`/regulation/proposal/${regulationId}/publish`) + }, + // 删除制度提案 deleteProposal: (regulationId: string) => { return http.del(`/regulation/proposal/${regulationId}`) }, - // 发布制度 + // 公示制度 publishRegulation: (regulationId: string) => { - return http.post(`/regulation/${regulationId}/publish`) + return http.post(`/regulation/${regulationId}/approve`) }, - // 获取已发布制度列表 + // 获取已公示制度列表 getPublishedRegulationList: (params: { page: number size: number @@ -54,5 +70,39 @@ export const regulationApi = { // 确认制度知晓 confirmRegulation: (regulationId: string) => { return http.post(`/regulation/${regulationId}/confirm`) + }, + + // 搜索制度类型(后端搜索接口) + searchRegulationTypes: (params: { + page?: number + size?: number + typeName?: string + status?: string + remark?: string + }) => { + return http.get('/regulation/types', params) + }, + + // 创建制度类型 + createRegulationType: (data: { + typeName: string + sortOrder?: number + isEnabled?: string + }) => { + return http.post('/regulation/types', data) + }, + + // 更新制度类型 + updateRegulationType: (typeId: string, data: { + typeName: string + sortOrder?: number + isEnabled?: string + }) => { + return http.put(`/regulation/types/${typeId}`, data) + }, + + // 删除制度类型 + deleteRegulationType: (typeId: string) => { + return http.del(`/regulation/types/${typeId}`) } } \ No newline at end of file diff --git a/src/apis/regulation/type.ts b/src/apis/regulation/type.ts index c708bcb..1444879 100644 --- a/src/apis/regulation/type.ts +++ b/src/apis/regulation/type.ts @@ -1,11 +1,8 @@ // 制度状态枚举 export enum RegulationStatus { DRAFT = 'DRAFT', // 草稿 - VOTING = 'VOTING', // 投票中 APPROVED = 'APPROVED', // 已通过 - REJECTED = 'REJECTED', // 已否决 - PUBLISHED = 'PUBLISHED', // 已发布 - ARCHIVED = 'ARCHIVED' // 已归档 + PUBLISHED = 'PUBLISHED', // 已公示 } // 制度级别枚举 @@ -22,9 +19,7 @@ export interface Regulation { content: string regulationType: string status: RegulationStatus - publisherId: string - publisherName: string - publishTime: string + publishTime: string // 公示时间 effectiveTime: string expireTime: string scope: string @@ -38,6 +33,7 @@ export interface Regulation { page: number pageSize: number delFlag: string + confirmStatus?: string } // 创建提案请求接口 @@ -48,10 +44,78 @@ export interface CreateProposalRequest { scope: string level: RegulationLevel remark?: string + createBy?: string } // 分页参数接口 export interface PaginationParams { page: number size: number +} + +// 制度类型接口 +export interface RegulationType { + typeId: string + typeName: string + sortOrder: number + isEnabled: string + remark?: string + createBy: string + createTime: string + updateBy: string + updateTime: string + delFlag: string +} + +// 创建制度类型请求接口 +export interface CreateRegulationTypeRequest { + typeName: string + sortOrder?: number + isEnabled?: string + remark?: string +} + +// 更新制度类型请求接口 +export interface UpdateRegulationTypeRequest { + typeName: string + sortOrder?: number + isEnabled?: string + remark?: string +} + +// 制度类型搜索请求接口 +export interface RegulationTypeSearchRequest { + page?: number + size?: number + typeName?: string + status?: string + remark?: string +} + +// 制度类型搜索响应接口 +export interface RegulationTypeSearchResponse { + records: RegulationType[] + total: number + current: number + size: number + pages: number +} + +// 制度提案搜索请求接口 +export interface RegulationProposalSearchRequest { + page?: number + size?: number + status?: string + type?: string + title?: string + proposer?: string +} + +// 制度提案搜索响应接口 +export interface RegulationProposalSearchResponse { + records: Regulation[] + total: number + current: number + size: number + pages: number } \ No newline at end of file diff --git a/src/router/route.ts b/src/router/route.ts index 4e85f13..432dbc6 100644 --- a/src/router/route.ts +++ b/src/router/route.ts @@ -37,14 +37,27 @@ export const systemRoutes: RouteRecordRaw[] = [ path: '/regulation/system-regulation', name: 'SystemRegulation', component: () => import('@/views/regulation/repository.vue'), - meta: { title: '制度确认', icon: 'file-text', hidden: false }, + meta: { title: '制度公告', icon: 'file-text', hidden: false }, }, { path: '/regulation/process-management', name: 'ProcessManagement', component: () => import('@/views/regulation/confirm.vue'), - meta: { title: '流程管理', icon: 'workflow', hidden: false }, + meta: { title: '制度公示', icon: 'workflow', hidden: false }, }, + { + path: '/regulation/proposal', + name: 'RegulationProposal', + component: () => import('@/views/regulation/proposal/index.vue'), + meta: { title: '制度提案', icon: 'edit', hidden: false }, + }, + { + path: '/regulation/type', + name: 'RegulationType', + component: () => import('@/views/regulation/type/index.vue'), + meta: { title: '制度类型', icon: 'tag', hidden: false }, + }, + ], }, { @@ -545,9 +558,9 @@ export const systemRoutes: RouteRecordRaw[] = [ }, }, { - path: 'project-management/project-template/information-retrieval', + path: '/project-management/project-template/information-retrieval', name: 'InformationRetrieval', - component: () => import ('@/views/default/error/404.vue'), + component: () => import ('@/views/project-management/bidding/information-retrieval/index.vue'), meta: { title: '信息检索(N)', icon: 'trophy', @@ -796,11 +809,11 @@ export const systemRoutes: RouteRecordRaw[] = [ { path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/attachment', name: 'AttachmentManagement', - component: () => import('@/views/operation-platform/data-processing/data-storage/index.vue'), + component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/index.vue'), meta: { title: '附件管理', icon: 'attachment', hidden: false }, }, { - path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/model-config', + path: '/construction-operation-platform/implementation-workflow/data-processing/model-config', name: 'ModelConfig', component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/model-config/index.vue'), meta: { title: '模型配置', icon: 'robot', hidden: false }, @@ -811,8 +824,23 @@ export const systemRoutes: RouteRecordRaw[] = [ { path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/preprocessed-data', name: 'PreprocessedData', - component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/data-preprocessing/index.vue'), + component: () => import('@/components/ParentView/index.vue'), + redirect: '/construction-operation-platform/implementation-workflow/data-processing/data-storage', meta: { title: '数据预处理', icon: 'filter', hidden: false }, + children: [ + { + path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/preprocessed-data/ImageBatchUpload', + name: 'ImageBatchUpload', + component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/data-preprocessing/index.vue'), + meta: { title: '批量上传', icon: 'file', hidden: false }, + }, + { + path: '/construction-operation-platform/implementation-workflow/data-processing/data-storage/preprocessed-data/ImageSorting', + name: 'ImageSorting', + component: () => import('@/views/construction-operation-platform/implementation-workflow/data-processing/image-sorting/index.vue'), + meta: { title: '图像分拣', icon: 'attachment', hidden: false }, + }, + ], }, { path: '/construction-operation-platform/implementation-workflow/data-processing/intelligent-inspection', diff --git a/src/utils/pdfGenerator.ts b/src/utils/pdfGenerator.ts new file mode 100644 index 0000000..6b0bdfc --- /dev/null +++ b/src/utils/pdfGenerator.ts @@ -0,0 +1,169 @@ +import jsPDF from 'jspdf' +import html2canvas from 'html2canvas' + +// PDF生成器类 +export class PDFGenerator { + // 生成制度PDF + static async generateRegulationPDF(regulation: any): Promise { + // 创建临时HTML元素 + const tempDiv = document.createElement('div') + tempDiv.style.position = 'absolute' + tempDiv.style.left = '-9999px' + tempDiv.style.top = '-9999px' + tempDiv.style.width = '800px' + tempDiv.style.padding = '40px' + tempDiv.style.backgroundColor = 'white' + tempDiv.style.fontFamily = 'Arial, sans-serif' + tempDiv.style.fontSize = '14px' + tempDiv.style.lineHeight = '1.6' + tempDiv.style.color = '#333' + + // 添加水印样式 + tempDiv.style.position = 'relative' + tempDiv.style.overflow = 'hidden' + + // 生成HTML内容 + tempDiv.innerHTML = ` +
+ +
迪特聚能科技
+ + +

${regulation.title || '制度文档'}

+ + +
+ + + + + + + + + + + + + + + + + +
制度类型:${regulation.regulationType || '-'}发布人:${regulation.createByName || regulation.createBy || '-'}
发布时间:${regulation.publishTime || '-'}生效日期:${regulation.effectiveTime || '-'}
适用范围:${regulation.scope || '-'}制度级别:${regulation.level || '-'}
版本:${regulation.version || '1.0'}
+
+ + +
+ + +
+

制度内容:

+
${regulation.content || ''}
+
+ + ${regulation.remark ? ` + +
+

备注:

+
${regulation.remark}
+
+ ` : ''} + + +
+ 生成时间:${new Date().toLocaleString('zh-CN')} | 制度ID:${regulation.regulationId || '-'} +
+
+ ` + + // 添加到DOM + document.body.appendChild(tempDiv) + + try { + // 使用html2canvas转换为图片 + const canvas = await html2canvas(tempDiv, { + scale: 2, // 提高清晰度 + useCORS: true, + allowTaint: true, + backgroundColor: '#ffffff', + width: 800, + height: tempDiv.scrollHeight + }) + + // 创建PDF + const imgData = canvas.toDataURL('image/png') + const pdf = new jsPDF('p', 'mm', 'a4') + + const imgWidth = 210 // A4宽度 + const pageHeight = 295 // A4高度 + const imgHeight = (canvas.height * imgWidth) / canvas.width + let heightLeft = imgHeight + let position = 0 + + // 添加第一页 + pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight) + heightLeft -= pageHeight + + // 添加后续页面 + while (heightLeft >= 0) { + position = heightLeft - imgHeight + pdf.addPage() + pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight) + heightLeft -= pageHeight + } + + // 返回PDF blob + return pdf.output('blob') + } finally { + // 清理临时元素 + document.body.removeChild(tempDiv) + } + } + + // 下载PDF文件 + static downloadPDF(blob: Blob, filename: string) { + const url = URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = filename + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + URL.revokeObjectURL(url) + } +} \ No newline at end of file diff --git a/src/views/construction-operation-platform/implementation-workflow/data-processing/data-preprocessing/index.vue b/src/views/construction-operation-platform/implementation-workflow/data-processing/data-preprocessing/index.vue index 2fde12e..9be1792 100644 --- a/src/views/construction-operation-platform/implementation-workflow/data-processing/data-preprocessing/index.vue +++ b/src/views/construction-operation-platform/implementation-workflow/data-processing/data-preprocessing/index.vue @@ -1,202 +1,160 @@ \ No newline at end of file + +.thumbnail-cell { + display: flex; + justify-content: center; + align-items: center; + height: 60px; + + .thumbnail-image { + max-height: 60px; + max-width: 80px; + object-fit: contain; + border-radius: 2px; + } + + .file-icon { + font-size: 24px; + color: var(--color-text-3); + } +} + +/* 上传进度框样式 */ +.upload-progress-fixed { + position: fixed; + bottom: 24px; + right: 24px; + width: 360px; + z-index: 1000; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); + border-radius: 8px; + animation: fadeIn 0.3s ease; + + :deep(.arco-card-header) { + border-bottom: 1px solid var(--color-border); + padding-bottom: 12px; + } + + :deep(.arco-progress-text) { + font-size: 14px; + } +} + +.progress-details { + margin-top: 12px; + font-size: 13px; + color: var(--color-text-2); + + p { + display: flex; + align-items: center; + margin: 6px 0; + + .arco-icon { + margin-right: 8px; + font-size: 16px; + } + } +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } +} + \ No newline at end of file diff --git a/src/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/components/AttachmentUpload.vue b/src/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/components/AttachmentUpload.vue index 4bfb83e..401861d 100644 --- a/src/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/components/AttachmentUpload.vue +++ b/src/views/construction-operation-platform/implementation-workflow/data-processing/data-storage/components/AttachmentUpload.vue @@ -105,8 +105,16 @@ const formData = reactive({ const fetchBusinessTypes = async () => { try { const res = await getAttachBusinessTypes() + console.log("res:",res); if (res.data) { - businessTypes.value = res.data + res.data.forEach(item => { + const key = Object.keys(item)[0]; + const value = item[key]; + businessTypes.value.push({ + name: value, + code:key + }); + }); } } catch (error) { console.error('获取业务类型失败:', error) diff --git a/src/views/construction-operation-platform/implementation-workflow/data-processing/image-sorting/index.vue b/src/views/construction-operation-platform/implementation-workflow/data-processing/image-sorting/index.vue new file mode 100644 index 0000000..f1625a8 --- /dev/null +++ b/src/views/construction-operation-platform/implementation-workflow/data-processing/image-sorting/index.vue @@ -0,0 +1,603 @@ + + + + + \ No newline at end of file diff --git a/src/views/operation-platform/data-processing/data-storage/components/PreviewModal.vue b/src/views/operation-platform/data-processing/data-storage/components/PreviewModal.vue index 8bdee3a..1b29315 100644 --- a/src/views/operation-platform/data-processing/data-storage/components/PreviewModal.vue +++ b/src/views/operation-platform/data-processing/data-storage/components/PreviewModal.vue @@ -106,12 +106,14 @@ const getAudioUrl = (filePath: string): string => { const openPreview = (item: PreviewItem) => { currentPreviewItem.value = item audioList.value = [] - for (const audio of item.audios) { - let temp={ - audioId:audio.audioId, - url:getAudioUrl(audio.filePath) + if(item.audios){ + for (const audio of item.audios) { + let temp={ + audioId:audio.audioId, + url:getAudioUrl(audio.filePath) + } + audioList.value.push(temp) } - audioList.value.push(temp) } previewModalVisible.value = true diff --git a/src/views/operation-platform/data-processing/data-storage/index.vue b/src/views/operation-platform/data-processing/data-storage/index.vue index b7b461e..3b95a64 100644 --- a/src/views/operation-platform/data-processing/data-storage/index.vue +++ b/src/views/operation-platform/data-processing/data-storage/index.vue @@ -251,15 +251,22 @@ const fetchPartList = async (projectId: string, turbineId: string) => { // 处理筛选变化,获取图像列表 const handleFilterChange = async () => { - if (!filterParams.unit) return + // if (!filterParams.project) return loading.image = true try { let params = { - turbineId: filterParams.unit + projectId: filterParams.project + } + if(filterParams.unit){ + params = { + projectId: filterParams.project, + turbineId: filterParams.unit + } } if(filterParams.component){ params = { + projectId: filterParams.project, turbineId: filterParams.unit, partId: filterParams.component } diff --git a/src/views/project-management/bidding/information-retrieval/components/BiddingDetailModal.vue b/src/views/project-management/bidding/information-retrieval/components/BiddingDetailModal.vue new file mode 100644 index 0000000..992779f --- /dev/null +++ b/src/views/project-management/bidding/information-retrieval/components/BiddingDetailModal.vue @@ -0,0 +1,198 @@ + + + + + \ No newline at end of file diff --git a/src/views/project-management/bidding/information-retrieval/components/CrawlerSettings.vue b/src/views/project-management/bidding/information-retrieval/components/CrawlerSettings.vue new file mode 100644 index 0000000..0131282 --- /dev/null +++ b/src/views/project-management/bidding/information-retrieval/components/CrawlerSettings.vue @@ -0,0 +1,164 @@ + + + + + \ No newline at end of file diff --git a/src/views/regulation/confirm.vue b/src/views/regulation/confirm.vue index eabb7ee..3fedb0e 100644 --- a/src/views/regulation/confirm.vue +++ b/src/views/regulation/confirm.vue @@ -1,14 +1,69 @@