Compare commits

...

841 Commits

Author SHA1 Message Date
YunaiV f153406146 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-24 09:29:31 +08:00
YunaiV 837f155668 fix:【PAY 支付】支付渠道配置的解析 2025-05-24 09:29:16 +08:00
YunaiV b72d980cf4 Merge branch 'master' of https://github.com/YunaiV/ruoyi-vue-pro 2025-05-23 09:12:40 +08:00
YunaiV a964ac1831 (〃'▽'〃) v2.6.0 发布:简化项目结构,希望你会喜欢 2025-05-23 09:12:19 +08:00
YunaiV f675608e35 【同步】jdk21 和 jdk8 的代码 2025-05-23 09:12:05 +08:00
YunaiV 93982451eb Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	pom.xml
#	yudao-dependencies/pom.xml
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenCreateListReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenUpdateReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/column/CodegenColumnSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobSaveReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/redis/RedisController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/file/FileConfigDO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactService.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryService.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/erp/Demo03StudentErpService.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/erp/Demo03StudentErpServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceImpl.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobService.java
2025-05-23 09:04:07 +08:00
YunaiV a86db4b43f (〃'▽'〃) v2.6.0 发布:简化项目结构,希望你会喜欢 2025-05-23 09:01:50 +08:00
YunaiV 3140ec8960 Merge remote-tracking branch 'origin/master-jdk17' into master-jdk17 2025-05-21 22:56:57 +08:00
YunaiV 951663b6b7 fix:【AI 大模型】toolContext 为空,会导致报错问题 2025-05-21 22:56:49 +08:00
xingyu4j 78e69421db perf: vben5 代码生成 使用 table action 2025-05-21 14:37:57 +08:00
xingyu4j 39e7d782a7 perf: vben5 代码生成 使用 table action 2025-05-21 14:27:00 +08:00
YunaiV 73e4f831f2 review:【INFRA 基础设施】代码生成的 review 2025-05-20 21:12:24 +08:00
芋道源码 c8ee7adeca
!1351 feat:【INFRA 基础设施】vben5-antd-general 新增 general 标准模式批量删除
Merge pull request !1351 from puhui999/vben5-antd-general
2025-05-20 13:11:01 +00:00
芋道源码 20b4329af6
!1350 perf:【INFRA 基础设施】优化一些 todo 提到的问题
Merge pull request !1350 from puhui999/vben5-antd-schema
2025-05-20 13:03:46 +00:00
芋道源码 5cca48f7ea
Merge pull request #848 from nxiaoqidai/patch-3
Fix: 当流程ID配置没有中缀的时候不设置过期时间
2025-05-20 20:37:40 +08:00
YunaiV 86058b0d3b fix:【BPM 工作流】当流程ID配置没有中缀的时候不设置过期时间 2025-05-20 20:36:47 +08:00
puhui999 a89ff72a36 feat:【INFRA 基础设施】vben5-antd-general 新增 general 标准模式批量删除 2025-05-20 18:02:17 +08:00
puhui999 6982243370 perf:【INFRA 基础设施】优化一些 todo 提到的问题 2025-05-20 16:34:40 +08:00
puhui999 c320b525b5 Merge remote-tracking branch 'refs/remotes/yudao/master-jdk17' into vben5-antd-schema
# Conflicts:
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/Demo01ContactController.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java
#	yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/normal/Demo03StudentNormalServiceImpl.java
2025-05-20 16:10:46 +08:00
puhui999 b9ffa1820d perf:【INFRA 基础设施】优化一些 todo 提到的问题 2025-05-20 16:09:21 +08:00
YunaiV 0c68962a97 review:【INFRA 基础设施】代码生成的 review 2025-05-20 13:31:56 +08:00
芋道源码 d14aaae641
!1348 feat:【INFRA 基础设施】vben5-antd-schema 代码生成时,可生成批量删除
Merge pull request !1348 from puhui999/vben5-antd-schema
2025-05-20 05:07:18 +00:00
puhui999 064fecf4ee perf:【INFRA 基础设施】代码生成DO模式:主子表非erp模式下,主表保存更新时携带的子表信息放主表的 DO 里 2025-05-20 11:39:17 +08:00
puhui999 cd341da674 perf:【INFRA 基础设施】代码生成主子表非 erp 模式时,当子表一对多时更新改为通过 diffList 实现对应的增删改 2025-05-20 11:15:05 +08:00
puhui999 bc77af09e0 perf:【INFRA 基础设施】代码生成示例 demo 代码格式化 2025-05-20 10:24:13 +08:00
puhui999 15e2121078 Merge remote-tracking branch 'origin/vben5-antd-schema' into vben5-antd-schema 2025-05-20 09:57:46 +08:00
puhui999 3e3dbce047 Merge remote-tracking branch 'yudao/master-jdk17' into vben5-antd-schema 2025-05-20 09:57:17 +08:00
puhui999 61cfcc283b perf:【INFRA 基础设施】代码生成配置 delete-batch-enable: false # 是否生成批量删除接口 2025-05-19 23:52:58 +08:00
YunaiV bb236af631 perf: 优化 FileTypeUtils 的 TIKA 创建,提升性能 2025-05-19 20:29:39 +08:00
YunaiV 479dfb6c23 【同步】jdk21 和 jdk8 的代码 2025-05-19 20:12:12 +08:00
puhui999 05bf229a3c perf:【INFRA 基础设施】vben5-antd-schema 主主子表inner代码生成时,可生成批量删除 2025-05-19 18:13:27 +08:00
puhui999 e10425e049 perf:【INFRA 基础设施】vben5-antd-schema 主主子表normal代码生成时,可生成批量删除 2025-05-19 17:58:57 +08:00
Xixiang Chen ea283dd85a
Fix: 当流程ID配置没有中缀的时候不设置过期时间 2025-05-19 17:52:02 +08:00
puhui999 ef1e7b312b perf:【INFRA 基础设施】vben5-antd-schema 主主子表erp代码生成时,可生成批量删除 2025-05-19 16:52:52 +08:00
YunaiV 501cfe5afa feat:【INFRA 基础设施】代码生成时,支持配置 VO/DO 模式 2025-05-19 13:04:25 +08:00
puhui999 6dee926253 feat:【INFRA 基础设施】新增 vben5-antd-schema 模板代码生成时,可生成批量删除 2025-05-19 12:55:07 +08:00
puhui999 9295d61030 feat:【INFRA 基础设施】代码生成时,可生成批量删除接口 2025-05-19 11:50:07 +08:00
puhui999 7a3634d8c0 perf: vben5 utils 2025-05-19 11:02:03 +08:00
YunaiV e00bfd02a1 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	pom.xml
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
#	yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java
#	yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPerformanceController.java
#	yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java
#	yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java
#	yudao-module-mall/yudao-module-promotion/pom.xml
#	yudao-module-mall/yudao-module-trade/pom.xml
#	yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java
#	yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
#	yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
2025-05-17 14:14:23 +08:00
芋道源码 0f7e715bb5
!1347 ruoyi-vue-pro 单体项目,移除 api module,简化项目结构
Merge pull request !1347 from 芋道源码/develop-api-remove
2025-05-17 05:55:45 +00:00
YunaiV fcf097847a reactor:【INFRA 基础设施】代码生成时,区分 boot 还是 cloud 项目
reactor:【INFRA 基础设施】代码生成时,更严格的区分 master 还是 master-jdk17 分支
2025-05-17 13:11:54 +08:00
YunaiV 3e2a809f26 fix:【IoT 物联网】system 依赖的引用不正确 2025-05-17 11:43:13 +08:00
YunaiV dfffc93584 reactor:移除 mall-trade 的 api 包 2025-05-17 11:31:10 +08:00
YunaiV 31b8ee425f reactor:移除 promotion-statistics 的 api 包 2025-05-17 10:56:17 +08:00
YunaiV 1519c03c49 reactor:移除 mall-statistics 的 api 包 2025-05-17 10:48:53 +08:00
YunaiV 5f6d0b3b19 reactor:移除 mall-product 的 api 包 2025-05-17 10:18:33 +08:00
YunaiV 86f88ea590 reactor:移除 pay 的 api 包 2025-05-17 09:48:32 +08:00
YunaiV 494711a68c reactor:移除 ai 的 api 包 2025-05-17 09:08:00 +08:00
YunaiV 5caa9e9395 reactor:移除 ai 的 api 包 2025-05-17 09:00:36 +08:00
YunaiV eefd5341b3 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into develop-api-remove
# Conflicts:
#	yudao-module-ai/yudao-module-ai-biz/pom.xml
2025-05-17 08:13:34 +08:00
YunaiV 23bd042dc8 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-17 08:02:12 +08:00
YunaiV 8fb018a699 reactor:将 ai starter 融合到 ai-module 的 framework/ai 里 2025-05-17 08:01:52 +08:00
YunaiV 543c45e4f1 reactor:将 pay starter 融合到 pay-module 的 framework/pay 里 2025-05-16 23:44:17 +08:00
YunaiV f3b680cfd3 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/weixin/WxPayClientConfig.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceImpl.java
2025-05-16 23:40:08 +08:00
YunaiV d4ed2c49f1 reactor:将 pay starter 融合到 pay-module 的 framework/pay 里 2025-05-16 23:27:00 +08:00
YunaiV ff32b015ab reactor:移除 mp 的 api 包 2025-05-16 20:35:08 +08:00
YunaiV 2bd9dcbfc8 reactor:移除 erp 的 api 包 2025-05-16 13:21:15 +08:00
YunaiV 7944d57ea5 reactor:移除 member 的 api 包 2025-05-16 13:10:21 +08:00
YunaiV e3ab3895b7 reactor:移除 crm 的 api 包 2025-05-16 09:45:15 +08:00
YunaiV 13da7eba6f reactor:移除 bpm 的 api 包 2025-05-16 09:26:15 +08:00
YunaiV ef19efb265 reactor:移除 report 的 api 包 2025-05-15 18:07:43 +08:00
YunaiV e31b6dbff9 reactor:移除 system 和 infra 的 api 包 2025-05-15 17:11:33 +08:00
YunaiV 925a07c7de fix:【AI 大模型】dictDataApi 未沉底移除干净 2025-05-15 10:33:32 +08:00
YunaiV b758e690c1 reactor:移除 system 和 infra 的 api 包 2025-05-15 00:08:11 +08:00
YunaiV ee7b3fb275 reactor:移除 infra 对 system 的依赖 2025-05-14 23:53:14 +08:00
YunaiV 23bb3ebd23 reactor:yudao-common 增加 biz 包,将 framework 依赖的 api 统一迁移,方便后续 yudao-framework 独立仓库 2025-05-14 21:30:36 +08:00
YunaiV 89ca20e298 reactor:yudao-common 增加 biz 包,将 framework 依赖的 api 统一迁移,方便后续 yudao-framework 独立仓库 2025-05-14 21:18:38 +08:00
YunaiV e4e162a47b Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiAccessLogCommonApi.java
#	yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiErrorLogCommonApi.java
#	yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiAccessLogCreateReqDTO.java
#	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
#	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java
#	yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java
#	yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
#	yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApiImpl.java
#	yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java
#	yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java
2025-05-14 21:04:37 +08:00
芋道源码 e917fce6b3
!1343 reactor:yudao-common 增加 biz 包,将 framework 依赖的 api 统一迁移,方便后续 yudao-framework 独立仓库
Merge pull request !1343 from 芋道源码/develop
2025-05-14 11:31:58 +00:00
YunaiV 6c6babb4c3 reactor:yudao-common 增加 biz 包,将 framework 依赖的 api 统一迁移,方便后续 yudao-framework 独立仓库 2025-05-14 19:23:40 +08:00
安浩浩 abf5fae91a fix:将API导入路径中的simpleClassName_strikeCase替换为businessName,以确保正确引用API 2025-05-13 22:55:31 +08:00
YunaiV 6bb02e6053 (〃'▽'〃) v2.5.0 发布:又熬过 30 个夜,头发还在 2025-05-13 20:16:23 +08:00
YunaiV 3a55ea0858 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	pom.xml
#	yudao-dependencies/pom.xml
2025-05-13 20:14:04 +08:00
YunaiV e68b294ea1 (〃'▽'〃) v2.5.0 发布:又熬过 30 个夜,头发还在 2025-05-13 20:10:01 +08:00
YunaiV 51d8346733 application-local 默认切到 Kongdy 2025-05-13 20:01:19 +08:00
YunaiV f3b897ea5d Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-13 19:30:11 +08:00
YunaiV 2cb4c7ddb4 fix:修复工作流的发起时间未返回 2025-05-13 19:23:09 +08:00
YunaiV 0cd831d5f5 fix:【CRM】receiveContactLog 记录日志不正确的问题 2025-05-13 09:55:19 +08:00
YunaiV 69da106b9e reactor:增强MPJLambdaWrapperX 类,左连接后可以使用betweenIfPresent等 2025-05-12 21:21:52 +08:00
YunaiV 1cf079fec3 fix:【BPM 工作流】项目重启后,审批重启前的流程会出现生成的下一待办任务所属人出现缺失 2025-05-12 20:56:31 +08:00
YunaiV ee5cb23730 fix(bpm):修复自选审批人时存在多个并行节点时审批人覆盖问题
多个并行节点中只有最后一个节点的审批人会被保存,其他都为空
2025-05-12 20:48:33 +08:00
芋道源码 edb302521f
!1340 fix(bpm):修复自选审批人时存在多个并行节点时审批人覆盖问题
Merge pull request !1340 from whc/master-jdk17
2025-05-12 12:45:55 +00:00
YunaiV 5421299b09 Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-05-12 20:21:52 +08:00
芋道源码 47755e9352
!1339 perf: vben5 代码生成
Merge pull request !1339 from puhui999/master-jdk17
2025-05-12 12:21:06 +00:00
芋道源码 a1ebef07d1
!1338 【功能完善】商城:【会员】发送客服消息时也给自己发送一条 websocket 消息
Merge pull request !1338 from puhui999/develop-new
2025-05-12 12:20:49 +00:00
吴焕超 03c804ee10 fix(bpm):修复自选审批人时存在多个并行节点时审批人覆盖问题
多个并行节点中只有最后一个节点的审批人会被保存,其他都为空
2025-05-12 18:24:35 +08:00
YunaiV c9ecb27f8b 【同步】jdk21 和 jdk8 的代码 2025-05-12 09:26:15 +08:00
YunaiV efc535c051 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawBaseVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayTransferNotifyReqDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoTransferController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/vo/transfer/PayDemoTransferCreateReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/PayTransferController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferCreateReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoTransferServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java
2025-05-12 09:19:22 +08:00
YunaiV 50e31f1bec feat:同步最新菜单 sql 2025-05-12 09:10:21 +08:00
YunaiV 51c1091430 fix:【PAY 支付】PayDemoWithdrawServiceImpl 拼写错误 2025-05-11 20:48:51 +08:00
YunaiV 7c38a32fc9 fix:【MALL 商城】小程序发货,uploadTime 不正确的问题 2025-05-11 17:11:38 +08:00
YunaiV 44548ee03f feat:【MALL 商城】商城分佣提现,完成对微信转账(小程序)的对接 2025-05-11 12:39:05 +08:00
YunaiV fd8567f0fa fix:【PAY 支付】wxjava v3 微信支付,connection pool shutdown 问题 2025-05-11 08:52:52 +08:00
YunaiV 4d25e810e3 feat:【MALL 商城】商城分佣提现,初步对接成功微信支付 2025-05-11 08:12:42 +08:00
YunaiV b91a30dd3e feat:【PAY 支付】增加 channelPackageInfo 字段,对接微信新的转账 API(太难了!!!!!!!!!!!!!!!!!!!!) 2025-05-10 20:05:17 +08:00
YunaiV 0e7ce63719 feat:【PAY 支付】转账单,支持导出功能 2025-05-10 17:15:30 +08:00
YunaiV 288d8e3132 reactor:【PAY 支付】优化退款回调接口,增加 merchantRefundId 退款编号参数
reactor:【MALL 商城】售后退款时,基于回调处理
2025-05-10 16:43:55 +08:00
YunaiV fe8871b5f1 feat:【MALL 商城】佣金提现,支持提现失败时,重新发起 2025-05-10 11:48:29 +08:00
YunaiV 423c0b7ea7 feat:【MALL 商城】佣金提现,优化字段,以及支持更多 API 自动打款 2025-05-10 10:07:11 +08:00
YunaiV d2b668a676 feat:【PAY 支付】提现示例,拆分 create 和 transfer 两个状态,更符合实际场景 2025-05-09 22:03:01 +08:00
puhui999 74712db1a8 perf: vben5 代码生成 2025-05-09 16:38:47 +08:00
YunaiV 38c76806a3 feat:【PAY 支付】微信支付的转账,接入新的 API(需要继续测试,= = 真麻烦)
feat:【PAY 支付】钱包支持转账功能
2025-05-08 23:31:23 +08:00
puhui999 99803d1ebf 【功能完善】商城:【会员】发送客服消息时也给自己发送一条 websocket 消息 2025-05-08 17:08:37 +08:00
YunaiV f81dc105a2 feat:【PAY 支付】AbstractAlipayPayClient,支付宝增加回调解析 2025-05-08 13:57:49 +08:00
YunaiV 7653be9d48 feat:【PAY 支付】示例转账单,改成示例提现单,理解成本更低 2025-05-08 13:09:14 +08:00
YunaiV 1e7f22cde0 feat:【PAY 支付】完善支付转账示例,以及转账功能(支付宝) 2025-05-07 23:37:24 +08:00
YunaiV ffee189589 reactor:移除 PayClient 获取转账时的 type 字段,只有支付宝会区分,后续通过 channelExtras 区分 2025-05-07 09:21:29 +08:00
xingyu4j 5327d3a494 perf: vben5 代码生成 2025-05-06 23:26:44 +08:00
xingyu4j 6ba0484f33 perf: vben5 代码生成 2025-05-06 22:14:10 +08:00
YunaiV 8eb76c210d 【同步】jdk21 和 jdk8 的代码 2025-05-06 20:58:00 +08:00
YunaiV e633c7cfe3 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
#	yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java
2025-05-06 20:50:33 +08:00
YunaiV a34de9f223 feat:【MALL 商城】增加微信物流的对接(和社区同学,一起测试中。。。) 2025-05-06 20:49:13 +08:00
YunaiV 9847d4cdb1 fix:【PAY 支付】支付宝回调时,区分公钥模式、证书模式 2025-05-05 23:52:36 +08:00
YunaiV be86acb9b6 fix:【PAY 支付】支付宝回调时,区分公钥模式、证书模式 2025-05-05 23:37:40 +08:00
YunaiV a2bfa7a95a feat:weixin-java from 4.7.2.B => 4.7.4.B
feat:微信支付 v3 从平台证书切换成微信支付公钥
feat:微信支付 v3 增加 header 解析
2025-05-05 22:35:49 +08:00
YunaiV 59234e1eea feat:增加租户切换的能力 2025-05-05 17:27:40 +08:00
YunaiV 8500575f44 fix:TenantDatabaseInterceptor 针对 TenantBaseDO 忽略不正确 2025-05-05 15:31:29 +08:00
YunaiV 1c0909d970 reactor:@TenantIgnore 增加 enable 属性,用于是否开启 2025-05-05 11:33:39 +08:00
YunaiV e6fcb60332 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-05 11:19:27 +08:00
YunaiV 70cbb82c84 reactor:@TenantIgnore 添加在 DO 实体类上,该表自动忽略租户 2025-05-05 11:18:19 +08:00
YunaiV 112f63bb7e reactor:@TenantIgnore 添加在 Controller 时,自动添加到 TenantProperties 中 2025-05-05 10:23:44 +08:00
YunaiV e4890f616b reactor:@TenantIgnore 添加在 Controller 时,自动添加到 TenantProperties 中 2025-05-05 09:37:27 +08:00
YunaiV bafc69d67d Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-05 09:34:11 +08:00
YunaiV 152c24e8b8 reactor:@TenantIgnore 添加在 Controller 时,自动添加到 TenantProperties 中 2025-05-05 09:34:02 +08:00
YunaiV 8e0398bce6 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageServiceImpl.java
2025-05-05 09:33:51 +08:00
YunaiV be86cdfd51 reactor:@TenantIgnore 添加在 Controller 时,自动添加到 TenantProperties 中 2025-05-05 09:33:34 +08:00
YunaiV 5a87b33df2 fix:【MP 公众号】receiveMessage 记录消息时,兜底 MpUserDO 的创建边界 2025-05-04 21:26:40 +08:00
YunaiV 0343c4d2ba fix:【MALL 商城】秒杀、积分商品库存剩余 1 时,无法下单 2025-05-04 11:39:47 +08:00
芋道源码 8b70307ae7
!1336 【功能完善】INFRA:代码生成 vben5 antd 树表、主子表模版
Merge pull request !1336 from puhui999/master-jdk17
2025-05-04 03:14:10 +00:00
YunaiV 5af9496d66 fix:application-local.yaml 配置文件的,spring.autoconfigure.exclude 增加 noinspection SpringBootApplicationYaml,避免出现很难看的报错提醒!!! 2025-05-04 11:13:09 +08:00
YunaiV fe0840cde8 fix:【MALL 商城】linux 部署时,express.client 配置项,因为大写无法识别 2025-05-04 10:51:53 +08:00
YunaiV 1138376f7a fix:【PAY 支付】支付示例订单退款时,校验 payRefundId 不正确的问题 2025-05-04 10:39:28 +08:00
YunaiV 5f58dfdcd5 fix:AOP 拼接参数时,servlet 相关 request、response 可能无法序列化的问题 2025-05-04 10:36:23 +08:00
YunaiV 0ff319ebf7 Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-04 10:09:19 +08:00
YunaiV 2c82556db7 chore:mybatis from 3.5.11 -> 3.5.19 2025-05-04 10:08:09 +08:00
YunaiV 59e5f780be Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-04 10:06:53 +08:00
YunaiV 2ee64635f3 chore:mybatis from 3.5.11 -> 3.5.19 2025-05-04 10:06:27 +08:00
YunaiV ded7a38a38 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-04 09:59:10 +08:00
YunaiV d3963644b8 chore:guava from 33.4.0-jre => 33.4.8-jre 2025-05-04 09:58:49 +08:00
YunaiV 3bcb9890e8 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-04 09:53:43 +08:00
YunaiV 163839926a fix:justauth-spring-boot-starter 引入的 hutool-core 冲突 2025-05-04 09:53:34 +08:00
YunaiV d695dc3cd9 update:AI 功能说明 2025-05-03 22:11:31 +08:00
YunaiV b66a753226 feat:【AI 大模型】新增 Coze 智能体的接入 2025-05-03 21:56:31 +08:00
YunaiV 50f86f1e0a fix:【AI 大模型】logback 和 slf4j-simple 的日志冲突 2025-05-03 20:05:20 +08:00
YunaiV 8b958cdc9b feat:【AI 大模型】工作流增加 OLLAMA 的接入 2025-05-03 19:50:29 +08:00
puhui999 c6582b2a61 【功能完善】INFRA:代码生成 vben5 antd 主子表 erp 模版 2025-05-03 18:24:12 +08:00
YunaiV 04b8aa0422 reactor:【AI 大模型】优化消息发送后,读取文档的逻辑,避免 N 次读取 2025-05-03 18:09:28 +08:00
puhui999 515cbbb285 【功能完善】INFRA:代码生成 vben5 antd 主子表 inner 模版 2025-05-03 17:31:09 +08:00
YunaiV 3e8596ee4b feat:【AI 大模型】增加知识库的删除功能 2025-05-03 16:51:17 +08:00
puhui999 57138d7995 【功能完善】INFRA:代码生成 vben5 antd 主子表 normal 模版 2025-05-03 16:39:55 +08:00
YunaiV e11ee654ef feat:【AI 大模型】增加 AI ToolContext 上下文 2025-05-03 16:37:50 +08:00
芋道源码 3c87f953ee
!1332 feat: 完善AI工作流运行测试(通义千问)
Merge pull request !1332 from Lesan/feature/ai-workflow
2025-05-03 08:27:39 +00:00
YunaiV 282e87b17e fix:【AI 大模型】写作时,获取聊天模型错误 2025-05-03 16:10:37 +08:00
芋道源码 48e5670f09
!1333 fix: ai-writer 获取聊天模型错误
Merge pull request !1333 from dhb52/N/A
2025-05-03 08:10:05 +00:00
芋道源码 fe2122d3be
!1323 feat:AI工具新增ToolContext
Merge pull request !1323 from Ren/feature/ai
2025-05-03 07:39:08 +00:00
puhui999 b0f4a252c7 【功能完善】INFRA:代码生成 vben5 antd 树表模版 2025-05-03 15:06:09 +08:00
puhui999 28c818e9bc Merge remote-tracking branch 'yudao/master-jdk17' into master-jdk17
# Conflicts:
#	yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
2025-05-03 13:34:23 +08:00
puhui999 ed920f3fd3 【代码优化】INFRA:代码生成 vben5 antd 模版 2025-05-03 13:32:53 +08:00
YunaiV 8176278086 feat:集成积木仪表盘 2025-05-03 10:28:41 +08:00
YunaiV 09b872a882 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-03 10:26:44 +08:00
YunaiV 4fb4af2c5c feat:集成积木仪表盘 2025-05-03 10:26:14 +08:00
YunaiV 0038aa0cdf chore:guice version 移除 2025-05-03 09:15:35 +08:00
YunaiV b0a53a26cd Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
2025-05-03 09:07:55 +08:00
YunaiV 0b98ef4ecf chore:jimureport 1.8.1 to 1.9.4 2025-05-03 09:06:36 +08:00
YunaiV 28c20fa323 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-05-03 08:45:47 +08:00
YunaiV bd057ce14d chore:mybatis 相关依赖升级 2025-05-03 08:45:36 +08:00
YunaiV 071fafd687 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	README.md
#	pom.xml
#	yudao-dependencies/pom.xml
2025-05-03 08:36:08 +08:00
YunaiV 585a124d34 chore:spring 相关依赖升级 2025-05-03 08:35:31 +08:00
YunaiV cd263022d4 fix:【全局】sqlserver 在分页的兼容性 2025-05-02 22:47:25 +08:00
YunaiV 387c5cd6ff Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-05-02 22:21:41 +08:00
YunaiV c8a14f11ec Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-05-02 21:09:43 +08:00
YunaiV 00ed548ef5 【同步】jdk21 和 jdk8 的代码 2025-05-02 21:09:14 +08:00
YunaiV a557f0733f Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/file/FileApiImpl.java
#	yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java
#	yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImplTest.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java
#	yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java
2025-05-02 21:01:58 +08:00
芋道源码 c2db16cc15
!1335 reactor:【INFRA】文件上传 api,增加 directory 参数,去除 path 参数,并支持按照日期分目录、文件名不再使用 …
Merge pull request !1335 from 芋道源码/develop
2025-05-02 13:00:17 +00:00
YunaiV cce09044c1 reactor:【INFRA】文件上传 api,增加 directory 参数,去除 path 参数,并支持按照日期分目录、文件名不再使用 sha256 而是时间戳 2025-05-02 18:22:00 +08:00
xingyu4j bf05e2d277 fix: vben5 Codegen Front Type 2025-05-02 13:46:36 +08:00
YunaiV d778184213 feat:【MALL】增加优惠模版的领取信息的返回 2025-05-01 09:01:57 +08:00
YunaiV 95b8cf00fd fix:【商城】已删除的商品,无法评论,导致 TradeOrderAutoCommentJob 重复持续运行 2025-04-30 21:29:50 +08:00
YunaiV 361e50e5de feat:Redis Stream 增加清理 Job,避免占用内存过多 2025-04-30 19:41:24 +08:00
YunaiV 74490ed03b reactor:使用 aj-captcha 官方 1.4.0 2025-04-30 15:09:06 +08:00
YunaiV e7ad73c278 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java
2025-04-30 15:02:49 +08:00
YunaiV d7656535a2 reactor:使用 aj-captcha 官方 1.4.0 2025-04-30 15:01:19 +08:00
YunaiV b047274306 【同步】jdk21 和 jdk8 的代码 2025-04-30 13:47:25 +08:00
YunaiV 622e71cd55 【同步】jdk21 和 jdk8 的代码 2025-04-30 13:47:00 +08:00
YunaiV 4d925f69db 【同步】jdk21 和 jdk8 的代码 2025-04-30 09:45:18 +08:00
YunaiV 3c361527fc reactor:使用 justauth 官方 1.16.7(jdk8 特殊适配,等 1.4.1) 2025-04-30 09:42:33 +08:00
dhb52 8dbbad9e2d
fix: ai-writer 获取聊天模型错误
Signed-off-by: dhb52 <dhb52@126.com>
2025-04-29 16:20:37 +00:00
YunaiV 54941f1361 Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareCreateReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareUpdateReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/record/IotOtaUpgradeRecordPageReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/task/IotOtaUpgradeTaskPageReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java
#	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java
2025-04-30 00:11:24 +08:00
YunaiV 4cebe4af14 reactor:使用 justauth 官方 1.16.7 2025-04-30 00:05:54 +08:00
xingyu4j d591e9a01e feat: 使用 modalApi.unlock() 替换 modalApi.lock(false) 2025-04-29 22:53:30 +08:00
YunaiV dad0cc4cb1 Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-04-29 22:12:35 +08:00
YunaiV cb701d7d7f fix:【INFRA】阿里云 S3 上传时,会 aws-chunked encoding is not supported 报错的问题 2025-04-29 19:11:50 +08:00
xingyu4j 5a906a7b20 fix: requiredMode 调成为 Schema.RequiredMode.REQUIRED 的方式,解决提示 REQUIRED 找不到的问题 2025-04-29 14:26:37 +08:00
Lesan bce63cd04f feat: 完善AI工作流运行测试(通义千问) 2025-04-29 13:59:33 +08:00
YunaiV 4dde700f35 feat:【MALL】App 售后筛选时,增加 status 过滤 2025-04-28 23:16:54 +08:00
xingyu4j aa48a6f533 fix: vben 代码生成默认vbenForm 样式 2025-04-28 15:10:30 +08:00
xingyu4j 1080972e36 fix: VxeTableGridOptions 从 #/adapter/vxe-table 导入 2025-04-28 15:06:48 +08:00
YunaiV 00a08d6cb6 reactor:【MALL】修改购物车查询接口,返回库存、状态等状态,默认不自动取消 selected 状态 2025-04-28 00:24:59 +08:00
YunaiV ec76c1ae6e fix:【MALL】修复 addBrokerage 创建分销记录时,每个订单项,生成分销记录 2025-04-27 09:44:27 +08:00
YunaiV 3395a3d86b feat:【MALL】商城订单取消时,额外校验支付单的状态,进一步兜底回调情况 2025-04-27 08:58:54 +08:00
YunaiV 03e510adfd fix:【MALL】修复了一些问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1315 2025-04-26 17:34:17 +08:00
芋道源码 f6acc9dea5
!1315 修复了一些问题
Merge pull request !1315 from puhui999/develop-tmp
2025-04-26 09:26:25 +00:00
YunaiV abfbe1ea83 feat:【SYSTEM】通过系统配置管理来设置系统是否可注册用户 2025-04-26 17:22:42 +08:00
YunaiV 4a9e9961b0 fix:【SYSTEM】AdminUserServiceImplTest 的 testUpdateUserProfile_success 单测报错 2025-04-26 17:04:20 +08:00
YunaiV cca592a15b fix:【SYSTEM】修复创建租户管理员时,select/update 自动拼接user_id 问题 2025-04-26 16:51:41 +08:00
YunaiV dd068eb94f refactor:【INFRA】优化 vben5.0 标准代码生成的模版 2025-04-26 16:48:55 +08:00
YunaiV 3d45f92852 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into develop 2025-04-26 16:44:38 +08:00
芋道源码 380cc87ea4
!1329 【代码优化】INFRA:代码生成 vben5 schema data.ts 模版优化
Merge pull request !1329 from puhui999/master-jdk17
2025-04-26 08:44:31 +00:00
YunaiV df8593d27b Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into develop 2025-04-26 11:23:03 +08:00
芋道源码 24b48f3826
!1325 【fix】bpm 回退操作参数取值
Merge pull request !1325 from aho/master-jdk17
2025-04-26 03:22:57 +00:00
YunaiV cf3a13d4ff fix:【BPM】修复多实例使用 LinkedHashSet 保持顺序 2025-04-26 11:19:31 +08:00
YunaiV a9bb55340b feat:使用 aws s3 2.0 客户端 2025-04-26 10:00:53 +08:00
YunaiV cc0c92b868 feat:使用 aws s3 2.0 客户端 2025-04-26 10:00:29 +08:00
YunaiV 2da16930ae Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
2025-04-26 09:44:14 +08:00
YunaiV 46676a439d feat:【INFRA】文件存储,增加 enablePathStyleAccess 选项 2025-04-25 21:48:37 +08:00
puhui999 03d3239463 【功能完善】INFRA:代码生成 vben5 antd 单表表单模版 2025-04-25 18:08:24 +08:00
puhui999 ff39a2b57b 【功能完善】INFRA:代码生成 vben5 antd 单表表单模版 2025-04-25 11:15:57 +08:00
芋道源码 0885eb7c70
!1219 【依赖升级】AWS SDK for Java 1.x to 2.x
Merge pull request !1219 from puhui999/develop
2025-04-24 14:20:39 +00:00
puhui999 ef2d0b354a 【功能新增】INFRA:代码生成 vben5 antd 模版 50% 2025-04-24 18:25:04 +08:00
puhui999 c26a46da66 【功能新增】INFRA:代码生成 vben5 antd 模版 50% 2025-04-24 11:37:56 +08:00
YunaiV 1b62f5a456 【功能优化】VBEN5.0 接入的 SQL 同步 2025-04-23 23:15:36 +08:00
YunaiV ab8cad2352 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java
2025-04-23 23:08:41 +08:00
YunaiV bbc59e44d0 【功能优化】VBEN5.0 接入的 SQL 同步 2025-04-23 23:08:07 +08:00
puhui999 32bdc20a4b 【代码优化】INFRA:代码生成 vben5 schema data.ts 模版优化 2025-04-22 16:12:12 +08:00
YunaiV 11402e1412 【功能优化】SYSTEM:updateUserProfile 接口,增加 avatar 参数,逐步替代掉 updateUserAvatar 接口 2025-04-22 09:11:47 +08:00
YunaiV 10397aa480 【代码优化】SYSTEM:profile 接口,不在加载 socialuser,而是提供独立接口 2025-04-21 20:15:00 +08:00
YunaiV 1c854bb547 【代码评审】INFRA:代码生成在 vben5 的模版 2025-04-21 20:14:15 +08:00
芋道源码 6d179320c9
!1328 【功能新增】代码生成: vue3_vben5_antd schema 主子表 erp 模板
Merge pull request !1328 from puhui999/master-jdk17
2025-04-21 12:12:15 +00:00
puhui999 2d0f989968 【功能新增】代码生成: vue3_vben5_antd schema 主子表 erp 模板 2025-04-21 19:10:33 +08:00
puhui999 b3a40af214 【代码优化】代码生成: vue3_vben5_antd schema 主子表模板优化 2025-04-21 16:03:36 +08:00
YunaiV 436eb29d30 【功能新增】SYSTEM:返回人信息时,增加 username、email,用于 vben 界面的展示 2025-04-19 19:45:07 +08:00
芋道源码 08eb75ea0d
!1326 代码生成: vue3_vben5_antd schema 主子表标准模式和内嵌模式模板完成
Merge pull request !1326 from puhui999/master-jdk17
2025-04-19 03:58:28 +00:00
puhui999 e1fa4e1a70 【代码优化】代码生成: vue3_vben5_antd schema 主子表标准模式和内嵌模式模板完成 2025-04-17 18:42:05 +08:00
puhui999 dfcbcf09d4 【代码优化】代码生成: vue3_vben5_antd schema 主子表标准模式和内嵌模式模板完成 2025-04-17 16:25:13 +08:00
puhui999 f3aa501e94 【代码优化】代码生成: vue3_vben5_antd schema 主子表模版优化 2025-04-17 11:19:30 +08:00
puhui999 da248cd126 【代码优化】代码生成: vue3_vben5_antd schema 主子表模板优化(标准和内嵌模式) 2025-04-16 23:53:33 +08:00
puhui999 1f7f06549f 【代码优化】代码生成: vue3_vben5_antd schema 主子表 api 和 data.ts 模板优化 2025-04-16 22:29:32 +08:00
puhui999 3923189887 【功能新增】代码生成: vue3_vben5_antd schema 主子表 2025-04-16 18:47:47 +08:00
aho d67ca05621 【fix】bpm 回退操作参数取值 2025-04-16 17:26:08 +08:00
puhui999 e704f4c755 【代码优化】代码生成: vue3_vben5_antd 模版目录调整 2025-04-16 15:52:20 +08:00
puhui999 24aea3e30a 【代码优化】INFRA: vue3_vben5_antd schema 单表和树表代码生成模版优化 2025-04-16 15:26:01 +08:00
Ren dda2b56bbf feat:AI工具新增ToolContext 2025-04-12 23:52:24 +08:00
YunaiV 61edbcb9ce 2.4.2 版本发布 2025-04-12 12:24:50 +08:00
YunaiV cbc07d91ed Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	pom.xml
#	yudao-dependencies/pom.xml
2025-04-12 12:24:00 +08:00
YunaiV 7c94085499 2.4.2 版本发布 2025-04-12 12:19:56 +08:00
YunaiV d621d8254d 【同步】jdk21 和 jdk8 的代码 2025-04-12 12:06:00 +08:00
YunaiV 07b3865f2e Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-04-12 12:01:22 +08:00
YunaiV fdd15424fc 171 fix(protection): 修复HTTP接口签名 API重复请求问题 2025-04-12 12:01:00 +08:00
YunaiV d8451b004e Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java
2025-04-12 11:56:35 +08:00
YunaiV f6601ab639 171 fix(protection): 修复HTTP接口签名 API重复请求问题 2025-04-12 11:32:18 +08:00
YunaiV 4d88cfdf86 【代码修复】BPM:BpmProcessIdRedisDAO 的时间处理不对 2025-04-12 10:47:32 +08:00
YunaiV 42dbd4e21a 【代码评审】INFRA:代码生成在 vben5 的模版 2025-04-12 09:48:15 +08:00
芋道源码 f83d93bd5b
!1321 【功能新增】INFRA: vben next schema 单表和树表代码生成
Merge pull request !1321 from puhui999/master-jdk17
2025-04-12 01:26:11 +00:00
YunaiV 5d77e3751b 【缺陷修复】AI:临时修复 tinyflow 在 groovy 冲突的问题 2025-04-12 09:22:00 +08:00
YunaiV 160771264f Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-04-12 08:58:22 +08:00
YunaiV e56b99f2a7 Merge branch 'feature/ai' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-04-12 08:57:32 +08:00
芋道源码 e2f158996b
!1318 排除TinyFlow的AI工作流中的agents-flex-store-elasticsearch, 在没用到es的时候一直检测es存活
Merge pull request !1318 from neviabit/N/A
2025-04-12 00:57:06 +00:00
YunaiV 911f5f8bf3 【代码评审】AI:PPT 相关 2025-04-12 08:54:35 +08:00
芋道源码 c357e7ae55
!1317 【优化代码】AI PPT:优化文多多、讯飞 API
Merge pull request !1317 from 小新/feature/ai
2025-04-12 00:48:47 +00:00
puhui999 37e5152a35 【代码优化】INFRA: vben next 树表代码生成 2025-04-11 21:38:39 +08:00
puhui999 015565cc9a 【功能新增】INFRA: vben next 树表代码生成 2025-04-11 18:21:42 +08:00
puhui999 69486939d5 【功能新增】INFRA: vben next 单表代码生成 2025-04-11 16:47:11 +08:00
xiaoxin 47df4bb21f feat: mcp demo 2025-04-09 13:16:29 +08:00
neviabit 8b49e5a94d
排除TinyFlow的AI工作流中的agents-flex-store-elasticsearch, 防止一直检测失败导致的Elasticsearch health check failed, 这导致了日志logs被这些无意义的异常给占满
Signed-off-by: neviabit <10192451+neviabit@user.noreply.gitee.com>
2025-04-08 09:20:56 +00:00
xiaoxin 3445baf926 Merge remote-tracking branch 'yd_origin/feature/ai' into feature/ai 2025-04-07 15:45:59 +08:00
YunaiV be416b7d78 【代码优化】MALL:在线客服的注释 2025-04-03 23:33:21 +08:00
puhui999 d5c1a2ff9f 【缺陷修复】商城:订单取消收回优惠券失败导致管理员确认退款不成功的问题 2025-04-02 17:48:10 +08:00
puhui999 09aa6b2567 【缺陷修复】商城:优惠券在领取类型为指定发放和新人券时无法发送的问题 2025-04-02 11:35:36 +08:00
YunaiV 1e4e02ec2f Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-04-01 19:16:02 +08:00
芋道源码 a484007d97
!1312 修复了一些问题
Merge pull request !1312 from puhui999/develop-tmp
2025-04-01 11:15:55 +00:00
puhui999 40b6e5a3bb 【缺陷修复】商城:检查是否包邮 2025-04-01 18:04:17 +08:00
puhui999 81124292fd 【代码优化】商城:客服消息携带用户头像信息 2025-04-01 16:28:02 +08:00
YunaiV 7f8261ce37 【同步】jdk21 和 jdk8 的代码 2025-03-30 10:58:17 +08:00
YunaiV 4ed753d6b8 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
2025-03-30 10:55:04 +08:00
YunaiV fd2d067324 Merge branch 'feature/ai' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-03-30 10:53:39 +08:00
YunaiV a53c7dafd3 Merge branch 'feature/bpm' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-03-30 10:53:17 +08:00
芋道源码 7179786a45
!1305 feat: AI工作流优化
Merge pull request !1305 from Lesan/feature/ai-工作流
2025-03-30 02:19:03 +00:00
jason d7a785d1de 【问题修复】 并行网关保存问题 2025-03-28 21:41:40 +08:00
Lesan 2aff972600 feat: AI工作流优化 2025-03-28 15:54:46 +08:00
芋道源码 743d88a4fc
!1301 条件判断添加支持JOIN表的属性
Merge pull request !1301 from QINY/master-jdk17
2025-03-25 13:09:01 +00:00
YunaiV f0c26d5b5a 【代码评审】BPM:子流程的代码 2025-03-25 12:49:34 +08:00
芋道源码 2cf5e17f4b
!1303 子流程优化
Merge pull request !1303 from Lesan/feature/bpm-子流程
2025-03-25 04:44:01 +00:00
Lesan c9a8548920 feat: 流程时间线适配子流程节点 2025-03-25 11:07:24 +08:00
Lesan b471dc55c3 fix: 存在子流程情况下的取消逻辑优化 2025-03-25 10:37:38 +08:00
Lesan e14716a307 fix: 存在子流程情况下的取消逻辑优化 2025-03-25 10:24:34 +08:00
YunaiV 4bb52bb37d 【代码评审】AI:工作流 2025-03-25 09:55:05 +08:00
芋道源码 c8e63f4a8c
!1300 feat: AI工作流
Merge pull request !1300 from Lesan/feature/ai-工作流
2025-03-25 01:21:55 +00:00
qiny ba4d4540ab 条件判断添加支持JOIN表的属性 2025-03-24 16:58:42 +08:00
Lesan 587504c36a feat: AI工作流 2025-03-24 15:15:27 +08:00
YunaiV 4fbe9fa480 【代码优化】BPM:流程模型->基本信息->谁可以发起,支持指定多个部门 2025-03-23 17:28:08 +08:00
芋道源码 af842c70af
Merge pull request #777 from minivv/master-jdk17
【Simple设计器】流程模型->基本信息->谁可以发起,支持指定多个部门
2025-03-23 17:08:52 +08:00
YunaiV 3991647560 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/bpm 2025-03-23 17:06:54 +08:00
YunaiV b634a1e97b 【缺陷修复】CRM:修复跟进日志的操作日志记录失败 2025-03-23 16:54:48 +08:00
YunaiV 138239324c 【功能新增】AI:百川模型的接入 2025-03-23 12:48:13 +08:00
YunaiV 51d054c586 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/ai 2025-03-23 12:18:44 +08:00
YunaiV cd4813f7dd 【功能新增】AI:百川模型的接入 2025-03-23 12:18:37 +08:00
YunaiV ef5e56d560 【代码优化】AI:硅基流动的图片生成 2025-03-23 11:22:46 +08:00
YunaiV 59c744520a 【代码优化】AI:硅基流动的图片生成 2025-03-23 10:41:51 +08:00
YunaiV 813e7af846 【代码评审】AI:硅基流动的图片生成 2025-03-23 10:27:01 +08:00
芋道源码 5dc93cb872
!1294 【功能新增】AI:画图通用功能增加硅基流动平台
Merge pull request !1294 from 拽拽的哥/feature/ai
2025-03-23 01:41:53 +00:00
YunaiV 0c9dd34981 【功能修复】IOT:多个 ProductCategoryMapper 的名字冲突 2025-03-23 09:00:33 +08:00
YunaiV 113dfae732 【代码优化】BPM:1297 fix: 修复simple设计器第一个发起人节点,审批时校验是否存在审批人导致流程异常 2025-03-22 23:20:31 +08:00
芋道源码 26c1a10b0c
!1297 fix: 修复simple设计器第一个发起人节点,审批时校验是否存在审批人导致流程异常
Merge pull request !1297 from SamllNorth_Lee/feature/bpm
2025-03-22 14:51:58 +00:00
YunaiV 9b11199665 【功能新增】system:增加租户的下拉选择,用于登录界面 2025-03-22 09:41:22 +08:00
xiaoxin b2ec4d38a0 【优化代码】AI PPT:优化文多多、讯飞 API 2025-03-21 14:41:02 +08:00
lizhixian 629bf28495 fix:修复审批接口,校验任务规则为发起人自选时,先从历史变量中查询审批人。 2025-03-21 14:08:24 +08:00
zzt ecf4df8620 【功能新增】AI:腾讯图像创作 2025-03-20 08:04:32 +08:00
lizhixian f70a50472f fix:修复simple设计器第一个发起人节点,审批时校验是否存在审批人导致流程异常 2025-03-19 17:23:12 +08:00
lizhixian b6c700af6b fix:修复simple设计器第一个发起人节点,审批时校验是否存在审批人导致流程异常 2025-03-19 17:21:29 +08:00
smallNorthLee 41639d5dd7 review: 重构组装下一个节点审批人方法 2025-03-18 19:12:39 +08:00
xiaoxin 270fea0c5d 【解决 TODO 】AI PPT:解决一些 TODO 2025-03-18 14:41:06 +08:00
zzt 7b3401e216 【功能新增】AI:画图通用功能增加硅基流动平台 2025-03-18 00:22:15 +08:00
YunaiV acf68b1cec 【代码评审】AI:PPT API 的接入 2025-03-17 22:15:57 +08:00
芋道源码 1db3b867aa
!1293 【功能新增】AI:讯飞、文多多 PPT API 对接
Merge pull request !1293 from 小新/feature/ai
2025-03-17 13:52:02 +00:00
YunaiV 67e548d545 【代码评审】BPM:任务前置、后置通知 2025-03-17 21:37:15 +08:00
芋道源码 979485027d
!1291 review: 重构组装下一个节点审批人方法
Merge pull request !1291 from SamllNorth_Lee/feature/bpm
2025-03-17 13:28:25 +00:00
芋道源码 b2dd2148d3
!1292 feat: 任务前后置通知
Merge pull request !1292 from Lesan/feature/bpm-任务前后置通知
2025-03-17 13:26:27 +00:00
YunaiV 71add4b058 【代码评审】IoT:整体实现 2025-03-17 20:45:26 +08:00
YunaiV af62352fd9 【同步】jdk21 和 jdk8 的代码 2025-03-17 18:53:54 +08:00
YunaiV 0f4f5b484b Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceGroupService.java
2025-03-17 18:50:27 +08:00
YunaiV 6639d37132 【代码评审】IoT:整体实现 2025-03-17 18:50:12 +08:00
xiaoxin ecc3bd281c 【功能新增】AI:讯飞 PPT API 对接,测试用例完善 2025-03-17 15:44:17 +08:00
郑威 6fbcac3c13 【Simple设计器】流程模型->基本信息->谁可以发起,支持指定多个部门
指定部门可以在部门新增成员后无需重新修改相关流程
2025-03-17 15:41:28 +08:00
YunaiV 7119350a37 【同步】jdk21 和 jdk8 的代码 2025-03-17 13:37:52 +08:00
YunaiV de171c592a Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-03-17 13:19:44 +08:00
YunaiV e9a99c1e27 【代码评审】IoT:整体实现 2025-03-17 13:17:29 +08:00
YunaiV 77e64c217e Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	pom.xml
#	yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceStatusUpdateReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelSaveReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionPageReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/callback/EmqxCallback.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/client/EmqxClient.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/start/EmqxStart.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
#	yudao-server/src/main/resources/application-local.yaml
2025-03-17 13:16:59 +08:00
YunaiV 7c84ab9919 【代码评审】IoT:整体实现 2025-03-17 13:14:54 +08:00
xiaoxin c79273c5d6 【测试用例新增】AI:文多多 API 测试完善 2025-03-17 09:46:47 +08:00
Lesan 58c667f728 feat: 任务前后置通知 2025-03-17 08:54:34 +08:00
YunaiV eb7269083a Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-03-17 08:54:10 +08:00
YunaiV 638976dac8 【代码评审】IoT:整体实现 2025-03-16 23:15:32 +08:00
YunaiV a9733b4d2a 【代码评审】IoT:整体实现 2025-03-16 23:11:04 +08:00
YunaiV b6c7937aeb 【代码评审】IoT:OTA 的实现 2025-03-16 22:40:41 +08:00
smallNorthLee 7ed96c4c6c review: 重构组装下一个节点审批人方法 2025-03-16 22:32:42 +08:00
YunaiV 8203e074ac 【代码评审】IoT:OTA 的实现 2025-03-16 22:28:10 +08:00
smallNorthLee 8ed3066506 review: 重构组装下一个节点审批人方法 2025-03-16 21:41:47 +08:00
YunaiV 9dfe2f6fdf 【代码评审】IoT:OTA 的实现 2025-03-16 21:33:47 +08:00
YunaiV 44d7d623b3 【代码评审】IoT:OTA 的实现 2025-03-16 21:26:51 +08:00
芋道源码 08ff69d554
!1282 refactor(iot): 移除升级任务中的设备名称设置
Merge pull request !1282 from 陈玄礼/feature/iot-shelly
2025-03-16 13:03:05 +00:00
YunaiV 3b85adc754 【代码评审】IoT:数据桥梁的接入 2025-03-16 20:51:00 +08:00
芋道源码 3191d1bd1a
!1284 【代码优化】IoT: 数据桥梁代码优化
Merge pull request !1284 from puhui999/iot
2025-03-16 12:43:51 +00:00
YunaiV 0bdd000226 【代码评审】IoT:mqtt 协议的接入 2025-03-16 20:43:11 +08:00
YunaiV ba1e4f36b6 【同步】jdk21 和 jdk8 的代码 2025-03-16 17:27:05 +08:00
YunaiV 7609c74c8b Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java
2025-03-16 17:22:39 +08:00
YunaiV d597d0057e 【缺陷修复】全局:application-dev 配置文件,多了一个 spring 前缀 2025-03-16 17:04:04 +08:00
YunaiV c95f0c152d 【功能优化】全局:增加 methodArgumentNotValidExceptionExceptionHandler 对「组合校验」场景的兼容 2025-03-16 16:58:13 +08:00
YunaiV 8ccc55d1aa 【功能优化】商城:KdNiaoExpressClient 增加 requestType 配置,使用免费版,还是增值版 2025-03-16 16:45:48 +08:00
YunaiV 2dc8071faa 【功能优化】全局:增加 selectFirstOne 方法,解决容易出现并发场景下的查询 2025-03-16 16:31:36 +08:00
YunaiV 36165e72fc Merge branch 'feature/bpm' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17 2025-03-16 16:19:10 +08:00
YunaiV dc1c824749 【缺陷修复】BPM:processTaskAssigned 忽略数据权限,避免分配给 leader 的时候,因为没数据权限,导致查询不到 2025-03-16 15:29:50 +08:00
YunaiV 2ddf9d05e6 【缺陷修复】BPM:使用 DataPermissionUtils 替代 DataPermission,避免 this 调用无法生效的问题 2025-03-16 15:24:56 +08:00
YunaiV fc8e4662bb 【功能优化】限流的配置,增加 expire 过期,原因参见 https://t.zsxq.com/lcR0W 场景 2025-03-16 14:45:09 +08:00
YunaiV 7516738330 【缺陷修复】BPM:修复 task 的 category 不正确的问题 2025-03-16 13:52:33 +08:00
YunaiV bd93257a26 【缺陷修复】PAY:WxAppPayClient 返回结果不读id问题 2025-03-16 10:42:10 +08:00
YunaiV 2511f2c55b 【缺陷修复】BPM:“结束节点不能未空”文案部正确的问题 2025-03-15 22:40:31 +08:00
xiaoxin a82abed2b5 【功能新增】AI:对接文多多 v2 接口 2025-03-15 22:38:09 +08:00
YunaiV 803da9ed9e 【功能优化】System:componentName 重复校验,避免 vue3 router 初始化有问题 2025-03-15 21:37:18 +08:00
芋道源码 0debd8e069
!1247 【bugfix】新人券已关闭但是注册时仍然发放了update module/promotion/dal/mysql/coupon/CouponTemplateMapper.java.
Merge pull request !1247 from 山野羡民/N/A
2025-03-15 13:18:36 +00:00
YunaiV a4815b30d0 【缺陷修复】商城:修正商城中将会员等级关闭,还继续计算折扣价格 2025-03-15 21:16:53 +08:00
YunaiV 5aacefc00e 【缺陷修复】AI:新增对话进行问答时,toolNames cannot be null的问题 2025-03-15 21:07:34 +08:00
YunaiV bba36bfca9 【依赖升级】weixin-java from 4.6.0 to 4.7.2.B 2025-03-15 20:51:05 +08:00
YunaiV 664b1321d6 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-dependencies/pom.xml
2025-03-15 20:50:36 +08:00
YunaiV 075545c11e 【依赖升级】weixin-java from 4.6.0 to 4.7.2.B 2025-03-15 20:50:19 +08:00
YunaiV 0cc99b8279 【缺陷修复】升级 springdoc 1.7.0 到 1.8.0,解决 knife4j get 和 post 参数不正确的问题 2025-03-15 19:45:01 +08:00
YunaiV 937ae041bc Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-03-15 18:58:53 +08:00
YunaiV dd0cadd426 【缺陷修复】关闭 knife4j 增强,存在兼容性问题,悲伤 2025-03-15 18:58:02 +08:00
安浩浩 86e4379e62 【功能完善】IoT:新增 TDengine 相关依赖 2025-03-15 18:08:05 +08:00
安浩浩 81739186c9 【功能优化】IoT:重构上行请求处理逻辑,合并属性和事件上报处理,简化代码结构,删除冗余处理器 2025-03-15 17:56:45 +08:00
YunaiV 0ab54a9fe4 【代码评审】BPM:fix: 解决审批节点表单无可编辑字段时,variables流程变量值为空,流程节点流转异常问题 2025-03-15 16:48:05 +08:00
芋道源码 4e2ebe0c66
!1280 fix: 解决审批节点表单无可编辑字段时,variables流程变量值为空,流程节点流转异常问题
Merge pull request !1280 from SamllNorth_Lee/feature/bpm
2025-03-15 08:36:14 +00:00
芋道源码 b6f74f3b9b
!1285 fix: 代码评审修改
Merge pull request !1285 from Lesan/feature/bpm-流程前后置通知
2025-03-15 08:09:23 +00:00
YunaiV a9eaa3ed74 【同步】jdk21 和 jdk8 的代码 2025-03-15 13:49:04 +08:00
YunaiV 7da7c10b47 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskApproveReqVO.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/dept/BpmTaskCandidateStartUserSelectStrategy.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmHttpRequestTrigger.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmUpdateNormalFormTrigger.java
2025-03-15 13:43:34 +08:00
芋道源码 367e3b9880
!1286 2.4.2:工作流的更新
Merge pull request !1286 from 芋道源码/feature/bpm
2025-03-15 05:22:46 +00:00
YunaiV a193322373 更新 README:工作流(增加钉钉、飞书)能力 2025-03-15 13:16:31 +08:00
YunaiV 71216a50bf 更新 README:工作流(增加钉钉、飞书)能力 2025-03-15 13:15:36 +08:00
YunaiV 045fb584d2 【代码评审】BPM:子流程的想法 2025-03-15 11:21:29 +08:00
LesanOuO 25899d9988 fix: 代码评审修改 2025-03-15 10:45:45 +08:00
YunaiV 4364ef09c5 【代码评审】BPM:流程前后置通知 2025-03-15 08:24:57 +08:00
芋道源码 6f2e538927
!1283 feat: 流程前后置通知
Merge pull request !1283 from Lesan/feature/bpm-流程前后置通知
2025-03-15 00:04:55 +00:00
YunaiV 6e89d33d39 【依赖管理】全局:tika-core 从 3.1.0 降低到 2.9.3 版本,解决 jdk8 兼容性 2025-03-15 07:06:01 +08:00
YunaiV 2379e34012 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-03-15 07:02:23 +08:00
YunaiV d94e577943 【依赖管理】全局:tika-core 使用 3.1.0 确认 2025-03-15 07:00:39 +08:00
YunaiV 41640642d4 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts:
#	yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
2025-03-15 06:56:16 +08:00
安浩浩 348c138749 【功能完善】IoT:引入 IotStandardResponse 实体类,统一处理器的响应格式,优化错误处理逻辑 2025-03-15 00:26:44 +08:00
芋道源码 a8d7da329f
!1256 Spring AI 1.0.0 M6 适配:增加知识库、工具调用(function calling)、工作流、豆包/混元/硅基流动等模型的接入
Merge pull request !1256 from 芋道源码/feature/ai
2025-03-14 14:54:11 +00:00
YunaiV dd0f8a71c7 【功能新增】AI:更新菜单 SQL 2025-03-14 22:53:29 +08:00
YunaiV 9dbadbbb5d 【功能新增】AI:更新最新的 AI 介绍图 2025-03-14 22:12:31 +08:00
YunaiV 1e8845ce6d 【功能新增】AI:增加 AI 对话,与 tool 的打通 2025-03-14 21:11:28 +08:00
YunaiV e869aaee83 【功能新增】AI:增加函数的管理 2025-03-14 19:29:36 +08:00
puhui999 acd32f7b4e 【代码优化】IoT: 数据桥梁代码优化 2025-03-14 17:41:12 +08:00
puhui999 3756830b9c 【代码优化】IoT: 数据桥梁代码优化 2025-03-14 17:40:19 +08:00
puhui999 966357b44e 【代码优化】IoT: 数据桥梁测试代码抽离到测试类 2025-03-14 17:34:16 +08:00
lizhixian d3db32b44e fix:解决校验流程画布数据,极端情况下无用户任务节点导致的异常问题 2025-03-14 16:58:12 +08:00
YunaiV ffe4afaaaf 【功能新增】AI:新增 function call 示例,完成所有模型的测试 = = 累 2025-03-14 13:26:23 +08:00
Lesan e114a35451 feat: 流程前后置通知 2025-03-14 09:29:58 +08:00
陈玄礼 37c725c1a3 refactor(iot): 移除升级任务中的设备名称设置
- 删除了创建升级任务时设置设备名称的代码逻辑
- 优化了升级任务初始化过程,减少了不必要的设备名称查询和设置操作
2025-03-13 22:23:28 +08:00
陈玄礼 b87a583842 refactor(iot): 重构 OTA 升级模块
- 更新错误码定义,调整 OTA 相关错误码的编号和描述
- 移除未使用的 IotOtaFirmwareCommonReqVO 类- 优化 IotOtaFirmwareCreateReqVO 和 IotOtaFirmwareUpdateReqVO 的结构
- 删除冗余的 IotOtaUpgradeRecordCreateReqBO 类
- 重构 IotOtaUpgradeRecordMapper 的查询方法
- 更新 IotOtaUpgradeRecordService 接口,简化升级记录创建方法
- 删除未使用的 IotOtaUpgradeRecordJob 类
- 优化 IotOtaUpgradeRecordController 的重试接口,使用 PUT 方法
2025-03-13 22:16:45 +08:00
lizhixian be608b26e6 review: 代码重构 2025-03-13 16:22:58 +08:00
lizhixian c9690e144c fix: 解决审批节点表单无可编辑字段时,variables流程变量值为空,流程节点流转异常问题 2025-03-13 16:05:13 +08:00
YunaiV 25a0fe908a 【功能新增】AI:新增 function call 示例。会继续完善! 2025-03-13 12:51:50 +08:00
lizhixian 575e7a38f3 fix: 解决审批节点表单无可编辑字段时,variables流程变量值为空,流程节点流转异常问题 2025-03-13 09:38:15 +08:00
lizhixian 149cab1dac Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
2025-03-13 09:03:31 +08:00
YunaiV 34453a3f70 【代码评审】IoT:数据桥梁的维护 2025-03-13 08:30:27 +08:00
芋道源码 27e08266e0
!1269 【代码优化】IoT: 优化数据桥梁
Merge pull request !1269 from puhui999/iot
2025-03-13 00:18:30 +00:00
YunaiV 569d651481 【功能完善】IoT:增加 device config 配置 2025-03-13 08:17:31 +08:00
YunaiV 24261cf767 【代码评审】BPM:计算下一个节点的审批人(审批人自选) 2025-03-13 06:44:41 +08:00
YunaiV 9ae18fe53d 【问题修复】BPM:formConf、formFields 在 BpmProcessDefinitionRespVO 缺少的问题,导致无法发起流程 2025-03-13 06:25:16 +08:00
smallNorthLee c2789f628c fix: 解决审批节点表单无可编辑字段时,variables流程变量值为空,流程节点流转异常问题 2025-03-12 22:46:31 +08:00
smallNorthLee 23844b930c fix: 解决审批节点表单无可编辑字段时,variables流程变量值为空,流程节点流转异常问题 2025-03-12 22:42:32 +08:00
YunaiV f7ab30c50a 【功能新增】AI:新增 Dify、FastGPT 的接入例子 2025-03-12 21:50:07 +08:00
芋道源码 44083c96c3
!1276 fix: 发起流程报错,返回的VO缺少字段,icon为null时,copyTo转换异常问题
Merge pull request !1276 from SamllNorth_Lee/feature/bpm
2025-03-12 01:56:06 +00:00
smallNorthLee 42eb89b243 review:重构代码,校验选择的下一个节点的审批人,是否合法 2025-03-11 22:40:53 +08:00
smallNorthLee cc61bb1a61 review: 校验流程设计器第一个用户任务节点的规则类型是否为“审批人自选” 2025-03-11 22:37:23 +08:00
smallNorthLee 2123d7c067 remove: 删除错误代码 2025-03-11 21:28:29 +08:00
smallNorthLee 27ae2a4761 review: 父子类字段调整 2025-03-11 21:23:19 +08:00
lizhixian 494b80d1eb review: 优化审批时,校验选择的下一个节点的审批人,是否合法 2025-03-11 17:34:13 +08:00
lizhixian 26dd8b6670 fix:获取下一个节点审批人为空时,返回new HashMap<>(),避免下级使用空指针
review: 优化审批时,校验选择的下一个节点的审批人,是否合法
2025-03-11 17:11:41 +08:00
YunaiV 07fe6167e0 【功能新增】AI:接入 minimax 和 moonshot 月之暗灭(kimi) 2025-03-11 13:20:59 +08:00
YunaiV 99d5e7c509 【依赖升级】AI:spring-ai-alibaba-starter 升级到最新,解决流式返回报错的问题 2025-03-11 12:53:34 +08:00
lizhixian b6a9b5dda9 fix: 校验第一个用户任务节点的规则类型是否为“审批人自选” 2025-03-11 10:22:21 +08:00
YunaiV b9e8495712 【功能新增】AI:新增 AzureOpenAiEmbeddingModel、OpenAiEmbeddingModel 向量模型 2025-03-11 09:42:24 +08:00
YunaiV 20eb3013f2 【功能新增】AI:新增 QianFanEmbeddingModel 向量模型 2025-03-11 07:57:14 +08:00
YunaiV 3a3607e1cb 【功能新增】AI:新增 ZhiPuAiEmbeddingModel 向量模型 2025-03-11 07:49:54 +08:00
YunaiV d7e801c438 【功能新增】AI:知识库文档的模型变化时,触发重索引(异步) 2025-03-10 09:12:24 +08:00
smallNorthLee 4054e5fdec fix: 发起流程报错,返回的VO缺少字段 2025-03-09 22:28:13 +08:00
xiaoxin ea1d9f0075 【功能新增】AI:文多多对接 2025-03-09 21:43:45 +08:00
YunaiV 32e1ef4da8 【功能新增】AI:聊天记录返回时,增加 segments 2025-03-09 21:19:41 +08:00
YunaiV b709af11a1 【功能新增】AI:聊天记录返回时,增加 segments 2025-03-09 21:00:34 +08:00
YunaiV cddaca5863 【功能新增】AI:聊天时,增加知识库的拼接 2025-03-09 19:02:17 +08:00
puhui999 cdf316e778 【代码优化】IoT: 数据桥梁 config 优化 2025-03-09 18:04:46 +08:00
puhui999 b1d3b73b6d 【代码优化】IoT: 数据桥梁 config 优化 2025-03-09 13:29:12 +08:00
puhui999 ff9267ad75 【功能新增】IoT: 数据桥梁 CRUD 2025-03-09 12:53:54 +08:00
YunaiV 3bb57edc85 【功能新增】AI:聊天角色,新增 knowledge 的引用绑定 2025-03-09 12:00:04 +08:00
YunaiV 9126691ac0 【功能新增】AI:聊天角色,新增 document 的引用绑定 2025-03-09 11:51:19 +08:00
YunaiV f286a81392 【功能修复】AI:升级 tika 版本,解决 pdf 读取问题 2025-03-09 09:43:12 +08:00
YunaiV f2ee2008e6 【功能新增】AI:增加 MilvusVectorStore 向量库的接入 2025-03-09 09:27:33 +08:00
YunaiV 588c9fe323 【功能新增】AI:增加 RedisVectorStore 向量库的接入 2025-03-08 22:09:16 +08:00
安浩浩 e66c69932f 【功能完善】IoT: 更新设备属性映射逻辑,新增对 device_key 字段的处理 2025-03-08 21:59:54 +08:00
puhui999 415dd435f3 【代码优化】IoT: 数据桥梁的执行器根据引入的消息队列动态加载 2025-03-08 11:25:03 +08:00
puhui999 831970233c 【代码优化】IoT: 数据桥梁的执行器根据引入的消息队列动态加载 2025-03-08 10:50:22 +08:00
smallNorthLee e5c8be2b05 review: 优化TODO 2025-03-07 22:53:35 +08:00
安浩浩 824a801b39 【功能完善】IoT: 添加 Webhook 处理器以处理设备连接和断开事件,更新设备状态管理逻辑 2025-03-07 22:36:38 +08:00
YunaiV 44bcc9476d 【功能新增】AI:增加 QdrantVectorStore 向量库的接入 2025-03-06 22:22:22 +08:00
YunaiV 40b3c49495 【问题修复】 同一个人多个待办任务,获取待办任务,优先查询传递的 taskId 2025-03-06 08:01:23 +08:00
YunaiV 9ff56403d6 【代码评审】BPM:下一个审批人 2025-03-06 07:51:20 +08:00
芋道源码 8a5638bdea
!1271 feat:审批通过时,查询下一个执行节点,校验流程执行正确与否
Merge pull request !1271 from SamllNorth_Lee/feature/bpm
2025-03-05 23:14:07 +00:00
smallNorthLee 1b678bd7a9 feat: 新增校验 流程模型创建时第一个用户任务的规则类型不能是审批人自选 2025-03-05 21:41:01 +08:00
smallNorthLee 847e51269b feat: 新增校验 流程模型创建时第一个用户任务的规则类型不能是审批人自选 2025-03-05 21:40:44 +08:00
lizhixian a23ce60041 review: 代码审查 2025-03-05 12:39:43 +08:00
lizhixian ead8e94deb review: 代码审查 2025-03-05 12:37:32 +08:00
lizhixian 672a5ef538 review: 代码审查 2025-03-05 12:30:38 +08:00
lizhixian 1e2b56256c review: 代码审查 2025-03-05 09:25:00 +08:00
smallNorthLee 1f9769a432 review: 拆分发起人自选审批人 和 审批人选择下一个节点审批人 2025-03-05 00:36:48 +08:00
smallNorthLee 1e3fd24d65 review: 流程发起时,只预测类型为发起人自选的节点信息 2025-03-04 23:18:19 +08:00
jason d1fead11da Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm 2025-03-04 23:17:52 +08:00
jason ffa7c246cf 【问题修复】 同一个人多个待办任务,获取待办任务,优先查询传递的 taskId 2025-03-04 23:17:35 +08:00
YunaiV 6ccd0ca61e 【代码优化】AI:优化 pom 依赖的说明 2025-03-04 23:12:24 +08:00
smallNorthLee ebd722cb41 review: 修改获取下一个执行的流程节点接口地址和方法 2025-03-04 22:59:22 +08:00
smallNorthLee c16f7b8154 review: 24行 2025-03-04 22:54:44 +08:00
smallNorthLee 9e151b3966 review: 278 281行 2025-03-04 22:28:25 +08:00
smallNorthLee 4e57bd157f review: 27行 2025-03-04 22:09:11 +08:00
smallNorthLee dadd43677e review: 51行 2025-03-04 22:07:58 +08:00
YunaiV cc24eca470 【代码重构】AI:“聊天模型”重构为“模型”,支持 type 模型类型 2025-03-04 20:19:30 +08:00
YunaiV 71b45a29a3 【代码评审】IoT:MQTT 插件 2025-03-04 20:13:19 +08:00
smallNorthLee 6e2d00d561 feat:审批通过时,查询下一个执行节点,校验流程执行正确与否 2025-03-03 22:38:05 +08:00
YunaiV 433e91da8e 【代码重构】AI:“聊天模型”重构为“模型”,支持 type 模型类型 2025-03-03 21:55:49 +08:00
puhui999 7ab61b6d06 【代码优化】IoT: kafka 数据桥梁消息等待的最大时间调整为 10 秒 2025-03-03 21:50:52 +08:00
YunaiV 1c9c9790cd 【代码重构】AI:“聊天模型”重构为“模型”,支持 type 模型类型 2025-03-03 21:48:22 +08:00
YunaiV 89d079349c 【代码重构】AI:“聊天模型”重构为“模型”,支持 type 模型类型 2025-03-03 21:26:31 +08:00
smallNorthLee d41cce94cd feat:审批通过时,查询下一个执行节点,校验流程执行正确与否 2025-03-03 21:24:13 +08:00
lizhixian 33ab961629 feat:审批通过时,查询下一个执行的任务节点 2025-03-03 17:36:13 +08:00
puhui999 ce5e64e0aa 【代码优化】IoT: 优化数据桥梁的执行器减少子类代码冗余 2025-03-03 13:03:41 +08:00
puhui999 3b54deb989 【代码优化】IoT: 优化数据桥梁的执行器减少子类代码冗余 2025-03-03 12:48:07 +08:00
puhui999 61ea09488e 【代码优化】IoT: 优化数据桥梁执行器抽象类增加泛型,减少子类类型强转 2025-03-03 12:22:19 +08:00
smallNorthLee 1b08e6828f feat:新增获取下一个执行的流程节点接口 2025-03-02 22:31:06 +08:00
YunaiV 3f460dc620 【功能新增】AI:新增知识库分段的新增 2025-03-02 21:52:31 +08:00
smallNorthLee 9dfed5365b feat:
新增:审批人自选标识,
新增:审批人自选策略,
新增:获得流程实例的审批用户选择的下一个节点的审批人
新增:错误码1_009_004_007,下一个节点审批人未配置
2025-03-02 21:06:28 +08:00
YunaiV 5f5e77a392 【功能新增】AI:新增 document 向量的进度查询 2025-03-02 20:54:02 +08:00
安浩浩 3c9985978b 【功能完善】IoT: 更新 MQTT 主题配置为数组,重构 EMQX 认证逻辑,优化异常处理和响应格式 2025-03-02 20:47:50 +08:00
YunaiV d8a7d668a4 【功能新增】BPM:支持通过“历史”进行恢复 2025-03-02 09:56:54 +08:00
YunaiV c6b58b0ebf 【代码评审】IoT:数据桥梁实现 2025-03-01 23:58:16 +08:00
芋道源码 6a1798bf6a
!1255 【功能新增】IoT: 新增 Kafka、RabbitMQ、RedisStreamMQ 数据桥梁实现
Merge pull request !1255 from puhui999/iot
2025-03-01 15:36:14 +00:00
YunaiV 53693529e1 【代码评审】IoT:首页统计 2025-03-01 23:30:47 +08:00
芋道源码 8bcfd40847
!1266 对IOT首页功能的code review的修改
Merge pull request !1266 from alwayssuper/feature/iot
2025-03-01 14:40:50 +00:00
smallNorthLee 4d35a272c3 feat: 新增常量PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES 2025-03-01 22:30:40 +08:00
YunaiV 9927dd4439 【功能新增】BPM:增加流程定义的 simple 接口 2025-03-01 20:39:23 +08:00
smallNorthLee 3cf0708f64 review: 代码审查,方法抽取 2025-03-01 20:36:01 +08:00
smallNorthLee 8a3264cfd3 review: 代码审查,方法抽取 2025-03-01 20:22:50 +08:00
smallNorthLee 5e15a100cb review: 代码审查 2025-03-01 19:47:16 +08:00
puhui999 cb16539b66 【功能新增】IoT: 新增 Redis Stream MQ 数据桥梁实现 2025-03-01 17:43:46 +08:00
YunaiV fedb9242b5 【代码评审】BPM:下一个审批人 2025-03-01 16:34:30 +08:00
芋道源码 10d7cbb9af
!1267 feat: 审批通过时,校验节点是否为下一个执行节点
Merge pull request !1267 from SamllNorth_Lee/fix/bpm
2025-03-01 07:48:40 +00:00
YunaiV ebd93514b3 【功能新增】AI:新增 document 向量的进度查询 2025-03-01 13:35:00 +08:00
YunaiV a998168b3b 【功能新增】AI:新增知识库文档的更新信息与状态 2025-03-01 11:42:11 +08:00
YunaiV d1e207899a 【功能新增】AI:知识库,新增切片接口 2025-03-01 07:48:16 +08:00
smallNorthLee ff555b5136 feat: 审批通过时,校验节点是否为下一个执行节点 2025-02-28 22:37:57 +08:00
YunaiV e5cc9d2ad8 【代码优化】AI:知识库的索引过程 2025-02-28 18:57:17 +08:00
puhui999 7b449b81e7 【功能新增】IoT: 新增 RabbitMQ 数据桥梁实现 2025-02-28 18:03:34 +08:00
lizhixian deef88f56f feat:审批通过时,校验节点是否为下一个执行节点 2025-02-28 17:10:59 +08:00
alwayssuper 0f0ebda469 [fix]:iot home count 2025-02-28 15:28:38 +08:00
puhui999 69a27b1ee2 【功能新增】IoT: 新增 Kafka 数据桥梁实现 2025-02-28 14:46:02 +08:00
芋道源码 79d5c5e2df
!1264 fix: 代码评审修改
Merge pull request !1264 from Lesan/feature/bpm-子流程
2025-02-28 05:28:23 +00:00
Lesan 5b88d88177 fix: 代码评审修改 2025-02-28 09:35:43 +08:00
Lesan 8df3a2d950 fix: 代码评审修改 2025-02-28 09:29:56 +08:00
YunaiV 7918ba7d29 【功能新增】AI:新增知识库文档的批量添加 2025-02-28 08:16:44 +08:00
YunaiV 0a8c75625a 【代码重构】AI:知识库相关的表结构 2025-02-28 07:43:43 +08:00
smallNorthLee 093e563b80 feat: add TODO 2025-02-27 23:33:16 +08:00
陈玄礼 4e33cd2bde refactor(iot): 优化 OTA 相关 Mapper 接口的文档注释
- 移除了多余的 TODO 注释
- 更新了 IotOtaFirmwareMapper、IotOtaUpgradeRecordMapper 和 IotOtaUpgradeTaskMapper 的类注释
- 统一了注释格式,增加了作者信息
2025-02-27 23:28:04 +08:00
陈玄礼 4629084c1b refactor(iot): 重构升级记录状态更新逻辑
- 修改 IotOtaUpgradeRecordMapper 中的 cancelUpgradeRecordByTaskId 方法- 新增 updateUpgradeRecordStatusByTaskIdAndStatus 方法,用于更通用的状态更新
- 在 IotOtaUpgradeRecordServiceImpl 中调用新方法来取消升级记录
2025-02-27 23:18:25 +08:00
陈玄礼 0302ebee99 refactor(iot): 优化 OTA 升级记录查询方法
- 重写 getOtaUpgradeRecordCount 和 getOtaUpgradeRecordStatistics 方法,使用 MyBatis-Plus 的 LambdaQueryWrapperX
-移除 XML 中对应的 SQL 查询语句
- 提高代码可维护性和数据库兼容性
2025-02-27 23:07:09 +08:00
lizhixian 6c6992c86a feat:TODO List 2025-02-27 17:28:22 +08:00
lizhixian db6d7a7430 feat:添加TODO描述 2025-02-27 15:17:30 +08:00
YunaiV 6e1ec8b3eb 【代码评审】IoT:首页统计 2025-02-27 13:30:39 +08:00
YunaiV 2a65e3bd2e Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot 2025-02-27 12:50:33 +08:00
芋道源码 3aef51f811
!1263 【新增】:IOT首页的数据统计
Merge pull request !1263 from alwayssuper/feature/iot
2025-02-27 04:50:24 +00:00
YunaiV 36dd18d41f 【代码评审】IoT:MQTT 插件 2025-02-27 12:45:42 +08:00
alwayssuper 6cf7a67406 [fix]:iot home count 2025-02-27 10:52:28 +08:00
YunaiV 074146c991 【代码评审】BPM:触发器 HTTP 异步 2025-02-27 09:56:34 +08:00
jason 62a1fa8296 Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm 2025-02-27 09:03:06 +08:00
jason 0565db2f2d 【代码评审修改】 异步 http 触发器修改为 Http 回调触发器 2025-02-27 06:40:02 +08:00
smallNorthLee b030257466 review: 代码审查 修改方法名称validateNextAssignees 2025-02-26 23:24:21 +08:00
安浩浩 006ef40c4b 【功能完善】IoT: 添加 MQTT 主题非法错误码,重构设备服务调用和属性设置逻辑,优化 MQTT 消息处理流程 2025-02-26 22:54:44 +08:00
smallNorthLee 357f4966d3 review: 代码审查 修改方法名称validateNextAssignees 2025-02-26 22:38:31 +08:00
YunaiV e892dcabac 【代码评审】BPM:子流程的多实例 2025-02-26 21:45:47 +08:00
YunaiV 3c0b9262d7 【代码评审】BPM:触发器 HTTP 异步 2025-02-26 21:34:52 +08:00
芋道源码 35f0d689f1
!1262 feat: 子流程-多实例
Merge pull request !1262 from Lesan/feature/bpm-子流程
2025-02-26 13:30:40 +00:00
lizhixian 13c2d36eee feat:添加流程审批时校验,是否为下一个流程审批的节点 2025-02-26 17:45:35 +08:00
alwayssuper 8daa2131ba [fix]:iot home count 2025-02-26 16:49:29 +08:00
lizhixian 37b2fd4789 feat:调整字段名称 2025-02-26 15:59:42 +08:00
Lesan 8a9d64bbaf feat: 子流程-多实例 2025-02-26 15:18:34 +08:00
Lesan 9c9f2812e9 fix: 添加buildTimeoutBoundaryEvent方法 2025-02-26 08:59:54 +08:00
alwayssuper 9f8c6a944c Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into origin/feature/iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
2025-02-26 08:36:27 +08:00
Lesan 0d886dc42b fix: 添加必要注释 2025-02-26 08:29:09 +08:00
jason 3f1cd80573 Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
2025-02-25 22:26:25 +08:00
jason 5e31062d6b 【代码评审修改】 异步 http 触发器代码评审修改 2025-02-25 22:23:12 +08:00
lizhixian b2ca263067 feat:添加描述 2025-02-25 16:29:35 +08:00
lizhixian f2909d6bb6 feat:新增自选节点审批人参数,由前端传递下个节点选择的审批人 2025-02-25 16:27:05 +08:00
YunaiV 197c4ad9bf 【功能修复】INFRA:错误日志、访问日志,params 过长的问题 2025-02-25 13:17:27 +08:00
YunaiV 48c976cf0a 【代码评审】BPM:子流程的超时 2025-02-25 12:41:30 +08:00
安浩浩 4cefea6880 【功能完善】IoT: 添加 MQTT 消息处理器,重构设备属性和事件上报逻辑,优化消息处理流程 2025-02-25 09:51:39 +08:00
芋道源码 f7e4293ed2
!1254 BPM-子流程
Merge pull request !1254 from Lesan/feature/bpm-子流程
2025-02-25 01:46:09 +00:00
安浩浩 4746281df9 【功能完善】IoT: 更新 MQTT 主题配置,重构设备属性和事件上报处理逻辑,优化消息处理流程 2025-02-25 08:50:02 +08:00
安浩浩 4015e7905f 【功能完善】IoT: 更新 MQTT 客户端逻辑,重构消息处理和重连机制,优化配置文件 2025-02-25 08:14:19 +08:00
YunaiV d0fbb7677c 【代码评审】BPM:触发器 HTTP 异步 2025-02-25 07:56:05 +08:00
smallNorthLee e11529375e feat: 审批时查询下一个节点的类型是否为自选审批人是否已选择了审批人,否则由前端传递 2025-02-24 22:56:18 +08:00
YunaiV deca69ada6 【功能优化】AI:DispatcherType.ASYNC 时,不进行认证,解决 Spring AI SSE 的认证问题
https://github.com/YunaiV/yudao-cloud/issues/197
2025-02-24 21:28:15 +08:00
YunaiV a7e5aaec3b 【代码新增】AI:轨迹流动的接入 2025-02-24 21:19:44 +08:00
lizhixian 45a72f4cd8 fix:审批接口添加审批人参数 2025-02-24 17:15:17 +08:00
lizhixian 5d16355042 fix:
1、预测节点审批人查询,如果不存在,则直接返回空,避免类型转换异常
2、如果processVariables不为空,则使用前端传递的参数值
2025-02-24 16:31:03 +08:00
Lesan 15d0a11bad feat: 子流程-超时设置 2025-02-24 15:30:15 +08:00
jason fda6aff8af 【功能优化】 异步 http 请求触发器外部回调 controller 接口 2025-02-24 13:25:22 +08:00
jason a42ad08bc9 【功能优化】 异步 http 请求触发器外部回调 controller 接口 2025-02-24 13:20:52 +08:00
YunaiV 117470998e 【代码新增】AI:增加混元、通义的 deepseek 测试案例 2025-02-24 12:41:14 +08:00
puhui999 1b15fb3845 【代码优化】IoT: 优化数据桥接缓存实现 2025-02-24 10:46:38 +08:00
Lesan dee2b7cb96 fix: 代码审查修改 2025-02-24 09:38:37 +08:00
YunaiV a1d5602c40 【代码新增】AI:适配腾讯混元大模型、知识引擎(deepseek) 2025-02-23 21:14:53 +08:00
smallNorthLee f45758b8fd feat: 审批校验自选审批人节点是否存在审批人 2025-02-23 20:12:05 +08:00
YunaiV 46726fe67c 【代码新增】AI:适配字节豆包 doubao、deepseek 2025-02-23 20:00:54 +08:00
YunaiV 875cfa10c6 【代码新增】AI:适配 提供 OllamaChatModelTests,用于本地 ollma 模型的调用 2025-02-23 19:22:48 +08:00
YunaiV 4ee638db87 【代码优化】AI:适配 Spring AI 1.0.6 对 sd、mj 的兼容 2025-02-23 18:47:35 +08:00
YunaiV 430dc99d12 【代码优化】AI:适配 Spring AI 1.0.6 对 ZhiPu 的兼容 2025-02-23 18:29:33 +08:00
YunaiV c96d966a41 【代码优化】AI:无法适配 Spring AI 1.0.6 对百度 QianFan 的逻辑:无语!!! 2025-02-23 17:57:59 +08:00
YunaiV d05a7bd59a 【代码优化】AI:适配 Spring AI 1.0.6 对 Ollama 的逻辑 2025-02-23 17:33:53 +08:00
YunaiV 5655ae925c 【代码优化】AI:适配 Spring AI 1.0.6 对 OpenAI 的逻辑 2025-02-23 17:19:19 +08:00
jason 8c681a77f5 Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm
# Conflicts:
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
2025-02-22 22:53:49 +08:00
jason 3f8221ba84 【功能新增】 新增异步 http 请求触发器 2025-02-22 22:51:56 +08:00
安浩浩 53697b55c2 【功能完善】IoT: 更新 EMQX 插件配置,添加 MQTT 连接参数,重构相关逻辑 2025-02-22 22:50:37 +08:00
YunaiV 8cf8af1f6d 【代码评审】IoT:固件管理 2025-02-22 19:51:13 +08:00
芋道源码 ebfe35c787
!1243 feat(iot): 添加 OTA 固件管理功能
Merge pull request !1243 from 陈玄礼/feature/iot-ota-shelly
2025-02-22 10:36:03 +00:00
YunaiV f76843573e 【代码评审】IoT:数据桥梁的执行器抽离 2025-02-22 18:31:09 +08:00
芋道源码 672247dbe4
!1248 【代码优化】IoT: 基于 guava 对 producer 做 cache
Merge pull request !1248 from puhui999/iot
2025-02-22 10:22:16 +00:00
YunaiV fa40ae1dbd 【代码评审】IoT:MQTT 连接参数 2025-02-22 18:21:18 +08:00
芋道源码 2a9dffb6ed
!1246 【性能优化】循环中减少不必要的查询 update r/yudao/module/promotion/service/coupon/CouponServiceImpl.java.
Merge pull request !1246 from 山野羡民/N/A
2025-02-22 09:42:57 +00:00
YunaiV 254b55778f 【代码评审】BPM:子流程 2025-02-22 17:17:27 +08:00
alwayssuper 6d059eae61 [fix]:statistics 2025-02-22 16:58:47 +08:00
芋道源码 10bbe741b0
!1249 feat: 子流程
Merge pull request !1249 from Lesan/feature/bpm-子流程
2025-02-22 08:39:26 +00:00
YunaiV 7a6d1bdd79 【代码评审】BPM:删除表单数据触发器 2025-02-22 16:20:04 +08:00
YunaiV 7ef73b7d09 【代码重构】AI:spring ai 依赖,升级到 1.0.0-M6 2025-02-22 10:47:18 +08:00
YunaiV 3b7b81829d 【代码重构】AI:使用 alibaba ai 替代 tongyi 的实现 2025-02-22 09:22:58 +08:00
jason b88c09f48d Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm 2025-02-21 22:42:10 +08:00
jason cbdc081cfe 【功能优化】 删除表单数据触发器 2025-02-21 22:41:49 +08:00
Lesan 11858ca0dd feat: 子流程-子流程发起人 2025-02-21 15:40:23 +08:00
Lesan 0e48458ef7 feat: 子流程-添加高亮 2025-02-21 14:04:00 +08:00
YunaiV f582c9cfa3 【代码重构】AI:使用 OpenAiApi 接入 deepseek 2025-02-21 13:46:54 +08:00
Lesan 9698fee364 feat: 子流程 2025-02-21 09:52:43 +08:00
YunaiV 22801802ac 【代码重构】AI:使用 OpenAiApi 接入星火 2025-02-21 09:50:28 +08:00
安浩浩 8043ce612f 【功能新增】IoT: 添加 IoT 设备 MQTT 连接参数响应 VO,包含客户端 ID、用户名和密码字段 2025-02-20 18:31:34 +08:00
安浩浩 ca95752266 【功能新增】IoT: 添加 EMQX 插件,支持设备连接认证和 MQTT 连接参数获取,优化配置文件 2025-02-20 18:30:57 +08:00
puhui999 4be18af236 【代码优化】IoT: 基于 guava 对 producer 做 cache 2025-02-20 18:21:52 +08:00
puhui999 0400932260 【代码优化】IoT: 数据桥梁的执行器抽离 2025-02-20 17:44:06 +08:00
YunaiV c8485a1d6d 【代码评审】IoT:移除 tongyi 库,准备换到 alibaba ai 库 2025-02-20 12:49:06 +08:00
山野羡民 db9534073b
【bugfix】新人券已关闭但是注册时仍然发放了update module/promotion/dal/mysql/coupon/CouponTemplateMapper.java.
Signed-off-by: 山野羡民 <liyujiang_tk@yeah.net>
2025-02-20 02:43:13 +00:00
山野羡民 12170402e2
【性能优化】循环中减少不必要的查询 update r/yudao/module/promotion/service/coupon/CouponServiceImpl.java.
Signed-off-by: 山野羡民 <liyujiang_tk@yeah.net>
2025-02-20 02:39:48 +00:00
Shelly Chan 54381e29a7 feat(iot): 添加 OTA 固件管理功能
- 新增 OTA 固件相关错误码
- 实现 OTA 固件创建、更新和查询接口
- 添加 OTA 升级记录相关功能
- 实现 OTA 固件升级任务定时处理
2025-02-20 01:05:41 +08:00
YunaiV 8e7bbfe0da 【代码评审】IoT:rocketmq 数据桥接的接入 2025-02-19 22:42:19 +08:00
芋道源码 41c41bc6c3
!1241 【功能新增】IoT: 数据桥梁增加 RocketMQConfig 配置,实现executeRocketMQ 发送消息
Merge pull request !1241 from puhui999/iot
2025-02-19 14:38:10 +00:00
YunaiV ceba5b8cec 【代码评审】BPM:优化流程发起预测节点审批人是否配置在后端逻辑中实现 2025-02-19 22:35:39 +08:00
YunaiV 24f1ce16c7 【代码评审】BPM:优化流程发起预测节点审批人是否配置在后端逻辑中实现 2025-02-19 22:20:12 +08:00
芋道源码 b496ec3fd0
!1238 fix: 修复流程预测节点错误问题
Merge pull request !1238 from SamllNorth_Lee/fix/bpm
2025-02-19 14:03:56 +00:00
smallNorthLee eaa15b24ff review: 代码审查 2025-02-19 21:05:14 +08:00
smallNorthLee 248127a941 review: 代码审查 2025-02-19 20:01:38 +08:00
puhui999 add90365df 【功能新增】IoT: 数据桥梁增加 RocketMQConfig 配置,实现executeRocketMQ 发送消息 2025-02-19 15:51:34 +08:00
lizhixian 642e72ae7a review: 代码审查 2025-02-19 15:02:04 +08:00
lizhixian 29a902f37e review: 代码审查 2025-02-19 15:00:28 +08:00
lizhixian 4b89f68936 review: 代码审查 2025-02-19 14:13:08 +08:00
lizhixian cb3467ada2 review: 代码审查 2025-02-19 14:11:42 +08:00
芋道源码 243ce1ff4b
!1240 fix: Simple模型抄送节点在流程预测时未显示抄送人
Merge pull request !1240 from Lesan/feature/bpm-fix
2025-02-19 05:38:13 +00:00
YunaiV 009f1889a9 【代码评审】BPM:触发器,修改节点的评审 2025-02-19 12:55:17 +08:00
Lesan 3017933710 fix: Simple模型抄送节点在流程预测时未显示抄送人 2025-02-19 10:04:05 +08:00
lizhixian 9a83515c05 fix: 流程发起预测节点审批人是否配置在后端逻辑中实现 2025-02-18 16:06:51 +08:00
lizhixian 23ed5b780f fix: 移除节点参数,预测节点审批人是否配置在后端逻辑中实现 2025-02-18 14:13:49 +08:00
lizhixian 1f6f00164a fix: 修复流程预测错误问题 2025-02-18 10:00:36 +08:00
smallNorthLee 3265df7548 fix: 修复流程预测节点错误问题
fix: 补充校验规则,流程创建时只校验预测节点的审批人是否配置
2025-02-17 22:41:15 +08:00
smallNorthLee c68ab33dfd fix: 修复流程预测节点错误问题
fix: 补充校验规则,流程创建时只校验预测节点的审批人是否配置
2025-02-17 22:13:42 +08:00
lizhixian 5e277e020f fix: 解决流程预测审批节点错误问题 2025-02-17 16:11:00 +08:00
lizhixian 296e6ab3ad fix: 调整获得审批详情接口请求方式和参数类型,流程变量参数使用get请求传递错误 2025-02-17 16:04:52 +08:00
lizhixian 8651f2f649 fix: 添加nodeIds参数,只校验预测轨迹下的节点审批人 2025-02-17 16:03:14 +08:00
lizhixian 1023afda40 fix: 修复流程分支节点预测问题 2025-02-17 10:28:11 +08:00
lizhixian 3d20ce1a9b fix: 修复流程分支节点预测问题 2025-02-17 09:52:09 +08:00
jason 1f2222cf83 Merge remote-tracking branch 'origin/feature/bpm' into feature/bpm 2025-02-16 08:47:31 +08:00
jason 9a4bb60a78 【功能优化】 修改表单触发器增加条件设置 2025-02-16 08:47:13 +08:00
YunaiV 21a9d37f97 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro 2025-02-15 10:03:12 +08:00
YunaiV 3c10dcf392 【功能修复】MALL:管理后台,无法查询到订单的情况 2025-02-15 10:02:48 +08:00
YunaiV a4e090383b 【功能新增】BPM:已完成的列表,强制移除自动完成的“发起人”节点 2025-02-15 09:40:02 +08:00
YunaiV 56ea9d2381 【代码优化】BPM:修复停用状态下的流程删除报错问题 2025-02-15 09:21:44 +08:00
芋道源码 64ea9906ef
!1235 fix: 修复停用状态下的流程删除报错问题
Merge pull request !1235 from SamllNorth_Lee/fix/bpm
2025-02-15 01:18:50 +00:00
YunaiV e9a3773b72 【代码评审】BPM:办理人的逻辑 2025-02-15 08:48:51 +08:00
芋道源码 04fc7404e1
!1234 BPM-办理人
Merge pull request !1234 from Lesan/feature/bpm-办理人
2025-02-15 00:37:30 +00:00
YunaiV 75bca650da 【代码评审】IoT:增加相关待定项 2025-02-15 08:29:50 +08:00
lizhixian 045a224c22 fix: 修复停用状态下的流程删除报错问题 2025-02-14 15:51:57 +08:00
安浩浩 3ab7ad484a 【功能完善】IoT: 增强插件启动和停止逻辑,添加异常处理,更新错误码,优化配置文件 2025-02-14 09:34:25 +08:00
Lesan 00eea85a69 chore: 添加必要注释 2025-02-14 08:31:15 +08:00
Lesan ef29682230 feat: 添加节点类型以区分不同节点 2025-02-14 08:22:04 +08:00
YunaiV 8826f92d9d 【代码评审】BPM:移除流程图标非空校验,还是需要 URL 格式的校验 2025-02-13 19:59:01 +08:00
芋道源码 e79494a429
!1233 fix: 移除流程图标非空校验
Merge pull request !1233 from SamllNorth_Lee/fix/bpm
2025-02-13 11:58:15 +00:00
smallNorthLee 94499c0e5f fix: 移除流程图标非空校验 2025-02-13 19:49:49 +08:00
Lesan 7cf55c5300 fix: 添加节点类型以区分不同节点 2025-02-13 09:33:12 +08:00
芋道源码 ec71cd94e8
!1226 替换javax为jakarta
Merge pull request !1226 from 冰是睡着的水/N/A
2025-02-12 10:53:57 +00:00
YunaiV f289432890 【代码评审】BPM:办理人的逻辑 2025-02-12 18:46:40 +08:00
芋道源码 25c277fbf0
!1228 BPM设计器-办理人节点
Merge pull request !1228 from Lesan/feature/bpm-办理人
2025-02-12 10:21:58 +00:00
YunaiV c27b02beb6 【代码评审】IoT:增加相关待定项 2025-02-12 18:19:53 +08:00
Lesan e5aede6265 feat: 办理人节点高亮处理 2025-02-12 14:10:20 +08:00
Lesan 0085b42518 feat: 办理人节点 2025-02-12 13:53:15 +08:00
冰是睡着的水 2ab2e45465
替换javax为jakarta
Signed-off-by: 冰是睡着的水 <850083043@qq.com>
2025-02-11 06:15:30 +00:00
YunaiV d116e5eec1 【代码评审】IoT:物模型的维护 2025-02-09 07:26:01 +08:00
芋道源码 88ec5269d9
!1223 【代码优化】IoT: 物模型
Merge pull request !1223 from puhui999/iot
2025-02-08 23:23:34 +00:00
YunaiV bb11fdd3fa Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
2025-02-09 07:23:17 +08:00
YunaiV bc9b3715b1 【功能新增】IoT:设备拓扑图的添加 2025-02-08 21:44:49 +08:00
YunaiV 4254c06c37 【功能新增】IoT:设备注册 sub register 逻辑 2025-02-08 20:56:16 +08:00
YunaiV 5f7bb8041f 【功能新增】IoT:设备注册 register 逻辑 2025-02-08 19:31:50 +08:00
puhui999 6abd67a38c 【代码优化】IoT: 物模型 2025-02-08 17:31:11 +08:00
YunaiV d718f80108 【代码评审】IoT:plugin 相关的实现 2025-02-08 07:39:48 +08:00
YunaiV 724512399a 【功能新增】IoT:动态脚本 js、groovy demo 2025-02-08 07:29:17 +08:00
YunaiV 4919439b96 【功能新增】IoT:OTA 升级的下行消息的实现 2025-02-07 21:18:57 +08:00
YunaiV 795e06bc8f 【功能修复】IoT:插件还是考虑支持多租户,因此需要忽略部分场景下的租户,避免报错 2025-02-07 21:06:03 +08:00
puhui999 cf40cce552 【代码优化】S3FileClient 2025-02-07 18:10:03 +08:00
YunaiV 8fac009d4b 【功能优化】IoT:基于 review 修改 ota 的表结构设计 2025-02-07 09:44:41 +08:00
YunaiV 8ced4a0a2c 【功能新增】IoT:增加 ota 的表结构设计(100%) 2025-02-06 22:00:34 +08:00
puhui999 f141d64eb2 【依赖升级】AWS SDK for Java 1.x to 2.x 2025-02-06 16:05:56 +08:00
YunaiV 7bcbe9a243 Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot 2025-02-05 23:17:20 +08:00
YunaiV 00edd5a724 【功能新增】IoT:增加 ota 的表结构设计(90%) 2025-02-05 23:15:43 +08:00
安浩浩 6eadbba345 【代码重构】IoT:重构插件配置管理,替换 PluginInfo 为 PluginConfig 2025-02-05 21:44:23 +08:00
YunaiV b46e630912 【代码评审】IoT:plugin 相关的实现 2025-02-04 17:34:04 +08:00
YunaiV d23be86164 【代码评审】IoT:物模型的实现 2025-02-04 16:35:55 +08:00
YunaiV d24e3ad773 【功能新增】IoT:增加 alert 告警相关的表结构 2025-02-04 13:41:52 +08:00
YunaiV f6f162ad2f 【功能新增】IoT:增加 IotRuleSceneJob 执行定时任务 2025-02-04 12:39:56 +08:00
YunaiV 8d0caaa16c 【功能新增】IoT:基于 Quartz 实现 IotSchedulerManager!为了兼容 boot 和 cloud! 2025-02-04 00:12:08 +08:00
YunaiV 2109449a89 【功能优化】IoT:增加有状态的 Bridge 实现思路 2025-02-03 20:06:18 +08:00
YunaiV 7168e60fdd 【功能新增】IoT:实现 IotRuleSceneDataBridgeAction 的 http 部分的逻辑 2025-02-03 18:33:43 +08:00
YunaiV 5e71d1fc85 【代码优化】IoT:增加 IotDataBridgeDO 数据桥梁的定义 2025-02-03 13:25:47 +08:00
YunaiV 48cfcdadc1 【代码优化】IoT:实现规则 IotRuleSceneDeviceControlAction 执行器 2025-02-03 12:05:13 +08:00
YunaiV 4f84182dab 【代码优化】IoT:简化 isTriggerConditionParameterMatched 方法,完善注释,提升可读性(虽然多了一些计算) 2025-02-02 22:21:53 +08:00
YunaiV 910bb6ca3c 【代码新增】IoT:完善 IotRuleSceneServiceImpl 的规则匹配计算,isTriggerConditionParameterMatched 函数有点长,= = 捉摸咋优化下 2025-02-02 22:08:34 +08:00
YunaiV a4be3bb84d 【代码新增】IoT:增加 IotRuleSceneMessageHandler 处理规则场景,尝试基于 Spring El 表达式实现初步计算(部分场景) trigger 条件匹配 2025-02-02 19:44:38 +08:00
YunaiV 06749a18fc 【代码新增】IoT:增加规则引擎的 IotRuleSceneDO 场景联动的实体 2025-02-01 20:35:41 +08:00
YunaiV f46a2fb011 【代码新增】IoT:增加 device 配置下发(设置)实现 2025-01-31 23:14:09 +08:00
YunaiV 47c281d933 【代码优化】IoT:去除 Simulation 关键字,定义更清晰 2025-01-31 22:47:04 +08:00
YunaiV 252366781d 【代码优化】IoT:优化插件 common 和 http 的配置类 2025-01-31 21:51:06 +08:00
YunaiV a74459e94e 【代码优化】IoT:实现 IotDeviceEventReportVertxHandler 事件上行 2025-01-31 21:16:01 +08:00
YunaiV 2512f2dde8 【代码优化】IoT:优化 http 插件 IotDevicePropertyReportVertxHandler 的代码 2025-01-31 19:05:42 +08:00
YunaiV 7f0de1e34e 【代码新增】IoT:server 实现事件上行的逻辑(不包括 http 插件部分) 2025-01-31 18:04:55 +08:00
YunaiV 45b8172a61 【代码新增】IoT:实现 device 下行属性获取、设置的下行消息 2025-01-31 17:51:39 +08:00
YunaiV b454069897 【代码新增】IoT:实现 device 下行服务调用的逻辑 2025-01-31 11:10:20 +08:00
YunaiV 7670ac19e5 【代码新增】IoT:增加 plugin 插件的心跳机制,以及 Job 超时离线 2025-01-30 23:36:18 +08:00
YunaiV e650e75271 【代码优化】IoT:设备上行时,增加 processId,用于设备与插件的映射 2025-01-30 21:06:47 +08:00
YunaiV 30ae986c1a 【代码优化】IoT:整理 plugins 的依赖,以及对应 server 的启动逻辑 2025-01-30 20:00:54 +08:00
YunaiV 4a251b19c4 【代码新增】IoT:优化 plugins 相关的代码,包拆成分 upstream、downstream、config 三个,职责更明确 2025-01-30 18:44:50 +08:00
YunaiV 2d18e218c7 【代码新增】IoT:增加 IotDeviceDownstreamHandler 接口的定义,以及 IotDeviceDownstreamServer 的部分实现 2025-01-30 18:10:46 +08:00
YunaiV 6a7aa3c3fc 【代码优化】IoT:重构设备 message 为 control,包括上行 + 下行,更合适 2025-01-30 09:20:54 +08:00
YunaiV 2f1598a5da 【代码优化】IoT:重构设备 upstream 为 message,包括上行 + 下行 2025-01-30 08:43:41 +08:00
YunaiV 5110948db8 【代码优化】IoT:设备下行实现前,相关代码的整理 2025-01-30 07:48:28 +08:00
YunaiV 911c8c7461 【功能修改】IoT:完善设备详情的属性展示 2025-01-29 21:47:34 +08:00
YunaiV 39aaeaa298 【功能新增】IoT:增加 IotDeviceOfflineCheckJob,处理设备超时下线 2025-01-29 21:18:38 +08:00
YunaiV eb74f753a8 【功能新增】IoT:增加 IotDeviceOnlineMessageConsumer,处理设备自动上线 2025-01-29 19:09:21 +08:00
YunaiV 7fe4dd2368 【功能新增】IoT:设备模拟更新状态 2025-01-29 15:13:41 +08:00
YunaiV f5f8c418dc 【功能新增】IoT:设备状态上传的部分实现 2025-01-29 11:38:51 +08:00
YunaiV f6366d9b55 【功能修改】IoT:设备状态从 status 到 state,移除已禁用 2025-01-29 00:17:08 +08:00
YunaiV f14cc470aa 【功能修复】IoT:解决物模型的 identifier 存在驼峰情况下,无法插入和查询的情况 2025-01-28 23:16:30 +08:00
YunaiV 76ab64a255 【代码评审】IoT:物模型的管理 2025-01-28 22:24:28 +08:00
YunaiV 0b16f1678c 【功能优化】Bpm:完善设备属性的历史值 2025-01-28 12:04:59 +08:00
YunaiV dfa03d24fd 【功能优化】Bpm:完善设备属性的历史值 2025-01-28 10:23:47 +08:00
YunaiV 8c90448670 【功能优化】Bpm:完善最新数据的接口 2025-01-28 09:23:28 +08:00
YunaiV 6071afeae8 【功能优化】Bpm:设备日志的展示 2025-01-28 08:35:07 +08:00
YunaiV 5fbfe49305 【功能优化】Bpm:设备属性上报 2025-01-28 04:56:03 +08:00
YunaiV eb2d4fdbc0 【功能优化】IoT:同步最新代码 2025-01-28 03:58:24 +08:00
YunaiV 8236154ae8 Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot
# Conflicts:
#	yudao-dependencies/pom.xml
#	yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java
#	yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/thingmodel/IotThingModelTypeEnum.java
2025-01-28 03:54:16 +08:00
YunaiV a364153d4a 【功能优化】IoT:device 和 thingmodel 读取增加缓存 2025-01-27 22:23:31 +08:00
YunaiV 7745035fa4 【功能优化】IoT:设备属性日志表,增加 report_time 上报时间 2025-01-27 21:32:33 +08:00
YunaiV 043d82e5b6 【功能优化】IoT:完整实现 saveDeviceProperty 的设备属性日志的保存 2025-01-27 17:10:59 +08:00
YunaiV 8e80a53a8b 【功能优化】IoT:部分实现 IotDevicePropertyMessageConsumer,支持缓存的记录(差设备属性的日志记录) 2025-01-27 16:50:10 +08:00
YunaiV b319485ca6 【功能优化】IoT:清理通用 TDengine 封装,使用 SQL 查询 2025-01-27 14:23:34 +08:00
YunaiV 8089f3a319 【功能优化】IoT:
1. DeviceDataApi => IotDeviceUpstreamApi,并新建 upstream 包
2. ThingModelMessage => IotDeviceMessage 设备消息
3. 基于 spring event 异步消费 IotDeviceMessage,并实现 IotDeviceLogMessageConsumer 记录日志
2025-01-27 14:15:07 +08:00
YunaiV f4ad3e9d2d 【代码评审】IoT:插件体系 2025-01-26 17:55:04 +08:00
安浩浩 7bfa830628 【代码优化】重构 HTTP插件并添加自动配置 2025-01-26 17:29:03 +08:00
YunaiV 269dec1b2e 【代码评审】IoT:模拟设备数据 2025-01-25 11:46:26 +08:00
芋道源码 03462a103c
!1211 [feat]:模拟设备加入 spring event
Merge pull request !1211 from alwayssuper/feature/iot
2025-01-25 03:27:53 +00:00
YunaiV 5264de077d 【代码评审】IoT:插件体系 2025-01-25 11:26:10 +08:00
安浩浩 88ef8ba2e3 【功能完善】IoT: 删除旧版 HTTP 插件,重构 HttpPlugin 以支持独立启动,新增 VertxService 管理 HTTP 服务器逻辑,优化代码结构和异常处理,更新相关配置以提升插件性能和可维护性。 2025-01-25 00:12:06 +08:00
安浩浩 698cec92bd 【功能完善】IoT: 重命名插件模块,重构插件管理逻辑,优化代码结构,更新配置文件以支持新插件架构。 2025-01-24 23:17:26 +08:00
alwayssuper 03d4f60e80 [fix]:code review 2025-01-24 15:56:01 +08:00
alwayssuper 4f962bd1f7 [fix]:code review 2025-01-23 16:54:45 +08:00
alwayssuper 2b27085ec2 feat:simulator2 2025-01-22 22:08:10 +08:00
alwayssuper 13ced8a114 Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into feature/iot
 Conflicts:
	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/ExampleService.java
2025-01-22 20:30:19 +08:00
alwayssuper 0707792755 [fix]:code review 2025-01-22 16:59:00 +08:00
alwayssuper e7999749fb Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into origin/feature/iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/ExampleService.java
2025-01-22 08:32:56 +08:00
alwayssuper 3c3a12acc1 Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into feature/iot
 Conflicts:
	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/ExampleService.java
2025-01-21 20:48:30 +08:00
alwayssuper 5b75a4fb8a Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot 2025-01-21 20:46:32 +08:00
YunaiV 916024b891 【功能新增】IoT:验证通过独立、内嵌模式的调用 2025-01-21 19:38:41 +08:00
安浩浩 a152f6d98f 【功能完善】IoT: 删除旧版 HTTP 插件,新增 HTTP 和 MQTT 插件,重构插件管理逻辑,优化代码结构,支持 EMQX 插件,更新相关配置文件。 2025-01-21 18:18:28 +08:00
alwayssuper 0cb148a33d Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot 2025-01-20 20:31:08 +08:00
YunaiV d608c4b984 【功能实现】IoT:增加 HttpPlugin 独立启动的 demo 2025-01-20 20:02:46 +08:00
YunaiV 3647fd3686 【代码优化】IoT:移除 ServiceRegistry,使用 SpringUtils 替代 2025-01-20 19:28:03 +08:00
安浩浩 a85890d958 【功能完善】IoT: 添加插件目录配置,重构 SpringPluginManager 实例化逻辑,删除不再使用的 ExampleService 类以优化代码结构。 2025-01-20 17:03:27 +08:00
alwayssuper 9f3730d5d9 [fix]:code review 2025-01-20 16:31:37 +08:00
alwayssuper 495ae4526b Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into origin/feature/iot 2025-01-20 08:02:57 +08:00
安浩浩 5524324554 【功能完善】IoT: 删除不再使用的 MQTT RPC 相关配置和实现,包括 MqttConfig、RpcServer、RpcClient 和 RpcController 类,优化代码结构以清理未使用的组件。 2025-01-19 09:53:57 +08:00
安浩浩 890d304340 【功能完善】IoT: 更新 Vert.x 版本至 4.5.1,新增 EMQX 插件及其相关配置,重构 MQTT 插件以支持 Vert.x MQTT 服务器,优化插件启动和停止逻辑,更新插件描述信息。 2025-01-15 22:37:07 +08:00
alwayssuper 62a868f497 feat:simulator1 2025-01-12 20:13:41 +08:00
alwayssuper f1d887d0e0 Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/iot
 Conflicts:
	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogDataMapper.java
	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataService.java
	yudao-server/src/main/resources/application-local.yaml
2025-01-10 20:46:43 +08:00
alwayssuper d9dda54cce local 2025-01-10 20:42:00 +08:00
YunaiV deab8c1cc6 【代码评审】IoT:设备日志 TDengine 表与模拟设备 2025-01-09 12:36:30 +08:00
YunaiV 16120820a0 Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into feature/iot
# Conflicts:
#	yudao-server/src/main/resources/application-local.yaml
2025-01-08 22:37:33 +08:00
YunaiV aad0581777 【代码评审】IoT:插件机制 2025-01-08 22:36:38 +08:00
安浩浩 0af6d5a758 【功能完善】IoT: 新增插件启动逻辑,重构插件状态管理,删除不再使用的状态文件更新方法 2025-01-08 17:59:32 +08:00
安浩浩 d39e2c1bc4 【代码优化】修改配置文件 2025-01-07 23:21:49 +08:00
安浩浩 77b89aad77 【功能完善】IoT: 集成 Vert.x 支持,重构 HTTP 插件为 Vert.x 插件 2025-01-07 23:13:57 +08:00
安浩浩 cde6ebf921 【功能完善】IoT: 更新设备数据 API,重构保存设备数据方法以使用 DTO,新增参数校验依赖,优化插件管理功能,添加插件实例上报和状态更新接口,同时更新插件信息获取逻辑,删除不再使用的文件和配置。 2025-01-07 17:44:55 +08:00
YunaiV b5856c4cfc 【代码评审】IoT:插件机制 2025-01-06 20:24:47 +08:00
安浩浩 603649d248 【功能完善】IoT: 新增 MQTT RPC 支持,包含请求和响应模型、序列化工具、MQTT 配置及客户端/服务器实现,提供示例服务和控制器接口,优化插件结构以支持 HTTP 插件的集成。 2025-01-06 18:59:26 +08:00
alwayssuper 6aad4545a8 [功能添加]:物模型日志表查询与创建 模拟设备基础逻辑 2025-01-06 16:43:37 +08:00
alwayssuper 0249ca9929 [功能添加]:物模型日志表创建.1 2025-01-06 11:04:39 +08:00
alwayssuper 4f59ebf462 Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into origin/feature/iot 2025-01-06 07:48:03 +08:00
alwayssuper 8a7e146445 feat:simulator 2025-01-05 22:56:13 +08:00
alwayssuper 51b3e31e40 feat:SQLinit 2025-01-05 18:09:19 +08:00
alwayssuper c31dfcc25f feat:物模型列表 2025-01-03 22:30:06 +08:00
alwayssuper 977ddcf02f Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into origin/feature/iot 2025-01-03 07:59:14 +08:00
安浩浩 dc1f9338f1 【功能完善】IoT: 添加 MQTT 插件支持,重构插件管理,新增获取运行状态插件信息接口,优化插件信息存储逻辑,移除不必要的 Spring 注解。 2025-01-01 22:34:26 +08:00
alwayssuper eaee4642d6 [功能添加]:物模型日志表创建 2024-12-31 17:00:25 +08:00
alwayssuper 9c3aa5d95f Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into origin/feature/iot 2024-12-31 14:22:26 +08:00
alwayssuper 1ce9420a8d Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into origin/feature/iot 2024-12-31 14:17:50 +08:00
alwayssuper c4c63a8fd6 feat:iotmessage 2024-12-30 22:46:24 +08:00
安浩浩 24a660b5c2 【功能完善】IoT: 更新插件管理功能,重构插件标识符为 pluginKey,删除 PluginInstanceController,添加插件实例定时更新任务,优化插件信息获取接口。 2024-12-30 18:29:46 +08:00
安浩浩 cbfbc55cd8 【功能完善】IoT: 添加插件和插件实例管理功能,包括插件信息的增删改查接口,支持文件上传和状态更新,同时优化了枚举类型的处理逻辑。 2024-12-30 12:01:58 +08:00
安浩浩 8ca9bebfd1 【代码优化】IoT: 更新 HttpPlugin,重构线程池初始化逻辑以确保线程池活跃 2024-12-30 09:33:56 +08:00
安浩浩 1a3c6756ab 【代码优化】IoT: HTTP 插件模块,删除测试代码 2024-12-29 22:33:16 +08:00
安浩浩 0e20ca342f 【代码优化】IoT: 插件管理 2024-12-29 22:31:58 +08:00
YunaiV c9904f0994 【代码评审】IoT:ThingModel 维护 2024-12-28 21:06:19 +08:00
芋道源码 4014e1b025
!1172 【代码优化】IOT: ThingModel
Merge pull request !1172 from puhui999/iot
2024-12-28 13:02:00 +00:00
puhui999 f623a57862 Merge remote-tracking branch 'yudao/feature/iot' into iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelEvent.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelService.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
2024-12-27 10:54:52 +08:00
puhui999 8b7f329183 【代码优化】IOT: ThingModel 2024-12-27 10:37:16 +08:00
YunaiV b4288bc393 【代码评审】IoT:ThingModel 维护 2024-12-26 13:56:38 +08:00
芋道源码 4075fde765
!1171 【功能完善】IOT: ThingModel 服务和事件
Merge pull request !1171 from puhui999/iot
2024-12-26 05:50:02 +00:00
puhui999 fae17e9125 【功能完善】IOT: ThingModel 服务和事件 2024-12-26 13:27:02 +08:00
puhui999 3524bfd3b3 Merge remote-tracking branch 'yudao/feature/iot' into iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotProductThingModelServiceImpl.java
2024-12-26 13:14:53 +08:00
YunaiV 7b64b7fc69 【功能优化】IoT:跨租户校验 ProductKey 和 DeviceKey,避免跨租户的 Tdengine 表冲突 2024-12-26 12:57:56 +08:00
YunaiV 09a26666ec 【功能修复】IoT:解决 device 建表的时候,tdengine 默认字段都是小写的问题,通过 _ 解决 2024-12-26 12:51:36 +08:00
YunaiV 245ab4e62d 【代码优化】IoT:修复 device 建表时,tdengine 分成 length 和 type 的情况 2024-12-26 09:55:19 +08:00
YunaiV 064b3381df 【代码重构】IoT:弱化 TdEngineDDLMapper 封装,由每个业务独立实现 2024-12-26 07:55:15 +08:00
puhui999 1f9af15e71 【功能完善】IOT: ThingModel 服务和事件 2024-12-26 00:15:57 +08:00
puhui999 38796cc4d4 【功能完善】IOT: ThingModel 服务和事件 2024-12-25 18:36:22 +08:00
puhui999 f4e9a586e3 【功能完善】IOT: ThingModel 服务和事件 2024-12-25 15:47:24 +08:00
puhui999 94cfc4a1b1 【功能完善】IOT: ThingModel 服务和事件 2024-12-25 12:15:58 +08:00
芋道源码 39896555f0
!1170 【代码优化】IOT: ThingModel 评审优化
Merge pull request !1170 from puhui999/iot
2024-12-24 01:28:58 +00:00
puhui999 ed901bc97f Merge remote-tracking branch 'yudao/feature/iot' into iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
2024-12-23 09:47:59 +08:00
YunaiV e01d03eefb 【代码评审】IoT:物模型日志 2024-12-21 16:33:50 +08:00
芋道源码 f580383267
!1167 【代码优化】IOT:物模型日志评审优化
Merge pull request !1167 from alwayssuper/feature/iot
2024-12-21 08:29:40 +00:00
YunaiV e998b0c7eb 【代码评审】IoT:评审 plugin 实现 2024-12-21 16:28:25 +08:00
alwayssuper f68f0de05d Merge branch 'feature/iot' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into origin/feature/iot 2024-12-21 08:00:59 +08:00
安浩浩 a2532013ec 【新增功能】IoT: HTTP 插件模块 2024-12-20 18:57:40 +08:00
alwayssuper 8ff09fea01 [代码优化]:物模型日志评审优化 2024-12-20 14:44:46 +08:00
puhui999 767a26dd70 【代码优化】IOT: ThingModel 评审优化 2024-12-20 10:18:02 +08:00
YunaiV b2434b7b41 【代码评审】IoT:模拟设备发送的 review 2024-12-19 21:23:07 +08:00
YunaiV 95067fd6c6 【代码评审】IoT:评审 ThingModel 的实现 2024-12-19 21:12:07 +08:00
YunaiV 92de5b1f09 Merge branch 'feature/iot' of https://gitee.com/alwayssuper/ruoyi-vue-pro into feature/iot
# Conflicts:
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/dataType/ThingModelArgument.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
2024-12-19 21:07:25 +08:00
YunaiV caa7198e8a 【代码评审】IoT:评审 ThingModel 的实现 2024-12-19 21:02:36 +08:00
芋道源码 666f7dbc92
!1165 【代码优化】IOT: ThingModel 评审优化
Merge pull request !1165 from puhui999/iot
2024-12-19 12:58:31 +00:00
alwayssuper 067130ecde 新增:物模型日志建表 2024-12-19 16:43:56 +08:00
puhui999 8454a10cea 【代码优化】IOT: ThingModel 评审优化 2024-12-19 11:19:10 +08:00
YunaiV de78cc9258 【代码评审】IoT:评审 ThingModel 的实现 2024-12-18 20:41:31 +08:00
芋道源码 cb3275b405
!1164 【代码优化】IOT: 产品物模型代码评审问题优化
Merge pull request !1164 from puhui999/iot
2024-12-18 12:32:46 +00:00
puhui999 0352dda469 【代码优化】IOT: 优化一些 TODO 2024-12-18 18:07:49 +08:00
puhui999 10da1e095b 【代码优化】IOT: 产品物模型代码评审问题优化 2024-12-17 16:53:42 +08:00
安浩浩 91b817a9ec 【功能修改】IoT:删除 WelcomePlugin,新增 HttpPlugin 以支持 HTTP 服务器功能 2024-12-16 22:25:01 +08:00
YunaiV 0245aac530 【代码评审】IoT:评审 thinkmodel 的实现 2024-12-16 20:42:07 +08:00
芋道源码 0ce665ea27
!1162 【功能完善】IoT: 产品物模型
Merge pull request !1162 from puhui999/iot
2024-12-16 12:23:04 +00:00
安浩浩 ce49123043 【功能修改】IoT:更新问候语打印方法,返回问候语数量;删除不再使用的插件控制器和配置类 2024-12-16 18:43:08 +08:00
安浩浩 290fcd94d5 【功能新增】IoT:增加插件支持,包含插件API和示例控制器 2024-12-16 18:18:53 +08:00
puhui999 9e98768022 【功能完善】IoT: 产品物模型 CRUD 接口测试 2024-12-16 16:41:28 +08:00
puhui999 f930f31fab 【功能完善】IoT: 产品物模型属性相关 2024-12-16 12:12:22 +08:00
puhui999 c5894765b5 Merge remote-tracking branch 'yudao/feature/iot' into iot 2024-12-16 10:51:02 +08:00
puhui999 741096e208 【功能完善】IoT: 产品物模型 2024-12-16 10:50:48 +08:00
YunaiV 92c2717d46 【功能新增】IoT:设备管理,增加批量导入 2024-12-15 10:46:33 +08:00
YunaiV dea8883f82 【代码评审】IoT:插件管理相关的逻辑 2024-12-15 08:38:12 +08:00
安浩浩 555310de66 【功能新增】IoT:增加插件管理功能,包含插件实例和类型的定义及相关配置 2024-12-14 21:51:17 +08:00
YunaiV 39ba4e72da 【功能新增】IoT:设备管理界面增加设备分组功能 2024-12-14 19:43:22 +08:00
YunaiV b02e396aff 【功能新增】IoT:设备管理界面增加批量删除功能 2024-12-14 19:12:42 +08:00
YunaiV 3450658159 【功能新增】IoT:设备管理界面增加导出设备功能 2024-12-14 18:56:51 +08:00
YunaiV b5ac526139 【功能新增】IoT:设备管理界面增加设备分组选择功能 2024-12-14 18:41:46 +08:00
YunaiV b143bc177f 【功能新增】IoT:设备分组的管理 2024-12-14 17:00:58 +08:00
YunaiV 9041de2da5 【功能完善】IoT:设备分页筛选去除多余字段 2024-12-14 16:34:26 +08:00
YunaiV afaf98c44f 【功能完善】IoT:设备新增、修改支持更多字段 2024-12-14 16:12:24 +08:00
YunaiV db9c485285 【功能新增】IoT:产品导出功能 2024-12-07 20:48:19 +08:00
YunaiV 9841c869a2 【功能新增】IoT:产品详情,优化相关展示 2024-12-07 20:17:11 +08:00
YunaiV a8c87d168a 【功能新增】IoT:产品新增时,productKey 由前端生成;同时增加 icon、picUrl 字段 2024-12-07 19:50:07 +08:00
YunaiV 9b9fd30c90 【代码重构】IoT:产品放到 product 子目录下 2024-12-07 18:50:31 +08:00
YunaiV 3a2c691af0 【功能新增】IoT:产品分类的维护 2024-12-07 16:42:56 +08:00
YunaiV ce919d12d1 【代码评审】IoT:tdengine 操作 2024-12-05 21:45:48 +08:00
安浩浩 89fb71e857 【优化功能】 优化 tdengine 操作数据库相关代码 2024-11-09 23:44:05 +08:00
YunaiV 9b30d5d355 【代码评审】IoT:tdengine 封装的 review 2024-11-09 13:39:51 +08:00
安浩浩 e3dcea9cb3 【优化功能】 优化 tdengine 操作数据库相关代码 2024-11-08 23:07:37 +08:00
安浩浩 d7b8cf547f 【新增功能】 设备历史数据展示 2024-11-05 23:26:34 +08:00
安浩浩 624f5283b3 【新增功能】 设备数据存储和展示 2024-11-03 00:16:46 +08:00
安浩浩 3dafd31da6 【新增功能】 数据接收,JSON 标准格式数据接收 2024-10-31 21:47:54 +08:00
安浩浩 8c84ac9d8a 【新增功能】 mqtt 数据接收 2024-10-27 21:26:35 +08:00
安浩浩 88088c7987 【功能优化】 产品发布后物模型不可操作优化 2024-10-26 23:26:26 +08:00
安浩浩 7b5aa23d5c 【功能优化】 产品发布创建超级表优化 2024-10-26 23:15:31 +08:00
安浩浩 ea8dd67e9e 【代码优化】增加注解 2024-10-23 23:38:55 +08:00
安浩浩 61a0c05279 【新增功能】 集成 tdengine 2024-10-23 23:26:24 +08:00
安浩浩 05c5482715 【新增功能】 集成 tdengine 2024-10-23 23:23:40 +08:00
3989 changed files with 43971 additions and 18645 deletions

1
.gitignore vendored
View File

@ -51,3 +51,4 @@ rebel.xml
application-my.yaml
/yudao-ui-app/unpackage/
**/.DS_Store

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -149,22 +149,45 @@
### 工作流程
| | 功能 | 描述 |
|----|-------|-----------------------------------------|
| 🚀 | 流程模型 | 配置工作流的流程模型,支持 BPMN 和仿钉钉/飞书设计器 |
| 🚀 | 流程表单 | 拖动表单元素生成相应的工作流表单,覆盖 Element UI 所有的表单组件 |
| 🚀 | 用户分组 | 自定义用户分组,可用于工作流的审批分组 |
| 🚀 | 我的流程 | 查看我发起的工作流程,支持新建、取消流程等操作,高亮流程图、审批时间线 |
| 🚀 | 待办任务 | 查看自己【未】审批的工作任务,支持通过、不通过、转派、委派、退回、加减签等操作 |
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,支持流程预测,展示未来审批人信息 |
| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
![功能图](/.image/common/bpm-feature.png)
基于 Flowable 构建,可支持信创(国产)数据库,满足中国特色流程操作:
| BPMN 设计器 | 钉钉/飞书设计器 |
|------------------------------|--------------------------------|
| ![](/.image/工作流设计器-bpmn.jpg) | ![](/.image/工作流设计器-simple.jpg) |
> 历经头部企业生产验证,工作流引擎须标配仿钉钉/飞书 + BPMN 双设计器!!!
>
> 前者支持轻量配置简单流程,后者实现复杂场景深度编排
| 功能列表 | 功能描述 | 是否完成 |
|------------|-------------------------------------------------------------------------------------|------|
| SIMPLE 设计器 | 仿钉钉/飞书设计器支持拖拽搭建表单流程10 分钟快速完成审批流程配置 | ✅ |
| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ |
| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ |
| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ |
| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ |
| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ |
| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ |
| 转办 | A 转给其 B 审批B 审批后,进入下一节点 | ✅ |
| 委派 | A 转给其 B 审批B 审批后,转给 AA 继续审批后进入下一节点 | ✅ |
| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ |
| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ |
| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ |
| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ |
| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ |
| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ |
| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ |
| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ |
| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ |
| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ |
| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ |
| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ |
| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ |
| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ |
| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ |
### 支付系统
| | 功能 | 描述 |

View File

@ -33,13 +33,13 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<revision>2.4.1-jdk8-SNAPSHOT</revision>
<revision>2.6.0-jdk8-SNAPSHOT</revision>
<!-- Maven 相关 -->
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<!-- 看看咋放到 bom 里 -->
<lombok.version>1.18.36</lombok.version>

File diff suppressed because it is too large Load Diff

View File

@ -14,20 +14,20 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties>
<revision>2.4.1-jdk8-SNAPSHOT</revision>
<revision>2.6.0-jdk8-SNAPSHOT</revision>
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
<!-- 统一依赖管理 -->
<spring.framework.version>5.3.39</spring.framework.version>
<spring.security.version>5.8.14</spring.security.version>
<spring.boot.version>2.7.18</spring.boot.version>
<!-- Web 相关 -->
<springdoc.version>1.7.0</springdoc.version>
<springdoc.version>1.8.0</springdoc.version>
<knife4j.version>4.5.0</knife4j.version>
<servlet.versoin>2.5</servlet.versoin>
<!-- DB 相关 -->
<druid.version>1.2.24</druid.version>
<mybatis.version>3.5.17</mybatis.version>
<mybatis-plus.version>3.5.9</mybatis-plus.version>
<mybatis.version>3.5.19</mybatis.version>
<mybatis-plus.version>3.5.10.1</mybatis-plus.version>
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
<mybatis-plus-join.version>1.4.13</mybatis-plus-join.version>
<easy-trans.version>3.0.6</easy-trans.version>
@ -35,8 +35,9 @@
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
<taos.version>3.3.3</taos.version>
<!-- 消息队列 -->
<rocketmq-spring.version>2.3.1</rocketmq-spring.version>
<rocketmq-spring.version>2.3.2</rocketmq-spring.version>
<!-- 服务保障相关 -->
<lock4j.version>2.2.7</lock4j.version>
<!-- 监控相关 -->
@ -50,30 +51,33 @@
<!-- Bpm 工作流相关 -->
<flowable.version>6.8.0</flowable.version>
<!-- 工具类相关 -->
<captcha-plus.version>1.0.10</captcha-plus.version>
<anji-plus-captcha.version>1.4.0</anji-plus-captcha.version>
<jsoup.version>1.18.3</jsoup.version>
<lombok.version>1.18.36</lombok.version>
<mapstruct.version>1.6.3</mapstruct.version>
<hutool.version>5.8.35</hutool.version>
<easyexcel.verion>4.0.3</easyexcel.verion>
<easyexcel.version>4.0.3</easyexcel.version>
<velocity.version>2.4</velocity.version> <!-- JDK8 不能从 2.4 升级到 2.4.1,会报包不存在!!!! -->
<fastjson.version>1.2.83</fastjson.version>
<guava.version>33.4.0-jre</guava.version>
<guava.version>33.4.8-jre</guava.version>
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
<commons-net.version>3.11.1</commons-net.version>
<jsch.version>0.1.55</jsch.version>
<tika-core.version>2.9.2</tika-core.version>
<tika-core.version>2.9.3</tika-core.version> <!-- JDK8 不能从 2.9.3 升级到 3.X会报 JDK8 不支持 -->
<ip2region.version>2.7.0</ip2region.version>
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
<netty.version>4.1.116.Final</netty.version>
<mqtt.version>1.2.5</mqtt.version>
<pf4j-spring.version>0.9.0</pf4j-spring.version>
<vertx.version>4.5.13</vertx.version>
<!-- 三方云服务相关 -->
<commons-io.version>2.17.0</commons-io.version>
<commons-compress.version>1.27.1</commons-compress.version>
<aws-java-sdk-s3.version>1.12.777</aws-java-sdk-s3.version>
<justauth.version>1.0.8</justauth.version>
<jimureport.version>1.7.8</jimureport.version>
<weixin-java.version>4.6.0</weixin-java.version>
<awssdk.version>2.30.14</awssdk.version>
<justauth.version>1.16.7</justauth.version>
<justauth-starter.version>1.4.0</justauth-starter.version>
<jimureport.version>1.9.4</jimureport.version>
<weixin-java.version>4.7.5.B</weixin-java.version>
<!-- 专属于 JDK8 安全漏洞升级 -->
<logback.version>1.2.13</logback.version> <!-- 无法使用 1.3.X 版本,启动会报错 -->
</properties>
@ -189,6 +193,7 @@
<version>${druid.version}</version>
</dependency>
<dependency>
<!-- 注意:必须声明,避免 flowable 和 mybatis-plus 引入的 mybatis 版本不一致!!! -->
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
@ -291,6 +296,12 @@
<version>${kingbase.jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>${taos.version}</version>
</dependency>
<!-- Job 定时任务相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
@ -304,7 +315,6 @@
<artifactId>yudao-spring-boot-starter-mq</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
@ -494,7 +504,7 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.verion}</version>
<version>${easyexcel.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
@ -530,12 +540,6 @@
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId> <!-- 解决 ThreadLocal 父子线程的传值问题 -->
@ -555,9 +559,9 @@
</dependency>
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-captcha-plus</artifactId>
<version>${captcha-plus.version}</version>
<groupId>com.anji-plus</groupId>
<artifactId>captcha-spring-boot-starter</artifactId> <!-- 验证码,一般用于登录使用 -->
<version>${anji-plus-captcha.version}</version>
</dependency>
<dependency>
@ -574,16 +578,22 @@
<!-- 三方云服务相关 -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>${aws-java-sdk-s3.version}</version>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>${awssdk.version}</version>
</dependency>
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
<version>${justauth.version}</version>
</dependency>
<dependency>
<groupId>com.xkcoding.justauth</groupId>
<artifactId>justauth-spring-boot-starter</artifactId>
<version>${justauth-starter.version}</version>
<exclusions>
<!-- 移除,避免和项目里的 hutool-all 冲突 -->
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
@ -612,14 +622,49 @@
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<version>${jimureport.version}</version>
</dependency>
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimubi-spring-boot-starter</artifactId>
<version>${jimureport.version}</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- PF4J -->
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-spring</artifactId>
<version>${pf4j-spring.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Vert.x -->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-mqtt</artifactId>
<version>${vertx.version}</version>
</dependency>
<!-- MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.infra.api.logger;
package cn.iocoder.yudao.framework.common.biz.infra.logger;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
import org.springframework.scheduling.annotation.Async;
import javax.validation.Valid;
@ -10,7 +10,7 @@ import javax.validation.Valid;
*
* @author 芋道源码
*/
public interface ApiAccessLogApi {
public interface ApiAccessLogCommonApi {
/**
* 创建 API 访问日志

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.infra.api.logger;
package cn.iocoder.yudao.framework.common.biz.infra.logger;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
import org.springframework.scheduling.annotation.Async;
import javax.validation.Valid;
@ -10,7 +10,7 @@ import javax.validation.Valid;
*
* @author 芋道源码
*/
public interface ApiErrorLogApi {
public interface ApiErrorLogCommonApi {
/**
* 创建 API 错误日志

View File

@ -0,0 +1,4 @@
/**
* 针对 infra 模块的 api
*/
package cn.iocoder.yudao.framework.common.biz.infra;

View File

@ -0,0 +1,4 @@
/**
* 特殊用于 framework starter 需要调用 biz 业务模块的接口定义
*/
package cn.iocoder.yudao.framework.common.biz;

View File

@ -0,0 +1,22 @@
package cn.iocoder.yudao.framework.common.biz.system.dict;
import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO;
import java.util.List;
/**
* 字典数据 API 接口
*
* @author 芋道源码
*/
public interface DictDataCommonApi {
/**
* 获得指定字典类型的字典数据列表
*
* @param dictType 字典类型
* @return 字典数据列表
*/
List<DictDataRespDTO> getDictDataList(String dictType);
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.api.dict.dto;
package cn.iocoder.yudao.framework.common.biz.system.dict.dto;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import lombok.Data;

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.framework.common.biz.system.logger;
import cn.iocoder.yudao.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
import org.springframework.scheduling.annotation.Async;
import javax.validation.Valid;
/**
* 操作日志 API 接口
*
* @author 芋道源码
*/
public interface OperateLogCommonApi {
/**
* 创建操作日志
*
* @param createReqDTO 请求
*/
void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
/**
* 异步创建操作日志
*
* @param createReqDTO 请求
*/
@Async
default void createOperateLogAsync(OperateLogCreateReqDTO createReqDTO) {
createOperateLog(createReqDTO);
}
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.api.logger.dto;
package cn.iocoder.yudao.framework.common.biz.system.logger.dto;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import lombok.Data;

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.system.api.oauth2;
package cn.iocoder.yudao.framework.common.biz.system.oauth2;
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenRespDTO;
import javax.validation.Valid;
@ -11,7 +11,7 @@ import javax.validation.Valid;
*
* @author 芋道源码
*/
public interface OAuth2TokenApi {
public interface OAuth2TokenCommonApi {
/**
* 创建访问令牌

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.api.oauth2.dto;
package cn.iocoder.yudao.framework.common.biz.system.oauth2.dto;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.api.oauth2.dto;
package cn.iocoder.yudao.framework.common.biz.system.oauth2.dto;
import lombok.Data;
import lombok.experimental.Accessors;

View File

@ -0,0 +1,4 @@
/**
* 针对 system 模块的 api
*/
package cn.iocoder.yudao.framework.common.biz.system;

View File

@ -1,24 +1,13 @@
package cn.iocoder.yudao.module.system.api.permission;
package cn.iocoder.yudao.framework.common.biz.system.permission;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import java.util.Collection;
import java.util.Set;
import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
/**
* 权限 API 接口
*
* @author 芋道源码
*/
public interface PermissionApi {
/**
* 获得拥有多个角色的用户编号集合
*
* @param roleIds 角色编号集合
* @return 用户编号集合
*/
Set<Long> getUserRoleIdListByRoleIds(Collection<Long> roleIds);
public interface PermissionCommonApi {
/**
* 判断是否有权限任一一个即可

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.system.api.tenant;
package cn.iocoder.yudao.framework.common.biz.system.tenant;
import java.util.List;
@ -7,7 +7,7 @@ import java.util.List;
*
* @author 芋道源码
*/
public interface TenantApi {
public interface TenantCommonApi {
/**
* 获得所有租户

View File

@ -0,0 +1,17 @@
package cn.iocoder.yudao.framework.common.enums;
/**
* RPC 相关的枚举
*
* 虽然放在 yudao-spring-boot-starter-rpc 会相对合适但是每个 API 模块需要使用到所以暂时只好放在此处
*
* @author 芋道源码
*/
public class RpcConstants {
/**
* RPC API 的前缀
*/
public static final String RPC_API_PREFIX = "/rpc-api";
}

View File

@ -11,6 +11,7 @@ import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.hutool.core.convert.Convert.toCollection;
import static java.util.Arrays.asList;
/**
@ -335,4 +336,17 @@ public class CollectionUtils {
return list.stream().filter(Objects::nonNull).flatMap(Collection::stream).collect(Collectors.toList());
}
/**
* 转换为 LinkedHashSet
*
* @param <T> 元素类型
* @param elementType 集合中元素类型
* @param value 被转换的值
* @return {@link LinkedHashSet}
*/
@SuppressWarnings("unchecked")
public static <T> LinkedHashSet<T> toLinkedHashSet(Class<T> elementType, Object value) {
return (LinkedHashSet<T>) toCollection(LinkedHashSet.class, elementType, value);
}
}

View File

@ -8,12 +8,16 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import static cn.hutool.core.date.DatePattern.UTC_MS_WITH_XXX_OFFSET_PATTERN;
import static cn.hutool.core.date.DatePattern.createFormatter;
/**
* 时间工具类用于 {@link java.time.LocalDateTime}
*
@ -26,6 +30,8 @@ public class LocalDateTimeUtils {
*/
public static LocalDateTime EMPTY = buildTime(1970, 1, 1);
public static DateTimeFormatter UTC_MS_WITH_XXX_OFFSET_FORMATTER = createFormatter(UTC_MS_WITH_XXX_OFFSET_PATTERN);
/**
* 解析时间
*

View File

@ -7,13 +7,16 @@ import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import lombok.SneakyThrows;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
@ -23,6 +26,17 @@ import java.util.Map;
*/
public class HttpUtils {
/**
* 编码 URL 参数
*
* @param value 参数
* @return 编码后的参数
*/
@SneakyThrows
public static String encodeUtf8(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8.name());
}
@SuppressWarnings("unchecked")
public static String replaceUrlQuery(String url, String key, String value) {
UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());

View File

@ -1,14 +1,9 @@
package cn.iocoder.yudao.framework.common.util.io;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import lombok.SneakyThrows;
import java.io.ByteArrayInputStream;
import java.io.File;
/**
@ -63,22 +58,4 @@ public class FileUtils {
return file;
}
/**
* 生成文件路径
*
* @param content 文件内容
* @param originalName 原始文件名
* @return path唯一不可重复
*/
public static String generatePath(byte[] content, String originalName) {
String sha256Hex = DigestUtil.sha256Hex(content);
// 情况一如果存在 name则优先使用 name 的后缀
if (StrUtil.isNotBlank(originalName)) {
String extName = FileNameUtil.extName(originalName);
return StrUtil.isBlank(extName) ? sha256Hex : sha256Hex + "." + extName;
}
// 情况二基于 content 计算
return sha256Hex + '.' + FileTypeUtil.getType(new ByteArrayInputStream(content));
}
}

View File

@ -1,9 +1,11 @@
package cn.iocoder.yudao.framework.common.util.number;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import java.math.BigDecimal;
import java.util.List;
/**
* 数字的工具类补全 {@link cn.hutool.core.util.NumberUtil} 的功能
@ -20,6 +22,18 @@ public class NumberUtils {
return StrUtil.isNotEmpty(str) ? Integer.valueOf(str) : null;
}
public static boolean isAllNumber(List<String> values) {
if (CollUtil.isEmpty(values)) {
return false;
}
for (String value : values) {
if (!NumberUtil.isNumber(value)) {
return false;
}
}
return true;
}
/**
* 通过经纬度获取地球上两点之间的距离
*

View File

@ -116,4 +116,8 @@ public class ServletUtils {
return ServletUtil.getParamMap(request);
}
public static Map<String, String> getHeaderMap(HttpServletRequest request) {
return ServletUtil.getHeaderMap(request);
}
}

View File

@ -97,12 +97,26 @@ public class SpringExpressionUtils {
* @return 执行界面
*/
public static Object parseExpression(String expressionString) {
return parseExpression(expressionString, null);
}
/**
* Bean 工厂解析 EL 表达式的结果
*
* @param expressionString EL 表达式
* @param variables 变量
* @return 执行界面
*/
public static Object parseExpression(String expressionString, Map<String, Object> variables) {
if (StrUtil.isBlank(expressionString)) {
return null;
}
Expression expression = EXPRESSION_PARSER.parseExpression(expressionString);
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new BeanFactoryResolver(SpringUtil.getApplicationContext()));
if (MapUtil.isNotEmpty(variables)) {
context.setVariables(variables);
}
return expression.getValue(context);
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.string;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import org.aspectj.lang.JoinPoint;
import java.util.Arrays;
import java.util.Collection;
@ -77,4 +78,30 @@ public class StrUtils {
.collect(Collectors.joining("\n"));
}
/**
* 拼接方法的参数
*
* 特殊排除一些无法序列化的参数 ServletRequestServletResponseMultipartFile
*
* @param joinPoint 连接点
* @return 拼接后的参数
*/
public static String joinMethodArgs(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
if (ArrayUtil.isEmpty(args)) {
return "";
}
return ArrayUtil.join(args, ",", item -> {
if (item == null) {
return "";
}
// 讨论可见https://t.zsxq.com/XUJVkhttps://t.zsxq.com/MnKcL
String clazzName = item.getClass().getName();
if (StrUtil.startWithAny(clazzName, "javax.servlet", "jakarta.servlet", "org.springframework.web")) {
return "";
}
return item;
});
}
}

View File

@ -34,13 +34,6 @@
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行数据权限的获取 -->
<version>${revision}</version>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>

View File

@ -1,9 +1,9 @@
package cn.iocoder.yudao.framework.datapermission.config;
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -18,11 +18,11 @@ import java.util.List;
*/
@AutoConfiguration
@ConditionalOnClass(LoginUser.class)
@ConditionalOnBean(value = {PermissionApi.class, DeptDataPermissionRuleCustomizer.class})
@ConditionalOnBean(value = {PermissionCommonApi.class, DeptDataPermissionRuleCustomizer.class})
public class YudaoDeptDataPermissionAutoConfiguration {
@Bean
public DeptDataPermissionRule deptDataPermissionRule(PermissionApi permissionApi,
public DeptDataPermissionRule deptDataPermissionRule(PermissionCommonApi permissionApi,
List<DeptDataPermissionRuleCustomizer> customizers) {
// 创建 DeptDataPermissionRule 对象
DeptDataPermissionRule rule = new DeptDataPermissionRule(permissionApi);

View File

@ -12,6 +12,8 @@ import net.sf.jsqlparser.schema.Table;
import java.util.List;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.skipPermissionCheck;
/**
* 基于 {@link DataPermissionRule} 的数据权限处理器
*
@ -27,6 +29,11 @@ public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
@Override
public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
// 特殊跨租户访问
if (skipPermissionCheck()) {
return null;
}
// 获得 Mapper 对应的数据权限的规则
List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(mappedStatementId);
if (CollUtil.isEmpty(rules)) {

View File

@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.datapermission.core.rule.dept;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@ -11,12 +13,13 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
@ -59,7 +62,7 @@ public class DeptDataPermissionRule implements DataPermissionRule {
static final Expression EXPRESSION_NULL = new NullValue();
private final PermissionApi permissionApi;
private final PermissionCommonApi permissionApi;
/**
* 基于部门的表字段配置

View File

@ -32,13 +32,12 @@ public class DataPermissionUtils {
* @param runnable 逻辑
*/
public static void executeIgnore(Runnable runnable) {
DataPermission dataPermission = getDisableDataPermissionDisable();
DataPermissionContextHolder.add(dataPermission);
addDisableDataPermission();
try {
// 执行 runnable
runnable.run();
} finally {
DataPermissionContextHolder.remove();
removeDataPermission();
}
}
@ -50,14 +49,25 @@ public class DataPermissionUtils {
*/
@SneakyThrows
public static <T> T executeIgnore(Callable<T> callable) {
DataPermission dataPermission = getDisableDataPermissionDisable();
DataPermissionContextHolder.add(dataPermission);
addDisableDataPermission();
try {
// 执行 callable
return callable.call();
} finally {
DataPermissionContextHolder.remove();
removeDataPermission();
}
}
/**
* 添加忽略数据权限
*/
public static void addDisableDataPermission(){
DataPermission dataPermission = getDisableDataPermissionDisable();
DataPermissionContextHolder.add(dataPermission);
}
public static void removeDataPermission(){
DataPermissionContextHolder.remove();
}
}

View File

@ -2,13 +2,13 @@ package cn.iocoder.yudao.framework.datapermission.core.rule.dept;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import org.junit.jupiter.api.BeforeEach;
@ -39,7 +39,7 @@ class DeptDataPermissionRuleTest extends BaseMockitoUnitTest {
private DeptDataPermissionRule rule;
@Mock
private PermissionApi permissionApi;
private PermissionCommonApi permissionApi;
@BeforeEach
@SuppressWarnings("unchecked")

View File

@ -4,6 +4,7 @@ import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
@ -30,7 +31,14 @@ public class TenantProperties {
*
* 默认情况下每个请求需要带上 tenant-id 的请求头但是部分请求是无需带上的例如说短信回调支付回调等 Open API
*/
private Set<String> ignoreUrls = Collections.emptySet();
private Set<String> ignoreUrls = new HashSet<>();
/**
* 需要忽略跨切换租户访问的请求
*
* 原因是某些接口访问的是个人信息在跨租户是获取不到的
*/
private Set<String> ignoreVisitUrls = Collections.emptySet();
/**
* 需要忽略多租户的表

View File

@ -1,8 +1,11 @@
package cn.iocoder.yudao.framework.tenant.config;
import cn.iocoder.yudao.framework.common.biz.system.tenant.TenantCommonApi;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
@ -14,9 +17,9 @@ import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkServiceImpl;
import cn.iocoder.yudao.framework.tenant.core.web.TenantContextWebFilter;
import cn.iocoder.yudao.framework.tenant.core.web.TenantVisitContextInterceptor;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@ -24,6 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.BatchStrategies;
@ -32,16 +36,29 @@ import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.pattern.PathPattern;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@AutoConfiguration
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户
@EnableConfigurationProperties(TenantProperties.class)
public class YudaoTenantAutoConfiguration {
@Resource
private ApplicationContext applicationContext;
@Bean
public TenantFrameworkService tenantFrameworkService(TenantApi tenantApi) {
public TenantFrameworkService tenantFrameworkService(TenantCommonApi tenantApi) {
return new TenantFrameworkServiceImpl(tenantApi);
}
@ -67,13 +84,60 @@ public class YudaoTenantAutoConfiguration {
// ========== WEB ==========
@Bean
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter(TenantProperties tenantProperties) {
FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TenantContextWebFilter());
registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
addIgnoreUrls(tenantProperties);
return registrationBean;
}
/**
* 如果 Controller 接口上 {@link TenantIgnore} 注解那么添加到忽略的 URL
*
* @param tenantProperties 租户配置
*/
private void addIgnoreUrls(TenantProperties tenantProperties) {
// 获得接口对应的 HandlerMethod 集合
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
applicationContext.getBean("requestMappingHandlerMapping");
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
// 获得有 @TenantIgnore 注解的接口
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = entry.getValue();
if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class)) {
continue;
}
// 添加到忽略的 URL
if (entry.getKey().getPatternsCondition() != null) {
tenantProperties.getIgnoreUrls().addAll(entry.getKey().getPatternsCondition().getPatterns());
}
if (entry.getKey().getPathPatternsCondition() != null) {
tenantProperties.getIgnoreUrls().addAll(
convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
}
}
}
@Bean
public TenantVisitContextInterceptor tenantVisitContextInterceptor(TenantProperties tenantProperties,
SecurityFrameworkService securityFrameworkService) {
return new TenantVisitContextInterceptor(tenantProperties, securityFrameworkService);
}
@Bean
public WebMvcConfigurer tenantWebMvcConfigurer(TenantProperties tenantProperties,
TenantVisitContextInterceptor tenantVisitContextInterceptor) {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tenantVisitContextInterceptor)
.excludePathPatterns(tenantProperties.getIgnoreVisitUrls().toArray(new String[0]));
}
};
}
// ========== Security ==========
@Bean

View File

@ -1,5 +1,7 @@
package cn.iocoder.yudao.framework.tenant.core.aop;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import java.lang.annotation.*;
/**
@ -9,10 +11,22 @@ import java.lang.annotation.*;
* 1Redis 场景因为是基于 Key 实现多租户的能力所以忽略没有意义不像 DB 是一个 column 实现的
* 2MQ 场景有点难以抉择目前可以通过 Consumer 手动在消费的方法上添加 @TenantIgnore 进行忽略
*
* 特殊
* 1如果添加到 Controller 类上则该 URL 自动添加到 {@link TenantProperties#getIgnoreUrls()}
* 2如果添加到 DO 实体类上则它对应的表名相当于自动添加到 {@link TenantProperties#getIgnoreTables()}
*
* @author 芋道源码
*/
@Target({ElementType.METHOD})
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TenantIgnore {
/**
* 是否开启忽略租户默认为 true 开启
*
* 支持 Spring EL 表达式如果返回 true 则满足条件进行租户的忽略
*/
String enable() default "true";
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.tenant.core.aop;
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import lombok.extern.slf4j.Slf4j;
@ -24,7 +25,12 @@ public class TenantIgnoreAspect {
public Object around(ProceedingJoinPoint joinPoint, TenantIgnore tenantIgnore) throws Throwable {
Boolean oldIgnore = TenantContextHolder.isIgnore();
try {
// 计算条件满足的情况下才进行忽略
Object enable = SpringExpressionUtils.parseExpression(tenantIgnore.enable());
if (Boolean.TRUE.equals(enable)) {
TenantContextHolder.setIgnore(true);
}
// 执行逻辑
return joinPoint.proceed();
} finally {

View File

@ -1,15 +1,17 @@
package cn.iocoder.yudao.framework.tenant.core.db;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.toolkit.SqlParserUtils;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.Map;
/**
* 基于 MyBatis Plus 多租户的功能实现 DB 层面的多租户的功能
@ -18,16 +20,21 @@ import java.util.Set;
*/
public class TenantDatabaseInterceptor implements TenantLineHandler {
private final Set<String> ignoreTables = new HashSet<>();
/**
* 忽略的表
*
* KEY表名
* VALUE是否忽略
*/
private final Map<String, Boolean> ignoreTables = new HashMap<>();
public TenantDatabaseInterceptor(TenantProperties properties) {
// 不同 DB 大小写的习惯不同所以需要都添加进去
properties.getIgnoreTables().forEach(table -> {
ignoreTables.add(table.toLowerCase());
ignoreTables.add(table.toUpperCase());
addIgnoreTable(table, true);
});
// OracleKeyGenerator 生成主键时会查询这个表查询这个表后会自动拼接 TENANT_ID 导致报错
ignoreTables.add("DUAL");
addIgnoreTable("DUAL", true);
}
@Override
@ -37,8 +44,40 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
@Override
public boolean ignoreTable(String tableName) {
return TenantContextHolder.isIgnore() // 情况一全局忽略多租户
|| CollUtil.contains(ignoreTables, SqlParserUtils.removeWrapperSymbol(tableName)); // 情况二忽略多租户的表
// 情况一全局忽略多租户
if (TenantContextHolder.isIgnore()) {
return true;
}
// 情况二忽略多租户的表
tableName = SqlParserUtils.removeWrapperSymbol(tableName);
Boolean ignore = ignoreTables.get(tableName.toLowerCase());
if (ignore == null) {
ignore = computeIgnoreTable(tableName);
synchronized (ignoreTables) {
addIgnoreTable(tableName, ignore);
}
}
return ignore;
}
private void addIgnoreTable(String tableName, boolean ignore) {
ignoreTables.put(tableName.toLowerCase(), ignore);
ignoreTables.put(tableName.toUpperCase(), ignore);
}
private boolean computeIgnoreTable(String tableName) {
// 找不到的表说明不是 yudao 项目里的不进行拦截忽略租户
TableInfo tableInfo = TableInfoHelper.getTableInfo(tableName);
if (tableInfo == null) {
return true;
}
// 如果继承了 TenantBaseDO 基类显然不忽略租户
if (TenantBaseDO.class.isAssignableFrom(tableInfo.getEntityType())) {
return false;
}
// 如果添加了 @TenantIgnore 注解显然也不忽略租户
TenantIgnore tenantIgnore = tableInfo.getEntityType().getAnnotation(TenantIgnore.class);
return tenantIgnore != null;
}
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.framework.tenant.core.service;
import cn.iocoder.yudao.framework.common.biz.system.tenant.TenantCommonApi;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.RequiredArgsConstructor;
@ -21,7 +21,7 @@ public class TenantFrameworkServiceImpl implements TenantFrameworkService {
private static final ServiceException SERVICE_EXCEPTION_NULL = new ServiceException();
private final TenantApi tenantApi;
private final TenantCommonApi tenantApi;
/**
* 针对 {@link #getTenantIds()} 的缓存

View File

@ -45,6 +45,7 @@ public class TenantUtils {
*
* @param tenantId 租户编号
* @param callable 逻辑
* @return 结果
*/
public static <V> V execute(Long tenantId, Callable<V> callable) {
Long oldTenantId = TenantContextHolder.getTenantId();
@ -78,6 +79,25 @@ public class TenantUtils {
}
}
/**
* 忽略租户执行对应的逻辑
*
* @param callable 逻辑
* @return 结果
*/
public static <V> V executeIgnore(Callable<V> callable) {
Boolean oldIgnore = TenantContextHolder.isIgnore();
try {
TenantContextHolder.setIgnore(true);
// 执行逻辑
return callable.call();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
TenantContextHolder.setIgnore(oldIgnore);
}
}
/**
* 将多租户编号添加到 header
*

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.framework.tenant.core.web;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
@RequiredArgsConstructor
@Slf4j
public class TenantVisitContextInterceptor implements HandlerInterceptor {
private static final String PERMISSION = "system:tenant:visit";
private final TenantProperties tenantProperties;
private final SecurityFrameworkService securityFrameworkService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 如果和当前租户编号一致则直接跳过
Long visitTenantId = WebFrameworkUtils.getVisitTenantId(request);
if (visitTenantId == null) {
return true;
}
if (ObjUtil.equal(visitTenantId, TenantContextHolder.getTenantId())) {
return true;
}
// 必须是登录用户
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser == null) {
return true;
}
// 校验用户是否可切换租户
if (!securityFrameworkService.hasAnyPermissions(PERMISSION)) {
throw exception0(GlobalErrorCodeConstants.FORBIDDEN.getCode(), "您无权切换租户");
}
// 重点切换租户编号
loginUser.setVisitTenantId(visitTenantId);
TenantContextHolder.setTenantId(visitTenantId);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 重点清理切换换回原租户编号
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser != null && loginUser.getTenantId() != null) {
TenantContextHolder.setTenantId(loginUser.getTenantId());
}
}
}

View File

@ -27,13 +27,6 @@
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行 Dict 的查询 -->
<version>${revision}</version>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springframework</groupId>

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.dict.config;
import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
@ -10,7 +10,7 @@ public class YudaoDictAutoConfiguration {
@Bean
@SuppressWarnings("InstantiationOfUtilityClass")
public DictFrameworkUtils dictUtils(DictDataApi dictDataApi) {
public DictFrameworkUtils dictUtils(DictDataCommonApi dictDataApi) {
DictFrameworkUtils.init(dictDataApi);
return new DictFrameworkUtils();
}

View File

@ -1,10 +1,9 @@
package cn.iocoder.yudao.framework.dict.core;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.SneakyThrows;
@ -12,6 +11,9 @@ import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
/**
* 字典工具类
@ -21,76 +23,57 @@ import java.util.List;
@Slf4j
public class DictFrameworkUtils {
private static DictDataApi dictDataApi;
private static DictDataCommonApi dictDataApi;
private static final DictDataRespDTO DICT_DATA_NULL = new DictDataRespDTO();
// TODO @puhui999GET_DICT_DATA_CACHEGET_DICT_DATA_LIST_CACHEPARSE_DICT_DATA_CACHE 3 个缓存是有点重叠可以思考下有没可能减少 1 微信讨论好私聊再具体改哈
/**
* 针对 {@link #getDictDataLabel(String, String)} 缓存
* 针对 dictType 的字段数据缓存
*/
private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
private static final LoadingCache<String, List<DictDataRespDTO>> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
Duration.ofMinutes(1L), // 过期时间 1 分钟
new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() {
new CacheLoader<String, List<DictDataRespDTO>>() {
@Override
public DictDataRespDTO load(KeyValue<String, String> key) {
return ObjectUtil.defaultIfNull(dictDataApi.getDictData(key.getKey(), key.getValue()), DICT_DATA_NULL);
public List<DictDataRespDTO> load(String dictType) {
return dictDataApi.getDictDataList(dictType);
}
});
/**
* 针对 {@link #getDictDataLabelList(String)} 的缓存
*/
private static final LoadingCache<String, List<String>> GET_DICT_DATA_LIST_CACHE = CacheUtils.buildAsyncReloadingCache(
Duration.ofMinutes(1L), // 过期时间 1 分钟
new CacheLoader<String, List<String>>() {
@Override
public List<String> load(String dictType) {
return dictDataApi.getDictDataLabelList(dictType);
}
});
/**
* 针对 {@link #parseDictDataValue(String, String)} 的缓存
*/
private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
Duration.ofMinutes(1L), // 过期时间 1 分钟
new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() {
@Override
public DictDataRespDTO load(KeyValue<String, String> key) {
return ObjectUtil.defaultIfNull(dictDataApi.parseDictData(key.getKey(), key.getValue()), DICT_DATA_NULL);
}
});
public static void init(DictDataApi dictDataApi) {
public static void init(DictDataCommonApi dictDataApi) {
DictFrameworkUtils.dictDataApi = dictDataApi;
log.info("[init][初始化 DictFrameworkUtils 成功]");
}
@SneakyThrows
public static String getDictDataLabel(String dictType, Integer value) {
return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, String.valueOf(value))).getLabel();
public static void clearCache() {
GET_DICT_DATA_CACHE.invalidateAll();
}
@SneakyThrows
public static String getDictDataLabel(String dictType, String value) {
return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel();
public static String parseDictDataLabel(String dictType, Integer value) {
if (value == null) {
return null;
}
return parseDictDataLabel(dictType, String.valueOf(value));
}
@SneakyThrows
public static String parseDictDataLabel(String dictType, String value) {
List<DictDataRespDTO> dictDatas = GET_DICT_DATA_CACHE.get(dictType);
DictDataRespDTO dictData = CollUtil.findOne(dictDatas, data -> Objects.equals(data.getValue(), value));
return dictData != null ? dictData.getLabel(): null;
}
@SneakyThrows
public static List<String> getDictDataLabelList(String dictType) {
return GET_DICT_DATA_LIST_CACHE.get(dictType);
List<DictDataRespDTO> dictDatas = GET_DICT_DATA_CACHE.get(dictType);
return convertList(dictDatas, DictDataRespDTO::getLabel);
}
@SneakyThrows
public static String parseDictDataValue(String dictType, String label) {
return PARSE_DICT_DATA_CACHE.get(new KeyValue<>(dictType, label)).getValue();
List<DictDataRespDTO> dictDatas = GET_DICT_DATA_CACHE.get(dictType);
DictDataRespDTO dictData = CollUtil.findOne(dictDatas, data -> Objects.equals(data.getLabel(), label));
return dictData!= null ? dictData.getValue(): null;
}
}

View File

@ -56,7 +56,7 @@ public class DictConvert implements Converter<Object> {
// 使用字典格式化
String type = getType(contentProperty);
String value = String.valueOf(object);
String label = DictFrameworkUtils.getDictDataLabel(type, value);
String label = DictFrameworkUtils.parseDictDataLabel(type, value);
if (label == null) {
log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);
return new WriteCellData<>("");

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.excel.core.util;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
@ -8,8 +9,6 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
@ -40,7 +39,7 @@ public class ExcelUtils {
.registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
.sheet(sheetName).doWrite(data);
// 设置 header contentType写在最后的原因是避免报错时响应 contentType 已经被修改了
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename));
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
}

View File

@ -1,16 +1,19 @@
package cn.iocoder.yudao.framework.dict.core.util;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import java.util.List;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
@ -19,33 +22,40 @@ import static org.mockito.Mockito.when;
public class DictFrameworkUtilsTest extends BaseMockitoUnitTest {
@Mock
private DictDataApi dictDataApi;
private DictDataCommonApi dictDataApi;
@BeforeEach
public void setUp() {
DictFrameworkUtils.init(dictDataApi);
DictFrameworkUtils.clearCache();
}
@Test
public void testGetDictDataLabel() {
public void testParseDictDataLabel() {
// mock 数据
DictDataRespDTO dataRespDTO = randomPojo(DictDataRespDTO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
List<DictDataRespDTO> dictDatas = ListUtil.of(
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("")),
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel(""))
);
// mock 方法
when(dictDataApi.getDictData(dataRespDTO.getDictType(), dataRespDTO.getValue())).thenReturn(dataRespDTO);
when(dictDataApi.getDictDataList(eq("animal"))).thenReturn(dictDatas);
// 断言返回值
assertEquals(dataRespDTO.getLabel(), DictFrameworkUtils.getDictDataLabel(dataRespDTO.getDictType(), dataRespDTO.getValue()));
assertEquals("", DictFrameworkUtils.parseDictDataLabel("animal", "dog"));
}
@Test
public void testParseDictDataValue() {
// mock 数据
DictDataRespDTO resp = randomPojo(DictDataRespDTO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()));
List<DictDataRespDTO> dictDatas = ListUtil.of(
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("")),
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel(""))
);
// mock 方法
when(dictDataApi.parseDictData(resp.getDictType(), resp.getLabel())).thenReturn(resp);
when(dictDataApi.getDictDataList(eq("animal"))).thenReturn(dictDatas);
// 断言返回值
assertEquals(resp.getValue(), DictFrameworkUtils.parseDictDataValue(resp.getDictType(), resp.getLabel()));
assertEquals("dog", DictFrameworkUtils.parseDictDataValue("animal", ""));
}
}

View File

@ -6,6 +6,7 @@ import cn.hutool.system.SystemUtil;
import cn.iocoder.yudao.framework.common.enums.DocumentEnum;
import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
import cn.iocoder.yudao.framework.mq.redis.core.job.RedisPendingMessageResendJob;
import cn.iocoder.yudao.framework.mq.redis.core.job.RedisStreamMessageCleanupJob;
import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener;
import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
@ -73,6 +74,17 @@ public class YudaoRedisMQConsumerAutoConfiguration {
return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient);
}
/**
* 创建 Redis Stream 消息清理任务
*/
@Bean
@ConditionalOnBean(AbstractRedisStreamMessageListener.class)
public RedisStreamMessageCleanupJob redisStreamMessageCleanupJob(List<AbstractRedisStreamMessageListener<?>> listeners,
RedisMQTemplate redisTemplate,
RedissonClient redissonClient) {
return new RedisStreamMessageCleanupJob(listeners, redisTemplate, redissonClient);
}
/**
* 创建 Redis Stream 集群消费的容器
*

View File

@ -23,13 +23,13 @@ import java.util.Objects;
@AllArgsConstructor
public class RedisPendingMessageResendJob {
private static final String LOCK_KEY = "redis:pending:msg:lock";
private static final String LOCK_KEY = "redis:stream:pending-message-resend:lock";
/**
* 消息超时时间默认 5 分钟
*
* 1. 超时的消息才会被重新投递
* 2. 由于定时任务 1 分钟一次消息超时后不会被立即重投极端情况下消息5分钟过期后再等 1 分钟才会被扫瞄到
* 2. 由于定时任务 1 分钟一次消息超时后不会被立即重投极端情况下消息 5 分钟过期后再等 1 分钟才会被扫瞄到
*/
private static final int EXPIRE_TIME = 5 * 60;
@ -39,7 +39,7 @@ public class RedisPendingMessageResendJob {
private final RedissonClient redissonClient;
/**
* 一分钟执行一次,这里选择每分钟的35秒执行是为了避免整点任务过多的问题
* 一分钟执行一次,这里选择每分钟的 35 秒执行是为了避免整点任务过多的问题
*/
@Scheduled(cron = "35 * * * * ?")
public void messageResend() {

View File

@ -0,0 +1,72 @@
package cn.iocoder.yudao.framework.mq.redis.core.job;
import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate;
import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StreamOperations;
import org.springframework.scheduling.annotation.Scheduled;
import java.util.List;
/**
* Redis Stream 消息清理任务
* 用于定期清理已消费的消息防止内存占用过大
*
* @see <a href="https://www.cnblogs.com/nanxiang/p/16179519.html">记一次 redis stream 数据类型内存不释放问题</a>
*
* @author 芋道源码
*/
@Slf4j
@AllArgsConstructor
public class RedisStreamMessageCleanupJob {
private static final String LOCK_KEY = "redis:stream:message-cleanup:lock";
/**
* 保留的消息数量默认保留最近 10000 条消息
*/
private static final long MAX_COUNT = 10000;
private final List<AbstractRedisStreamMessageListener<?>> listeners;
private final RedisMQTemplate redisTemplate;
private final RedissonClient redissonClient;
/**
* 每小时执行一次清理任务
*/
@Scheduled(cron = "0 0 * * * ?")
public void cleanup() {
RLock lock = redissonClient.getLock(LOCK_KEY);
// 尝试加锁
if (lock.tryLock()) {
try {
execute();
} catch (Exception ex) {
log.error("[cleanup][执行异常]", ex);
} finally {
lock.unlock();
}
}
}
/**
* 执行清理逻辑
*/
private void execute() {
StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream();
listeners.forEach(listener -> {
try {
// 使用 XTRIM 命令清理消息只保留最近的 MAX_LEN 条消息
Long trimCount = ops.trim(listener.getStreamKey(), MAX_COUNT, true);
if (trimCount != null && trimCount > 0) {
log.info("[execute][Stream({}) 清理消息数量({})]", listener.getStreamKey(), trimCount);
}
} catch (Exception ex) {
log.error("[execute][Stream({}) 清理异常]", listener.getStreamKey(), ex);
}
});
}
}

View File

@ -63,6 +63,11 @@
<artifactId>opengauss-jdbc</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>

View File

@ -53,4 +53,14 @@ public abstract class BaseDO implements Serializable, TransPojo {
@TableLogic
private Boolean deleted;
/**
* creatorcreateTimeupdateTimeupdater 都清空避免前端直接传递 creator 之类的字段直接就被更新了
*/
public void clean(){
this.creator = null;
this.createTime = null;
this.updater = null;
this.updateTime = null;
}
}

View File

@ -92,10 +92,36 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
default T selectOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
SFunction<T, ?> field3, Object value3) {
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2)
.eq(field3, value3));
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
}
/**
* 获取满足条件的第 1 条记录
*
* 目的解决并发场景下插入多条记录后使用 selectOne 会报错的问题
*
* @param field 字段名
* @param value 字段值
* @return 实体
*/
default T selectFirstOne(SFunction<T, ?> field, Object value) {
// 如果明确使用 MySQL 等场景可以考虑使用 LIMIT 1 进行优化
List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field, value));
return CollUtil.getFirst(list);
}
default T selectFirstOne(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
return CollUtil.getFirst(list);
}
default T selectFirstOne(SFunction<T,?> field1, Object value1, SFunction<T,?> field2, Object value2,
SFunction<T,?> field3, Object value3) {
List<T> list = selectList(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
return CollUtil.getFirst(list);
}
default Long selectCount() {
return selectCount(new QueryWrapper<>());
}
@ -189,4 +215,11 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
return delete(new LambdaQueryWrapper<T>().eq(field, value));
}
default int deleteBatch(SFunction<T, ?> field, Collection<?> values) {
if (CollUtil.isEmpty(values)) {
return 0;
}
return delete(new LambdaQueryWrapper<T>().in(field, values));
}
}

View File

@ -4,7 +4,6 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.util.StringUtils;
@ -15,94 +14,94 @@ import java.util.function.Consumer;
* 拓展 MyBatis Plus Join QueryWrapper 主要增加如下功能
* <p>
* 1. 拼接条件的方法增加 xxxIfPresent 方法用于判断值不存在的时候不要拼接到条件中
*
* 2. SFunction<S, ?> column + <S> 泛型支持任意类字段主表子表三表推荐写法, 让编译器自动推断 S 类型
* @param <T> 数据类型
*/
public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
public MPJLambdaWrapperX<T> likeIfPresent(SFunction<T, ?> column, String val) {
MPJWrappers.lambdaJoin().like(column, val);
public <S> MPJLambdaWrapperX<T> likeIfPresent(SFunction<S, ?> column, String val) {
if (StringUtils.hasText(val)) {
return (MPJLambdaWrapperX<T>) super.like(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Collection<?> values) {
public <S> MPJLambdaWrapperX<T> inIfPresent(SFunction<S, ?> column, Collection<?> values) {
if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
return (MPJLambdaWrapperX<T>) super.in(column, values);
}
return this;
}
public MPJLambdaWrapperX<T> inIfPresent(SFunction<T, ?> column, Object... values) {
public <S> MPJLambdaWrapperX<T> inIfPresent(SFunction<S, ?> column, Object... values) {
if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
return (MPJLambdaWrapperX<T>) super.in(column, values);
}
return this;
}
public MPJLambdaWrapperX<T> eqIfPresent(SFunction<T, ?> column, Object val) {
public <S> MPJLambdaWrapperX<T> eqIfPresent(SFunction<S, ?> column, Object val) {
if (ObjectUtil.isNotEmpty(val)) {
return (MPJLambdaWrapperX<T>) super.eq(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> neIfPresent(SFunction<T, ?> column, Object val) {
public <S> MPJLambdaWrapperX<T> neIfPresent(SFunction<S, ?> column, Object val) {
if (ObjectUtil.isNotEmpty(val)) {
return (MPJLambdaWrapperX<T>) super.ne(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> gtIfPresent(SFunction<T, ?> column, Object val) {
public <S> MPJLambdaWrapperX<T> gtIfPresent(SFunction<S, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.gt(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> geIfPresent(SFunction<T, ?> column, Object val) {
public <S> MPJLambdaWrapperX<T> geIfPresent(SFunction<S, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.ge(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> ltIfPresent(SFunction<T, ?> column, Object val) {
public <S> MPJLambdaWrapperX<T> ltIfPresent(SFunction<S, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.lt(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> leIfPresent(SFunction<T, ?> column, Object val) {
public <S> MPJLambdaWrapperX<T> leIfPresent(SFunction<S, ?> column, Object val) {
if (val != null) {
return (MPJLambdaWrapperX<T>) super.le(column, val);
}
return this;
}
public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object val1, Object val2) {
if (val1 != null && val2 != null) {
return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
}
if (val1 != null) {
return (MPJLambdaWrapperX<T>) ge(column, val1);
}
if (val2 != null) {
return (MPJLambdaWrapperX<T>) le(column, val2);
}
return this;
}
public MPJLambdaWrapperX<T> betweenIfPresent(SFunction<T, ?> column, Object[] values) {
public <S> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<S, ?> column, Object[] values) {
Object val1 = ArrayUtils.get(values, 0);
Object val2 = ArrayUtils.get(values, 1);
return betweenIfPresent(column, val1, val2);
}
public <S> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<S, ?> column, Object val1, Object val2) {
if (val1 != null && val2 != null) {
return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
}
if (val1 != null) {
return (MPJLambdaWrapperX<T>) super.ge(column, val1);
}
if (val2 != null) {
return (MPJLambdaWrapperX<T>) super.le(column, val2);
}
return this;
}
// ========== 重写父类方法方便链式调用 ==========
@Override
@ -310,4 +309,41 @@ public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
return this;
}
// ========== 关键重写使 leftJoin 返回当前类型 this ==========
@Override
public <A, B> MPJLambdaWrapperX<T> leftJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
super.leftJoin(clazz, left, right);
return this;
}
@Override
public <A, B> MPJLambdaWrapperX<T> rightJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
super.rightJoin(clazz, left, right);
return this;
}
@Override
public <A, B> MPJLambdaWrapperX<T> innerJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
super.innerJoin(clazz, left, right);
return this;
}
// ========== 添加扩展 Join 支持 ext 函数式参数 ==========
public <A, B> MPJLambdaWrapperX<T> leftJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
super.leftJoin(clazz, left, right);
if (ext != null) ext.accept(this);
return this;
}
public <A, B> MPJLambdaWrapperX<T> rightJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
super.rightJoin(clazz, left, right);
if (ext != null) ext.accept(this);
return this;
}
public <A, B> MPJLambdaWrapperX<T> innerJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
super.innerJoin(clazz, left, right);
if (ext != null) ext.accept(this);
return this;
}
}

View File

@ -13,7 +13,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 字段字段的 TypeHandler 实现类基于 {@link cn.hutool.crypto.symmetric.AES} 实现
* 字段字段的 TypeHandler 实现类基于 {@link AES} 实现
* 可通过 jasypt.encryptor.password 配置项设置密钥
*
* @author 芋道源码

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.framework.mybatis.core.type;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;
/**
* Set<Long> 的类型转换器实现类对应数据库的 varchar 类型
*
* @author 芋道源码
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class LongSetTypeHandler implements TypeHandler<Set<Long>> {
private static final String COMMA = ",";
@Override
public void setParameter(PreparedStatement ps, int i, Set<Long> strings, JdbcType jdbcType) throws SQLException {
// 设置占位符
ps.setString(i, CollUtil.join(strings, COMMA));
}
@Override
public Set<Long> getResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return getResult(value);
}
@Override
public Set<Long> getResult(ResultSet rs, int columnIndex) throws SQLException {
String value = rs.getString(columnIndex);
return getResult(value);
}
@Override
public Set<Long> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String value = cs.getString(columnIndex);
return getResult(value);
}
private Set<Long> getResult(String value) {
if (value == null) {
return null;
}
return StrUtils.splitToLongSet(value, COMMA);
}
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
import org.aspectj.lang.JoinPoint;
@ -18,7 +18,7 @@ public class DefaultIdempotentKeyResolver implements IdempotentKeyResolver {
@Override
public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
String methodName = joinPoint.getSignature().toString();
String argsStr = StrUtil.join(",", joinPoint.getArgs());
String argsStr = StrUtils.joinMethodArgs(joinPoint);
return SecureUtil.md5(methodName + argsStr);
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
@ -19,7 +19,7 @@ public class UserIdempotentKeyResolver implements IdempotentKeyResolver {
@Override
public String resolver(JoinPoint joinPoint, Idempotent idempotent) {
String methodName = joinPoint.getSignature().toString();
String argsStr = StrUtil.join(",", joinPoint.getArgs());
String argsStr = StrUtils.joinMethodArgs(joinPoint);
Long userId = WebFrameworkUtils.getLoginUserId();
Integer userType = WebFrameworkUtils.getLoginUserType();
return SecureUtil.md5(methodName + argsStr + userId + userType);

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
import org.aspectj.lang.JoinPoint;
@ -19,7 +19,7 @@ public class ClientIpRateLimiterKeyResolver implements RateLimiterKeyResolver {
@Override
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
String methodName = joinPoint.getSignature().toString();
String argsStr = StrUtil.join(",", joinPoint.getArgs());
String argsStr = StrUtils.joinMethodArgs(joinPoint);
String clientIp = ServletUtils.getClientIP();
return SecureUtil.md5(methodName + argsStr + clientIp);
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
import org.aspectj.lang.JoinPoint;
@ -18,7 +18,7 @@ public class DefaultRateLimiterKeyResolver implements RateLimiterKeyResolver {
@Override
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
String methodName = joinPoint.getSignature().toString();
String argsStr = StrUtil.join(",", joinPoint.getArgs());
String argsStr = StrUtils.joinMethodArgs(joinPoint);
return SecureUtil.md5(methodName + argsStr);
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.system.SystemUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
import org.aspectj.lang.JoinPoint;
@ -19,7 +19,7 @@ public class ServerNodeRateLimiterKeyResolver implements RateLimiterKeyResolver
@Override
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
String methodName = joinPoint.getSignature().toString();
String argsStr = StrUtil.join(",", joinPoint.getArgs());
String argsStr = StrUtils.joinMethodArgs(joinPoint);
String serverNode = String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
return SecureUtil.md5(methodName + argsStr + serverNode);
}

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.framework.ratelimiter.core.keyresolver.RateLimiterKeyResolver;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
@ -19,7 +19,7 @@ public class UserRateLimiterKeyResolver implements RateLimiterKeyResolver {
@Override
public String resolver(JoinPoint joinPoint, RateLimiter rateLimiter) {
String methodName = joinPoint.getSignature().toString();
String argsStr = StrUtil.join(",", joinPoint.getArgs());
String argsStr = StrUtils.joinMethodArgs(joinPoint);
Long userId = WebFrameworkUtils.getLoginUserId();
Integer userType = WebFrameworkUtils.getLoginUserType();
return SecureUtil.md5(methodName + argsStr + userId + userType);

View File

@ -44,6 +44,7 @@ public class RateLimiterRedisDAO {
RateLimiterConfig config = rateLimiter.getConfig();
if (config == null) {
rateLimiter.trySetRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
rateLimiter.expire(rateInterval, TimeUnit.SECONDS); // 原因参见 https://t.zsxq.com/lcR0W
return rateLimiter;
}
// 2. 如果存在并且配置相同则直接返回
@ -54,6 +55,7 @@ public class RateLimiterRedisDAO {
}
// 3. 如果存在并且配置不同则进行新建
rateLimiter.setRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS);
rateLimiter.expire(rateInterval, TimeUnit.SECONDS); // 原因参见 https://t.zsxq.com/lcR0W
return rateLimiter;
}

View File

@ -2,10 +2,12 @@ package cn.iocoder.yudao.framework.signature.core.aop;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
@ -69,13 +71,17 @@ public class ApiSignatureAspect {
// 3. nonce 记入缓存防止重复使用重点二此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2
String nonce = request.getHeader(signature.nonce());
signatureRedisDAO.setNonce(appId, nonce, signature.timeout() * 2, signature.timeUnit());
if (BooleanUtil.isFalse(signatureRedisDAO.setNonce(appId, nonce, signature.timeout() * 2, signature.timeUnit()))) {
String timestamp = request.getHeader(signature.timestamp());
log.info("[verifySignature][appId({}) timestamp({}) nonce({}) sign({}) 存在重复请求]", appId, timestamp, nonce, clientSignature);
throw new ServiceException(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), "存在重复请求");
}
return true;
}
/**
* 校验请求头加签参数
*
* <p>
* 1. appId 是否为空
* 2. timestamp 是否为空请求是否已经超时默认 10 分钟
* 3. nonce 是否为空随机数是否 10 位以上是否在规定时间内已经访问过了
@ -118,7 +124,7 @@ public class ApiSignatureAspect {
/**
* 构建签名字符串
*
* <p>
* 格式为 = 请求参数 + 请求体 + 请求头 + 密钥
*
* @param signature signature

View File

@ -17,7 +17,7 @@ public class ApiSignatureRedisDAO {
/**
* 验签随机数
*
* <p>
* KEY 格式signature_nonce:%s // 参数为 随机数
* VALUE 格式String
* 过期时间不固定
@ -26,7 +26,7 @@ public class ApiSignatureRedisDAO {
/**
* 签名密钥
*
* <p>
* HASH 结构
* KEY 格式%s // 参数为 appid
* VALUE 格式String
@ -40,8 +40,8 @@ public class ApiSignatureRedisDAO {
return stringRedisTemplate.opsForValue().get(formatNonceKey(appId, nonce));
}
public void setNonce(String appId, String nonce, int time, TimeUnit timeUnit) {
stringRedisTemplate.opsForValue().set(formatNonceKey(appId, nonce), "", time, timeUnit);
public Boolean setNonce(String appId, String nonce, int time, TimeUnit timeUnit) {
return stringRedisTemplate.opsForValue().setIfAbsent(formatNonceKey(appId, nonce), "", time, timeUnit);
}
private static String formatNonceKey(String appId, String nonce) {

View File

@ -63,13 +63,12 @@ public class ApiSignatureTest {
when(request.getReader()).thenReturn(new BufferedReader(new StringReader("test")));
// mock 方法
when(signatureRedisDAO.getAppSecret(eq(appId))).thenReturn(appSecret);
when(signatureRedisDAO.setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS))).thenReturn(true);
// 调用
boolean result = apiSignatureAspect.verifySignature(apiSignature, request);
// 断言结果
assertTrue(result);
// 断言调用
verify(signatureRedisDAO).setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS));
}
}

View File

@ -59,13 +59,6 @@
<groupId>io.github.mouzt</groupId>
<artifactId>bizlog-sdk</artifactId>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行 Token 的校验 -->
<version>${revision}</version>
</dependency>
</dependencies>
</project>

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.framework.operatelog.core.service;
import cn.iocoder.yudao.framework.common.biz.system.logger.OperateLogCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
import com.mzt.logapi.beans.LogRecord;
import com.mzt.logapi.service.ILogRecordService;
import lombok.extern.slf4j.Slf4j;
@ -17,7 +17,7 @@ import java.util.List;
/**
* 操作日志 ILogRecordService 实现类
*
* 基于 {@link OperateLogApi} 实现记录操作日志
* 基于 {@link OperateLogCommonApi} 实现记录操作日志
*
* @author HUIHUI
*/
@ -25,7 +25,7 @@ import java.util.List;
public class LogRecordServiceImpl implements ILogRecordService {
@Resource
private OperateLogApi operateLogApi;
private OperateLogCommonApi operateLogApi;
@Override
public void record(LogRecord logRecord) {

View File

@ -1,5 +1,7 @@
package cn.iocoder.yudao.framework.security.config;
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
@ -7,8 +9,7 @@ import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPoint
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService;
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkServiceImpl;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import javax.annotation.Resource;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
@ -20,8 +21,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.annotation.Resource;
/**
* Spring Security 自动配置类主要用于相关组件的配置
*
@ -70,12 +69,12 @@ public class YudaoSecurityAutoConfiguration {
*/
@Bean
public TokenAuthenticationFilter authenticationTokenFilter(GlobalExceptionHandler globalExceptionHandler,
OAuth2TokenApi oauth2TokenApi) {
OAuth2TokenCommonApi oauth2TokenApi) {
return new TokenAuthenticationFilter(securityProperties, globalExceptionHandler, oauth2TokenApi);
}
@Bean("ss") // 使用 Spring Security 的缩写方便使用
public SecurityFrameworkService securityFrameworkService(PermissionApi permissionApi) {
public SecurityFrameworkService securityFrameworkService(PermissionCommonApi permissionApi) {
return new SecurityFrameworkServiceImpl(permissionApi);
}

View File

@ -30,6 +30,7 @@ import org.springframework.web.util.pattern.PathPattern;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.DispatcherType;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -142,7 +143,9 @@ public class YudaoWebSecurityConfigurerAdapter {
// 每个项目的自定义规则
.authorizeHttpRequests(c -> authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(c)))
// 兜底规则必须认证
.authorizeHttpRequests(c -> c.anyRequest().authenticated());
.authorizeHttpRequests(c -> c
.dispatcherTypeMatchers(DispatcherType.ASYNC).permitAll() // WebFlux 异步请求无需认证目的SSE 场景
.anyRequest().authenticated());
// 添加 Token Filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

View File

@ -56,6 +56,10 @@ public class LoginUser {
*/
@JsonIgnore
private Map<String, Object> context;
/**
* 访问的租户编号
*/
private Long visitTenantId;
public void setContext(String key, Object value) {
if (context == null) {

View File

@ -2,6 +2,8 @@ package cn.iocoder.yudao.framework.security.core.filter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
@ -10,8 +12,6 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.filter.OncePerRequestFilter;
@ -35,7 +35,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final GlobalExceptionHandler globalExceptionHandler;
private final OAuth2TokenApi oauth2TokenApi;
private final OAuth2TokenCommonApi oauth2TokenApi;
@Override
@SuppressWarnings("NullableProblems")

View File

@ -1,14 +1,15 @@
package cn.iocoder.yudao.framework.security.core.service;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import lombok.AllArgsConstructor;
import java.util.Arrays;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.skipPermissionCheck;
/**
* 默认的 {@link SecurityFrameworkService} 实现类
@ -18,7 +19,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
@AllArgsConstructor
public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
private final PermissionApi permissionApi;
private final PermissionCommonApi permissionApi;
@Override
public boolean hasPermission(String permission) {
@ -27,6 +28,12 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
@Override
public boolean hasAnyPermissions(String... permissions) {
// 特殊跨租户访问
if (skipPermissionCheck()) {
return true;
}
// 权限校验
Long userId = getLoginUserId();
if (userId == null) {
return false;
@ -41,6 +48,12 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
@Override
public boolean hasAnyRoles(String... roles) {
// 特殊跨租户访问
if (skipPermissionCheck()) {
return true;
}
// 权限校验
Long userId = getLoginUserId();
if (userId == null) {
return false;
@ -55,6 +68,12 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService {
@Override
public boolean hasAnyScopes(String... scope) {
// 特殊跨租户访问
if (skipPermissionCheck()) {
return true;
}
// 权限校验
LoginUser user = SecurityFrameworkUtils.getLoginUser();
if (user == null) {
return false;

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.framework.security.core.util;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
@ -137,4 +138,21 @@ public class SecurityFrameworkUtils {
return authenticationToken;
}
/**
* 是否条件跳过权限校验包括数据权限功能权限
*
* @return 是否跳过
*/
public static boolean skipPermissionCheck() {
LoginUser loginUser = getLoginUser();
if (loginUser == null) {
return false;
}
if (loginUser.getVisitTenantId() == null) {
return false;
}
// 重点跨租户访问时无法进行权限校验
return ObjUtil.notEqual(loginUser.getVisitTenantId(), loginUser.getTenantId());
}
}

View File

@ -53,18 +53,6 @@
<scope>provided</scope> <!-- 设置为 provided主要是 GlobalExceptionHandler 使用 -->
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-infra-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行错误码的记录 -->
<version>${revision}</version>
</dependency>
<!-- xss -->
<dependency>
<groupId>org.jsoup</groupId>

View File

@ -2,10 +2,11 @@ package cn.iocoder.yudao.framework.apilog.config;
import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter;
import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor;
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiAccessLogCommonApi;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -14,8 +15,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.Filter;
@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
@ -26,7 +25,7 @@ public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
@ConditionalOnProperty(prefix = "yudao.access-log", value = "enable", matchIfMissing = true) // 允许使用 yudao.access-log.enable=false 禁用访问日志
public FilterRegistrationBean<ApiAccessLogFilter> apiAccessLogFilter(WebProperties webProperties,
@Value("${spring.application.name}") String applicationName,
ApiAccessLogApi apiAccessLogApi) {
ApiAccessLogCommonApi apiAccessLogApi) {
ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogApi);
return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER);
}

View File

@ -9,6 +9,8 @@ import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum;
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiAccessLogCommonApi;
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@ -17,8 +19,6 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -53,9 +53,9 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
private final String applicationName;
private final ApiAccessLogApi apiAccessLogApi;
private final ApiAccessLogCommonApi apiAccessLogApi;
public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogApi apiAccessLogApi) {
public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogCommonApi apiAccessLogApi) {
super(webProperties);
this.applicationName = applicationName;
this.apiAccessLogApi = apiAccessLogApi;

View File

@ -62,9 +62,9 @@ public class BannerApplicationRunner implements ApplicationRunner {
if (isNotPresent("cn.iocoder.yudao.module.ai.framework.web.config.AiWebConfiguration")) {
System.out.println("[AI 大模型 yudao-module-ai - 已禁用][参考 https://doc.iocoder.cn/ai/build/ 开启]");
}
// IOT 物联网
// IoT 物联网
if (isNotPresent("cn.iocoder.yudao.module.iot.framework.web.config.IotWebConfiguration")) {
System.out.println("[IOT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]");
System.out.println("[IoT 物联网 yudao-module-iot - 已禁用][参考 https://doc.iocoder.cn/iot/build/ 开启]");
}
});
}

View File

@ -1,12 +1,12 @@
package cn.iocoder.yudao.framework.web.config;
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -60,7 +60,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogApi apiErrorLogApi) {
public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogCommonApi apiErrorLogApi) {
return new GlobalExceptionHandler(applicationName, apiErrorLogApi);
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.web.core.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
@ -12,8 +13,8 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi;
import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -22,6 +23,7 @@ import org.springframework.security.access.AccessDeniedException;
import org.springframework.util.Assert;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
@ -35,6 +37,7 @@ import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -58,7 +61,7 @@ public class GlobalExceptionHandler {
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
private final String applicationName;
private final ApiErrorLogApi apiErrorLogApi;
private final ApiErrorLogCommonApi apiErrorLogApi;
/**
* 处理所有异常主要是提供给 Filter 使用
@ -133,9 +136,23 @@ public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public CommonResult<?> methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) {
log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex);
// 获取 errorMessage
String errorMessage = null;
FieldError fieldError = ex.getBindingResult().getFieldError();
assert fieldError != null; // 断言避免告警
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
if (fieldError == null) {
// 组合校验参考自 https://t.zsxq.com/3HVTx
List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
if (CollUtil.isNotEmpty(allErrors)) {
errorMessage = allErrors.get(0).getDefaultMessage();
}
} else {
errorMessage = fieldError.getDefaultMessage();
}
// 转换 CommonResult
if (StrUtil.isEmpty(errorMessage)) {
return CommonResult.error(BAD_REQUEST);
}
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", errorMessage));
}
/**
@ -376,11 +393,11 @@ public class GlobalExceptionHandler {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
}
// 9. IOT 物联网
// 9. IoT 物联网
if (message.contains("iot_")) {
log.error("[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
log.error("[IoT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[IOT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
"[IoT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
}
return null;
}

View File

@ -1,11 +1,9 @@
package cn.iocoder.yudao.framework.web.core.util;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
@ -27,6 +25,7 @@ public class WebFrameworkUtils {
private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result";
public static final String HEADER_TENANT_ID = "tenant-id";
public static final String HEADER_VISIT_TENANT_ID = "visit-tenant-id";
/**
* 终端的 Header
@ -53,6 +52,18 @@ public class WebFrameworkUtils {
return NumberUtil.isNumber(tenantId) ? Long.valueOf(tenantId) : null;
}
/**
* 获得访问的租户编号 header
* 考虑到其它 framework 组件也会使用到租户编号所以不得不放在 WebFrameworkUtils 统一提供
*
* @param request 请求
* @return 租户编号
*/
public static Long getVisitTenantId(HttpServletRequest request) {
String tenantId = request.getHeader(HEADER_VISIT_TENANT_ID);
return NumberUtil.isNumber(tenantId)? Long.valueOf(tenantId) : null;
}
public static void setLoginUserId(ServletRequest request, Long userId) {
request.setAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_ID, userId);
}

View File

@ -8,12 +8,7 @@
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modules>
<module>yudao-module-ai-api</module>
<module>yudao-module-ai-biz</module>
<module>yudao-spring-boot-starter-ai</module>
</modules>
<packaging>pom</packaging>
<packaging>jar</packaging>
<artifactId>yudao-module-ai</artifactId>
<name>${project.artifactId}</name>
@ -23,5 +18,196 @@
国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek
国外OpenAI、Ollama、Midjourney、StableDiffusion、Suno
</description>
<properties>
<spring-ai.version>1.0.0-M6</spring-ai.version>
<tinyflow.version>1.0.2</tinyflow.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-infra</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Job 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-job</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<!-- Spring AI Model 模型接入 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-stability-ai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<!-- 通义千问 -->
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>${spring-ai.version}.1</version>
</dependency>
<dependency>
<!-- 文心一言 -->
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-qianfan-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<!-- 智谱 GLM -->
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-minimax-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-moonshot-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- 向量存储https://db-engines.com/en/ranking/vector+dbms -->
<dependency>
<!-- Qdranthttps://qdrant.tech/ -->
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-qdrant-store</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<!-- Redishttps://redis.io/docs/latest/develop/get-started/vector-database/ -->
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-redis-store</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<!-- Milvushttps://milvus.io/ -->
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-milvus-store</artifactId>
<version>${spring-ai.version}</version>
<exclusions>
<!-- 解决和 logback 的日志冲突 -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!-- Tika负责内容的解析 -->
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-tika-document-reader</artifactId>
<version>${spring-ai.version}</version>
<!-- TODO 芋艿boot 项目里,不引入 cloud 依赖!!!另外,这样也是为了解决启动报错的问题! -->
<exclusions>
<exclusion>
<artifactId>spring-cloud-function-context</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
<exclusion>
<artifactId>spring-cloud-function-core</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- TinyFlowAI 工作流 -->
<dependency>
<groupId>dev.tinyflow</groupId>
<artifactId>tinyflow-java-core</artifactId>
<version>${tinyflow.version}</version>
<exclusions>
<exclusion>
<groupId>com.jfinal</groupId>
<artifactId>enjoy</artifactId>
</exclusion>
<exclusion>
<!-- 解决 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1318/ 问题 -->
<groupId>com.agentsflex</groupId>
<artifactId>agents-flex-store-elasticsearch</artifactId>
</exclusion>
<exclusion>
<!-- TODO @芋艿:暂时移除 groovy和 iot 冲突 -->
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</exclusion>
<!-- 解决和 logback 的日志冲突 -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -12,15 +12,18 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessage
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService;
import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService;
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService;
import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
@ -33,7 +36,7 @@ import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 聊天消息")
@ -48,6 +51,10 @@ public class AiChatMessageController {
private AiChatConversationService chatConversationService;
@Resource
private AiChatRoleService chatRoleService;
@Resource
private AiKnowledgeSegmentService knowledgeSegmentService;
@Resource
private AiKnowledgeDocumentService knowledgeDocumentService;
@Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢")
@PostMapping("/send")
@ -57,7 +64,6 @@ public class AiChatMessageController {
@Operation(summary = "发送消息(流式)", description = "流式返回,响应较快")
@PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
@PermitAll // 解决 SSE 最终响应的时候会被 Access Denied 拦截的问题
public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) {
return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId());
}
@ -71,8 +77,38 @@ public class AiChatMessageController {
if (conversation == null || ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) {
return success(Collections.emptyList());
}
// 1. 获取消息列表
List<AiChatMessageDO> messageList = chatMessageService.getChatMessageListByConversationId(conversationId);
return success(BeanUtils.toBean(messageList, AiChatMessageRespVO.class));
if (CollUtil.isEmpty(messageList)) {
return success(Collections.emptyList());
}
// 2. 拼接数据主要是知识库段落信息
Map<Long, AiKnowledgeSegmentDO> segmentMap = knowledgeSegmentService.getKnowledgeSegmentMap(convertListByFlatMap(messageList,
message -> CollUtil.isEmpty(message.getSegmentIds()) ? null : message.getSegmentIds().stream()));
Map<Long, AiKnowledgeDocumentDO> documentMap = knowledgeDocumentService.getKnowledgeDocumentMap(
convertList(segmentMap.values(), AiKnowledgeSegmentDO::getDocumentId));
List<AiChatMessageRespVO> messageVOList = BeanUtils.toBean(messageList, AiChatMessageRespVO.class);
for (int i = 0; i < messageList.size(); i++) {
AiChatMessageDO message = messageList.get(i);
if (CollUtil.isEmpty(message.getSegmentIds())) {
continue;
}
// 设置知识库段落信息
messageVOList.get(i).setSegments(convertList(message.getSegmentIds(), segmentId -> {
AiKnowledgeSegmentDO segment = segmentMap.get(segmentId);
if (segment == null) {
return null;
}
AiKnowledgeDocumentDO document = documentMap.get(segment.getDocumentId());
if (document == null) {
return null;
}
return new AiChatMessageRespVO.KnowledgeSegment().setId(segment.getId()).setContent(segment.getContent())
.setDocumentId(segment.getDocumentId()).setDocumentName(document.getName());
}));
}
return success(messageVOList);
}
@Operation(summary = "删除消息")
@ -105,7 +141,8 @@ public class AiChatMessageController {
Map<Long, AiChatRoleDO> roleMap = chatRoleService.getChatRoleMap(
convertSet(pageResult.getList(), AiChatMessageDO::getRoleId));
return success(BeanUtils.toBean(pageResult, AiChatMessageRespVO.class,
respVO -> MapUtils.findAndThen(roleMap, respVO.getRoleId(), role -> respVO.setRoleName(role.getName()))));
respVO -> MapUtils.findAndThen(roleMap, respVO.getRoleId(),
role -> respVO.setRoleName(role.getName()))));
}
@Operation(summary = "管理员删除消息")

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
@ -31,7 +31,7 @@ public class AiChatConversationRespVO implements VO {
private Long roleId;
@Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@Trans(type = TransType.SIMPLE, target = AiChatModelDO.class, fields = "name", ref = "modelName")
@Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = "name", ref = "modelName")
private Long modelId;
@Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922")

View File

@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - AI 聊天消息 Response VO")
@Data
@ -39,6 +40,12 @@ public class AiChatMessageRespVO {
@Schema(description = "是否携带上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean useContext;
@Schema(description = "知识库段落编号数组", example = "[1,2,3]")
private List<Long> segmentIds;
@Schema(description = "知识库段落数组")
private List<KnowledgeSegment> segments;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51")
private LocalDateTime createTime;
@ -47,4 +54,22 @@ public class AiChatMessageRespVO {
@Schema(description = "角色名字", example = "小黄")
private String roleName;
@Schema(description = "知识库段落", example = "Java 开发手册")
@Data
public static class KnowledgeSegment {
@Schema(description = "段落编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册")
private String content;
@Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790")
private Long documentId;
@Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品使用手册")
private String documentName;
}
}

View File

@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - AI 聊天消息发送 Response VO")
@Data
@ -28,6 +29,12 @@ public class AiChatMessageSendRespVO {
@Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
private String content;
@Schema(description = "知识库段落编号数组", example = "[1,2,3]")
private List<Long> segmentIds;
@Schema(description = "知识库段落数组")
private List<AiChatMessageRespVO.KnowledgeSegment> segments;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;

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