Compare commits
	
		
			63 Commits
		
	
	
		
			prod
			...
			5f3ae0f9f1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5f3ae0f9f1 | |||
| 786c864a27 | |||
| c61e802b85 | |||
| 9a568799f4 | |||
| 8aa38063bf | |||
| c4a11ec245 | |||
| 169b76589c | |||
| 199f51ea21 | |||
| 23572dfc07 | |||
| 570b0ce316 | |||
| f953a96c36 | |||
| 25c4eee464 | |||
| b209ef1fab | |||
| 77e9f4d9a2 | |||
| e73c808bc3 | |||
| edf0d1a5db | |||
| cc23a308c1 | |||
| bc891327c9 | |||
| 39bedfeb92 | |||
| 56fc4ff83e | |||
| 524ed30728 | |||
| 584304e744 | |||
| 56418600c5 | |||
| 40e57b18cb | |||
| ced6cb219c | |||
| 218ec5ea95 | |||
| 1c601bd68e | |||
| 7d6eba719b | |||
| 8cfc34dbcb | |||
| 23a749973d | |||
| 4b96702dc9 | |||
| a1af8711ef | |||
| 9e8cff931b | |||
| 5bccd71bdc | |||
| 544f35a601 | |||
| f920d4976e | |||
| cdcd665d43 | |||
| 08de61e455 | |||
| 025c3115b7 | |||
| 9e366554b7 | |||
| d934abf0fe | |||
| e16e9133e2 | |||
| d7854a35d7 | |||
| 97e0dd467f | |||
| e58a99e696 | |||
| 0d5a9eb505 | |||
| 45ac1817e1 | |||
| f2d4ff4237 | |||
| a4cc5c14f3 | |||
| 5be571cc30 | |||
| ff656dd046 | |||
| 20574d0037 | |||
| 42cf396e93 | |||
| 2a30b05dd7 | |||
| 4ecee185bf | |||
| 48ab59c67d | |||
| 806e8f3391 | |||
| 61244321a7 | |||
| ff1e613316 | |||
| 03161751fc | |||
| 9ebf4a3e5f | |||
| 3ba13e3ef8 | |||
| 8d3853fe6b | 
| @ -1,3 +1,7 @@ | |||||||
|  | # 开发环境配置 | ||||||
|  | server: | ||||||
|  |   # 服务器的HTTP端口,默认为8080 | ||||||
|  |   port: 8899 | ||||||
| --- # 监控中心配置 | --- # 监控中心配置 | ||||||
| spring.boot.admin.client: | spring.boot.admin.client: | ||||||
|   # 增加客户端开关 |   # 增加客户端开关 | ||||||
| @ -32,6 +36,12 @@ snail-job: | |||||||
|  |  | ||||||
| --- # 数据源配置 | --- # 数据源配置 | ||||||
| spring: | spring: | ||||||
|  |   ai: | ||||||
|  |     dashscope: | ||||||
|  |       api-key: sk-8d8df92fcbac4bd2922edba30b0bb8fa | ||||||
|  |       chat: | ||||||
|  |         options: | ||||||
|  |           model: qwen-plus | ||||||
|   datasource: |   datasource: | ||||||
|     type: com.zaxxer.hikari.HikariDataSource |     type: com.zaxxer.hikari.HikariDataSource | ||||||
|     # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content |     # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content | ||||||
| @ -52,9 +62,9 @@ spring: | |||||||
|           url: jdbc:mysql://192.168.110.2:13386/xinnengyuandev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |           url: jdbc:mysql://192.168.110.2:13386/xinnengyuandev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 | ||||||
|           username: xinnengyuandev |           username: xinnengyuandev | ||||||
|           password: StRWCZdZirysNSs2 |           password: StRWCZdZirysNSs2 | ||||||
| #          url: jdbc:mysql://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |           #          url: jdbc:mysql://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 | ||||||
| #          username: xinnengyuan |           #          username: xinnengyuan | ||||||
| #          password: mEZPC5Sdf3r2HENi |           #          password: mEZPC5Sdf3r2HENi | ||||||
|           # 从库数据源 |           # 从库数据源 | ||||||
|         slave: |         slave: | ||||||
|           lazy: true |           lazy: true | ||||||
| @ -77,13 +87,13 @@ spring: | |||||||
|           url: jdbc:mysql://192.168.110.2:13386/zmkgc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true |           url: jdbc:mysql://192.168.110.2:13386/zmkgc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true | ||||||
|           username: zmkgc |           username: zmkgc | ||||||
|           password: nWKDKRNRT48tFBdh |           password: nWKDKRNRT48tFBdh | ||||||
| #        slave: |       #        slave: | ||||||
| #          lazy: true |       #          lazy: true | ||||||
| #          type: ${spring.datasource.type} |       #          type: ${spring.datasource.type} | ||||||
| #          driverClassName: com.mysql.cj.jdbc.Driver |       #          driverClassName: com.mysql.cj.jdbc.Driver | ||||||
| #          url: jdbc:mysql://192.168.110.2:13386/zmkgprod?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true |       #          url: jdbc:mysql://192.168.110.2:13386/zmkgprod?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true | ||||||
| #          username: zmkgprod |       #          username: zmkgprod | ||||||
| #          password: MaY8nehwWkJriWPm |       #          password: MaY8nehwWkJriWPm | ||||||
|       #        oracle: |       #        oracle: | ||||||
|       #          type: ${spring.datasource.type} |       #          type: ${spring.datasource.type} | ||||||
|       #          driverClassName: oracle.jdbc.OracleDriver |       #          driverClassName: oracle.jdbc.OracleDriver | ||||||
| @ -354,3 +364,7 @@ qrCode: | |||||||
| # 无人机大图 | # 无人机大图 | ||||||
| drone: | drone: | ||||||
|   url: http://192.168.110.2:9512 |   url: http://192.168.110.2:9512 | ||||||
|  | # 聊天服务 | ||||||
|  | chat: | ||||||
|  |   server: | ||||||
|  |     port: 19099 | ||||||
|  | |||||||
| @ -1,3 +1,7 @@ | |||||||
|  | # 开发环境配置 | ||||||
|  | server: | ||||||
|  |   # 服务器的HTTP端口,默认为8080 | ||||||
|  |   port: 9918 | ||||||
| --- # 临时文件存储位置 避免临时文件被系统清理报错 | --- # 临时文件存储位置 避免临时文件被系统清理报错 | ||||||
| spring.servlet.multipart.location: /ruoyi/server/temp | spring.servlet.multipart.location: /ruoyi/server/temp | ||||||
|  |  | ||||||
| @ -35,6 +39,12 @@ snail-job: | |||||||
|  |  | ||||||
| --- # 数据源配置 | --- # 数据源配置 | ||||||
| spring: | spring: | ||||||
|  |   ai: | ||||||
|  |     dashscope: | ||||||
|  |       api-key: xxx | ||||||
|  |       chat: | ||||||
|  |         options: | ||||||
|  |           model: qwen-plus | ||||||
|   datasource: |   datasource: | ||||||
|     type: com.zaxxer.hikari.HikariDataSource |     type: com.zaxxer.hikari.HikariDataSource | ||||||
|     # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content |     # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content | ||||||
| @ -105,7 +115,7 @@ spring.data: | |||||||
|     # 端口,默认为6379 |     # 端口,默认为6379 | ||||||
|     port: 9287 |     port: 9287 | ||||||
|     # 数据库索引 |     # 数据库索引 | ||||||
|     database: 6 |     database: 17 | ||||||
|     # redis 密码必须配置 |     # redis 密码必须配置 | ||||||
|     password: syar23rdsaagdrsa |     password: syar23rdsaagdrsa | ||||||
|     # 连接超时时间 |     # 连接超时时间 | ||||||
| @ -164,7 +174,7 @@ sms: | |||||||
|   # 配置源类型用于标定配置来源(interface,yaml) |   # 配置源类型用于标定配置来源(interface,yaml) | ||||||
|   config-type: yaml |   config-type: yaml | ||||||
|   # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制 |   # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制 | ||||||
|   restricted: true |   restricted: false | ||||||
|   # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效 |   # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效 | ||||||
|   minute-max: 1 |   minute-max: 1 | ||||||
|   # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效 |   # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效 | ||||||
| @ -183,12 +193,45 @@ sms: | |||||||
|       signature: 您的短信签名 |       signature: 您的短信签名 | ||||||
|       sdk-app-id: 您的sdkAppId |       sdk-app-id: 您的sdkAppId | ||||||
|     config2: |     config2: | ||||||
|       # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 |       # 登录 | ||||||
|       supplier: tencent |       supplier: tencent | ||||||
|       access-key-id: 您的accessKey |       access-key-id: AKIDb3JK5dx4wa0DCxWqvxlKejvysZ3ITVJv | ||||||
|       access-key-secret: 您的accessKeySecret |       access-key-secret: c5LPFsJI8k7GDxTkoeFj4A1ukQr66rPi | ||||||
|       signature: 您的短信签名 |       signature: 重庆远界大数据研究院 | ||||||
|       sdk-app-id: 您的sdkAppId |       sdk-app-id: 1401018866 | ||||||
|  |       template-id: 2491779 | ||||||
|  |     config3: | ||||||
|  |       # 注册 | ||||||
|  |       supplier: tencent | ||||||
|  |       access-key-id: AKIDb3JK5dx4wa0DCxWqvxlKejvysZ3ITVJv | ||||||
|  |       access-key-secret: c5LPFsJI8k7GDxTkoeFj4A1ukQr66rPi | ||||||
|  |       signature: 重庆远界大数据研究院 | ||||||
|  |       sdk-app-id: 1401018866 | ||||||
|  |       template-id: 2491776 | ||||||
|  |     config4: | ||||||
|  |       # 质量工单逾期 | ||||||
|  |       supplier: tencent | ||||||
|  |       access-key-id: AKIDb3JK5dx4wa0DCxWqvxlKejvysZ3ITVJv | ||||||
|  |       access-key-secret: c5LPFsJI8k7GDxTkoeFj4A1ukQr66rPi | ||||||
|  |       signature: 重庆远界大数据研究院 | ||||||
|  |       sdk-app-id: 1401018866 | ||||||
|  |       template-id: 2534747 | ||||||
|  |     config5: | ||||||
|  |       # 设计图纸 | ||||||
|  |       supplier: tencent | ||||||
|  |       access-key-id: AKIDb3JK5dx4wa0DCxWqvxlKejvysZ3ITVJv | ||||||
|  |       access-key-secret: c5LPFsJI8k7GDxTkoeFj4A1ukQr66rPi | ||||||
|  |       signature: 重庆远界大数据研究院 | ||||||
|  |       sdk-app-id: 1401018866 | ||||||
|  |       template-id: 2534750 | ||||||
|  |     config6: | ||||||
|  |       # 安全工单 | ||||||
|  |       supplier: tencent | ||||||
|  |       access-key-id: AKIDb3JK5dx4wa0DCxWqvxlKejvysZ3ITVJv | ||||||
|  |       access-key-secret: c5LPFsJI8k7GDxTkoeFj4A1ukQr66rPi | ||||||
|  |       signature: 重庆远界大数据研究院 | ||||||
|  |       sdk-app-id: 1401018866 | ||||||
|  |       template-id: 2534848 | ||||||
|  |  | ||||||
| --- # 三方授权 | --- # 三方授权 | ||||||
| justauth: | justauth: | ||||||
| @ -275,8 +318,11 @@ weather: | |||||||
| dxf2GeoJson: | dxf2GeoJson: | ||||||
|   file-name: main |   file-name: main | ||||||
| ys7: | ys7: | ||||||
|   app-key: 3acf9f1a43dc4209841e0893003db0a2 |   app-key: xxx | ||||||
|   app-secret: 4bbf3e9394f55d3af6e3af27b2d3db36 |   app-secret: xxx | ||||||
|  |   job: | ||||||
|  |     capture-enabled: false   # 控制是否启用萤石抓拍任务 | ||||||
|  |     device-sync-enabled: false # 控制是否同步萤石设备 | ||||||
| # 斯巴达算法 | # 斯巴达算法 | ||||||
| sparta: | sparta: | ||||||
|   url: http://119.3.204.120:8040 |   url: http://119.3.204.120:8040 | ||||||
| @ -286,10 +332,14 @@ sparta: | |||||||
| id-card: | id-card: | ||||||
|   encrypt-key: 7ae260d150a14027d2238a1cf80a48ef |   encrypt-key: 7ae260d150a14027d2238a1cf80a48ef | ||||||
| recognizer: | recognizer: | ||||||
|   url: http://192.168.110.5:50070 |   url: http://192.168.110.5:50071 | ||||||
|  |  | ||||||
| qrCode: | qrCode: | ||||||
|   url: http://xny.yj-3d.com:7171 |   url: http://xny.yj-3d.com:7788 | ||||||
| # 无人机大图 | # 无人机大图 | ||||||
| drone: | drone: | ||||||
|   url: http://192.168.110.2:9512 |   url: http://192.168.110.2:9512 | ||||||
|  | # 聊天服务 | ||||||
|  | chat: | ||||||
|  |   server: | ||||||
|  |     port: 18088 | ||||||
|  | |||||||
| @ -1,3 +1,7 @@ | |||||||
|  | # 开发环境配置 | ||||||
|  | server: | ||||||
|  |   # 服务器的HTTP端口,默认为8080 | ||||||
|  |   port: 8899 | ||||||
| --- # 临时文件存储位置 避免临时文件被系统清理报错 | --- # 临时文件存储位置 避免临时文件被系统清理报错 | ||||||
| spring.servlet.multipart.location: /ruoyi/server/temp | spring.servlet.multipart.location: /ruoyi/server/temp | ||||||
|  |  | ||||||
| @ -35,6 +39,12 @@ snail-job: | |||||||
|  |  | ||||||
| --- # 数据源配置 | --- # 数据源配置 | ||||||
| spring: | spring: | ||||||
|  |   ai: | ||||||
|  |     dashscope: | ||||||
|  |       api-key: xxx | ||||||
|  |       chat: | ||||||
|  |         options: | ||||||
|  |           model: qwen-plus | ||||||
|   datasource: |   datasource: | ||||||
|     type: com.zaxxer.hikari.HikariDataSource |     type: com.zaxxer.hikari.HikariDataSource | ||||||
|     # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content |     # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content | ||||||
| @ -326,7 +336,7 @@ ys7: | |||||||
|   app-key: 3acf9f1a43dc4209841e0893003db0a2 |   app-key: 3acf9f1a43dc4209841e0893003db0a2 | ||||||
|   app-secret: 09e29c70ae1161fbc3ce2030fc09ba2e |   app-secret: 09e29c70ae1161fbc3ce2030fc09ba2e | ||||||
|   job: |   job: | ||||||
|     capture-enabled: false   # 控制是否启用萤石抓拍任务 |     capture-enabled: true   # 控制是否启用萤石抓拍任务 | ||||||
|     device-sync-enabled: true # 控制是否同步萤石设备 |     device-sync-enabled: true # 控制是否同步萤石设备 | ||||||
| # 斯巴达算法 | # 斯巴达算法 | ||||||
| sparta: | sparta: | ||||||
| @ -344,3 +354,7 @@ qrCode: | |||||||
| # 无人机大图 | # 无人机大图 | ||||||
| drone: | drone: | ||||||
|   url: http://192.168.110.2:9512 |   url: http://192.168.110.2:9512 | ||||||
|  | # 聊天服务 | ||||||
|  | chat: | ||||||
|  |   server: | ||||||
|  |     port: 19099 | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ captcha: | |||||||
| # 开发环境配置 | # 开发环境配置 | ||||||
| server: | server: | ||||||
|   # 服务器的HTTP端口,默认为8080 |   # 服务器的HTTP端口,默认为8080 | ||||||
|   port: 8899 |   #  port: 8899 | ||||||
|   servlet: |   servlet: | ||||||
|     # 应用的访问路径 |     # 应用的访问路径 | ||||||
|     context-path: / |     context-path: / | ||||||
| @ -106,6 +106,10 @@ sa-token: | |||||||
|   is-share: false |   is-share: false | ||||||
|   # jwt秘钥 |   # jwt秘钥 | ||||||
|   jwt-secret-key: abcdefghijklmnopqrstuvwxyz |   jwt-secret-key: abcdefghijklmnopqrstuvwxyz | ||||||
|  |   # token有效期,单位s 默认30天, -1代表永不过期 | ||||||
|  |   timeout: 2592000 | ||||||
|  |   # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 | ||||||
|  |   active-timeout: 86400 | ||||||
|  |  | ||||||
| # security配置 | # security配置 | ||||||
| security: | security: | ||||||
| @ -277,8 +281,8 @@ springdoc: | |||||||
|       packages-to-scan: org.dromara.gps |       packages-to-scan: org.dromara.gps | ||||||
|     - group: 24.招标模块 |     - group: 24.招标模块 | ||||||
|       packages-to-scan: org.dromara.tender |       packages-to-scan: org.dromara.tender | ||||||
| #    - group: 25.app版本模块 |     #    - group: 25.app版本模块 | ||||||
| #      packages-to-scan: org.dromara.app |     #      packages-to-scan: org.dromara.app | ||||||
|     - group: 25.数据迁移模块 |     - group: 25.数据迁移模块 | ||||||
|       packages-to-scan: org.dromara.transferData |       packages-to-scan: org.dromara.transferData | ||||||
|     - group: 26.netty消息模块 |     - group: 26.netty消息模块 | ||||||
| @ -300,6 +304,14 @@ xss: | |||||||
|     - /system/notice |     - /system/notice | ||||||
|     - /warm-flow/save-xml |     - /warm-flow/save-xml | ||||||
|     - /project/project |     - /project/project | ||||||
|  |     - /xzd/contractDetails/** | ||||||
|  |     - /xzd/contractChange/** | ||||||
|  |     - /comprehensive/csContractChange/** | ||||||
|  |     - /comprehensive/csContractInformation/** | ||||||
|  |     - /hetongbiangeng/** | ||||||
|  |     - /fenbaohetongbiangg/** | ||||||
|  |     - /fenbaohetongxinxi/** | ||||||
|  |     - /contractManagement/** | ||||||
|  |  | ||||||
| # 全局线程池相关配置 | # 全局线程池相关配置 | ||||||
| # 如使用JDK21请直接使用虚拟线程 不要开启此配置 | # 如使用JDK21请直接使用虚拟线程 不要开启此配置 | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								xinnengyuan/ruoyi-admin/src/main/resources/template/设计更改通知单.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								xinnengyuan/ruoyi-admin/src/main/resources/template/设计更改通知单.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								xinnengyuan/ruoyi-admin/src/main/resources/template/设计验证表.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								xinnengyuan/ruoyi-admin/src/main/resources/template/设计验证表.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -29,6 +29,8 @@ import org.dromara.manager.ys7manager.Ys7Constant; | |||||||
| import org.dromara.manager.ys7manager.Ys7Manager; | import org.dromara.manager.ys7manager.Ys7Manager; | ||||||
| import org.dromara.manager.ys7manager.vo.Ys7ResponseVo; | import org.dromara.manager.ys7manager.vo.Ys7ResponseVo; | ||||||
| import org.dromara.other.domain.OthYs7Device; | import org.dromara.other.domain.OthYs7Device; | ||||||
|  | import org.dromara.other.domain.dto.ys7deviceimg.OthYs7DeviceImgCreateByCapture; | ||||||
|  | import org.dromara.other.service.IOthYs7DeviceImgService; | ||||||
| import org.dromara.other.service.IOthYs7DeviceService; | import org.dromara.other.service.IOthYs7DeviceService; | ||||||
| import org.dromara.out.domain.OutConstructionValue; | import org.dromara.out.domain.OutConstructionValue; | ||||||
| import org.dromara.out.domain.OutConstructionValueRange; | import org.dromara.out.domain.OutConstructionValueRange; | ||||||
| @ -55,6 +57,8 @@ import java.time.LocalDate; | |||||||
| import java.time.temporal.TemporalAdjusters; | import java.time.temporal.TemporalAdjusters; | ||||||
| import java.util.*; | import java.util.*; | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
|  | import java.util.regex.Matcher; | ||||||
|  | import java.util.regex.Pattern; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -112,6 +116,9 @@ public class DemoTest { | |||||||
|     @Resource |     @Resource | ||||||
|     private IOthYs7DeviceService ys7DeviceService; |     private IOthYs7DeviceService ys7DeviceService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IOthYs7DeviceImgService ys7DeviceImgService; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private Ys7Manager ys7Manager; |     private Ys7Manager ys7Manager; | ||||||
|  |  | ||||||
| @ -547,4 +554,38 @@ public class DemoTest { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void capturePic() { | ||||||
|  |         List<String> urlList = List.of( | ||||||
|  |             "http://xny.yj-3d.com:9000/xinnengyuan-dev/2025/10/23/db8a379b456142459852b654f20d5f97.png", | ||||||
|  |             "http://xny.yj-3d.com:9000/xinnengyuan-dev/2025/10/23/913dbcf0f7244c8b878e84b5525bec4b.png", | ||||||
|  |             "http://xny.yj-3d.com:9000/xinnengyuan-dev/2025/10/23/2b904765f03f40b2ad0ddbf6ddeadb45.png" | ||||||
|  |         ); | ||||||
|  |         for (String url : urlList) { | ||||||
|  |             Pattern pattern = Pattern.compile(".*/device/img/([^/]+)/.*"); | ||||||
|  |             Matcher matcher = pattern.matcher(url); | ||||||
|  |             OthYs7Device ys7Device = ys7DeviceService.lambdaQuery() | ||||||
|  |                 .eq(OthYs7Device::getDeviceSerial, "GA1730672") | ||||||
|  |                 .last("limit 1") | ||||||
|  |                 .one(); | ||||||
|  |             if (ys7Device == null) { | ||||||
|  |                 throw new ServiceException("设备不存在", HttpStatus.ERROR); | ||||||
|  |             } | ||||||
|  |             String deviceSerial = ys7Device.getDeviceSerial(); | ||||||
|  |             // 如果没有预置位,则直接对默认通道抓图 | ||||||
|  |             OthYs7DeviceImgCreateByCapture img = new OthYs7DeviceImgCreateByCapture(); | ||||||
|  |             img.setProjectId(ys7Device.getProjectId()); | ||||||
|  |             img.setDeviceSerial(deviceSerial); | ||||||
|  |             img.setDeviceName(ys7Device.getDeviceName()); | ||||||
|  | //        String url = "http://xny.yj-3d.com:9000/xinnengyuan/ys7/device/img/GA1044315/2025-10-13_859fdfb7dde540608356f29cb9e3d63e.jpg"; | ||||||
|  | //            String url = "http://xny.yj-3d.com:9000/xinnengyuan/ys7/device/img/GA1044315/2025-10-12_2801707255b84004acb5fee2a75299b2.jpg"; | ||||||
|  |             img.setCreateTime(new Date()); | ||||||
|  |             img.setUrl(url); | ||||||
|  |             log.info("图片:{},识别中", url); | ||||||
|  |             ys7DeviceImgService.saveCapturePic(List.of(img)); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ public class RecognizerTest { | |||||||
|  |  | ||||||
|     @Test |     @Test | ||||||
|     void test() { |     void test() { | ||||||
|         RecognizeVo recognize = recognizerManager.recognize("http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png", List.of(RecognizerTypeEnum.SOLAR)); |         RecognizeVo recognize = recognizerManager.recognize("http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png", List.of(RecognizerTypeEnum.PANEL)); | ||||||
|         log.info("recognize: {}", recognize); |         log.info("recognize: {}", recognize); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,9 +1,17 @@ | |||||||
| package org.dromara.test; | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
|  | import org.dromara.common.core.utils.MapstructUtils; | ||||||
| import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | ||||||
| import org.dromara.safety.service.IHseViolationRecordService; | import org.dromara.safety.service.IHseViolationRecordService; | ||||||
|  | import org.dromara.system.domain.SysMenu; | ||||||
|  | import org.dromara.system.domain.vo.SysMenuVo; | ||||||
|  | import org.dromara.system.mapper.SysMenuMapper; | ||||||
|  | import org.dromara.system.service.ISysMenuService; | ||||||
|  | import org.hamcrest.core.Is; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
| import org.springframework.boot.test.context.SpringBootTest; | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| @ -20,6 +28,9 @@ public class ViolationRecordTest { | |||||||
|     @Resource |     @Resource | ||||||
|     private IHseViolationRecordService violationRecordService; |     private IHseViolationRecordService violationRecordService; | ||||||
|  |  | ||||||
|  |     @Autowired | ||||||
|  |     private SysMenuMapper sysMenuMapper; | ||||||
|  |  | ||||||
|     @Test |     @Test | ||||||
|     void test() { |     void test() { | ||||||
|         List<HseViolationRecordCreateDto> list = new ArrayList<>(); |         List<HseViolationRecordCreateDto> list = new ArrayList<>(); | ||||||
| @ -55,4 +66,26 @@ public class ViolationRecordTest { | |||||||
|         list.add(dto5); |         list.add(dto5); | ||||||
|         violationRecordService.insertByMonitor(list); |         violationRecordService.insertByMonitor(list); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void contextLoads() { | ||||||
|  |         SysMenuVo sysMenuVo = sysMenusByList(1972500768346673154L); | ||||||
|  |         System.out.println(sysMenuVo.toString()); | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SysMenuVo sysMenusByList(Long id) { | ||||||
|  |         SysMenuVo sysMenus = new SysMenuVo(); | ||||||
|  |         List<SysMenu> res = sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getParentId, id)); | ||||||
|  |         if (res != null && res.size() > 0 ) { | ||||||
|  |             sysMenus.setChildren(MapstructUtils.convert(res, SysMenuVo.class)); | ||||||
|  |             res.forEach(sysMenu -> { | ||||||
|  |                 sysMenusByList(sysMenu.getMenuId()); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         return sysMenus; | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,32 @@ | |||||||
|  | package org.dromara.common.core.domain.vo; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | public class XzdCustomerSupplierVos  implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 类型(1、供应商,2、客户) | ||||||
|  |      */ | ||||||
|  |     private String type; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 供应商-客户id | ||||||
|  |      */ | ||||||
|  |     private Long cSId; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdCsContractInformationService { | ||||||
|  |  | ||||||
|  |     String selectNameByIds(String ids); | ||||||
|  | } | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | import org.dromara.common.core.domain.vo.XzdCustomerSupplierVos; | ||||||
|  |  | ||||||
|  | public interface XzdCustomerSupplierService { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询供应商-客户中间 | ||||||
|  |      * | ||||||
|  |      * @param id 主键 | ||||||
|  |      * @return 供应商-客户中间 | ||||||
|  |      */ | ||||||
|  |     XzdCustomerSupplierVos queryByIdone(Long id); | ||||||
|  | } | ||||||
| @ -0,0 +1,8 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdCustomerinformationService { | ||||||
|  |  | ||||||
|  |     String selectNmaeByIds(String id); | ||||||
|  |  | ||||||
|  |     String selectNmaeById(Long id); | ||||||
|  | } | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdJsCgJungonService { | ||||||
|  |  | ||||||
|  |     String selectNameByIds(String ids); | ||||||
|  | } | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdProjectService { | ||||||
|  |  | ||||||
|  |     String selectNmaeByIds(String ids); | ||||||
|  | } | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdPurchaseContractInformationService { | ||||||
|  |     String selectNameByIds(String ids); | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdSupplierInfoService { | ||||||
|  |  | ||||||
|  |     String selectNmaeByIds(String ids); | ||||||
|  |  | ||||||
|  |     String selectNmaeById(Long id); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | package org.dromara.common.core.service; | ||||||
|  |  | ||||||
|  | public interface XzdSupplierOpenBankService { | ||||||
|  |  | ||||||
|  |     String selectNameByIds(String ids); | ||||||
|  | } | ||||||
| @ -37,4 +37,36 @@ public interface TransConstant { | |||||||
|      */ |      */ | ||||||
|     String PROJECT_ID_TO_NAME = "project_id_to_name"; |     String PROJECT_ID_TO_NAME = "project_id_to_name"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 客户id转名称 | ||||||
|  |      */ | ||||||
|  |     String XZD_KHXX_ID_TO_NAME = "khxx_id_to_name"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //    /** | ||||||
|  | //     * 供应商id转名称 | ||||||
|  | //     */ | ||||||
|  | //    String XZD_KHXX_ID_TO_NAME = "gysxx_id_to_name"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 新中大项目id转名称 | ||||||
|  |      */ | ||||||
|  |     String XZD_PROJECT_ID_TO_NAME = "xzd_project_id_to_name"; | ||||||
|  |     /** | ||||||
|  |      * 采购合同id转名称 | ||||||
|  |      */ | ||||||
|  |     String XZD_PURCHASE_CONTRACT_ID_TO_NAME = "xzd_purchase_contract_id_to_name"; | ||||||
|  |     /** | ||||||
|  |      * 综合服务合同id转名称 | ||||||
|  |      */ | ||||||
|  |     String XZD_CS_CONTRACT_INFORMATION_ID_TO_NAME = "xzd_cs_contract_information_id_to_name"; | ||||||
|  |     /** | ||||||
|  |      * 结算-采购合同竣工结算id转名称 | ||||||
|  |      */ | ||||||
|  |     String XZD_JS_CG_JUNGON_ID_TO_NAME = "xzd_js_cg_jungon_id_to_name"; | ||||||
|  |     /** | ||||||
|  |      * 新中大供应商信息-开户银行id转银行名称 | ||||||
|  |      */ | ||||||
|  |     String XZD_SUPPLIER_OPEN_BANK_ID_TO_NAME = "xzd_supplier_open_bank_id_to_name"; | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,26 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import org.dromara.common.core.service.XzdCsContractInformationService; | ||||||
|  | import org.dromara.common.core.service.XzdPurchaseContractInformationService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | @TranslationType(type = TransConstant.XZD_CS_CONTRACT_INFORMATION_ID_TO_NAME) | ||||||
|  | public class XzdCsContractInformationImpl implements TranslationInterface<String> { | ||||||
|  |  | ||||||
|  |     private final XzdCsContractInformationService xzdCsContractInformationService; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdCsContractInformationService.selectNameByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdCsContractInformationService.selectNameByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import org.dromara.common.core.service.XzdCustomerinformationService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | @TranslationType(type = TransConstant.XZD_KHXX_ID_TO_NAME) | ||||||
|  | public class XzdCustomerinformationImpl implements TranslationInterface<String> { | ||||||
|  |  | ||||||
|  |     private final XzdCustomerinformationService xzdCustomerinformationService; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdCustomerinformationService.selectNmaeByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdCustomerinformationService.selectNmaeByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import org.dromara.common.core.service.XzdJsCgJungonService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | @TranslationType(type = TransConstant.XZD_JS_CG_JUNGON_ID_TO_NAME) | ||||||
|  | public class XzdJsCgJungonImpl implements TranslationInterface<String> { | ||||||
|  |  | ||||||
|  |     private final XzdJsCgJungonService xzdJsCgJungonService; | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdJsCgJungonService.selectNameByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdJsCgJungonService.selectNameByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import org.dromara.common.core.service.XzdProjectService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | @TranslationType(type = TransConstant.XZD_PROJECT_ID_TO_NAME) | ||||||
|  | public class XzdProjectImpl implements TranslationInterface<String> { | ||||||
|  |     private final XzdProjectService xzdProjectService; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdProjectService.selectNmaeByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdProjectService.selectNmaeByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  |  | ||||||
|  | import org.dromara.common.core.service.XzdPurchaseContractInformationService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | @TranslationType(type = TransConstant.XZD_PURCHASE_CONTRACT_ID_TO_NAME) | ||||||
|  | public class XzdPurchaseContractInformationImpl implements TranslationInterface<String> { | ||||||
|  |  | ||||||
|  |     private final XzdPurchaseContractInformationService xzdCustomerinformationService; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdCustomerinformationService.selectNameByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdCustomerinformationService.selectNameByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,24 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import org.dromara.common.core.service.XzdSupplierInfoService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | //@TranslationType(type = TransConstant.XZD_KHXX_ID_TO_NAME) | ||||||
|  | public class XzdSupplierInfoImpl implements TranslationInterface<String> { | ||||||
|  |  | ||||||
|  |     private final XzdSupplierInfoService xzdSupplierInfoService; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdSupplierInfoService.selectNmaeByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdSupplierInfoService.selectNmaeByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package org.dromara.common.translation.core.impl; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import org.dromara.common.core.service.XzdSupplierOpenBankService; | ||||||
|  | import org.dromara.common.translation.annotation.TranslationType; | ||||||
|  | import org.dromara.common.translation.constant.TransConstant; | ||||||
|  | import org.dromara.common.translation.core.TranslationInterface; | ||||||
|  |  | ||||||
|  | @AllArgsConstructor | ||||||
|  | @TranslationType(type = TransConstant.XZD_SUPPLIER_OPEN_BANK_ID_TO_NAME) | ||||||
|  | public class XzdSupplierOpenBankImpl implements TranslationInterface<String> { | ||||||
|  |  | ||||||
|  |     private final XzdSupplierOpenBankService xzdSupplierOpenBankService; | ||||||
|  |     @Override | ||||||
|  |     public String translation(Object key, String other) { | ||||||
|  |         if (key instanceof String ids) { | ||||||
|  |             return xzdSupplierOpenBankService.selectNameByIds(ids); | ||||||
|  |         } else if (key instanceof Long id) { | ||||||
|  |             return xzdSupplierOpenBankService.selectNameByIds(id.toString()); | ||||||
|  |         } | ||||||
|  |         return null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -5,3 +5,10 @@ org.dromara.common.translation.core.impl.OssUrlTranslationImpl | |||||||
| org.dromara.common.translation.core.impl.UserNameTranslationImpl | org.dromara.common.translation.core.impl.UserNameTranslationImpl | ||||||
| org.dromara.common.translation.core.impl.NicknameTranslationImpl | org.dromara.common.translation.core.impl.NicknameTranslationImpl | ||||||
| org.dromara.common.translation.core.impl.ProjectNameTranslationImpl | org.dromara.common.translation.core.impl.ProjectNameTranslationImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdCustomerinformationImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdProjectImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdPurchaseContractInformationImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdSupplierInfoImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdJsCgJungonImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdCsContractInformationImpl | ||||||
|  | org.dromara.common.translation.core.impl.XzdSupplierOpenBankImpl | ||||||
|  | |||||||
| @ -15,16 +15,31 @@ | |||||||
|         system系统模块 |         system系统模块 | ||||||
|     </description> |     </description> | ||||||
|  |  | ||||||
|  |     <dependencyManagement> | ||||||
|  |         <dependencies> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.alibaba.cloud.ai</groupId> | ||||||
|  |                 <artifactId>spring-ai-alibaba-bom</artifactId> | ||||||
|  |                 <version>1.0.0.2</version> | ||||||
|  |                 <type>pom</type> | ||||||
|  |                 <scope>import</scope> | ||||||
|  |             </dependency> | ||||||
|  |         </dependencies> | ||||||
|  |     </dependencyManagement> | ||||||
|  |  | ||||||
|  |  | ||||||
|     <dependencies> |     <dependencies> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.alibaba.cloud.ai</groupId> | ||||||
|  |             <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> | ||||||
|  |         </dependency> | ||||||
|         <!-- Java WebSocket 标准API --> |         <!-- Java WebSocket 标准API --> | ||||||
| <!--        <dependency>--> |         <!--        <dependency>--> | ||||||
| <!--            <groupId>javax.websocket</groupId>--> |         <!--            <groupId>javax.websocket</groupId>--> | ||||||
| <!--            <artifactId>javax.websocket-api</artifactId>--> |         <!--            <artifactId>javax.websocket-api</artifactId>--> | ||||||
| <!--            <version>1.1</version>--> |         <!--            <version>1.1</version>--> | ||||||
| <!--            <scope>provided</scope>--> |         <!--            <scope>provided</scope>--> | ||||||
| <!--        </dependency>--> |         <!--        </dependency>--> | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.springframework.boot</groupId> |             <groupId>org.springframework.boot</groupId> | ||||||
|             <artifactId>spring-boot-starter-websocket</artifactId> |             <artifactId>spring-boot-starter-websocket</artifactId> | ||||||
| @ -36,18 +51,18 @@ | |||||||
|             </exclusions> |             </exclusions> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |  | ||||||
| <!--        <dependency>--> |         <!--        <dependency>--> | ||||||
| <!--            <groupId>com.drewnoakes</groupId>--> |         <!--            <groupId>com.drewnoakes</groupId>--> | ||||||
| <!--            <artifactId>metadata-extractor</artifactId>--> |         <!--            <artifactId>metadata-extractor</artifactId>--> | ||||||
| <!--            <version>2.18.0</version>--> |         <!--            <version>2.18.0</version>--> | ||||||
| <!--        </dependency>--> |         <!--        </dependency>--> | ||||||
|  |  | ||||||
|  |  | ||||||
| <!--        <dependency>--> |         <!--        <dependency>--> | ||||||
| <!--            <groupId>technology.tabula</groupId>--> |         <!--            <groupId>technology.tabula</groupId>--> | ||||||
| <!--            <artifactId>tabula</artifactId>--> |         <!--            <artifactId>tabula</artifactId>--> | ||||||
| <!--            <version>1.0.4</version>--> |         <!--            <version>1.0.4</version>--> | ||||||
| <!--        </dependency>--> |         <!--        </dependency>--> | ||||||
|  |  | ||||||
|  |  | ||||||
|         <!-- JSON解析(FastJSON) --> |         <!-- JSON解析(FastJSON) --> | ||||||
| @ -119,19 +134,18 @@ | |||||||
|         </dependency> |         </dependency> | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         <!--  支持中文字体  --> |         <!--  支持中文字体  --> | ||||||
| <!--        <dependency>--> |         <!--        <dependency>--> | ||||||
| <!--            <groupId>com.itextpdf</groupId>--> |         <!--            <groupId>com.itextpdf</groupId>--> | ||||||
| <!--            <artifactId>itext-asian</artifactId>--> |         <!--            <artifactId>itext-asian</artifactId>--> | ||||||
| <!--            <version>5.2.0</version>--> |         <!--            <version>5.2.0</version>--> | ||||||
| <!--        </dependency>--> |         <!--        </dependency>--> | ||||||
| <!--        <!–  iText  –>--> |         <!--        <!–  iText  –>--> | ||||||
| <!--        <dependency>--> |         <!--        <dependency>--> | ||||||
| <!--            <groupId>com.itextpdf</groupId>--> |         <!--            <groupId>com.itextpdf</groupId>--> | ||||||
| <!--            <artifactId>itextpdf</artifactId>--> |         <!--            <artifactId>itextpdf</artifactId>--> | ||||||
| <!--            <version>5.5.13.3</version>--> |         <!--            <version>5.5.13.3</version>--> | ||||||
| <!--        </dependency>--> |         <!--        </dependency>--> | ||||||
|         <!--  ZXing  --> |         <!--  ZXing  --> | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>com.google.zxing</groupId> |             <groupId>com.google.zxing</groupId> | ||||||
|  | |||||||
| @ -0,0 +1,51 @@ | |||||||
|  | package org.dromara.ai.controller; | ||||||
|  |  | ||||||
|  | import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
|  | import org.springframework.ai.chat.client.ChatClient; | ||||||
|  | import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  | import org.springframework.web.bind.annotation.GetMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestParam; | ||||||
|  | import org.springframework.web.bind.annotation.RestController; | ||||||
|  | import reactor.core.publisher.Flux; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025-10-23 11:32 | ||||||
|  |  */ | ||||||
|  | @Validated | ||||||
|  | @RestController | ||||||
|  | @RequestMapping("/ai") | ||||||
|  | public class AIController { | ||||||
|  |  | ||||||
|  |     private static final String DEFAULT_PROMPT = "你是一个博学的智能聊天助手,请根据用户提问回答!"; | ||||||
|  |  | ||||||
|  |     private final ChatClient dashScopeChatClient; | ||||||
|  |  | ||||||
|  |     public AIController(ChatClient.Builder chatClientBuilder) { | ||||||
|  |         this.dashScopeChatClient = chatClientBuilder | ||||||
|  |             .defaultSystem(DEFAULT_PROMPT) | ||||||
|  |             // 实现 Logger 的 Advisor | ||||||
|  |             .defaultAdvisors( | ||||||
|  |                 new SimpleLoggerAdvisor() | ||||||
|  |             ) | ||||||
|  |             // 设置 ChatClient 中 ChatModel 的 Options 参数 | ||||||
|  |             .defaultOptions( | ||||||
|  |                 DashScopeChatOptions.builder() | ||||||
|  |                     .withTopP(0.7) | ||||||
|  |                     .build() | ||||||
|  |             ) | ||||||
|  |             .build(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * ChatClient 流式调用 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/stream/chat") | ||||||
|  |     public Flux<String> streamChat(@RequestParam(value = "query", defaultValue = "你好,很高兴认识你,能简单介绍一下自己吗?") String query, HttpServletResponse response) { | ||||||
|  |         response.setCharacterEncoding("UTF-8"); | ||||||
|  |         return dashScopeChatClient.prompt(query).stream().content(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -9,10 +9,7 @@ import lombok.RequiredArgsConstructor; | |||||||
| import org.dromara.bigscreen.domain.dto.ProjectUpdateDto; | import org.dromara.bigscreen.domain.dto.ProjectUpdateDto; | ||||||
| import org.dromara.bigscreen.domain.dto.TanchuangInfoReq; | import org.dromara.bigscreen.domain.dto.TanchuangInfoReq; | ||||||
| import org.dromara.bigscreen.domain.dto.Ys7DeviceUpdateReq; | import org.dromara.bigscreen.domain.dto.Ys7DeviceUpdateReq; | ||||||
| import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo; | import org.dromara.bigscreen.domain.vo.*; | ||||||
| import org.dromara.bigscreen.domain.vo.ProjectLandVo; |  | ||||||
| import org.dromara.bigscreen.domain.vo.ProjectPeopleVo; |  | ||||||
| import org.dromara.bigscreen.domain.vo.ProjectSafetyInspectionVo; |  | ||||||
| import org.dromara.bigscreen.service.ProjectBigScreenService; | import org.dromara.bigscreen.service.ProjectBigScreenService; | ||||||
| import org.dromara.common.core.constant.HttpStatus; | import org.dromara.common.core.constant.HttpStatus; | ||||||
| import org.dromara.common.core.domain.R; | import org.dromara.common.core.domain.R; | ||||||
| @ -20,7 +17,12 @@ import org.dromara.common.core.exception.ServiceException; | |||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| import org.dromara.common.log.annotation.Log; | import org.dromara.common.log.annotation.Log; | ||||||
| import org.dromara.common.log.enums.BusinessType; | import org.dromara.common.log.enums.BusinessType; | ||||||
|  | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
|  | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.web.core.BaseController; | import org.dromara.common.web.core.BaseController; | ||||||
|  | import org.dromara.facility.domain.bo.FacRedLineBo; | ||||||
|  | import org.dromara.facility.domain.vo.redline.FacRedLineVo; | ||||||
|  | import org.dromara.facility.service.IFacRedLineService; | ||||||
| import org.dromara.gps.domain.bo.GpsEquipmentBo; | import org.dromara.gps.domain.bo.GpsEquipmentBo; | ||||||
| import org.dromara.land.domain.BusLandBlock; | import org.dromara.land.domain.BusLandBlock; | ||||||
| import org.dromara.land.domain.BusLandTransferLedger; | import org.dromara.land.domain.BusLandTransferLedger; | ||||||
| @ -33,6 +35,7 @@ import org.dromara.manager.ys7manager.Ys7Manager; | |||||||
| import org.dromara.other.domain.OthYs7Device; | import org.dromara.other.domain.OthYs7Device; | ||||||
| import org.dromara.other.service.IOthYs7DeviceService; | import org.dromara.other.service.IOthYs7DeviceService; | ||||||
| import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; | import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; | ||||||
|  | import org.dromara.project.domain.vo.project.BusProjectVo; | ||||||
| import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo; | import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo; | ||||||
| import org.dromara.project.service.IBusProjectNewsService; | import org.dromara.project.service.IBusProjectNewsService; | ||||||
| import org.dromara.project.service.IBusProjectService; | import org.dromara.project.service.IBusProjectService; | ||||||
| @ -86,6 +89,8 @@ public class ProjectBigScreenController extends BaseController { | |||||||
|  |  | ||||||
|     private final BusLandTransferLedgerSonServiceImpl busLandTransferLedgerSonService; |     private final BusLandTransferLedgerSonServiceImpl busLandTransferLedgerSonService; | ||||||
|  |  | ||||||
|  |     private final IFacRedLineService facRedLineService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询项目土地统计 |      * 查询项目土地统计 | ||||||
|      */ |      */ | ||||||
| @ -271,7 +276,7 @@ public class ProjectBigScreenController extends BaseController { | |||||||
|                 throw new ServiceException("更新云端萤石摄像头名称异常", HttpStatus.ERROR); |                 throw new ServiceException("更新云端萤石摄像头名称异常", HttpStatus.ERROR); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (req.getLatitude() != null  &&  req.getLongitude() != null) { |         if (req.getLatitude() != null && req.getLongitude() != null) { | ||||||
|             ys7Device.setLatitude(req.getLatitude()); |             ys7Device.setLatitude(req.getLatitude()); | ||||||
|             ys7Device.setLongitude(req.getLongitude()); |             ys7Device.setLongitude(req.getLongitude()); | ||||||
|         } |         } | ||||||
| @ -334,6 +339,22 @@ public class ProjectBigScreenController extends BaseController { | |||||||
|         return toAjax(projectService.updatePosition(dto)); |         return toAjax(projectService.updatePosition(dto)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取项目信息 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/getProjectInfo/{projectId}") | ||||||
|  |     public R<ProjectInfo> getProjectInfo(@NotNull(message = "主键不能为空") | ||||||
|  |                                          @PathVariable Long projectId) { | ||||||
|  |         BusProjectVo projectVo = projectService.queryById(projectId); | ||||||
|  |         ProjectInfo info = new ProjectInfo(); | ||||||
|  |         info.setLat(projectVo.getLat()); | ||||||
|  |         info.setLng(projectVo.getLng()); | ||||||
|  |         info.setPlan(projectVo.getPlan()); | ||||||
|  |         info.setPosition(projectVo.getPosition()); | ||||||
|  |         info.setProjectId(projectVo.getId().toString()); | ||||||
|  |         return R.ok(info); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询项目地域分散图 |      * 查询项目地域分散图 | ||||||
| @ -372,4 +393,12 @@ public class ProjectBigScreenController extends BaseController { | |||||||
|         return R.ok(projectBigScreenService.getInfoData(req)); |         return R.ok(projectBigScreenService.getInfoData(req)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询设施-红线列表 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/redLine/list") | ||||||
|  |     public TableDataInfo<FacRedLineVo> list(FacRedLineBo bo, PageQuery pageQuery) { | ||||||
|  |         return facRedLineService.queryPageList(bo, pageQuery); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,42 @@ | |||||||
|  | package org.dromara.bigscreen.domain.vo; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025-10-22 15:00 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class ProjectInfo implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = -8436930470114636496L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 纬度 | ||||||
|  |      */ | ||||||
|  |     private String lat; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 经度 | ||||||
|  |      */ | ||||||
|  |     private String lng; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 计划 | ||||||
|  |      */ | ||||||
|  |     private String plan; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 位置 | ||||||
|  |      */ | ||||||
|  |     private String position; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 项目id | ||||||
|  |      */ | ||||||
|  |     private String projectId; | ||||||
|  | } | ||||||
| @ -1,12 +1,21 @@ | |||||||
| package org.dromara.common.utils; | package org.dromara.common.utils; | ||||||
|  |  | ||||||
|  | import jakarta.annotation.Resource; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.dromara.common.core.utils.MessageUtils; | import org.dromara.common.core.utils.MessageUtils; | ||||||
| import org.dromara.common.sse.dto.SseMessageDto; | import org.dromara.common.sse.dto.SseMessageDto; | ||||||
| import org.dromara.common.sse.utils.SseMessageUtils; | import org.dromara.common.sse.utils.SseMessageUtils; | ||||||
|  | import org.dromara.contractor.domain.SubConstructionUser; | ||||||
|  | import org.dromara.mobileAttendanceMachine.DeviceMessageSender; | ||||||
|  | import org.dromara.mobileAttendanceMachine.KqjEntity; | ||||||
|  | import org.dromara.project.domain.BusAttendanceMachine; | ||||||
|  | import org.dromara.project.service.IBusAttendanceMachineService; | ||||||
| import org.dromara.sms4j.api.SmsBlend; | import org.dromara.sms4j.api.SmsBlend; | ||||||
| import org.dromara.sms4j.api.entity.SmsResponse; | import org.dromara.sms4j.api.entity.SmsResponse; | ||||||
| import org.dromara.sms4j.core.factory.SmsFactory; | import org.dromara.sms4j.core.factory.SmsFactory; | ||||||
|  | import org.dromara.system.domain.vo.SysOssVo; | ||||||
|  | import org.dromara.system.service.ISysOssService; | ||||||
|  | import org.springframework.context.annotation.Lazy; | ||||||
| import org.springframework.scheduling.annotation.Async; | import org.springframework.scheduling.annotation.Async; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
| @ -17,6 +26,16 @@ import java.util.List; | |||||||
| @Slf4j | @Slf4j | ||||||
| public class AsyncUtil { | public class AsyncUtil { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     @Lazy | ||||||
|  |     private DeviceMessageSender deviceMessageSender; | ||||||
|  |     @Resource | ||||||
|  |     @Lazy | ||||||
|  |     private ISysOssService ossService; | ||||||
|  |     @Resource | ||||||
|  |     @Lazy | ||||||
|  |     private IBusAttendanceMachineService attendanceMachineService; | ||||||
|  |  | ||||||
|     //发送短信 |     //发送短信 | ||||||
|     @Async |     @Async | ||||||
|     public void sendSms(List<String> mobileList, String config) { |     public void sendSms(List<String> mobileList, String config) { | ||||||
| @ -39,4 +58,27 @@ public class AsyncUtil { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     //下发考勤人员 | ||||||
|  |     @Async | ||||||
|  |     public void sendPersonnel(Long teamId, SubConstructionUser constructionUser) { | ||||||
|  |         SysOssVo byId = ossService.getById(Long.valueOf(constructionUser.getFacePic())); | ||||||
|  |         List<BusAttendanceMachine> list = attendanceMachineService.lambdaQuery().apply("FIND_IN_SET({0}, teams)", teamId).list(); | ||||||
|  |         for (BusAttendanceMachine machine : list) { | ||||||
|  |              deviceMessageSender.sendPersonnelInformation(machine.getSn(), constructionUser.getSysUserId().toString(), constructionUser.getUserName(), byId.getUrl()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //删除考勤人员 | ||||||
|  |     @Async | ||||||
|  |     public void deletePersonnel(SubConstructionUser constructionUser) { | ||||||
|  |         List<BusAttendanceMachine> list = attendanceMachineService.lambdaQuery().apply("FIND_IN_SET({0}, teams)", constructionUser.getTeamId()).list(); | ||||||
|  |         for (BusAttendanceMachine machine : list) { | ||||||
|  |             try { | ||||||
|  |                 deviceMessageSender.deleteUser(machine.getSn(), constructionUser.getSysUserId().toString()); | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 log.error("删除考勤人员异常", e); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -364,10 +364,11 @@ public class SubConstructionUserController extends BaseController { | |||||||
|                     if (user.getEntryDate() != null) { |                     if (user.getEntryDate() != null) { | ||||||
|                         vo.setEntryDate(DateUtils.formatDateTime(user.getEntryDate())); |                         vo.setEntryDate(DateUtils.formatDateTime(user.getEntryDate())); | ||||||
|                     } |                     } | ||||||
|  |                     //0男 1女 2未知 | ||||||
|                     String sex = vo.getSex(); |                     String sex = vo.getSex(); | ||||||
|                     if (sex != null && sex.equals("1")) { |                     if (sex != null && sex.equals("0")) { | ||||||
|                         vo.setSex("男"); |                         vo.setSex("男"); | ||||||
|                     } else if (sex != null && sex.equals("2")) { |                     } else if (sex != null && sex.equals("1")) { | ||||||
|                         vo.setSex("女"); |                         vo.setSex("女"); | ||||||
|                     } else { |                     } else { | ||||||
|                         vo.setSex("未知"); |                         vo.setSex("未知"); | ||||||
|  | |||||||
| @ -101,4 +101,7 @@ public class SubConstructionUserQueryReq implements Serializable { | |||||||
|      */ |      */ | ||||||
|     private String userId; |     private String userId; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private String phone; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -26,6 +26,7 @@ import org.dromara.common.oss.core.OssClient; | |||||||
| import org.dromara.common.oss.exception.OssException; | import org.dromara.common.oss.exception.OssException; | ||||||
| import org.dromara.common.oss.factory.OssFactory; | import org.dromara.common.oss.factory.OssFactory; | ||||||
| import org.dromara.common.satoken.utils.LoginHelper; | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.utils.AsyncUtil; | ||||||
| import org.dromara.common.utils.IdCardEncryptorUtil; | import org.dromara.common.utils.IdCardEncryptorUtil; | ||||||
| import org.dromara.common.utils.baiduUtil.BaiDuFace; | import org.dromara.common.utils.baiduUtil.BaiDuFace; | ||||||
| import org.dromara.common.utils.baiduUtil.BaiDuOCR; | import org.dromara.common.utils.baiduUtil.BaiDuOCR; | ||||||
| @ -46,6 +47,7 @@ import org.dromara.contractor.mapper.SubConstructionUserMapper; | |||||||
| import org.dromara.contractor.service.ISubConstructionUserFileService; | import org.dromara.contractor.service.ISubConstructionUserFileService; | ||||||
| import org.dromara.contractor.service.ISubConstructionUserService; | import org.dromara.contractor.service.ISubConstructionUserService; | ||||||
| import org.dromara.contractor.service.ISubContractorService; | import org.dromara.contractor.service.ISubContractorService; | ||||||
|  | import org.dromara.mobileAttendanceMachine.DeviceMessageSender; | ||||||
| import org.dromara.project.domain.*; | import org.dromara.project.domain.*; | ||||||
| import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum; | import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum; | ||||||
| import org.dromara.project.domain.enums.BusAttendanceCommuterEnum; | import org.dromara.project.domain.enums.BusAttendanceCommuterEnum; | ||||||
| @ -151,6 +153,11 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU | |||||||
|     @Resource |     @Resource | ||||||
|     private ISysRoleService roleService; |     private ISysRoleService roleService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private AsyncUtil asyncUtil; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询施工人员 |      * 查询施工人员 | ||||||
|      * |      * | ||||||
| @ -202,8 +209,10 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU | |||||||
|         LambdaQueryWrapper<SubConstructionUser> lqw = Wrappers.lambdaQuery(); |         LambdaQueryWrapper<SubConstructionUser> lqw = Wrappers.lambdaQuery(); | ||||||
|         // 从对象中取值 |         // 从对象中取值 | ||||||
|         String userName = req.getUserName(); |         String userName = req.getUserName(); | ||||||
|  |         String phone = req.getPhone(); | ||||||
|  |  | ||||||
|         // 模糊查询 |         // 模糊查询 | ||||||
|  |         lqw.like(StringUtils.isNotBlank(phone), SubConstructionUser::getPhone, phone); | ||||||
|         lqw.like(StringUtils.isNotBlank(userName), SubConstructionUser::getUserName, userName); |         lqw.like(StringUtils.isNotBlank(userName), SubConstructionUser::getUserName, userName); | ||||||
|         lqw.isNull(SubConstructionUser::getProjectId); |         lqw.isNull(SubConstructionUser::getProjectId); | ||||||
|         lqw.isNull(SubConstructionUser::getTeamId); |         lqw.isNull(SubConstructionUser::getTeamId); | ||||||
| @ -290,6 +299,8 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU | |||||||
|         //强退 |         //强退 | ||||||
|         roleService.cleanOnlineUser(Collections.singletonList(constructionUser.getSysUserId())); |         roleService.cleanOnlineUser(Collections.singletonList(constructionUser.getSysUserId())); | ||||||
|  |  | ||||||
|  |         asyncUtil.sendPersonnel(dto.getTeamId(), constructionUser); | ||||||
|  |  | ||||||
|         return i > 0; |         return i > 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,8 +1,15 @@ | |||||||
| package org.dromara.design.controller; | package org.dromara.design.controller; | ||||||
|  |  | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import com.alibaba.excel.EasyExcel; | ||||||
|  | import com.alibaba.excel.ExcelWriter; | ||||||
|  | import com.alibaba.excel.write.metadata.WriteSheet; | ||||||
|  | import com.alibaba.excel.write.metadata.style.WriteCellStyle; | ||||||
|  | import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.apache.poi.ss.usermodel.IndexedColors; | ||||||
| import org.dromara.common.core.domain.R; | import org.dromara.common.core.domain.R; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| import org.dromara.common.log.annotation.Log; | import org.dromara.common.log.annotation.Log; | ||||||
| @ -10,17 +17,17 @@ import org.dromara.common.log.enums.BusinessType; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.web.core.BaseController; | import org.dromara.common.web.core.BaseController; | ||||||
| import org.dromara.design.domain.bo.ImportExcelFileReq; | import org.dromara.design.domain.bo.*; | ||||||
| import org.dromara.design.domain.bo.ObtainAllVersionNumbersReq; |  | ||||||
| import org.dromara.design.domain.bo.CoryObtainTheListReq; |  | ||||||
| import org.dromara.design.domain.bo.SheetListReq; |  | ||||||
| import org.dromara.design.domain.vo.*; | import org.dromara.design.domain.vo.*; | ||||||
|  | import org.dromara.design.exportUtil.bill.*; | ||||||
| import org.dromara.design.service.IBusBillofquantitiesVersionsService; | import org.dromara.design.service.IBusBillofquantitiesVersionsService; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
| import java.util.List; | import java.io.IOException; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.util.*; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 工程量清单版本 |  * 工程量清单版本 | ||||||
| @ -103,6 +110,74 @@ public class BusBillofquantitiesVersionsController extends BaseController { | |||||||
|         return R.ok(busBillofquantitiesVersionsService.obtainAllClassification(bo)); |         return R.ok(busBillofquantitiesVersionsService.obtainAllClassification(bo)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 导出工程量清单版本列表 | ||||||
|  |      */ | ||||||
|  |     @Log(title = "工程量清单版本", businessType = BusinessType.EXPORT) | ||||||
|  |     @PostMapping("/export") | ||||||
|  |     public void export(String versions,Long projectId, HttpServletResponse response) throws IOException { | ||||||
|  |         Map<String, List<BillOfQuantitiesExport>> sheetDataMap = busBillofquantitiesVersionsService.export(versions,projectId); | ||||||
|  |  | ||||||
|  |         if (sheetDataMap.isEmpty()) { | ||||||
|  |             response.getWriter().write("无数据可导出"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 设置响应头(同上) | ||||||
|  |         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); | ||||||
|  |         response.setCharacterEncoding("UTF-8"); | ||||||
|  |         String fileName = URLEncoder.encode( "工程量清单", "UTF-8").replaceAll("\\+", "%20"); | ||||||
|  |         response.setHeader("Content-disposition", "attachment;filename*=UTF-8''" + fileName + ".xlsx"); | ||||||
|  |  | ||||||
|  |         // 3. 构建Excel写入器 | ||||||
|  |         ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build(); | ||||||
|  |         try { | ||||||
|  |             // 4. 遍历每个Sheet分组,创建Sheet并写入数据 | ||||||
|  |             for (Map.Entry<String, List<BillOfQuantitiesExport>> entry : sheetDataMap.entrySet()) { | ||||||
|  |                 String sheetName = entry.getKey(); | ||||||
|  |                 List<BillOfQuantitiesExport> dataList = entry.getValue(); | ||||||
|  |  | ||||||
|  |                 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); | ||||||
|  |                 // 背景设置为红色 | ||||||
|  |                 headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); | ||||||
|  |  | ||||||
|  |                 HorizontalCellStyleStrategy horizontalCellStyleStrategy = | ||||||
|  |                     new HorizontalCellStyleStrategy(headWriteCellStyle,  new WriteCellStyle()); | ||||||
|  |  | ||||||
|  |                 // 定义Sheet(同时注册标题处理器和冻结窗格处理器) | ||||||
|  |                 WriteSheet writeSheet = EasyExcel.writerSheet(sheetName) | ||||||
|  |                     .registerWriteHandler(new FreezePaneWriteHandler()) // 冻结前2行 | ||||||
|  |                     .registerWriteHandler(new ColumnWidthWriteHandler()) // 调整列宽 | ||||||
|  |                     .registerWriteHandler(new CustomRowStyleHandler()) // 新增:边框和标题样式 | ||||||
|  |                     .registerWriteHandler(horizontalCellStyleStrategy) | ||||||
|  |                     .head(head(sheetName)) | ||||||
|  |                     .build(); | ||||||
|  |  | ||||||
|  |                 // 写入数据 | ||||||
|  |                 excelWriter.write(dataList, writeSheet); | ||||||
|  |             } | ||||||
|  |         } finally { | ||||||
|  |             excelWriter.finish(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private List<List<String>> head(String sheetName) { | ||||||
|  |         List<List<String>> list = new ArrayList<List<String>>(); | ||||||
|  |         List<String> list1 = Arrays.asList(sheetName,"编号"); | ||||||
|  |         List<String> list2 = Arrays.asList(sheetName, "名称"); | ||||||
|  |         List<String> list3 = Arrays.asList(sheetName, "规格"); | ||||||
|  |         List<String> list4 = Arrays.asList(sheetName, "单位"); | ||||||
|  |         List<String> list5 = Arrays.asList(sheetName, "数量"); | ||||||
|  |         List<String> list6 = Arrays.asList(sheetName, "备注"); | ||||||
|  |         list.add(list1); | ||||||
|  |         list.add(list2); | ||||||
|  |         list.add(list3); | ||||||
|  |         list.add(list4); | ||||||
|  |         list.add(list5); | ||||||
|  |         list.add(list6); | ||||||
|  |         return list; | ||||||
|  |     } | ||||||
|  |  | ||||||
| //    /** | //    /** | ||||||
| //     * 导入物资设备清单 | //     * 导入物资设备清单 | ||||||
|  | |||||||
| @ -1,17 +1,40 @@ | |||||||
| package org.dromara.design.controller; | package org.dromara.design.controller; | ||||||
|  |  | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.HashMap; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.util.StrUtil; | ||||||
|  | import com.deepoove.poi.XWPFTemplate; | ||||||
|  | import com.deepoove.poi.config.Configure; | ||||||
|  | import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.*; | import jakarta.validation.constraints.*; | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import org.dromara.design.domain.BusDrawingreviewReceipts; | ||||||
|  | import org.dromara.design.domain.DesCollectFile; | ||||||
|  | import org.dromara.design.domain.DesDesignChange; | ||||||
| import org.dromara.design.domain.bo.DesUserBo; | import org.dromara.design.domain.bo.DesUserBo; | ||||||
|  | import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto; | ||||||
|  | import org.dromara.design.domain.vo.DesCollectFileWordVo; | ||||||
| import org.dromara.design.domain.vo.DesUserVo; | import org.dromara.design.domain.vo.DesUserVo; | ||||||
|  | import org.dromara.design.domain.vo.designchange.DesDesignChangeVo; | ||||||
|  | import org.dromara.design.service.IDesDesignChangeService; | ||||||
| import org.dromara.design.service.IDesUserService; | import org.dromara.design.service.IDesUserService; | ||||||
|  | import org.dromara.project.domain.BusProject; | ||||||
| import org.dromara.project.domain.vo.project.BusSubProjectVo; | import org.dromara.project.domain.vo.project.BusSubProjectVo; | ||||||
| import org.dromara.project.service.IBusProjectService; | import org.dromara.project.service.IBusProjectService; | ||||||
|  | import org.dromara.system.service.ISysDictDataService; | ||||||
|  | import org.dromara.system.service.ISysUserService; | ||||||
|  | import org.springframework.core.io.ClassPathResource; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| @ -44,6 +67,12 @@ public class BusDrawingreviewReceiptsController extends BaseController { | |||||||
|  |  | ||||||
|     private final IDesUserService desUserService; |     private final IDesUserService desUserService; | ||||||
|  |  | ||||||
|  |     private final IDesDesignChangeService desDesignChangeService; | ||||||
|  |  | ||||||
|  |     private final ISysDictDataService dictDataService; | ||||||
|  |  | ||||||
|  |     private final ISysUserService userService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询设计-图纸评审验证列表 |      * 查询设计-图纸评审验证列表 | ||||||
|      */ |      */ | ||||||
| @ -132,4 +161,85 @@ public class BusDrawingreviewReceiptsController extends BaseController { | |||||||
|         return R.ok(desUserService.queryList(bo)); |         return R.ok(desUserService.queryList(bo)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private static final String TEMPLATE_PATH = "template/设计验证表.docx"; | ||||||
|  |     @PostMapping("/downloadWord") | ||||||
|  |     public void generateDesignLeaderDoc(Long id, HttpServletResponse response) { | ||||||
|  |         OutputStream outputStream = null; | ||||||
|  |         try { | ||||||
|  |             // 1. 调用Service生成目标模板的Word字节流 | ||||||
|  |             byte[] docBytes = generateDocBytes(id); | ||||||
|  |  | ||||||
|  |             // 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型) | ||||||
|  |             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型 | ||||||
|  |             // 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”(此处用projectId拼接,真实场景可从数据中获取项目名) | ||||||
|  |             String downloadFileName = URLEncoder.encode( | ||||||
|  |                 "设计验证表.docx", | ||||||
|  |                 "UTF-8" | ||||||
|  |             ); | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName); | ||||||
|  |             response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验) | ||||||
|  |  | ||||||
|  |             // 3. 将Word字节流写入响应 | ||||||
|  |             outputStream = response.getOutputStream(); | ||||||
|  |             outputStream.write(docBytes); | ||||||
|  |             outputStream.flush(); | ||||||
|  |  | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             // 异常处理:返回500错误状态码 | ||||||
|  |             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | ||||||
|  |         } finally { | ||||||
|  |             // 关闭流,避免资源泄漏 | ||||||
|  |             if (outputStream != null) { | ||||||
|  |                 try { | ||||||
|  |                     outputStream.close(); | ||||||
|  |                 } catch (Exception e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public byte[] generateDocBytes(Long id) throws Exception { | ||||||
|  |         // -------------------------- 步骤1:按projectId查询项目数据(模拟真实业务) -------------------------- | ||||||
|  |         // 实际场景替换为数据库查询(如调用DAO获取项目名称、负责人等) | ||||||
|  |         DesDesignChangeVo desDesignChangeVo = desDesignChangeService.queryById(id); | ||||||
|  |         BusDrawingreviewReceipts receipts = busDrawingreviewReceiptsService.lambdaQuery() | ||||||
|  |             .eq(BusDrawingreviewReceipts::getDrawingreviewId, id) | ||||||
|  |             .last("limit 1") | ||||||
|  |             .one(); | ||||||
|  |         DesDesignExtendDetailDto extendDetail = desDesignChangeVo.getExtendDetail(); | ||||||
|  |         String s = dictDataService.selectDictLabel("des_user_major", receipts.getProfessional()); | ||||||
|  |         String designerName = null; | ||||||
|  |         if(StrUtil.isNotBlank(receipts.getDesigner())){ | ||||||
|  |             Long userId = Long.parseLong(receipts.getDesigner()); | ||||||
|  |             designerName= userService.queryNameById(userId); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Map<String, Object> placeholderData = new HashMap<>(); | ||||||
|  |         placeholderData.put("projectName", receipts.getProjectName()); | ||||||
|  |         placeholderData.put("subName",extendDetail.getSubName()); | ||||||
|  |         placeholderData.put("stage", receipts.getStage()); | ||||||
|  |         placeholderData.put("professionalName", s); | ||||||
|  |         placeholderData.put("volume", receipts.getVolume()); | ||||||
|  |         placeholderData.put("designerName", designerName); | ||||||
|  |         placeholderData.put("verificationOpinion", receipts.getVerificationOpinion()); | ||||||
|  |         placeholderData.put("executionOpinion", receipts.getExecutionOpinion()); | ||||||
|  |         // -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 -------------------------- | ||||||
|  |         // 读取resources下的“设计项目负责人任命通知单.docx”模板 | ||||||
|  |         ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH); | ||||||
|  |         try (InputStream templateIs = templateResource.getInputStream(); | ||||||
|  |              ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { | ||||||
|  |  | ||||||
|  |             XWPFTemplate template = XWPFTemplate.compile(templateIs).render(placeholderData); | ||||||
|  |  | ||||||
|  |             // -------------------------- 步骤3:将生成的文档写入字节流 -------------------------- | ||||||
|  |             template.write(outputStream); | ||||||
|  |             template.close(); // 关闭模板资源 | ||||||
|  |             return outputStream.toByteArray(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,14 +1,31 @@ | |||||||
| package org.dromara.design.controller; | package org.dromara.design.controller; | ||||||
|  |  | ||||||
| import java.util.List; | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.util.*; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  | import com.deepoove.poi.XWPFTemplate; | ||||||
|  | import com.deepoove.poi.config.Configure; | ||||||
|  | import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.*; | import jakarta.validation.constraints.*; | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import org.dromara.design.domain.DesCollectFile; | ||||||
| import org.dromara.design.domain.bo.DesCollectFileBo; | import org.dromara.design.domain.bo.DesCollectFileBo; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
|  | import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto; | ||||||
| import org.dromara.design.domain.vo.DesCollectFileVo; | import org.dromara.design.domain.vo.DesCollectFileVo; | ||||||
|  | import org.dromara.design.domain.vo.DesCollectFileWordVo; | ||||||
|  | import org.dromara.design.domain.vo.designchange.DesDesignChangeVo; | ||||||
| import org.dromara.design.service.IDesCollectFileService; | import org.dromara.design.service.IDesCollectFileService; | ||||||
|  | import org.dromara.project.domain.BusProject; | ||||||
|  | import org.dromara.project.service.IBusProjectService; | ||||||
|  | import org.springframework.core.io.ClassPathResource; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| @ -38,6 +55,8 @@ public class DesCollectFileController extends BaseController { | |||||||
|  |  | ||||||
|     private final IDesCollectFileService desCollectFileService; |     private final IDesCollectFileService desCollectFileService; | ||||||
|  |  | ||||||
|  |     private final IBusProjectService projectService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询收资文件列表 |      * 查询收资文件列表 | ||||||
|      */ |      */ | ||||||
| @ -105,7 +124,6 @@ public class DesCollectFileController extends BaseController { | |||||||
|         return toAjax(desCollectFileService.deleteWithValidByIds(List.of(ids), true)); |         return toAjax(desCollectFileService.deleteWithValidByIds(List.of(ids), true)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 上传资料文件 |      * 上传资料文件 | ||||||
|      */ |      */ | ||||||
| @ -117,4 +135,93 @@ public class DesCollectFileController extends BaseController { | |||||||
|                            @NotNull(message = "请先选择项目")Long projectId) { |                            @NotNull(message = "请先选择项目")Long projectId) { | ||||||
|         return toAjax(desCollectFileService.addFile(file, catalogueId, projectId)); |         return toAjax(desCollectFileService.addFile(file, catalogueId, projectId)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @PostMapping("/exportZip") | ||||||
|  |     public void exportZip(ExportDto dto, HttpServletResponse response) throws Exception { | ||||||
|  |         desCollectFileService.exportAsZip(dto, response); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static final String TEMPLATE_PATH = "template/设计输入资料清单及评审表.docx"; | ||||||
|  |     @PostMapping("/downloadWord") | ||||||
|  |     public void generateDesignLeaderDoc(Long projectId, HttpServletResponse response) { | ||||||
|  |         OutputStream outputStream = null; | ||||||
|  |         try { | ||||||
|  |             // 1. 调用Service生成目标模板的Word字节流 | ||||||
|  |             byte[] docBytes = generateDocBytes(projectId); | ||||||
|  |  | ||||||
|  |             // 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型) | ||||||
|  |             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型 | ||||||
|  |             // 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”(此处用projectId拼接,真实场景可从数据中获取项目名) | ||||||
|  |             String downloadFileName = URLEncoder.encode( | ||||||
|  |                 "设计输入资料清单及评审表.docx", | ||||||
|  |                 "UTF-8" | ||||||
|  |             ); | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName); | ||||||
|  |             response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验) | ||||||
|  |  | ||||||
|  |             // 3. 将Word字节流写入响应 | ||||||
|  |             outputStream = response.getOutputStream(); | ||||||
|  |             outputStream.write(docBytes); | ||||||
|  |             outputStream.flush(); | ||||||
|  |  | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             // 异常处理:返回500错误状态码 | ||||||
|  |             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | ||||||
|  |         } finally { | ||||||
|  |             // 关闭流,避免资源泄漏 | ||||||
|  |             if (outputStream != null) { | ||||||
|  |                 try { | ||||||
|  |                     outputStream.close(); | ||||||
|  |                 } catch (Exception e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public byte[] generateDocBytes(Long projectId) throws Exception { | ||||||
|  |         // -------------------------- 步骤1:按projectId查询项目数据(模拟真实业务) -------------------------- | ||||||
|  |         // 实际场景替换为数据库查询(如调用DAO获取项目名称、负责人等) | ||||||
|  |         List<DesCollectFile> list = desCollectFileService.lambdaQuery() | ||||||
|  |             .eq(DesCollectFile::getProjectId, projectId).list(); | ||||||
|  |  | ||||||
|  |         List<DesCollectFileWordVo> files = new ArrayList<>(); | ||||||
|  |         int i = 1; | ||||||
|  |         for (DesCollectFile desCollectFile : list) { | ||||||
|  |             DesCollectFileWordVo desCollectFileWordVo = new DesCollectFileWordVo(); | ||||||
|  |             desCollectFileWordVo.setNum(i); | ||||||
|  |             i++; | ||||||
|  |             desCollectFileWordVo.setFileName(desCollectFile.getFileName()); | ||||||
|  |             files.add(desCollectFileWordVo); | ||||||
|  |          } | ||||||
|  |  | ||||||
|  |         BusProject project = projectService.getById(projectId); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         Map<String, Object> placeholderData = new HashMap<>(); | ||||||
|  |         placeholderData.put("projectName", project.getProjectName()); | ||||||
|  |         placeholderData.put("files",files); | ||||||
|  |         // -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 -------------------------- | ||||||
|  |         // 读取resources下的“设计项目负责人任命通知单.docx”模板 | ||||||
|  |         ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH); | ||||||
|  |         try (InputStream templateIs = templateResource.getInputStream(); | ||||||
|  |              ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { | ||||||
|  |  | ||||||
|  |             LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); | ||||||
|  |  | ||||||
|  |             Configure config = Configure.builder() | ||||||
|  |                 .bind("files", policy).build(); | ||||||
|  |  | ||||||
|  |             XWPFTemplate template = XWPFTemplate.compile(templateIs, config).render(placeholderData); | ||||||
|  |  | ||||||
|  |             // -------------------------- 步骤3:将生成的文档写入字节流 -------------------------- | ||||||
|  |             template.write(outputStream); | ||||||
|  |             template.close(); // 关闭模板资源 | ||||||
|  |             return outputStream.toByteArray(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,10 +2,13 @@ package org.dromara.design.controller; | |||||||
|  |  | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.NotEmpty; | import jakarta.validation.constraints.NotEmpty; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
|  |  | ||||||
|  | import org.apache.poi.xwpf.usermodel.*; | ||||||
| import org.dromara.common.core.domain.R; | import org.dromara.common.core.domain.R; | ||||||
| import org.dromara.common.excel.utils.ExcelUtil; | import org.dromara.common.excel.utils.ExcelUtil; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| @ -13,17 +16,37 @@ import org.dromara.common.log.annotation.Log; | |||||||
| import org.dromara.common.log.enums.BusinessType; | import org.dromara.common.log.enums.BusinessType; | ||||||
| import org.dromara.common.web.core.BaseController; | import org.dromara.common.web.core.BaseController; | ||||||
| import org.dromara.design.domain.DesConstructionSchedulePlan; | import org.dromara.design.domain.DesConstructionSchedulePlan; | ||||||
|  | import org.dromara.design.domain.DesUser; | ||||||
| import org.dromara.design.domain.dto.constructionscheduleplan.*; | import org.dromara.design.domain.dto.constructionscheduleplan.*; | ||||||
| import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo; | import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo; | ||||||
|  | import org.dromara.design.exportUtil.plan.AttachmentPersonnel; | ||||||
| import org.dromara.design.service.IDesConstructionSchedulePlanService; | import org.dromara.design.service.IDesConstructionSchedulePlanService; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import org.dromara.design.service.IDesUserService; | ||||||
|  | import org.dromara.system.domain.vo.SysDictDataVo; | ||||||
|  | import org.dromara.system.service.ISysDictDataService; | ||||||
|  | import org.dromara.system.service.ISysDictTypeService; | ||||||
|  | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr; | ||||||
|  | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; | ||||||
|  | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; | ||||||
|  | import org.springframework.core.io.ClassPathResource; | ||||||
|  | import org.springframework.http.HttpStatus; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
|  | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
| import java.util.List; | import java.io.*; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.util.*; | ||||||
|  | import java.util.regex.Matcher; | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  | import org.apache.poi.poifs.filesystem.POIFSFileSystem; | ||||||
| /** | /** | ||||||
|  * 设计计划 |  * 设计计划 | ||||||
|  * |  * | ||||||
| @ -37,7 +60,10 @@ public class DesConstructionSchedulePlanController extends BaseController { | |||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private IDesConstructionSchedulePlanService desConstructionSchedulePlanService; |     private IDesConstructionSchedulePlanService desConstructionSchedulePlanService; | ||||||
|  |     @Resource | ||||||
|  |     private  IDesUserService desUserService; | ||||||
|  |     @Resource | ||||||
|  |     private ISysDictTypeService dictTypeService; | ||||||
|     /** |     /** | ||||||
|      * 查询设计计划列表 |      * 查询设计计划列表 | ||||||
|      */ |      */ | ||||||
| @ -143,4 +169,174 @@ public class DesConstructionSchedulePlanController extends BaseController { | |||||||
|                           @PathVariable Long[] ids) { |                           @PathVariable Long[] ids) { | ||||||
|         return toAjax(desConstructionSchedulePlanService.deleteByIds(List.of(ids))); |         return toAjax(desConstructionSchedulePlanService.deleteByIds(List.of(ids))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @PostMapping("/exportSchedule") | ||||||
|  |     public void exportSchedule(HttpServletResponse response, Long projectId) throws IOException { | ||||||
|  |         desConstructionSchedulePlanService.exportSchedule(response,projectId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static final String TEMPLATE_RESOURCE_PATH = "template/CCCET-JL-CX-25设计计划表.docx"; | ||||||
|  |     // -------------------------- 2. 核心接口:修复单元格清空逻辑与数据填充 -------------------------- | ||||||
|  |     @PostMapping("/downloadWord") | ||||||
|  |     public void fillCccetTemplate(Long projectId, HttpServletResponse response) { | ||||||
|  |         // 1. 基础参数校验(避免空数据) | ||||||
|  |  | ||||||
|  |         // 2. 读取resource中的模板+填充数据 | ||||||
|  |         try ( | ||||||
|  |             // 关键:通过ClassPathResource读取resource/template下的模板 | ||||||
|  |             InputStream templateIs = new ClassPathResource(TEMPLATE_RESOURCE_PATH).getInputStream(); | ||||||
|  |             XWPFDocument doc = new XWPFDocument(templateIs); // 加载模板 | ||||||
|  |             OutputStream out = response.getOutputStream()    // 响应流 | ||||||
|  |         ) { | ||||||
|  |             // -------------------------- | ||||||
|  |             // 步骤1:填充第1页-主信息表(索引0,固定6列) | ||||||
|  |             // -------------------------- | ||||||
|  | //            XWPFTable mainTable = doc.getTables().get(0); | ||||||
|  | //            // 工程名称(第1行第0列) | ||||||
|  | //            if (mainTable.getRows().size() > 1 && mainTable.getRow(1).getCell(0) != null) { | ||||||
|  | //                mainTable.getRow(1).getCell(0).setText(request.getProjectName() == null ? "" : request.getProjectName()); | ||||||
|  | //            } | ||||||
|  | //            // 工程号(第1行第1列) | ||||||
|  | //            if (mainTable.getRows().size() > 1 && mainTable.getRow(1).getCell(1) != null) { | ||||||
|  | //                mainTable.getRow(1).getCell(1).setText(request.getProjectNo()); | ||||||
|  | //            } | ||||||
|  | //            // 编制日期(第2行第3列) | ||||||
|  | //            if (mainTable.getRows().size() > 2 && mainTable.getRow(2).getCell(3) != null) { | ||||||
|  | //                mainTable.getRow(2).getCell(3).setText(request.getCompileDate() == null ? "" : request.getCompileDate()); | ||||||
|  | //            } | ||||||
|  | //            // 编制人(第3行第0列) | ||||||
|  | //            if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(0) != null) { | ||||||
|  | //                mainTable.getRow(3).getCell(0).setText(request.getCompiler() == null ? "" : request.getCompiler()); | ||||||
|  | //            } | ||||||
|  | //            // 批准人(第3行第2列) | ||||||
|  | //            if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(2) != null) { | ||||||
|  | //                mainTable.getRow(3).getCell(2).setText(request.getApprover() == null ? "" : request.getApprover()); | ||||||
|  | //            } | ||||||
|  | //            // 设计阶段(第3行第4列) | ||||||
|  | //            if (mainTable.getRows().size() > 3 && mainTable.getRow(3).getCell(4) != null) { | ||||||
|  | //                mainTable.getRow(3).getCell(4).setText(request.getDesignStage() == null ? "" : request.getDesignStage()); | ||||||
|  | //            } | ||||||
|  | //            // 设计规模(第4行第0列) | ||||||
|  | //            if (mainTable.getRows().size() > 4 && mainTable.getRow(4).getCell(0) != null) { | ||||||
|  | //                mainTable.getRow(4).getCell(0).setText(request.getDesignScale() == null ? "" : request.getDesignScale()); | ||||||
|  | //            } | ||||||
|  |  | ||||||
|  |             // -------------------------- | ||||||
|  |             // 步骤2:填充第3页-附件1人员配置表(索引2,固定11列) | ||||||
|  |             // -------------------------- | ||||||
|  |             XWPFTable staffTable = doc.getTables().get(2); | ||||||
|  |             // 删除模板中附件1的空数据行(保留第0行表头) | ||||||
|  |             while (staffTable.getRows().size() > 2) { | ||||||
|  |                 staffTable.removeRow(1); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             List<AttachmentPersonnel> list = getPersonnelDataByProjectId(projectId); | ||||||
|  |             for (AttachmentPersonnel staff : list) { | ||||||
|  |                 XWPFTableRow newRow = staffTable.createRow(); | ||||||
|  |                 // 补全11列(避免POI默认列数不足导致null) | ||||||
|  |                 while (newRow.getTableCells().size() < 11) { | ||||||
|  |                     newRow.createCell(); | ||||||
|  |                 } | ||||||
|  |                 // 按附件1列顺序填充 | ||||||
|  |                 newRow.getCell(0).setText(staff.getProfessional() == null ? "" : staff.getProfessional()); | ||||||
|  |                 newRow.getCell(1).setText(staff.getLeaderName() == null ? "" : staff.getLeaderName()); | ||||||
|  |                 newRow.getCell(2).setText(staff.getLeaderTitle() == null ? "" : staff.getLeaderTitle()); | ||||||
|  |                 newRow.getCell(3).setText(staff.getDesignerName() == null ? "" : staff.getDesignerName()); | ||||||
|  |                 newRow.getCell(4).setText(staff.getDesignerTitle() == null ? "" : staff.getDesignerTitle()); | ||||||
|  |                 newRow.getCell(5).setText(staff.getReviewerName() == null ? "" : staff.getReviewerName()); | ||||||
|  |                 newRow.getCell(6).setText(staff.getReviewerTitle() == null ? "" : staff.getReviewerTitle()); | ||||||
|  |                 newRow.getCell(7).setText(staff.getCheckerName() == null ? "" : staff.getCheckerName()); | ||||||
|  |                 newRow.getCell(8).setText(staff.getCheckerTitle() == null ? "" : staff.getCheckerTitle()); | ||||||
|  |                 newRow.getCell(9).setText(staff.getApproverName() == null ? "" : staff.getApproverName()); | ||||||
|  |                 newRow.getCell(10).setText(staff.getApproverTitle() == null ? "" : staff.getApproverTitle()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // -------------------------- | ||||||
|  |             // 步骤3:设置响应头(触发前端下载) | ||||||
|  |             // -------------------------- | ||||||
|  |             response.setContentType("application/octet-stream"); | ||||||
|  |             // 文件名:填充后_工程号_CCCET-JL-CX-25设计计划表.docx | ||||||
|  |             String fileName = "CCCET-JL-CX-25设计计划表.docx"; | ||||||
|  |             response.setHeader("Content-Disposition", | ||||||
|  |                 "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); | ||||||
|  |             response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 允许前端获取文件名 | ||||||
|  |  | ||||||
|  |             // -------------------------- | ||||||
|  |             // 步骤4:写出文件到前端 | ||||||
|  |             // -------------------------- | ||||||
|  |             doc.write(out); | ||||||
|  |             out.flush(); | ||||||
|  |  | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             // 异常封装(前端可捕获具体错误) | ||||||
|  |             throw new RuntimeException("CCCET-JL-CX-25模板填充失败:" + e.getMessage()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 根据projectId获取数据(仅针对CCCET-JL-CX-25设计计划表.docx附件1) | ||||||
|  |      */ | ||||||
|  |     private List<AttachmentPersonnel> getPersonnelDataByProjectId(Long projectId) { | ||||||
|  |         // 模拟数据库查询(实际项目替换为真实Service调用) | ||||||
|  |         List<DesUser> userList = desUserService.list(Wrappers.<DesUser>lambdaQuery() | ||||||
|  |             .eq(DesUser::getProjectId, projectId) | ||||||
|  |         ); | ||||||
|  |         if (userList.isEmpty()) { | ||||||
|  |             return Collections.emptyList(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 专业字典映射(编码→名称) | ||||||
|  |         List<SysDictDataVo> majorDict = dictTypeService.selectDictDataByType("des_user_major"); | ||||||
|  |         Map<String, String> majorMap = majorDict.stream() | ||||||
|  |             .collect(Collectors.toMap(SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel)); | ||||||
|  |  | ||||||
|  |         // 按角色分组(1-专业负责人,2-设计人,3-校审人,4-审定人,5-审核人) | ||||||
|  |         DesUser leader = userList.stream().filter(u -> "1".equals(u.getUserType())).findFirst().orElse(null); | ||||||
|  |         Map<String, List<DesUser>> designerMap = userList.stream() | ||||||
|  |             .filter(u -> "2".equals(u.getUserType())) | ||||||
|  |             .collect(Collectors.groupingBy(DesUser::getUserMajor)); | ||||||
|  |         Map<String, List<DesUser>> reviewerMap = userList.stream() | ||||||
|  |             .filter(u -> "3".equals(u.getUserType())) | ||||||
|  |             .collect(Collectors.groupingBy(DesUser::getUserMajor)); | ||||||
|  |         Map<String, List<DesUser>> checkerMap = userList.stream() | ||||||
|  |             .filter(u -> "5".equals(u.getUserType())) | ||||||
|  |             .collect(Collectors.groupingBy(DesUser::getUserMajor)); | ||||||
|  |         Map<String, List<DesUser>> approverMap = userList.stream() | ||||||
|  |             .filter(u -> "4".equals(u.getUserType())) | ||||||
|  |             .collect(Collectors.groupingBy(DesUser::getUserMajor)); | ||||||
|  |  | ||||||
|  |         // 构建附件1数据(一个专业一行,避免重复) | ||||||
|  |         List<AttachmentPersonnel> dataList = new ArrayList<>(); | ||||||
|  |         for (Map.Entry<String, List<DesUser>> entry : designerMap.entrySet()) { | ||||||
|  |             String majorCode = entry.getKey(); | ||||||
|  |             String majorName = majorMap.getOrDefault(majorCode, majorCode); | ||||||
|  |             List<DesUser> designers = entry.getValue(); | ||||||
|  |  | ||||||
|  |             // 获取对应专业的其他角色 | ||||||
|  |             DesUser reviewer = reviewerMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null); | ||||||
|  |             DesUser checker = checkerMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null); | ||||||
|  |             DesUser approver = approverMap.getOrDefault(majorCode, Collections.emptyList()).stream().findFirst().orElse(null); | ||||||
|  |             // 封装数据(多个设计人用顿号分隔) | ||||||
|  |             AttachmentPersonnel data = new AttachmentPersonnel(); | ||||||
|  |             data.setProfessional(majorName); | ||||||
|  |             data.setLeaderName(leader != null ? leader.getUserName() : ""); | ||||||
|  |             //data.setLeadeTitle(leader != null ? leader.getUserTitle() : ""); | ||||||
|  |             data.setDesignerName(designers.stream().map(DesUser::getUserName).collect(Collectors.joining("、"))); | ||||||
|  |             //data.setDesignerTitle(designers.stream().map(DesUser::getUserTitle).collect(Collectors.joining("、"))); | ||||||
|  |             data.setReviewerName(reviewer != null ? reviewer.getUserName() : ""); | ||||||
|  |             //data.setReviewerTitle(reviewer != null ? reviewer.getUserTitle() : ""); | ||||||
|  |             data.setCheckerName(checker != null ? checker.getUserName() : ""); | ||||||
|  |             //data.setCheckerTitle(checker != null ? checker.getUserTitle() : ""); | ||||||
|  |             data.setApproverName(approver != null ? approver.getUserName() : ""); | ||||||
|  |             //data.setApproverTitle(approver != null ? approver.getUserTitle() : ""); | ||||||
|  |  | ||||||
|  |             dataList.add(data); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return dataList; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ package org.dromara.design.controller; | |||||||
|  |  | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
|  | import com.deepoove.poi.XWPFTemplate; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.NotEmpty; | import jakarta.validation.constraints.NotEmpty; | ||||||
| @ -16,24 +17,36 @@ import org.dromara.common.log.enums.BusinessType; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.web.core.BaseController; | import org.dromara.common.web.core.BaseController; | ||||||
|  | import org.dromara.design.domain.DesUser; | ||||||
| import org.dromara.design.domain.DesVolumeCatalog; | import org.dromara.design.domain.DesVolumeCatalog; | ||||||
| import org.dromara.design.domain.DesVolumeFile; | import org.dromara.design.domain.DesVolumeFile; | ||||||
| import org.dromara.design.domain.dto.designchange.DesDesignChangeCreateReq; | import org.dromara.design.domain.dto.designchange.DesDesignChangeCreateReq; | ||||||
| import org.dromara.design.domain.dto.designchange.DesDesignChangeQueryReq; | import org.dromara.design.domain.dto.designchange.DesDesignChangeQueryReq; | ||||||
| import org.dromara.design.domain.dto.designchange.DesDesignChangeUpdateReq; | import org.dromara.design.domain.dto.designchange.DesDesignChangeUpdateReq; | ||||||
|  | import org.dromara.design.domain.dto.designchange.DesDesignExtendDetailDto; | ||||||
| import org.dromara.design.domain.dto.volumecatalog.DesVolumeCatalogQueryReq; | import org.dromara.design.domain.dto.volumecatalog.DesVolumeCatalogQueryReq; | ||||||
| import org.dromara.design.domain.vo.designchange.DesDesignChangeVo; | import org.dromara.design.domain.vo.designchange.DesDesignChangeVo; | ||||||
| import org.dromara.design.domain.vo.volumecatalog.DesVolumeCatalogVo; | import org.dromara.design.domain.vo.volumecatalog.DesVolumeCatalogVo; | ||||||
| import org.dromara.design.service.IDesDesignChangeService; | import org.dromara.design.service.IDesDesignChangeService; | ||||||
| import org.dromara.design.service.IDesVolumeCatalogService; | import org.dromara.design.service.IDesVolumeCatalogService; | ||||||
| import org.dromara.design.service.IDesVolumeFileService; | import org.dromara.design.service.IDesVolumeFileService; | ||||||
|  | import org.dromara.project.domain.BusProject; | ||||||
| import org.dromara.system.domain.vo.SysOssVo; | import org.dromara.system.domain.vo.SysOssVo; | ||||||
|  | import org.dromara.system.service.ISysDictDataService; | ||||||
| import org.dromara.system.service.ISysOssService; | import org.dromara.system.service.ISysOssService; | ||||||
|  | import org.springframework.core.io.ClassPathResource; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.net.URLEncoder; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
|  | import java.util.HashMap; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -56,6 +69,9 @@ public class DesDesignChangeController extends BaseController { | |||||||
|     @Resource |     @Resource | ||||||
|     private IDesVolumeFileService desVolumeFileService; |     private IDesVolumeFileService desVolumeFileService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private ISysDictDataService dictDataService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询设计变更管理列表 |      * 查询设计变更管理列表 | ||||||
|      */ |      */ | ||||||
| @ -146,4 +162,92 @@ public class DesDesignChangeController extends BaseController { | |||||||
|         return R.ok(list); |         return R.ok(list); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static final String TEMPLATE_PATH = "template/设计更改通知单.docx"; | ||||||
|  |  | ||||||
|  |     @PostMapping("/downloadWord") | ||||||
|  |     public void generateDesignLeaderDoc(Long id, HttpServletResponse response) { | ||||||
|  |         OutputStream outputStream = null; | ||||||
|  |         try { | ||||||
|  |             // 1. 调用Service生成目标模板的Word字节流 | ||||||
|  |             byte[] docBytes = generateDocBytes(id); | ||||||
|  |  | ||||||
|  |             // 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型) | ||||||
|  |             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型 | ||||||
|  |             // 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”(此处用projectId拼接,真实场景可从数据中获取项目名) | ||||||
|  |             String downloadFileName = URLEncoder.encode( | ||||||
|  |                 "设计更改通知单.docx", | ||||||
|  |                 "UTF-8" | ||||||
|  |             ); | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName); | ||||||
|  |             response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验) | ||||||
|  |  | ||||||
|  |             // 3. 将Word字节流写入响应 | ||||||
|  |             outputStream = response.getOutputStream(); | ||||||
|  |             outputStream.write(docBytes); | ||||||
|  |             outputStream.flush(); | ||||||
|  |  | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             // 异常处理:返回500错误状态码 | ||||||
|  |             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | ||||||
|  |         } finally { | ||||||
|  |             // 关闭流,避免资源泄漏 | ||||||
|  |             if (outputStream != null) { | ||||||
|  |                 try { | ||||||
|  |                     outputStream.close(); | ||||||
|  |                 } catch (Exception e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public byte[] generateDocBytes(Long id) throws Exception { | ||||||
|  |         // -------------------------- 步骤1:按projectId查询项目数据(模拟真实业务) -------------------------- | ||||||
|  |         // 实际场景替换为数据库查询(如调用DAO获取项目名称、负责人等) | ||||||
|  |         DesDesignChangeVo vo = desDesignChangeService.queryById(id); | ||||||
|  |         DesDesignExtendDetailDto extendDetail = vo.getExtendDetail()==null?new DesDesignExtendDetailDto():vo.getExtendDetail(); | ||||||
|  |  | ||||||
|  |         Map<String, Object> placeholderData = new HashMap<>(); | ||||||
|  |         placeholderData.put("projectName", vo.getProjectName()); | ||||||
|  |         placeholderData.put("designPhase",extendDetail.getDesignPhase()); | ||||||
|  |         placeholderData.put("subName",extendDetail.getSubName()); | ||||||
|  |         String s = dictDataService.selectDictLabel("des_user_major", vo.getSpecialty()); | ||||||
|  |         placeholderData.put("specialty",s); | ||||||
|  |         placeholderData.put("volumeNo",vo.getVolumeNo()); | ||||||
|  |  | ||||||
|  |         String changeReason = vo.getChangeReason(); | ||||||
|  |         List<String> reasons = Arrays.asList("设计漏项", "设计改进", "设计差错", "接口差错", | ||||||
|  |             "业主要求", "施工承包商要求", "外部资料与最终情况不符", "材料代用或其他"); | ||||||
|  |  | ||||||
|  |         String reason = reasons.stream() | ||||||
|  |             .map(item -> changeReason.contains(String.valueOf(reasons.indexOf(item) + 1)) ? "  ☑" + item : "  □" + item) | ||||||
|  |             .collect(Collectors.joining()); | ||||||
|  |  | ||||||
|  |         placeholderData.put("changeReason", reason); | ||||||
|  |         placeholderData.put("designDisposal1", "1".equals(extendDetail.getDesignDisposal())?"☑" : "□"); | ||||||
|  |         placeholderData.put("designDisposal2", "2".equals(extendDetail.getDesignDisposal())?"☑" : "□"); | ||||||
|  |         placeholderData.put("designDisposal3", "3".equals(extendDetail.getDesignDisposal())?"☑" : "□"); | ||||||
|  |         placeholderData.put("changeContent",vo.getChangeContent()); | ||||||
|  |         placeholderData.put("changeCategory1", "1".equals(extendDetail.getChangeCategory())?"☑" : "□"); | ||||||
|  |         placeholderData.put("changeCategory2", "2".equals(extendDetail.getChangeCategory())?"☑" : "□"); | ||||||
|  |         placeholderData.put("involvingProfessions", extendDetail.getInvolvingProfessions()); | ||||||
|  |         // -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 -------------------------- | ||||||
|  |         // 读取resources下的“设计项目负责人任命通知单.docx”模板 | ||||||
|  |         ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH); | ||||||
|  |         try (InputStream templateIs = templateResource.getInputStream(); | ||||||
|  |              ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { | ||||||
|  |  | ||||||
|  |             // 1. 加载模板 2. 注入替换数据 3. 渲染生成新文档 | ||||||
|  |             XWPFTemplate template = XWPFTemplate.compile(templateIs) | ||||||
|  |                 .render(placeholderData); // 自动匹配{{变量名}}占位符 | ||||||
|  |  | ||||||
|  |             // -------------------------- 步骤3:将生成的文档写入字节流 -------------------------- | ||||||
|  |             template.write(outputStream); | ||||||
|  |             template.close(); // 关闭模板资源 | ||||||
|  |             return outputStream.toByteArray(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -129,6 +129,7 @@ public class DesExtractController extends BaseController { | |||||||
|     @SaCheckPermission("design:extract:userMajor") |     @SaCheckPermission("design:extract:userMajor") | ||||||
|     @GetMapping("/userMajor") |     @GetMapping("/userMajor") | ||||||
|     public R<List<DesUserVo>> selectUserMajor(DesUserBo bo) { |     public R<List<DesUserVo>> selectUserMajor(DesUserBo bo) { | ||||||
|  |         bo.setUserType("1"); | ||||||
|         return R.ok( deUserService.queryList(bo)); |         return R.ok( deUserService.queryList(bo)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; | |||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.*; | import jakarta.validation.constraints.*; | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| @ -128,4 +129,9 @@ public class DesPrelimSchemeController extends BaseController { | |||||||
|         return toAjax(desPrelimSchemeService.updateFile(file, projectId,id)); |         return toAjax(desPrelimSchemeService.updateFile(file, projectId,id)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @PostMapping("/exportZipWithStatus") | ||||||
|  |     public void exportZipWithStatus(ExportDto dto, HttpServletResponse response) throws Exception { | ||||||
|  |         desPrelimSchemeService.exportAsZipWithStatusPrefix(dto, response); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; | |||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.*; | import jakarta.validation.constraints.*; | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| @ -126,4 +127,10 @@ public class DesSchemeController extends BaseController { | |||||||
|     public R<Void> updateFile(MultipartFile file, Long projectId, @NotNull(message = "主键不能为空")@PathVariable Long id) { |     public R<Void> updateFile(MultipartFile file, Long projectId, @NotNull(message = "主键不能为空")@PathVariable Long id) { | ||||||
|         return toAjax(desSchemeService.updateFile(file, projectId,id)); |         return toAjax(desSchemeService.updateFile(file, projectId,id)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @PostMapping("/exportZipWithStatus") | ||||||
|  |     public void exportZipWithStatus(ExportDto dto, HttpServletResponse response) throws Exception { | ||||||
|  |         desSchemeService.exportAsZipWithStatusPrefix(dto, response); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,16 +1,18 @@ | |||||||
| package org.dromara.design.controller; | package org.dromara.design.controller; | ||||||
|  |  | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
|  | import java.io.OutputStream; | ||||||
|  | import java.net.URLEncoder; | ||||||
| import java.rmi.ServerException; | import java.rmi.ServerException; | ||||||
| import java.time.LocalDate; | import java.time.LocalDate; | ||||||
| import java.time.ZoneId; | import java.time.ZoneId; | ||||||
| import java.util.ArrayList; | import java.util.*; | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.Date; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
|  | import com.deepoove.poi.XWPFTemplate; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.*; | import jakarta.validation.constraints.*; | ||||||
| @ -22,8 +24,15 @@ import org.apache.poi.ss.usermodel.Row; | |||||||
| import org.apache.poi.xssf.usermodel.XSSFSheet; | import org.apache.poi.xssf.usermodel.XSSFSheet; | ||||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||||
| //import org.dromara.design.domain.DesUserExcelData; | //import org.dromara.design.domain.DesUserExcelData; | ||||||
|  | import org.dromara.design.domain.DesUser; | ||||||
| import org.dromara.design.domain.DesUserExcelData; | import org.dromara.design.domain.DesUserExcelData; | ||||||
| import org.dromara.design.domain.dto.desUser.DesUserBatchDto; | import org.dromara.design.domain.dto.desUser.DesUserBatchDto; | ||||||
|  | import org.dromara.project.domain.BusProject; | ||||||
|  | import org.dromara.project.service.IBusProjectService; | ||||||
|  | import org.springframework.core.io.ClassPathResource; | ||||||
|  | import org.springframework.http.HttpStatus; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
|  | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||||
| @ -54,6 +63,7 @@ import org.springframework.web.multipart.MultipartFile; | |||||||
| public class DesUserController extends BaseController { | public class DesUserController extends BaseController { | ||||||
|  |  | ||||||
|     private final IDesUserService desUserService; |     private final IDesUserService desUserService; | ||||||
|  |     private final IBusProjectService projectService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询设计人员列表 |      * 查询设计人员列表 | ||||||
| @ -142,5 +152,75 @@ public class DesUserController extends BaseController { | |||||||
|         return toAjax(desUserService.batchAddOrUpdate(dto)); |         return toAjax(desUserService.batchAddOrUpdate(dto)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static final String TEMPLATE_PATH = "template/设计项目负责人任命通知单.docx"; | ||||||
|  |  | ||||||
|  |     @PostMapping("/downloadWord") | ||||||
|  |     public void generateDesignLeaderDoc( Long projectId, | ||||||
|  |         HttpServletResponse response | ||||||
|  |     ) { | ||||||
|  |         OutputStream outputStream = null; | ||||||
|  |         try { | ||||||
|  |             // 1. 调用Service生成目标模板的Word字节流 | ||||||
|  |             byte[] docBytes = generateDocBytes(projectId); | ||||||
|  |  | ||||||
|  |             // 2. 配置响应头:确保前端正确下载(避免中文乱码、指定文件类型) | ||||||
|  |             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); // 二进制流类型 | ||||||
|  |             // 下载文件名:格式为“[项目名]-设计负责人任命通知单.docx”(此处用projectId拼接,真实场景可从数据中获取项目名) | ||||||
|  |             String downloadFileName = URLEncoder.encode( | ||||||
|  |                 "设计负责人任命通知单.docx", | ||||||
|  |                 "UTF-8" | ||||||
|  |             ); | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName); | ||||||
|  |             response.setContentLength(docBytes.length); // 设置响应体长度(优化下载体验) | ||||||
|  |  | ||||||
|  |             // 3. 将Word字节流写入响应 | ||||||
|  |             outputStream = response.getOutputStream(); | ||||||
|  |             outputStream.write(docBytes); | ||||||
|  |             outputStream.flush(); | ||||||
|  |  | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             // 异常处理:返回500错误状态码 | ||||||
|  |             response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | ||||||
|  |         } finally { | ||||||
|  |             // 关闭流,避免资源泄漏 | ||||||
|  |             if (outputStream != null) { | ||||||
|  |                 try { | ||||||
|  |                     outputStream.close(); | ||||||
|  |                 } catch (Exception e) { | ||||||
|  |                     e.printStackTrace(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public byte[] generateDocBytes(Long projectId) throws Exception { | ||||||
|  |         // -------------------------- 步骤1:按projectId查询项目数据(模拟真实业务) -------------------------- | ||||||
|  |         // 实际场景替换为数据库查询(如调用DAO获取项目名称、负责人等) | ||||||
|  |         BusProject byId = projectService.getById(projectId); | ||||||
|  |         DesUser desUser = desUserService.lambdaQuery().eq(DesUser::getProjectId, projectId) | ||||||
|  |             .eq(DesUser::getUserType, "1") | ||||||
|  |             .last("limit 1").one(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         Map<String, Object> placeholderData = new HashMap<>(); | ||||||
|  |         placeholderData.put("projectName", byId==null?"" :byId.getProjectName()); | ||||||
|  |         placeholderData.put("leaderName",desUser==null?"": desUser.getUserName()); | ||||||
|  |  | ||||||
|  |         // -------------------------- 步骤2:用poi-tl加载目标模板并替换占位符 -------------------------- | ||||||
|  |         // 读取resources下的“设计项目负责人任命通知单.docx”模板 | ||||||
|  |         ClassPathResource templateResource = new ClassPathResource(TEMPLATE_PATH); | ||||||
|  |         try (InputStream templateIs = templateResource.getInputStream(); | ||||||
|  |              ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { | ||||||
|  |  | ||||||
|  |             // 1. 加载模板 2. 注入替换数据 3. 渲染生成新文档 | ||||||
|  |             XWPFTemplate template = XWPFTemplate.compile(templateIs) | ||||||
|  |                 .render(placeholderData); // 自动匹配{{变量名}}占位符 | ||||||
|  |  | ||||||
|  |             // -------------------------- 步骤3:将生成的文档写入字节流 -------------------------- | ||||||
|  |             template.write(outputStream); | ||||||
|  |             template.close(); // 关闭模板资源 | ||||||
|  |             return outputStream.toByteArray(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,11 @@ | |||||||
|  | package org.dromara.design.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | public class ExportDto { | ||||||
|  |     private Long projectId; | ||||||
|  |     private List<Long> ids; | ||||||
|  | } | ||||||
| @ -0,0 +1,15 @@ | |||||||
|  | package org.dromara.design.domain.vo; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | public class DesCollectFileWordVo { | ||||||
|  |  | ||||||
|  |     private Integer num; | ||||||
|  |  | ||||||
|  |     private String fileName; | ||||||
|  |  | ||||||
|  |     private String opinion; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -1,5 +1,7 @@ | |||||||
| package org.dromara.design.domain.vo; | package org.dromara.design.domain.vo; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.annotation.ExcelIgnore; | ||||||
|  | import com.alibaba.excel.annotation.format.DateTimeFormat; | ||||||
| import org.dromara.design.domain.DesSubcontract; | import org.dromara.design.domain.DesSubcontract; | ||||||
| import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | ||||||
| import com.alibaba.excel.annotation.ExcelProperty; | import com.alibaba.excel.annotation.ExcelProperty; | ||||||
| @ -31,13 +33,13 @@ public class DesSubcontractVo implements Serializable { | |||||||
|     /** |     /** | ||||||
|      * 主键ID |      * 主键ID | ||||||
|      */ |      */ | ||||||
|     @ExcelProperty(value = "主键ID") |     @ExcelIgnore | ||||||
|     private Long id; |     private Long id; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 项目id |      * 项目id | ||||||
|      */ |      */ | ||||||
|     @ExcelProperty(value = "项目id") |     @ExcelIgnore | ||||||
|     private Long projectId; |     private Long projectId; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @ -49,7 +51,13 @@ public class DesSubcontractVo implements Serializable { | |||||||
|     /** |     /** | ||||||
|      * 分包要求 |      * 分包要求 | ||||||
|      */ |      */ | ||||||
|  |     @ExcelProperty(value = "说明") | ||||||
|     private String requirement; |     private String requirement; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建时间 | ||||||
|  |      */ | ||||||
|  |     @DateTimeFormat("yyyy-MM-dd") | ||||||
|  |     @ExcelProperty(value = "创建时间") | ||||||
|     private Date createTime; |     private Date createTime; | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,33 @@ | |||||||
|  | package org.dromara.design.exportUtil.bill; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.annotation.ExcelProperty; | ||||||
|  | import com.alibaba.excel.annotation.format.NumberFormat; | ||||||
|  | import com.alibaba.excel.annotation.write.style.HeadStyle; | ||||||
|  | import com.alibaba.excel.enums.poi.FillPatternTypeEnum; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.math.BigDecimal; | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 9) | ||||||
|  | public class BillOfQuantitiesExport { | ||||||
|  |     @ExcelProperty(value = "编号", index = 0) | ||||||
|  |     private String num; | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "名称及规格", index = 1) | ||||||
|  |     private String name; | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "规格", index = 2) | ||||||
|  |     private String specification; | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "单位", index = 3) | ||||||
|  |     @NumberFormat("#") // 若单位为文本,可去掉此注解 | ||||||
|  |     private String unit; | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "数量", index = 4) | ||||||
|  |     @NumberFormat("#,##0.00") // 数量格式化(保留两位小数) | ||||||
|  |     private BigDecimal quantity; | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "备注", index = 5) | ||||||
|  |     private String remark; | ||||||
|  | } | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | package org.dromara.design.exportUtil.bill; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.write.handler.SheetWriteHandler; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; | ||||||
|  | import org.apache.poi.ss.usermodel.Sheet; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 调整指定列的宽度(第二列和第五列) | ||||||
|  |  */ | ||||||
|  | public class ColumnWidthWriteHandler implements SheetWriteHandler { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { | ||||||
|  |         Sheet sheet = writeSheetHolder.getSheet(); | ||||||
|  |  | ||||||
|  |         // 设置列宽(单位:字符数,1字符≈256个单位,这里按实际需求调整) | ||||||
|  |         // 第二列(索引1):例如设置宽度为30个字符 | ||||||
|  |         sheet.setColumnWidth(1, 30 * 256); | ||||||
|  |         // 第五列(索引4):例如设置宽度为15个字符 | ||||||
|  |         sheet.setColumnWidth(4, 15 * 256); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,51 @@ | |||||||
|  | package org.dromara.design.exportUtil.bill; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.write.handler.RowWriteHandler; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteTableHolder; | ||||||
|  | import org.apache.poi.ss.usermodel.*; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 行样式处理器: | ||||||
|  |  * 1. 第二行(索引1)及以后所有行添加边框 | ||||||
|  |  * 2. 第二行(索引1)的第二列(索引1)标题栏加粗加大 | ||||||
|  |  */ | ||||||
|  | import com.alibaba.excel.write.handler.RowWriteHandler; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteTableHolder; | ||||||
|  | import org.apache.poi.ss.usermodel.*; | ||||||
|  |  | ||||||
|  | public class CustomRowStyleHandler implements RowWriteHandler { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) { | ||||||
|  |         // 关键修改:通过 writeSheetHolder 获取 Workbook(兼容所有版本) | ||||||
|  |         Workbook workbook = writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook(); | ||||||
|  |         int rowIndex = row.getRowNum(); | ||||||
|  |  | ||||||
|  |         // 1. 第二行(索引1)及以后的行添加边框 | ||||||
|  |         if (rowIndex >= 1) { | ||||||
|  |             CellStyle borderStyle = ExcelStyleUtils.createBorderStyle(workbook); | ||||||
|  |  | ||||||
|  |             for (int i = 0; i <= 5; i++) { | ||||||
|  |                 Cell cell = row.getCell(i); | ||||||
|  |                 if (cell == null) { | ||||||
|  |                     cell = row.createCell(i); | ||||||
|  |                 } | ||||||
|  |                 cell.setCellStyle(borderStyle); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 2. 第二行(索引1)的第二列(索引1)标题栏加粗加大 | ||||||
|  |             if (rowIndex == 1) { | ||||||
|  |                 for (int i = 0; i <= 5; i++) { | ||||||
|  |                     Cell secondColumnCell = row.getCell(i); | ||||||
|  |                     if (secondColumnCell != null) { | ||||||
|  |                         CellStyle headerStyle = ExcelStyleUtils.createSecondColumnHeaderStyle(workbook); | ||||||
|  |                         secondColumnCell.setCellStyle(headerStyle); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,57 @@ | |||||||
|  | package org.dromara.design.exportUtil.bill; | ||||||
|  |  | ||||||
|  | import org.apache.poi.ss.usermodel.*; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 样式工具类(定义边框、字体等样式) | ||||||
|  |  */ | ||||||
|  | public class ExcelStyleUtils { | ||||||
|  |     // 边框样式(细实线) | ||||||
|  |     public static final BorderStyle BORDER_STYLE = BorderStyle.THIN; | ||||||
|  |     // 边框颜色(黑色) | ||||||
|  |     public static final short BORDER_COLOR = IndexedColors.BLACK.getIndex(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建带边框的单元格样式 | ||||||
|  |      */ | ||||||
|  |     public static CellStyle createBorderStyle(Workbook workbook) { | ||||||
|  |         CellStyle style = workbook.createCellStyle(); | ||||||
|  |         // 上下左右边框 | ||||||
|  |         style.setBorderTop(BORDER_STYLE); | ||||||
|  |         style.setBorderBottom(BORDER_STYLE); | ||||||
|  |         style.setBorderLeft(BORDER_STYLE); | ||||||
|  |         style.setBorderRight(BORDER_STYLE); | ||||||
|  |         // 边框颜色 | ||||||
|  |         style.setTopBorderColor(BORDER_COLOR); | ||||||
|  |         style.setBottomBorderColor(BORDER_COLOR); | ||||||
|  |         style.setLeftBorderColor(BORDER_COLOR); | ||||||
|  |         style.setRightBorderColor(BORDER_COLOR); | ||||||
|  |         // 单元格内容居中(可选) | ||||||
|  |         style.setAlignment(HorizontalAlignment.CENTER); | ||||||
|  |         style.setVerticalAlignment(VerticalAlignment.CENTER); | ||||||
|  |         return style; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建第二列标题栏样式(加粗、字号加大) | ||||||
|  |      */ | ||||||
|  |     public static CellStyle createSecondColumnHeaderStyle(Workbook workbook) { | ||||||
|  |         CellStyle style = createBorderStyle(workbook); // 继承边框样式 | ||||||
|  |         Font font = workbook.createFont(); | ||||||
|  |         font.setBold(true); // 加粗 | ||||||
|  |         font.setFontHeightInPoints((short) 12); // 字号加大(默认11,这里设12) | ||||||
|  |         style.setFont(font); | ||||||
|  |         return style; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建第一行(合并标题行)的白色背景样式 | ||||||
|  |      */ | ||||||
|  |     public static CellStyle createFirstRowWhiteStyle(Workbook workbook) { | ||||||
|  |         CellStyle style = workbook.createCellStyle(); | ||||||
|  |         // 设置白色背景 | ||||||
|  |         style.setFillForegroundColor(IndexedColors.WHITE.getIndex()); | ||||||
|  |         style.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 纯色填充 | ||||||
|  |         return style; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | package org.dromara.design.exportUtil.bill; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.write.handler.SheetWriteHandler; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; | ||||||
|  | import org.apache.poi.ss.usermodel.Sheet; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 冻结前3行的处理器(滚动时前3行固定) | ||||||
|  |  */ | ||||||
|  | public class FreezePaneWriteHandler implements SheetWriteHandler { | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { | ||||||
|  |         Sheet sheet = writeSheetHolder.getSheet(); | ||||||
|  |         // 参数说明:冻结0列,冻结2行,从第0列、第2行开始滚动 | ||||||
|  |         // 前2行(索引0和1)将固定在顶部 | ||||||
|  |         sheet.createFreezePane(0, 2, 0, 2); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,41 @@ | |||||||
|  | package org.dromara.design.exportUtil.bill; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.write.handler.SheetWriteHandler; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; | ||||||
|  | import org.apache.poi.ss.usermodel.Cell; | ||||||
|  | import org.apache.poi.ss.usermodel.Row; | ||||||
|  | import org.apache.poi.ss.usermodel.Sheet; | ||||||
|  | import org.apache.poi.ss.usermodel.Workbook; | ||||||
|  | import org.apache.poi.ss.util.CellRangeAddress; | ||||||
|  |  | ||||||
|  | public class SheetHeaderWriteHandler implements SheetWriteHandler { | ||||||
|  |  | ||||||
|  |     private final String sheetName; | ||||||
|  |  | ||||||
|  |     public SheetHeaderWriteHandler( String sheetName) { | ||||||
|  |         this.sheetName = sheetName; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { | ||||||
|  |         Sheet sheet = writeSheetHolder.getSheet(); | ||||||
|  |         Workbook workbook = writeWorkbookHolder.getWorkbook(); | ||||||
|  |  | ||||||
|  |         // 第一行(索引0):合并标题 + 白色背景 | ||||||
|  |         Row titleRow = sheet.createRow(0); | ||||||
|  |         Cell titleCell = titleRow.createCell(0); | ||||||
|  |         titleCell.setCellValue(sheetName); | ||||||
|  |         // 应用白色背景样式 | ||||||
|  |         titleCell.setCellStyle(ExcelStyleUtils.createFirstRowWhiteStyle(workbook)); | ||||||
|  |         // 合并第一行的0-5列 | ||||||
|  |         sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5)); | ||||||
|  |  | ||||||
|  |         // 第2行(索引1):字段标题栏(手动指定,覆盖实体类默认表头) | ||||||
|  |         Row headerRow = sheet.createRow(1); | ||||||
|  |         String[] headers = {"编号", "名称", "规格", "单位", "数量", "备注"}; | ||||||
|  |         for (int i = 0; i < headers.length; i++) { | ||||||
|  |             headerRow.createCell(i).setCellValue(headers[i]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | package org.dromara.design.exportUtil.plan; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @AllArgsConstructor | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class AttachmentPersonnel { | ||||||
|  |     String professional;  // 专业及人员分工 | ||||||
|  |     String leaderName;    // 专业负责人姓名 | ||||||
|  |     String leaderTitle;   // 专业负责人职称 | ||||||
|  |     String designerName;  // 设计人姓名 | ||||||
|  |     String designerTitle; // 设计人职称 | ||||||
|  |     String reviewerName;  // 校审人姓名 | ||||||
|  |     String reviewerTitle; // 校审人职称 | ||||||
|  |     String checkerName;   // 审核人姓名 | ||||||
|  |     String checkerTitle;  // 审核人职称 | ||||||
|  |     String approverName;  // 审定人姓名 | ||||||
|  |     String approverTitle; // 审定人职称 | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | package org.dromara.design.exportUtil.plan; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.annotation.ExcelIgnore; | ||||||
|  | import com.alibaba.excel.annotation.ExcelProperty; | ||||||
|  | import com.alibaba.excel.annotation.format.DateTimeFormat; | ||||||
|  | import com.alibaba.excel.converters.localdate.LocalDateStringConverter; | ||||||
|  | import lombok.Data; | ||||||
|  | import org.dromara.common.excel.annotation.ExcelDictFormat; | ||||||
|  | import org.dromara.common.excel.convert.ExcelDictConvert; | ||||||
|  |  | ||||||
|  | import java.time.LocalDate; | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | public class ConstructionScheduleExport { | ||||||
|  |     @ExcelProperty(value = "编号", index = 0) | ||||||
|  |     private String levelCode; // 层级编号(如1、1.1、1.1.1) | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "节点名称", index = 1) | ||||||
|  |     private String nodeName; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @DateTimeFormat("yyyy-MM-dd") | ||||||
|  |     @ExcelProperty(value = "预计开始时间", index = 2) | ||||||
|  |     private LocalDate planStartDate; | ||||||
|  |  | ||||||
|  |     @DateTimeFormat("yyyy-MM-dd") | ||||||
|  |     @ExcelProperty(value = "预计结束时间", index = 3) | ||||||
|  |     private LocalDate planEndDate; | ||||||
|  |  | ||||||
|  |     @DateTimeFormat("yyyy-MM-dd") | ||||||
|  |     @ExcelProperty(value = "实际开始时间", index = 4) | ||||||
|  |     private LocalDate practicalStartDate; | ||||||
|  |  | ||||||
|  |     @DateTimeFormat("yyyy-MM-dd") | ||||||
|  |     @ExcelProperty(value = "实际结束时间", index = 5) | ||||||
|  |     private LocalDate practicalEndDate; | ||||||
|  |  | ||||||
|  |     @ExcelProperty(value = "状态", index = 6,converter = ExcelDictConvert.class) | ||||||
|  |     @ExcelDictFormat(dictType = "project_construction_status") | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     // 用于构建层级关系的临时字段(不导出) | ||||||
|  |     @ExcelIgnore | ||||||
|  |     private Long id; | ||||||
|  |  | ||||||
|  |     @ExcelIgnore | ||||||
|  |     private Long parentId; | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | package org.dromara.design.exportUtil.plan; | ||||||
|  |  | ||||||
|  | import com.alibaba.excel.write.handler.SheetWriteHandler; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; | ||||||
|  | import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; | ||||||
|  | import org.apache.poi.ss.usermodel.Cell; | ||||||
|  | import org.apache.poi.ss.usermodel.Row; | ||||||
|  | import org.apache.poi.ss.usermodel.Sheet; | ||||||
|  | import org.apache.poi.ss.usermodel.Workbook; | ||||||
|  | import org.apache.poi.ss.util.CellRangeAddress; | ||||||
|  |  | ||||||
|  | public class ScheduleHeaderWriteHandler implements SheetWriteHandler { | ||||||
|  |     @Override | ||||||
|  |     public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { | ||||||
|  |         Sheet sheet = writeSheetHolder.getSheet(); | ||||||
|  |  | ||||||
|  |         // 第一行直接作为标题栏 | ||||||
|  |         Row titleRow = sheet.createRow(0); | ||||||
|  |         String[] titles = {"编号", "节点名称", "预计开始时间", "预计结束时间", "实际开始时间", "实际结束时间", "状态"}; | ||||||
|  |         for (int i = 0; i < titles.length; i++) { | ||||||
|  |             Cell cell = titleRow.createCell(i); | ||||||
|  |             cell.setCellValue(titles[i]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -3,14 +3,15 @@ package org.dromara.design.service; | |||||||
| import com.baomidou.mybatisplus.extension.service.IService; | import com.baomidou.mybatisplus.extension.service.IService; | ||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.design.domain.BusBillofquantities; |  | ||||||
| import org.dromara.design.domain.BusBillofquantitiesVersions; | import org.dromara.design.domain.BusBillofquantitiesVersions; | ||||||
| import org.dromara.design.domain.bo.*; | import org.dromara.design.domain.bo.*; | ||||||
| import org.dromara.design.domain.vo.*; | import org.dromara.design.domain.vo.*; | ||||||
|  | import org.dromara.design.exportUtil.bill.BillOfQuantitiesExport; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 工程量清单版本Service接口 |  * 工程量清单版本Service接口 | ||||||
| @ -100,4 +101,7 @@ public interface IBusBillofquantitiesVersionsService extends IService<BusBillofq | |||||||
|     List<BusBillofquantitiesMaterialTotalVo> queryMaterialTotalListByProject(Long projectId); |     List<BusBillofquantitiesMaterialTotalVo> queryMaterialTotalListByProject(Long projectId); | ||||||
|  |  | ||||||
|     List<BusBillofquantitiesVo> obtainAllClassification(ObtainAllVersionNumbersReq bo); |     List<BusBillofquantitiesVo> obtainAllClassification(ObtainAllVersionNumbersReq bo); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     Map<String, List<BillOfQuantitiesExport>> export(String versions,Long projectId); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,12 +1,14 @@ | |||||||
| package org.dromara.design.service; | package org.dromara.design.service; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.extension.service.IService; | import com.baomidou.mybatisplus.extension.service.IService; | ||||||
| import org.dromara.design.domain.DesCollectFile; | import org.dromara.design.domain.DesCollectFile; | ||||||
| import org.dromara.design.domain.bo.DesCollectFileBo; | import org.dromara.design.domain.bo.DesCollectFileBo; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.dromara.design.domain.vo.DesCollectFileVo; | import org.dromara.design.domain.vo.DesCollectFileVo; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
| @ -79,5 +81,6 @@ public interface IDesCollectFileService extends IService<DesCollectFile>{ | |||||||
|     Boolean addFile(MultipartFile file, Long catalogueId, Long projectId); |     Boolean addFile(MultipartFile file, Long catalogueId, Long projectId); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void exportAsZip(ExportDto dto, HttpServletResponse response) throws Exception; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ import org.dromara.design.domain.dto.constructionscheduleplan.*; | |||||||
| import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo; | import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| @ -114,4 +115,7 @@ public interface IDesConstructionSchedulePlanService extends IService<DesConstru | |||||||
|      * @return 实体列表 |      * @return 实体列表 | ||||||
|      */ |      */ | ||||||
|     List<DesConstructionSchedulePlan> convertToEntities(List<DesConstructionSchedulePlanExcelDto> excelList); |     List<DesConstructionSchedulePlan> convertToEntities(List<DesConstructionSchedulePlanExcelDto> excelList); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void exportSchedule(HttpServletResponse response, Long projectId) throws IOException; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package org.dromara.design.service; | package org.dromara.design.service; | ||||||
|  |  | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.servlet.http.HttpServletResponse; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.dromara.design.domain.vo.DesPrelimSchemeVo; | import org.dromara.design.domain.vo.DesPrelimSchemeVo; | ||||||
| import org.dromara.design.domain.bo.DesPrelimSchemeBo; | import org.dromara.design.domain.bo.DesPrelimSchemeBo; | ||||||
| import org.dromara.design.domain.DesPrelimScheme; | import org.dromara.design.domain.DesPrelimScheme; | ||||||
| @ -8,7 +9,6 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.extension.service.IService; | import com.baomidou.mybatisplus.extension.service.IService; | ||||||
| import org.springframework.web.bind.annotation.PathVariable; |  | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| @ -81,4 +81,7 @@ public interface IDesPrelimSchemeService extends IService<DesPrelimScheme>{ | |||||||
|      * 修改文件 |      * 修改文件 | ||||||
|      */ |      */ | ||||||
|     Boolean updateFile(MultipartFile file, Long projectId, Long id); |     Boolean updateFile(MultipartFile file, Long projectId, Long id); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void exportAsZipWithStatusPrefix(ExportDto dto, HttpServletResponse response) throws Exception; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,9 @@ | |||||||
| package org.dromara.design.service; | package org.dromara.design.service; | ||||||
|  |  | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
| import org.dromara.common.core.domain.R; | import org.dromara.common.core.domain.R; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.dromara.design.domain.vo.DesSchemeVo; | import org.dromara.design.domain.vo.DesSchemeVo; | ||||||
| import org.dromara.design.domain.bo.DesSchemeBo; | import org.dromara.design.domain.bo.DesSchemeBo; | ||||||
| import org.dromara.design.domain.DesScheme; | import org.dromara.design.domain.DesScheme; | ||||||
| @ -82,4 +84,7 @@ public interface IDesSchemeService extends IService<DesScheme>{ | |||||||
|      * 修改文件 |      * 修改文件 | ||||||
|      */ |      */ | ||||||
|     Boolean updateFile(MultipartFile file, Long projectId, Long id); |     Boolean updateFile(MultipartFile file, Long projectId, Long id); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void exportAsZipWithStatusPrefix(ExportDto dto, HttpServletResponse response) throws Exception; | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ package org.dromara.design.service.impl; | |||||||
|  |  | ||||||
| import cn.hutool.core.bean.BeanUtil; | import cn.hutool.core.bean.BeanUtil; | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
| import com.alibaba.fastjson2.util.BeanUtils; | import cn.hutool.core.collection.CollectionUtil; | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||||
| @ -28,12 +28,11 @@ import org.dromara.common.excel.coryUtils.ExcelReader; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.utils.BatchNumberGenerator; | import org.dromara.common.utils.BatchNumberGenerator; | ||||||
| import org.dromara.common.utils.excel.ExcelDynamicReader; |  | ||||||
| import org.dromara.design.domain.BusBillofquantities; | import org.dromara.design.domain.BusBillofquantities; | ||||||
| import org.dromara.design.domain.BusBillofquantitiesVersions; | import org.dromara.design.domain.BusBillofquantitiesVersions; | ||||||
| import org.dromara.design.domain.bo.*; | import org.dromara.design.domain.bo.*; | ||||||
| import org.dromara.design.domain.dto.MaterialsAndEquipmentExcelDto; |  | ||||||
| import org.dromara.design.domain.vo.*; | import org.dromara.design.domain.vo.*; | ||||||
|  | import org.dromara.design.exportUtil.bill.BillOfQuantitiesExport; | ||||||
| import org.dromara.design.mapper.BusBillofquantitiesVersionsMapper; | import org.dromara.design.mapper.BusBillofquantitiesVersionsMapper; | ||||||
| import org.dromara.design.service.IBusBillofquantitiesService; | import org.dromara.design.service.IBusBillofquantitiesService; | ||||||
| import org.dromara.design.service.IBusBillofquantitiesVersionsService; | import org.dromara.design.service.IBusBillofquantitiesVersionsService; | ||||||
| @ -363,6 +362,35 @@ public class BusBillofquantitiesVersionsServiceImpl extends ServiceImpl<BusBillo | |||||||
|         return BeanUtil.copyToList(busBillofquantities,BusBillofquantitiesVo.class); |         return BeanUtil.copyToList(busBillofquantities,BusBillofquantitiesVo.class); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public Map<String, List<BillOfQuantitiesExport>> export(String versions,Long projectId) { | ||||||
|  |         // 1. 从数据库查询指定版本的所有数据 | ||||||
|  |         List<BusBillofquantities> dbList = busBillofquantitiesService.list(Wrappers.<BusBillofquantities>lambdaQuery() | ||||||
|  |             .eq(BusBillofquantities::getVersions, versions) | ||||||
|  |             .eq(BusBillofquantities::getProjectId, projectId) | ||||||
|  |             .orderByAsc(BusBillofquantities::getId) | ||||||
|  |         ); | ||||||
|  |         if (CollectionUtil.isEmpty(dbList)) { | ||||||
|  |             return Collections.emptyMap(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 转换为导出实体并按sheet分组 | ||||||
|  |         Map<String, List<BillOfQuantitiesExport>> sheetMap = new LinkedHashMap<>(); | ||||||
|  |         for (BusBillofquantities dbItem : dbList) { | ||||||
|  |             BillOfQuantitiesExport exportItem = new BillOfQuantitiesExport(); | ||||||
|  |             BeanUtil.copyProperties(dbItem, exportItem); | ||||||
|  |             // 处理编号、名称等字段(若需格式化可在此补充) | ||||||
|  |             exportItem.setNum(dbItem.getNum()); | ||||||
|  |             exportItem.setName(dbItem.getName()); | ||||||
|  |  | ||||||
|  |             // 按sheet分组 | ||||||
|  |             String sheetName = dbItem.getSheet(); | ||||||
|  |             sheetMap.computeIfAbsent(sheetName, k -> new ArrayList<>()).add(exportItem); | ||||||
|  |         } | ||||||
|  |         return sheetMap; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 递归构建树形结构 |      * 递归构建树形结构 | ||||||
|      * |      * | ||||||
|  | |||||||
| @ -2,8 +2,11 @@ package org.dromara.design.service.impl; | |||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollectionUtil; | import cn.hutool.core.collection.CollectionUtil; | ||||||
| import cn.hutool.core.convert.Convert; | import cn.hutool.core.convert.Convert; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.apache.commons.io.FileUtils; | ||||||
| import org.dromara.common.core.domain.event.ProcessDeleteEvent; | import org.dromara.common.core.domain.event.ProcessDeleteEvent; | ||||||
| import org.dromara.common.core.domain.event.ProcessEvent; | import org.dromara.common.core.domain.event.ProcessEvent; | ||||||
| import org.dromara.common.core.domain.event.ProcessTaskEvent; | import org.dromara.common.core.domain.event.ProcessTaskEvent; | ||||||
| @ -18,10 +21,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| import org.dromara.design.domain.DesCollect; | import org.dromara.design.domain.DesCollect; | ||||||
|  | import org.dromara.design.domain.DesCollectCatalogue; | ||||||
| import org.dromara.design.domain.DesCollectFile; | import org.dromara.design.domain.DesCollectFile; | ||||||
| import org.dromara.design.domain.bo.DesCollectFileBo; | import org.dromara.design.domain.bo.DesCollectFileBo; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.dromara.design.domain.vo.DesCollectFileVo; | import org.dromara.design.domain.vo.DesCollectFileVo; | ||||||
| import org.dromara.design.mapper.DesCollectFileMapper; | import org.dromara.design.mapper.DesCollectFileMapper; | ||||||
|  | import org.dromara.design.service.IDesCollectCatalogueService; | ||||||
| import org.dromara.design.service.IDesCollectFileService; | import org.dromara.design.service.IDesCollectFileService; | ||||||
| import org.dromara.system.domain.vo.SysOssUploadVo; | import org.dromara.system.domain.vo.SysOssUploadVo; | ||||||
| import org.dromara.system.domain.vo.SysOssVo; | import org.dromara.system.domain.vo.SysOssVo; | ||||||
| @ -31,10 +37,22 @@ import org.springframework.stereotype.Service; | |||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.io.File; | ||||||
| import java.util.List; | import java.io.FileInputStream; | ||||||
| import java.util.Map; | import java.io.IOException; | ||||||
| import java.util.Collection; | import java.io.InputStream; | ||||||
|  | import java.net.URI; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.net.http.HttpClient; | ||||||
|  | import java.net.http.HttpRequest; | ||||||
|  | import java.net.http.HttpResponse; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.time.Duration; | ||||||
|  | import java.util.*; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | import java.util.zip.ZipEntry; | ||||||
|  | import java.util.zip.ZipOutputStream; | ||||||
|  |  | ||||||
| import static org.dromara.common.constant.MinioPathConstant.ContactNoticeTemplate; | import static org.dromara.common.constant.MinioPathConstant.ContactNoticeTemplate; | ||||||
|  |  | ||||||
| @ -53,6 +71,8 @@ public class DesCollectFileServiceImpl extends ServiceImpl<DesCollectFileMapper, | |||||||
|  |  | ||||||
|     private final ISysOssService ossService; |     private final ISysOssService ossService; | ||||||
|  |  | ||||||
|  |     private final IDesCollectCatalogueService collectCatalogueService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询收资文件 |      * 查询收资文件 | ||||||
|      * |      * | ||||||
| @ -217,4 +237,144 @@ public class DesCollectFileServiceImpl extends ServiceImpl<DesCollectFileMapper, | |||||||
|         log.info("监听删除流程事件,上传资料审核任务执行了{}", processDeleteEvent.toString()); |         log.info("监听删除流程事件,上传资料审核任务执行了{}", processDeleteEvent.toString()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void exportAsZip(ExportDto dto, HttpServletResponse response) throws Exception { | ||||||
|  |         // 1. 查询所有收资文件 | ||||||
|  |         List<DesCollectFile> files = baseMapper.selectList(Wrappers.<DesCollectFile>lambdaQuery() | ||||||
|  |             .eq(DesCollectFile::getProjectId, dto.getProjectId()) | ||||||
|  |             .in(CollectionUtil.isNotEmpty(dto.getIds()),DesCollectFile::getId, dto.getIds()) | ||||||
|  |         ); | ||||||
|  |         if (files.isEmpty()) { | ||||||
|  |             throw new RuntimeException("没有可导出的收资文件"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 提取所有catalogueId,查询对应的目录名称 | ||||||
|  |         List<Long> catalogueIds = files.stream() | ||||||
|  |             .map(DesCollectFile::getCatalogueId) | ||||||
|  |             .distinct() | ||||||
|  |             .collect(Collectors.toList()); | ||||||
|  |         Map<Long, String> catalogueNameMap = getCatalogueNames(catalogueIds); // 获取名称映射 | ||||||
|  |  | ||||||
|  |         // 3. 按catalogueId分组 | ||||||
|  |         Map<Long, List<DesCollectFile>> catalogueGroup = files.stream() | ||||||
|  |             .collect(Collectors.groupingBy(DesCollectFile::getCatalogueId)); | ||||||
|  |  | ||||||
|  |         // 4. 创建临时根目录 | ||||||
|  |         File tempRootDir = File.createTempFile("collect_file_", "_temp"); | ||||||
|  |         if (!tempRootDir.delete() || !tempRootDir.mkdirs()) { | ||||||
|  |             throw new RuntimeException("创建临时根目录失败"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             // 5. 按分组创建文件夹(用目录名称)并下载文件 | ||||||
|  |             for (Map.Entry<Long, List<DesCollectFile>> entry : catalogueGroup.entrySet()) { | ||||||
|  |                 Long catalogueId = entry.getKey(); | ||||||
|  |                 List<DesCollectFile> fileList = entry.getValue(); | ||||||
|  |  | ||||||
|  |                 // 获取目录名称(若查询不到,用catalogueId作为默认名称) | ||||||
|  |                 String catalogueName = catalogueNameMap.getOrDefault(catalogueId, String.valueOf(catalogueId)); | ||||||
|  |                 // 处理名称中的特殊字符(避免创建文件夹失败) | ||||||
|  |                 String safeCatalogueName = catalogueName.replaceAll("[\\\\/:*?\"<>|]", "_"); | ||||||
|  |  | ||||||
|  |                 // 创建以目录名称命名的文件夹 | ||||||
|  |                 File catalogueDir = new File(tempRootDir, safeCatalogueName); | ||||||
|  |                 if (!catalogueDir.exists() && !catalogueDir.mkdirs()) { | ||||||
|  |                     throw new RuntimeException("创建文件夹[" + safeCatalogueName + "]失败"); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 // 下载文件(命名格式:审核状态-原文件名) | ||||||
|  |                 for (DesCollectFile file : fileList) { | ||||||
|  |                     String newFileName = BusinessStatusEnum.getByStatus(file.getStatus()).getDesc() + "-" + file.getFileName(); | ||||||
|  |                     File destFile = new File(catalogueDir, newFileName); | ||||||
|  |                     downloadFile(file.getFileUrl(), destFile); // 复用之前的下载方法 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 6. 压缩并导出(逻辑不变) | ||||||
|  |             response.setContentType("application/zip"); | ||||||
|  |             response.setCharacterEncoding(StandardCharsets.UTF_8.name()); | ||||||
|  |             String zipFileName = URLEncoder.encode("收资文件汇总", StandardCharsets.UTF_8.name()) + ".zip"; | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + zipFileName); | ||||||
|  |  | ||||||
|  |             try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { | ||||||
|  |                 zipDirectory(tempRootDir, tempRootDir.getName(), zos); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } finally { | ||||||
|  |             FileUtils.deleteQuietly(tempRootDir); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 查询catalogueId对应的目录名称(从数据库获取) | ||||||
|  |      * @param catalogueIds 多个catalogueId | ||||||
|  |      * @return key: catalogueId, value: 目录名称 | ||||||
|  |      */ | ||||||
|  |     public Map<Long, String> getCatalogueNames(List<Long> catalogueIds) { | ||||||
|  |         if (catalogueIds.isEmpty()) { | ||||||
|  |             return Collections.emptyMap(); | ||||||
|  |         } | ||||||
|  |         // 实际实现:从目录表查询,例如 | ||||||
|  |         List<DesCollectCatalogue> desCollectCatalogues = collectCatalogueService.listByIds(catalogueIds); | ||||||
|  |         return desCollectCatalogues.stream() | ||||||
|  |             .collect(Collectors.toMap(DesCollectCatalogue::getId, DesCollectCatalogue::getCatalogueName)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 下载文件(Java 21兼容,使用HttpClient替代URL) | ||||||
|  |      * @param fileUrl 文件URL(远程地址或本地路径) | ||||||
|  |      * @param destFile 目标文件 | ||||||
|  |      */ | ||||||
|  |     private void downloadFile(String fileUrl, File destFile) throws Exception { | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         // 远程URL文件,使用HttpClient下载 | ||||||
|  |         HttpClient client = HttpClient.newBuilder() | ||||||
|  |             .connectTimeout(Duration.ofMinutes(5)) | ||||||
|  |             .build(); | ||||||
|  |         HttpRequest request = HttpRequest.newBuilder() | ||||||
|  |             .uri(URI.create(fileUrl)) | ||||||
|  |             .timeout(Duration.ofMinutes(10)) | ||||||
|  |             .GET() | ||||||
|  |             .build(); | ||||||
|  |         HttpResponse<Path> response = client.send( | ||||||
|  |             request, | ||||||
|  |             HttpResponse.BodyHandlers.ofFile(destFile.toPath()) | ||||||
|  |         ); | ||||||
|  |         if (response.statusCode() != 200) { | ||||||
|  |             throw new RuntimeException("文件下载失败:" + fileUrl + ",状态码:" + response.statusCode()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 递归压缩目录到ZIP流 | ||||||
|  |      * @param sourceDir 源目录 | ||||||
|  |      * @param baseName ZIP内的基础路径(避免包含系统临时目录路径) | ||||||
|  |      * @param zos ZIP输出流 | ||||||
|  |      */ | ||||||
|  |     private void zipDirectory(File sourceDir, String baseName, ZipOutputStream zos) throws IOException { | ||||||
|  |         File[] files = sourceDir.listFiles(); | ||||||
|  |         if (files == null) return; | ||||||
|  |  | ||||||
|  |         for (File file : files) { | ||||||
|  |             String entryName = baseName + File.separator + file.getName(); | ||||||
|  |             if (file.isDirectory()) { | ||||||
|  |                 // 递归压缩子目录 | ||||||
|  |                 zipDirectory(file, entryName, zos); | ||||||
|  |             } else { | ||||||
|  |                 // 压缩文件 | ||||||
|  |                 zos.putNextEntry(new ZipEntry(entryName)); | ||||||
|  |                 try (InputStream in = new FileInputStream(file)) { | ||||||
|  |                     byte[] buffer = new byte[1024]; | ||||||
|  |                     int len; | ||||||
|  |                     while ((len = in.read(buffer)) != -1) { | ||||||
|  |                         zos.write(buffer, 0, len); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 zos.closeEntry(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,10 @@ | |||||||
| package org.dromara.design.service.impl; | package org.dromara.design.service.impl; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.collection.CollectionUtil; | ||||||
|  | import com.alibaba.excel.EasyExcel; | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.IdWorker; | import com.baomidou.mybatisplus.core.toolkit.IdWorker; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| @ -14,15 +17,19 @@ import org.dromara.common.core.constant.HttpStatus; | |||||||
| import org.dromara.common.core.exception.ServiceException; | import org.dromara.common.core.exception.ServiceException; | ||||||
| import org.dromara.common.core.utils.ObjectUtils; | import org.dromara.common.core.utils.ObjectUtils; | ||||||
| import org.dromara.common.core.utils.StringUtils; | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.excel.utils.ExcelUtil; | ||||||
| import org.dromara.design.domain.DesConstructionSchedulePlan; | import org.dromara.design.domain.DesConstructionSchedulePlan; | ||||||
| import org.dromara.design.domain.bo.DesUserBo; | import org.dromara.design.domain.bo.DesUserBo; | ||||||
| import org.dromara.design.domain.dto.constructionscheduleplan.*; | import org.dromara.design.domain.dto.constructionscheduleplan.*; | ||||||
| import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo; | import org.dromara.design.domain.vo.DesConstructionSchedulePlanVo; | ||||||
|  | import org.dromara.design.exportUtil.plan.ConstructionScheduleExport; | ||||||
|  | import org.dromara.design.exportUtil.plan.ScheduleHeaderWriteHandler; | ||||||
| import org.dromara.design.mapper.DesConstructionSchedulePlanMapper; | import org.dromara.design.mapper.DesConstructionSchedulePlanMapper; | ||||||
| import org.dromara.design.service.IDesConstructionSchedulePlanService; | import org.dromara.design.service.IDesConstructionSchedulePlanService; | ||||||
|  |  | ||||||
| import org.dromara.project.service.IBusProjectService; | import org.dromara.project.service.IBusProjectService; | ||||||
| import org.dromara.system.domain.vo.SysDictDataVo; | import org.dromara.system.domain.vo.SysDictDataVo; | ||||||
|  | import org.dromara.system.domain.vo.SysUserExportVo; | ||||||
| import org.dromara.system.service.ISysDictDataService; | import org.dromara.system.service.ISysDictDataService; | ||||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| @ -36,6 +43,7 @@ import java.nio.charset.StandardCharsets; | |||||||
| import java.time.LocalDate; | import java.time.LocalDate; | ||||||
| import java.time.ZoneId; | import java.time.ZoneId; | ||||||
| import java.util.*; | import java.util.*; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 施工进度计划Service业务层处理 |  * 施工进度计划Service业务层处理 | ||||||
| @ -624,4 +632,97 @@ public class DesConstructionSchedulePlanServiceImpl extends ServiceImpl<DesConst | |||||||
|         } |         } | ||||||
|         return null; |         return null; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void exportSchedule(HttpServletResponse response, Long projectId) throws IOException { | ||||||
|  |         // 1. 构建导出数据(含层级编号) | ||||||
|  |         List<ConstructionScheduleExport> dataList = buildExportData(projectId); | ||||||
|  |         // 2. 设置响应头 | ||||||
|  |         ExcelUtil.exportExcel(dataList, "用户数据", ConstructionScheduleExport.class, response); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     public List<ConstructionScheduleExport> buildExportData(Long projectId) { | ||||||
|  |         // 1. 查询项目下所有里程碑节点 | ||||||
|  |         List<DesConstructionSchedulePlan> allNodes = baseMapper.selectList(Wrappers.<DesConstructionSchedulePlan>lambdaQuery() | ||||||
|  |             .eq(DesConstructionSchedulePlan::getProjectId, projectId)); | ||||||
|  |         if (CollectionUtil.isEmpty(allNodes)) { | ||||||
|  |             return new ArrayList<>(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 转换为导出模型并缓存ID映射 | ||||||
|  |         Map<Long, ConstructionScheduleExport> nodeMap = new HashMap<>(); | ||||||
|  |         List<ConstructionScheduleExport> exportList = new ArrayList<>(); | ||||||
|  |         for (DesConstructionSchedulePlan node : allNodes) { | ||||||
|  |             ConstructionScheduleExport export = new ConstructionScheduleExport(); | ||||||
|  |             BeanUtils.copyProperties(node, export); | ||||||
|  |             nodeMap.put(node.getId(), export); | ||||||
|  |             exportList.add(export); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 3. 构建树形结构并生成层级编号 | ||||||
|  |         List<ConstructionScheduleExport> rootNodes = new ArrayList<>(); | ||||||
|  |         for (ConstructionScheduleExport export : exportList) { | ||||||
|  |             if (export.getParentId() == 0) { // 父ID为0的是根节点 | ||||||
|  |                 rootNodes.add(export); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 4. 递归生成层级编号(根节点从1开始) | ||||||
|  |         int rootIndex = 1; | ||||||
|  |         for (ConstructionScheduleExport root : rootNodes) { | ||||||
|  |             root.setLevelCode(String.valueOf(rootIndex)); | ||||||
|  |             buildChildrenCode(root, nodeMap); | ||||||
|  |             rootIndex++; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 5. 按层级顺序排序(确保1.1在1之后,1.1.1在1.1之后) | ||||||
|  |         return sortByLevelCode(exportList); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 递归为子节点生成编号(如父节点1 -> 子节点1.1、1.2) | ||||||
|  |     private void buildChildrenCode(ConstructionScheduleExport parent, Map<Long, ConstructionScheduleExport> nodeMap) { | ||||||
|  |         List<ConstructionScheduleExport> children = nodeMap.values().stream() | ||||||
|  |             .filter(node -> parent.getId().equals(node.getParentId())) | ||||||
|  |             .collect(Collectors.toList()); | ||||||
|  |  | ||||||
|  |         int childIndex = 1; | ||||||
|  |         for (ConstructionScheduleExport child : children) { | ||||||
|  |             child.setLevelCode(parent.getLevelCode() + "." + childIndex); | ||||||
|  |             buildChildrenCode(child, nodeMap); // 递归处理孙子节点 | ||||||
|  |             childIndex++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 按层级编号排序(字符串自然排序) | ||||||
|  |     private List<ConstructionScheduleExport> sortByLevelCode(List<ConstructionScheduleExport> list) { | ||||||
|  |         return list.stream() | ||||||
|  |             .sorted(Comparator.comparing(ConstructionScheduleExport::getLevelCode)) | ||||||
|  |             .collect(Collectors.toList()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,8 +1,11 @@ | |||||||
| package org.dromara.design.service.impl; | package org.dromara.design.service.impl; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.collection.CollectionUtil; | ||||||
| import cn.hutool.core.convert.Convert; | import cn.hutool.core.convert.Convert; | ||||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.apache.commons.io.FileUtils; | ||||||
| import org.dromara.common.core.domain.event.ProcessDeleteEvent; | import org.dromara.common.core.domain.event.ProcessDeleteEvent; | ||||||
| import org.dromara.common.core.domain.event.ProcessEvent; | import org.dromara.common.core.domain.event.ProcessEvent; | ||||||
| import org.dromara.common.core.domain.event.ProcessTaskEvent; | import org.dromara.common.core.domain.event.ProcessTaskEvent; | ||||||
| @ -15,13 +18,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| import org.dromara.design.domain.DesScheme; | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.dromara.message.domain.MsgConfig; |  | ||||||
| import org.dromara.message.domain.bo.MsgNoticeBo; |  | ||||||
| import org.dromara.message.domain.dto.SendMsgDto; |  | ||||||
| import org.dromara.message.service.IMsgConfigService; | import org.dromara.message.service.IMsgConfigService; | ||||||
| import org.dromara.message.service.IMsgNoticeService; | import org.dromara.message.service.IMsgNoticeService; | ||||||
| import org.dromara.system.domain.vo.SysOssUploadVo; |  | ||||||
| import org.dromara.system.domain.vo.SysOssVo; | import org.dromara.system.domain.vo.SysOssVo; | ||||||
| import org.dromara.system.service.ISysOssService; | import org.dromara.system.service.ISysOssService; | ||||||
| import org.springframework.context.event.EventListener; | import org.springframework.context.event.EventListener; | ||||||
| @ -33,8 +32,18 @@ import org.dromara.design.mapper.DesPrelimSchemeMapper; | |||||||
| import org.dromara.design.service.IDesPrelimSchemeService; | import org.dromara.design.service.IDesPrelimSchemeService; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
|  | import java.io.*; | ||||||
|  | import java.net.URI; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.net.http.HttpClient; | ||||||
|  | import java.net.http.HttpRequest; | ||||||
|  | import java.net.http.HttpResponse; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.time.Duration; | ||||||
| import java.util.*; | import java.util.*; | ||||||
| import java.util.stream.Collectors; | import java.util.zip.ZipEntry; | ||||||
|  | import java.util.zip.ZipOutputStream; | ||||||
|  |  | ||||||
| import static org.dromara.common.constant.MinioPathConstant.ContactNoticeTemplate; | import static org.dromara.common.constant.MinioPathConstant.ContactNoticeTemplate; | ||||||
|  |  | ||||||
| @ -189,6 +198,105 @@ public class DesPrelimSchemeServiceImpl extends ServiceImpl<DesPrelimSchemeMappe | |||||||
|         return  baseMapper.updateById(desPrelimScheme)>0; |         return  baseMapper.updateById(desPrelimScheme)>0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 文件名添加审核状态前缀后压缩为ZIP导出 | ||||||
|  |      * @param response 响应对象 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void exportAsZipWithStatusPrefix(ExportDto dto, HttpServletResponse response) throws Exception { | ||||||
|  |         // 1. 查询数据 | ||||||
|  |         List<DesPrelimScheme> schemes = baseMapper.selectList(Wrappers.<DesPrelimScheme>lambdaQuery() | ||||||
|  |             .eq(DesPrelimScheme::getProjectId, dto.getProjectId()) | ||||||
|  |             .in(CollectionUtil.isNotEmpty(dto.getIds()), DesPrelimScheme::getId, dto.getIds()) | ||||||
|  |         ); | ||||||
|  |         if (schemes.isEmpty()) { | ||||||
|  |             throw new RuntimeException("没有可导出的初步设计方案文件"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 创建临时目录(存放重命名后的文件) | ||||||
|  |         File tempDir = File.createTempFile("prelim_scheme_", "_temp"); | ||||||
|  |         if (!tempDir.delete()) { // 删除临时文件,创建同名目录 | ||||||
|  |             throw new RuntimeException("创建临时目录失败"); | ||||||
|  |         } | ||||||
|  |         if (!tempDir.mkdirs()) { | ||||||
|  |             throw new RuntimeException("创建临时目录失败"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             // 3. 下载文件并以“审核状态-原文件名”命名 | ||||||
|  |             for (DesPrelimScheme scheme : schemes) { | ||||||
|  |                 String status = BusinessStatusEnum.getByStatus(scheme.getStatus()).getDesc(); // 审核状态(如draft、approved) | ||||||
|  |                 String originalFileName = scheme.getFileName(); // 原文件名 | ||||||
|  |                 String newFileName = status + "-" + originalFileName; // 新文件名:状态-原文件名 | ||||||
|  |  | ||||||
|  |                 // 临时文件路径 | ||||||
|  |                 File tempFile = new File(tempDir, newFileName); | ||||||
|  |  | ||||||
|  |                 // 下载文件到临时目录(根据实际存储类型实现,此处以URL为例) | ||||||
|  |                 downloadFile(scheme.getFileUrl(), tempFile); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 4. 压缩临时目录中的所有文件为ZIP并写入响应 | ||||||
|  |             response.setContentType("application/zip"); | ||||||
|  |             response.setCharacterEncoding(StandardCharsets.UTF_8.name()); | ||||||
|  |             String zipFileName = URLEncoder.encode("初步设计方案", StandardCharsets.UTF_8.name()) + ".zip"; | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + zipFileName); | ||||||
|  |  | ||||||
|  |             // 压缩文件到响应流 | ||||||
|  |             try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { | ||||||
|  |                 File[] tempFiles = tempDir.listFiles(); | ||||||
|  |                 if (tempFiles != null) { | ||||||
|  |                     for (File file : tempFiles) { | ||||||
|  |                         // ZIP条目名称为新文件名(不含临时目录路径) | ||||||
|  |                         zos.putNextEntry(new ZipEntry(file.getName())); | ||||||
|  |                         try (InputStream in = new FileInputStream(file)) { | ||||||
|  |                             byte[] buffer = new byte[1024]; | ||||||
|  |                             int len; | ||||||
|  |                             while ((len = in.read(buffer)) != -1) { | ||||||
|  |                                 zos.write(buffer, 0, len); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         zos.closeEntry(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } finally { | ||||||
|  |             // 5. 清理临时目录 | ||||||
|  |             FileUtils.deleteQuietly(tempDir); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 下载文件到本地临时目录(根据实际存储类型调整,如OSS、本地文件系统) | ||||||
|  |      */ | ||||||
|  |     private void downloadFile(String fileUrl, File destFile) throws Exception { | ||||||
|  |         // 示例:从URL下载(若为OSS,使用OSS SDK的getObject方法) | ||||||
|  |         // 创建HTTP客户端(设置超时时间) | ||||||
|  |         HttpClient client = HttpClient.newBuilder() | ||||||
|  |             .connectTimeout(Duration.ofMinutes(5)) // 连接超时 | ||||||
|  |             .build(); | ||||||
|  |  | ||||||
|  |         // 创建HTTP请求 | ||||||
|  |         HttpRequest request = HttpRequest.newBuilder() | ||||||
|  |             .uri(URI.create(fileUrl)) // 转换为URI(比URL更推荐) | ||||||
|  |             .timeout(Duration.ofMinutes(10)) // 响应超时 | ||||||
|  |             .GET() | ||||||
|  |             .build(); | ||||||
|  |  | ||||||
|  |         // 发送请求并将响应体写入目标文件 | ||||||
|  |         HttpResponse<Path> response = client.send( | ||||||
|  |             request, | ||||||
|  |             HttpResponse.BodyHandlers.ofFile(destFile.toPath()) // 直接写入文件路径 | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         // 检查响应状态(200表示成功) | ||||||
|  |         if (response.statusCode() != 200) { | ||||||
|  |             throw new RuntimeException("文件下载失败,URL: " + fileUrl + ",状态码: " + response.statusCode()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) |      * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) | ||||||
|      * 正常使用只需#processEvent.flowCode=='leave1' |      * 正常使用只需#processEvent.flowCode=='leave1' | ||||||
|  | |||||||
| @ -1,8 +1,11 @@ | |||||||
| package org.dromara.design.service.impl; | package org.dromara.design.service.impl; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.collection.CollectionUtil; | ||||||
| import cn.hutool.core.convert.Convert; | import cn.hutool.core.convert.Convert; | ||||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||||
|  | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.apache.commons.io.FileUtils; | ||||||
| import org.dromara.common.core.domain.event.ProcessDeleteEvent; | import org.dromara.common.core.domain.event.ProcessDeleteEvent; | ||||||
| import org.dromara.common.core.domain.event.ProcessEvent; | import org.dromara.common.core.domain.event.ProcessEvent; | ||||||
| import org.dromara.common.core.domain.event.ProcessTaskEvent; | import org.dromara.common.core.domain.event.ProcessTaskEvent; | ||||||
| @ -19,6 +22,7 @@ import org.dromara.common.oss.core.OssClient; | |||||||
| import org.dromara.common.oss.factory.OssFactory; | import org.dromara.common.oss.factory.OssFactory; | ||||||
| import org.dromara.design.domain.DesCollectFile; | import org.dromara.design.domain.DesCollectFile; | ||||||
| import org.dromara.design.domain.DesPrelimScheme; | import org.dromara.design.domain.DesPrelimScheme; | ||||||
|  | import org.dromara.design.domain.dto.ExportDto; | ||||||
| import org.dromara.system.domain.vo.SysOssUploadVo; | import org.dromara.system.domain.vo.SysOssUploadVo; | ||||||
| import org.dromara.system.domain.vo.SysOssVo; | import org.dromara.system.domain.vo.SysOssVo; | ||||||
| import org.dromara.system.service.ISysOssService; | import org.dromara.system.service.ISysOssService; | ||||||
| @ -31,10 +35,23 @@ import org.dromara.design.mapper.DesSchemeMapper; | |||||||
| import org.dromara.design.service.IDesSchemeService; | import org.dromara.design.service.IDesSchemeService; | ||||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||||
|  |  | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.FileInputStream; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.net.URI; | ||||||
|  | import java.net.URLEncoder; | ||||||
|  | import java.net.http.HttpClient; | ||||||
|  | import java.net.http.HttpRequest; | ||||||
|  | import java.net.http.HttpResponse; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.time.Duration; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.zip.ZipEntry; | ||||||
|  | import java.util.zip.ZipOutputStream; | ||||||
|  |  | ||||||
| import static org.dromara.common.constant.MinioPathConstant.ContactNoticeTemplate; | import static org.dromara.common.constant.MinioPathConstant.ContactNoticeTemplate; | ||||||
|  |  | ||||||
| @ -183,6 +200,101 @@ public class DesSchemeServiceImpl extends ServiceImpl<DesSchemeMapper, DesScheme | |||||||
|         return  baseMapper.updateById(desScheme)>0; |         return  baseMapper.updateById(desScheme)>0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void exportAsZipWithStatusPrefix(ExportDto dto, HttpServletResponse response) throws Exception { | ||||||
|  |         // 1. 查询数据 | ||||||
|  |         List<DesScheme> schemes = baseMapper.selectList(Wrappers.<DesScheme>lambdaQuery() | ||||||
|  |             .eq(DesScheme::getProjectId, dto.getProjectId()) | ||||||
|  |             .in(CollectionUtil.isNotEmpty(dto.getIds()), DesScheme::getId, dto.getIds()) | ||||||
|  |         ); | ||||||
|  |         if (schemes.isEmpty()) { | ||||||
|  |             throw new RuntimeException("没有可导出的初步设计方案文件"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 2. 创建临时目录(存放重命名后的文件) | ||||||
|  |         File tempDir = File.createTempFile("prelim_scheme_", "_temp"); | ||||||
|  |         if (!tempDir.delete()) { // 删除临时文件,创建同名目录 | ||||||
|  |             throw new RuntimeException("创建临时目录失败"); | ||||||
|  |         } | ||||||
|  |         if (!tempDir.mkdirs()) { | ||||||
|  |             throw new RuntimeException("创建临时目录失败"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             // 3. 下载文件并以“审核状态-原文件名”命名 | ||||||
|  |             for (DesScheme scheme : schemes) { | ||||||
|  |                 String status = BusinessStatusEnum.getByStatus(scheme.getStatus()).getDesc(); // 审核状态(如draft、approved) | ||||||
|  |                 String originalFileName = scheme.getFileName(); // 原文件名 | ||||||
|  |                 String newFileName = status + "-" + originalFileName; // 新文件名:状态-原文件名 | ||||||
|  |  | ||||||
|  |                 // 临时文件路径 | ||||||
|  |                 File tempFile = new File(tempDir, newFileName); | ||||||
|  |  | ||||||
|  |                 // 下载文件到临时目录(根据实际存储类型实现,此处以URL为例) | ||||||
|  |                 downloadFile(scheme.getFileUrl(), tempFile); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // 4. 压缩临时目录中的所有文件为ZIP并写入响应 | ||||||
|  |             response.setContentType("application/zip"); | ||||||
|  |             response.setCharacterEncoding(StandardCharsets.UTF_8.name()); | ||||||
|  |             String zipFileName = URLEncoder.encode("初步设计方案", StandardCharsets.UTF_8.name()) + ".zip"; | ||||||
|  |             response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + zipFileName); | ||||||
|  |  | ||||||
|  |             // 压缩文件到响应流 | ||||||
|  |             try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { | ||||||
|  |                 File[] tempFiles = tempDir.listFiles(); | ||||||
|  |                 if (tempFiles != null) { | ||||||
|  |                     for (File file : tempFiles) { | ||||||
|  |                         // ZIP条目名称为新文件名(不含临时目录路径) | ||||||
|  |                         zos.putNextEntry(new ZipEntry(file.getName())); | ||||||
|  |                         try (InputStream in = new FileInputStream(file)) { | ||||||
|  |                             byte[] buffer = new byte[1024]; | ||||||
|  |                             int len; | ||||||
|  |                             while ((len = in.read(buffer)) != -1) { | ||||||
|  |                                 zos.write(buffer, 0, len); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         zos.closeEntry(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } finally { | ||||||
|  |             // 5. 清理临时目录 | ||||||
|  |             FileUtils.deleteQuietly(tempDir); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 下载文件到本地临时目录(根据实际存储类型调整,如OSS、本地文件系统) | ||||||
|  |      */ | ||||||
|  |     private void downloadFile(String fileUrl, File destFile) throws Exception { | ||||||
|  |         // 示例:从URL下载(若为OSS,使用OSS SDK的getObject方法) | ||||||
|  |         // 创建HTTP客户端(设置超时时间) | ||||||
|  |         HttpClient client = HttpClient.newBuilder() | ||||||
|  |             .connectTimeout(Duration.ofMinutes(5)) // 连接超时 | ||||||
|  |             .build(); | ||||||
|  |  | ||||||
|  |         // 创建HTTP请求 | ||||||
|  |         HttpRequest request = HttpRequest.newBuilder() | ||||||
|  |             .uri(URI.create(fileUrl)) // 转换为URI(比URL更推荐) | ||||||
|  |             .timeout(Duration.ofMinutes(10)) // 响应超时 | ||||||
|  |             .GET() | ||||||
|  |             .build(); | ||||||
|  |  | ||||||
|  |         // 发送请求并将响应体写入目标文件 | ||||||
|  |         HttpResponse<Path> response = client.send( | ||||||
|  |             request, | ||||||
|  |             HttpResponse.BodyHandlers.ofFile(destFile.toPath()) // 直接写入文件路径 | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         // 检查响应状态(200表示成功) | ||||||
|  |         if (response.statusCode() != 200) { | ||||||
|  |             throw new RuntimeException("文件下载失败,URL: " + fileUrl + ",状态码: " + response.statusCode()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) |      * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) | ||||||
|      * 正常使用只需#processEvent.flowCode=='leave1' |      * 正常使用只需#processEvent.flowCode=='leave1' | ||||||
|  | |||||||
| @ -1,39 +0,0 @@ | |||||||
| package org.dromara.facility.domain.vo.matrix; |  | ||||||
|  |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.NoArgsConstructor; |  | ||||||
| import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryStructureVo; |  | ||||||
|  |  | ||||||
| import java.io.Serial; |  | ||||||
| import java.io.Serializable; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lilemy |  | ||||||
|  * @date 2025-08-23 01:17 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @NoArgsConstructor |  | ||||||
| @AllArgsConstructor |  | ||||||
| public class FacMatrixStructureVo implements Serializable { |  | ||||||
|  |  | ||||||
|     @Serial |  | ||||||
|     private static final long serialVersionUID = 7526403047030009646L; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 主键 |  | ||||||
|      */ |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 方阵名称 |  | ||||||
|      */ |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 分项工程 |  | ||||||
|      */ |  | ||||||
|     private List<PgsProgressCategoryStructureVo> children; |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @ -847,7 +847,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan | |||||||
|         // 根据类型,更新对应数据 |         // 根据类型,更新对应数据 | ||||||
|         if (type.equals(RecognizerTypeEnum.HOLE.getValue())) { |         if (type.equals(RecognizerTypeEnum.HOLE.getValue())) { | ||||||
|             photovoltaicPanelPointService.updateFinishNumberByCoordinate(projectIds, matchPoints); |             photovoltaicPanelPointService.updateFinishNumberByCoordinate(projectIds, matchPoints); | ||||||
|         } else if (type.equals(RecognizerTypeEnum.PILE.getValue())) { |         } else if (type.equals(RecognizerTypeEnum.COLUMN.getValue())) { | ||||||
|             photovoltaicPanelColumnService.updateFinishNumberByCoordinate(projectIds, matchPoints); |             photovoltaicPanelColumnService.updateFinishNumberByCoordinate(projectIds, matchPoints); | ||||||
|         } else if (type.equals(RecognizerTypeEnum.BRACKET.getValue())) { |         } else if (type.equals(RecognizerTypeEnum.BRACKET.getValue())) { | ||||||
|             photovoltaicPanelSupportService.updateFinishNumberByCoordinate(projectIds, matchPoints); |             photovoltaicPanelSupportService.updateFinishNumberByCoordinate(projectIds, matchPoints); | ||||||
| @ -871,7 +871,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan | |||||||
|                 return list.stream().map(point -> |                 return list.stream().map(point -> | ||||||
|                     new IdCoordinatePoint(point.getId(), point.getPositions())).toList(); |                     new IdCoordinatePoint(point.getId(), point.getPositions())).toList(); | ||||||
|             } |             } | ||||||
|         } else if (type.equals(RecognizerTypeEnum.PILE.getValue())) { |         } else if (type.equals(RecognizerTypeEnum.COLUMN.getValue())) { | ||||||
|             List<FacPhotovoltaicPanelColumn> list = photovoltaicPanelColumnService.lambdaQuery() |             List<FacPhotovoltaicPanelColumn> list = photovoltaicPanelColumnService.lambdaQuery() | ||||||
|                 .in(FacPhotovoltaicPanelColumn::getProjectId, projectIds) |                 .in(FacPhotovoltaicPanelColumn::getProjectId, projectIds) | ||||||
|                 .ne(FacPhotovoltaicPanelColumn::getStatus, FacFinishStatusEnum.FINISH.getValue()) |                 .ne(FacPhotovoltaicPanelColumn::getStatus, FacFinishStatusEnum.FINISH.getValue()) | ||||||
|  | |||||||
| @ -61,7 +61,7 @@ public class GpsEquipmentSonController extends BaseController { | |||||||
|     /** |     /** | ||||||
|      * 查询GPS设备定位日期信息列表 |      * 查询GPS设备定位日期信息列表 | ||||||
|      */ |      */ | ||||||
|     @SaCheckPermission("gps:equipmentSon:getRlList") | //    @SaCheckPermission("gps:equipmentSon:getRlList") | ||||||
|     @GetMapping("/getRlList") |     @GetMapping("/getRlList") | ||||||
|     public R<List<GpsStatusVo>> getRlList(GpsEquipmentSonBo bo) { |     public R<List<GpsStatusVo>> getRlList(GpsEquipmentSonBo bo) { | ||||||
|         return R.ok(gpsEquipmentSonService.getRlList(bo)); |         return R.ok(gpsEquipmentSonService.getRlList(bo)); | ||||||
|  | |||||||
| @ -81,31 +81,15 @@ public interface GpsEquipmentSonMapper extends BaseMapperPlus<GpsEquipmentSon, G | |||||||
|         "    rn = 1;") |         "    rn = 1;") | ||||||
|     List<GpsEquipmentSonVo> getUserListByProjectId(@Param("projectId") Long projectId, @Param("startTime") LocalDateTime startOfDay, @Param("endTime") LocalDateTime now); |     List<GpsEquipmentSonVo> getUserListByProjectId(@Param("projectId") Long projectId, @Param("startTime") LocalDateTime startOfDay, @Param("endTime") LocalDateTime now); | ||||||
|  |  | ||||||
|     @Select("WITH RECURSIVE date_range AS (\n" + |     @Select("SELECT\n" + | ||||||
|         "    -- 1. 初始化开始日期(取startTime的“年月日”部分,忽略时分秒)\n" + |         "  DATE(create_time) AS riqi,\n" + | ||||||
|         "    SELECT DATE(#{bo.startTime}) AS stat_date\n" + |         "  COUNT(id) AS count \n" + | ||||||
|         "    UNION ALL\n" + |         "FROM\n" + | ||||||
|         "    -- 2. 递归生成后续日期,直到不超过endTime的“年月日”\n" + |         "  gps_equipment_son\n" + | ||||||
|         "    SELECT DATE_ADD(stat_date, INTERVAL 1 DAY)\n" + |         "WHERE\n" + | ||||||
|         "    FROM date_range\n" + |         "  project_id = #{bo.projectId}\n" + | ||||||
|         "    WHERE stat_date < DATE(#{bo.endTime})\n" + |         "  AND client_id = #{bo.clientId}\n" + | ||||||
|         ")\n" + |         "  AND create_time BETWEEN #{bo.startTime} AND #{bo.endTime}\n" + | ||||||
|         "\n" + |         "  GROUP BY DATE(create_time)") | ||||||
|         "SELECT \n" + |  | ||||||
|         "    dr.stat_date AS riqi,  -- 统计日期(格式:YYYY-MM-DD)\n" + |  | ||||||
|         "    COUNT(ges.id) AS count  -- 当天符合条件的记录数\n" + |  | ||||||
|         "FROM date_range dr\n" + |  | ||||||
|         "LEFT JOIN (\n" + |  | ||||||
|         "    SELECT \n" + |  | ||||||
|         "        DATE(create_time) AS data_date,  -- 提取创建时间的“年月日”\n" + |  | ||||||
|         "        id  -- 仅需主键用于计数(减少数据传输)\n" + |  | ||||||
|         "    FROM gps_equipment_son\n" + |  | ||||||
|         "    WHERE \n" + |  | ||||||
|         "        project_id = #{bo.projectId}        -- 匹配项目ID\n" + |  | ||||||
|         "        AND client_id =#{bo.clientId}            -- 客户端ID为空\n" + |  | ||||||
|         "        AND create_time BETWEEN #{bo.startTime} AND #{bo.endTime}  -- 时间范围\n" + |  | ||||||
|         ") ges ON dr.stat_date = ges.data_date  -- 按日期关联\n" + |  | ||||||
|         "GROUP BY dr.stat_date  -- 按统计日期分组\n" + |  | ||||||
|         "ORDER BY dr.stat_date;  -- 按日期升序排列") |  | ||||||
|     List<GpsStatusVo> getRlList(@Param("bo") GpsEquipmentSonBo bo); |     List<GpsStatusVo> getRlList(@Param("bo") GpsEquipmentSonBo bo); | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ package org.dromara.job.attendance; | |||||||
| import cn.hutool.core.collection.CollectionUtil; | import cn.hutool.core.collection.CollectionUtil; | ||||||
| import cn.hutool.core.date.DateUtil; | import cn.hutool.core.date.DateUtil; | ||||||
| import com.aizuda.snailjob.client.job.core.annotation.JobExecutor; | import com.aizuda.snailjob.client.job.core.annotation.JobExecutor; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| @ -120,11 +121,23 @@ public class AttendanceJob { | |||||||
| //                //查询项目下的关联人员 | //                //查询项目下的关联人员 | ||||||
| //                List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(Wrappers.lambdaQuery(BusUserProjectRelevancy.class) | //                List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(Wrappers.lambdaQuery(BusUserProjectRelevancy.class) | ||||||
| //                    .eq(BusUserProjectRelevancy::getProjectId, rule.getProjectId())); | //                    .eq(BusUserProjectRelevancy::getProjectId, rule.getProjectId())); | ||||||
|                 List<SubConstructionUser> constructionUsers = constructionUserService.list(Wrappers.<SubConstructionUser>lambdaQuery() |                 LambdaQueryWrapper<SubConstructionUser> queryWrapper = new LambdaQueryWrapper<>(); | ||||||
|                     .eq(SubConstructionUser::getProjectId, rule.getProjectId()) |  | ||||||
|                     .isNotNull(SubConstructionUser::getTeamId) |                 // 拼接条件:(role = 1 AND teamId IS NOT NULL) OR (role IN (2)) | ||||||
|                     .eq(SubConstructionUser::getUserRole, "0")  //0-施工人员 1-管理人员 2-分包管理人员 |                 queryWrapper.eq(SubConstructionUser::getProjectId, rule.getProjectId()) // 全局条件:projectId必选 | ||||||
|                 ); |                     // 外层nested:包裹整个OR条件块 | ||||||
|  |                     .nested(w -> | ||||||
|  |                         // 内层nested:强制 (user_role=0 AND team_id IS NOT NULL) 作为一个整体 | ||||||
|  |                         w.nested(inner -> inner | ||||||
|  |                                 .eq(SubConstructionUser::getUserRole, "0") | ||||||
|  |                                 .isNotNull(SubConstructionUser::getTeamId) | ||||||
|  |                             ) | ||||||
|  |                             .or() // 连接两个子条件 | ||||||
|  |                             .in(SubConstructionUser::getUserRole, Arrays.asList("1", "2")) | ||||||
|  |                     ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 List<SubConstructionUser> constructionUsers = constructionUserService.list(queryWrapper); | ||||||
|  |  | ||||||
|  |  | ||||||
|                 //查询当天已打上班卡人员 |                 //查询当天已打上班卡人员 | ||||||
| @ -235,11 +248,23 @@ public class AttendanceJob { | |||||||
|                 //查询项目下的关联人员 |                 //查询项目下的关联人员 | ||||||
| //                List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(Wrappers.lambdaQuery(BusUserProjectRelevancy.class) | //                List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(Wrappers.lambdaQuery(BusUserProjectRelevancy.class) | ||||||
| //                    .eq(BusUserProjectRelevancy::getProjectId, rule.getProjectId())); | //                    .eq(BusUserProjectRelevancy::getProjectId, rule.getProjectId())); | ||||||
|                 List<SubConstructionUser> constructionUsers = constructionUserService.list(Wrappers.<SubConstructionUser>lambdaQuery() |                 LambdaQueryWrapper<SubConstructionUser> queryWrapper = new LambdaQueryWrapper<>(); | ||||||
|                     .eq(SubConstructionUser::getProjectId, rule.getProjectId()) |  | ||||||
|                     .isNotNull(SubConstructionUser::getTeamId) |                 // 拼接条件:(role = 1 AND teamId IS NOT NULL) OR (role IN (2)) | ||||||
|                     .eq(SubConstructionUser::getUserRole, "0")  //0-施工人员 1-管理人员 2-分包管理人员 |                 queryWrapper.eq(SubConstructionUser::getProjectId, rule.getProjectId()) // 全局条件:projectId必选 | ||||||
|                 ); |                     // 外层nested:包裹整个OR条件块 | ||||||
|  |                     .nested(w -> | ||||||
|  |                         // 内层nested:强制 (user_role=0 AND team_id IS NOT NULL) 作为一个整体 | ||||||
|  |                         w.nested(inner -> inner | ||||||
|  |                                 .eq(SubConstructionUser::getUserRole, "0") | ||||||
|  |                                 .isNotNull(SubConstructionUser::getTeamId) | ||||||
|  |                             ) | ||||||
|  |                             .or() // 连接两个子条件 | ||||||
|  |                             .in(SubConstructionUser::getUserRole, Arrays.asList("1", "2")) | ||||||
|  |                     ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 List<SubConstructionUser> constructionUsers = constructionUserService.list(queryWrapper); | ||||||
|                 //查询当天打卡人员 |                 //查询当天打卡人员 | ||||||
|                 List<BusAttendance> allAttendanceList = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class) |                 List<BusAttendance> allAttendanceList = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class) | ||||||
|                     .eq(BusAttendance::getClockDate, date) |                     .eq(BusAttendance::getClockDate, date) | ||||||
|  | |||||||
| @ -1,45 +0,0 @@ | |||||||
| package org.dromara.job.once; |  | ||||||
|  |  | ||||||
| import jakarta.annotation.Resource; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| import org.dromara.manager.ys7manager.Ys7Manager; |  | ||||||
| import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo; |  | ||||||
| import org.dromara.other.service.IOthYs7DeviceService; |  | ||||||
| import org.springframework.boot.CommandLineRunner; |  | ||||||
| import org.springframework.stereotype.Component; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * 同步摄像头设备数据 |  | ||||||
|  * |  | ||||||
|  * @author lilemy |  | ||||||
|  * @date 2025/6/13 11:08 |  | ||||||
|  */ |  | ||||||
| @Slf4j |  | ||||||
| @Component |  | ||||||
| public class FullSyncYs7DeviceData implements CommandLineRunner { |  | ||||||
|  |  | ||||||
|     @Resource |  | ||||||
|     private Ys7Manager ys7Manager; |  | ||||||
|  |  | ||||||
|     @Resource |  | ||||||
|     private IOthYs7DeviceService ys7DeviceService; |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public void run(String... args) throws Exception { |  | ||||||
|         log.info("开始同步摄像头设备数据"); |  | ||||||
|         try { |  | ||||||
|             List<Ys7QueryDeviceResponseVo> ys7QueryDeviceList = ys7Manager.queryAllDeviceList(); |  | ||||||
|             Boolean result = ys7DeviceService.saveOrUpdateByDeviceList(ys7QueryDeviceList); |  | ||||||
|             if (result) { |  | ||||||
|                 log.info("摄像头设备数据同步成功"); |  | ||||||
|             } else { |  | ||||||
|                 log.info("没有需要同步的设备"); |  | ||||||
|             } |  | ||||||
|         } catch (Exception e) { |  | ||||||
|             log.info("摄像头设备数据同步失败", e); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -21,6 +21,7 @@ import java.net.URI; | |||||||
| import java.net.URISyntaxException; | import java.net.URISyntaxException; | ||||||
| import java.net.URLConnection; | import java.net.URLConnection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @author lilemy |  * @author lilemy | ||||||
| @ -82,7 +83,9 @@ public class RecognizerManager { | |||||||
|             // 画矩形框 |             // 画矩形框 | ||||||
|             g.drawRect(x, y, w, h); |             g.drawRect(x, y, w, h); | ||||||
|             // 写文字(类型 + 置信度) |             // 写文字(类型 + 置信度) | ||||||
|             String label = target.getType() + " (" + String.format("%.2f", target.getScore()) + ")"; |             RecognizerTypeEnum recognizerTypeEnum = RecognizerTypeEnum.fromValue(target.getType()); | ||||||
|  |             String label = recognizerTypeEnum != null ? Objects.requireNonNull(recognizerTypeEnum).getText() : target.getType() | ||||||
|  |                 + " (" + String.format("%.2f", target.getScore()) + ")"; | ||||||
|             g.drawString(label, x, y - 5); |             g.drawString(label, x, y - 5); | ||||||
|         } |         } | ||||||
|         g.dispose(); |         g.dispose(); | ||||||
|  | |||||||
| @ -12,15 +12,17 @@ import java.util.stream.Collectors; | |||||||
| @Getter | @Getter | ||||||
| public enum RecognizerTypeEnum { | public enum RecognizerTypeEnum { | ||||||
|  |  | ||||||
|     HARDHAT("安全帽识别", "nohelmet", "1"), |     WEARING_ALL("穿戴安全帽反光衣", "wearingall", ""), | ||||||
|     VEST("反光背心识别", "novest", ""), |     NO_EQUIPMENT("没穿安全帽反光衣", "noequipment", "1"), | ||||||
|     SMOKING("吸烟识别", "smoking", "3"), |     NO_HELMET("有反光衣没安全帽", "nohelmet", ""), | ||||||
|     FIRE("火焰识别", "fire", "16"), |     NO_VEST("有安全帽没反光衣", "novest", ""), | ||||||
|     SMOKE("烟雾识别","smoke",""), |     SMOKE("吸烟", "smoke", "3"), | ||||||
|     SOLAR("光伏板识别", "solar", ""), |     FIRE("火焰", "fire", "16"), | ||||||
|     BRACKET("光伏板支架识别", "bracket", ""), |     SMOGGY("烟雾", "smoggy", ""), | ||||||
|     PILE("光伏板立柱识别", "pile", ""), |     PANEL("光伏板", "solar", ""), | ||||||
|     HOLE("洞", "hole", ""); |     BRACKET("光伏板支架", "bracket", ""), | ||||||
|  |     COLUMN("光伏板桩", "column", ""), | ||||||
|  |     HOLE("光伏板孔", "hole", ""); | ||||||
|  |  | ||||||
|     private final String text; |     private final String text; | ||||||
|  |  | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ import org.springframework.context.annotation.Configuration; | |||||||
| import org.springframework.web.socket.server.standard.ServerEndpointExporter; | import org.springframework.web.socket.server.standard.ServerEndpointExporter; | ||||||
|  |  | ||||||
|  |  | ||||||
| @Configuration | //@Configuration | ||||||
| public class WebSocketConfig { | public class WebSocketConfig { | ||||||
|     @Bean |     @Bean | ||||||
|     public ServerEndpointExporter serverEndpointExporter() { |     public ServerEndpointExporter serverEndpointExporter() { | ||||||
|  | |||||||
| @ -220,7 +220,17 @@ public class OthYs7DeviceImgServiceImpl extends ServiceImpl<OthYs7DeviceImgMappe | |||||||
|                 othYs7DeviceImg.setDeviceName(img.getDeviceName()); |                 othYs7DeviceImg.setDeviceName(img.getDeviceName()); | ||||||
|                 othYs7DeviceImg.setUrl(ossUrl); |                 othYs7DeviceImg.setUrl(ossUrl); | ||||||
|                 // 将抓取的图片进行识别 |                 // 将抓取的图片进行识别 | ||||||
|                 List<RecognizerTypeEnum> recTypes = List.of(RecognizerTypeEnum.HARDHAT, RecognizerTypeEnum.SMOKING, RecognizerTypeEnum.FIRE); | //                List<RecognizerTypeEnum> recTypes = List.of(RecognizerTypeEnum.NO_EQUIPMENT, | ||||||
|  | //                    RecognizerTypeEnum.NO_HELMET, | ||||||
|  | //                    RecognizerTypeEnum.NO_EQUIPMENT, | ||||||
|  | //                    RecognizerTypeEnum.NO_VEST, | ||||||
|  | //                    RecognizerTypeEnum.SMOKE, | ||||||
|  | //                    RecognizerTypeEnum.FIRE); | ||||||
|  |                 List<RecognizerTypeEnum> recTypes = List.of( | ||||||
|  |                     RecognizerTypeEnum.COLUMN, | ||||||
|  |                     RecognizerTypeEnum.PANEL, | ||||||
|  |                     RecognizerTypeEnum.BRACKET, | ||||||
|  |                     RecognizerTypeEnum.HOLE); | ||||||
|                 RecognizeVo recognizeVo = null; |                 RecognizeVo recognizeVo = null; | ||||||
|                 try { |                 try { | ||||||
|                     recognizeVo = recognizerManager.recognize(ossUrl, recTypes); |                     recognizeVo = recognizerManager.recognize(ossUrl, recTypes); | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.dromara.contractor.domain.SubContractor; | ||||||
| import org.dromara.contractor.service.ISubContractorService; | import org.dromara.contractor.service.ISubContractorService; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.dromara.out.domain.bo.OutSettlementValueSubcontractBo; | import org.dromara.out.domain.bo.OutSettlementValueSubcontractBo; | ||||||
| @ -59,7 +60,11 @@ public class OutSettlementValueSubcontractServiceImpl extends ServiceImpl<OutSet | |||||||
|         LambdaQueryWrapper<OutSettlementValueSubcontract> lqw = buildQueryWrapper(bo); |         LambdaQueryWrapper<OutSettlementValueSubcontract> lqw = buildQueryWrapper(bo); | ||||||
|         Page<OutSettlementValueSubcontractVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); |         Page<OutSettlementValueSubcontractVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); | ||||||
|         result.getRecords().forEach(e -> { |         result.getRecords().forEach(e -> { | ||||||
|             e.setContractorName(contractorService.queryById(e.getContractorId()).getName()); |             SubContractor contractor = contractorService.getById(e.getContractorId()); | ||||||
|  |             if(contractor != null) { | ||||||
|  |                 e.setContractorName(contractor.getName()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|         }); |         }); | ||||||
|         return TableDataInfo.build(result); |         return TableDataInfo.build(result); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,37 +0,0 @@ | |||||||
| package org.dromara.progress.domain.vo.progresscategory; |  | ||||||
|  |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.NoArgsConstructor; |  | ||||||
|  |  | ||||||
| import java.io.Serial; |  | ||||||
| import java.io.Serializable; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lilemy |  | ||||||
|  * @date 2025-08-23 01:19 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @NoArgsConstructor |  | ||||||
| @AllArgsConstructor |  | ||||||
| public class PgsProgressCategoryStructureVo implements Serializable { |  | ||||||
|  |  | ||||||
|     @Serial |  | ||||||
|     private static final long serialVersionUID = -8392912623299656962L; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 主键id |  | ||||||
|      */ |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 类别名称 |  | ||||||
|      */ |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 子类别 |  | ||||||
|      */ |  | ||||||
|     private List<PgsProgressCategoryStructureVo> children; |  | ||||||
| } |  | ||||||
| @ -1149,8 +1149,8 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla | |||||||
|         } |         } | ||||||
|         List<Long> projectIds = projects.stream().map(BusProject::getId).distinct().toList(); |         List<Long> projectIds = projects.stream().map(BusProject::getId).distinct().toList(); | ||||||
|         // 识别类型:洞、桩、架、架子 |         // 识别类型:洞、桩、架、架子 | ||||||
|         List<RecognizerTypeEnum> enumList = List.of(RecognizerTypeEnum.HOLE, RecognizerTypeEnum.SOLAR, |         List<RecognizerTypeEnum> enumList = List.of(RecognizerTypeEnum.HOLE, RecognizerTypeEnum.PANEL, | ||||||
|             RecognizerTypeEnum.PILE, RecognizerTypeEnum.BRACKET); |             RecognizerTypeEnum.COLUMN, RecognizerTypeEnum.BRACKET); | ||||||
|         // 调用识别算法 |         // 调用识别算法 | ||||||
|         RecognizeVo recognizeVo = null; |         RecognizeVo recognizeVo = null; | ||||||
|         try { |         try { | ||||||
| @ -1187,10 +1187,10 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla | |||||||
|             } |             } | ||||||
|             log.info("类型:{},识别到的设施:{},转换坐标:{}", type, value, coordinateList); |             log.info("类型:{},识别到的设施:{},转换坐标:{}", type, value, coordinateList); | ||||||
|             // 处理对应设施 |             // 处理对应设施 | ||||||
|             if (type.equals(RecognizerTypeEnum.SOLAR.getValue())) { |             if (type.equals(RecognizerTypeEnum.PANEL.getValue())) { | ||||||
|                 photovoltaicPanelService.updateFinishNumberByCoordinate(projectIds, coordinateList); |                 photovoltaicPanelService.updateFinishNumberByCoordinate(projectIds, coordinateList); | ||||||
|             } else if (type.equals(RecognizerTypeEnum.HOLE.getValue()) |             } else if (type.equals(RecognizerTypeEnum.HOLE.getValue()) | ||||||
|                 || type.equals(RecognizerTypeEnum.PILE.getValue()) |                 || type.equals(RecognizerTypeEnum.COLUMN.getValue()) | ||||||
|                 || type.equals(RecognizerTypeEnum.BRACKET.getValue())) { |                 || type.equals(RecognizerTypeEnum.BRACKET.getValue())) { | ||||||
|                 photovoltaicPanelPartsService.updateFinishNumberByCoordinate(projectIds, coordinateList, type); |                 photovoltaicPanelPartsService.updateFinishNumberByCoordinate(projectIds, coordinateList, type); | ||||||
|             } else { |             } else { | ||||||
|  | |||||||
| @ -162,6 +162,12 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe | |||||||
|         Long id = progressPlan.getId(); |         Long id = progressPlan.getId(); | ||||||
|         List<PgsProgressPlanDetailCreateDto> detailList = req.getDetailList(); |         List<PgsProgressPlanDetailCreateDto> detailList = req.getDetailList(); | ||||||
|         if (CollUtil.isNotEmpty(detailList)) { |         if (CollUtil.isNotEmpty(detailList)) { | ||||||
|  |             // 判断详情数量是否合法 | ||||||
|  |             boolean isAnyEmpty = detailList.stream() | ||||||
|  |                 .allMatch(detail -> detail.getPlanNumber().compareTo(BigDecimal.ZERO) <= 0); | ||||||
|  |             if (isAnyEmpty) { | ||||||
|  |                 throw new ServiceException("新增进度计划详情失败,请进行均分", HttpStatus.BAD_REQUEST); | ||||||
|  |             } | ||||||
|             List<PgsProgressPlanDetail> newDetailList = detailList.stream().map(detail -> { |             List<PgsProgressPlanDetail> newDetailList = detailList.stream().map(detail -> { | ||||||
|                 PgsProgressPlanDetail progressPlanDetail = new PgsProgressPlanDetail(); |                 PgsProgressPlanDetail progressPlanDetail = new PgsProgressPlanDetail(); | ||||||
|                 BeanUtils.copyProperties(detail, progressPlanDetail); |                 BeanUtils.copyProperties(detail, progressPlanDetail); | ||||||
|  | |||||||
| @ -91,4 +91,17 @@ public class BusAttendanceMachineController extends BaseController { | |||||||
|                           @PathVariable Long[] ids) { |                           @PathVariable Long[] ids) { | ||||||
|         return toAjax(busAttendanceMachineService.deleteWithValidByIds(List.of(ids), true)); |         return toAjax(busAttendanceMachineService.deleteWithValidByIds(List.of(ids), true)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 批量重新下发 | ||||||
|  |      */ | ||||||
|  |     @SaCheckPermission("project:attendanceMachine:reissue") | ||||||
|  |     @RepeatSubmit() | ||||||
|  |     @PostMapping("/reissue/{ids}") | ||||||
|  |     public R<Void> reissue(@NotEmpty(message = "主键不能为空") | ||||||
|  |                                @PathVariable Long[] ids){ | ||||||
|  |         busAttendanceMachineService.reissue(List.of(ids)); | ||||||
|  |         return R.ok("已开始执行,请稍后刷新"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package org.dromara.project.controller; | package org.dromara.project.controller; | ||||||
|  |  | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.NotEmpty; | import jakarta.validation.constraints.NotEmpty; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
| @ -13,10 +14,12 @@ import org.dromara.common.log.enums.BusinessType; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.web.core.BaseController; | import org.dromara.common.web.core.BaseController; | ||||||
|  | import org.dromara.project.domain.BusProjectTeam; | ||||||
| import org.dromara.project.domain.dto.leave.BusLeaveManagerReviewReq; | import org.dromara.project.domain.dto.leave.BusLeaveManagerReviewReq; | ||||||
| import org.dromara.project.domain.dto.leave.BusLeaveQueryReq; | import org.dromara.project.domain.dto.leave.BusLeaveQueryReq; | ||||||
| import org.dromara.project.domain.vo.leave.BusLeaveVo; | import org.dromara.project.domain.vo.leave.BusLeaveVo; | ||||||
| import org.dromara.project.service.IBusLeaveService; | import org.dromara.project.service.IBusLeaveService; | ||||||
|  | import org.dromara.project.service.IBusProjectTeamService; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
| @ -36,6 +39,8 @@ public class BusLeaveController extends BaseController { | |||||||
|  |  | ||||||
|     private final IBusLeaveService busLeaveService; |     private final IBusLeaveService busLeaveService; | ||||||
|  |  | ||||||
|  |     private final IBusProjectTeamService projectTeamService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询施工人员请假申请列表 |      * 查询施工人员请假申请列表 | ||||||
|      */ |      */ | ||||||
| @ -91,4 +96,17 @@ public class BusLeaveController extends BaseController { | |||||||
|                           @PathVariable Long[] ids) { |                           @PathVariable Long[] ids) { | ||||||
|         return toAjax(busLeaveService.deleteWithValidByIds(List.of(ids), true)); |         return toAjax(busLeaveService.deleteWithValidByIds(List.of(ids), true)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取项目下所有班组 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/teamList") | ||||||
|  |     public R<List<BusProjectTeam>> add(Long projectId) { | ||||||
|  |         List<BusProjectTeam> list = projectTeamService.list(Wrappers.lambdaQuery(BusProjectTeam.class) | ||||||
|  |             .select(BusProjectTeam::getId, BusProjectTeam::getTeamName) | ||||||
|  |             .eq(BusProjectTeam::getProjectId, projectId) | ||||||
|  |         ); | ||||||
|  |         return R.ok(list); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package org.dromara.project.controller; | package org.dromara.project.controller; | ||||||
|  |  | ||||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | import cn.dev33.satoken.annotation.SaCheckPermission; | ||||||
|  | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import jakarta.servlet.http.HttpServletResponse; | import jakarta.servlet.http.HttpServletResponse; | ||||||
| import jakarta.validation.constraints.NotEmpty; | import jakarta.validation.constraints.NotEmpty; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
| @ -13,9 +14,12 @@ import org.dromara.common.log.enums.BusinessType; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.web.core.BaseController; | import org.dromara.common.web.core.BaseController; | ||||||
|  | import org.dromara.project.domain.BusProjectTeam; | ||||||
|  | import org.dromara.project.domain.dto.reissuecard.BusReissueCardAddReq; | ||||||
| import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq; | import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq; | ||||||
| import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq; | import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq; | ||||||
| import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo; | import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo; | ||||||
|  | import org.dromara.project.service.IBusProjectTeamService; | ||||||
| import org.dromara.project.service.IBusReissueCardService; | import org.dromara.project.service.IBusReissueCardService; | ||||||
| import org.springframework.validation.annotation.Validated; | import org.springframework.validation.annotation.Validated; | ||||||
| import org.springframework.web.bind.annotation.*; | import org.springframework.web.bind.annotation.*; | ||||||
| @ -36,6 +40,8 @@ public class BusReissueCardController extends BaseController { | |||||||
|  |  | ||||||
|     private final IBusReissueCardService busReissueCardService; |     private final IBusReissueCardService busReissueCardService; | ||||||
|  |  | ||||||
|  |     private final IBusProjectTeamService projectTeamService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询施工人员补卡申请列表 |      * 查询施工人员补卡申请列表 | ||||||
|      */ |      */ | ||||||
| @ -91,4 +97,16 @@ public class BusReissueCardController extends BaseController { | |||||||
|                           @PathVariable Long[] ids) { |                           @PathVariable Long[] ids) { | ||||||
|         return toAjax(busReissueCardService.deleteWithValidByIds(List.of(ids), true)); |         return toAjax(busReissueCardService.deleteWithValidByIds(List.of(ids), true)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取项目下所有班组 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/teamList") | ||||||
|  |     public R<List<BusProjectTeam>> add(Long projectId) { | ||||||
|  |         List<BusProjectTeam> list = projectTeamService.list(Wrappers.lambdaQuery(BusProjectTeam.class) | ||||||
|  |             .select(BusProjectTeam::getId, BusProjectTeam::getTeamName) | ||||||
|  |             .eq(BusProjectTeam::getProjectId, projectId) | ||||||
|  |         ); | ||||||
|  |         return R.ok(list); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -128,8 +128,8 @@ public class BusAttendanceAppController extends BaseController { | |||||||
|      * 获取用户打卡异常记录 |      * 获取用户打卡异常记录 | ||||||
|      */ |      */ | ||||||
|     @GetMapping("/getAbnormalAttendance/{projectId}") |     @GetMapping("/getAbnormalAttendance/{projectId}") | ||||||
|     public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId, PageQuery pageQuery){ |     public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId,String handle, PageQuery pageQuery){ | ||||||
|         return attendanceService.getAbnormalAttendance(projectId,pageQuery); |         return attendanceService.getAbnormalAttendance(projectId,handle,pageQuery); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -157,4 +157,9 @@ public class BusProjectUpdateReq implements Serializable { | |||||||
|      */ |      */ | ||||||
|     private List<Long> deptIds; |     private List<Long> deptIds; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 省份 | ||||||
|  |      */ | ||||||
|  |     private String province; | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| package org.dromara.project.domain.vo.project; | package org.dromara.project.domain.vo.project; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
| import java.io.Serial; | import java.io.Serial; | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
| @ -11,6 +13,8 @@ import java.util.List; | |||||||
|  * @date 2025-08-23 01:14 |  * @date 2025-08-23 01:14 | ||||||
|  */ |  */ | ||||||
| @Data | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | @AllArgsConstructor | ||||||
| public class BusProjectStructureVo implements Serializable { | public class BusProjectStructureVo implements Serializable { | ||||||
|  |  | ||||||
|     @Serial |     @Serial | ||||||
| @ -29,5 +33,5 @@ public class BusProjectStructureVo implements Serializable { | |||||||
|     /** |     /** | ||||||
|      * 子项目列表 |      * 子项目列表 | ||||||
|      */ |      */ | ||||||
|     private List<BusSubProjectStructureVo> children; |     private List<BusProjectStructureVo> children; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,38 +0,0 @@ | |||||||
| package org.dromara.project.domain.vo.project; |  | ||||||
|  |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.NoArgsConstructor; |  | ||||||
| import org.dromara.facility.domain.vo.matrix.FacMatrixStructureVo; |  | ||||||
|  |  | ||||||
| import java.io.Serial; |  | ||||||
| import java.io.Serializable; |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @author lilemy |  | ||||||
|  * @date 2025-08-23 01:15 |  | ||||||
|  */ |  | ||||||
| @Data |  | ||||||
| @NoArgsConstructor |  | ||||||
| @AllArgsConstructor |  | ||||||
| public class BusSubProjectStructureVo implements Serializable { |  | ||||||
|  |  | ||||||
|     @Serial |  | ||||||
|     private static final long serialVersionUID = 6993209784456857540L; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 项目主键 |  | ||||||
|      */ |  | ||||||
|     private Long id; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 项目名称 |  | ||||||
|      */ |  | ||||||
|     private String name; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 方阵列表 |  | ||||||
|      */ |  | ||||||
|     private List<FacMatrixStructureVo> children; |  | ||||||
| } |  | ||||||
| @ -1,9 +1,12 @@ | |||||||
| package org.dromara.project.mapper; | package org.dromara.project.mapper; | ||||||
|  |  | ||||||
|  | import org.apache.ibatis.annotations.Param; | ||||||
| import org.dromara.project.domain.BusProjectTeam; | import org.dromara.project.domain.BusProjectTeam; | ||||||
| import org.dromara.project.domain.vo.projectteam.BusProjectTeamVo; | import org.dromara.project.domain.vo.projectteam.BusProjectTeamVo; | ||||||
| import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 项目班组Mapper接口 |  * 项目班组Mapper接口 | ||||||
|  * |  * | ||||||
| @ -12,4 +15,5 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | |||||||
|  */ |  */ | ||||||
| public interface BusProjectTeamMapper extends BaseMapperPlus<BusProjectTeam, BusProjectTeamVo> { | public interface BusProjectTeamMapper extends BaseMapperPlus<BusProjectTeam, BusProjectTeamVo> { | ||||||
|  |  | ||||||
|  |     List<BusProjectTeam> selectByPunchRangeIn(@Param("punchRangeList") List<String> punchRangeList); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,12 +1,15 @@ | |||||||
| package org.dromara.project.service; | package org.dromara.project.service; | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.extension.service.IService; | import com.baomidou.mybatisplus.extension.service.IService; | ||||||
|  | import jakarta.validation.constraints.NotEmpty; | ||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.project.domain.BusAttendanceMachine; | import org.dromara.project.domain.BusAttendanceMachine; | ||||||
| import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq; | import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineQueryReq; | ||||||
| import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq; | import org.dromara.project.domain.dto.attendancemachine.BusAttendanceMachineUpdateReq; | ||||||
| import org.dromara.project.domain.vo.BusAttendanceMachineVo; | import org.dromara.project.domain.vo.BusAttendanceMachineVo; | ||||||
|  | import org.springframework.scheduling.annotation.Async; | ||||||
|  | import org.springframework.web.bind.annotation.PathVariable; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @ -75,4 +78,7 @@ public interface IBusAttendanceMachineService extends IService<BusAttendanceMach | |||||||
|      * @return 是否删除成功 |      * @return 是否删除成功 | ||||||
|      */ |      */ | ||||||
|     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); |     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     void reissue(Collection<Long> ids); | ||||||
| } | } | ||||||
|  | |||||||
| @ -131,7 +131,7 @@ public interface IBusAttendanceService extends IService<BusAttendance>{ | |||||||
|     /** |     /** | ||||||
|      * 获取用户打卡异常记录 |      * 获取用户打卡异常记录 | ||||||
|      */ |      */ | ||||||
|     TableDataInfo<BusAttendanceVo> getAbnormalAttendance(@NotNull @PathVariable("projectId") Long projectId, PageQuery pageQuery); |     TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId,String handle, PageQuery pageQuery); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 统计指定日期的打卡人员 |      * 统计指定日期的打卡人员 | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||||
| import com.baomidou.mybatisplus.extension.service.IService; | import com.baomidou.mybatisplus.extension.service.IService; | ||||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||||
|  | import org.apache.ibatis.annotations.Param; | ||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.project.domain.BusProjectTeam; | import org.dromara.project.domain.BusProjectTeam; | ||||||
| @ -126,4 +127,6 @@ public interface IBusProjectTeamService extends IService<BusProjectTeam> { | |||||||
|     Boolean deleteUserId(Long id,Long userId); |     Boolean deleteUserId(Long id,Long userId); | ||||||
|  |  | ||||||
|     List<TeamManageVo> getManager(Long teamId); |     List<TeamManageVo> getManager(Long teamId); | ||||||
|  |  | ||||||
|  |     List<BusProjectTeam> selectByPunchRangeIn(List<String> punchRangeList); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package org.dromara.project.service.impl; | package org.dromara.project.service.impl; | ||||||
|  |  | ||||||
| import cn.hutool.core.collection.CollUtil; | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import cn.hutool.core.util.StrUtil; | ||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||||
| @ -28,13 +29,14 @@ import org.dromara.project.service.IBusAttendanceMachineService; | |||||||
| import org.dromara.project.service.IBusProjectService; | import org.dromara.project.service.IBusProjectService; | ||||||
| import org.dromara.project.service.IBusProjectTeamMemberService; | import org.dromara.project.service.IBusProjectTeamMemberService; | ||||||
| import org.dromara.project.service.IBusProjectTeamService; | import org.dromara.project.service.IBusProjectTeamService; | ||||||
|  | import org.dromara.system.domain.vo.SysOssVo; | ||||||
|  | import org.dromara.system.service.ISysOssService; | ||||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||||
|  | import org.springframework.context.annotation.Lazy; | ||||||
|  | import org.springframework.scheduling.annotation.Async; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
| import java.util.Arrays; | import java.util.*; | ||||||
| import java.util.Collection; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; |  | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -61,8 +63,14 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa | |||||||
|     private DeviceMessageSender deviceMessageSender; |     private DeviceMessageSender deviceMessageSender; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|  |     @Lazy | ||||||
|     private ISubConstructionUserService constructionUserService; |     private ISubConstructionUserService constructionUserService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     @Lazy | ||||||
|  |     private ISysOssService ossService; | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询考勤机 |      * 查询考勤机 | ||||||
|      * |      * | ||||||
| @ -300,4 +308,57 @@ public class BusAttendanceMachineServiceImpl extends ServiceImpl<BusAttendanceMa | |||||||
|         } |         } | ||||||
|         return baseMapper.deleteByIds(ids) > 0; |         return baseMapper.deleteByIds(ids) > 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Async | ||||||
|  |     @Override | ||||||
|  |     public void reissue(Collection<Long> ids) { | ||||||
|  |         List<BusAttendanceMachine> busAttendanceMachines = baseMapper.selectByIds(ids); | ||||||
|  |  | ||||||
|  |         for (BusAttendanceMachine machine : busAttendanceMachines) { | ||||||
|  |             String sn = machine.getSn(); | ||||||
|  |             try { | ||||||
|  |                 deviceMessageSender.deleteAllUsers(sn); | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 log.error("删除考勤人员异常", e); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             String teams = machine.getTeams(); | ||||||
|  |             if (StrUtil.isBlank(teams)) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             List<Long> oldTeamIds = Arrays.stream(teams.split(",")) | ||||||
|  |                 .map(Long::parseLong) | ||||||
|  |                 .distinct() | ||||||
|  |                 .toList(); | ||||||
|  |  | ||||||
|  |             List<Long> userIds = projectTeamMemberService.lambdaQuery() | ||||||
|  |                 .select(BusProjectTeamMember::getMemberId) | ||||||
|  |                 .in(BusProjectTeamMember::getTeamId, oldTeamIds) | ||||||
|  |                 .list() | ||||||
|  |                 .stream().map(BusProjectTeamMember::getMemberId) | ||||||
|  |                 .toList(); | ||||||
|  |             if (CollUtil.isEmpty(userIds)) { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             List<SubConstructionUser> users = constructionUserService.lambdaQuery() | ||||||
|  |                 .in(SubConstructionUser::getSysUserId, userIds) | ||||||
|  |                 .list(); | ||||||
|  |  | ||||||
|  |             Map<Long, String> faceMap = new HashMap<>(); | ||||||
|  |             List<String> list = users.stream().map(SubConstructionUser::getFacePic).filter(StrUtil::isNotBlank).toList(); | ||||||
|  |             if (CollUtil.isNotEmpty(list)) { | ||||||
|  |                 //转成Long的集合 | ||||||
|  |                 List<Long> list1 = list.stream().map(Long::parseLong).toList(); | ||||||
|  |                 List<SysOssVo> sysOssVos = ossService.listByIds(list1); | ||||||
|  |                 faceMap = sysOssVos.stream().collect(Collectors.toMap(SysOssVo::getOssId, SysOssVo::getUrl)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             for (SubConstructionUser user : users) { | ||||||
|  |                 String facePic = StrUtil.isBlank(user.getFacePic()) ? "" : faceMap.get(Long.valueOf(user.getFacePic())); | ||||||
|  |                 deviceMessageSender.sendPersonnelInformation(sn, user.getSysUserId().toString() | ||||||
|  |                     , user.getUserName(), facePic); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -353,7 +353,6 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B | |||||||
|                     throw new ServiceException("当前用户没有设置工资,禁止打卡", HttpStatus.ERROR); |                     throw new ServiceException("当前用户没有设置工资,禁止打卡", HttpStatus.ERROR); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // 判断用户是否已经被拉黑 |             // 判断用户是否已经被拉黑 | ||||||
|             constructionBlacklistService.validUserInBlacklist(constructionUser.getSysUserId(), req.getProjectId()); |             constructionBlacklistService.validUserInBlacklist(constructionUser.getSysUserId(), req.getProjectId()); | ||||||
|             Boolean result = false; |             Boolean result = false; | ||||||
| @ -793,7 +792,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B | |||||||
|  |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId, PageQuery pageQuery) { |     public TableDataInfo<BusAttendanceVo> getAbnormalAttendance(Long projectId,String handle, PageQuery pageQuery) { | ||||||
|  |  | ||||||
|         List<String> abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(), |         List<String> abnormalList = Arrays.asList(BusAttendanceClockStatusEnum.LATE.getValue(), | ||||||
|             BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(), |             BusAttendanceClockStatusEnum.LEAVEEARLY.getValue(), | ||||||
| @ -810,6 +809,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B | |||||||
|  |  | ||||||
|         IPage<BusAttendanceVo> busAttendanceVoIPage = baseMapper.selectVoPage(pageQuery.build(), Wrappers.lambdaQuery(BusAttendance.class) |         IPage<BusAttendanceVo> busAttendanceVoIPage = baseMapper.selectVoPage(pageQuery.build(), Wrappers.lambdaQuery(BusAttendance.class) | ||||||
|             .eq(BusAttendance::getUserId, userId) |             .eq(BusAttendance::getUserId, userId) | ||||||
|  |             .eq(StrUtil.isNotBlank(handle), BusAttendance::getHandle, handle) | ||||||
|             .eq(b, BusAttendance::getProjectId, projectId) |             .eq(b, BusAttendance::getProjectId, projectId) | ||||||
|             .in(BusAttendance::getClockStatus, abnormalList) |             .in(BusAttendance::getClockStatus, abnormalList) | ||||||
|             .ge(BusAttendance::getClockDate, LocalDate.now().minusDays(29)) |             .ge(BusAttendance::getClockDate, LocalDate.now().minusDays(29)) | ||||||
|  | |||||||
| @ -603,7 +603,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave> | |||||||
|                     .eq(BusAttendance::getUserId, busLeave.getUserId()) |                     .eq(BusAttendance::getUserId, busLeave.getUserId()) | ||||||
|                 ); |                 ); | ||||||
|                 for (BusAttendance attendance : list) { |                 for (BusAttendance attendance : list) { | ||||||
|                     attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue()); |                     attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); | ||||||
|                 } |                 } | ||||||
|                 if(!list.isEmpty()){ |                 if(!list.isEmpty()){ | ||||||
|                     attendanceService.updateBatchById(list); |                     attendanceService.updateBatchById(list); | ||||||
| @ -619,7 +619,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave> | |||||||
|                         .eq(BusAttendance::getUserId, busLeave.getUserId()) |                         .eq(BusAttendance::getUserId, busLeave.getUserId()) | ||||||
|                     ); |                     ); | ||||||
|                     for (BusAttendance attendance : list) { |                     for (BusAttendance attendance : list) { | ||||||
|                         attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue()); |                         attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); | ||||||
|                     } |                     } | ||||||
|                     if(!list.isEmpty()){ |                     if(!list.isEmpty()){ | ||||||
|                         attendanceService.updateBatchById(list); |                         attendanceService.updateBatchById(list); | ||||||
| @ -635,7 +635,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave> | |||||||
|                         .eq(BusAttendance::getUserId, busLeave.getUserId()) |                         .eq(BusAttendance::getUserId, busLeave.getUserId()) | ||||||
|                     ); |                     ); | ||||||
|                     for (BusAttendance attendance : list) { |                     for (BusAttendance attendance : list) { | ||||||
|                         attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue()); |                         attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue()); | ||||||
|                     } |                     } | ||||||
|                     if(!list.isEmpty()){ |                     if(!list.isEmpty()){ | ||||||
|                         attendanceService.updateBatchById(list); |                         attendanceService.updateBatchById(list); | ||||||
|  | |||||||
| @ -1,6 +1,8 @@ | |||||||
| package org.dromara.project.service.impl; | package org.dromara.project.service.impl; | ||||||
|  |  | ||||||
| import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
| import org.dromara.common.core.utils.MapstructUtils; | import org.dromara.common.core.utils.MapstructUtils; | ||||||
| import org.dromara.common.core.utils.StringUtils; | import org.dromara.common.core.utils.StringUtils; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| @ -9,6 +11,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.dromara.project.domain.BusProjectTeam; | ||||||
|  | import org.dromara.project.service.IBusProjectTeamService; | ||||||
|  | import org.springframework.context.annotation.Lazy; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.dromara.project.domain.bo.BusProjectPunchrangeBo; | import org.dromara.project.domain.bo.BusProjectPunchrangeBo; | ||||||
| import org.dromara.project.domain.vo.BusProjectPunchrangeVo; | import org.dromara.project.domain.vo.BusProjectPunchrangeVo; | ||||||
| @ -16,9 +21,11 @@ import org.dromara.project.domain.BusProjectPunchrange; | |||||||
| import org.dromara.project.mapper.BusProjectPunchrangeMapper; | import org.dromara.project.mapper.BusProjectPunchrangeMapper; | ||||||
| import org.dromara.project.service.IBusProjectPunchrangeService; | import org.dromara.project.service.IBusProjectPunchrangeService; | ||||||
|  |  | ||||||
|  | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 项目打卡范围Service业务层处理 |  * 项目打卡范围Service业务层处理 | ||||||
| @ -33,6 +40,10 @@ public class BusProjectPunchrangeServiceImpl extends ServiceImpl<BusProjectPunch | |||||||
|  |  | ||||||
|     private final BusProjectPunchrangeMapper baseMapper; |     private final BusProjectPunchrangeMapper baseMapper; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     @Lazy | ||||||
|  |     private IBusProjectTeamService busProjectTeamService; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询项目打卡范围 |      * 查询项目打卡范围 | ||||||
|      * |      * | ||||||
| @ -130,6 +141,13 @@ public class BusProjectPunchrangeServiceImpl extends ServiceImpl<BusProjectPunch | |||||||
|         if(isValid){ |         if(isValid){ | ||||||
|             //TODO 做一些业务上的校验,判断是否需要校验 |             //TODO 做一些业务上的校验,判断是否需要校验 | ||||||
|         } |         } | ||||||
|  |         List<String> idList = ids.stream() | ||||||
|  |             .map(String::valueOf) // 核心:将 Long 转为 String | ||||||
|  |             .collect(Collectors.toList()); | ||||||
|  |         List<BusProjectTeam> busProjectTeams = busProjectTeamService.selectByPunchRangeIn(idList); | ||||||
|  |         if(!busProjectTeams.isEmpty()){ | ||||||
|  |             throw new ServiceException("项目打卡范围正在被使用,请先解除关联关系!" ); | ||||||
|  |         } | ||||||
|         return baseMapper.deleteByIds(ids) > 0; |         return baseMapper.deleteByIds(ids) > 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -38,14 +38,12 @@ import org.dromara.contractor.service.ISubContractorService; | |||||||
| import org.dromara.design.service.IDesTechnicalStandardService; | import org.dromara.design.service.IDesTechnicalStandardService; | ||||||
| import org.dromara.facility.domain.FacMatrix; | import org.dromara.facility.domain.FacMatrix; | ||||||
| import org.dromara.facility.domain.vo.matrix.FacMatrixBySubProjectVo; | import org.dromara.facility.domain.vo.matrix.FacMatrixBySubProjectVo; | ||||||
| import org.dromara.facility.domain.vo.matrix.FacMatrixStructureVo; |  | ||||||
| import org.dromara.facility.service.IFacMatrixService; | import org.dromara.facility.service.IFacMatrixService; | ||||||
| import org.dromara.manager.weathermanager.WeatherConstant; | import org.dromara.manager.weathermanager.WeatherConstant; | ||||||
| import org.dromara.manager.weathermanager.WeatherManager; | import org.dromara.manager.weathermanager.WeatherManager; | ||||||
| import org.dromara.manager.weathermanager.vo.WeatherVo; | import org.dromara.manager.weathermanager.vo.WeatherVo; | ||||||
| import org.dromara.progress.domain.PgsProgressCategory; | import org.dromara.progress.domain.PgsProgressCategory; | ||||||
| import org.dromara.progress.domain.enums.PgsRelevancyStructureEnum; | import org.dromara.progress.domain.enums.PgsRelevancyStructureEnum; | ||||||
| import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryStructureVo; |  | ||||||
| import org.dromara.progress.service.IPgsProgressCategoryService; | import org.dromara.progress.service.IPgsProgressCategoryService; | ||||||
| import org.dromara.progress.service.IPgsProgressCategoryTemplateService; | import org.dromara.progress.service.IPgsProgressCategoryTemplateService; | ||||||
| import org.dromara.project.constant.BusProjectConstant; | import org.dromara.project.constant.BusProjectConstant; | ||||||
| @ -1023,8 +1021,8 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|             .list(); |             .list(); | ||||||
|  |  | ||||||
|         // 构造子项目结构 |         // 构造子项目结构 | ||||||
|         List<BusSubProjectStructureVo> subProjectStructures = subProjects.stream().map(subProject -> { |         List<BusProjectStructureVo> subProjectStructures = new ArrayList<>(subProjects.stream().map(subProject -> { | ||||||
|             BusSubProjectStructureVo subProjectVo = new BusSubProjectStructureVo(); |             BusProjectStructureVo subProjectVo = new BusProjectStructureVo(); | ||||||
|             subProjectVo.setId(subProject.getId()); |             subProjectVo.setId(subProject.getId()); | ||||||
|             subProjectVo.setName(subProject.getProjectName()); |             subProjectVo.setName(subProject.getProjectName()); | ||||||
|  |  | ||||||
| @ -1054,22 +1052,22 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|                     .collect(Collectors.groupingBy(PgsProgressCategory::getParentId)); |                     .collect(Collectors.groupingBy(PgsProgressCategory::getParentId)); | ||||||
|             } |             } | ||||||
|             Map<Long, List<PgsProgressCategory>> finalSub3CategoryMap = sub3CategoryMap; |             Map<Long, List<PgsProgressCategory>> finalSub3CategoryMap = sub3CategoryMap; | ||||||
|             List<FacMatrixStructureVo> structureVoList = sub1Category.stream() |             List<BusProjectStructureVo> structureVoList = sub1Category.stream() | ||||||
|                 .map(category -> { |                 .map(category -> { | ||||||
|                     FacMatrixStructureVo matrixVo = new FacMatrixStructureVo(); |                     BusProjectStructureVo matrixVo = new BusProjectStructureVo(); | ||||||
|                     Long id = category.getId(); |                     Long id = category.getId(); | ||||||
|                     matrixVo.setId(id); |                     matrixVo.setId(id); | ||||||
|                     matrixVo.setName(category.getName()); |                     matrixVo.setName(category.getName()); | ||||||
|                     if (CollUtil.isNotEmpty(finalSub2CategoryMap) && finalSub2CategoryMap.containsKey(id)) { |                     if (CollUtil.isNotEmpty(finalSub2CategoryMap) && finalSub2CategoryMap.containsKey(id)) { | ||||||
|                         matrixVo.setChildren(finalSub2CategoryMap.get(id).stream() |                         matrixVo.setChildren(finalSub2CategoryMap.get(id).stream() | ||||||
|                             .map(c -> { |                             .map(c -> { | ||||||
|                                 PgsProgressCategoryStructureVo subSubCategoryVo = new PgsProgressCategoryStructureVo(); |                                 BusProjectStructureVo subSubCategoryVo = new BusProjectStructureVo(); | ||||||
|                                 subSubCategoryVo.setId(c.getId()); |                                 subSubCategoryVo.setId(c.getId()); | ||||||
|                                 subSubCategoryVo.setName(c.getName()); |                                 subSubCategoryVo.setName(c.getName()); | ||||||
|                                 if (CollUtil.isNotEmpty(finalSub3CategoryMap) && finalSub3CategoryMap.containsKey(c.getId())) { |                                 if (CollUtil.isNotEmpty(finalSub3CategoryMap) && finalSub3CategoryMap.containsKey(c.getId())) { | ||||||
|                                     subSubCategoryVo.setChildren(finalSub3CategoryMap.get(c.getId()).stream() |                                     subSubCategoryVo.setChildren(finalSub3CategoryMap.get(c.getId()).stream() | ||||||
|                                         .map(c3 -> { |                                         .map(c3 -> { | ||||||
|                                             PgsProgressCategoryStructureVo sub3CategoryVo = new PgsProgressCategoryStructureVo(); |                                             BusProjectStructureVo sub3CategoryVo = new BusProjectStructureVo(); | ||||||
|                                             sub3CategoryVo.setId(c3.getId()); |                                             sub3CategoryVo.setId(c3.getId()); | ||||||
|                                             sub3CategoryVo.setName(c3.getName()); |                                             sub3CategoryVo.setName(c3.getName()); | ||||||
|                                             return sub3CategoryVo; |                                             return sub3CategoryVo; | ||||||
| @ -1097,8 +1095,8 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|                     .list(); |                     .list(); | ||||||
|                 // 找到该子项目下的方阵 |                 // 找到该子项目下的方阵 | ||||||
|                 List<FacMatrix> matrices = matrixMap.getOrDefault(subProject.getId(), new ArrayList<>()); |                 List<FacMatrix> matrices = matrixMap.getOrDefault(subProject.getId(), new ArrayList<>()); | ||||||
|                 List<FacMatrixStructureVo> matrixVos = matrices.stream().map(matrix -> { |                 List<BusProjectStructureVo> matrixVos = matrices.stream().map(matrix -> { | ||||||
|                     FacMatrixStructureVo matrixVo = new FacMatrixStructureVo(); |                     BusProjectStructureVo matrixVo = new BusProjectStructureVo(); | ||||||
|                     matrixVo.setId(matrix.getId()); |                     matrixVo.setId(matrix.getId()); | ||||||
|                     matrixVo.setName(matrix.getMatrixName()); |                     matrixVo.setName(matrix.getMatrixName()); | ||||||
|  |  | ||||||
| @ -1108,19 +1106,26 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|                         .toList(); |                         .toList(); | ||||||
|  |  | ||||||
|                     // 构造分项工程树 |                     // 构造分项工程树 | ||||||
|                     List<PgsProgressCategoryStructureVo> categoryTree = buildCategoryTree(categories); |                     List<BusProjectStructureVo> categoryTree = buildCategoryTree(categories); | ||||||
|                     matrixVo.setChildren(categoryTree); |                     matrixVo.setChildren(categoryTree); | ||||||
|                     return matrixVo; |                     return matrixVo; | ||||||
|                 }).toList(); |                 }).toList(); | ||||||
|                 List<FacMatrixStructureVo> resultList = Stream.concat( |                 List<BusProjectStructureVo> resultList = Stream.concat( | ||||||
|                     structureVoList.stream(), |                     structureVoList.stream(), | ||||||
|                     matrixVos.stream() |                     matrixVos.stream() | ||||||
|                 ).toList(); |                 ).toList(); | ||||||
|                 subProjectVo.setChildren(resultList); |                 subProjectVo.setChildren(resultList); | ||||||
|             } |             } | ||||||
|             return subProjectVo; |             return subProjectVo; | ||||||
|         }).toList(); |         }).toList()); | ||||||
|  |  | ||||||
|  |         // 获取分项工程 | ||||||
|  |         List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery() | ||||||
|  |             .eq(PgsProgressCategory::getRelevancyStructure, PgsRelevancyStructureEnum.PROJECT.getValue()) | ||||||
|  |             .in(PgsProgressCategory::getProjectId, projectId) | ||||||
|  |             .list(); | ||||||
|  |         List<BusProjectStructureVo> projectStructureVos = this.buildCategoryTree(progressCategoryList); | ||||||
|  |         subProjectStructures.addAll(projectStructureVos); | ||||||
|         vo.setChildren(subProjectStructures); |         vo.setChildren(subProjectStructures); | ||||||
|         return vo; |         return vo; | ||||||
|     } |     } | ||||||
| @ -1252,159 +1257,159 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
| //        projectVos.add(create("台湾省", "台北", 25.0330, 121.5654, 1)); | //        projectVos.add(create("台湾省", "台北", 25.0330, 121.5654, 1)); | ||||||
|  |  | ||||||
|         // 1号项目 |         // 1号项目 | ||||||
|         projectVos.add(create("贵州省", "都匀市沙包堡匀东农业光伏电站项目", 26.2556, 107.5139, 1)); |         projectVos.add(create("贵州省", "都匀市沙包堡匀东农业光伏电站项目", 26.2556, 107.5139, 1, "118.0452MWp")); | ||||||
|  |  | ||||||
| // 2号项目 | // 2号项目 | ||||||
|         projectVos.add(create("贵州省", "长顺县朝核农业光伏电站", 26.1833, 106.4522, 1)); |         projectVos.add(create("贵州省", "长顺县朝核农业光伏电站", 26.1833, 106.4522, 1, "99.84MW")); | ||||||
|  |  | ||||||
| // 3号项目 | // 3号项目 | ||||||
|         projectVos.add(create("重庆市", "重庆无水港绿色低碳能源项目", 29.533155, 106.504962, 1)); |         projectVos.add(create("重庆市", "重庆无水港绿色低碳能源项目", 29.533155, 106.504962, 1, "2.598MW")); | ||||||
|  |  | ||||||
| // 4号项目 | // 4号项目 | ||||||
|         projectVos.add(create("贵州省", "兴义市捧乍猪场坪农业光伏电站项目", 25.1467, 104.8925, 1)); |         projectVos.add(create("贵州省", "兴义市捧乍猪场坪农业光伏电站项目", 25.1467, 104.8925, 1, "100MW")); | ||||||
|  |  | ||||||
| // 5号项目 | // 5号项目 | ||||||
|         projectVos.add(create("贵州省", "华能盘州市羊场高光村、松林农业光伏发电项目", 25.7833, 104.6583, 1)); |         projectVos.add(create("贵州省", "华能盘州市羊场高光村、松林农业光伏发电项目", 25.7833, 104.6583, 1, "200MW")); | ||||||
|  |  | ||||||
| // 6号项目 | // 6号项目 | ||||||
|         projectVos.add(create("贵州省", "大唐(六盘水)新能源有限公司水城区化乐农业光伏电站项目", 26.5167, 104.8289, 1)); |         projectVos.add(create("贵州省", "大唐(六盘水)新能源有限公司水城区化乐农业光伏电站项目", 26.5167, 104.8289, 1, "99.84MW")); | ||||||
|  |  | ||||||
| // 7号项目 | // 7号项目 | ||||||
|         projectVos.add(create("广西壮族自治区", "河池市宜州区北牙瑶族乡100MWp农光互补光伏发电项目", 24.6833, 108.6958, 1)); |         projectVos.add(create("广西壮族自治区", "河池市宜州区北牙瑶族乡100MWp农光互补光伏发电项目", 24.6833, 108.6958, 1, "101.34MWp")); | ||||||
|  |  | ||||||
| // 8号项目 | // 8号项目 | ||||||
|         projectVos.add(create("四川省", "凉山木里茶布朗光伏发电项目220kV升压站设计施工总承包项目", 27.9167, 100.3250, 1)); |         projectVos.add(create("四川省", "凉山木里茶布朗光伏发电项目220kV升压站设计施工总承包项目", 27.9167, 100.3250, 1, "220kV")); | ||||||
|  |  | ||||||
| // 9号项目 | // 9号项目 | ||||||
|         projectVos.add(create("内蒙古自治区", "土默特右旗英能光伏电力开发有限公司100兆瓦光伏基地项目", 40.5333, 110.5489, 1)); |         projectVos.add(create("内蒙古自治区", "土默特右旗英能光伏电力开发有限公司100兆瓦光伏基地项目", 40.5333, 110.5489, 1, "100MWp")); | ||||||
|  |  | ||||||
| // 10号项目 | // 10号项目 | ||||||
|         projectVos.add(create("云南省", "云南沾益农业光伏项目", 25.5000, 103.8194, 1)); |         projectVos.add(create("云南省", "云南沾益农业光伏项目", 25.5000, 103.8194, 1, "350MWp")); | ||||||
|  |  | ||||||
| // 11号项目 | // 11号项目 | ||||||
|         projectVos.add(create("贵州省", "威宁县盐仓老鸦营30MW农业光伏电站项目", 26.8833, 104.2250, 1)); |         projectVos.add(create("贵州省", "威宁县盐仓老鸦营30MW农业光伏电站项目", 26.8833, 104.2250, 1, "30MW")); | ||||||
|  |  | ||||||
| // 12号项目 | // 12号项目 | ||||||
|         projectVos.add(create("云南省", "大黑土光伏电站总承包工程项目", 25.0406, 102.7142, 1)); |         projectVos.add(create("云南省", "大黑土光伏电站总承包工程项目", 25.0406, 102.7142, 1, "272.97MW")); | ||||||
|  |  | ||||||
| // 13号项目 | // 13号项目 | ||||||
|         projectVos.add(create("贵州省", "晴隆县碧痕新坪村风光火储一体化农业光伏电站", 25.5333, 105.1250, 1)); |         projectVos.add(create("贵州省", "晴隆县碧痕新坪村风光火储一体化农业光伏电站", 25.5333, 105.1250, 1, "/")); | ||||||
|  |  | ||||||
| // 15号项目 | // 15号项目 | ||||||
|         projectVos.add(create("河北省", "怀安县风光储一体化项目", 40.6667, 114.5417, 1)); |         projectVos.add(create("河北省", "怀安县风光储一体化项目", 40.6667, 114.5417, 1, "200MW")); | ||||||
|  |  | ||||||
| // 16号项目 | // 16号项目 | ||||||
|         projectVos.add(create("云南省", "保山市隆阳区黑岩洼光伏发电项目", 25.1250, 99.1667, 1)); |         projectVos.add(create("云南省", "保山市隆阳区黑岩洼光伏发电项目", 25.1250, 99.1667, 1, "100MW")); | ||||||
|  |  | ||||||
| // 17号项目 | // 17号项目 | ||||||
|         projectVos.add(create("云南省", "白玉光伏发电项目", 25.1250, 99.1667, 1)); |         projectVos.add(create("云南省", "白玉光伏发电项目", 25.1250, 99.1667, 1, "340MW")); | ||||||
|  |  | ||||||
| // 20号项目 | // 20号项目 | ||||||
|         projectVos.add(create("云南省", "云南省沾益区菱角农业光伏发电项目", 25.6000, 103.6833, 1)); |         projectVos.add(create("云南省", "云南省沾益区菱角农业光伏发电项目", 25.6000, 103.6833, 1, "350MWp")); | ||||||
|  |  | ||||||
| // 21号项目 | // 21号项目 | ||||||
|         projectVos.add(create("云南省", "云南省文山州砚山县平远光伏发电项目", 23.7500, 104.3333, 1)); |         projectVos.add(create("云南省", "云南省文山州砚山县平远光伏发电项目", 23.7500, 104.3333, 1, "120MW")); | ||||||
|  |  | ||||||
| // 22号项目 | // 22号项目 | ||||||
|         projectVos.add(create("贵州省", "兴仁市大山能投农业光伏电站项目", 25.4000, 105.1833, 1)); |         projectVos.add(create("贵州省", "兴仁市大山能投农业光伏电站项目", 25.4000, 105.1833, 1, "100MW")); | ||||||
|  |  | ||||||
| // 23号项目 | // 23号项目 | ||||||
|         projectVos.add(create("贵州省", "兴仁市潘家庄能投农业光伏电站项目", 25.5333, 104.9833, 1)); |         projectVos.add(create("贵州省", "兴仁市潘家庄能投农业光伏电站项目", 25.5333, 104.9833, 1, "100MW")); | ||||||
|  |  | ||||||
| // 47号项目 | // 47号项目 | ||||||
|         projectVos.add(create("重庆市", "丰都许明寺镇100MW农牧光互补复合项目", 29.9333, 107.7500, 1)); |         projectVos.add(create("重庆市", "丰都许明寺镇100MW农牧光互补复合项目", 29.9333, 107.7500, 1, "100MW")); | ||||||
|  |  | ||||||
| // 48号项目 | // 48号项目 | ||||||
|         projectVos.add(create("云南省", "文山市茂克光伏电站项目", 23.3667, 104.2000, 1)); |         projectVos.add(create("云南省", "文山市茂克光伏电站项目", 23.3667, 104.2000, 1, "90.2MW")); | ||||||
|  |  | ||||||
| // 50号项目 | // 50号项目 | ||||||
|         projectVos.add(create("云南省", "文山市清水井光伏电站项目", 23.4500, 104.3333, 1)); |         projectVos.add(create("云南省", "文山市清水井光伏电站项目", 23.4500, 104.3333, 1, "120.25MW")); | ||||||
|  |  | ||||||
| // 52号项目(原序号1) | // 52号项目(原序号1) | ||||||
|         projectVos.add(create("广西壮族自治区", "新铝电力新山站屋顶分布式光伏发电项目EPC总承包", 22.8241, 108.3178, 1)); |         projectVos.add(create("广西壮族自治区", "新铝电力新山站屋顶分布式光伏发电项目EPC总承包", 22.8241, 108.3178, 1, "0.3MWp")); | ||||||
|  |  | ||||||
| // 53号项目(原序号2) | // 53号项目(原序号2) | ||||||
|         projectVos.add(create("江西省", "江西省高速公路服务区分布式光伏项目EPC", 28.6764, 115.8922, 1)); |         projectVos.add(create("江西省", "江西省高速公路服务区分布式光伏项目EPC", 28.6764, 115.8922, 1, "120.12MWp")); | ||||||
|  |  | ||||||
| // 54号项目(原序号3) | // 54号项目(原序号3) | ||||||
|         projectVos.add(create("河南省", "龙佰集团股份有限公司7MWp分布式光伏发电项目EPC总承包", 34.7573, 113.6145, 1)); |         projectVos.add(create("河南省", "龙佰集团股份有限公司7MWp分布式光伏发电项目EPC总承包", 34.7573, 113.6145, 1, "8.4MWp")); | ||||||
|  |  | ||||||
| // 55号项目(原序号4) | // 55号项目(原序号4) | ||||||
|         projectVos.add(create("吉林省", "吉林热电检修安装工程有限公司吉林省南湖宾馆光储充一体化项目EPC总承包", 43.8868, 125.3245, 1)); |         projectVos.add(create("吉林省", "吉林热电检修安装工程有限公司吉林省南湖宾馆光储充一体化项目EPC总承包", 43.8868, 125.3245, 1, "400kW")); | ||||||
|  |  | ||||||
| // 56号项目(原序号5) | // 56号项目(原序号5) | ||||||
|         projectVos.add(create("吉林省", "集安市瀚能风电场相关装备有限公司益盛汉参集团分布式光伏发电项目EPC", 41.1333, 126.1650, 1)); |         projectVos.add(create("吉林省", "集安市瀚能风电场相关装备有限公司益盛汉参集团分布式光伏发电项目EPC", 41.1333, 126.1650, 1, "3.50784MW")); | ||||||
|  |  | ||||||
| // 57号项目(原序号6) | // 57号项目(原序号6) | ||||||
|         projectVos.add(create("重庆市", "重庆潼南综合智慧零碳电厂耀辉环保单元项目", 30.1550, 106.2289, 1)); |         projectVos.add(create("重庆市", "重庆潼南综合智慧零碳电厂耀辉环保单元项目", 30.1550, 106.2289, 1, "2.9MW")); | ||||||
|  |  | ||||||
| // 58号项目(原序号7) | // 58号项目(原序号7) | ||||||
|         projectVos.add(create("重庆市", "汇智能源公司重庆永川综合智慧零碳电厂", 29.4167, 105.7833, 1)); |         projectVos.add(create("重庆市", "汇智能源公司重庆永川综合智慧零碳电厂", 29.4167, 105.7833, 1, "2MW")); | ||||||
|  |  | ||||||
| // 59号项目(原序号8) | // 59号项目(原序号8) | ||||||
|         projectVos.add(create("广西壮族自治区", "德保县乡村振兴光伏发电项目(第二批)EPC 总承包", 23.7167, 106.6833, 1)); |         projectVos.add(create("广西壮族自治区", "德保县乡村振兴光伏发电项目(第二批)EPC 总承包", 23.7167, 106.6833, 1, "44.775MW")); | ||||||
|  |  | ||||||
| // 60号项目(原序号9) | // 60号项目(原序号9) | ||||||
|         projectVos.add(create("重庆市", "汇智能源公司重庆永川综合智慧零碳电厂升科精锻单元项目工程EPC总承包工程(一期)", 29.4167, 105.7833, 1)); |         projectVos.add(create("重庆市", "汇智能源公司重庆永川综合智慧零碳电厂升科精锻单元项目工程EPC总承包工程(一期)", 29.4167, 105.7833, 1, "/")); | ||||||
|  |  | ||||||
| // 62号项目(原序号11) | // 62号项目(原序号11) | ||||||
|         projectVos.add(create("贵州省", "新铝电力莲塘、马隘变电站屋顶分布式光伏发电项目EPC工程总承包项目", 23.7833, 106.9500, 1)); |         projectVos.add(create("贵州省", "新铝电力莲塘、马隘变电站屋顶分布式光伏发电项目EPC工程总承包项目", 23.7833, 106.9500, 1, "0.788MW")); | ||||||
|  |  | ||||||
| // 63号项目(原序号12) | // 63号项目(原序号12) | ||||||
|         projectVos.add(create("广西壮族自治区", "广西德保县乡村振兴光伏发电项目(第三批)EPC总承包", 23.7167, 106.6833, 1)); |         projectVos.add(create("广西壮族自治区", "广西德保县乡村振兴光伏发电项目(第三批)EPC总承包", 23.7167, 106.6833, 1, "191MW(直流侧装机容量243.9007MWp)")); | ||||||
|  |  | ||||||
| // 64号项目(原序号13) | // 64号项目(原序号13) | ||||||
|         projectVos.add(create("内蒙古自治区", "内蒙古自治区蒙西户用分布式200MW光伏发电项目EPC总承包四期", 40.6667, 109.8333, 1)); |         projectVos.add(create("内蒙古自治区", "内蒙古自治区蒙西户用分布式200MW光伏发电项目EPC总承包四期", 40.6667, 109.8333, 1, "200MW")); | ||||||
|  |  | ||||||
| // 65号项目(原序号14) | // 65号项目(原序号14) | ||||||
|         projectVos.add(create("广东省", "惠来县50MWp居民屋顶分布式光伏项目", 23.0333, 116.2833, 1)); |         projectVos.add(create("广东省", "惠来县50MWp居民屋顶分布式光伏项目", 23.0333, 116.2833, 1, "50MWp")); | ||||||
|  |  | ||||||
| // 66号项目(原序号15) | // 66号项目(原序号15) | ||||||
|         projectVos.add(create("广西壮族自治区", "田东县乡村振兴分布式光伏发电项目(二期)EPC总承包", 23.6167, 106.9167, 1)); |         projectVos.add(create("广西壮族自治区", "田东县乡村振兴分布式光伏发电项目(二期)EPC总承包", 23.6167, 106.9167, 1, "92MW")); | ||||||
|  |  | ||||||
| // 67号项目(原序号16) | // 67号项目(原序号16) | ||||||
|         projectVos.add(create("广西壮族自治区", "田东县乡村振兴分布式光伏发电项目(一期)EPC总承包", 23.6167, 106.9167, 1)); |         projectVos.add(create("广西壮族自治区", "田东县乡村振兴分布式光伏发电项目(一期)EPC总承包", 23.6167, 106.9167, 1, "203MW")); | ||||||
|  |  | ||||||
| // 68号项目(原序号17) | // 68号项目(原序号17) | ||||||
|         projectVos.add(create("重庆市", "华能重庆华通电脑有限公司屋顶分布式光伏EPC项目合同", 29.533155, 106.504962, 1)); |         projectVos.add(create("重庆市", "华能重庆华通电脑有限公司屋顶分布式光伏EPC项目合同", 29.533155, 106.504962, 1, "10.2245MWp")); | ||||||
|  |  | ||||||
| // 69号项目(原序号18) | // 69号项目(原序号18) | ||||||
|         projectVos.add(create("广东省", "大埔峡能白罗20MW、长兴20MW、洋门10MW、群丰10MW农光互补光伏发电项目", 24.3667, 116.7000, 1)); |         projectVos.add(create("广东省", "大埔峡能白罗20MW、长兴20MW、洋门10MW、群丰10MW农光互补光伏发电项目", 24.3667, 116.7000, 1, "60MWp")); | ||||||
|  |  | ||||||
| // 70号项目(原序号19) | // 70号项目(原序号19) | ||||||
|         projectVos.add(create("广东省", "化州区域分布式光伏项目", 21.7000, 110.6333, 1)); |         projectVos.add(create("广东省", "化州区域分布式光伏项目", 21.7000, 110.6333, 1, "15MWp")); | ||||||
|  |  | ||||||
| // 71号项目(原序号20) | // 71号项目(原序号20) | ||||||
|         projectVos.add(create("河北省", "兴隆县10MW分布式光伏项目", 40.4167, 117.4833, 1)); |         projectVos.add(create("河北省", "兴隆县10MW分布式光伏项目", 40.4167, 117.4833, 1, "5.99MW")); | ||||||
|  |  | ||||||
| // 75号项目(原序号24) | // 75号项目(原序号24) | ||||||
|         projectVos.add(create("重庆市", "石柱发电公司厂区分布式光伏施工项目", 29.9333, 108.1333, 1)); |         projectVos.add(create("重庆市", "石柱发电公司厂区分布式光伏施工项目", 29.9333, 108.1333, 1, "0.9MW")); | ||||||
|  |  | ||||||
| // 76号项目(原序号25) | // 76号项目(原序号25) | ||||||
|         projectVos.add(create("陕西省", "靖边燃气发电厂3.0MW光伏发电工程", 37.6167, 108.7833, 1)); |         projectVos.add(create("陕西省", "靖边燃气发电厂3.0MW光伏发电工程", 37.6167, 108.7833, 1, "3MWp")); | ||||||
|  |  | ||||||
| // 77号项目(原序号26) | // 77号项目(原序号26) | ||||||
|         projectVos.add(create("河北省", "河北兴隆 10MW分布式光伏项目", 40.4167, 117.4833, 1)); |         projectVos.add(create("河北省", "河北兴隆 10MW分布式光伏项目", 40.4167, 117.4833, 1, "4MW")); | ||||||
|  |  | ||||||
| // 79号项目(原序号28) | // 79号项目(原序号28) | ||||||
|         projectVos.add(create("广东省", "茂名分公司化工区物资仓库屋顶光伏发电合同能源管理项目", 21.6833, 110.8667, 1)); |         projectVos.add(create("广东省", "茂名分公司化工区物资仓库屋顶光伏发电合同能源管理项目", 21.6833, 110.8667, 1, "1.855MWp")); | ||||||
|  |  | ||||||
| // 88号项目(原序号37) | // 88号项目(原序号37) | ||||||
|         projectVos.add(create("河北省", "怀安县风光储一体化项目", 40.6667, 114.5417, 1)); |         projectVos.add(create("河北省", "怀安县风光储一体化项目", 40.6667, 114.5417, 1, "200MW")); | ||||||
|  |  | ||||||
| // 91号项目(原序号2) | // 91号项目(原序号2) | ||||||
|         projectVos.add(create("辽宁省", "鑫泰新能源大石桥市200MW风电场新建工程项目", 40.6333, 122.5333, 2)); |         projectVos.add(create("辽宁省", "鑫泰新能源大石桥市200MW风电场新建工程项目", 40.6333, 122.5333, 2, "200MW")); | ||||||
|  |  | ||||||
| // 92号项目(原序号3) | // 92号项目(原序号3) | ||||||
|         projectVos.add(create("辽宁省", "大石桥市冠程新能源550MW风电场工程项目", 40.6333, 122.5333, 2)); |         projectVos.add(create("辽宁省", "大石桥市冠程新能源550MW风电场工程项目", 40.6333, 122.5333, 2, "550MW")); | ||||||
|  |  | ||||||
| // 96号项目(原序号7) | // 96号项目(原序号7) | ||||||
|         projectVos.add(create("四川省", "阿坝公司运检大楼“风光油储型”微电网试点项目", 31.9500, 102.2167, 2)); |         projectVos.add(create("四川省", "阿坝公司运检大楼“风光油储型”微电网试点项目", 31.9500, 102.2167, 2, "0.6MW")); | ||||||
|  |  | ||||||
|         // 老挝 - 万象 |         // 老挝 - 万象 | ||||||
|         projectVos.add(create("老挝", "巴塞", 15.110507, 105.817291, 1)); |         projectVos.add(create("老挝", "巴塞", 15.110507, 105.817291, 1, "1000MW")); | ||||||
|         // 老挝 - 琅勃拉邦 |         // 老挝 - 琅勃拉邦 | ||||||
|         projectVos.add(create("老挝", "波利坎塞", 18.39639, 103.65583, 1)); |         projectVos.add(create("老挝", "波利坎塞", 18.39639, 103.65583, 1, "50.1MW")); | ||||||
|         Map<String, Map<String, Map<String, String>>> map = new HashMap<>(); |         Map<String, Map<String, Map<String, String>>> map = new HashMap<>(); | ||||||
|         for (SysDictDataVo projectType : projectTypes) { |         for (SysDictDataVo projectType : projectTypes) { | ||||||
|             Map<String, Map<String, String>> map1 = new HashMap<>(); |             Map<String, Map<String, String>> map1 = new HashMap<>(); | ||||||
| @ -1486,21 +1491,21 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|     /** |     /** | ||||||
|      * 构造分项工程树 |      * 构造分项工程树 | ||||||
|      */ |      */ | ||||||
|     private List<PgsProgressCategoryStructureVo> buildCategoryTree(List<PgsProgressCategory> categories) { |     private List<BusProjectStructureVo> buildCategoryTree(List<PgsProgressCategory> categories) { | ||||||
|         Map<Long, PgsProgressCategoryStructureVo> map = new HashMap<>(); |         Map<Long, BusProjectStructureVo> map = new HashMap<>(); | ||||||
|         List<PgsProgressCategoryStructureVo> roots = new ArrayList<>(); |         List<BusProjectStructureVo> roots = new ArrayList<>(); | ||||||
|  |  | ||||||
|         for (PgsProgressCategory c : categories) { |         for (PgsProgressCategory c : categories) { | ||||||
|             PgsProgressCategoryStructureVo node = new PgsProgressCategoryStructureVo(c.getId(), c.getName(), new ArrayList<>()); |             BusProjectStructureVo node = new BusProjectStructureVo(c.getId(), c.getName(), new ArrayList<>()); | ||||||
|             map.put(c.getId(), node); |             map.put(c.getId(), node); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (PgsProgressCategory c : categories) { |         for (PgsProgressCategory c : categories) { | ||||||
|             PgsProgressCategoryStructureVo node = map.get(c.getId()); |             BusProjectStructureVo node = map.get(c.getId()); | ||||||
|             if (c.getParentId() == 0) { |             if (c.getParentId() == 0) { | ||||||
|                 roots.add(node); |                 roots.add(node); | ||||||
|             } else { |             } else { | ||||||
|                 PgsProgressCategoryStructureVo parent = map.get(c.getParentId()); |                 BusProjectStructureVo parent = map.get(c.getParentId()); | ||||||
|                 if (parent != null) { |                 if (parent != null) { | ||||||
|                     parent.getChildren().add(node); |                     parent.getChildren().add(node); | ||||||
|                 } |                 } | ||||||
| @ -1539,7 +1544,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|      * @param projectType 项目类型 |      * @param projectType 项目类型 | ||||||
|      * @return 项目信息 |      * @return 项目信息 | ||||||
|      */ |      */ | ||||||
|     private static BusProjectVo create(String province, String name, double lat, double lng, Integer projectType) { |     private static BusProjectVo create(String province, String name, double lat, double lng, Integer projectType, String plan) { | ||||||
|         BusProjectVo vo = new BusProjectVo(); |         BusProjectVo vo = new BusProjectVo(); | ||||||
|         vo.setId(IdWorker.getID()); |         vo.setId(IdWorker.getID()); | ||||||
|         vo.setProvince(province); |         vo.setProvince(province); | ||||||
| @ -1547,6 +1552,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | |||||||
|         vo.setLat(String.valueOf(lat)); |         vo.setLat(String.valueOf(lat)); | ||||||
|         vo.setLng(String.valueOf(lng)); |         vo.setLng(String.valueOf(lng)); | ||||||
|         vo.setProjectType(projectType.toString()); |         vo.setProjectType(projectType.toString()); | ||||||
|  |         vo.setPlan(plan); | ||||||
|         return vo; |         return vo; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,6 +17,7 @@ import org.dromara.common.enums.AppUserTypeEnum; | |||||||
| import org.dromara.common.mybatis.core.page.PageQuery; | import org.dromara.common.mybatis.core.page.PageQuery; | ||||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||||
| import org.dromara.common.satoken.utils.LoginHelper; | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.utils.AsyncUtil; | ||||||
| import org.dromara.common.utils.IdCardEncryptorUtil; | import org.dromara.common.utils.IdCardEncryptorUtil; | ||||||
| import org.dromara.contractor.domain.SubConstructionUser; | import org.dromara.contractor.domain.SubConstructionUser; | ||||||
| import org.dromara.contractor.service.ISubConstructionUserService; | import org.dromara.contractor.service.ISubConstructionUserService; | ||||||
| @ -90,6 +91,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM | |||||||
|     @Resource |     @Resource | ||||||
|     private ISysOssService ossService; |     private ISysOssService ossService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private AsyncUtil asyncUtil; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 查询项目班组下的成员 |      * 查询项目班组下的成员 | ||||||
| @ -219,6 +222,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM | |||||||
|             userService.updateFb(constructionUser.getSysUserId(),req.getContractorId(),false); |             userService.updateFb(constructionUser.getSysUserId(),req.getContractorId(),false); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         asyncUtil.sendPersonnel(req.getTeamId(), constructionUser); | ||||||
|  |  | ||||||
|         return projectTeamMember.getId(); |         return projectTeamMember.getId(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -356,6 +361,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM | |||||||
|             .set(SubConstructionUser::getTeamId, null) |             .set(SubConstructionUser::getTeamId, null) | ||||||
|             .set(SubConstructionUser::getLeaveDate, new Date()); |             .set(SubConstructionUser::getLeaveDate, new Date()); | ||||||
|         constructionUserService.update(constructionUserLuw); |         constructionUserService.update(constructionUserLuw); | ||||||
|  |  | ||||||
|  |         asyncUtil.deletePersonnel(constructionUser); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	