Compare commits

418 Commits

Author SHA1 Message Date
lg
dbc09a62ea 后端修改 2025-10-22 09:29:20 +08:00
zt
f3fa78475c bug 2025-10-21 20:05:55 +08:00
c565771283 10-21-修复 2025-10-21 20:04:59 +08:00
bac8488244 新中大综合服务合同修改,建管大屏接口优化、gps接口优化 2025-10-21 18:35:07 +08:00
lcj
a5f661b558 承包合同,安全质量大屏 2025-10-21 18:29:06 +08:00
zt
ceecec97c7 打印天气 2025-10-21 18:25:52 +08:00
c6ae8a4c00 10-21-收票与开票-收票登记 2025-10-21 17:31:00 +08:00
zt
37d0c776c0 设计计划 2025-10-21 15:53:56 +08:00
f8eea0f63f 修改查询语句 2025-10-21 10:36:52 +08:00
lg
59c749ab2a 表名修改 2025-10-21 10:09:59 +08:00
eeeba2bf4b 10-21-修复 2025-10-21 10:07:55 +08:00
lg
a9ce42101f 补充 2025-10-20 20:16:44 +08:00
lcj
13de88265f 识别逻辑 2025-10-20 20:09:51 +08:00
a464a1236d 综合服务进度、采购进度、竣工、竣工调整添加底部计量结算内容 2025-10-20 20:07:40 +08:00
fce5d0e7fc 10-20-修复字段 2025-10-20 19:57:27 +08:00
66ba43d030 Merge remote-tracking branch 'origin/dev' into dev 2025-10-20 19:26:18 +08:00
1aa77e5eda 10-20-决算清 2025-10-20 19:26:08 +08:00
zt
037016fc13 人脸对接 2025-10-20 19:24:36 +08:00
99f0026552 大屏接口添加计划容量 2025-10-20 17:12:06 +08:00
lg
535262d721 枚举 2025-10-20 16:32:32 +08:00
fbcb9ca3f2 10-20-决算清单(调整)初始化 2025-10-20 16:19:00 +08:00
2a7a20b966 Merge remote-tracking branch 'origin/dev' into dev 2025-10-20 16:10:14 +08:00
98fdab0dba 10-20-承包合同进度结算补齐 2025-10-20 16:10:03 +08:00
lg
bd71335ae6 分包合同枚举 2025-10-20 15:53:15 +08:00
zt
7f746fc250 考勤机 2025-10-20 15:41:43 +08:00
lg
901c8785fe 合同类型字段补充 2025-10-20 15:30:34 +08:00
e4e9718acb 10-20-初始化 2025-10-20 15:08:29 +08:00
738101f374 10-20-初始化 2025-10-20 15:05:58 +08:00
lg
a7befd7278 字段修改补充 2025-10-20 14:56:38 +08:00
lg
52e968c313 字段修改 2025-10-20 14:47:03 +08:00
lg
de9d7d34d6 部门修改和变更增加清单,合同内清单 2025-10-20 14:29:59 +08:00
zt
9f0105d88a 角色优化 2025-10-20 14:21:18 +08:00
lcj
80ec8ff86d 结算 2025-10-20 14:19:43 +08:00
f3473fe5d5 阶段成本分解校验修改 2025-10-18 21:05:20 +08:00
lcj
856f3f334b 修改日期 2025-10-18 20:35:50 +08:00
lcj
0b216a4101 修改配置 2025-10-18 20:19:35 +08:00
c7338b45ad 大屏项目 2025-10-18 20:09:38 +08:00
c93b1b752e Merge remote-tracking branch 'origin/dev' into dev 2025-10-18 20:08:43 +08:00
e38074bb25 大屏项目 2025-10-18 20:08:17 +08:00
zt
be0f425e14 Merge remote-tracking branch 'origin/dev' into dev 2025-10-18 20:03:14 +08:00
zt
f24e33b1c7 注销 2025-10-18 20:02:54 +08:00
48ea20581c 项目 2025-10-18 19:54:27 +08:00
lcj
e7fa22e573 承包分包合同进度结算 2025-10-18 19:44:37 +08:00
83b7b32035 解决冲突 2025-10-18 18:56:03 +08:00
6a0be071b8 合同管理-承包、分包、采购、综合服务的信息、变更添加合同变更清单 2025-10-18 18:47:21 +08:00
lg
7bdf8f53b9 采购合同修改 2025-10-18 18:45:25 +08:00
lg
03b249afe7 单据编号统一接口 2025-10-18 17:15:16 +08:00
lg
2e5e42fd84 成本单 2025-10-18 14:21:49 +08:00
f9d9785536 10-17-收票与开票-开票申请 2025-10-18 14:14:27 +08:00
a06511e0bf Merge remote-tracking branch 'origin/dev' into dev 2025-10-18 14:13:49 +08:00
zt
31aa56d34b 设备打卡 2025-10-17 21:15:44 +08:00
2b4517760f 立项及成本-成本预算-阶段成本分解接口 2025-10-17 20:10:36 +08:00
c318d0b10b 合同管理-合同变更清单初始化 2025-10-17 17:42:40 +08:00
lcj
ec54b4ff52 大屏、产值 2025-10-17 15:42:05 +08:00
zt
965a0cc90e 材料 2025-10-17 15:39:59 +08:00
zt
ebddc5c51f 分包 2025-10-17 15:37:24 +08:00
a323844440 立项与成本-成本预算-总体计划成本接口 2025-10-17 14:15:35 +08:00
lg
6bcddf50da 资金计划 2025-10-17 11:54:00 +08:00
lcj
c72275859f 大屏、产值 2025-10-17 11:51:09 +08:00
9561ee9323 10-17-收票与开票-开票申请 2025-10-17 11:24:46 +08:00
b7a52de2d2 立项与成本-成本预算-完工成本填报新增 2025-10-17 10:53:00 +08:00
bfc3ea60fd 立项与成本-成本预算-完工成本填报初始化 2025-10-17 10:34:03 +08:00
zt
1acc676b0f 短信优化 2025-10-17 10:15:11 +08:00
d6a378f711 Merge remote-tracking branch 'origin/dev' into dev 2025-10-16 21:59:24 +08:00
b4f56b6c79 10-16-承包合同收款-分包合同付款 2025-10-16 21:58:55 +08:00
zt
b5d2b3df06 优化 2025-10-16 20:33:34 +08:00
lcj
4042b4a441 修改bug 2025-10-16 20:31:56 +08:00
1fd3da3e2a 收款与付款-采购、综合服务付款接口 2025-10-16 20:07:05 +08:00
zt
0d84c49ca4 优化 2025-10-16 18:43:05 +08:00
lcj
cecfb60e71 项目部门关联 2025-10-16 17:55:48 +08:00
lcj
aec8667edc 进度计划产值 2025-10-16 15:18:39 +08:00
e930cd3b7c 10-16-承包合同竣工结算调整 2025-10-16 14:42:14 +08:00
373906bde7 Merge remote-tracking branch 'origin/dev' into dev 2025-10-16 14:40:51 +08:00
bca9745e60 收款与付款-采购、综合服务付款初始化 2025-10-16 14:40:31 +08:00
lcj
6808057111 考勤机 2025-10-15 23:57:32 +08:00
lg
9f1da9e6c0 结算信息 2025-10-15 22:50:38 +08:00
d8838f8e01 采购合同结算接口 2025-10-15 22:01:22 +08:00
d92d37c646 大屏接口修改与ws接口修改 2025-10-15 21:59:27 +08:00
zt
6398a28974 优化 2025-10-15 20:36:12 +08:00
cce9ef98d8 10-15-承包合同竣工结算 2025-10-15 19:52:55 +08:00
467a972a6d Merge remote-tracking branch 'origin/dev' into dev 2025-10-15 19:17:20 +08:00
00e5f5ede6 10-15-变更子表更新方式 2025-10-15 19:08:43 +08:00
1b590bbcbd 10-15-修复 2025-10-15 17:30:17 +08:00
40d53dffba 10-15-方案选择帮助,印章帮助,预算分类 2025-10-15 13:51:35 +08:00
zt
db3af72d5f 优化 2025-10-15 10:49:45 +08:00
9604cab4d6 综合服务对应接口和结算采购合同对应接口 2025-10-15 10:30:54 +08:00
536b25d773 Merge remote-tracking branch 'origin/dev' into dev 2025-10-14 23:21:52 +08:00
e87cbce77a 解决ws不兼容 2025-10-14 23:21:23 +08:00
f34afd962d Merge remote-tracking branch 'origin/dev' into dev 2025-10-14 21:10:20 +08:00
lcj
98f23e2c02 修改bug 2025-10-14 20:24:17 +08:00
zt
b9507e1fd7 优化 2025-10-14 18:42:02 +08:00
1ceef7f1d1 1 2025-10-14 17:38:15 +08:00
lcj
0fb3fd70a6 进度计划甘特图 2025-10-14 17:21:37 +08:00
aab0a5e0b8 10-13-承包合同结算周期 2025-10-14 16:26:40 +08:00
f9d1a7a489 10-13-承包合同,变更,终止,方案选择 2025-10-14 16:22:38 +08:00
87e58ca4af 增加移动考勤机 2025-10-14 16:02:32 +08:00
lcj
d6263c6430 大屏质量、物资、识别记录 2025-10-14 15:12:32 +08:00
lg
253ef81066 分包合同信息 2025-10-14 15:01:31 +08:00
2f4bec42a3 大屏接口修改 2025-10-14 14:57:54 +08:00
zt
3879ce28b6 bug 2025-10-14 14:25:59 +08:00
lg
691b5341c7 采购合同 2025-10-14 11:03:46 +08:00
4a50dc6ff0 10-13-承包合同,变更,终止 2025-10-13 22:46:49 +08:00
d7e4c65afb Merge remote-tracking branch 'origin/dev' into dev 2025-10-13 22:45:07 +08:00
61b39d89de 大屏接口修改 2025-10-13 21:49:27 +08:00
2497527c77 供应商接口修改 2025-10-13 21:47:46 +08:00
zt
79f74434f7 bug 2025-10-13 21:20:44 +08:00
zt
bd0fe7228b 设计优化 2025-10-13 19:59:52 +08:00
66b45df3fb Merge remote-tracking branch 'origin/dev' into dev 2025-10-13 18:44:18 +08:00
38d6832f2c 表名枚举 2025-10-13 18:34:06 +08:00
8e51d67071 表名枚举 2025-10-13 18:32:53 +08:00
942ca4202a 10-13-承包合同信息完善,合作协议完善 2025-10-13 15:09:43 +08:00
zt
255a202c02 Merge remote-tracking branch 'origin/dev' into dev 2025-10-13 11:44:29 +08:00
zt
1033ee01fb 审批 2025-10-13 11:44:13 +08:00
201f7bd3a7 安全帽表名修改 2025-10-13 11:42:14 +08:00
8a7726e216 安全帽接口修改 2025-10-13 09:55:16 +08:00
lcj
bc85fe64a4 进度计划,施工产值 2025-10-13 09:39:21 +08:00
549fbe92de 10-12-承包合同信息 2025-10-12 21:32:13 +08:00
270071a5f3 Merge remote-tracking branch 'origin/dev' into dev 2025-10-12 21:31:41 +08:00
09cbb6a8c5 大屏接口修改 2025-10-12 20:56:08 +08:00
zt
f825b9f968 优化 2025-10-12 20:51:38 +08:00
f7b9d2f431 10-12-支付条款新增 2025-10-12 19:32:10 +08:00
742df7279b 10-12-承包合同 2025-10-12 18:52:18 +08:00
684209aa36 安全帽和大屏接口 2025-10-12 18:18:30 +08:00
d033b505e2 10-12-合作协议 2025-10-12 17:20:45 +08:00
59623f53a0 Merge remote-tracking branch 'origin/dev' into dev 2025-10-12 16:08:01 +08:00
b9cf8ea3de 10-12-新增银行卡,合作协议 2025-10-12 16:07:54 +08:00
45761415fa 批次需求计划优化 2025-10-12 15:23:35 +08:00
lcj
4dca396d11 进度计划,施工产值 2025-10-12 14:16:05 +08:00
0efaf12849 Merge remote-tracking branch 'origin/dev' into dev 2025-10-12 00:25:45 +08:00
lg
51686c212e 标前立项 2025-10-12 00:25:23 +08:00
lg
866c53c6cc Merge remote-tracking branch 'origin/dev' into dev 2025-10-12 00:24:44 +08:00
809494ffca Merge remote-tracking branch 'origin/dev' into dev 2025-10-11 23:38:07 +08:00
zt
7824803bf6 管理员和分包补卡 2025-10-11 20:59:45 +08:00
zt
5df3bb7baf 管理员和分包补卡 2025-10-11 19:23:53 +08:00
c7dcddb58e 10-11-项目信息 2025-10-11 19:14:51 +08:00
zt
cc64f16231 优化 2025-10-11 15:27:33 +08:00
26129e7433 10-11-安装包上传,事务分离 2025-10-11 14:49:08 +08:00
lg
e7aec88abf Merge remote-tracking branch 'origin/dev' into dev 2025-10-11 10:56:21 +08:00
lg
f820edebb5 标前立项 2025-10-11 10:56:07 +08:00
9d586f7b77 Merge remote-tracking branch 'origin/dev' into dev 2025-10-11 10:55:31 +08:00
lcj
00e9fa1ea3 根据配置文件抓拍图片 2025-10-11 10:50:14 +08:00
9a698857ce 10-11-项目信息,工程建设 2025-10-11 10:16:11 +08:00
b47cdb5732 大屏接口优化 2025-10-10 22:46:42 +08:00
zt
3bf7a1201f bug修改 2025-10-10 22:44:03 +08:00
lcj
bb38b6a6e1 添加抓拍,修改项目大屏 2025-10-10 21:57:57 +08:00
zt
11b5908d8c bug修改 2025-10-10 21:45:08 +08:00
zt
6c96c6f534 bug修改 2025-10-10 21:03:10 +08:00
lg
22a7500048 误删除 2025-10-10 20:59:39 +08:00
lg
412db4d348 误删除 2025-10-10 20:36:44 +08:00
lg
6a200b391e 1111 2025-10-10 20:12:13 +08:00
lg
6e0e867e57 Merge branch 'dev' of http://192.168.110.2:3000/lcj/xinnengyuan into dev 2025-10-10 20:11:33 +08:00
66d2f24256 10-10-1 2025-10-10 20:10:20 +08:00
lg
69e8e4169b 1111 2025-10-10 20:07:47 +08:00
33d051164e 10-10-项目信息初始化 2025-10-10 18:25:22 +08:00
2d18345087 10-10-修复2 2025-10-10 16:34:21 +08:00
ef10a4f0a4 10-10-修复 2025-10-10 16:33:12 +08:00
9784aa7ee3 Merge remote-tracking branch 'origin/dev' into dev 2025-10-10 16:14:55 +08:00
af069f3fa5 10-10-xzd项目经理推荐审批模块 2025-10-10 16:14:49 +08:00
zt
d8f5cc34ea bug修改 2025-10-10 15:22:17 +08:00
0870003967 Merge remote-tracking branch 'origin/dev' into dev 2025-10-10 14:42:48 +08:00
fb4ce63f59 10-10-xzd供应商信息模块 2025-10-10 14:42:34 +08:00
lcj
502cc55143 修改bug,建表 2025-10-10 10:08:23 +08:00
zt
372c825844 考勤优化 2025-10-09 18:32:50 +08:00
lg
ca256a28a1 xzd-客户信息 2025-10-08 19:35:40 +08:00
lcj
666e402d5d 修改进度计划判定逻辑 2025-10-01 15:07:12 +08:00
lcj
3630c13f59 修改bug 2025-09-30 23:16:30 +08:00
zt
334ff20129 考勤 2025-09-30 17:45:56 +08:00
lcj
3371ef9c1c 修改bug 2025-09-30 16:59:59 +08:00
lg
ed6b4c608f xzd-客户信息 2025-09-30 11:24:14 +08:00
lcj
cdd9266452 修改权限 2025-09-30 09:37:25 +08:00
lcj
a1450c4796 进度计划 2025-09-29 20:08:07 +08:00
lcj
a1ba33c06d 进度计划同步、大屏摄像头 2025-09-29 17:06:44 +08:00
zt
b0493e7de9 考勤 2025-09-29 17:03:55 +08:00
zt
7b00d67cf7 施工产值报错 2025-09-29 15:53:07 +08:00
3eae13e67a Merge remote-tracking branch 'origin/dev' into dev 2025-09-29 15:19:59 +08:00
9fe3cd494f 09-29-上传时间改为120秒,上传时删除原文件使用日志记录 2025-09-29 15:19:51 +08:00
zt
2c554321bb 数据转移 2025-09-29 09:54:34 +08:00
lcj
39038889b6 萤石云 2025-09-28 20:14:39 +08:00
zt
cbf4b3b22e 专业 2025-09-28 20:03:36 +08:00
lcj
3d3df16817 进度计划 2025-09-28 17:04:29 +08:00
c66d5f0789 设计出图优化 2025-09-28 16:57:24 +08:00
zt
d644df94dc 专业 2025-09-28 16:25:42 +08:00
zt
eb6a7f2373 考勤 2025-09-28 12:31:24 +08:00
lcj
fa625aff6d 修改bug 2025-09-28 12:30:21 +08:00
e64897246a 合规性手续bug修改 2025-09-28 10:54:02 +08:00
lcj
6c138d1f4d 修改bug 2025-09-28 09:46:50 +08:00
fdd1b8dfa0 批次需求计划修改实体类字段类型 2025-09-28 09:45:54 +08:00
zt
9f7b6d77d3 分包 2025-09-26 20:45:19 +08:00
zt
45999b0c03 分包 2025-09-26 18:55:07 +08:00
944d36e5e7 09-26-修复联系人列表 2025-09-26 11:37:24 +08:00
f87c67349d 批次需求计划修改 2025-09-26 10:23:01 +08:00
zt
259ddd46cf 优化 2025-09-25 20:37:50 +08:00
lcj
570e7dd019 进度计划、施工产值逻辑修改;合同 2025-09-25 20:30:34 +08:00
zt
4a27c7d179 Merge remote-tracking branch 'origin/dev' into dev 2025-09-25 18:39:10 +08:00
zt
f2912f0661 优化 2025-09-25 18:38:50 +08:00
cd4e1db7bd Merge remote-tracking branch 'origin/dev' into dev 2025-09-25 17:35:06 +08:00
23eab88db1 09-25-完善功能 2025-09-25 17:34:47 +08:00
a7004ac125 招标计划新增添加事务 2025-09-25 17:01:28 +08:00
f02cd59135 一览表查询版本修改 2025-09-25 16:43:01 +08:00
zt
d0e40bdd33 优化 2025-09-25 15:50:58 +08:00
zt
a34c07c64e 优化 2025-09-25 15:17:53 +08:00
af83c40d98 09-25-供应商入库更新修复 2025-09-25 11:26:33 +08:00
1bb59cc2f1 一览表查询版本修改 2025-09-25 10:29:17 +08:00
zt
e1b9b0e8c5 Merge remote-tracking branch 'origin/dev' into dev 2025-09-25 10:24:59 +08:00
zt
1de11bb110 安全 2025-09-25 10:24:39 +08:00
84c9946337 供应商入库修改 2025-09-24 19:36:40 +08:00
bc41175162 供应商重复导入修改 2025-09-24 14:59:06 +08:00
1e76e4ffe1 供应商导入修改 2025-09-24 14:48:35 +08:00
2952d978d2 Merge remote-tracking branch 'origin/dev' into dev 2025-09-24 14:45:29 +08:00
256e3f9c0d 09-24-通讯录uer过滤条件新增管理员过滤 2025-09-24 14:45:19 +08:00
faff11ad6f 修改物资设备清单相关修改 2025-09-24 14:36:04 +08:00
zt
a177ab3067 bug 2025-09-24 13:16:18 +08:00
zt
7f1971248a 设计人员 2025-09-24 12:35:19 +08:00
zt
4d6c7fe2c0 bug 2025-09-23 20:25:40 +08:00
278004788b 修改物资设备清单导入修改 2025-09-23 19:52:09 +08:00
a8744cc4cc 修改物资设备清单导入修改 2025-09-23 16:49:06 +08:00
20dc9b3e85 修改物资设备清单导入和批次需求计划新增 2025-09-23 14:23:23 +08:00
zt
d0c1a1337e 优化 2025-09-23 14:11:58 +08:00
zt
70553dff79 优化 2025-09-23 11:38:29 +08:00
8af5fb52ec 项目级大屏出勤统计修改查询范围 2025-09-23 09:21:05 +08:00
zt
b754e3ffc0 优化 2025-09-22 22:57:43 +08:00
lcj
d72f763545 进度计划 2025-09-22 22:10:04 +08:00
zt
683f58cdc8 身份证 2025-09-22 21:37:32 +08:00
zt
61dfb371f8 身份证 2025-09-22 21:36:35 +08:00
zt
9772f1a024 BUG和工资 2025-09-22 21:09:36 +08:00
5b6d3bf758 09-22-优化安装包文件上传 2025-09-22 20:56:02 +08:00
a2167e8227 Merge remote-tracking branch 'origin/dev' into dev 2025-09-22 17:23:46 +08:00
lcj
49c5689b4a bug修改 2025-09-22 17:11:49 +08:00
53413e2ddf Merge remote-tracking branch 'origin/dev' into dev 2025-09-22 17:11:23 +08:00
6c0deb23c6 项目列表删除goid 2025-09-22 16:51:17 +08:00
5cd202ceda 变更安全工单、增加题库操作 2025-09-22 15:32:47 +08:00
71078cd36f 项目列表增加项目概况 2025-09-22 15:09:09 +08:00
81c8938076 人员任命导入导出接口修改 2025-09-22 11:49:50 +08:00
lcj
ce99cdd623 AI识别同步进度计划 2025-09-21 23:59:16 +08:00
9ad44e727e 项目级大屏接口、人员任命导入导出接口 2025-09-20 20:13:38 +08:00
zt
275ed8946c Merge remote-tracking branch 'origin/dev' into dev 2025-09-20 20:08:02 +08:00
zt
325547f201 BUG 2025-09-20 20:07:50 +08:00
7fdd75da1f 变更 2025-09-20 19:59:35 +08:00
zt
5f8d494154 BUG,分包薪水转换 2025-09-20 19:16:56 +08:00
lcj
f1dffb54eb 无人机、红线、进度 2025-09-20 18:46:07 +08:00
zt
8e4200323a 人脸转换 2025-09-20 15:24:29 +08:00
zt
40a8f0770a 人脸转换 2025-09-20 15:08:44 +08:00
zt
7fcf5ef303 appbug 2025-09-20 10:16:32 +08:00
lcj
fc9b64fc36 修改bug 2025-09-19 20:28:48 +08:00
c7400d25fe 设计出图bug修改 2025-09-19 18:26:27 +08:00
zt
48a08ac729 数据 2025-09-19 15:38:55 +08:00
zt
31dcd00bbc 数据 2025-09-19 14:34:42 +08:00
zt
4e3d62af4a 物资 2025-09-19 11:40:19 +08:00
zt
1e7ffe891a 工作流和角色 2025-09-18 21:31:53 +08:00
zt
f706e73c30 施工人员文件处理 2025-09-18 18:27:29 +08:00
zt
a64ff2ff32 土地 2025-09-18 18:12:02 +08:00
zt
15b3176893 设计人员 2025-09-18 17:15:17 +08:00
lcj
ee7981a462 修改bug 2025-09-18 16:37:12 +08:00
5c86398b75 09-18-优化安装包文件上传,优化netty系统首次发送消息 2025-09-18 15:05:01 +08:00
5f3b24868f 考勤列表详情bug修改 2025-09-18 11:15:37 +08:00
zt
b8f223aea1 bug 2025-09-18 10:56:17 +08:00
lcj
bf6ea00b26 畅写 2025-09-18 08:57:37 +08:00
zt
0c4a697fea bug 2025-09-18 02:26:12 +08:00
zt
6d7aa8ca17 bug 2025-09-18 02:18:26 +08:00
zt
caa134dfc4 bug 2025-09-18 00:47:42 +08:00
zt
23f0f2fd16 bug 2025-09-17 22:55:35 +08:00
lcj
25690503e5 接入无人机大图,AI进度填报 2025-09-17 22:46:34 +08:00
928ba9783b gps大屏 2025-09-17 21:30:23 +08:00
6224b42479 09-17-优化 2025-09-17 20:02:35 +08:00
1d2ec60e68 09-17-修改通讯录获权限判断 2025-09-17 19:12:55 +08:00
b35ff07ba4 09-17-netty完善 2025-09-17 18:32:52 +08:00
zt
4ffb639d33 bug 2025-09-17 17:44:28 +08:00
6110374e67 bug修改 2025-09-17 16:40:15 +08:00
19f8e10714 获取工程量清单接口回退版本、项目级大屏人员定位接口 2025-09-17 16:14:04 +08:00
42c5f46f75 09-17-netty完善 2025-09-17 14:58:04 +08:00
646b503d47 09-17-netty连接后初始化只创建系统消息 2025-09-17 14:54:03 +08:00
f6ed7d3d7b app人员轨迹接口 2025-09-17 10:21:02 +08:00
lcj
223f1aee98 进度,人员bug 2025-09-16 22:01:07 +08:00
8b4e56e6e8 Merge remote-tracking branch 'origin/dev' into dev 2025-09-16 21:31:52 +08:00
b2ec975f22 09-16-01 2025-09-16 21:31:12 +08:00
zt
267d62e5a5 app 2025-09-16 21:23:56 +08:00
579fd04687 09-16-netty优化 2025-09-16 20:45:30 +08:00
4354d0a687 导入读取excel数据工具类优化 2025-09-16 18:39:02 +08:00
zt
0f9beafd9c 安全,质量 2025-09-16 16:53:21 +08:00
c07e9f76a6 bug修改 2025-09-16 16:23:49 +08:00
e42e81ab06 数据转换1.0 2025-09-16 16:15:17 +08:00
5d6d9020e7 09-15-netty优化,修复完善app版本模块 2025-09-16 16:10:06 +08:00
zt
7ee081c39c 考勤 2025-09-16 15:52:30 +08:00
lcj
d66d44460b 安全、质量、进度、施工人员;对象存储添加文件大小 2025-09-16 15:24:05 +08:00
zt
9d0c66b2d3 考勤 2025-09-16 09:34:03 +08:00
300579d32c Merge remote-tracking branch 'origin/dev' into dev 2025-09-15 20:14:41 +08:00
e8838a91d0 09-15-netty优化兼容其余类型,app版本模块 2025-09-15 20:14:30 +08:00
2f57979a41 合规性手续修改状态接口修改 2025-09-15 19:47:20 +08:00
zt
e075f8f6e5 考勤 2025-09-15 19:14:40 +08:00
6032c6fcba 合规性手续删除接口 2025-09-15 17:12:28 +08:00
da20820627 09-15-netty优化,系统消息发送方法添加roomId 2025-09-15 16:28:54 +08:00
e7c50c770e 09-15-netty优化,土地流转修复 2025-09-15 16:08:49 +08:00
ef68e7b7a8 Merge remote-tracking branch 'origin/dev' into dev 2025-09-15 15:35:46 +08:00
d9b879667b 09-15-netty优化,恢复用户列表权限,暂留部门列表权限 2025-09-15 15:35:28 +08:00
3e1b698ea8 09-14-netty优化,恢复用户列表权限,暂留部门列表权限 2025-09-15 15:24:52 +08:00
af81b1b740 物资工程量清单暂时复原 2025-09-15 11:18:19 +08:00
lcj
2d7f9ea42d 安全、质量 2025-09-15 09:27:47 +08:00
5b94ae37cd bug优化、app获取天气接口 2025-09-14 18:35:00 +08:00
26cf862d6e 09-14-netty优化 2025-09-14 17:40:52 +08:00
zt
f7cd344a0b bug 2025-09-14 16:58:23 +08:00
89c89cbfcd 数据转换 2025-09-14 16:52:43 +08:00
868616ea26 09-14-netty新增其他类型系统房间 2025-09-14 15:35:30 +08:00
b5cf663a2b 09-14-netty发送注册初始化消息 2025-09-14 10:59:26 +08:00
lcj
4c536ca269 安全、质量 2025-09-13 22:10:24 +08:00
zt
f0f30ce841 bug 2025-09-13 18:08:21 +08:00
4d2a2186c9 bug修改和批次需求计划优化 2025-09-13 18:03:14 +08:00
c277e5f80d 09-12-netty发送房间确认信息逻辑优化 2025-09-13 15:13:20 +08:00
21aae1f8c0 09-12-netty房间创建后发送确认消息 2025-09-13 12:34:25 +08:00
lcj
7e90c101e8 项目大屏 2025-09-12 23:08:40 +08:00
lcj
c3899ae6a2 企业大屏 2025-09-12 22:16:33 +08:00
lcj
c662e1aa4d 接go数据 2025-09-12 21:16:00 +08:00
91f01dc012 09-12-netty优化 2025-09-12 20:18:13 +08:00
ce972d030f 机械台账管理接口 2025-09-12 20:10:26 +08:00
lcj
dd025df653 企业大屏 2025-09-12 19:49:28 +08:00
d77e12ee4e 09-12-netty优化 2025-09-12 19:15:00 +08:00
zt
9afda7305c 考勤数据 2025-09-12 17:18:47 +08:00
974b11f8d3 09-12-netty优化 2025-09-12 15:43:51 +08:00
a1d1aaff49 字体文件 2025-09-12 11:57:16 +08:00
zt
9402c3c9f3 app 2025-09-12 09:54:19 +08:00
8e9307bf00 09-10-netty新增隐藏聊天接口 2025-09-11 20:27:24 +08:00
c68d6cb53c gps新增数据来源 2025-09-11 20:17:47 +08:00
8e84195e98 09-10-netty修复消除未读消息,修改列表赋值 2025-09-11 19:36:36 +08:00
542c4e91ac 09-10-netty优化系统房间的创建 2025-09-11 17:24:55 +08:00
47b0a4b087 09-10-netty优化,将系统消息存储为JSON 2025-09-11 17:18:51 +08:00
6ace8b0dc2 09-10-netty优化,序号修复,新增移除审核 2025-09-11 16:04:01 +08:00
1e33027d4f 修改金额精度问题 2025-09-11 15:26:07 +08:00
9fbc9dbc45 09-10-netty优化已读返回 2025-09-11 15:21:19 +08:00
8bf12d04cd 09-10-netty优化已读返回 2025-09-11 15:18:53 +08:00
00dcc00b05 09-10-netty优化 2025-09-11 11:17:55 +08:00
0b29401112 09-10-netty发送时添加name字段 2025-09-11 11:14:22 +08:00
lcj
e8c78865cb 接go数据 2025-09-11 09:23:39 +08:00
zt
a8cb16ab3f 通知 2025-09-10 20:21:01 +08:00
2c45762c66 09-10-netty优化 2025-09-10 19:41:11 +08:00
056b28af31 我的任务优化、工程量清单优化、gps消息websocket连接、物资管理:物资验收入库添加附件 2025-09-10 19:38:10 +08:00
lcj
7dd6d97a3e 进度管理app 2025-09-10 19:18:30 +08:00
zt
697beb67c4 通知 2025-09-10 17:34:49 +08:00
lcj
4d627af3a1 进度管理app、注解翻译项目名称 2025-09-10 16:43:49 +08:00
ab332c462f 09-10-netty设置系统消息type为2 2025-09-10 16:11:30 +08:00
0f3d1e38be 09-10-netty优化 2025-09-10 16:00:43 +08:00
lcj
4392a287cc 修改bug 2025-09-10 10:03:53 +08:00
lcj
f38538be33 修改进度管理 2025-09-10 00:15:55 +08:00
lcj
ede1e501b4 企业级大屏 2025-09-09 23:42:24 +08:00
4a2b62cf92 我的任务bug修改 2025-09-09 21:52:49 +08:00
zt
325f392e8f 大屏,消息 2025-09-09 20:39:00 +08:00
lcj
5b991396c2 企业级大屏 2025-09-09 19:49:14 +08:00
c75563b46a 09-09-修改 2025-09-09 18:53:28 +08:00
724ebf8dbd 09-09-netty完善修改 2025-09-09 18:47:48 +08:00
a52b9078a0 gps定位接口 2025-09-09 17:47:49 +08:00
9d682a3290 09-09-netty发送系统消息 2025-09-09 17:08:39 +08:00
lcj
abad289c2b 进度管理,企业级大屏,修改bug 2025-09-09 15:42:00 +08:00
820188863e 修改一览表单价精度 2025-09-09 15:24:17 +08:00
113b5debc9 供应商bug修改 2025-09-09 10:40:17 +08:00
6b4cd4ae0d Merge remote-tracking branch 'origin/dev' into dev 2025-09-09 09:12:54 +08:00
261dd0b643 09-09-netty消息搭建 2025-09-09 09:12:19 +08:00
zt
71f3810e51 Merge remote-tracking branch 'origin/dev' into dev 2025-09-08 20:03:11 +08:00
zt
fa835684d4 消息 2025-09-08 20:02:51 +08:00
e19ef3003a bug修改 2025-09-08 20:00:29 +08:00
zt
8a18223d06 二维码 2025-09-08 16:38:01 +08:00
c90828f98e 09-08-土地流转新增type区分完成和未完成 2025-09-08 16:02:26 +08:00
2ecb0063bf 限价、投标、招采、物资一览bug修改 2025-09-08 15:33:03 +08:00
zt
998547e63f bug 2025-09-08 11:47:14 +08:00
zt
78829ef5e7 bug 2025-09-08 11:42:36 +08:00
zt
da0dd8f78f bug 2025-09-06 19:20:40 +08:00
lcj
96d0406931 物资、里程碑进度execl导出 2025-09-06 19:07:10 +08:00
d7616960c6 gpsbug修改 2025-09-06 18:48:39 +08:00
66e8495859 bug修改 2025-09-06 18:35:51 +08:00
95c2858a64 bug修改 2025-09-06 18:33:06 +08:00
5cbb0c630b bug修改 2025-09-06 18:24:27 +08:00
lcj
e0cc521291 进度、物资管理模块 2025-09-06 15:30:57 +08:00
ff9f49b1d9 09-06-修复bug,完善功能 2025-09-06 15:16:41 +08:00
zt
b738bb821d app 2025-09-06 13:06:33 +08:00
2cea57646d 设计管理设计出图导入导出 2025-09-06 12:52:12 +08:00
lcj
ab5cd491d6 修改ai工单 2025-09-04 22:25:10 +08:00
lcj
3f3e20a64b 项目大屏进度数据统计,修改ai工单逻辑 2025-09-04 21:30:18 +08:00
zt
f5d9cb7fc1 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 21:27:26 +08:00
zt
5b05d2eb40 版本号 2025-09-04 21:27:11 +08:00
fbffc18a9f 考试卷app 2025-09-04 21:26:19 +08:00
zt
490820d080 版本号 2025-09-04 20:26:56 +08:00
zt
8e9b7c9b14 优化 2025-09-04 20:17:25 +08:00
ae3738c098 增加iText 7 核心模块 2025-09-04 19:57:50 +08:00
zt
127059e934 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 17:45:42 +08:00
zt
742e67af23 考勤 2025-09-04 17:45:21 +08:00
lcj
4e61a4afe9 人员工资、退场,巡检工单 2025-09-04 17:05:00 +08:00
43d249d68a 配置文件修改 2025-09-04 15:18:14 +08:00
dc8a89f05e gps接口 2025-09-04 11:23:50 +08:00
17d4041ef3 变更jar,增加考试卷 2025-09-04 10:56:54 +08:00
zt
d19cda78b3 考勤 2025-09-04 09:27:21 +08:00
2f0b548f20 BUG修改 2025-09-03 20:36:55 +08:00
lcj
f1aed20560 安全日志、ai工单接口 2025-09-03 15:44:13 +08:00
zt
8c412d033b 考勤 2025-09-03 15:39:13 +08:00
a929225ed5 09-03-修复供应商入库修改 2025-09-03 15:11:01 +08:00
zt
3b6b1d53a9 app,角色,菜单 2025-09-03 10:26:28 +08:00
lcj
81162852a2 修改人员实名认证 2025-09-03 10:24:09 +08:00
lcj
f584e6233c 修改bug 2025-09-02 20:30:01 +08:00
e8da350f0b 收资清单模板导出接口优化 2025-09-02 19:08:16 +08:00
e916829032 收资清单模板导出接口优化 2025-09-02 18:58:56 +08:00
8c131cb9a5 新增收资清单模板导出接口 2025-09-02 18:57:32 +08:00
lcj
9aef0d4b86 物资领料逻辑修改 app人员管理接口 2025-09-02 17:32:42 +08:00
de5c569f88 09-02-更新apifox模块 2025-09-02 16:54:01 +08:00
lcj
79edeb6ccd 安全模块、人员模块app接口 2025-09-02 15:14:06 +08:00
a3ef525ab6 修改设计出图bug 2025-09-02 09:54:26 +08:00
659e4e3d5f 09-02-完善税率字段对应sql 2025-09-02 09:11:33 +08:00
lcj
96e6c75949 修改材料设备出入库逻辑 2025-09-01 17:33:19 +08:00
711c473749 09-01-供应商入库新增导入,修改字段;物资设备清单新增按设备名称查询,新增税率字段. 2025-09-01 17:08:21 +08:00
4636aa3c05 修改投标成本清单列表查询接口 2025-08-30 06:49:46 +08:00
lcj
788f13fa7b 修改采购联系单 2025-08-30 06:29:25 +08:00
a588b94310 修改分标策划、招标计划新增接口 2025-08-30 04:59:51 +08:00
lcj
b44de3ff49 修改站班会日期查询 2025-08-30 03:58:37 +08:00
lcj
5d643fbc6a 修改班组 2025-08-30 03:47:18 +08:00
lcj
19fd73f4c8 修改施工人员身份证转换 2025-08-30 03:32:36 +08:00
lcj
a07792c8e3 修改进度、产值 2025-08-30 03:25:03 +08:00
zt
8a29ffdd2e 优化 2025-08-30 02:05:48 +08:00
d46f672b9a 修改联系单排序 2025-08-30 00:53:31 +08:00
lcj
d6528845e4 修改项目结构,施工产值 2025-08-30 00:33:17 +08:00
lcj
0ff805683f 修改物质供货总计划逻辑 2025-08-29 23:18:22 +08:00
3f79a955b3 代码合并 2025-08-29 22:37:56 +08:00
zt
971c8c277d 优化 2025-08-29 20:52:14 +08:00
lcj
12f02638a2 修改物质供货总计划逻辑 2025-08-29 20:15:53 +08:00
1883 changed files with 164043 additions and 3730 deletions

Binary file not shown.

View File

@ -307,7 +307,6 @@
<artifactId>snail-job-client-job-core</artifactId> <artifactId>snail-job-client-job-core</artifactId>
<version>${snailjob.version}</version> <version>${snailjob.version}</version>
</dependency> </dependency>
<!-- 加密包引入 --> <!-- 加密包引入 -->
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>

View File

@ -6,6 +6,7 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -28,6 +29,8 @@ import org.dromara.common.social.utils.SocialUtils;
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.common.tenant.helper.TenantHelper; import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.system.domain.bo.SysTenantBo; import org.dromara.system.domain.bo.SysTenantBo;
import org.dromara.system.domain.vo.SysClientVo; import org.dromara.system.domain.vo.SysClientVo;
import org.dromara.system.domain.vo.SysTenantVo; import org.dromara.system.domain.vo.SysTenantVo;
@ -41,16 +44,20 @@ import org.dromara.web.domain.vo.TenantListVo;
import org.dromara.web.service.IAuthStrategy; import org.dromara.web.service.IAuthStrategy;
import org.dromara.web.service.SysLoginService; import org.dromara.web.service.SysLoginService;
import org.dromara.web.service.SysRegisterService; import org.dromara.web.service.SysRegisterService;
import org.dromara.websocket.domain.ChatGroup;
import org.dromara.websocket.service.Impl.ChatGroupServiceImpl;
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.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/** /**
* 认证 * 认证
@ -72,6 +79,7 @@ public class AuthController {
private final ISysSocialService socialUserService; private final ISysSocialService socialUserService;
private final ISysClientService clientService; private final ISysClientService clientService;
private final ScheduledExecutorService scheduledExecutorService; private final ScheduledExecutorService scheduledExecutorService;
private final ChatGroupServiceImpl chatGroupService;
/** /**
@ -103,10 +111,7 @@ public class AuthController {
// Long userId = LoginHelper.getUserId(); // Long userId = LoginHelper.getUserId();
// scheduledExecutorService.schedule(() -> { // scheduledExecutorService.schedule(() -> {
// SseMessageDto dto = new SseMessageDto(); // chatGroupService.createSystem(userId,client.getClientKey());
// dto.setMessage("欢迎登录新能源项目管理系统");
// dto.setUserIds(List.of(userId));
// SseMessageUtils.publishMessage(dto);
// }, 5, TimeUnit.SECONDS); // }, 5, TimeUnit.SECONDS);
return R.ok(loginVo); return R.ok(loginVo);
} }
@ -193,6 +198,17 @@ public class AuthController {
return R.ok(); return R.ok();
} }
@PostMapping("/app/register")
public R<Void> appRegister(@Validated @RequestBody RegisterBody user) {
if("sms".equals(user.getGrantType())){
registerService.appSmsRegister(user);
}else {
registerService.appRegister(user);
}
return R.ok();
}
/** /**
* 登录页面租户下拉框 * 登录页面租户下拉框
* *

View File

@ -57,16 +57,23 @@ public class CaptchaController {
*/ */
@RateLimiter(key = "#phonenumber", time = 60, count = 1) @RateLimiter(key = "#phonenumber", time = 60, count = 1)
@GetMapping("/resource/sms/code") @GetMapping("/resource/sms/code")
public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) { public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber,String type) {
String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber; String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber;
String code = RandomUtil.randomNumbers(4); String code = RandomUtil.randomNumbers(4);
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
// 验证码模板id 自行处理 (查数据库或写死均可) // 验证码模板id 自行处理 (查数据库或写死均可)
String templateId = "";
LinkedHashMap<String, String> map = new LinkedHashMap<>(1); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("code", code); map.put("1", code);
SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); map.put("2", Constants.CAPTCHA_EXPIRATION.toString());
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map); String configName;
if("login".equals(type)){
configName = "config2";
}else{
configName = "config3";
}
SmsBlend smsBlend = SmsFactory.getSmsBlend(configName);
SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, map);
if (!smsResponse.isSuccess()) { if (!smsResponse.isSuccess()) {
log.error("验证码短信发送异常 => {}", smsResponse); log.error("验证码短信发送异常 => {}", smsResponse);
return R.fail(smsResponse.getData().toString()); return R.fail(smsResponse.getData().toString());

View File

@ -55,7 +55,8 @@ public class UserActionListener implements SaTokenListener {
String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY); String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY);
String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY); String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY);
dto.setUserName(username); dto.setUserName(username);
dto.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY)); String clientId = (String) loginModel.getExtra(LoginHelper.CLIENT_KEY);
dto.setClientKey(clientId);
dto.setDeviceType(loginModel.getDevice()); dto.setDeviceType(loginModel.getDevice());
dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY)); dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY));
TenantHelper.dynamic(tenantId, () -> { TenantHelper.dynamic(tenantId, () -> {
@ -75,7 +76,7 @@ public class UserActionListener implements SaTokenListener {
SpringUtils.context().publishEvent(logininforEvent); SpringUtils.context().publishEvent(logininforEvent);
// 更新登录信息 // 更新登录信息
loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip); loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip);
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); log.info("user doLogin, userId:{}, token:{}, clientid{}", loginId, tokenValue, clientId);
} }
/** /**

View File

@ -77,6 +77,90 @@ public class SysRegisterService {
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success")); recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
} }
/**
* 注册
*/
public void appRegister(RegisterBody registerBody) {
String tenantId = registerBody.getTenantId();
String username = registerBody.getPhonenumber();
String password = registerBody.getPassword();
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
// 校验密码是否符合要求
// String pattern = "^(?!.*\\s)(?!^[a-zA-Z]+$)(?!^[0-9]+$)(?!^[^a-zA-Z0-9]+$)(?!^[a-zA-Z0-9]+$).{8,18}$";
// boolean isValid = password.matches(pattern);
// if (!isValid) {
// throw new UserException("注册失败密码需满足818位包含大小写字母、数字、特殊字符中的至少三种组合");
// }
SysUserBo sysUser = new SysUserBo();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPhonenumber(username);
sysUser.setPassword(BCrypt.hashpw(password));
sysUser.setUserType(userType);
sysUser.setEmail(registerBody.getEmail());
SysUser sysUserByPhonenumber = userMapper.selectDefFlagUser(username);
if(sysUserByPhonenumber != null){
sysUser.setUserId(sysUserByPhonenumber.getUserId());
userMapper.updateDefFlag(sysUser);
userMapper.updateConstructionUser(sysUserByPhonenumber.getUserId());
}else {
boolean exist = TenantHelper.dynamic(tenantId, () -> {
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getPhonenumber, sysUser.getPhonenumber()));
});
if (exist) {
throw new UserException("user.register.save.error", username);
}
boolean regFlag = userService.registerUser(sysUser, tenantId);
if (!regFlag) {
throw new UserException("user.register.error");
}
}
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/**
* 短信注册
*/
public void appSmsRegister(RegisterBody registerBody) {
String tenantId = registerBody.getTenantId();
String username = registerBody.getPhonenumber();
String smsCode = registerBody.getSmsCode();
validateSmsCode(tenantId, username, smsCode);
// 校验用户类型是否存在
String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
// 验证码开关
SysUserBo sysUser = new SysUserBo();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPhonenumber(username);
sysUser.setUserType(userType);
boolean exist = TenantHelper.dynamic(tenantId, () -> {
return userMapper.exists(new LambdaQueryWrapper<SysUser>()
.eq(SysUser::getPhonenumber, sysUser.getPhonenumber()));
});
if (exist) {
throw new UserException("user.register.save.error", username);
}
boolean regFlag = userService.registerUser(sysUser, tenantId);
if (!regFlag) {
throw new UserException("user.register.error");
}
recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
}
/** /**
* 校验验证码 * 校验验证码
* *
@ -98,6 +182,18 @@ public class SysRegisterService {
} }
} }
/**
* 校验短信验证码
*/
private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
if (StringUtils.isBlank(code)) {
recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
throw new CaptchaExpireException();
}
return code.equals(smsCode);
}
/** /**
* 记录登录信息 * 记录登录信息
* *

View File

@ -19,14 +19,14 @@ snail-job:
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表 # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
server: server:
host: 192.168.110.119 host: 127.0.0.1
port: 17888 port: 17888
# 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段
namespace: ${spring.profiles.active} namespace: ${spring.profiles.active}
# 随主应用端口漂移 # 随主应用端口漂移
port: 2${server.port} port: 2${server.port}
# 客户端ip指定 # 客户端ip指定
host: host: 127.0.0.1
# RPC类型: netty, grpc # RPC类型: netty, grpc
rpc-type: grpc rpc-type: grpc
@ -52,14 +52,38 @@ 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
# username: xinnengyuan
# password: mEZPC5Sdf3r2HENi
# 从库数据源 # 从库数据源
slave:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
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
password: nWKDKRNRT48tFBdh
slave1:
lazy: true
type: ${spring.datasource.type}
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
username: zmkgprod
password: MaY8nehwWkJriWPm
slave2:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
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
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/zmkgdev?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: zmkgdev # username: zmkgprod
# password: JhYxREf25AXdy3h8 # password: MaY8nehwWkJriWPm
# oracle: # oracle:
# type: ${spring.datasource.type} # type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver # driverClassName: oracle.jdbc.OracleDriver
@ -102,7 +126,7 @@ spring.data:
# 端口默认为6379 # 端口默认为6379
port: 9287 port: 9287
# 数据库索引 # 数据库索引
database: 10 database: 16
# redis 密码必须配置 # redis 密码必须配置
password: syar23rdsaagdrsa password: syar23rdsaagdrsa
# 连接超时时间 # 连接超时时间
@ -161,7 +185,7 @@ sms:
# 配置源类型用于标定配置来源(interface,yaml) # 配置源类型用于标定配置来源(interface,yaml)
config-type: yaml config-type: yaml
# 用于标定yml中的配置是否开启短信拦截接口配置不受此限制 # 用于标定yml中的配置是否开启短信拦截接口配置不受此限制
restricted: true restricted: false
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效 # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
minute-max: 1 minute-max: 1
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效 # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
@ -180,12 +204,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
--- # 三方授权 --- # 三方授权
@ -274,7 +331,10 @@ dxf2GeoJson:
file-name: main.exe file-name: main.exe
ys7: ys7:
app-key: 3acf9f1a43dc4209841e0893003db0a2 app-key: 3acf9f1a43dc4209841e0893003db0a2
app-secret: 4bbf3e9394f55d3af6e3af27b2d3db36 app-secret: 09e29c70ae1161fbc3ce2030fc09ba2e
job:
capture-enabled: false # 控制是否启用萤石抓拍任务
device-sync-enabled: false # 控制是否同步萤石设备
#ys7: #ys7:
# app-key: 081b0d6d5f7f4de8bc5c7fa350fb26ec # app-key: 081b0d6d5f7f4de8bc5c7fa350fb26ec
# app-secret: caa37b9f60ef02deb57e563bc190e6db # app-secret: caa37b9f60ef02deb57e563bc190e6db
@ -287,7 +347,10 @@ 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://192.168.110.151:7788 url: http://192.168.110.151:7788
# 无人机大图
drone:
url: http://192.168.110.2:9512

View File

@ -290,3 +290,6 @@ recognizer:
qrCode: qrCode:
url: http://xny.yj-3d.com:7171 url: http://xny.yj-3d.com:7171
# 无人机大图
drone:
url: http://192.168.110.2:9512

View File

@ -16,7 +16,7 @@ spring.boot.admin.client:
--- # snail-job 配置 --- # snail-job 配置
snail-job: snail-job:
enabled: false enabled: true
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
group: "ruoyi_group" group: "ruoyi_group"
# SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表 # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表
@ -29,7 +29,7 @@ snail-job:
# 随主应用端口漂移 # 随主应用端口漂移
port: 2${server.port} port: 2${server.port}
# 客户端ip指定 # 客户端ip指定
host: host: 127.0.0.1
# RPC类型: netty, grpc # RPC类型: netty, grpc
rpc-type: grpc rpc-type: grpc
@ -60,6 +60,21 @@ spring:
# 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/zmkgc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username: zmkgc
# password: nWKDKRNRT48tFBdh
# slave1:
# lazy: true
# type: ${spring.datasource.type}
# 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
# username: zmkgprod
# password: MaY8nehwWkJriWPm
# # 从库数据源
# slave:
# lazy: true
# type: ${spring.datasource.type}
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# username: # username:
# password: # password:
@ -164,7 +179,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 +198,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:
@ -276,7 +324,10 @@ dxf2GeoJson:
file-name: main file-name: main
ys7: ys7:
app-key: 3acf9f1a43dc4209841e0893003db0a2 app-key: 3acf9f1a43dc4209841e0893003db0a2
app-secret: 4bbf3e9394f55d3af6e3af27b2d3db36 app-secret: 09e29c70ae1161fbc3ce2030fc09ba2e
job:
capture-enabled: false # 控制是否启用萤石抓拍任务
device-sync-enabled: true # 控制是否同步萤石设备
# 斯巴达算法 # 斯巴达算法
sparta: sparta:
url: http://119.3.204.120:8040 url: http://119.3.204.120:8040
@ -286,7 +337,10 @@ 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:7788 url: http://xny.yj-3d.com:7788
# 无人机大图
drone:
url: http://192.168.110.2:9512

View File

@ -122,10 +122,14 @@ security:
- /warm-flow-ui/** - /warm-flow-ui/**
- /warm-flow/** - /warm-flow/**
- /other/ys7Device/webhook - /other/ys7Device/webhook
- /**/changxie/callback/**
- /progress/progressPlanDetail/insert/numberAI
- /project/project/list/sub/matrix/**
- /gps/equipment/dataAcceptance
- /resource/oss/upload
# todo 仅测试 # todo 仅测试
- /facility/matrix/** - /facility/matrix/**
- /**/changxie/callback/** - /hat/device/data
- /gps/equipment/dataAcceptance
# 多租户配置 # 多租户配置
tenant: tenant:
@ -249,8 +253,8 @@ springdoc:
packages-to-scan: org.dromara.design packages-to-scan: org.dromara.design
- group: 13.工作流模块 - group: 13.工作流模块
packages-to-scan: org.dromara.workflow packages-to-scan: org.dromara.workflow
- group: 14.罗成模块 - group: 14.合同模块
packages-to-scan: org.dromara.cory packages-to-scan: org.dromara.ctr
- group: 15.无人机模块 - group: 15.无人机模块
packages-to-scan: org.dromara.drone packages-to-scan: org.dromara.drone
- group: 20.代码生成模块 - group: 20.代码生成模块
@ -263,8 +267,6 @@ springdoc:
packages-to-scan: org.dromara.out packages-to-scan: org.dromara.out
- group: 19.消息模块 - group: 19.消息模块
packages-to-scan: org.dromara.message packages-to-scan: org.dromara.message
# - group: 20.手续模块
# packages-to-scan: org.dromara.formalities
- group: 21.分标策划模块 - group: 21.分标策划模块
packages-to-scan: org.dromara.tender packages-to-scan: org.dromara.tender
- group: 22.大屏模块 - group: 22.大屏模块
@ -273,13 +275,16 @@ springdoc:
packages-to-scan: org.dromara.bidding packages-to-scan: org.dromara.bidding
- group: 23.GPS定位模块 - group: 23.GPS定位模块
packages-to-scan: org.dromara.gps packages-to-scan: org.dromara.gps
- group: 24.招标模块
# - group: 20.合同模块 packages-to-scan: org.dromara.tender
# packages-to-scan: org.dromara.ctr # - group: 25.app版本模块
# - group: 21.招标模块 # packages-to-scan: org.dromara.app
# packages-to-scan: org.dromara.tender - group: 25.数据迁移模块
packages-to-scan: org.dromara.transferData
- group: 26.netty消息模块
packages-to-scan: org.dromara.websocket
- group: 27.新中大模块
packages-to-scan: org.dromara.xzd
# knife4j的增强配置不需要增强可以不配 # knife4j的增强配置不需要增强可以不配
knife4j: knife4j:
enable: true enable: true
@ -294,6 +299,7 @@ xss:
excludeUrls: excludeUrls:
- /system/notice - /system/notice
- /warm-flow/save-xml - /warm-flow/save-xml
- /project/project
# 全局线程池相关配置 # 全局线程池相关配置
# 如使用JDK21请直接使用虚拟线程 不要开启此配置 # 如使用JDK21请直接使用虚拟线程 不要开启此配置
@ -332,12 +338,13 @@ sse:
copy: /task/taskCopyList copy: /task/taskCopyList
project: /personnel-management/project project: /personnel-management/project
violationRecord: /safety-management/ai/violationRecord violationRecord: /safety-management/ai/violationRecord
drawing: /design-management/volumeCatalog
--- # websocket --- # websocket
websocket: websocket:
# 如果关闭 需要和前端开关一起关闭 # 如果关闭 需要和前端开关一起关闭
enabled: false enabled: true
# 路径 # 路径
path: /resource/websocket path: /resource/websocket
# 设置访问源地址 # 设置访问源地址

View File

@ -1,21 +1,61 @@
package org.dromara.test; package org.dromara.test;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.utils.IdCardEncryptorUtil;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.contractor.service.ISubUserSalaryDetailService;
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.service.IFacMatrixService; import org.dromara.facility.service.IFacMatrixService;
import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService; import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService;
import org.dromara.facility.service.IFacPhotovoltaicPanelService;
import org.dromara.manager.recognizermanager.vo.RecognizeConvertCoordinateResult;
import org.dromara.manager.ys7manager.Ys7Constant;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.manager.ys7manager.vo.Ys7ResponseVo;
import org.dromara.other.domain.OthYs7Device;
import org.dromara.other.service.IOthYs7DeviceService;
import org.dromara.out.domain.OutConstructionValue;
import org.dromara.out.domain.OutConstructionValueRange;
import org.dromara.out.service.IOutConstructionValueRangeService;
import org.dromara.out.service.IOutConstructionValueService;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
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.progress.service.IPgsProgressPlanDetailService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.system.service.ISysDeptService; import org.dromara.system.service.ISysDeptService;
import org.dromara.tender.service.impl.TenderSupplierInputServiceImpl;
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.Date; import java.math.BigDecimal;
import java.util.List; import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/** /**
* @author lilemy * @author lilemy
@ -34,6 +74,9 @@ public class DemoTest {
@Resource @Resource
private IPgsProgressCategoryTemplateService progressCategoryTemplateService; private IPgsProgressCategoryTemplateService progressCategoryTemplateService;
@Resource
private IPgsProgressPlanDetailService progressPlanDetailService;
@Resource @Resource
private IFacMatrixService matrixService; private IFacMatrixService matrixService;
@ -45,6 +88,227 @@ public class DemoTest {
@Resource @Resource
private ISysDeptService deptService; private ISysDeptService deptService;
@Autowired
private TenderSupplierInputServiceImpl tenderSupplierInputService;
@Resource
private ISubConstructionUserService constructionUserService;
@Resource
private ISubUserSalaryDetailService userSalaryDetailService;
@Resource
private IdCardEncryptorUtil idCardEncryptorUtil;
@Resource
private IFacPhotovoltaicPanelService photovoltaicPanelService;
@Resource
private IOutConstructionValueRangeService constructionValueRangeService;
@Resource
private IOutConstructionValueService constructionValueService;
@Resource
private IOthYs7DeviceService ys7DeviceService;
@Resource
private Ys7Manager ys7Manager;
@Test
void testConstructionValue() {
/* LocalDate today = LocalDate.now();
// 找到本周一
LocalDate thisMonday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
// 上周一 = 本周一 - 1 周
LocalDate lastMonday = thisMonday.minusWeeks(1);
// 上周日 = 上周一 + 6 天
LocalDate lastSunday = lastMonday.plusDays(6);
log.info("执行定时任务:同步 {}至{} 计划详情到施工产值", lastMonday, lastSunday);
Boolean synced = progressPlanDetailService.syncPlanDetail2ConstructionValue(lastMonday, lastSunday, null);*/
LocalDate start = LocalDate.of(2024, 1, 1); // 起始时间2024-01-01
LocalDate end = LocalDate.of(2025, 10, 20); // 截止时间2025-09-15
// 如果起始不是周一,调整到当周的周一
if (start.getDayOfWeek() != DayOfWeek.MONDAY) {
start = start.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
}
while (!start.isAfter(end)) {
LocalDate monday = start;
LocalDate sunday = start.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
// 输出本周的周一和周日
System.out.println(monday + " ~ " + sunday);
log.info("执行定时任务:同步 {}至{} 计划详情到施工产值", monday, sunday);
// Boolean synced = progressPlanDetailService.syncPlanDetail2ConstructionValue(start, now, null);
// 获取范围时间内的计划详情
List<PgsProgressPlanDetail> planDetailList = progressPlanDetailService.lambdaQuery()
.ge(PgsProgressPlanDetail::getDate, monday)
.le(PgsProgressPlanDetail::getDate, sunday)
.ne(PgsProgressPlanDetail::getFinishedNumber, BigDecimal.ZERO)
// .eq(PgsProgressPlanDetail::getStatus, "1")
.list();
if (CollUtil.isEmpty(planDetailList)) {
// 下一周
start = start.plusWeeks(1);
continue;
}
// 获取进度类别
List<Long> categoryIds = planDetailList.stream()
.map(PgsProgressPlanDetail::getProgressCategoryId)
.distinct()
.toList();
List<PgsProgressCategory> categoryList = progressCategoryService.lambdaQuery()
.in(CollUtil.isNotEmpty(categoryIds), PgsProgressCategory::getId, categoryIds)
.list();
Map<Long, PgsProgressCategory> categoryMap = categoryList.stream()
.collect(
Collectors.toMap(PgsProgressCategory::getId,
Function.identity(),
(v1, v2) -> v1)
);
// 为每一个项目创建一个施工产值范围
Set<Long> projectIds = planDetailList.stream()
.map(PgsProgressPlanDetail::getProjectId).collect(Collectors.toSet());
// 获取所有父级项目
List<BusProject> projectList = projectService.listByIds(projectIds);
List<Long> allProjectIds = projectList
.stream().map(project -> {
if (project.getPId() != 0L) {
return project.getPId();
} else {
return project.getId();
}
}).distinct().toList();
// 根据项目区分
Map<Long, List<PgsProgressPlanDetail>> detailMap = planDetailList.stream()
.collect(Collectors.groupingBy(PgsProgressPlanDetail::getProjectId));
List<OutConstructionValue> saveList = new ArrayList<>();
List<PgsProgressPlanDetail> allUpdateList = new ArrayList<>();
List<OutConstructionValueRange> ranges = allProjectIds.stream().map(id -> {
OutConstructionValueRange range = new OutConstructionValueRange();
long rangeId = IdWorker.getId(range);
range.setId(rangeId);
range.setProjectId(id);
range.setStartDate(monday);
range.setEndDate(sunday);
// 获取所有子项目
List<Long> subProject = new ArrayList<>(projectList.stream()
.filter(project -> Objects.equals(project.getPId(), id))
.map(BusProject::getId)
.distinct()
.toList());
subProject.add(id);
List<PgsProgressPlanDetail> detailList = new ArrayList<>();
for (Long p : subProject) {
List<PgsProgressPlanDetail> details = detailMap.getOrDefault(p, List.of());
detailList.addAll(details);
}
if (CollUtil.isEmpty(detailList)) {
return null;
}
BigDecimal allConstructionValue = BigDecimal.ZERO;
BigDecimal allOwnerValue = BigDecimal.ZERO;
List<PgsProgressPlanDetail> updateList = new ArrayList<>();
for (PgsProgressPlanDetail planDetail : detailList) {
OutConstructionValue value = new OutConstructionValue();
Long progressCategoryId = planDetail.getProgressCategoryId();
PgsProgressCategory category = categoryMap.get(progressCategoryId);
if (category == null) {
continue;
}
value.setProjectId(id);
value.setRangeId(rangeId);
value.setMatrixId(category.getMatrixId());
value.setProgressCategoryId(progressCategoryId);
value.setDetailId(planDetail.getId());
BigDecimal finishedNumber = planDetail.getFinishedNumber();
BigDecimal aiFill = planDetail.getAiFill();
// 如果完成数量为0, 则不保存
if (finishedNumber.compareTo(BigDecimal.ZERO) == 0) {
continue;
}
value.setArtificialNum(finishedNumber.subtract(aiFill).intValue());
value.setUavNum(aiFill.intValue());
value.setPlanNum(planDetail.getPlanNumber().intValue());
value.setReportDate(planDetail.getDate());
value.setPlanDate(planDetail.getDate());
// 计算产值
BigDecimal constructionPrice = category.getConstructionPrice();
BigDecimal ownerPrice = category.getOwnerPrice();
BigDecimal constructionValue = constructionPrice.multiply(finishedNumber).setScale(4, RoundingMode.HALF_UP);
BigDecimal ownerValue = ownerPrice.multiply(finishedNumber).setScale(4, RoundingMode.HALF_UP);
value.setOutValue(constructionValue);
value.setOwnerValue(ownerValue);
// 统计总产值
allConstructionValue = allConstructionValue.add(constructionValue);
allOwnerValue = allOwnerValue.add(ownerValue);
// 添加需要修改状态的计划详情
PgsProgressPlanDetail update = new PgsProgressPlanDetail();
update.setId(planDetail.getId());
update.setStatus("2");
updateList.add(update);
saveList.add(value);
}
range.setOutValue(allConstructionValue.setScale(4, RoundingMode.HALF_UP));
range.setOwnerValue(allOwnerValue.setScale(4, RoundingMode.HALF_UP));
// 如果产值都为0则不保存
if (allConstructionValue.compareTo(BigDecimal.ZERO) == 0 && allOwnerValue.compareTo(BigDecimal.ZERO) == 0) {
return null;
}
allUpdateList.addAll(updateList);
return range;
}).filter(Objects::nonNull).toList();
// 保存数据
if (CollUtil.isNotEmpty(ranges)) {
boolean saveBatch = constructionValueRangeService.saveBatch(ranges);
if (!saveBatch) {
throw new ServiceException("同步计划详情到施工产值失败,数据库异常", HttpStatus.ERROR);
}
}
if (CollUtil.isNotEmpty(saveList)) {
boolean saved = constructionValueService.saveBatch(saveList);
if (!saved) {
throw new ServiceException("同步计划详情到施工产值失败,数据库异常", HttpStatus.ERROR);
}
}
if (CollUtil.isNotEmpty(allUpdateList)) {
boolean updateBatch = progressPlanDetailService.updateBatchById(allUpdateList);
if (!updateBatch) {
throw new ServiceException("同步计划详情到施工产值失败,数据库异常", HttpStatus.ERROR);
}
}
// 下一周
start = start.plusWeeks(1);
}
/* LocalDate today = LocalDate.of(2025, 9, 16);
LocalDate localDate = today.minusDays(1);*/
/* // 找到本周一
LocalDate thisMonday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
// 上周一 = 本周一 - 1 周
LocalDate lastMonday = thisMonday.minusWeeks(1);
// 上周日 = 上周一 + 6 天
LocalDate lastSunday = lastMonday.plusDays(6);*/
}
@Test
void setIdCardEncryptorUtil() {
List<SubConstructionUser> list = constructionUserService.list();
List<SubConstructionUser> update = list.stream().filter(user -> StringUtils.isNotBlank(user.getSfzNumber()))
.filter(user -> IdcardUtil.isValidCard18(user.getSfzNumber()))
.toList().stream()
.map(user -> {
SubConstructionUser updateUser = new SubConstructionUser();
updateUser.setId(user.getId());
updateUser.setSfzNumber(idCardEncryptorUtil.encrypt(user.getSfzNumber()));
return updateUser;
}).toList();
constructionUserService.updateBatchById(update);
}
@Test @Test
void test() { void test() {
@ -99,4 +363,188 @@ public class DemoTest {
deptService.selectProjectIdById(100L); deptService.selectProjectIdById(100L);
deptService.selectProjectIdById(1937478258803171329L); deptService.selectProjectIdById(1937478258803171329L);
}*/ }*/
@Test
void tenderExport() {
// 同步修改用户表的team_id字段并添加入场时间
LambdaUpdateWrapper<SubConstructionUser> constructionUserLuw = Wrappers.lambdaUpdate(SubConstructionUser.class)
.in(SubConstructionUser::getId, 1961446214960435201L, 1963077776210710529L, 1963080543771832321L, 1963151975159324673L)
.set(SubConstructionUser::getEntryDate, new Date());
constructionUserService.update(constructionUserLuw);
}
@Test
void testSalary() {
List<SubConstructionUser> list = constructionUserService.lambdaQuery()
.eq(SubConstructionUser::getProjectId, 1897160897167638529L)
.list();
if (CollUtil.isNotEmpty(list)) {
for (SubConstructionUser user : list) {
for (int i = 1; i < 7; i++) {
userSalaryDetailService.insertByAttendance(user.getSysUserId(), LocalDate.now().minusDays(i));
}
}
}
}
@Test
void testImport() {
photovoltaicPanelService.updateFinishNumberByCoordinate(List.of(1968510961294921730L),
List.of(new RecognizeConvertCoordinateResult("107.124334530", "23.830557974")));
}
@Test
void testRemove() {
List<Long> projectIds = List.of(
1968510961294921730L,
1968511074637598722L,
1968511192354934785L,
1968514103508094977L,
1968514270462365697L,
1968515178185248770L,
1968515232044306434L,
1968515275153362945L,
1968515323392053250L,
1968515384058466306L,
1968515428077686785L,
1968515467575447554L,
1968515518674653186L
);
for (Long projectId : projectIds) {
PgsProgressCategory p = progressCategoryService.lambdaQuery()
.eq(PgsProgressCategory::getProjectId, projectId)
.eq(PgsProgressCategory::getMatrixId, "0")
.eq(PgsProgressCategory::getName, "地埋电缆")
.one();
progressCategoryService.remove(new LambdaQueryWrapper<>(PgsProgressCategory.class)
.eq(PgsProgressCategory::getParentId, p.getId()));
progressCategoryService.removeById(p);
}
}
@Test
void testProject1() {
List<BusProject> projects = projectService.lambdaQuery()
.eq(BusProject::getPId, 1897160897167638529L)
.list();
List<Long> projectIds = projects.stream().map(BusProject::getId).toList();
List<PgsProgressCategory> t10101 = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getProjectId, projectIds)
.ne(PgsProgressCategory::getMatrixId, "0")
.eq(PgsProgressCategory::getMatrixName, "T10101")
.list();
log.info("t10101: {}", t10101);
Map<String, PgsProgressCategory> name = t10101.stream()
.collect(Collectors.toMap(PgsProgressCategory::getName, Function.identity()));
List<PgsProgressCategory> other = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getProjectId, projectIds)
.ne(PgsProgressCategory::getMatrixId, "0")
.ne(PgsProgressCategory::getMatrixName, "T10101")
.ne(PgsProgressCategory::getParentId, 0)
.list();
log.info("other: {}", other);
other.forEach(o -> {
o.setId(o.getId());
PgsProgressCategory category = name.get(o.getName());
if (StringUtils.isBlank(o.getWorkType())) {
o.setTotal(category.getTotal());
}
o.setUnit(category.getUnit());
o.setUnitType(category.getUnitType());
BigDecimal ownerPrice = category.getOwnerPrice();
o.setOwnerPrice(ownerPrice);
BigDecimal constructionPrice = category.getConstructionPrice();
o.setConstructionPrice(constructionPrice);
// 计算产值
try {
BigDecimal multiply = o.getOwnerPrice().multiply(o.getTotal());
o.setOwnerOutputValue(multiply.setScale(4, RoundingMode.HALF_UP));
BigDecimal multiply1 = o.getConstructionPrice().multiply(o.getTotal());
o.setConstructionOutputValue(multiply1.setScale(4, RoundingMode.HALF_UP));
} catch (Exception e) {
}
});
progressCategoryService.updateBatchById(other);
}
@Test
void testProject2() {
PgsProgressCategory p1 = progressCategoryService.lambdaQuery()
.eq(PgsProgressCategory::getProjectId, 1968510858786131970L)
.eq(PgsProgressCategory::getMatrixId, "0")
.eq(PgsProgressCategory::getName, "其他工程")
.one();
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.eq(PgsProgressCategory::getProjectId, 1968510858786131970L)
.eq(PgsProgressCategory::getMatrixId, "0")
.eq(PgsProgressCategory::getParentId, p1.getId())
.list();
List<Long> projectIds = List.of(
1968510961294921730L,
1968511074637598722L,
1968511192354934785L,
1968514103508094977L,
1968514270462365697L,
1968515178185248770L,
1968515232044306434L,
1968515275153362945L,
1968515323392053250L,
1968515384058466306L,
1968515428077686785L,
1968515467575447554L,
1968515518674653186L
);
for (Long projectId : projectIds) {
PgsProgressCategory p = progressCategoryService.lambdaQuery()
.eq(PgsProgressCategory::getProjectId, projectId)
.eq(PgsProgressCategory::getMatrixId, "0")
.eq(PgsProgressCategory::getName, "其他工程")
.one();
progressCategoryService.remove(new LambdaQueryWrapper<>(PgsProgressCategory.class)
.eq(PgsProgressCategory::getParentId, p.getId()));
for (PgsProgressCategory category : progressCategoryList) {
PgsProgressCategoryCreateReq req = new PgsProgressCategoryCreateReq();
req.setParentId(p.getId());
req.setProjectId(p.getProjectId());
req.setMatrixId(p.getMatrixId());
req.setName(category.getName());
req.setUnitType(category.getUnitType());
req.setUnit(category.getUnit());
req.setOwnerPrice(category.getOwnerPrice());
req.setConstructionPrice(category.getConstructionPrice());
req.setTotal(category.getTotal());
progressCategoryService.insertByReq(req);
}
}
}
@Test
void openSxtLx() {
String token = ys7Manager.getToken();
List<OthYs7Device> list = ys7DeviceService.list();
for (OthYs7Device othYs7Device : list) {
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("accessToken", token);
paramMap.put("deviceSerial", othYs7Device.getDeviceSerial());
paramMap.put("enable", 1);
String errorMsg = "Ys7 Token 请求失败";
try (HttpResponse response = HttpRequest.post(Ys7Constant.setDeviceVideoUrlByPost)
.form(paramMap)
.execute()) {
if (!response.isOk()) {
log.error("{}{}", errorMsg, response.getStatus());
// throw new ServiceException(errorMsg + response.getStatus());
}
String body = response.body();
Ys7ResponseVo responseVo = JSONUtil.toBean(body, Ys7ResponseVo.class);
if (!responseVo.getCode().equals("200")) {
log.error("{},状态码:{}{}", errorMsg, responseVo.getCode(), responseVo.getMsg());
// throw new ServiceException(errorMsg + responseVo.getMsg());
}
log.info("Ys7 Token 请求成功:{}", body);
}
}
}
} }

View File

@ -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.PHO)); RecognizeVo recognize = recognizerManager.recognize("http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png", List.of(RecognizerTypeEnum.SOLAR));
log.info("recognize: {}", recognize); log.info("recognize: {}", recognize);
} }
} }

View File

@ -80,4 +80,9 @@ public interface CacheNames {
*/ */
String ONLINE_TOKEN = "online_tokens"; String ONLINE_TOKEN = "online_tokens";
/**
* 项目名称
*/
String PROJECT_NAME = "project_name#30d";
} }

View File

@ -65,7 +65,7 @@ public interface Constants {
/** /**
* 验证码有效期(分钟) * 验证码有效期(分钟)
*/ */
Integer CAPTCHA_EXPIRATION = 2; Integer CAPTCHA_EXPIRATION = 5;
/** /**
* 顶级父级id * 顶级父级id

View File

@ -70,4 +70,9 @@ public class UserDTO implements Serializable {
*/ */
private Date createTime; private Date createTime;
/**
* 头像
*/
private String avatarUrl;
} }

View File

@ -30,4 +30,13 @@ public class RegisterBody extends LoginBody {
private String userType; private String userType;
private Long projectId;
private String email;
private String phonenumber;
private Long deptId;
private String smsCode;
} }

View File

@ -0,0 +1,17 @@
package org.dromara.common.core.service;
/**
* @author lilemy
* @date 2025-09-10 16:15
*/
public interface ProjectService {
/**
* 通过项目ID查询项目名称
*
* @param projectId 项目ID
* @return 项目名称
*/
String selectProjectNameById(Long projectId);
}

View File

@ -124,4 +124,20 @@ public interface UserService {
*/ */
Map<Long, String> selectPostNamesByIds(List<Long> postIds); Map<Long, String> selectPostNamesByIds(List<Long> postIds);
/**
* 通过用户id查询头像
*/
String selectAvatarById(Long userId);
/**
* 通过用户id查询用户信息
*/
UserDTO selectUser(Long userId);
/**
* 查询对应专业的用户Id
*/
List<String> selectUserByProfession(String code,String businessId,String type,Long projectId);
} }

View File

@ -376,4 +376,19 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
} }
} }
/**
* 校验日期范围
*
* @param startDate 开始日期
* @param endDate 结束日期
* @return true 表示日期范围有效false 表示日期范围无效
*/
public static boolean isValidDateRange(LocalDate startDate, LocalDate endDate) {
try {
return !startDate.isAfter(endDate); // start <= end
} catch (DateTimeParseException e) {
return false; // 格式非法
}
}
} }

View File

@ -1,10 +1,7 @@
package org.dromara.common.excel.coryUtils; package org.dromara.common.excel.coryUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@ -84,7 +81,7 @@ public class ExcelReader {
SheetData sheetData = new SheetData(); SheetData sheetData = new SheetData();
sheetData.setSheetName(sheet.getSheetName()); sheetData.setSheetName(sheet.getSheetName());
processSheetData(sheet, sheetData); processSheetData(workbook,sheet, sheetData);
sheetDataList.add(sheetData); sheetDataList.add(sheetData);
} }
} }
@ -114,7 +111,7 @@ public class ExcelReader {
sheetData.setSheetName(sheet.getSheetName()); sheetData.setSheetName(sheet.getSheetName());
// 处理单个sheet的数据 // 处理单个sheet的数据
processSheetData(sheet, sheetData); processSheetData(workbook, sheet, sheetData);
sheetDataList.add(sheetData); sheetDataList.add(sheetData);
} }
@ -129,7 +126,7 @@ public class ExcelReader {
/** /**
* 处理单个工作表的数据 * 处理单个工作表的数据
*/ */
private static void processSheetData(org.apache.poi.ss.usermodel.Sheet sheet, SheetData sheetData) { private static void processSheetData(Workbook workbook, Sheet sheet, SheetData sheetData) {
boolean foundChineseStart = false; boolean foundChineseStart = false;
List<List<String>> data = new ArrayList<>(); List<List<String>> data = new ArrayList<>();
boolean isFirstRow = true; boolean isFirstRow = true;
@ -140,29 +137,44 @@ public class ExcelReader {
isFirstRow = false; isFirstRow = false;
continue; continue;
} }
if(hasValidData(workbook,row)){
List<String> rowData = new ArrayList<>();
// 读取A到E列索引0到4
for (int cellIndex = 0; cellIndex < 6; cellIndex++) {
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
rowData.add(getCellValue(workbook,cell));
}
List<String> rowData = new ArrayList<>(); // 检查是否找到中文数字开头的行
// 读取A到E列索引0到4 String aColumnValue = rowData.get(0).trim();
for (int cellIndex = 0; cellIndex < 6; cellIndex++) { if (aColumnValue.matches(CHINESE_NUMBERS_REGEX)) {
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); foundChineseStart = true;
rowData.add(getCellValue(cell)); }
// 只有找到中文数字开头的行之后,才开始收集数据
if (foundChineseStart) {
data.add(rowData);
}
} }
// 检查是否找到中文数字开头的行
String aColumnValue = rowData.get(0).trim();
if (aColumnValue.matches(CHINESE_NUMBERS_REGEX)) {
foundChineseStart = true;
}
// 只有找到中文数字开头的行之后,才开始收集数据
if (foundChineseStart) {
data.add(rowData);
}
} }
sheetData.setData(data); sheetData.setData(data);
} }
private static boolean hasValidData(Workbook workbook,Row row) {
// 遍历行中的所有单元格
for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
String cellValue = getCellValue(workbook, cell).trim();
// 只要有一个单元格有非空值,就认为是有效行
if (!cellValue.isEmpty()) {
return true;
}
}
return false;
}
/** /**
* 根据数据构建树形结构 * 根据数据构建树形结构
*/ */
@ -263,7 +275,7 @@ public class ExcelReader {
/** /**
* 获取单元格的值,处理不同数据类型 * 获取单元格的值,处理不同数据类型
*/ */
private static String getCellValue(Cell cell) { private static String getCellValue(Workbook workbook, Cell cell) {
if (cell == null) { if (cell == null) {
return ""; return "";
} }
@ -278,6 +290,21 @@ public class ExcelReader {
return numericValue.substring(0, numericValue.length() - 2); return numericValue.substring(0, numericValue.length() - 2);
} }
return numericValue; return numericValue;
case FORMULA:
//这样对于字符串cell.getStringCellValue()方法即可取得其值如果公式生成的是数值使用cell.getStringCellValue()方法会抛出IllegalStateException异常在异常处理中使用cell.getNumericCellValue();
// 1. 获取公式文本(如 "A1+B1"
String formula = cell.getCellFormula();
System.out.println("公式文本:" + formula);
// 2. 创建公式计算器(关键步骤:用于计算公式结果)
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
// 3. 计算公式返回包含结果类型和值的CellValue对象
CellValue cellValue = evaluator.evaluate(cell);
// 4. 根据结果类型提取值
return getValue( cellValue.getCellType(), cellValue);
case BOOLEAN: case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue()); return String.valueOf(cell.getBooleanCellValue());
default: default:
@ -285,6 +312,19 @@ public class ExcelReader {
} }
} }
private static String getValue( CellType resultType, CellValue cellValue) {
return switch (resultType) {
case NUMERIC -> String.valueOf(cellValue.getNumberValue());
case STRING -> String.valueOf(cellValue.getStringValue());
case BOOLEAN -> String.valueOf(cellValue.getBooleanValue());
case ERROR -> String.valueOf(cellValue.getErrorValue());
case BLANK -> String.valueOf(CellType.BLANK);
default ->
// 保留原公式(不处理的类型)
cellValue.getStringValue();
};
}
/** /**
* 根据A列的值确定父节点的键 * 根据A列的值确定父节点的键
*/ */

View File

@ -71,7 +71,7 @@ public class MybatisPlusConfig {
public PaginationInnerInterceptor paginationInnerInterceptor() { public PaginationInnerInterceptor paginationInnerInterceptor() {
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
// 分页合理化 // 分页合理化
paginationInnerInterceptor.setOverflow(true); paginationInnerInterceptor.setOverflow(false);
return paginationInnerInterceptor; return paginationInnerInterceptor;
} }

View File

@ -8,6 +8,7 @@ import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -183,7 +183,7 @@ public class OssClient {
// 创建异步请求体length如果为空会报错 // 创建异步请求体length如果为空会报错
BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder() BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder()
.contentLength(length) .contentLength(length)
.subscribeTimeout(Duration.ofSeconds(30)) .subscribeTimeout(Duration.ofSeconds(120)) // 增加超时时间到120秒
.build(); .build();
// 使用 transferManager 进行上传 // 使用 transferManager 进行上传

View File

@ -77,7 +77,7 @@ public class RedisUtils {
public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) { public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
RTopic topic = CLIENT.getTopic(channelKey); RTopic topic = CLIENT.getTopic(channelKey);
topic.publish(msg); topic.publish(msg);
System.out.println("发布通道消息---------"+msg.toString()); // System.out.println("发布通道消息---------"+msg.toString());
consumer.accept(msg); consumer.accept(msg);
} }

View File

@ -28,7 +28,7 @@ public class SaPermissionImpl implements StpInterface {
public List<String> getPermissionList(Object loginId, String loginType) { public List<String> getPermissionList(Object loginId, String loginType) {
LoginUser loginUser = LoginHelper.getLoginUser(); LoginUser loginUser = LoginHelper.getLoginUser();
UserType userType = UserType.getUserType(loginUser.getUserType()); UserType userType = UserType.getUserType(loginUser.getUserType());
if (userType == UserType.SYS_USER) { if (userType == UserType.SYS_USER || userType == UserType.APP_USER) {
Long projectId = loginUser.getProjectId(); Long projectId = loginUser.getProjectId();
List<SysProjectRoleMenuVo> menuPermission = loginUser.getMenuPermission(); List<SysProjectRoleMenuVo> menuPermission = loginUser.getMenuPermission();
if (CollUtil.isNotEmpty(menuPermission)) { if (CollUtil.isNotEmpty(menuPermission)) {
@ -51,9 +51,10 @@ public class SaPermissionImpl implements StpInterface {
return new ArrayList<>(); return new ArrayList<>();
} }
} else if (userType == UserType.APP_USER) {
// 其他端 自行根据业务编写
} }
/* else if (userType == UserType.APP_USER) {
// 其他端 自行根据业务编写
}*/
return new ArrayList<>(); return new ArrayList<>();
// return Collections.singletonList("*"); // return Collections.singletonList("*");
} }
@ -65,7 +66,7 @@ public class SaPermissionImpl implements StpInterface {
public List<String> getRoleList(Object loginId, String loginType) { public List<String> getRoleList(Object loginId, String loginType) {
LoginUser loginUser = LoginHelper.getLoginUser(); LoginUser loginUser = LoginHelper.getLoginUser();
UserType userType = UserType.getUserType(loginUser.getUserType()); UserType userType = UserType.getUserType(loginUser.getUserType());
if (userType == UserType.SYS_USER) { if (userType == UserType.SYS_USER || userType == UserType.APP_USER) {
Long projectId = loginUser.getProjectId(); Long projectId = loginUser.getProjectId();
List<SysProjectRolePermissionVo> rolePermission = loginUser.getRolePermission(); List<SysProjectRolePermissionVo> rolePermission = loginUser.getRolePermission();
if (CollUtil.isNotEmpty(rolePermission)) { if (CollUtil.isNotEmpty(rolePermission)) {
@ -87,9 +88,10 @@ public class SaPermissionImpl implements StpInterface {
} else { } else {
return new ArrayList<>(); return new ArrayList<>();
} }
} else if (userType == UserType.APP_USER) {
// 其他端 自行根据业务编写
} }
/* else if (userType == UserType.APP_USER) {
// 其他端 自行根据业务编写
}*/
return new ArrayList<>(); return new ArrayList<>();
} }
} }

View File

@ -27,6 +27,8 @@ public class SseProperties {
private String violationRecord; private String violationRecord;
private String drawing;
} }

View File

@ -32,4 +32,9 @@ public interface TransConstant {
*/ */
String OSS_ID_TO_URL = "oss_id_to_url"; String OSS_ID_TO_URL = "oss_id_to_url";
/**
* 项目id转名称
*/
String PROJECT_ID_TO_NAME = "project_id_to_name";
} }

View File

@ -0,0 +1,35 @@
package org.dromara.common.translation.core.impl;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import org.dromara.common.core.service.ProjectService;
import org.dromara.common.translation.annotation.TranslationType;
import org.dromara.common.translation.constant.TransConstant;
import org.dromara.common.translation.core.TranslationInterface;
/**
* @author lilemy
* @date 2025-09-10 16:13
*/
@AllArgsConstructor
@TranslationType(type = TransConstant.PROJECT_ID_TO_NAME)
public class ProjectNameTranslationImpl implements TranslationInterface<String> {
@Resource
private ProjectService projectService;
/**
* 翻译
*
* @param key 需要被翻译的键(不为空)
* @param other 其他参数
* @return 返回键对应的值
*/
@Override
public String translation(Object key, String other) {
if (key instanceof Long id) {
return projectService.selectProjectNameById(id);
}
return null;
}
}

View File

@ -4,3 +4,4 @@ org.dromara.common.translation.core.impl.DictTypeTranslationImpl
org.dromara.common.translation.core.impl.OssUrlTranslationImpl 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

View File

@ -13,6 +13,7 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.server.HandshakeInterceptor; import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/** /**
* WebSocket 配置 * WebSocket 配置

View File

@ -12,6 +12,8 @@ public interface WebSocketConstants {
*/ */
String LOGIN_USER_KEY = "loginUser"; String LOGIN_USER_KEY = "loginUser";
String PROJECT_ID = "projectId";
/** /**
* 订阅的频道 * 订阅的频道
*/ */

View File

@ -13,6 +13,7 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY;
import static org.dromara.common.websocket.constant.WebSocketConstants.PROJECT_ID;
/** /**
* WebSocketHandler 实现类 * WebSocketHandler 实现类
@ -27,14 +28,17 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
*/ */
@Override @Override
public void afterConnectionEstablished(WebSocketSession session) throws IOException { public void afterConnectionEstablished(WebSocketSession session) throws IOException {
LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); // LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
if (ObjectUtil.isNull(loginUser)) { Long loginUser = (Long) session.getAttributes().get(PROJECT_ID);
// if (ObjectUtil.isNull(loginUser) ) {
if (loginUser == null ) {
session.close(CloseStatus.BAD_DATA); session.close(CloseStatus.BAD_DATA);
log.info("[connect] invalid token received. sessionId: {}", session.getId()); log.info("[connect] invalid token received. sessionId: {}", session.getId());
return; return;
} }
WebSocketSessionHolder.addSession(loginUser.getUserId(), session); WebSocketSessionHolder.addSession(loginUser, session);
log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); // WebSocketSessionHolder.addSession(loginUser.getUserId(), session);
// log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
} }
/** /**
@ -47,11 +51,13 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
@Override @Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 从WebSocket会话中获取登录用户信息 // 从WebSocket会话中获取登录用户信息
LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); // LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
Long loginUser = (Long) session.getAttributes().get(PROJECT_ID);
// 创建WebSocket消息DTO对象 // 创建WebSocket消息DTO对象
WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto(); WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto();
webSocketMessageDto.setSessionKeys(List.of(loginUser.getUserId())); // webSocketMessageDto.setSessionKeys(List.of(loginUser.getUserId()));
webSocketMessageDto.setSessionKeys(List.of(loginUser));
webSocketMessageDto.setMessage(message.getPayload()); webSocketMessageDto.setMessage(message.getPayload());
WebSocketUtils.publishMessage(webSocketMessageDto); WebSocketUtils.publishMessage(webSocketMessageDto);
} }
@ -100,13 +106,16 @@ public class PlusWebSocketHandler extends AbstractWebSocketHandler {
*/ */
@Override @Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY); // LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
if (ObjectUtil.isNull(loginUser)) { Long loginUser = (Long) session.getAttributes().get(PROJECT_ID);
// if (ObjectUtil.isNull(loginUser)) {
if (loginUser != null ) {
log.info("[disconnect] invalid token received. sessionId: {}", session.getId()); log.info("[disconnect] invalid token received. sessionId: {}", session.getId());
return; return;
} }
WebSocketSessionHolder.removeSession(loginUser.getUserId()); // WebSocketSessionHolder.removeSession(loginUser.getUserId());
log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); WebSocketSessionHolder.removeSession(loginUser);
// log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
} }
/** /**

View File

@ -15,6 +15,7 @@ import org.springframework.web.socket.server.HandshakeInterceptor;
import java.util.Map; import java.util.Map;
import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY;
import static org.dromara.common.websocket.constant.WebSocketConstants.PROJECT_ID;
/** /**
* WebSocket握手请求的拦截器 * WebSocket握手请求的拦截器
@ -44,6 +45,8 @@ public class PlusWebSocketInterceptor implements HandshakeInterceptor {
String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY); String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY); String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY);
String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString(); String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString();
String projectIdStr = ServletUtils.getRequest().getParameter("projectId");
Long projectId = Long.parseLong(projectIdStr);
if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) { if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) {
// token 无效 // token 无效
throw NotLoginException.newInstance(StpUtil.getLoginType(), throw NotLoginException.newInstance(StpUtil.getLoginType(),
@ -52,6 +55,7 @@ public class PlusWebSocketInterceptor implements HandshakeInterceptor {
} }
attributes.put(LOGIN_USER_KEY, loginUser); attributes.put(LOGIN_USER_KEY, loginUser);
attributes.put(PROJECT_ID,projectId);
return true; return true;
} catch (NotLoginException e) { } catch (NotLoginException e) {
log.error("WebSocket 认证失败'{}',无法访问系统资源", e.getMessage()); log.error("WebSocket 认证失败'{}',无法访问系统资源", e.getMessage());

View File

@ -26,7 +26,7 @@ public class WebSocketTopicListener implements ApplicationRunner, Ordered {
public void run(ApplicationArguments args) throws Exception { public void run(ApplicationArguments args) throws Exception {
// 订阅WebSocket消息 // 订阅WebSocket消息
WebSocketUtils.subscribeMessage((message) -> { WebSocketUtils.subscribeMessage((message) -> {
log.info("WebSocket主题订阅收到消息session keys={} message={}", message.getSessionKeys(), message.getMessage()); // log.info("WebSocket主题订阅收到消息session keys={} message={}", message.getSessionKeys(), message.getMessage());
// 如果key不为空就按照key发消息 如果为空就群发 // 如果key不为空就按照key发消息 如果为空就群发
if (CollUtil.isNotEmpty(message.getSessionKeys())) { if (CollUtil.isNotEmpty(message.getSessionKeys())) {
message.getSessionKeys().forEach(key -> { message.getSessionKeys().forEach(key -> {

View File

@ -69,8 +69,8 @@ public class WebSocketUtils {
broadcastMessage.setMessage(webSocketMessage.getMessage()); broadcastMessage.setMessage(webSocketMessage.getMessage());
broadcastMessage.setSessionKeys(unsentSessionKeys); broadcastMessage.setSessionKeys(unsentSessionKeys);
RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> { RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> {
log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}", // log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}",
WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage()); // WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage());
}); });
} }
} }
@ -84,7 +84,7 @@ public class WebSocketUtils {
WebSocketMessageDto broadcastMessage = new WebSocketMessageDto(); WebSocketMessageDto broadcastMessage = new WebSocketMessageDto();
broadcastMessage.setMessage(message); broadcastMessage.setMessage(message);
RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> { RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> {
log.info("WebSocket发送主题订阅消息topic:{} message:{}", WEB_SOCKET_TOPIC, message); // log.info("WebSocket发送主题订阅消息topic:{} message:{}", WEB_SOCKET_TOPIC, message);
}); });
} }

View File

@ -42,7 +42,7 @@ snail-job:
--- # 监控中心配置 --- # 监控中心配置
spring.boot.admin.client: spring.boot.admin.client:
# 增加客户端开关 # 增加客户端开关
enabled: true enabled: false
url: http://192.168.110.119:9090/admin url: http://192.168.110.119:9090/admin
instance: instance:
service-host-type: IP service-host-type: IP

View File

@ -2,9 +2,9 @@ spring:
datasource: datasource:
type: com.zaxxer.hikari.HikariDataSource type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true url: jdbc:mysql://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root username: xinnengyuan
password: root password: mEZPC5Sdf3r2HENi
hikari: hikari:
connection-timeout: 30000 connection-timeout: 30000
validation-timeout: 5000 validation-timeout: 5000
@ -42,8 +42,8 @@ snail-job:
--- # 监控中心配置 --- # 监控中心配置
spring.boot.admin.client: spring.boot.admin.client:
# 增加客户端开关 # 增加客户端开关
enabled: true enabled: false
url: http://localhost:9090/admin url: http://192.168.110.2:19191/admin
instance: instance:
service-host-type: IP service-host-type: IP
metadata: metadata:

View File

@ -17,6 +17,39 @@
<dependencies> <dependencies>
<!-- Java WebSocket 标准API -->
<!-- <dependency>-->
<!-- <groupId>javax.websocket</groupId>-->
<!-- <artifactId>javax.websocket-api</artifactId>-->
<!-- <version>1.1</version>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.drewnoakes</groupId>-->
<!-- <artifactId>metadata-extractor</artifactId>-->
<!-- <version>2.18.0</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>technology.tabula</groupId>-->
<!-- <artifactId>tabula</artifactId>-->
<!-- <version>1.0.4</version>-->
<!-- </dependency>-->
<!-- JSON解析FastJSON --> <!-- JSON解析FastJSON -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
@ -73,18 +106,32 @@
</dependency> </dependency>
<!-- 在pdf上生成二维码 --> <!-- 在pdf上生成二维码 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.2.5</version>
</dependency>
<!-- iText 7 核心模块必须layout依赖此模块 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>kernel</artifactId>
<version>7.2.5</version> <!-- 与layout版本严格一致 -->
</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 --> <!-- &lt;!&ndash; iText &ndash;&gt;-->
<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>
@ -108,6 +155,11 @@
<artifactId>ruoyi-common-doc</artifactId> <artifactId>ruoyi-common-doc</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-job</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.dromara</groupId> <groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId> <artifactId>ruoyi-common-mybatis</artifactId>
@ -216,6 +268,24 @@
<version>5.3.0</version> <version>5.3.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.25.0-GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version> <!-- 最新版本可自行调整 -->
</dependency>
</dependencies> </dependencies>

View File

@ -0,0 +1,144 @@
package org.dromara.app.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.dromara.app.domain.SysPackage;
import org.dromara.app.service.SysPackageServiceImpl;
import org.dromara.common.core.domain.R;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.impl.SysOssServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/app/sysPackage")
public class SysPackageController {
@Autowired
private SysOssServiceImpl sysOssService;
@Autowired
private SysPackageServiceImpl sysPackageService;
/**
* 获取最新版本
*/
@GetMapping("/getNewVersion")
public R<SysPackage> getNewVersion() {
LambdaQueryWrapper<SysPackage> lambdaQueryWrapper =new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByDesc(SysPackage::getCreateTime);
lambdaQueryWrapper.last("LIMIT 1");
SysPackage one = sysPackageService.getOne(lambdaQueryWrapper);
return R.ok(one);
}
/**
* 上传最新安装包及版本
*/
@GetMapping("/uploadNewVersion")
public R<SysPackage> uploadNewVersion(String version, String type, MultipartFile file) {
String originalFileName = "apk/package/app-release.apk";
// 先查询最新记录
LambdaQueryWrapper<SysPackage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByDesc(SysPackage::getCreateTime);
List<SysPackage> list = sysPackageService.list(lambdaQueryWrapper);
// 分离事务:先处理文件上传
SysOssVo upload = sysOssService.upload(file, originalFileName);
if (upload == null) {
return R.fail("上传失败");
}
// 分离事务:再处理数据库操作
return handleDatabaseOperations(version, type, upload, list);
}
@Transactional
public R<SysPackage> handleDatabaseOperations(String version, String type, SysOssVo upload, List<SysPackage> existingPackages) {
try {
// 先删除旧文件记录
if (existingPackages != null && !existingPackages.isEmpty()) {
SysPackage first = existingPackages.getFirst();
Boolean b = sysOssService.deleteWithValidByIds(List.of(first.getFileId()), false);
if (!b) {
log.error("通过IDS删除文件失败");
}
}
// 保存新记录
SysPackage sysPackage = new SysPackage();
sysPackage.setVersion(version);
sysPackage.setFileId(upload.getOssId());
sysPackage.setFileUrl(upload.getUrl());
sysPackage.setType(type);
boolean save = sysPackageService.save(sysPackage);
if (!save) {
return R.fail("保存失败");
}
return R.ok(sysPackage);
} catch (Exception e) {
log.error("数据库操作失败", e);
throw e; // 重新抛出异常触发事务回滚
}
}
// public R<SysPackage> uploadNewVersion(String version, String type, MultipartFile file) {
// String originalFileName = "apk/package/app-release.apk";
//
// //覆盖失败,先删除文件
// LambdaQueryWrapper<SysPackage> lambdaQueryWrapper =new LambdaQueryWrapper<>();
// lambdaQueryWrapper.orderByDesc(SysPackage::getCreateTime);
// List<SysPackage> list = sysPackageService.list(lambdaQueryWrapper);
// if (list != null && !list.isEmpty()){
// SysPackage first = list.getFirst();
// Boolean b = sysOssService.deleteWithValidByIds(List.of(first.getFileId()), false);
// if (!b){
// log.error("通过IDS删除文件失败");
// }
// }
//
// SysOssVo upload = sysOssService.upload(file, originalFileName);
// if (upload == null){
// return R.fail("上传失败");
// }
// SysPackage sysPackage = new SysPackage();
// sysPackage.setVersion( version);
// sysPackage.setFileId(upload.getOssId());
// sysPackage.setFileUrl(upload.getUrl());
// sysPackage.setType(type);
//
// boolean save = sysPackageService.save(sysPackage);
// if (!save){
// return R.fail("保存失败");
// }
//
// return R.ok(sysPackage);
// }
/**
* 删除 现在指向的是同一个文件
*/
@Transactional
@GetMapping("/remove")
public R<Void> remove(Long id){
SysPackage byId = sysPackageService.getById(id);
Boolean b1 = sysOssService.deleteWithValidByIds(List.of(byId.getFileId()), false);
boolean b = sysPackageService.removeById(id);
if (b1 && b){
return R.ok();
}
return R.fail("删除文件或记录失败");
}
}

View File

@ -0,0 +1,33 @@
package org.dromara.app.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
@Data
@TableName("sys_package")
@EqualsAndHashCode(callSuper = true)
public class SysPackage extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
@TableId(value = "id")
private Long id;
/**
* 0安卓1苹果2鸿蒙
*/
private String type;
private String version;
private Long fileId;
private String fileUrl;
}

View File

@ -0,0 +1,30 @@
package org.dromara.app.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.app.domain.SysPackage;
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = SysPackage.class)
public class SysPackageVo {
@ExcelProperty("id")
private Long id;
/**
* 0安卓1苹果2鸿蒙
*/
@ExcelProperty("安装包类型(0安卓1苹果2鸿蒙)")
private String type;
@ExcelProperty("版本")
private String version;
private Long fileId;
@ExcelProperty("安装包地址")
private String fileUrl;
}

View File

@ -0,0 +1,11 @@
package org.dromara.app.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.dromara.app.domain.SysPackage;
import org.dromara.app.domain.vo.SysPackageVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@Mapper
public interface SysPackageMapper extends BaseMapperPlus<SysPackage, SysPackageVo> {
}

View File

@ -0,0 +1,10 @@
package org.dromara.app.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.app.domain.SysPackage;
import org.dromara.app.mapper.SysPackageMapper;
import org.springframework.stereotype.Service;
@Service
public class SysPackageServiceImpl extends ServiceImpl<SysPackageMapper, SysPackage> {
}

View File

@ -3,7 +3,9 @@ package org.dromara.bidding.controller;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import org.apache.pdfbox.pdmodel.PDDocument;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.dromara.bidding.domain.bo.BusBiddingLimitListBo; import org.dromara.bidding.domain.bo.BusBiddingLimitListBo;
import org.dromara.bidding.domain.bo.BiddingAllVersionNumbersReq; import org.dromara.bidding.domain.bo.BiddingAllVersionNumbersReq;
import org.dromara.bidding.domain.vo.BusBiddingLimitListVo; import org.dromara.bidding.domain.vo.BusBiddingLimitListVo;
@ -22,6 +24,8 @@ 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.io.File;
import java.io.IOException;
import java.util.List; import java.util.List;
/** /**
@ -38,6 +42,8 @@ public class BusBiddingLimitListController extends BaseController {
private final IBusBiddingLimitListService busBiddingLimitListService; private final IBusBiddingLimitListService busBiddingLimitListService;
/** /**
* 查询成本-投标列表 * 查询成本-投标列表
*/ */
@ -101,8 +107,8 @@ public class BusBiddingLimitListController extends BaseController {
@Log(title = "成本-投标", businessType = BusinessType.INSERT) @Log(title = "成本-投标", businessType = BusinessType.INSERT)
@RepeatSubmit() @RepeatSubmit()
@PostMapping("/importExcelFile") @PostMapping("/importExcelFile")
public R<Void> importExcelFile(Long projectId, @RequestParam("file") MultipartFile file) { public R<Void> importExcelFile(BusBiddingLimitListBo bo, @RequestParam("file") MultipartFile file) {
return toAjax(busBiddingLimitListService.importExcelFile(projectId, file)); return toAjax(busBiddingLimitListService.importExcelFile(bo, file));
} }
/** /**

View File

@ -42,6 +42,14 @@ public class BusBiddingLimitVersions extends BaseEntity {
*/ */
private String versions; private String versions;
/**
* 版本号名称
*/
private String versionsName;
/** /**
* excel文件 * excel文件
*/ */

View File

@ -1,5 +1,6 @@
package org.dromara.bidding.domain.bo; package org.dromara.bidding.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.bidding.domain.BusBiddingLimitList; import org.dromara.bidding.domain.BusBiddingLimitList;
import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.AddGroup;
@ -91,4 +92,6 @@ public class BusBiddingLimitListBo extends BaseEntity {
private String remark; private String remark;
private Long type;
} }

View File

@ -44,6 +44,14 @@ public class BusBiddingLimitVersionsBo extends BaseEntity {
@NotBlank(message = "版本号不能为空", groups = { AddGroup.class, EditGroup.class }) @NotBlank(message = "版本号不能为空", groups = { AddGroup.class, EditGroup.class })
private String versions; private String versions;
/**
* 版本号名称
*/
private String versionsName;
/** /**
* excel文件 * excel文件
*/ */

View File

@ -1,5 +1,6 @@
package org.dromara.bidding.domain.vo; package org.dromara.bidding.domain.vo;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import org.dromara.bidding.domain.BusBiddingLimitList; import org.dromara.bidding.domain.BusBiddingLimitList;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
@ -77,6 +78,7 @@ public class BusBiddingLimitListVo implements Serializable {
* 名称 * 名称
*/ */
@ExcelProperty(value = "名称") @ExcelProperty(value = "名称")
@ColumnWidth(50)
private String name; private String name;
/** /**

View File

@ -52,6 +52,14 @@ public class BusBiddingLimitVersionsVo implements Serializable {
@ExcelProperty(value = "版本号") @ExcelProperty(value = "版本号")
private String versions; private String versions;
/**
* 版本号名称
*/
private String versionsName;
/** /**
* excel文件 * excel文件
*/ */

View File

@ -79,7 +79,7 @@ public interface IBusBiddingLimitListService extends IService<BusBiddingLimitLis
*/ */
List<BusBiddingLimitListVo> getTree(BusBiddingLimitListBo bo); List<BusBiddingLimitListVo> getTree(BusBiddingLimitListBo bo);
Boolean importExcelFile(Long projectId, MultipartFile file); Boolean importExcelFile(BusBiddingLimitListBo projectId, MultipartFile file);
List<BusBiddingLimitVersionsVo> obtainAllVersionNumbers(BiddingAllVersionNumbersReq bo); List<BusBiddingLimitVersionsVo> obtainAllVersionNumbers(BiddingAllVersionNumbersReq bo);

View File

@ -1,5 +1,7 @@
package org.dromara.bidding.service; package org.dromara.bidding.service;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.dromara.bidding.domain.vo.BusBiddingLimitVersionsVo; import org.dromara.bidding.domain.vo.BusBiddingLimitVersionsVo;
import org.dromara.bidding.domain.bo.BusBiddingLimitVersionsBo; import org.dromara.bidding.domain.bo.BusBiddingLimitVersionsBo;
import org.dromara.bidding.domain.BusBiddingLimitVersions; import org.dromara.bidding.domain.BusBiddingLimitVersions;
@ -67,4 +69,8 @@ public interface IBusBiddingLimitVersionsService extends IService<BusBiddingLimi
* @return 是否删除成功 * @return 是否删除成功
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
BusBiddingLimitVersions queryByProjectId( String versions, Long projectId);
BusBiddingLimitVersions getByProjectIdVersions(Long projectId, String versions);
} }

View File

@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.bidding.domain.BusBiddingLimitList; import org.dromara.bidding.domain.BusBiddingLimitList;
import org.dromara.bidding.domain.BusBiddingLimitVersions;
import org.dromara.bidding.domain.bo.BusBiddingLimitListBo; import org.dromara.bidding.domain.bo.BusBiddingLimitListBo;
import org.dromara.bidding.domain.bo.BusBiddingLimitVersionsBo; import org.dromara.bidding.domain.bo.BusBiddingLimitVersionsBo;
import org.dromara.bidding.domain.bo.BiddingAllVersionNumbersReq; import org.dromara.bidding.domain.bo.BiddingAllVersionNumbersReq;
@ -17,14 +18,13 @@ import org.dromara.bidding.mapper.BusBiddingLimitListMapper;
import org.dromara.bidding.service.IBusBiddingLimitListService; import org.dromara.bidding.service.IBusBiddingLimitListService;
import org.dromara.bidding.service.IBusBiddingLimitVersionsService; import org.dromara.bidding.service.IBusBiddingLimitVersionsService;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException; 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.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.excel.ExcelDynamicReader; import org.dromara.common.utils.excel.ExcelDynamicReader;
import org.dromara.tender.domain.BusBillofquantitiesLimitList;
import org.dromara.tender.domain.bo.BusBillofquantitiesLimitListBo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -179,13 +179,17 @@ public class BusBiddingLimitListServiceImpl extends ServiceImpl<BusBiddingLimitL
@Override @Override
public List<BusBiddingLimitListVo> getTree(BusBiddingLimitListBo bo) { public List<BusBiddingLimitListVo> getTree(BusBiddingLimitListBo bo) {
BusBiddingLimitVersions biddingLimitVersions = busBiddingLimitVersionsService.queryByProjectId(bo.getVersions(),bo.getProjectId());
if (biddingLimitVersions == null || (bo.getType() == 1L && !BusinessStatusEnum.FINISH.getStatus().equals(biddingLimitVersions.getStatus()))) {
return null;
}
//获取所有数据 //获取所有数据
List<BusBiddingLimitListVo> listVoList = queryList(bo); List<BusBiddingLimitListVo> listVoList = queryList(bo);
//过滤数量和单价为空的数据并计算总价 //过滤数量和单价为空的数据并计算总价
listVoList.stream().filter(vo -> vo.getUnitPrice() != null && vo.getUnitPrice().compareTo(BigDecimal.ZERO) != 0) listVoList.stream().filter(vo -> vo.getUnitPrice() != null && vo.getUnitPrice().compareTo(BigDecimal.ZERO) != 0)
.filter(vo -> vo.getQuantity() != null && vo.getQuantity().compareTo(BigDecimal.ZERO) != 0) .filter(vo -> vo.getQuantity() != null && vo.getQuantity().compareTo(BigDecimal.ZERO) != 0)
.forEach(item -> { .forEach(item -> {
item.setPrice(item.getUnitPrice().multiply(item.getQuantity()).setScale(2, RoundingMode.HALF_UP)); item.setPrice(item.getUnitPrice().multiply(item.getQuantity()).setScale(4, RoundingMode.HALF_UP));
}); });
//构建父子映射 //构建父子映射
@ -217,7 +221,7 @@ public class BusBiddingLimitListServiceImpl extends ServiceImpl<BusBiddingLimitL
// 如果是叶子节点,计算 price = quantity * unitPrice // 如果是叶子节点,计算 price = quantity * unitPrice
if (node.getChildren().isEmpty()) { if (node.getChildren().isEmpty()) {
if (node.getQuantity() != null && node.getUnitPrice() != null) { if (node.getQuantity() != null && node.getUnitPrice() != null) {
node.setPrice(node.getQuantity().multiply(node.getUnitPrice())); node.setPrice(node.getQuantity().multiply(node.getUnitPrice()).setScale(4, RoundingMode.HALF_UP));
} else { } else {
node.setPrice(BigDecimal.ZERO); // 默认值 node.setPrice(BigDecimal.ZERO); // 默认值
} }
@ -226,14 +230,22 @@ public class BusBiddingLimitListServiceImpl extends ServiceImpl<BusBiddingLimitL
BigDecimal totalPrice = node.getChildren().stream() BigDecimal totalPrice = node.getChildren().stream()
.map(BusBiddingLimitListVo::getPrice) .map(BusBiddingLimitListVo::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add) .reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.HALF_UP); .setScale(4, RoundingMode.HALF_UP);
node.setPrice(totalPrice); node.setPrice(totalPrice);
} }
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean importExcelFile(Long projectId, MultipartFile file) { public Boolean importExcelFile(BusBiddingLimitListBo bo, MultipartFile file) {
BusBiddingLimitVersions biddingLimitVersions = busBiddingLimitVersionsService.getByProjectIdVersions(bo.getProjectId(),bo.getVersions());
if (biddingLimitVersions == null) {
throw new ServiceException("版本号不存在!!!");
}
if (BusinessStatusEnum.FINISH.getStatus().equals(biddingLimitVersions.getStatus())) {
throw new ServiceException("数据已审核完成,不允许修改!!!");
}
// 跳过1行表头读取0到6列共7列映射到ExcelData实体类 // 跳过1行表头读取0到6列共7列映射到ExcelData实体类
List<BusBiddingLimitListBo> dataList = null; List<BusBiddingLimitListBo> dataList = null;
@ -242,7 +254,7 @@ public class BusBiddingLimitListServiceImpl extends ServiceImpl<BusBiddingLimitL
file, // 上传的文件 file, // 上传的文件
1, // 跳过1行表头 1, // 跳过1行表头
0, // 从第0列开始 0, // 从第0列开始
12, // 到第12列结束 13, // 到第12列结束
BusBiddingLimitListBo.class // 目标实体类 BusBiddingLimitListBo.class // 目标实体类
); );
} catch (Exception e) { } catch (Exception e) {
@ -265,7 +277,6 @@ public class BusBiddingLimitListServiceImpl extends ServiceImpl<BusBiddingLimitL
busBillofquantities.add(limitList); busBillofquantities.add(limitList);
}); });
log.info(busBillofquantities.toString()); log.info(busBillofquantities.toString());
return this.updateBatchById(busBillofquantities); return this.updateBatchById(busBillofquantities);
} }

View File

@ -1,30 +1,29 @@
package org.dromara.bidding.service.impl; package org.dromara.bidding.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.bidding.domain.BusBiddingLimitVersions;
import org.dromara.bidding.domain.bo.BusBiddingLimitVersionsBo;
import org.dromara.bidding.domain.vo.BusBiddingLimitVersionsVo;
import org.dromara.bidding.mapper.BusBiddingLimitVersionsMapper;
import org.dromara.bidding.service.IBusBiddingLimitVersionsService;
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;
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.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.dromara.common.mybatis.core.page.TableDataInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.design.domain.BusBillofquantitiesVersions;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.dromara.bidding.domain.bo.BusBiddingLimitVersionsBo;
import org.dromara.bidding.domain.vo.BusBiddingLimitVersionsVo;
import org.dromara.bidding.domain.BusBiddingLimitVersions;
import org.dromara.bidding.mapper.BusBiddingLimitVersionsMapper;
import org.dromara.bidding.service.IBusBiddingLimitVersionsService;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Collection;
/** /**
* 成本- 投标版本Service业务层处理 * 成本- 投标版本Service业务层处理
@ -46,7 +45,7 @@ public class BusBiddingLimitVersionsServiceImpl extends ServiceImpl<BusBiddingLi
* @return 成本- 投标版本 * @return 成本- 投标版本
*/ */
@Override @Override
public BusBiddingLimitVersionsVo queryById(Long id){ public BusBiddingLimitVersionsVo queryById(Long id) {
return baseMapper.selectVoById(id); return baseMapper.selectVoById(id);
} }
@ -120,7 +119,7 @@ public class BusBiddingLimitVersionsServiceImpl extends ServiceImpl<BusBiddingLi
/** /**
* 保存前的数据校验 * 保存前的数据校验
*/ */
private void validEntityBeforeSave(BusBiddingLimitVersions entity){ private void validEntityBeforeSave(BusBiddingLimitVersions entity) {
//TODO 做一些数据校验,如唯一约束 //TODO 做一些数据校验,如唯一约束
} }
@ -133,12 +132,26 @@ public class BusBiddingLimitVersionsServiceImpl extends ServiceImpl<BusBiddingLi
*/ */
@Override @Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){ if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
} }
return baseMapper.deleteByIds(ids) > 0; return baseMapper.deleteByIds(ids) > 0;
} }
@Override
public BusBiddingLimitVersions queryByProjectId(String versions, Long projectId) {
return baseMapper.selectOne(new LambdaQueryWrapper<BusBiddingLimitVersions>()
.eq(BusBiddingLimitVersions::getProjectId, projectId)
.eq(BusBiddingLimitVersions::getVersions, versions));
}
@Override
public BusBiddingLimitVersions getByProjectIdVersions(Long projectId, String versions) {
return baseMapper.selectOne(new LambdaQueryWrapper<BusBiddingLimitVersions>()
.eq(BusBiddingLimitVersions::getProjectId, projectId)
.eq(BusBiddingLimitVersions::getVersions, versions));
}
/** /**
* 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等)
@ -147,7 +160,7 @@ public class BusBiddingLimitVersionsServiceImpl extends ServiceImpl<BusBiddingLi
* *
* @param processEvent 参数 * @param processEvent 参数
*/ */
@org.springframework.context.event.EventListener(condition = "#processEvent.flowCode.endsWith('biddingLimitList')") @EventListener(condition = "#processEvent.flowCode.endsWith('biddingLimitList')")
public void processPlansHandlErequipmentList(ProcessEvent processEvent) { public void processPlansHandlErequipmentList(ProcessEvent processEvent) {
log.info("物资设备清单审核任务执行了{}", processEvent.toString()); log.info("物资设备清单审核任务执行了{}", processEvent.toString());
String id = processEvent.getBusinessId(); String id = processEvent.getBusinessId();
@ -177,7 +190,7 @@ public class BusBiddingLimitVersionsServiceImpl extends ServiceImpl<BusBiddingLi
* *
* @param processTaskEvent 参数 * @param processTaskEvent 参数
*/ */
@org.springframework.context.event.EventListener(condition = "#processTaskEvent.flowCode.endsWith('biddingLimitList')") @EventListener(condition = "#processTaskEvent.flowCode.endsWith('biddingLimitList')")
public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) { public void processTaskPlansHandlerEquipmentList(ProcessTaskEvent processTaskEvent) {
log.info("物资设备清单审核任务创建了{}", processTaskEvent.toString()); log.info("物资设备清单审核任务创建了{}", processTaskEvent.toString());
} }

View File

@ -0,0 +1,56 @@
package org.dromara.bigscreen.config;
import jakarta.annotation.Resource;
import org.dromara.bigscreen.listener.RedisMessageListener;
import org.dromara.drone.service.IDroProjectDroneService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import java.util.List;
@Configuration
public class RedisConfig {
@Resource
@Lazy
private IDroProjectDroneService droProjectDroneService;
/**
* 配置Redis消息监听容器
*/
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
// List<String> wrjKeys = droProjectDroneService.getTopicsByKeyPrefix();
// for (String key : wrjKeys) {
// // 订阅 wrj:8UUXN4P00A06NK 频道
// container.addMessageListener(listenerAdapter, new PatternTopic("wrj:osd4"+key));
// }
return container;
}
/**
* 配置消息监听适配器,将消息转发给自定义的监听器
*/
@Bean
public MessageListenerAdapter listenerAdapter(RedisMessageListener listener) {
return new MessageListenerAdapter(listener);
}
/**
* 配置StringRedisTemplate
*/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
}

View File

@ -0,0 +1,261 @@
package org.dromara.bigscreen.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.dromara.bigscreen.domain.dto.WeatherQueryReq;
import org.dromara.bigscreen.domain.vo.*;
import org.dromara.bigscreen.mapper.ProjectBigScreenMapper;
import org.dromara.bigscreen.service.EnterpriseBigScreenService;
import org.dromara.common.core.domain.R;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.project.domain.BusAttendance;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusUserProjectRelevancy;
import org.dromara.project.service.IBusAttendanceService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusUserProjectRelevancyService;
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.RestController;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
/**
* 企业级大屏
*
* @author lilemy
* @date 2025-09-09 14:55
*/
@Validated
@RestController
@RequestMapping("/enterprise/big/screen")
public class EnterpriseBigScreenController {
@Resource
private EnterpriseBigScreenService enterpriseBigScreenService;
@Resource
private IBusUserProjectRelevancyService userProjectRelevancyService;
@Resource
private IBusAttendanceService attendanceService;
@Resource
private IBusProjectService projectService;
/**
* 获取关键指标
*/
// @SaCheckPermission("enterprise:bigScreen:keyIndex")
@GetMapping("/keyIndex")
public R<EnterpriseKeyIndexVo> getEnterpriseKeyIndex() {
return R.ok(enterpriseBigScreenService.getEnterpriseKeyIndex());
}
/**
* 项目进度分析
*/
// @SaCheckPermission("enterprise:bigScreen:projectProgress")
@GetMapping("/projectProgress")
public R<ProjectProgressAnalysisVo> getProjectProgress() {
return R.ok(enterpriseBigScreenService.getProjectProgressAnalysis());
}
/**
* 项目产值对比
*/
// @SaCheckPermission("enterprise:bigScreen:projectOutputValueComparison")
@GetMapping("/projectOutputValueComparison")
public R<List<OutputValueComparisonVo>> getProjectOutputValueComparison() {
return R.ok(enterpriseBigScreenService.getProjectOutputValueComparison());
}
/**
* 项目进度完成度和计划容量
*/
// @SaCheckPermission("enterprise:bigScreen:projectProgressCapacity")
@GetMapping("/projectProgressCapacity")
public R<List<ProjectProgressCapacityVo>> getProjectProgressCapacity() {
return R.ok(enterpriseBigScreenService.getProjectProgressCapacity());
}
/**
* 风险预警
*/
// @SaCheckPermission("enterprise:bigScreen:riskEarlyWarning")
@GetMapping("/riskEarlyWarning")
public R<List<RiskEarlyWarningVo>> getRiskEarlyWarning() {
return R.ok(enterpriseBigScreenService.getRiskEarlyWarning());
}
/**
* 查询天气
*/
// @SaCheckPermission("enterprise:bigScreen:weather")
@GetMapping("/weather")
public R<List<WeatherVo>> getProjectWeather(WeatherQueryReq req) {
return R.ok(enterpriseBigScreenService.getWeather3DaysList(req));
}
/**
* 查询安全天数
*/
// @SaCheckPermission("enterprise:bigScreen:safetyDay")
@GetMapping("/safetyDay")
public R<Long> getProjectSafetyDay() {
LocalDate date = LocalDate.of(2023, 1, 1);
LocalDate now = LocalDate.now();
long days = Math.abs(ChronoUnit.DAYS.between(date, now));
return R.ok(days);
}
/**
* 人数统计
*/
// @SaCheckPermission("enterprise:bigScreen:peopleCount")
@GetMapping("/peopleCount")
public R<PeopleCountVo> getProjectPeopleCount() {
PeopleCountVo peopleCountVo = new PeopleCountVo();
List<BusUserProjectRelevancy> list = userProjectRelevancyService.list();
//0系统管理员 1普通人员 2项目管理员 3分包人员
peopleCountVo.setConstructionPersonnelCount(list.stream().filter(item -> "1".equals(item.getUserType()))
.map(BusUserProjectRelevancy::getUserId)
.distinct().count());
peopleCountVo.setManagersCount(list.stream().filter(item -> "2".equals(item.getUserType()))
.map(BusUserProjectRelevancy::getUserId)
.distinct().count());
// peopleCountVo.setManagersCount(69L);
peopleCountVo.setSubcontractorsCount(list.stream().filter(item -> "3".equals(item.getUserType()))
.map(BusUserProjectRelevancy::getUserId)
.distinct().count());
// peopleCountVo.setManagersCount(9L);
// Integer projectUserCount = projectBigScreenMapper.getUserCount();
// peopleCountVo.setConstructionPersonnelCount(Long.valueOf(projectUserCount));
return R.ok(peopleCountVo);
}
/**
* 出勤人数统计
*/
// @SaCheckPermission("enterprise:bigScreen:allAttendanceCount")
@GetMapping("/allAttendanceCount")
public R<TodayAttendanceCountVo> getAllAttendanceCount() {
TodayAttendanceCountVo todayAttendanceCountVo = new TodayAttendanceCountVo();
// List<BusProject> projectList = projectService.listByIds(List.of(1897160897167638529L, 1897161054676336641L));
// Integer countUser = 0;
// Integer countAttendance = 0;
// for (BusProject project : projectList) {
// Long projectId = project.getGoId();
// countUser = countUser + projectBigScreenMapper.getProjectUserCount(projectId);
// countAttendance = countAttendance + projectBigScreenMapper.getAttendanceCount(projectId, DateUtils.getDate());
// }
List<BusAttendance> list = attendanceService.list(Wrappers.<BusAttendance>lambdaQuery()
.eq(BusAttendance::getClockDate, LocalDate.now())
.in(BusAttendance::getClockStatus, Arrays.asList("1", "2", "3"))
);
long attendanceCount = list.stream().map(BusAttendance::getUserId).distinct().count();
todayAttendanceCountVo.setAttendanceCount(attendanceCount);
// 查询总人数
List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list();
long totalUserCount = relevancyList.stream().map(BusUserProjectRelevancy::getUserId).distinct().count();
// 计算考勤率(保留一位小数)
if (totalUserCount > 0) {
BigDecimal rate = new BigDecimal(attendanceCount * 100)
.divide(new BigDecimal(totalUserCount), 1, RoundingMode.HALF_UP);
todayAttendanceCountVo.setAttendanceRate(rate.doubleValue());
} else {
todayAttendanceCountVo.setAttendanceRate(0.0);
}
todayAttendanceCountVo.setAttendanceCount(attendanceCount);
return R.ok(todayAttendanceCountVo);
}
/**
* 每个项目的出勤人数
*/
// @SaCheckPermission("enterprise:bigScreen:projectAttendanceCount")
@GetMapping("/projectAttendanceCount")
public R<List<ProjectAttendanceCountVo>> getProjectAttendanceCount() {
// List<BusProject> projectList = projectService.listByIds(List.of(1897160897167638529L, 1897161054676336641L));
// return R.ok(projectList.stream().map(busProject -> {
// ProjectAttendanceCountVo vo = new ProjectAttendanceCountVo();
// vo.setProjectId(busProject.getId());
// vo.setProjectName(busProject.getProjectName());
// Long projectId = busProject.getGoId();
// Integer projectUserCount = projectBigScreenMapper.getProjectUserCount(projectId);
// Integer attendanceCount = projectBigScreenMapper.getAttendanceCount(projectId, DateUtils.getDate());
// vo.setAttendanceCount(Long.valueOf(attendanceCount));
// vo.setAttendanceRate(BigDecimalUtil.toPercentage(BigDecimal.valueOf(attendanceCount), BigDecimal.valueOf(projectUserCount)).doubleValue());
// return vo;
// }).toList());
ArrayList<ProjectAttendanceCountVo> projectAttendanceCountVos = new ArrayList<>();
List<BusProject> busProjects = projectService.getBaseMapper().selectList(new LambdaQueryWrapper<BusProject>().eq(BusProject::getPId, 0L).eq(BusProject::getIsDelete, 0));
List<Long> projectIds = new ArrayList<>();
for (BusProject busProject : busProjects) {
projectIds.add(busProject.getId());
}
List<BusAttendance> list = attendanceService.list(Wrappers.<BusAttendance>lambdaQuery()
.eq(BusAttendance::getClockDate, LocalDate.now())
.in(BusAttendance::getClockStatus, Arrays.asList("1", "2", "3"))
.in(BusAttendance::getProjectId, projectIds)
);
List<BusUserProjectRelevancy> relevancyList = userProjectRelevancyService.list(new LambdaQueryWrapper<BusUserProjectRelevancy>().in(BusUserProjectRelevancy::getProjectId, projectIds));
// 转换为 Map<projectId, 去重后的 userId 数量>
Map<Long, Integer> projectUserCountMap = relevancyList.stream()
.collect(Collectors.groupingBy(
BusUserProjectRelevancy::getProjectId,
Collectors.mapping(
BusUserProjectRelevancy::getUserId,
Collectors.collectingAndThen(
Collectors.toSet(),
Set::size
)
)
));
for (Long projectId : projectUserCountMap.keySet()) {
ProjectAttendanceCountVo projectAttendanceCountVo = new ProjectAttendanceCountVo();
BusProject byId = projectService.getById(projectId);
if (byId == null) {
continue;
}
projectAttendanceCountVo.setProjectName(byId.getProjectName());
long count = list.stream().filter(item -> item.getProjectId().equals(projectId))
.map(BusAttendance::getUserId)
.distinct()
.count();
Integer i = projectUserCountMap.get(projectId);
BigDecimal rate = new BigDecimal("0.0");
if (i > 0) {
rate = new BigDecimal(count * 100)
.divide(new BigDecimal(projectUserCountMap.get(projectId)), 1, RoundingMode.HALF_UP);
}
projectAttendanceCountVo.setAttendanceRate(rate.doubleValue());
projectAttendanceCountVos.add(projectAttendanceCountVo);
}
return R.ok(projectAttendanceCountVos);
}
}

View File

@ -1,6 +1,5 @@
package org.dromara.bigscreen.controller; package org.dromara.bigscreen.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -11,13 +10,13 @@ import org.dromara.ctr.domain.CtrExpensesContract;
import org.dromara.ctr.domain.CtrIncomeContract; import org.dromara.ctr.domain.CtrIncomeContract;
import org.dromara.ctr.service.ICtrExpensesContractService; import org.dromara.ctr.service.ICtrExpensesContractService;
import org.dromara.ctr.service.ICtrIncomeContractService; import org.dromara.ctr.service.ICtrIncomeContractService;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.out.domain.OutSettlementValueOwner; import org.dromara.out.domain.OutSettlementValueOwner;
import org.dromara.out.domain.OutSettlementValueSubcontract; import org.dromara.out.domain.OutSettlementValueSubcontract;
import org.dromara.out.service.IOutSettlementValueOwnerService; import org.dromara.out.service.IOutSettlementValueOwnerService;
import org.dromara.out.service.IOutSettlementValueSubcontractService; import org.dromara.out.service.IOutSettlementValueSubcontractService;
import org.dromara.project.domain.vo.project.BusProjectGisVo; import org.dromara.project.domain.vo.project.BusProjectGisVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -25,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.YearMonth; import java.time.YearMonth;
import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalAdjusters;
@ -61,7 +61,7 @@ public class MoneyBigScreenController {
/** /**
* 查询项目位置列表 * 查询项目位置列表
*/ */
@SaCheckPermission("money:bigScreen:projectGis") // @SaCheckPermission("money:bigScreen:projectGis")
@GetMapping("/project/gis") @GetMapping("/project/gis")
public R<List<BusProjectGisVo>> getProjectGis() { public R<List<BusProjectGisVo>> getProjectGis() {
return R.ok(moneyBigScreenService.getProjectGis()); return R.ok(moneyBigScreenService.getProjectGis());
@ -114,8 +114,8 @@ public class MoneyBigScreenController {
.eq(CtrIncomeContract::getProjectId, projectId) .eq(CtrIncomeContract::getProjectId, projectId)
.last("limit 1") .last("limit 1")
); );
if (contract != null && contract.getPayRatio()!= null) { if (contract != null && contract.getPayRatio() != null) {
actualAmount = actualAmount.add(projectMonthlyAmountMap.get(projectId).multiply(contract.getPayRatio()).divide(HUNDRED)); actualAmount = actualAmount.add(projectMonthlyAmountMap.get(projectId).multiply(contract.getPayRatio()).divide(HUNDRED).setScale(4, RoundingMode.HALF_UP));
} }
} }
@ -169,8 +169,8 @@ public class MoneyBigScreenController {
.last("limit 1") .last("limit 1")
); );
if (contract != null && contract.getPayRatio()!= null) { if (contract != null && contract.getPayRatio() != null) {
actualAmount = actualAmount.add(projectAmountMap.get(contractCode).multiply(contract.getPayRatio()).divide(HUNDRED)); actualAmount = actualAmount.add(projectAmountMap.get(contractCode).multiply(contract.getPayRatio()).setScale(4, RoundingMode.HALF_UP).divide(HUNDRED));
} }
} }
@ -243,7 +243,7 @@ public class MoneyBigScreenController {
.filter(contract -> contract.getAmount() != null && contract.getAmount().compareTo(THIRD_PHASE) >= 0) .filter(contract -> contract.getAmount() != null && contract.getAmount().compareTo(THIRD_PHASE) >= 0)
.count(); .count();
return R.ok(new MoneyContractCountVo(4, 4, 6, 6)); return R.ok(new MoneyContractCountVo(4, 4, 6, 6));
// return R.ok(new MoneyContractCountVo(lessThan1M, between1MAnd5M, between5MAnd10M, greaterThanOrEqualTo10M)); // return R.ok(new MoneyContractCountVo(lessThan1M, between1MAnd5M, between5MAnd10M, greaterThanOrEqualTo10M));
} }
@ -350,8 +350,8 @@ public class MoneyBigScreenController {
.eq(CtrIncomeContract::getProjectId, projectId) .eq(CtrIncomeContract::getProjectId, projectId)
.last("limit 1") .last("limit 1")
); );
if (contract != null && contract.getPayRatio()!= null) { if (contract != null && contract.getPayRatio() != null) {
incomeAmount = incomeAmount.add(incomeGroupedByProject.get(projectId).multiply(contract.getPayRatio()).divide(HUNDRED)); incomeAmount = incomeAmount.add(incomeGroupedByProject.get(projectId).multiply(contract.getPayRatio()).setScale(4, RoundingMode.HALF_UP).divide(HUNDRED));
} }
} }
@ -380,8 +380,8 @@ public class MoneyBigScreenController {
.last("limit 1") .last("limit 1")
); );
if (contract != null && contract.getPayRatio()!= null) { if (contract != null && contract.getPayRatio() != null) {
expensesAmount = expensesAmount.add(expenseGroupedByContract.get(contractCode).multiply(contract.getPayRatio()).divide(HUNDRED)); expensesAmount = expensesAmount.add(expenseGroupedByContract.get(contractCode).multiply(contract.getPayRatio()).setScale(4, RoundingMode.HALF_UP).divide(HUNDRED));
} }
} }
@ -448,8 +448,8 @@ public class MoneyBigScreenController {
.eq(CtrIncomeContract::getProjectId, projectId) .eq(CtrIncomeContract::getProjectId, projectId)
.last("limit 1") .last("limit 1")
); );
if (contract != null && contract.getPayRatio()!= null) { if (contract != null && contract.getPayRatio() != null) {
incomeAmount = incomeAmount.add(incomeGroupedByProject.get(projectId).multiply(contract.getPayRatio()).divide(HUNDRED)); incomeAmount = incomeAmount.add(incomeGroupedByProject.get(projectId).multiply(contract.getPayRatio()).setScale(4, RoundingMode.HALF_UP).divide(HUNDRED));
} }
} }
@ -478,8 +478,8 @@ public class MoneyBigScreenController {
.last("limit 1") .last("limit 1")
); );
if (contract != null && contract.getPayRatio()!= null) { if (contract != null && contract.getPayRatio() != null) {
expensesAmount = expensesAmount.add(expenseGroupedByContract.get(contractCode).multiply(contract.getPayRatio()).divide(HUNDRED)); expensesAmount = expensesAmount.add(expenseGroupedByContract.get(contractCode).multiply(contract.getPayRatio()).setScale(4, RoundingMode.HALF_UP).divide(HUNDRED));
} }
} }
@ -511,7 +511,7 @@ public class MoneyBigScreenController {
.filter(java.util.Objects::nonNull) // 过滤掉 null 值 .filter(java.util.Objects::nonNull) // 过滤掉 null 值
.reduce(BigDecimal.ZERO, BigDecimal::add); .reduce(BigDecimal.ZERO, BigDecimal::add);
List<OutSettlementValueSubcontract> subcontractList = settlementValueSubcontractService.list(); List<OutSettlementValueSubcontract> subcontractList = settlementValueSubcontractService.list();
BigDecimal expensesCash = subcontractList.stream() BigDecimal expensesCash = subcontractList.stream()
.map(OutSettlementValueSubcontract::getSettlementValue) .map(OutSettlementValueSubcontract::getSettlementValue)
@ -526,8 +526,6 @@ public class MoneyBigScreenController {
} }
/** /**
* 获取当前月份的开始时间和结束时间 * 获取当前月份的开始时间和结束时间
* *
@ -546,17 +544,17 @@ public class MoneyBigScreenController {
/** /**
* 查询项目天气 * 查询项目天气
*/ */
@SaCheckPermission("project:bigScreen:weather") // @SaCheckPermission("project:bigScreen:weather")
@GetMapping("/weather/{projectId}") @GetMapping("/weather/{projectId}")
public R<List<BusProjectWeatherVo>> getProjectWeather(@NotNull(message = "主键不能为空") public R<List<WeatherVo>> getProjectWeather(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
return R.ok(moneyBigScreenService.getProjectWeather(projectId)); return R.ok(moneyBigScreenService.getProjectWeather(projectId));
} }
/** /**
* 查询项目安全天数 * 查询项目安全天数
*/ */
@SaCheckPermission("project:bigScreen:safetyDay") // @SaCheckPermission("project:bigScreen:safetyDay")
@GetMapping("/safetyDay/{projectId}") @GetMapping("/safetyDay/{projectId}")
public R<BusProjectSafetyDayVo> getProjectSafetyDay(@NotNull(message = "主键不能为空") public R<BusProjectSafetyDayVo> getProjectSafetyDay(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {

View File

@ -1,28 +1,50 @@
package org.dromara.bigscreen.controller; package org.dromara.bigscreen.controller;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.bigscreen.domain.dto.ProjectUpdateDto;
import org.dromara.bigscreen.domain.dto.TanchuangInfoReq;
import org.dromara.bigscreen.domain.dto.Ys7DeviceUpdateReq;
import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo; import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo;
import org.dromara.bigscreen.domain.vo.ProjectLandVo; import org.dromara.bigscreen.domain.vo.ProjectLandVo;
import org.dromara.bigscreen.domain.vo.ProjectPeopleVo; import org.dromara.bigscreen.domain.vo.ProjectPeopleVo;
import org.dromara.bigscreen.domain.vo.ProjectSafetyInspectionVo; 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.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
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;
import org.dromara.land.domain.BusLandTransferLedgerSon;
import org.dromara.land.service.IBusLandBlockService; import org.dromara.land.service.IBusLandBlockService;
import org.dromara.land.service.IBusLandTransferLedgerService; import org.dromara.land.service.IBusLandTransferLedgerService;
import org.dromara.land.service.impl.BusLandTransferLedgerSonServiceImpl;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.manager.ys7manager.Ys7Manager;
import org.dromara.other.domain.OthYs7Device;
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.BusProjectWeatherVo;
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.IBusProjectService;
import org.dromara.quality.domain.dto.qualityinspection.QltQualityInspectionGisReq;
import org.dromara.quality.domain.vo.qualityinspection.QltQualityInspectionListGisVo;
import org.dromara.quality.service.IQltQualityInspectionService;
import org.dromara.safety.domain.dto.safetyinspection.HseSafetyInspectionGisReq;
import org.dromara.safety.domain.vo.safetyinspection.HseSafetyInspectionListGisVo;
import org.dromara.safety.service.IHseSafetyInspectionService;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -40,7 +62,7 @@ import java.util.stream.Collectors;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@RequestMapping("/project/big/screen") @RequestMapping("/project/big/screen")
public class ProjectBigScreenController { public class ProjectBigScreenController extends BaseController {
@Resource @Resource
private ProjectBigScreenService projectBigScreenService; private ProjectBigScreenService projectBigScreenService;
@ -49,15 +71,53 @@ public class ProjectBigScreenController {
private final IBusLandBlockService busLandBlockService; private final IBusLandBlockService busLandBlockService;
private final IOthYs7DeviceService othYs7DeviceService;
private final IBusProjectService projectService;
private final IBusProjectNewsService projectNewsService;
private final IQltQualityInspectionService qualityInspectionService;
private final IHseSafetyInspectionService safetyInspectionService;
private final Ys7Manager ys7Manager;
private final BusLandTransferLedgerSonServiceImpl busLandTransferLedgerSonService;
/** /**
* 查询项目土地统计 * 查询项目土地统计
*/ */
// @SaCheckPermission("project:big:screen")
@GetMapping("/{projectId}") @GetMapping("/{projectId}")
public R<List<ProjectLandVo>> landCount(@NotNull(message = "主键不能为空") public R<List<ProjectLandVo>> landCount(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
List<BusLandTransferLedger> levelList = busLandTransferLedgerService.list(Wrappers.lambdaQuery(BusLandTransferLedger.class) List<BusLandTransferLedger> levelList = busLandTransferLedgerService.list(Wrappers.lambdaQuery(BusLandTransferLedger.class)
.eq(BusLandTransferLedger::getProjectId, projectId)); .eq(BusLandTransferLedger::getProjectId, projectId));
if (CollectionUtil.isNotEmpty(levelList)) {
List<Long> list1 = levelList.stream().map(BusLandTransferLedger::getId).toList();
LambdaQueryWrapper<BusLandTransferLedgerSon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(BusLandTransferLedgerSon::getParentId, list1);
List<BusLandTransferLedgerSon> sonList = busLandTransferLedgerSonService.list(lambdaQueryWrapper);
Map<Long, BigDecimal> collect = sonList.stream()
.filter(vo -> "1".equals(vo.getTransferStatus()))
.collect(Collectors.groupingBy(
BusLandTransferLedgerSon::getParentId,
Collectors.reducing(
BigDecimal.ZERO,
BusLandTransferLedgerSon::getAreaValue,
BigDecimal::add
)
));
for (BusLandTransferLedger busLandTransferLedger : levelList) {
BigDecimal areaValue = collect.get(busLandTransferLedger.getId());
if (areaValue != null) {
busLandTransferLedger.setTransferAea(areaValue);
}
}
}
// 根据 landBlockId 分组,并对 designArea 和 transferAea 进行求和 // 根据 landBlockId 分组,并对 designArea 和 transferAea 进行求和
Map<Long, Map<String, BigDecimal>> groupedResult = levelList.stream() Map<Long, Map<String, BigDecimal>> groupedResult = levelList.stream()
.collect(Collectors.groupingBy( .collect(Collectors.groupingBy(
@ -101,17 +161,17 @@ public class ProjectBigScreenController {
/** /**
* 查询项目天气 * 查询项目天气
*/ */
@SaCheckPermission("project:bigScreen:weather") // @SaCheckPermission("project:big:screen")
@GetMapping("/weather/{projectId}") @GetMapping("/weather/{projectId}")
public R<List<BusProjectWeatherVo>> getProjectWeather(@NotNull(message = "主键不能为空") public R<List<WeatherVo>> getProjectWeather(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
return R.ok(projectBigScreenService.getProjectWeather(projectId)); return R.ok(projectBigScreenService.getProjectWeather(projectId));
} }
/** /**
* 查询项目安全天数 * 查询项目安全天数
*/ */
@SaCheckPermission("project:bigScreen:safetyDay") // @SaCheckPermission("project:big:screen")
@GetMapping("/safetyDay/{projectId}") @GetMapping("/safetyDay/{projectId}")
public R<BusProjectSafetyDayVo> getProjectSafetyDay(@NotNull(message = "主键不能为空") public R<BusProjectSafetyDayVo> getProjectSafetyDay(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
@ -121,7 +181,7 @@ public class ProjectBigScreenController {
/** /**
* 查询项目公告 * 查询项目公告
*/ */
@SaCheckPermission("project:bigScreen:news") // @SaCheckPermission("project:big:screen")
@GetMapping("/news/{projectId}") @GetMapping("/news/{projectId}")
public R<List<BusProjectNewsVo>> getProjectNews(@NotNull(message = "主键不能为空") public R<List<BusProjectNewsVo>> getProjectNews(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
@ -131,7 +191,7 @@ public class ProjectBigScreenController {
/** /**
* 查询项目AI安全巡检 * 查询项目AI安全巡检
*/ */
@SaCheckPermission("project:bigScreen:safetyInspection") // @SaCheckPermission("project:big:screen")
@GetMapping("/safetyInspection/{projectId}") @GetMapping("/safetyInspection/{projectId}")
public R<List<ProjectSafetyInspectionVo>> getProjectSafetyInspection(@NotNull(message = "主键不能为空") public R<List<ProjectSafetyInspectionVo>> getProjectSafetyInspection(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
@ -141,7 +201,7 @@ public class ProjectBigScreenController {
/** /**
* 查询项目人员情况 * 查询项目人员情况
*/ */
@SaCheckPermission("project:bigScreen:people") // @SaCheckPermission("project:big:screen")
@GetMapping("/people/{projectId}") @GetMapping("/people/{projectId}")
public R<ProjectPeopleVo> getProjectPeople(@NotNull(message = "主键不能为空") public R<ProjectPeopleVo> getProjectPeople(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
@ -151,20 +211,165 @@ public class ProjectBigScreenController {
/** /**
* 查询项目形象进度 * 查询项目形象进度
*/ */
@SaCheckPermission("project:bigScreen:imageProgress") // @SaCheckPermission("project:big:screen")
@GetMapping("/imageProgress/{projectId}") @GetMapping("/imageProgress/{projectId}")
public R<ProjectImageProgressVo> getProjectImageProgress(@NotNull(message = "主键不能为空") public R<List<ProjectImageProgressVo>> getProjectImageProgress(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
return R.ok(projectBigScreenService.getProjectImageProgress(projectId)); return R.ok(projectBigScreenService.getProjectImageProgress(projectId));
} }
/** /**
* 查询项目概括 * 查询项目概括
*/ */
@SaCheckPermission("project:bigScreen:generalize") // @SaCheckPermission("project:big:screen")
@GetMapping("/generalize/{projectId}") @GetMapping("/generalize/{projectId}")
public R<String> getProjectGeneralize(@NotNull(message = "主键不能为空") public R<String> getProjectGeneralize(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) { @PathVariable Long projectId) {
return R.ok(projectBigScreenService.getProjectGeneralize(projectId)); return R.ok(projectBigScreenService.getProjectGeneralize(projectId));
} }
/**
* 查询设备列表
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getClientList/{projectId}")
public R<List<Map<String, Object>>> getClientList(@NotNull(message = "主键不能为空")
@PathVariable Long projectId) {
return R.ok(projectBigScreenService.getClientList(projectId));
}
/**
* 修改萤石摄像头
*/
// @SaCheckPermission("project:big:screen")
@RepeatSubmit()
@PutMapping("/device")
public R<Void> edit(@Validated @RequestBody Ys7DeviceUpdateReq req) {
OthYs7Device one = othYs7DeviceService.lambdaQuery()
.eq(OthYs7Device::getDeviceSerial, req.getDeviceSerial())
.last("limit 1")
.one();
if (one == null) {
throw new ServiceException("萤石摄像头信息不存在", HttpStatus.NOT_FOUND);
}
// 将实体类和 DTO 进行转换
OthYs7Device ys7Device = new OthYs7Device();
BeanUtils.copyProperties(req, ys7Device);
ys7Device.setId(one.getId());
// 判断是否更新名称
String deviceName = req.getDeviceName();
if (deviceName != null && !deviceName.equals(one.getDeviceName())) {
Long count = othYs7DeviceService.lambdaQuery()
.eq(OthYs7Device::getDeviceName, req.getDeviceName())
.count();
if (count > 0) {
throw new ServiceException("已存在同名萤石摄像头", HttpStatus.CONFLICT);
}
// 更新云端名称
Boolean result = ys7Manager.updateDeviceName(one.getDeviceSerial(), deviceName);
if (!result) {
throw new ServiceException("更新云端萤石摄像头名称异常", HttpStatus.ERROR);
}
}
if (req.getLatitude() != null && req.getLongitude() != null) {
ys7Device.setLatitude(req.getLatitude());
ys7Device.setLongitude(req.getLongitude());
}
return toAjax(othYs7DeviceService.updateById(ys7Device));
}
/**
* 查询质量信息
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getQualityList/gis")
public R<QltQualityInspectionListGisVo> queryGisList(QltQualityInspectionGisReq req) {
return R.ok(qualityInspectionService.queryGisList(req));
}
/**
* 查询大屏安全信息
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getSafetyList/gis")
public R<HseSafetyInspectionListGisVo> queryGisList(HseSafetyInspectionGisReq req) {
return R.ok(safetyInspectionService.queryGisList(req));
}
/**
* 查询GPS设备用户列表
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getList")
public R<List<String>> getList(Long projectId) {
return R.ok(projectBigScreenService.getList(projectId));
}
/**
* 新增GPS设备详细
*/
// @SaCheckPermission("project:big:screen")
@Log(title = "GPS设备详细", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/setList")
public void setList(@RequestBody GpsEquipmentBo bo) {
projectBigScreenService.setList(bo);
}
/**
* 查询地图项目分类
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getProjectMapList")
public R<Map<String, Map<String, Map<String, String>>>> getProjectMapList() {
return R.ok(projectService.getProjectMapList());
}
/**
* 查询地图项目分类
*/
// @SaCheckPermission("project:big:screen")
@PostMapping("/updatePosition")
public R<Void> updatePosition(@RequestBody ProjectUpdateDto dto) {
return toAjax(projectService.updatePosition(dto));
}
/**
* 查询项目地域分散图
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getProjectDiYv")
public R<Map<String, Long>> getProjectDiYv() {
return R.ok(projectService.getProjectDiYv());
}
/**
* 计划和实际容量对比
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getProjectCapacity")
public R<Map<String, Map<String, String>>> getProjectCapacity() {
return R.ok(projectService.getProjectCapacity());
}
/**
* 更新无人机缓存
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/setWrjHc")
public void setWrjHc() {
projectBigScreenService.setWrjHc();
}
/**
* 更新无人机缓存
*/
// @SaCheckPermission("project:big:screen")
@GetMapping("/getInfoData")
public R<Map<String, Map<String, Object>>> getInfoData(TanchuangInfoReq req) {
return R.ok(projectBigScreenService.getInfoData(req));
}
} }

View File

@ -0,0 +1,58 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class BusAttendanceByGo {
private Long id; // 主键ID
private String userName; // 人员姓名
private String pacePhoto; // 人脸照
private Long projectId; // 项目id
private String createBy; // 创建者
private String updateBy; // 更新者
private LocalDateTime createdAt; // 创建时间
private LocalDateTime updatedAt; // 更新时间
private LocalDateTime deletedAt; // 删除时间
private String clockOn; // 上午打卡
private String clockOff; // 下午打卡
private String printingDate; // 年月日打卡时间
private String isPinch; // 1正常,2迟到,3早退,4缺勤,5补卡
private String openid; // 微信id
private String pinchOpenId; // 代打id
private String clockRecord; // 多次打卡时间记录
private String pinchUserName; // 代打人姓名
private String commuter; // 上下班1上班 2下班
private String punchRange; // 打卡范围
private BigDecimal dailyWage; // 日薪
private String lng; // 经度
private String lat; // 纬度
private String location; // 逆编码地址信息
private LocalDateTime missing; // 缺卡统一处理时间
}

View File

@ -0,0 +1,91 @@
package org.dromara.bigscreen.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("bus_construction_user")
public class BusConstructionUser {
@TableId(type = IdType.AUTO)
private Long id; // 主键ID
private String openid; // 微信id
private String nickName; // 微信名称
private Long teamId; // 班组id
private String headIcon; // 登陆照片
private String pacePhoto; // 人脸照
private String userName; // 人员姓名
private Long projectId; // 项目id
private String status; // 状态0在职 1离职-字典position_status
private String isPinch; // 是否代打
private String ifManagement; // 是否班组管理
private String createBy; // 创建者
private String updateBy; // 更新者
private LocalDateTime createdAt; // 创建时间
private LocalDateTime updatedAt; // 更新时间
private LocalDateTime deletedAt; // 删除时间
private String phone; // 电话
private String sex; // 1:男,2女,3保密
private String sfzNation; // 身份证民族
private String sfzNumber; // 身份证号码
private String sfzStart; // 身份证有效开始期
private String sfzEnd; // 身份证有效结束期
private String sfzSite; // 身份证地址
private String sfzBirth; // 身份证出生日期
private String nativePlace; // 籍贯
private String yhkNumber; // 银行卡号
private String yhkOpeningBank; // 开户行
private String yhkCardholder; // 持卡人
private String typeOfWork; // 工种(字典)
private String clock; // 打卡(1启用打卡 2禁止打卡)
private Long labourserviceId; // 劳务公司id
private String entryDate; // 入场时间
private String leaveDate; // 离场时间
private BigDecimal salary; // 薪水为0表示无效
private String projectRecord; // 是否开启项目备案1开启 2不开启
private String wxOrPc; // 哪添加的1表示pc 2表示小程序
private String subscription; // 消息订阅状态1订阅 2无订阅
private String devNum; // 安全帽设备标识
}

View File

@ -0,0 +1,52 @@
package org.dromara.bigscreen.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 企业大事记
*/
@Data
@TableName("bus_corporate_events")
public class BusCorporateEvents {
@TableId(type = IdType.AUTO)
private Long id;
/**
* 标题
*/
private String headline;
/**
* 内容
*/
private String content;
/**
* 创建人
*/
private Long createdBy;
/**
* 更新人
*/
private Long updatedBy;
/**
* 创建时间
*/
private LocalDateTime createdAt;
/**
* 更新时间
*/
private LocalDateTime updatedAt;
/**
* 删除时间(软删除标记)
*/
private LocalDateTime deletedAt;
}

View File

@ -0,0 +1,31 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BusProjectTeamByGo {
private Long id; // 主键id
private Long projectId; // 项目id
private String name; // 班组名称
private String isClockIn; // 范围内打卡0范围内打卡 1任何地点打卡
private String punchRange; // 打卡范围(id串)
private String remark; // 备注
private String createBy; // 创建者
private String updateBy; // 更新者
private Long createDept; // 创建部门
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 更新时间
}

View File

@ -0,0 +1,25 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BusProjectTeamMemberByGo {
private Long id; // 主键id
private Long teamId; // 班组id
private Long projectId; // 项目id
private Long memberId; // 施工人员id
private String postId; // 岗位0普通员工1组长
private String remark; // 备注
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 更新时间
}

View File

@ -0,0 +1,35 @@
package org.dromara.bigscreen.domain;
import lombok.Data;
import java.util.Date;
@Data
public class BusTour {
private Long id; // 主键ID
private Long projectId; // 项目id
private String tourCategory; // 类别字典(如:无人机识别、监控拍摄)
private String tourType; // 类型字典(如:安全帽、安全带)
private String picture; // 图片路径
private Integer num; // 违规数量
private String describe; // 故障描述
private Date createdAt; // 创建时间
private Date updatedAt; // 更新时间
private Date deletedAt; // 删除时间
private String tableName; // 表名
private Long tableId; // 表id
private String sxtName; // 摄像头名称
}

View File

@ -0,0 +1,34 @@
package org.dromara.bigscreen.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sys_project_introduce")
public class SysProjectIntroduce {
@TableId(type = IdType.AUTO)
private Long id; // 主键id
private Long projectId; // 项目id
private String headline; // 标题
private String richText; // 富文本
private String createdBy; // 创建人
private String updatedBy; // 更新人
private LocalDateTime createdAt; // 创建时间
private LocalDateTime updatedAt; // 更新时间
private LocalDateTime deletedAt; // 删除时间
private String files; // 附件
}

View File

@ -0,0 +1,16 @@
package org.dromara.bigscreen.domain.dto;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class ProjectUpdateDto implements Serializable {
private Long projectId; // 项目id
private String position; // 图片
}

View File

@ -0,0 +1,11 @@
package org.dromara.bigscreen.domain.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class TanchuangInfoReq implements Serializable {
private Long id;
}

View File

@ -0,0 +1,31 @@
package org.dromara.bigscreen.domain.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-09 15:16
*/
@Data
public class WeatherQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -2550570761981859666L;
/**
* 经度
*/
@NotBlank(message = "经度不能为空")
private String lng;
/**
* 纬度
*/
@NotBlank(message = "纬度不能为空")
private String lat;
}

View File

@ -0,0 +1,26 @@
package org.dromara.bigscreen.domain.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-09 15:16
*/
@Data
public class WurenjiQueryReq {
/**
* 经度
*/
private String longitude;
/**
* 纬度
*/
private String latitude;
}

View File

@ -0,0 +1,50 @@
package org.dromara.bigscreen.domain.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025/6/13 10:19
*/
@Data
public class Ys7DeviceUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -3434796275594146484L;
/**
* 设备序列号
*/
@NotBlank(message = "设备序列号不能为空")
private String deviceSerial;
/**
* 设备名称
*/
private String deviceName;
/**
* 设备详情
*/
private String detail;
/**
* 备注
*/
private String remark;
/**
* 纬度精确到6位小数
*/
private BigDecimal latitude;
/**
* 经度精确到6位小数
*/
private BigDecimal longitude;
}

View File

@ -0,0 +1,47 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-09-09 15:59
*/
@Data
public class EnterpriseKeyIndexVo implements Serializable {
@Serial
private static final long serialVersionUID = -3987781906203623727L;
/**
* 光伏项目数量
*/
private Integer photovoltaicCount;
/**
* 风电项目数量
*/
private Integer windElectricityCount;
/**
* 光伏项目总容量
*/
private BigDecimal photovoltaicTotalCapacity;
/**
* 风电项目总容量
*/
private BigDecimal windElectricityTotalCapacity;
/**
* 业绩数量
*/
private Long performanceCount;
/**
* 典型业绩
*/
private Long typicalPerformance;
}

View File

@ -0,0 +1,38 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-09-09 19:12
*/
@Data
public class OutputValueComparisonVo implements Serializable {
@Serial
private static final long serialVersionUID = -6902563869975528076L;
/**
* 项目id
*/
private Long projectId;
/**
* 项目名称
*/
private String projectName;
/**
* 计划产值
*/
private BigDecimal planValue;
/**
* 实际产值
*/
private BigDecimal actualValue;
}

View File

@ -0,0 +1,22 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
@Data
public class PeopleCountVo {
/**
* 施工人员
*/
private Long constructionPersonnelCount;
/**
* 分包人员
*/
private Long SubcontractorsCount;
/**
* 管理人员
*/
private Long managersCount;
}

View File

@ -0,0 +1,33 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-09-09 16:04
*/
@Data
public class PeopleOverviewVo implements Serializable {
@Serial
private static final long serialVersionUID = -4353811031023888101L;
/**
* 出勤人数
*/
private Long attendanceNumber;
/**
* 出勤率
*/
private BigDecimal attendanceRate;
/**
* 施工人员数量
*/
private Long constructorNumber;
}

View File

@ -0,0 +1,29 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
@Data
public class ProjectAttendanceCountVo {
/**
* 项目id
*/
private Long projectId;
/**
* 项目名称
*/
private String projectName;
/**
* 考勤人数
*/
private Long attendanceCount;
/**
* 考勤率
*/
private Double attendanceRate;
}

View File

@ -16,39 +16,49 @@ public class ProjectImageProgressVo implements Serializable {
@Serial @Serial
private static final long serialVersionUID = 7963637133004484891L; private static final long serialVersionUID = 7963637133004484891L;
/**
* 类别名称
*/
private String progressName;
/**
* 进度百分比
*/
private BigDecimal progressTotal;
/** /**
* 场区百分比 * 场区百分比
*/ */
private BigDecimal areaPercentage; // private BigDecimal areaPercentage;
/** /**
* 道路百分比 * 道路百分比
*/ */
private BigDecimal roadPercentage; // private BigDecimal roadPercentage;
/** /**
* 集电线路百分比 * 集电线路百分比
*/ */
private BigDecimal collectorLinePercentage; // private BigDecimal collectorLinePercentage;
/** /**
* 送出线路百分比 * 送出线路百分比
*/ */
private BigDecimal exportLinePercentage; // private BigDecimal exportLinePercentage;
/** /**
* 升压站百分比 * 升压站百分比
*/ */
private BigDecimal substationPercentage; // private BigDecimal substationPercentage;
/** /**
* 箱变百分比 * 箱变百分比
*/ */
private BigDecimal boxTransformerPercentage; // private BigDecimal boxTransformerPercentage;
/** /**
* 总百分比 * 总百分比
*/ */
private BigDecimal totalPercentage; // private BigDecimal totalPercentage;
} }

View File

@ -0,0 +1,39 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-09 16:51
*/
@Data
public class ProjectProgressAnalysisVo implements Serializable {
@Serial
private static final long serialVersionUID = -2170524608375159201L;
/**
* 并网总容量 (MW)
*/
private BigDecimal gridConnectedCapacity;
/**
* 计划总容量 (MW)
*/
private BigDecimal plannedCapacity;
/**
* 延期项目数量
*/
private Integer delayedProjectCount;
/**
* 项目进度详情
*/
List<ProjectProgressDetailVo> projectProgressDetailList;
}

View File

@ -0,0 +1,39 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-09-12 18:55
*/
@Data
public class ProjectProgressCapacityVo implements Serializable {
@Serial
private static final long serialVersionUID = -7370580195063977801L;
/**
* 项目id
*/
private Long projectId;
/**
* 项目名称
*/
private String projectName;
/**
* 进度百分比
*/
private BigDecimal progressPercentage;
/**
* 计划容量
*/
private BigDecimal plannedCapacity;
}

View File

@ -0,0 +1,33 @@
package org.dromara.bigscreen.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-09-09 16:55
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProjectProgressDetailVo {
/**
* 项目名称
*/
private String projectName;
/**
* 项目容量
*/
private BigDecimal projectCapacity;
/**
* 施工进度百分比 (0~100)
*/
private BigDecimal completionRate;
}

View File

@ -0,0 +1,48 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
/**
* @author lilemy
* @date 2025-09-09 20:04
*/
@Data
public class RiskEarlyWarningVo implements Serializable {
@Serial
private static final long serialVersionUID = 5250172770638676715L;
/**
* 时间
*/
private LocalDate date;
/**
* 风险类型
*/
private String riskType;
/**
* 报警内容
*/
private String alarmContent;
/**
* 威胁等级
*/
private String dangerLevel;
/**
* 来源
*/
private String source;
/**
* 告警等级
*/
private String alarmLevel;
}

View File

@ -0,0 +1,19 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
@Data
public class TodayAttendanceCountVo {
/**
* 考勤人员数量
*/
private Long attendanceCount;
/**
* 出勤率
*/
private Double attendanceRate;
}

View File

@ -0,0 +1,92 @@
package org.dromara.bigscreen.listener;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.drone.domain.DroProjectDrone;
import org.dromara.drone.service.IDroProjectDroneService;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.Objects;
/**
* Redis消息监听器用于处理订阅频道收到的消息
*/
@Component
public class RedisMessageListener implements MessageListener {
@Lazy
private final StringRedisTemplate stringRedisTemplate;
@Resource
@Lazy
private IDroProjectDroneService droProjectDroneService;
// 构造函数注入StringRedisTemplate
public RedisMessageListener(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
/**
* 处理接收到的消息
* @param message 消息对象
* @param pattern 订阅的模式
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 处理消息
// System.out.println("返回:"+stringRedisTemplate.getStringSerializer().deserialize(message.getBody()));
String gateway = JSONUtil.parseObj(stringRedisTemplate.getStringSerializer().deserialize(message.getBody())).getStr("gateway");
String key = "";
if (JSONUtil.parseObj(stringRedisTemplate.getStringSerializer().deserialize(message.getBody())).getJSONObject("data").get("job_number") != null) {
key = "wrj:osd1:"+gateway;
}else if (JSONUtil.parseObj(stringRedisTemplate.getStringSerializer().deserialize(message.getBody())).getJSONObject("data").get("wireless_link") != null) {
key = "wrj:osd2:"+gateway;
}else if (JSONUtil.parseObj(stringRedisTemplate.getStringSerializer().deserialize(message.getBody())).getJSONObject("data").get("network_state") != null) {
key = "wrj:osd3:"+gateway;
DroProjectDrone droProjectDrone = droProjectDroneService.getBaseMapper().selectOne(new LambdaQueryWrapper<DroProjectDrone>().eq(DroProjectDrone::getDroneSn, gateway));
setWs(message, gateway, droProjectDrone);
}else{
key = "wrj:osd4:"+gateway;
DroProjectDrone droProjectDrone = droProjectDroneService.getBaseMapper().selectOne(new LambdaQueryWrapper<DroProjectDrone>().eq(DroProjectDrone::getDroneSn, gateway));
setWs(message, gateway, droProjectDrone);
}
stringRedisTemplate
.opsForValue()
.set(key
, Objects.requireNonNull(stringRedisTemplate.getStringSerializer().deserialize(message.getBody())));
}
private void setWs(Message message, String gateway, DroProjectDrone droProjectDrone) {
String pushContent = buildPushMessage(gateway,stringRedisTemplate.getStringSerializer().deserialize(message.getBody()), droProjectDrone.getProjectId());
// 发送给指定用户equipment.getUserId()
WebSocketMessageDto messageDto = new WebSocketMessageDto();
messageDto.setMessage(pushContent);
messageDto.setSessionKeys(Collections.singletonList(droProjectDrone.getProjectId()));
WebSocketUtils.publishMessage(messageDto);
}
private String buildPushMessage(String key, String message, Long projectId) {
JSONObject messageObj = new JSONObject();
messageObj.put("type", "wrj_DATA_UPDATE");
messageObj.put("projectId",projectId.toString());
messageObj.put("clientId",key);
// 位置信息
JSONObject locationObj = new JSONObject();
locationObj.put("latitude", JSONUtil.parseObj(message).getJSONObject("data").get("latitude").toString()); // 纬度
locationObj.put("longitude", JSONUtil.parseObj(message).getJSONObject("data").get("longitude").toString()); // 经度
messageObj.put("location", locationObj);
return messageObj.toString();
}
}

View File

@ -0,0 +1,193 @@
package org.dromara.bigscreen.manager;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.drone.service.IDroProjectDroneService;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* Redis 订阅管理器(定时任务动态更新订阅关系)
*/
@Component
@Slf4j
public class RedisSubscribeManager {
// 1. 注入 Redis 核心组件
@Resource
private RedisMessageListenerContainer redisMessageListenerContainer;
@Resource
private MessageListenerAdapter redisMessageListenerAdapter;
// 2. 注入业务 Service延迟加载避免循环依赖
@Resource
@Lazy
private IDroProjectDroneService droProjectDroneService;
// 3. 维护已订阅的主题关系key=完整主题如wrj:8UUXN4P00A06NKvalue=对应的PatternTopic
private final Map<String, PatternTopic> subscribedTopics = new ConcurrentHashMap<>();
/**
* 项目启动后立即执行一次订阅(避免等待定时任务首次执行)
*/
@PostConstruct
public void initSubscribe() {
log.info("项目启动初始化Redis订阅...");
// 步骤1从数据库获取最新的主题列表原逻辑getTopicsByKeyPrefix
List<String> latestKeys = droProjectDroneService.getTopicsByKeyPrefix();
if (latestKeys == null || latestKeys.isEmpty()) {
log.warn("未获取到任何主题,将取消所有现有订阅");
cancelAllSubscribes();
return;
}
// 步骤2构建最新的完整主题格式wrj:key
Set<String> latestFullTopics = new HashSet<>();
for (String key : latestKeys) {
latestFullTopics.add("wrj:osd1:" + key);
latestFullTopics.add("wrj:osd2:" + key);
latestFullTopics.add("wrj:osd3:" + key);
latestFullTopics.add("wrj:osd4:" + key);
}
// 步骤3对比现有订阅删除过期主题
cancelExpiredSubscribes(latestFullTopics);
// 步骤4对比现有订阅新增未订阅的主题
addNewSubscribes(latestFullTopics);
}
/**
* 4. 定时任务定期更新订阅每5分钟执行一次可调整cron表达式
* cron格式秒 分 时 日 月 周 年示例0 0/5 * * * ? 表示每5分钟
*/
@Scheduled(cron = "0 0/6 * * * ?")
public void dynamicUpdateSubscribe() {
try {
Object object = RedisUtils.getCacheObject("xmjdap:ws");
log.info("开始执行Redis订阅更新定时任务...");
if (object == null) {
cancelAllSubscribes();
return;
}
long oldTime = Long.parseLong(String.valueOf(object));
long now = System.currentTimeMillis();
if (now-oldTime > 300000) {
RedisUtils.deleteObject("xmjdap:ws");
cancelAllSubscribes();
return;
}
// 步骤1从数据库获取最新的主题列表原逻辑getTopicsByKeyPrefix
List<String> latestKeys = droProjectDroneService.getTopicsByKeyPrefix();
if (latestKeys == null || latestKeys.isEmpty()) {
log.warn("定时任务未获取到任何主题,将取消所有现有订阅");
cancelAllSubscribes();
return;
}
// 步骤2构建最新的完整主题格式wrj:key
Set<String> latestFullTopics = new HashSet<>();
for (String key : latestKeys) {
latestFullTopics.add("wrj:osd1:" + key);
latestFullTopics.add("wrj:osd2:" + key);
latestFullTopics.add("wrj:osd3:" + key);
latestFullTopics.add("wrj:osd4:" + key);
}
// 步骤3对比现有订阅删除过期主题
cancelExpiredSubscribes(latestFullTopics);
// 步骤4对比现有订阅新增未订阅的主题
addNewSubscribes(latestFullTopics);
log.info("Redis订阅更新完成当前已订阅主题数{}", subscribedTopics.size());
} catch (Exception e) {
log.error("Redis订阅更新定时任务执行失败", e);
// 异常时不修改现有订阅,避免误删
}
}
/**
* 取消过期的订阅(现有订阅不在最新列表中的主题)
*/
private void cancelExpiredSubscribes(Set<String> latestFullTopics) {
// 遍历现有订阅,找出需要删除的主题
Set<String> expiredTopics = subscribedTopics.keySet().stream()
.filter(topic -> !latestFullTopics.contains(topic))
.collect(Collectors.toSet());
if (expiredTopics.isEmpty()) {
log.info("无过期订阅主题,无需删除");
return;
}
// 取消每个过期主题的订阅
for (String expiredTopic : expiredTopics) {
PatternTopic topic = subscribedTopics.get(expiredTopic);
if (topic != null) {
// 从容器中移除监听器(取消订阅)
redisMessageListenerContainer.removeMessageListener(redisMessageListenerAdapter, topic);
subscribedTopics.remove(expiredTopic);
log.info("已取消过期订阅:{}", expiredTopic);
}
}
}
/**
* 新增未订阅的主题(最新列表中有但现有订阅没有的主题)
*/
private void addNewSubscribes(Set<String> latestFullTopics) {
// 遍历最新主题,找出需要新增的主题
Set<String> newTopics = latestFullTopics.stream()
.filter(topic -> !subscribedTopics.containsKey(topic))
.collect(Collectors.toSet());
if (newTopics.isEmpty()) {
log.info("无新增订阅主题,无需添加");
return;
}
// 为每个新主题添加订阅
for (String newTopic : newTopics) {
PatternTopic topic = new PatternTopic(newTopic);
// 向容器中添加监听器(新增订阅)
redisMessageListenerContainer.addMessageListener(redisMessageListenerAdapter, topic);
subscribedTopics.put(newTopic, topic);
log.info("已新增订阅:{}", newTopic);
}
}
/**
* 取消所有现有订阅(兜底方法)
*/
public void cancelAllSubscribes() {
if (subscribedTopics.isEmpty()) {
return;
}
// 遍历所有已订阅主题,取消订阅
for (Map.Entry<String, PatternTopic> entry : subscribedTopics.entrySet()) {
redisMessageListenerContainer.removeMessageListener(redisMessageListenerAdapter, entry.getValue());
log.info("已取消订阅:{}", entry.getKey());
}
subscribedTopics.clear();
}
}

View File

@ -0,0 +1,59 @@
package org.dromara.bigscreen.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dromara.bigscreen.domain.*;
import java.time.LocalDate;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-10 19:32
*/
@DS("slave2")
@Mapper
public interface ProjectBigScreenMapper {
// @Select("select * from bus_corporate_events limit 10")
// List<BusCorporateEvents> getBusCorporateEvents();
//
// @Select("select * from sys_project_introduce where project_id = #{projectId}")
// List<SysProjectIntroduce> selectByProjectId(@Param("projectId") Long projectId);
//
// @Select("select count(*) from bus_construction_user where project_id = #{projectId} && deleted_at is NULL")
// Integer getProjectUserCount(@Param("projectId") Long projectId);
//
// @Select("select count(*) from bus_construction_user where project_id in (60,59) && deleted_at is NULL")
// Integer getUserCount();
//
// @Select("select count(*) from bus_attendance where project_id = #{projectId} && printing_date = #{printingDate} && commuter = '1'")
// Integer getAttendanceCount(@Param("projectId") Long projectId,
// @Param("printingDate") String printingDate);
//
// @Select("SELECT * FROM sys_project_team WHERE project_id = #{projectId} && deleted_at is NULL")
// List<BusProjectTeamByGo> getTeamList(@Param("projectId") Long projectId);
//
// @Select("SELECT * FROM bus_construction_user WHERE project_id = #{projectId} && deleted_at is NULL")
// List<BusConstructionUser> getProjectUserList(@Param("projectId") Long projectId);
//
// @Select({
// "<script>",
// "SELECT count(*) ",
// "FROM bus_attendance ",
// "WHERE openid IN ",
// "<foreach collection='openIds' item='id' open='(' separator=',' close=')'>",
// " #{id}",
// "</foreach>",
// "AND printing_date = #{printingDate} ",
// "AND commuter = '1'",
// "</script>"
// })
// Integer getAttendanceCountByOpenIds(@Param("openIds") List<String> openIds,
// @Param("printingDate") LocalDate printingDate);
//
// @Select("SELECT * FROM bus_tour WHERE project_id = #{projectId} AND deleted_at IS NULL LIMIT 10")
// List<BusTour> selectTourByProjectId(@Param("projectId") Long projectId);
}

View File

@ -0,0 +1,57 @@
package org.dromara.bigscreen.service;
import org.dromara.bigscreen.domain.dto.WeatherQueryReq;
import org.dromara.bigscreen.domain.vo.*;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-09 15:31
*/
public interface EnterpriseBigScreenService {
/**
* 获取关键指标
*
* @return 关键指标
*/
EnterpriseKeyIndexVo getEnterpriseKeyIndex();
/**
* 获取项目进度分析
*
* @return 项目进度分析
*/
ProjectProgressAnalysisVo getProjectProgressAnalysis();
/**
* 获取项目产值对比
*
* @return 项目产值对比
*/
List<OutputValueComparisonVo> getProjectOutputValueComparison();
/**
* 获取风险预警
*
* @return 风险预警
*/
List<RiskEarlyWarningVo> getRiskEarlyWarning();
/**
* 获取当前登录用户3天的天气列表
*
* @param req 查询参数
* @return 天气列表
*/
List<WeatherVo> getWeather3DaysList(WeatherQueryReq req);
/**
* 获取项目进度占比
*
* @return 项目进度占比
*/
List<ProjectProgressCapacityVo> getProjectProgressCapacity();
}

View File

@ -1,8 +1,8 @@
package org.dromara.bigscreen.service; package org.dromara.bigscreen.service;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.project.domain.vo.project.BusProjectGisVo; import org.dromara.project.domain.vo.project.BusProjectGisVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import java.util.List; import java.util.List;
@ -25,7 +25,7 @@ public interface MoneyBigScreenService {
* @param projectId 项目id * @param projectId 项目id
* @return 项目天气 * @return 项目天气
*/ */
List<BusProjectWeatherVo> getProjectWeather(Long projectId); List<WeatherVo> getProjectWeather(Long projectId);
/** /**
* 获取项目安全天数 * 获取项目安全天数

View File

@ -1,13 +1,16 @@
package org.dromara.bigscreen.service; package org.dromara.bigscreen.service;
import org.dromara.bigscreen.domain.dto.TanchuangInfoReq;
import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo; import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo;
import org.dromara.bigscreen.domain.vo.ProjectPeopleVo; import org.dromara.bigscreen.domain.vo.ProjectPeopleVo;
import org.dromara.bigscreen.domain.vo.ProjectSafetyInspectionVo; import org.dromara.bigscreen.domain.vo.ProjectSafetyInspectionVo;
import org.dromara.gps.domain.bo.GpsEquipmentBo;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo; import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author lilemy * @author lilemy
@ -21,7 +24,7 @@ public interface ProjectBigScreenService {
* @param projectId 项目id * @param projectId 项目id
* @return 项目天气 * @return 项目天气
*/ */
List<BusProjectWeatherVo> getProjectWeather(Long projectId); List<WeatherVo> getProjectWeather(Long projectId);
/** /**
* 获取项目安全天数 * 获取项目安全天数
@ -61,7 +64,7 @@ public interface ProjectBigScreenService {
* @param projectId 项目id * @param projectId 项目id
* @return 项目形象进度 * @return 项目形象进度
*/ */
ProjectImageProgressVo getProjectImageProgress(Long projectId); List<ProjectImageProgressVo> getProjectImageProgress(Long projectId);
/** /**
* 获取项目概括 * 获取项目概括
@ -70,4 +73,17 @@ public interface ProjectBigScreenService {
* @return 项目概括 * @return 项目概括
*/ */
String getProjectGeneralize(Long projectId); String getProjectGeneralize(Long projectId);
List<String> getList(Long projectId);
void setList(GpsEquipmentBo bo);
List<Map<String, Object>> getClientList(Long projectId);
/**
* 更新无人机缓存
*/
void setWrjHc();
Map<String, Map<String, Object>> getInfoData(TanchuangInfoReq req);
} }

View File

@ -0,0 +1,429 @@
package org.dromara.bigscreen.service.impl;
import cn.hutool.core.collection.CollUtil;
import jakarta.annotation.Resource;
import org.dromara.bigscreen.domain.dto.WeatherQueryReq;
import org.dromara.bigscreen.domain.vo.*;
import org.dromara.bigscreen.service.EnterpriseBigScreenService;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.utils.BigDecimalUtil;
import org.dromara.manager.weathermanager.WeatherConstant;
import org.dromara.manager.weathermanager.WeatherManager;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.out.domain.BusProcurement;
import org.dromara.out.domain.OutConstructionValueRange;
import org.dromara.out.domain.OutMonthPlanAudit;
import org.dromara.out.domain.OutValueAllocation;
import org.dromara.out.service.*;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.dromara.safety.domain.HseRecognizeRecord;
import org.dromara.safety.domain.HseViolationLevel;
import org.dromara.safety.domain.HseViolationRecord;
import org.dromara.safety.service.IHseRecognizeRecordService;
import org.dromara.safety.service.IHseViolationLevelService;
import org.dromara.safety.service.IHseViolationRecordService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author lilemy
* @date 2025-09-09 15:32
*/
@Service
public class EnterpriseBigScreenServiceImpl implements EnterpriseBigScreenService {
@Resource
private WeatherManager weatherManager;
@Resource
private IBusProjectService projectService;
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Resource
private IOutValueAllocationService outValueAllocationService;
@Resource
private IOutMonthPlanAuditService outMonthPlanAuditService;
@Resource
private IOutConstructionValueService outConstructionValueService;
@Resource
private IOutConstructionValueRangeService outConstructionValueRangeService;
@Resource
private IHseViolationRecordService hseViolationRecordService;
@Resource
private IHseViolationLevelService hseViolationLevelService;
@Resource
private IBusProcurementService busProcurementService;
@Resource
private IHseRecognizeRecordService hseRecognizeRecordService;
/**
* 获取关键指标
*
* @return 关键指标
*/
@Override
public EnterpriseKeyIndexVo getEnterpriseKeyIndex() {
EnterpriseKeyIndexVo vo = new EnterpriseKeyIndexVo();
// 在建项目
List<BusProject> projectList = projectService.lambdaQuery()
.eq(BusProject::getStatus, 0)
.eq(BusProject::getPId, 0)
.list();
// 光伏项目
int photovoltaicCount = projectList.stream()
.filter(s -> s.getProjectType().equals("1"))
.toList()
.size();
BigDecimal photovoltaicTotalCapacity = projectList.stream()
.filter(s -> s.getProjectType().equals("1"))
.map(BusProject::getPlan)
.filter(s -> s != null && !s.isBlank()) // 过滤掉空值
.map(BigDecimal::new) // 转成 BigDecimal
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 风电项目
int windElectricityCount = projectList.stream()
.filter(s -> s.getProjectType().equals("2"))
.toList()
.size();
BigDecimal windElectricityTotalCapacity = projectList.stream()
.filter(s -> s.getProjectType().equals("2"))
.map(BusProject::getPlan)
.filter(s -> s != null && !s.isBlank()) // 过滤掉空值
.map(BigDecimal::new) // 转成 BigDecimal
.reduce(BigDecimal.ZERO, BigDecimal::add);
vo.setPhotovoltaicCount(photovoltaicCount);
vo.setWindElectricityCount(windElectricityCount);
vo.setPhotovoltaicTotalCapacity(photovoltaicTotalCapacity);
vo.setWindElectricityTotalCapacity(windElectricityTotalCapacity);
vo.setPerformanceCount(52L);
vo.setTypicalPerformance(22L);
return vo;
}
/**
* 获取项目进度分析
*
* @return 项目进度分析
*/
@Override
public ProjectProgressAnalysisVo getProjectProgressAnalysis() {
ProjectProgressAnalysisVo vo = new ProjectProgressAnalysisVo();
// 1. 查询顶级项目
List<BusProject> projectList = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName, BusProject::getActual, BusProject::getPlan)
.eq(BusProject::getStatus, 0)
.eq(BusProject::getPId, 0)
.list();
if (CollUtil.isEmpty(projectList)) {
return vo;
}
// 2. 拿到顶级项目 id
List<Long> projectIds = projectList.stream()
.map(BusProject::getId)
.distinct()
.toList();
// 3. 查询子项目pId 在顶级项目id里
List<BusProject> subProject = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getPId)
.in(BusProject::getPId, projectIds)
.list();
// 4. 按父项目id分组子项目
Map<Long, List<BusProject>> subProjectMap = subProject.stream()
.collect(Collectors.groupingBy(BusProject::getPId));
// 5. 查询所有子项目的进度分类
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.select(PgsProgressCategory::getId,
PgsProgressCategory::getProjectId,
PgsProgressCategory::getCompleted,
PgsProgressCategory::getTotal)
.in(CollUtil.isNotEmpty(subProject),
PgsProgressCategory::getProjectId,
subProject.stream().map(BusProject::getId).toList())
.list();
// 6. 按子项目id分组进度分类
Map<Long, List<PgsProgressCategory>> progressCategoryMap = progressCategoryList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getProjectId));
// 并网容量 =(完工产值/计划总产值)* 计划容量
List<OutputValueComparisonVo> list = getProjectOutputValueComparison();
BigDecimal actualValue = list.stream()
.map(OutputValueComparisonVo::getActualValue)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal planValue = list.stream()
.map(OutputValueComparisonVo::getPlanValue)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal plannedCapacity = projectList.stream().map(BusProject::getPlan)
.filter(s -> s != null && !s.isBlank()) // 过滤掉空值
.map(BigDecimal::new) // 转成 BigDecimal
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal gridConnectedCapacity = BigDecimal.ZERO;
if (planValue.compareTo(BigDecimal.ZERO) != 0) {
gridConnectedCapacity = plannedCapacity.multiply(actualValue.divide(planValue, 2, RoundingMode.HALF_UP));
}
vo.setGridConnectedCapacity(gridConnectedCapacity);
List<ProjectProgressDetailVo> detailVoList = projectList.stream().map(project -> {
ProjectProgressDetailVo detailVo = new ProjectProgressDetailVo();
detailVo.setProjectName(project.getProjectName());
detailVo.setProjectCapacity(new BigDecimal(project.getActual()));
List<BusProject> children = subProjectMap.getOrDefault(project.getId(), List.of());
List<PgsProgressCategory> categoryList = new ArrayList<>();
for (BusProject child : children) {
categoryList.addAll(progressCategoryMap.getOrDefault(child.getId(), List.of()));
}
if (CollUtil.isNotEmpty(categoryList)) {
BigDecimal completed = categoryList.stream().map(PgsProgressCategory::getCompleted)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total = categoryList.stream().map(PgsProgressCategory::getTotal)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
detailVo.setCompletionRate(BigDecimalUtil.toPercentage(completed, total));
}
return detailVo;
}).toList();
vo.setGridConnectedCapacity(gridConnectedCapacity);
vo.setPlannedCapacity(plannedCapacity);
// todo 获取延迟项目数
vo.setDelayedProjectCount(0);
vo.setProjectProgressDetailList(detailVoList);
return vo;
}
/**
* 获取项目产值对比
*
* @return 项目产值对比
*/
@Override
public List<OutputValueComparisonVo> getProjectOutputValueComparison() {
// 查询顶级项目
List<BusProject> projectList = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName, BusProject::getActual, BusProject::getPlan)
.eq(BusProject::getStatus, 0)
.eq(BusProject::getPId, 0)
.list();
// 计划产值
List<OutValueAllocation> planList = outValueAllocationService.lambdaQuery()
.select(OutValueAllocation::getProjectId, OutValueAllocation::getOwnerTotalValue)
.list();
Map<Long, BigDecimal> planMap = planList.stream()
.collect(Collectors.toMap(OutValueAllocation::getProjectId, OutValueAllocation::getOwnerTotalValue));
// 实际产值
// 施工产值
List<OutConstructionValueRange> constructionValueRangeList = outConstructionValueRangeService.lambdaQuery()
.select(OutConstructionValueRange::getProjectId, OutConstructionValueRange::getOwnerValue)
.eq(OutConstructionValueRange::getAuditStatus, BusinessStatusEnum.FINISH.getStatus())
.list();
// 采购产值
List<BusProcurement> purchaseValueList = busProcurementService.lambdaQuery()
.select(BusProcurement::getProjectId, BusProcurement::getAcceptedQuantity, BusProcurement::getUnitPrice)
.list();
// 设计产值
List<OutMonthPlanAudit> designValueList = outMonthPlanAuditService.lambdaQuery()
.select(OutMonthPlanAudit::getProjectId, OutMonthPlanAudit::getDesignValue)
.eq(OutMonthPlanAudit::getType, "1")
.list();
// 封装数据
return projectList.stream().map(project -> {
OutputValueComparisonVo vo = new OutputValueComparisonVo();
vo.setProjectId(project.getId());
vo.setProjectName(project.getProjectName());
vo.setPlanValue(planMap.getOrDefault(project.getId(), BigDecimal.ZERO));
BigDecimal actualValue = BigDecimal.ZERO;
// 设计产值
List<OutMonthPlanAudit> designValue = designValueList.stream()
.filter(design -> design.getProjectId().equals(project.getId()))
.toList();
if (CollUtil.isNotEmpty(designValue)) {
BigDecimal dValue = designValue.stream()
.filter(Objects::nonNull)
.map(OutMonthPlanAudit::getDesignValue)
.reduce(BigDecimal.ZERO, BigDecimal::add);
actualValue = actualValue.add(dValue);
}
// 施工产值
List<OutConstructionValueRange> constructionValue = constructionValueRangeList.stream()
.filter(construction -> construction.getProjectId().equals(project.getId()))
.toList();
if (CollUtil.isNotEmpty(constructionValue)) {
BigDecimal cValue = constructionValue.stream()
.filter(Objects::nonNull)
.map(OutConstructionValueRange::getOwnerValue)
.reduce(BigDecimal.ZERO, BigDecimal::add);
actualValue = actualValue.add(cValue);
}
// 采购产值
List<BusProcurement> purchaseValue = purchaseValueList.stream()
.filter(purchase -> purchase.getProjectId().equals(project.getId()))
.toList();
if (CollUtil.isNotEmpty(purchaseValue)) {
BigDecimal pValue = purchaseValue.stream()
.filter(Objects::nonNull)
.filter(purchase -> purchase.getAcceptedQuantity() != null && purchase.getUnitPrice() != null)
.map(purchase -> purchase.getAcceptedQuantity().multiply(purchase.getUnitPrice()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
actualValue = actualValue.add(pValue);
}
vo.setActualValue(actualValue);
return vo;
}).filter(vo -> vo.getActualValue().compareTo(BigDecimal.ZERO) > 0)
.toList();
}
/**
* 获取风险预警
*
* @return 风险预警
*/
@Override
public List<RiskEarlyWarningVo> getRiskEarlyWarning() {
List<HseViolationRecord> recordList = hseViolationRecordService.lambdaQuery()
.last("limit 10")
.list();
recordList = recordList.stream()
.filter(record -> record.getReviewType() == null || record.getReviewType().equals("2"))
.toList();
if (CollUtil.isEmpty(recordList)) {
return Collections.emptyList();
}
// 项目映射
Set<Long> projectIds = recordList.stream()
.map(HseViolationRecord::getProjectId)
.collect(Collectors.toSet());
List<BusProject> projectList = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName)
.in(BusProject::getId, projectIds)
.list();
Map<Long, String> projectMap = projectList.stream()
.collect(Collectors.toMap(BusProject::getId, BusProject::getProjectName));
// 风险映射
Set<Long> levelIds = recordList.stream()
.map(HseViolationRecord::getLevelId)
.collect(Collectors.toSet());
List<HseViolationLevel> levelList = hseViolationLevelService.lambdaQuery()
.select(HseViolationLevel::getId, HseViolationLevel::getRiskType, HseViolationLevel::getViolationLevel)
.in(HseViolationLevel::getId, levelIds)
.list();
Map<Long, HseViolationLevel> levelMap = levelList.stream()
.collect(Collectors.toMap(HseViolationLevel::getId, level -> level));
// 识别记录映射
Set<Long> recognizeIds = recordList.stream()
.map(HseViolationRecord::getRecognizeId)
.collect(Collectors.toSet());
List<HseRecognizeRecord> recognizeRecordList = hseRecognizeRecordService.lambdaQuery()
.in(HseRecognizeRecord::getId, recognizeIds)
.list();
Map<Long, HseRecognizeRecord> recognizeRecordMap = recognizeRecordList.stream()
.collect(Collectors.toMap(HseRecognizeRecord::getId, recognize -> recognize));
return recordList.stream().map(record -> {
RiskEarlyWarningVo vo = new RiskEarlyWarningVo();
Date violationTime = record.getViolationTime() != null ? record.getViolationTime() : record.getCreateTime();
vo.setDate(DateUtils.toLocalDate(violationTime));
vo.setSource(projectMap.getOrDefault(record.getProjectId(), "未知项目"));
vo.setRiskType(record.getViolationType());
if (levelMap.containsKey(record.getLevelId())) {
HseViolationLevel level = levelMap.get(record.getLevelId());
vo.setAlarmLevel(level.getRiskType());
vo.setDangerLevel(level.getViolationLevel());
}
if (recognizeRecordMap.containsKey(record.getRecognizeId())) {
HseRecognizeRecord hseRecognizeRecord = recognizeRecordMap.get(record.getRecognizeId());
vo.setAlarmContent(hseRecognizeRecord.getDescription());
}
return vo;
}).toList();
}
/**
* 获取当前登录用户3天的天气列表
*
* @return 天气列表
*/
@Override
public List<WeatherVo> getWeather3DaysList(WeatherQueryReq req) {
return weatherManager.getWeatherListVo(req.getLng(), req.getLat(), WeatherConstant.THREE_DAYS_WEATHER_PATH);
}
/**
* 获取项目进度占比
*
* @return 项目进度占比
*/
@Override
public List<ProjectProgressCapacityVo> getProjectProgressCapacity() {
// 1. 查询顶级项目
List<BusProject> projectList = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName, BusProject::getActual, BusProject::getPlan)
.eq(BusProject::getStatus, 0)
.eq(BusProject::getPId, 0)
.list();
if (CollUtil.isEmpty(projectList)) {
return List.of();
}
// 2. 拿到顶级项目 id
List<Long> projectIds = projectList.stream()
.map(BusProject::getId)
.distinct()
.toList();
// 3. 查询子项目pId 在顶级项目id里
List<BusProject> subProject = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getPId)
.in(BusProject::getPId, projectIds)
.list();
// 4. 按父项目id分组子项目
Map<Long, List<BusProject>> subProjectMap = subProject.stream()
.collect(Collectors.groupingBy(BusProject::getPId));
// 5. 查询所有子项目的进度分类
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.select(PgsProgressCategory::getId,
PgsProgressCategory::getProjectId,
PgsProgressCategory::getCompleted,
PgsProgressCategory::getTotal)
.in(CollUtil.isNotEmpty(subProject),
PgsProgressCategory::getProjectId,
subProject.stream().map(BusProject::getId).toList())
.list();
// 6. 按子项目id分组进度分类
Map<Long, List<PgsProgressCategory>> progressCategoryMap = progressCategoryList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getProjectId));
return projectList.stream().map(project -> {
ProjectProgressCapacityVo detailVo = new ProjectProgressCapacityVo();
detailVo.setProjectId(project.getId());
detailVo.setProjectName(project.getProjectName());
detailVo.setPlannedCapacity(new BigDecimal(project.getPlan()));
List<BusProject> children = subProjectMap.getOrDefault(project.getId(), List.of());
List<PgsProgressCategory> categoryList = new ArrayList<>();
for (BusProject child : children) {
categoryList.addAll(progressCategoryMap.getOrDefault(child.getId(), List.of()));
}
if (CollUtil.isNotEmpty(categoryList)) {
BigDecimal completed = categoryList.stream().map(PgsProgressCategory::getCompleted)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal total = categoryList.stream().map(PgsProgressCategory::getTotal)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
detailVo.setProgressPercentage(BigDecimalUtil.toPercentage(completed, total));
}
return detailVo;
}).toList();
}
}

View File

@ -4,10 +4,10 @@ import jakarta.annotation.Resource;
import org.dromara.bigscreen.service.MoneyBigScreenService; import org.dromara.bigscreen.service.MoneyBigScreenService;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.project.domain.BusProject; import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.vo.project.BusProjectGisVo; import org.dromara.project.domain.vo.project.BusProjectGisVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -40,7 +40,7 @@ public class MoneyBigScreenServiceImpl implements MoneyBigScreenService {
* @return 项目天气 * @return 项目天气
*/ */
@Override @Override
public List<BusProjectWeatherVo> getProjectWeather(Long projectId) { public List<WeatherVo> getProjectWeather(Long projectId) {
checkProject(projectId); checkProject(projectId);
return projectService.getWeather(projectId); return projectService.getWeather(projectId);
} }

View File

@ -1,9 +1,11 @@
package org.dromara.bigscreen.service.impl; package org.dromara.bigscreen.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil; import cn.hutool.json.JSONArray;
import cn.hutool.core.util.RandomUtil; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.dromara.bigscreen.domain.dto.TanchuangInfoReq;
import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo; import org.dromara.bigscreen.domain.vo.ProjectImageProgressVo;
import org.dromara.bigscreen.domain.vo.ProjectPeopleVo; import org.dromara.bigscreen.domain.vo.ProjectPeopleVo;
import org.dromara.bigscreen.domain.vo.ProjectSafetyInspectionVo; import org.dromara.bigscreen.domain.vo.ProjectSafetyInspectionVo;
@ -11,27 +13,41 @@ import org.dromara.bigscreen.domain.vo.ProjectTeamAttendanceVo;
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.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.utils.BigDecimalUtil; import org.dromara.common.utils.BigDecimalUtil;
import org.dromara.contractor.domain.SubConstructionUser; import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.service.ISubConstructionUserService; import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.drone.service.IDroProjectDroneService;
import org.dromara.gps.domain.bo.GpsEquipmentBo;
import org.dromara.gps.domain.vo.DeviceVo;
import org.dromara.gps.domain.vo.GpsEquipmentSonVo;
import org.dromara.gps.domain.vo.LocationVo;
import org.dromara.gps.service.IDeviceService;
import org.dromara.gps.service.IGpsEquipmentService;
import org.dromara.manager.weathermanager.vo.WeatherVo;
import org.dromara.other.domain.OthYs7Device;
import org.dromara.other.service.IOthYs7DeviceService;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.domain.BusProject; import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusProjectTeam; import org.dromara.project.domain.BusProjectTeam;
import org.dromara.project.domain.BusProjectTeamMember; import org.dromara.project.domain.BusProjectTeamMember;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo; import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo; import org.dromara.project.domain.vo.projectnews.BusProjectNewsVo;
import org.dromara.project.service.*; import org.dromara.project.service.*;
import org.dromara.safety.domain.HseRecognizeRecord; import org.dromara.safety.domain.HseRecognizeRecord;
import org.dromara.safety.service.IHseRecognizeRecordService; import org.dromara.safety.service.IHseRecognizeRecordService;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.time.LocalDateTime;
import java.util.HashMap; import java.time.LocalTime;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -62,6 +78,23 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
@Resource @Resource
private IBusProjectTeamMemberService projectTeamMemberService; private IBusProjectTeamMemberService projectTeamMemberService;
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Resource
private IDroProjectDroneService droProjectDroneService;
@Resource
private IGpsEquipmentService gpsEquipmentService;
@Resource
private IOthYs7DeviceService othYs7DeviceService;
@Resource
@Lazy
private StringRedisTemplate stringRedisTemplate;
@Resource
private IDeviceService deviceService;
/** /**
* 获取项目天气 * 获取项目天气
* *
@ -69,7 +102,7 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
* @return 项目天气 * @return 项目天气
*/ */
@Override @Override
public List<BusProjectWeatherVo> getProjectWeather(Long projectId) { public List<WeatherVo> getProjectWeather(Long projectId) {
checkProject(projectId); checkProject(projectId);
return projectService.getWeather(projectId); return projectService.getWeather(projectId);
} }
@ -135,8 +168,12 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
// 获取大屏数据 // 获取大屏数据
ProjectPeopleVo vo = new ProjectPeopleVo(); ProjectPeopleVo vo = new ProjectPeopleVo();
// 获取施工人员总数 // 获取施工人员总数
Long count = constructionUserService.lambdaQuery() List<SubConstructionUser> list = constructionUserService.lambdaQuery()
.eq(SubConstructionUser::getProjectId, projectId).count(); .eq(SubConstructionUser::getProjectId, projectId)
.eq(SubConstructionUser::getUserRole, "0")
.isNotNull(SubConstructionUser::getTeamId).list();
List<Long> sysUserIdList = list.stream().map(SubConstructionUser::getSysUserId).toList();
int count = list.size();
BigDecimal countDec = BigDecimal.valueOf(count); BigDecimal countDec = BigDecimal.valueOf(count);
vo.setPeopleCount(countDec); vo.setPeopleCount(countDec);
// 获取考勤数据 // 获取考勤数据
@ -150,13 +187,17 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
List<BusProjectTeamMember> memberList = projectTeamMemberService.lambdaQuery() List<BusProjectTeamMember> memberList = projectTeamMemberService.lambdaQuery()
.select(BusProjectTeamMember::getId, BusProjectTeamMember::getTeamId) .select(BusProjectTeamMember::getId, BusProjectTeamMember::getTeamId)
.eq(BusProjectTeamMember::getProjectId, projectId) .eq(BusProjectTeamMember::getProjectId, projectId)
.in(BusProjectTeamMember::getMemberId, sysUserIdList)
.list(); .list();
Map<Long, List<BusProjectTeamMember>> memberMap = memberList.stream() Map<Long, List<BusProjectTeamMember>> memberMap = memberList.stream()
.collect(Collectors.groupingBy(BusProjectTeamMember::getTeamId)); .collect(Collectors.groupingBy(BusProjectTeamMember::getTeamId));
// 统计班组考勤数据 // 统计班组考勤数据
Map<Long, List<SubConstructionUser>> userTeamMap = new HashMap<>(); Map<Long, List<SubConstructionUser>> userTeamMap = new HashMap<>();
if (CollUtil.isNotEmpty(attendancePeopleList)) { if (CollUtil.isNotEmpty(attendancePeopleList)) {
List<SubConstructionUser> users = constructionUserService.listByIds(attendancePeopleList); List<SubConstructionUser> users = constructionUserService.lambdaQuery()
.in(SubConstructionUser::getSysUserId, attendancePeopleList)
.isNotNull(SubConstructionUser::getTeamId)
.list();
userTeamMap = users.stream() userTeamMap = users.stream()
.collect(Collectors.groupingBy(SubConstructionUser::getTeamId)); .collect(Collectors.groupingBy(SubConstructionUser::getTeamId));
} }
@ -167,7 +208,7 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
String punchTime = ""; String punchTime = "";
if (punchRange != null) { if (punchRange != null) {
String start = punchRange.split(",")[0]; String start = punchRange.split(",")[0];
punchTime = LocalDate.now() + " " + start; punchTime = LocalDate.now() + " ";
} }
List<ProjectTeamAttendanceVo> listVo = new ArrayList<>(); List<ProjectTeamAttendanceVo> listVo = new ArrayList<>();
for (BusProjectTeam projectTeam : teamList) { for (BusProjectTeam projectTeam : teamList) {
@ -201,53 +242,184 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
* @return 项目形象进度 * @return 项目形象进度
*/ */
@Override @Override
public ProjectImageProgressVo getProjectImageProgress(Long projectId) { public List<ProjectImageProgressVo> getProjectImageProgress(Long projectId) {
checkProject(projectId); checkProject(projectId);
// 生成 0 ~ 100 的随机 double // 获取当前项目的所有子项目
double random = RandomUtil.randomDouble(0, 100); List<Long> projectIds = new ArrayList<>(projectService.lambdaQuery()
.select(BusProject::getId)
// 保留两位小数(四舍五入) .eq(BusProject::getPId, projectId)
double result = NumberUtil.round(random, 2).doubleValue(); .list()
ProjectImageProgressVo vo = new ProjectImageProgressVo(); .stream()
vo.setAreaPercentage(BigDecimal.valueOf(result)); .map(BusProject::getId)
// 生成 0 ~ 100 的随机 double .toList());
double random1 = RandomUtil.randomDouble(0, 100); projectIds.add(projectId);
// 查询该子项目下的顶级进度类别父ID为0
// 保留两位小数(四舍五入) List<PgsProgressCategory> list = progressCategoryService.lambdaQuery()
double result1 = NumberUtil.round(random1, 2).doubleValue(); .in(PgsProgressCategory::getProjectId, projectIds)
vo.setRoadPercentage(BigDecimal.valueOf(result1)); .eq(PgsProgressCategory::getParentId, PgsProgressCategoryConstant.TOP_PARENT_ID)
// 生成 0 ~ 100 的随机 double .list();
double random2 = RandomUtil.randomDouble(0, 100); // 如果没有查询到顶级进度类别,直接返回空集合
if (CollUtil.isEmpty(list)) {
// 保留两位小数(四舍五入) return List.of();
double result2 = NumberUtil.round(random2, 2).doubleValue(); }
vo.setCollectorLinePercentage(BigDecimal.valueOf(result2)); List<ProjectImageProgressVo> topList = new ArrayList<>();
// 生成 0 ~ 100 的随机 double // 获取这些顶级类别的所有子节点
double random3 = RandomUtil.randomDouble(0, 100); List<Long> ids = list.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> childrenNodes = progressCategoryService.getChildrenNodeByTopIds(ids);
// 保留两位小数(四舍五入) if (CollUtil.isNotEmpty(list)) {
double result3 = NumberUtil.round(random3, 2).doubleValue(); // 按名称分组(同名的放在一起)
vo.setExportLinePercentage(BigDecimal.valueOf(result3)); Map<String, List<PgsProgressCategory>> subMap = list.stream()
// 生成 0 ~ 100 的随机 double .collect(Collectors.groupingBy(PgsProgressCategory::getName));
double random4 = RandomUtil.randomDouble(0, 100); for (Map.Entry<String, List<PgsProgressCategory>> entry : subMap.entrySet()) {
ProjectImageProgressVo topVo = new ProjectImageProgressVo();
// 保留两位小数(四舍五入) topVo.setProgressName(entry.getKey());
double result4 = NumberUtil.round(random4, 2).doubleValue(); List<PgsProgressCategory> value = entry.getValue();
vo.setSubstationPercentage(BigDecimal.valueOf(result4)); // 获取这些类别下的所有叶子节点
// 生成 0 ~ 100 的随机 double List<Long> topIds = value.stream().map(PgsProgressCategory::getId).distinct().toList();
double random5 = RandomUtil.randomDouble(0, 100); List<PgsProgressCategory> leafNodesByTopIds = childrenNodes.stream()
.filter(node -> {
// 保留两位小数(四舍五入) Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(","))
double result5 = NumberUtil.round(random5, 2).doubleValue(); .map(Long::parseLong)
vo.setBoxTransformerPercentage(BigDecimal.valueOf(result5)); .collect(Collectors.toSet());
return topIds.stream().anyMatch(ancestorSet::contains);
// 生成 0 ~ 100 的随机 double }).toList();
double random6 = RandomUtil.randomDouble(0, 100); // 如果有叶子节点,统计进度和状态;否则初始化为未完成
if (CollUtil.isNotEmpty(leafNodesByTopIds)) {
// 保留两位小数(四舍五入) topVo.setProgressTotal(progressCategoryService.getCompletedPercentage(leafNodesByTopIds));
double result6 = NumberUtil.round(random6, 2).doubleValue(); } else {
vo.setTotalPercentage(BigDecimal.valueOf(result6)); topVo.setProgressTotal(BigDecimal.ZERO);
return vo; }
// 加入结果集
topList.add(topVo);
}
}
return topList;
/* ProjectImageProgressVo vo = new ProjectImageProgressVo();
// 获取所有子项目列表
List<BusProject> subProjectList = projectService.lambdaQuery()
.eq(BusProject::getPId, projectId)
.list();
if (CollUtil.isEmpty(subProjectList)) {
return vo;
}
// 子项目id列表
List<Long> projectIds = new ArrayList<>(subProjectList.stream().map(BusProject::getId).toList());
// 计算集电线路
vo.setCollectorLinePercentage(BigDecimal.valueOf(0.00));
// 计算送出线路
vo.setExportLinePercentage(BigDecimal.valueOf(0.00));
// 计算升压站
vo.setSubstationPercentage(BigDecimal.valueOf(0.00));
// 计算光伏场区
vo.setAreaPercentage(BigDecimal.valueOf(0.00));
// 计算道路
vo.setRoadPercentage(BigDecimal.valueOf(0.00));
// 计算箱变
vo.setBoxTransformerPercentage(BigDecimal.ZERO);
// 获取集电线路、送出线路、升压站数据
projectIds.add(projectId);
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getProjectId, projectIds)
.in(PgsProgressCategory::getName, "集电线路", "送出线路", "升压站", "光伏场区")
.eq(PgsProgressCategory::getParentId, 0L)
.list();
if (CollUtil.isNotEmpty(progressCategoryList)) {
List<Long> categoryIds = progressCategoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = progressCategoryService.getLeafNodesByTopIds(categoryIds);
Map<String, List<PgsProgressCategory>> categoryMap = progressCategoryList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
// 计算集电线路
if (categoryMap.containsKey("集电线路")) {
List<PgsProgressCategory> categoryList = categoryMap.get("集电线路");
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setCollectorLinePercentage(percentage);
}
}
// 计算送出线路
if (categoryMap.containsKey("送出线路")) {
List<PgsProgressCategory> categoryList = categoryMap.get("送出线路");
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setExportLinePercentage(percentage);
}
}
// 计算升压站
if (categoryMap.containsKey("升压站")) {
List<PgsProgressCategory> categoryList = categoryMap.get("升压站");
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setSubstationPercentage(percentage);
}
}
// 计算光伏场区
if (categoryMap.containsKey("光伏场区")) {
List<PgsProgressCategory> categoryList = categoryMap.get("光伏场区");
List<Long> ids = categoryList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> list = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ids.stream().anyMatch(ancestorSet::contains);
}).toList();
BigDecimal percentage = progressCategoryService.getCompletedPercentage(list);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setAreaPercentage(percentage);
}
}
}
// 计算道路
List<PgsProgressCategory> roadCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getProjectId, projectIds)
.like(PgsProgressCategory::getName, "道路")
.ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue())
.list();
if (CollUtil.isNotEmpty(roadCategoryList)) {
BigDecimal percentage = progressCategoryService.getCompletedPercentage(roadCategoryList);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setRoadPercentage(percentage);
}
}
// 计算箱变
List<PgsProgressCategory> boxTransformerCategoryList = progressCategoryService.lambdaQuery()
.in(PgsProgressCategory::getProjectId, projectIds)
.like(PgsProgressCategory::getName, "箱变")
.ne(PgsProgressCategory::getUnitType, PgsProgressUnitTypeEnum.NULL.getValue())
.list();
if (CollUtil.isNotEmpty(boxTransformerCategoryList)) {
BigDecimal percentage = progressCategoryService.getCompletedPercentage(boxTransformerCategoryList);
if (percentage.compareTo(BigDecimal.ZERO) > 0) {
vo.setBoxTransformerPercentage(percentage);
}
}
// 计算总进度
vo.setTotalPercentage(
vo.getCollectorLinePercentage()
.add(vo.getExportLinePercentage())
.add(vo.getSubstationPercentage())
.add(vo.getAreaPercentage())
.add(vo.getRoadPercentage())
.add(vo.getBoxTransformerPercentage())
.divide(BigDecimal.valueOf(6), 2, RoundingMode.HALF_UP) // 保留两位小数
);
return vo;*/
} }
/** /**
@ -276,4 +448,190 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND); throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
} }
} }
@Override
public List<String> getList(Long projectId) {
if (projectId == null) {
throw new ServiceException("项目id不能为空");
}
Object object = RedisUtils.getCacheObject("xmjdp:" + projectId);
if (object == null) {
return null;
}
JSONArray objects = JSONUtil.parseArray(object);
return objects.toList(String.class);
}
@Override
public void setList(GpsEquipmentBo bo) {
if (bo.getProjectId() == null) {
throw new ServiceException("项目id不能为空");
}
RedisUtils.setCacheObject("xmjdp:" + bo.getProjectId(), bo.getIdList());
}
@Override
public List<Map<String, Object>> getClientList(Long projectId) {
// 获取当天的开始时间00:00:00
LocalDateTime startOfDay = LocalDateTime.now().with(LocalTime.MIN);
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
List<GpsEquipmentSonVo> voList = gpsEquipmentService.getClientList(projectId, startOfDay, now);
List<GpsEquipmentSonVo> appList = gpsEquipmentService.getUserListByProjectId(projectId, startOfDay, now);
List<LocationVo> anqmList = deviceService.getUserListByProjectId(projectId, startOfDay, now);
List<OthYs7Device> othYs7DeviceList = othYs7DeviceService.lambdaQuery()
.eq(OthYs7Device::getProjectId, projectId)
// .between(OthYs7Device::getUpdateTime, startOfDay, now)
.list();
List<String> wrjKeys = droProjectDroneService.getTopicsByProjectId(projectId);
List<Map<String, Object>> maps = new ArrayList<>();
Map<String, Object> gpsMap = new HashMap<>();
Map<String, Object> anqmMap = new HashMap<>();
Map<String, Object> appMap = new HashMap<>();
Map<String, Object> sbMap = new HashMap<>();
Map<String, Object> wrjMap = new HashMap<>();
Map<String, Object> sxtMap = new HashMap<>();
List<Map<String, Object>> gpsChildrenMap = new ArrayList<>();
List<Map<String, Object>> sbChildrenMap = new ArrayList<>();
List<Map<String, Object>> appChildrenMap = new ArrayList<>();
List<Map<String, Object>> anqmChildrenMap = new ArrayList<>();
List<Map<String, Object>> wrjChildrenMap = new ArrayList<>();
List<Map<String, Object>> sxtChildrenMap = new ArrayList<>();
if (voList != null && !voList.isEmpty()) {
for (GpsEquipmentSonVo item : voList) {
Map<String, Object> gps = new HashMap<>();
gps.put("id", item.getClientId());
gps.put("userId", item.getUserId());
gps.put("label", item.getClientId());
gps.put("name", item.getUserId() != null ? item.getUserName() : item.getClientId());
gps.put("type", "gps");
gps.put("lat", item.getLocLatitude());
gps.put("lng", item.getLocLongitude());
gps.put("alt", item.getLocAltitude());
sbChildrenMap.add(gps);
}
}
if (appList != null && !appList.isEmpty()) {
for (GpsEquipmentSonVo item : appList) {
Map<String, Object> app = new HashMap<>();
app.put("id", item.getUserId());
app.put("userId", item.getUserId());
app.put("label", item.getUserId());
app.put("name", item.getUserName());
app.put("type", "app");
app.put("lat", item.getLocLatitude());
app.put("lng", item.getLocLongitude());
app.put("alt", item.getLocAltitude());
appChildrenMap.add(app);
}
}
if (anqmList != null && !anqmList.isEmpty()) {
for (LocationVo item : anqmList) {
Map<String, Object> anqm = new HashMap<>();
anqm.put("id", item.getDevNum());
anqm.put("userId", item.getUserId());
anqm.put("label", item.getDevNum());
anqm.put("name", item.getDevNum());
anqm.put("type", "positioningDevice");
anqm.put("lat", item.getLatitude());
anqm.put("lng", item.getLongitude());
anqm.put("alt", item.getElevation());
anqmChildrenMap.add(anqm);
}
}
if (othYs7DeviceList != null && !othYs7DeviceList.isEmpty()) {
for (OthYs7Device item : othYs7DeviceList) {
Map<String, Object> sxt = new HashMap<>();
sxt.put("id", item.getDeviceSerial());
sxt.put("label", item.getDeviceSerial());
sxt.put("name", item.getDeviceName());
sxt.put("type", "shexiangtou");
sxt.put("lat", item.getLatitude());
sxt.put("lng", item.getLongitude());
sxt.put("alt", item.getAltitude());
sxt.put("status", item.getStatus());
sxt.put("detail", item.getDetail());
sxtChildrenMap.add(sxt);
}
}
if (wrjKeys != null && !wrjKeys.isEmpty()) {
for (String key : wrjKeys) {
Object object = stringRedisTemplate.opsForValue().get("wrj:osd4:" + key);
Object object6 = stringRedisTemplate.opsForValue().get("wrj:osd2:" + key);
String status = "";
if (object6 != null) {
JSONObject object1 = JSONUtil.parseObj(object6);
status = object1.getJSONObject("data").get("flighttask_step_code").toString();
}
if (object != null) {
JSONObject object1 = JSONUtil.parseObj(object);
Map<String, Object> wrj = new HashMap<>();
wrj.put("id", key);
wrj.put("label", key);
wrj.put("name", key);
wrj.put("type", "wurenji");
wrj.put("status", status);
wrj.put("lat", object1.getJSONObject("data").get("latitude"));
wrj.put("lng", object1.getJSONObject("data").get("longitude"));
wrj.put("alt", object1.getJSONObject("data").get("height"));
wrjChildrenMap.add(wrj);
}else {
Object object2 = stringRedisTemplate.opsForValue().get("wrj:osd3:" + key);
if (object2 != null) {
JSONObject object3 = JSONUtil.parseObj(object2);
Map<String, Object> wrj = new HashMap<>();
wrj.put("id", key);
wrj.put("label", key);
wrj.put("name", key);
wrj.put("type", "wurenji");
wrj.put("status", status);
wrj.put("lat", object3.getJSONObject("data").get("latitude"));
wrj.put("lng", object3.getJSONObject("data").get("longitude"));
wrj.put("alt", object3.getJSONObject("data").get("height"));
wrjChildrenMap.add(wrj);
}
}
}
}
gpsChildrenMap.add(sbMap);
gpsChildrenMap.add(appMap);
gpsChildrenMap.add(anqmMap);
gpsMap.put("id", 1);
gpsMap.put("label", "人员定位");
gpsMap.put("children", gpsChildrenMap);
sbMap.put("id", 4);
sbMap.put("label", "设备定位");
sbMap.put("children", sbChildrenMap);
appMap.put("id", 5);
appMap.put("label", "app定位");
appMap.put("children", appChildrenMap);
anqmMap.put("id", 6);
anqmMap.put("label", "安全帽定位");
anqmMap.put("children", anqmChildrenMap);
sxtMap.put("id", 2);
sxtMap.put("label", "摄像头");
sxtMap.put("children", sxtChildrenMap);
wrjMap.put("id", 3);
wrjMap.put("label", "无人机");
wrjMap.put("children", wrjChildrenMap);
maps.add(gpsMap);
maps.add(wrjMap);
maps.add(sxtMap);
return maps;
}
@Override
public void setWrjHc() {
RedisUtils.setCacheObject("xmjdap:ws",System.currentTimeMillis() );
}
@Override
public Map<String, Map<String, Object>> getInfoData(TanchuangInfoReq req) {
return projectService.getInfoData(req);
}
} }

View File

@ -1,13 +1,19 @@
package org.dromara.cailiaoshebei.controller; package org.dromara.cailiaoshebei.controller;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
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 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.cailiaoshebei.domain.bo.RemainingReq;
import org.dromara.cailiaoshebei.domain.dto.BusMrpDto; import org.dromara.cailiaoshebei.domain.dto.BusMrpDto;
import org.dromara.cailiaoshebei.domain.dto.BusMrpExportDto; import org.dromara.cailiaoshebei.domain.dto.BusMrpExportDto;
import org.dromara.cailiaoshebei.domain.vo.BusMrpVo; import org.dromara.cailiaoshebei.domain.vo.BusMrpVo;
@ -16,8 +22,14 @@ import org.dromara.common.core.exception.ServiceException;
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.CoryObtainTheListReq; import org.dromara.design.domain.bo.CoryObtainTheListReq;
import org.dromara.design.domain.vo.ObtainTheListRes;
import org.dromara.design.service.IBusBillofquantitiesService; import org.dromara.design.service.IBusBillofquantitiesService;
import org.dromara.design.service.IBusBillofquantitiesVersionsService; import org.dromara.design.service.IBusBillofquantitiesVersionsService;
import org.dromara.tender.domain.bo.BusBiddingPlanBo;
import org.dromara.tender.domain.vo.BusBiddingPlanVo;
import org.dromara.tender.domain.vo.BusBillofquantitiesLimitListVo;
import org.dromara.tender.service.IBusBiddingPlanService;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -52,6 +64,7 @@ public class BusMrpBaseController extends BaseController {
private final IBusBillofquantitiesVersionsService busBillofquantitiesVersionsService; private final IBusBillofquantitiesVersionsService busBillofquantitiesVersionsService;
private final IBusBillofquantitiesService busBillofquantitiesService; private final IBusBillofquantitiesService busBillofquantitiesService;
private final IBusBiddingPlanService busBiddingPlanService;
/** /**
* 查询物资-批次需求计划基础信息列表 * 查询物资-批次需求计划基础信息列表
@ -134,8 +147,14 @@ public class BusMrpBaseController extends BaseController {
* 获取剩余量 * 获取剩余量
*/ */
@GetMapping("/remaining") @GetMapping("/remaining")
public R<BigDecimal> remaining(Long suppliespriceId,Long mrpBaseId) { public R<List<Map<String,Object>>> remaining( RemainingReq req) {
return R.ok(busMrpBaseService.remaining(suppliespriceId,mrpBaseId)); String[] split = req.getLimitListId().split(",");
List<Map<String, Object>> maps = new ArrayList<>();
for (String id : split) {
Map<String, Object> remaining = busMrpBaseService.remaining(req.getProjectId(), Long.valueOf(id), req.getMrpBaseId());
maps.add(remaining);
}
return R.ok(maps);
} }
@ -168,25 +187,99 @@ public class BusMrpBaseController extends BaseController {
return R.ok(list); return R.ok(list);
} }
/**
* 获取工程量清单列表
*/
@SaCheckPermission("cailiaoshebei:mrpBase:getZhaoBiaoList")
@GetMapping("/getZhaoBiaoList")
public R<List<BusBiddingPlanVo>> getZhaoBiaoList(CoryObtainTheListReq req) {
BusBiddingPlanBo bo = new BusBiddingPlanBo();
bo.setProjectId(req.getProjectId());
bo.setType("3");
bo.setBidStatus(1);
List<BusBiddingPlanVo> busBiddingPlanVos = busBiddingPlanService.queryList(bo);
return R.ok(busBiddingPlanVos);
}
/**
* 招标计划数据详情
* @param bo
* @return
*/
@SaCheckPermission("cailiaoshebei:mrpBase:getMore")
@GetMapping("/getMore")
public R<List<BusBillofquantitiesLimitListVo>> getMore(BusBiddingPlanBo bo) {
if (bo.getId() == null) {
throw new ServiceException("id不能为空");
}
return R.ok(busBiddingPlanService.getMore(bo));
}
/** /**
* 获取工程量清单列表 * 获取工程量清单列表
*/ */
@SaCheckPermission("cailiaoshebei:purchaseDoc:coryEngineeringList") @SaCheckPermission("cailiaoshebei:purchaseDoc:coryEngineeringList")
@GetMapping("/coryEngineeringList") @GetMapping("/coryEngineeringList")
public R<List<BusBillofquantities>> obtainTheList(CoryObtainTheListReq req) { public R<List<BusBillofquantities>> obtainTheList(CoryObtainTheListReq req) {
BusBillofquantitiesVersions one = busBillofquantitiesVersionsService.getOne(Wrappers.<BusBillofquantitiesVersions>lambdaQuery() // public R<List<ObtainTheListRes>> obtainTheList(CoryObtainTheListReq req) {
.eq(BusBillofquantitiesVersions::getWorkOrderType, "3") //物资工程量清单 // BusBillofquantitiesVersions one = busBillofquantitiesVersionsService.getOne(Wrappers.<BusBillofquantitiesVersions>lambdaQuery()
.eq(BusBillofquantitiesVersions::getProjectId, req.getProjectId()) // .eq(BusBillofquantitiesVersions::getWorkOrderType, "3") //物资工程量清单
.eq(BusBillofquantitiesVersions::getVersions, req.getVersions()) // .eq(BusBillofquantitiesVersions::getProjectId, req.getProjectId())
.eq(BusBillofquantitiesVersions::getStatus, BusinessStatusEnum.FINISH.getStatus()) // .eq(BusBillofquantitiesVersions::getVersions, req.getVersions())
.last("limit 1") // .eq(BusBillofquantitiesVersions::getStatus, BusinessStatusEnum.FINISH.getStatus())
); // .last("limit 1")
if (one == null){ // );
throw new ServiceException("请先完成物资工程量清单"); // if (one == null){
// throw new ServiceException("请先完成物资工程量清单");
// }
// List<BusBillofquantities> list = busBillofquantitiesService.list(Wrappers.<BusBillofquantities>lambdaQuery()
// .eq(BusBillofquantities::getVersions, one.getVersions())
// );
// return R.ok(list);
// List<ObtainTheListRes> obtainTheListRes = new ArrayList<>();
// list.forEach(billofquantities -> {
// ObtainTheListRes res = new ObtainTheListRes();
// BeanUtils.copyProperties(billofquantities, res);
// obtainTheListRes.add(res);
// });
//
// Map<String, List<ObtainTheListRes>> parentMap = obtainTheListRes.stream()
// .collect(Collectors.groupingBy(ObtainTheListRes::getPid));
//
// // 3. 递归组装树形结构从顶级节点pid=0开始
// List<ObtainTheListRes> treeList = buildTree("0", parentMap);
// return R.ok(treeList);
List<BusBillofquantities> busBillofquantities = busBillofquantitiesService.getBaseMapper()
.selectList(new LambdaQueryWrapper<BusBillofquantities>()
.eq(BusBillofquantities::getProjectId, req.getProjectId())
.eq(BusBillofquantities::getName, req.getSid()));
List<String> sids = new ArrayList<>();
busBillofquantities.forEach(busBillofquantities1 -> {
sids.add(busBillofquantities1.getSid());
});
return R.ok(busBillofquantitiesService
.getBaseMapper()
.selectList(new LambdaQueryWrapper<BusBillofquantities>()
.eq(BusBillofquantities::getProjectId, req.getProjectId())
.in(BusBillofquantities::getPid, sids)));
}
private List<ObtainTheListRes> buildTree(String parentId, Map<String, List<ObtainTheListRes>> parentMap) {
// 获取当前父节点的所有直接子节点
List<ObtainTheListRes> children = parentMap.getOrDefault(parentId, Collections.emptyList());
if (children.isEmpty()) {
return Collections.emptyList();
} }
List<BusBillofquantities> list = busBillofquantitiesService.list(Wrappers.<BusBillofquantities>lambdaQuery()
.eq(BusBillofquantities::getVersions, one.getVersions()) // 为每个子节点递归设置其下一级子节点
); for (ObtainTheListRes child : children) {
return R.ok(list); // 递归查询当前子节点的子节点,设置为它的子树
List<ObtainTheListRes> subChildren = buildTree(child.getSid(), parentMap);
// 注意需要在Vo中添加子节点列表字段用于存储子树
child.setChildren(subChildren);
}
return children;
} }
} }

View File

@ -1,6 +1,7 @@
package org.dromara.cailiaoshebei.controller; package org.dromara.cailiaoshebei.controller;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; 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;
@ -9,6 +10,7 @@ import lombok.RequiredArgsConstructor;
import org.dromara.cailiaoshebei.domain.BusPlanDocAssociation; import org.dromara.cailiaoshebei.domain.BusPlanDocAssociation;
import org.dromara.cailiaoshebei.domain.bo.BusMaterialbatchdemandplanBo; import org.dromara.cailiaoshebei.domain.bo.BusMaterialbatchdemandplanBo;
import org.dromara.cailiaoshebei.domain.bo.BusPurchaseDocBo; import org.dromara.cailiaoshebei.domain.bo.BusPurchaseDocBo;
import org.dromara.cailiaoshebei.domain.bo.FeedbackDto;
import org.dromara.cailiaoshebei.domain.vo.BusMaterialbatchdemandplanVo; import org.dromara.cailiaoshebei.domain.vo.BusMaterialbatchdemandplanVo;
import org.dromara.cailiaoshebei.domain.vo.BusPurchaseDocVo; import org.dromara.cailiaoshebei.domain.vo.BusPurchaseDocVo;
import org.dromara.cailiaoshebei.service.IBusMaterialbatchdemandplanService; import org.dromara.cailiaoshebei.service.IBusMaterialbatchdemandplanService;
@ -33,8 +35,12 @@ 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 java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* 物资-采购联系单 * 物资-采购联系单
@ -67,6 +73,8 @@ public class BusPurchaseDocController extends BaseController {
return busPurchaseDocService.queryPageList(bo, pageQuery); return busPurchaseDocService.queryPageList(bo, pageQuery);
} }
/** /**
* 导出物资-采购联系单列表 * 导出物资-采购联系单列表
*/ */
@ -157,13 +165,36 @@ public class BusPurchaseDocController extends BaseController {
@PathVariable("id") Long id) { @PathVariable("id") Long id) {
List<BusPlanDocAssociation> list = planDocAssociationService.list(Wrappers.lambdaQuery(BusPlanDocAssociation.class) List<BusPlanDocAssociation> list = planDocAssociationService.list(Wrappers.lambdaQuery(BusPlanDocAssociation.class)
.eq(BusPlanDocAssociation::getDocId, id)); .eq(BusPlanDocAssociation::getDocId, id));
List<Long> list1 = list.stream().map(BusPlanDocAssociation::getPlanId).toList(); if (CollectionUtil.isEmpty(list)) {
if (list1.isEmpty()) {
return R.ok(new ArrayList<>()); return R.ok(new ArrayList<>());
} }
Map<Long, BigDecimal> collect = list.stream()
.filter(Objects::nonNull) // 过滤空对象
.collect(Collectors.toMap(
BusPlanDocAssociation::getPlanId,
BusPlanDocAssociation::getDemandQuantity,
(existing, replacement) -> existing // 保留第一个遇到的重复键
));
BusMaterialbatchdemandplanBo bo = new BusMaterialbatchdemandplanBo(); BusMaterialbatchdemandplanBo bo = new BusMaterialbatchdemandplanBo();
bo.setIds(list1); bo.setIds(new ArrayList<>(collect.keySet()));
return R.ok(materialbatchdemandplanService.queryList(bo)); List<BusMaterialbatchdemandplanVo> busMaterialbatchdemandplanVos = materialbatchdemandplanService.queryList(bo);
for (BusMaterialbatchdemandplanVo busMaterialbatchdemandplanVo : busMaterialbatchdemandplanVos) {
busMaterialbatchdemandplanVo.setDemandQuantity(collect.get(busMaterialbatchdemandplanVo.getId()));
}
return R.ok(busMaterialbatchdemandplanVos);
}
/**
* 修改回单
*/
@SaCheckPermission("cailiaoshebei:purchaseDoc:edit")
@Log(title = "物资-采购联系单", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateFeedback")
public R<Void> edit(@Validated(EditGroup.class) @RequestBody FeedbackDto bo) {
return toAjax(busPurchaseDocService.updateFeedback(bo));
} }
// //

View File

@ -1,32 +1,33 @@
package org.dromara.cailiaoshebei.controller; package org.dromara.cailiaoshebei.controller;
import java.util.List;
import cn.hutool.core.bean.BeanUtil;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.cailiaoshebei.domain.bo.BusTotalsupplyplanAuditBo; import org.dromara.cailiaoshebei.domain.bo.BusTotalsupplyplanAuditBo;
import org.dromara.cailiaoshebei.domain.bo.BusTotalsupplyplanBo;
import org.dromara.cailiaoshebei.domain.bo.MasterDataReq; import org.dromara.cailiaoshebei.domain.bo.MasterDataReq;
import org.dromara.cailiaoshebei.domain.bo.TotalsupplyplanQueryListReq; import org.dromara.cailiaoshebei.domain.bo.TotalsupplyplanQueryListReq;
import org.dromara.cailiaoshebei.domain.dto.MasterDataReqDto; import org.dromara.cailiaoshebei.domain.dto.MasterDataReqDto;
import org.dromara.cailiaoshebei.domain.vo.BusTotalsupplyplanAuditVo; import org.dromara.cailiaoshebei.domain.vo.BusTotalsupplyplanAuditVo;
import org.dromara.cailiaoshebei.domain.vo.BusTotalsupplyplanVo;
import org.dromara.cailiaoshebei.service.IBusTotalsupplyplanAuditService; import org.dromara.cailiaoshebei.service.IBusTotalsupplyplanAuditService;
import org.springframework.web.bind.annotation.*; import org.dromara.cailiaoshebei.service.IBusTotalsupplyplanService;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.EditGroup; import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.cailiaoshebei.domain.vo.BusTotalsupplyplanVo; import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.cailiaoshebei.domain.bo.BusTotalsupplyplanBo; import org.dromara.common.log.annotation.Log;
import org.dromara.cailiaoshebei.service.IBusTotalsupplyplanService; 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.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/** /**
* 物资-总供应计划 * 物资-总供应计划
@ -82,6 +83,16 @@ public class BusTotalsupplyplanController extends BaseController {
ExcelUtil.exportExcel(list, "物资-总供应计划", BusTotalsupplyplanVo.class, response); ExcelUtil.exportExcel(list, "物资-总供应计划", BusTotalsupplyplanVo.class, response);
} }
/**
* 导入物资-总供应计划数据
*/
@SaCheckPermission("design:totalsupplyplan:import")
@Log(title = "物资-总供应计划", businessType = BusinessType.IMPORT)
@PostMapping("/import")
public R<Void> importData(@RequestPart("file") MultipartFile file) {
return toAjax(busTotalsupplyplanService.importData(file));
}
/** /**
* 获取物资-总供应计划详细信息 * 获取物资-总供应计划详细信息
* *
@ -90,7 +101,7 @@ public class BusTotalsupplyplanController extends BaseController {
@SaCheckPermission("design:totalsupplyplan:query") @SaCheckPermission("design:totalsupplyplan:query")
@GetMapping("/{id}") @GetMapping("/{id}")
public R<BusTotalsupplyplanVo> getInfo(@NotNull(message = "主键不能为空") public R<BusTotalsupplyplanVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) { @PathVariable Long id) {
return R.ok(busTotalsupplyplanService.queryById(id)); return R.ok(busTotalsupplyplanService.queryById(id));
} }
@ -116,6 +127,17 @@ public class BusTotalsupplyplanController extends BaseController {
return toAjax(busTotalsupplyplanService.updateByBo(bo)); return toAjax(busTotalsupplyplanService.updateByBo(bo));
} }
/**
* 批量修改物资-总供应计划
*/
@SaCheckPermission("design:totalsupplyplan:batchEdit")
@Log(title = "物资-总供应计划", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/batchEdit")
public R<Void> batchEdit(@Validated(EditGroup.class) @RequestBody List<BusTotalsupplyplanBo> boList) {
return toAjax(busTotalsupplyplanService.updateBatch(boList));
}
// /** // /**
// * 删除物资-总供应计划 // * 删除物资-总供应计划
// * // *

View File

@ -0,0 +1,160 @@
package org.dromara.cailiaoshebei.controller.app;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.cailiaoshebei.domain.bo.BusMrpBaseBo;
import org.dromara.cailiaoshebei.domain.dto.BusMrpDto;
import org.dromara.cailiaoshebei.domain.dto.BusMrpExportDto;
import org.dromara.cailiaoshebei.domain.vo.BusMrpBaseVo;
import org.dromara.cailiaoshebei.domain.vo.BusMrpVo;
import org.dromara.cailiaoshebei.service.IBusMrpBaseService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
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.design.domain.BusBillofquantities;
import org.dromara.design.domain.BusBillofquantitiesVersions;
import org.dromara.design.domain.bo.CoryObtainTheListReq;
import org.dromara.design.domain.bo.ObtainAllVersionNumbersReq;
import org.dromara.design.domain.vo.BusBillofquantitiesVo;
import org.dromara.design.domain.vo.ObtainTheListRes;
import org.dromara.design.service.IBusBillofquantitiesService;
import org.dromara.design.service.IBusBillofquantitiesVersionsService;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* app物资-批次需求计划基础信息
*
* @author Lion Li
* @date 2025-08-13
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/cailiaoshebei/mrpBase")
public class BusMrpBaseAppController extends BaseController {
private final IBusMrpBaseService busMrpBaseService;
private final IBusBillofquantitiesVersionsService busBillofquantitiesVersionsService;
private final IBusBillofquantitiesService busBillofquantitiesService;
/**
* 查询物资-批次需求计划基础信息列表
*/
@GetMapping("/list")
public TableDataInfo<BusMrpBaseVo> list(BusMrpBaseBo bo, PageQuery pageQuery) {
return busMrpBaseService.queryPageList(bo, pageQuery);
}
/**
* 获取物资-批次需求计划基础信息详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<BusMrpVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(busMrpBaseService.queryById(id));
}
/**
* 删除物资-批次需求计划基础信息
*
* @param ids 主键串
*/
@Log(title = "物资-批次需求计划基础信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(busMrpBaseService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 批量新增或修改
*/
@RepeatSubmit()
@PostMapping("/batch")
public R<Void> batchAddOrUpdate(@RequestBody BusMrpDto dto) {
return toAjax(busMrpBaseService.batchAddOrUpdate(dto));
}
/**
* 获取剩余量
*/
@GetMapping("/remaining")
public R<Map<String,Object>> remaining(Long projectId,Long limitListId,Long mrpBaseId) {
return R.ok(busMrpBaseService.remaining(projectId,limitListId,mrpBaseId));
}
/**
* 获取所有大类
*/
@GetMapping("/obtainAllClassification")
public R<List<BusBillofquantitiesVo>> obtainAllClassification(ObtainAllVersionNumbersReq bo) {
return R.ok(busBillofquantitiesVersionsService.obtainAllClassification(bo));
}
/**
* 获取工程量清单列表
*/
@GetMapping("/coryEngineeringList")
public R<List<BusBillofquantities>> obtainTheList(CoryObtainTheListReq req) {
List<BusBillofquantities> busBillofquantities = busBillofquantitiesService.getBaseMapper()
.selectList(new LambdaQueryWrapper<BusBillofquantities>()
.eq(BusBillofquantities::getProjectId, req.getProjectId())
.eq(BusBillofquantities::getName, req.getSid()));
List<String> sids = new ArrayList<>();
busBillofquantities.forEach(busBillofquantities1 -> {
sids.add(busBillofquantities1.getSid());
});
return R.ok(busBillofquantitiesService
.getBaseMapper()
.selectList(new LambdaQueryWrapper<BusBillofquantities>()
.eq(BusBillofquantities::getProjectId, req.getProjectId())
.in(BusBillofquantities::getPid, sids)));
}
private List<ObtainTheListRes> buildTree(String parentId, Map<String, List<ObtainTheListRes>> parentMap) {
// 获取当前父节点的所有直接子节点
List<ObtainTheListRes> children = parentMap.getOrDefault(parentId, Collections.emptyList());
if (children.isEmpty()) {
return Collections.emptyList();
}
// 为每个子节点递归设置其下一级子节点
for (ObtainTheListRes child : children) {
// 递归查询当前子节点的子节点,设置为它的子树
List<ObtainTheListRes> subChildren = buildTree(child.getSid(), parentMap);
// 注意需要在Vo中添加子节点列表字段用于存储子树
child.setChildren(subChildren);
}
return children;
}
}

View File

@ -0,0 +1,214 @@
package org.dromara.cailiaoshebei.controller.app;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.cailiaoshebei.domain.BusPlanDocAssociation;
import org.dromara.cailiaoshebei.domain.bo.BusMaterialbatchdemandplanBo;
import org.dromara.cailiaoshebei.domain.bo.BusPurchaseDocBo;
import org.dromara.cailiaoshebei.domain.bo.FeedbackDto;
import org.dromara.cailiaoshebei.domain.vo.BusMaterialbatchdemandplanVo;
import org.dromara.cailiaoshebei.domain.vo.BusPurchaseDocVo;
import org.dromara.cailiaoshebei.service.IBusMaterialbatchdemandplanService;
import org.dromara.cailiaoshebei.service.IBusPlanDocAssociationService;
import org.dromara.cailiaoshebei.service.IBusPurchaseDocService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
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.design.service.IBusBillofquantitiesService;
import org.dromara.design.service.IBusBillofquantitiesVersionsService;
import org.dromara.tender.domain.bo.TenderSupplierInputBo;
import org.dromara.tender.domain.vo.TenderSupplierInputVo;
import org.dromara.tender.service.ITenderSupplierInputService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* app物资-采购联系单
*
* @author Lion Li
* @date 2025-08-13
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/cailiaoshebei/purchaseDoc")
public class BusPurchaseDocAppController extends BaseController {
private final IBusPurchaseDocService busPurchaseDocService;
private final IBusMaterialbatchdemandplanService materialbatchdemandplanService;
private final IBusPlanDocAssociationService planDocAssociationService;
private final IBusBillofquantitiesVersionsService busBillofquantitiesVersionsService;
private final IBusBillofquantitiesService busBillofquantitiesService;
private final ITenderSupplierInputService tenderSupplierInputService;
/**
* 查询物资-采购联系单列表
*/
@GetMapping("/list")
public TableDataInfo<BusPurchaseDocVo> list(BusPurchaseDocBo bo, PageQuery pageQuery) {
return busPurchaseDocService.queryPageList(bo, pageQuery);
}
/**
* 查询供应商入库列表
*/
@GetMapping("/supList")
public TableDataInfo<TenderSupplierInputVo> list(TenderSupplierInputBo bo, PageQuery pageQuery) {
return tenderSupplierInputService.queryPageList(bo, pageQuery);
}
/**
* 查询物资-批次需求计划列表
*/
@GetMapping("/planList")
public TableDataInfo<BusMaterialbatchdemandplanVo> list(BusMaterialbatchdemandplanBo bo, PageQuery pageQuery) {
return materialbatchdemandplanService.queryPageList(bo, pageQuery);
}
/**
* 获取物资-采购联系单详细信息
*
* @param id 主键
*/
@GetMapping("/{id}")
public R<BusPurchaseDocVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(busPurchaseDocService.queryById(id));
}
/**
* 获取物资-采购联系单详细PDF
*
* @param id 主键
*/
@SaCheckPermission("cailiaoshebei:purchaseDoc:pdf")
@GetMapping("/pdf/{id}")
public R<String> getPic(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok("操作成功", busPurchaseDocService.queryPicBase64ById(id));
}
/**
* 新增物资-采购联系单
*/
@SaCheckPermission("cailiaoshebei:purchaseDoc:add")
@Log(title = "物资-采购联系单", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody BusPurchaseDocBo bo) {
return toAjax(busPurchaseDocService.insertByBo(bo));
}
/**
* 修改物资-采购联系单
*/
@SaCheckPermission("cailiaoshebei:purchaseDoc:edit")
@Log(title = "物资-采购联系单", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody BusPurchaseDocBo bo) {
return toAjax(busPurchaseDocService.updateByBo(bo));
}
/**
* 删除物资-采购联系单
*
* @param ids 主键串
*/
@SaCheckPermission("cailiaoshebei:purchaseDoc:remove")
@Log(title = "物资-采购联系单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(busPurchaseDocService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 查询采购单关联的计划
*/
@GetMapping("/planList/{id}")
public R<List<BusMaterialbatchdemandplanVo>> list(@NotNull(message = "主键不能为空")
@PathVariable("id") Long id) {
List<BusPlanDocAssociation> list = planDocAssociationService.list(Wrappers.lambdaQuery(BusPlanDocAssociation.class)
.eq(BusPlanDocAssociation::getDocId, id));
if (CollectionUtil.isEmpty(list)) {
return R.ok(new ArrayList<>());
}
Map<Long, BigDecimal> collect = list.stream()
.filter(Objects::nonNull) // 过滤空对象
.collect(Collectors.toMap(
BusPlanDocAssociation::getPlanId,
BusPlanDocAssociation::getDemandQuantity,
(existing, replacement) -> existing // 保留第一个遇到的重复键
));
BusMaterialbatchdemandplanBo bo = new BusMaterialbatchdemandplanBo();
bo.setIds(new ArrayList<>(collect.keySet()));
List<BusMaterialbatchdemandplanVo> busMaterialbatchdemandplanVos = materialbatchdemandplanService.queryList(bo);
for (BusMaterialbatchdemandplanVo busMaterialbatchdemandplanVo : busMaterialbatchdemandplanVos) {
busMaterialbatchdemandplanVo.setDemandQuantity(collect.get(busMaterialbatchdemandplanVo.getId()));
}
return R.ok(busMaterialbatchdemandplanVos);
}
/**
* 修改回单
*/
@Log(title = "物资-采购联系单", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateFeedback")
public R<Void> edit(@Validated(EditGroup.class) @RequestBody FeedbackDto bo) {
return toAjax(busPurchaseDocService.updateFeedback(bo));
}
//
// /**
// * 获取工程量清单列表
// */
// @SaCheckPermission("cailiaoshebei:purchaseDoc:add")
// @GetMapping("/engineeringList")
// public R<List<BusBillofquantities>> obtainTheList(Long projectId) {
// BusBillofquantitiesVersions one = busBillofquantitiesVersionsService.getOne(Wrappers.<BusBillofquantitiesVersions>lambdaQuery()
// .eq(BusBillofquantitiesVersions::getWorkOrderType, "3") //物资工程量清单
// .eq(BusBillofquantitiesVersions::getProjectId, projectId)
// .eq(BusBillofquantitiesVersions::getStatus, BusinessStatusEnum.FINISH.getStatus())
// .last("limit 1")
// );
// if (one == null) {
// throw new ServiceException("请先完成物资工程量清单");
// }
// List<BusBillofquantities> list = busBillofquantitiesService.list(Wrappers.<BusBillofquantities>lambdaQuery()
// .eq(BusBillofquantities::getVersions, one.getVersions())
// );
//
// return R.ok(list);
// }
}

View File

@ -19,6 +19,7 @@ public class constant {
public static final String PURCHASE_DOC_FILE_URL = "docs/purchase/doc/"; // 采购联系单文件路径 public static final String PURCHASE_DOC_FILE_URL = "docs/purchase/doc/"; // 采购联系单文件路径
public static final String PURCHASE_DOC_TEMPLATE_PATH = "template/物资采购联系单模版.docx"; // 采购联系单文件路径 public static final String PURCHASE_DOC_TEMPLATE_PATH = "template/物资采购联系单模版.docx"; // 采购联系单文件路径
public static final String SUPPLIER_INPUT = "supplierInput";//供应商入库 public static final String SUPPLIER_INPUT = "supplierInput";//供应商入库
public static final String BusFormalitiesAreConsolidatedMoveOut = "ConsolidatedMoveOut";
/** /**
* 获取物资采购联系单文件名 * 获取物资采购联系单文件名

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date; import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@ -51,6 +52,8 @@ public class BusMaterialbatchdemandplan extends BaseEntity {
*/ */
private Long suppliespriceId; private Long suppliespriceId;
private Long suppliespricePid;
/** /**
* 基础信息ID * 基础信息ID
*/ */
@ -94,7 +97,7 @@ public class BusMaterialbatchdemandplan extends BaseEntity {
/** /**
* 计划到场时间 * 计划到场时间
*/ */
private Date arrivalTime; private LocalDate arrivalTime;
/** /**
* 备注 * 备注

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.io.Serial; import java.io.Serial;
import java.math.BigDecimal;
/** /**
* 物资-批次需求计划与采购单关联对象 bus_plan_doc_association * 物资-批次需求计划与采购单关联对象 bus_plan_doc_association
@ -37,6 +38,11 @@ public class BusPlanDocAssociation extends BaseEntity {
*/ */
private Long planId; private Long planId;
/**
* 需求数量
*/
private BigDecimal demandQuantity;
/** /**
* 采购联系单id * 采购联系单id
*/ */

View File

@ -1,14 +1,14 @@
package org.dromara.cailiaoshebei.domain; package org.dromara.cailiaoshebei.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.time.LocalDate;
import java.util.Date;
import java.io.Serial; import java.io.Serial;
import java.time.LocalDate;
import java.util.Date;
/** /**
* 物资-总供应计划对象 bus_totalsupplyplan * 物资-总供应计划对象 bus_totalsupplyplan
@ -35,6 +35,16 @@ public class BusTotalsupplyplan extends BaseEntity {
*/ */
private Long projectId; private Long projectId;
/**
* 批次ID
*/
private String sid;
/**
* 批次父ID
*/
private String pid;
/** /**
* 批次号 * 批次号
*/ */

View File

@ -114,4 +114,12 @@ public class BusMaterialbatchdemandplanBo extends BaseEntity {
* 主键集合 * 主键集合
*/ */
private List<Long> ids; private List<Long> ids;
/**
* 供应商id
*/
private Long supplierId;
private Long suppliespricePid;
} }

Some files were not shown because too many files have changed in this diff Show More