Переглянути джерело

Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/1.8.0-uniapp

 Conflicts:
	sql/ruoyi-vue-pro.sql
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.http
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/package-info.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressBaseVO.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressCreateReqVO.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressRespVO.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/vo/AppAddressUpdateReqVO.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/package-info.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/enums/AddressTypeEnum.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java
	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java
	yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java
YunaiV 3 роки тому
батько
коміт
3a0feef402
100 змінених файлів з 840 додано та 59 видалено
  1. 2 2
      Jenkinsfile
  2. 6 4
      README.md
  3. 15 20
      bin/deploy.sh
  4. 1 1
      pom.xml
  5. 0 0
      sql/bpm-activiti.sql
  6. 9 3
      yudao-dependencies/pom.xml
  7. 23 0
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java
  8. 2 1
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
  9. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java
  10. 2 2
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPayClientConfig.java
  11. 5 1
      yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml
  12. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java
  13. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java
  14. 13 3
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java
  15. 3 1
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java
  16. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java
  17. 41 0
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsChannelProperties.java
  18. 302 0
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java
  19. 50 0
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMapping.java
  20. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java
  21. 2 2
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java
  22. 4 0
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java
  23. 3 3
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java
  24. 222 0
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java
  25. 50 0
      yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMappingTest.java
  26. 5 1
      yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java
  27. 58 0
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/StringLiSTTypeHandler.java
  28. 3 3
      yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java
  29. 5 5
      yudao-module-bpm/pom.xml
  30. 1 0
      yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java
  31. 1 1
      yudao-module-bpm/yudao-module-bpm-biz-activiti/pom.xml
  32. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java
  33. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
  34. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
  35. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.http
  36. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
  37. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.http
  38. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
  39. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java
  40. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http
  41. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
  42. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.http
  43. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
  44. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java
  45. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java
  46. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java
  47. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java
  48. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java
  49. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java
  50. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java
  51. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java
  52. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
  53. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
  54. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/config/BpmActivitiConfiguration.java
  55. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java
  56. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehavior.java
  57. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/package-info.java
  58. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java
  59. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java
  60. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java
  61. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java
  62. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java
  63. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java
  64. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java
  65. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java
  66. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTaskEventListener.java
  67. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/package-info.java
  68. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java
  69. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java
  70. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java
  71. 3 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
  72. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java
  73. 3 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
  74. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java
  75. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java
  76. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java
  77. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java
  78. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java
  79. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
  80. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
  81. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
  82. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java
  83. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehaviorTest.java
  84. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java
  85. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/java/cn/iocoder/yudao/module/bpm/service/package-info.java
  86. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/application-unit-test.yaml
  87. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/logback.xml
  88. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/sql/clean.sql
  89. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/sql/create_tables.sql
  90. 1 1
      yudao-module-bpm/yudao-module-bpm-biz-flowable/pom.xml
  91. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java
  92. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
  93. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java
  94. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java
  95. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java
  96. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java
  97. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
  98. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
  99. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java
  100. 0 0
      yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java

+ 2 - 2
Jenkinsfile

@@ -21,7 +21,7 @@ pipeline {
         // GitHub 账号名
         GITHUB_ACCOUNT = 'https://gitee.com/zhijiantianya/ruoyi-vue-pro'
         // 应用名称
-        APP_NAME = 'yudao-admin-server'
+        APP_NAME = 'yudao-server'
         // 应用部署路径
         APP_DEPLOY_BASE_DIR = '/media/pi/KINGTON/data/work/projects/'
     }
@@ -57,4 +57,4 @@ pipeline {
             }
         }
     }
-}
+}

+ 6 - 4
README.md

@@ -7,19 +7,21 @@
 
 ## 🐯 平台简介
 
-**芋道**,一套**全部开源**的**企业级**的快速开发平台,毫无保留给个人及企业免费使用。
+**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
 
 > 有任何问题,或者想要的功能,可以在 _Issues_ 中提给艿艿。
+>
+> 😜 给项目点点 Star 吧,这对我们真的很重要!
 
 * 前端采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) ,正在支持 Vue 3 + ElementUI Plus 最新方案。
 * 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson。
 * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统。
 * 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能。
 * 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装。
-* 工作流使用 Activiti ,支持动态表单、在线设计流程、多种任务分配方式。
+* 工作流使用 Activiti + Flowable,支持动态表单、在线设计流程、多种任务分配方式。
 * 高效率开发,使用代码生成器可以一键生成前后端代码 + 单元测试 + Swagger 接口文档 + Validator 参数校验。
 * 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款。
-* 集成阿里云、腾讯云、云片等短信渠道,集成阿里云、腾讯云、七牛云等云存储服务。
+* 集成阿里云、腾讯云、云片等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务。
 
 | 项目名                | 说明                     | 传说门                                                                                                                                 |
 |--------------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
@@ -150,7 +152,7 @@ ps:核心功能已经实现,正在对接微信小程序中...
 
 | 框架                                                                                          | 说明               | 版本       | 学习指南                                                           |
 |---------------------------------------------------------------------------------------------|------------------|----------|----------------------------------------------------------------|
-| [Spring Boot](https://spring.io/projects/spring-boot)                                       | 应用开发框架           | 2.5.10   | [文档](https://github.com/YunaiV/SpringBoot-Labs)                |
+| [Spring Boot](https://spring.io/projects/spring-boot)                                       | 应用开发框架           | 2.5.12   | [文档](https://github.com/YunaiV/SpringBoot-Labs)                |
 | [MySQL](https://www.mysql.com/cn/)                                                          | 数据库服务器           | 5.7      |                                                                |
 | [Druid](https://github.com/alibaba/druid)                                                   | JDBC 连接池、监控组件    | 1.2.8    | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
 | [MyBatis Plus](https://mp.baomidou.com/)                                                    | MyBatis 增强工具包    | 3.5.1    | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao)         |

+ 15 - 20
bin/deploy.sh

@@ -1,20 +1,15 @@
 #!/bin/bash
 set -e
 
-# 基础
-# export JAVA_HOME=/work/programs/jdk/jdk1.8.0_181
-# export PATH=PATH=$PATH:$JAVA_HOME/bin
-# export CLASSPATH=$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
-
 DATE=$(date +%Y%m%d%H%M)
 # 基础路径
-BASE_PATH=/media/pi/KINGTON/data/work/projects/yudao-admin-server
+BASE_PATH=/work/projects/yudao-server
 # 编译后 jar 的地址。部署时,Jenkins 会上传 jar 包到该目录下
 SOURCE_PATH=$BASE_PATH/build
 # 服务名称。同时约定部署服务的 jar 包名字也为它。
-SERVER_NAME=yudao-admin-server
+SERVER_NAME=yudao-server
 # 环境
-PROFILES_ACTIVE=dev
+PROFILES_ACTIVE=development
 # 健康检查 URL
 HEALTH_CHECK_URL=http://127.0.0.1:48080/actuator/health/
 
@@ -62,7 +57,7 @@ function transfer() {
     echo "[transfer] 转移 $SERVER_NAME.jar 完成"
 }
 
-# 停止
+# 停止:优雅关闭之前已经启动的服务
 function stop() {
     echo "[stop] 开始停止 $BASE_PATH/$SERVER_NAME"
     PID=$(ps -ef | grep $BASE_PATH/$SERVER_NAME | grep -v "grep" | awk '{print $2}')
@@ -71,8 +66,8 @@ function stop() {
         # 正常关闭
         echo "[stop] $BASE_PATH/$SERVER_NAME 运行中,开始 kill [$PID]"
         kill -15 $PID
-        # 等待最大 60 秒,直到关闭完成。
-        for ((i = 0; i < 60; i++))
+        # 等待最大 120 秒,直到关闭完成。
+        for ((i = 0; i < 120; i++))
             do
                 sleep 1
                 PID=$(ps -ef | grep $BASE_PATH/$SERVER_NAME | grep -v "grep" | awk '{print $2}')
@@ -95,7 +90,7 @@ function stop() {
     fi
 }
 
-# 启动
+# 启动:启动后端项目
 function start() {
     # 开启启动前,打印启动参数
     echo "[start] 开始启动 $BASE_PATH/$SERVER_NAME"
@@ -108,13 +103,13 @@ function start() {
     echo "[start] 启动 $BASE_PATH/$SERVER_NAME 完成"
 }
 
-# 健康检查
+# 健康检查:自动判断后端项目是否正常启动
 function healthCheck() {
     # 如果配置健康检查,则进行健康检查
     if [ -n "$HEALTH_CHECK_URL" ]; then
-        # 健康检查最大 60 秒,直到健康检查通过
+        # 健康检查最大 120 秒,直到健康检查通过
         echo "[healthCheck] 开始通过 $HEALTH_CHECK_URL 地址,进行健康检查";
-        for ((i = 0; i < 60; i++))
+        for ((i = 0; i < 120; i++))
             do
                 # 请求健康检查地址,只获取状态码。
                 result=`curl -I -m 10 -o /dev/null -s -w %{http_code} $HEALTH_CHECK_URL || echo "000"`
@@ -138,11 +133,11 @@ function healthCheck() {
         else
             tail -n 10 nohup.out
         fi
-    # 如果未配置健康检查,则 slepp 60 秒,人工看日志是否部署成功。
+    # 如果未配置健康检查,则 sleep 120 秒,人工看日志是否部署成功。
     else
-        echo "[healthCheck] HEALTH_CHECK_URL 未配置,开始 sleep 60 秒";
-        sleep 60
-        echo "[healthCheck] sleep 60 秒完成,查看日志,自行判断是否启动成功";
+        echo "[healthCheck] HEALTH_CHECK_URL 未配置,开始 sleep 120 秒";
+        sleep 120
+        echo "[healthCheck] sleep 120 秒完成,查看日志,自行判断是否启动成功";
         tail -n 50 nohup.out
     fi
 }
@@ -159,7 +154,7 @@ function deploy() {
     # 启动 Java 服务
     start
     # 健康检查
-#    healthCheck
+    healthCheck
 }
 
 deploy

+ 1 - 1
pom.xml

@@ -25,7 +25,7 @@
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
     <properties>
-        <revision>1.6.1-snapshot</revision>
+        <revision>1.6.2-snapshot</revision>
         <!-- Maven 相关 -->
         <java.version>1.8</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
sql/bpm-activiti.sql


+ 9 - 3
yudao-dependencies/pom.xml

@@ -14,9 +14,9 @@
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
     <properties>
-        <revision>1.6.1-snapshot</revision>
+        <revision>1.6.2-snapshot</revision>
         <!-- 统一依赖管理 -->
-        <spring.boot.version>2.5.10</spring.boot.version>
+        <spring.boot.version>2.5.12</spring.boot.version>
         <!-- Web 相关 -->
         <knife4j.version>3.0.2</knife4j.version>
         <swagger-annotations.version>1.5.22</swagger-annotations.version>
@@ -26,7 +26,7 @@
         <druid.version>1.2.8</druid.version>
         <mybatis-plus.version>3.4.3.4</mybatis-plus.version>
         <dynamic-datasource.version>3.5.0</dynamic-datasource.version>
-        <redisson.version>3.16.6</redisson.version>
+        <redisson.version>3.17.0</redisson.version>
         <!-- Config 配置中心相关 -->
         <apollo.version>1.9.2</apollo.version>
         <!-- Job 定时任务相关 -->
@@ -60,6 +60,7 @@
         <minio.version>8.2.2</minio.version>
         <aliyun-java-sdk-core.version>4.5.25</aliyun-java-sdk-core.version>
         <aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>
+        <tencentcloud-sdk-java.version>3.1.471</tencentcloud-sdk-java.version>
         <yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
         <justauth.version>1.4.0</justauth.version>
     </properties>
@@ -552,6 +553,11 @@
                 <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
                 <version>${aliyun-java-sdk-dysmsapi.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.tencentcloudapi</groupId>
+                <artifactId>tencentcloud-sdk-java</artifactId>
+                <version>${tencentcloud-sdk-java.version}</version>
+            </dependency>
             <!-- SMS SDK end -->
 
             <dependency>

+ 23 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java

@@ -1,8 +1,19 @@
 package cn.iocoder.yudao.framework.common.util.collection;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.TypeUtil;
+import org.springframework.cglib.core.TypeUtils;
 
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Function;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 
 /**
  * Array 工具类
@@ -30,4 +41,16 @@ public class ArrayUtils {
         return result;
     }
 
+    public static <T, V> V[] toArray(Collection<T> from, Function<T, V> mapper) {
+        return toArray(convertList(from, mapper));
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T[] toArray(Collection<T> from) {
+        if (CollectionUtil.isEmpty(from)) {
+            return (T[]) (new Object[0]);
+        }
+        return ArrayUtil.toArray(from, (Class<T>) CollectionUtil.getElementType(from.iterator()));
+    }
+
 }

+ 2 - 1
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java

@@ -115,7 +115,7 @@ public class CollectionUtils {
             return new HashMap<>();
         }
         return from.stream()
-                   .collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toList())));
+                .collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toList())));
     }
 
     // 暂时没想好名字,先以 2 结尾噶
@@ -169,4 +169,5 @@ public class CollectionUtils {
     public static <T> Collection<T> singleton(T deptId) {
         return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
     }
+
 }

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/dept/rule/DeptDataPermissionRule.java

@@ -35,7 +35,7 @@ import java.util.Set;
  * 注意,使用 DeptDataPermissionRule 时,需要保证表中有 dept_id 部门编号的字段,可自定义。
  *
  * 实际业务场景下,会存在一个经典的问题?当用户修改部门时,冗余的 dept_id 是否需要修改?
- * 1. 一般情况下,dept_id 不进行修改,则会导致用户看到之前的数据。【yudao-admin-server 采用该方案】
+ * 1. 一般情况下,dept_id 不进行修改,则会导致用户看到之前的数据。【yudao-server 采用该方案】
  * 2. 部分情况下,希望该用户还是能看到之前的数据,则有两种方式解决:【需要你改造该 DeptDataPermissionRule 的实现代码】
  *  1)编写洗数据的脚本,将 dept_id 修改成新部门的编号;【建议】
  *      最终过滤条件是 WHERE dept_id = ?

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPayClientConfig.java

@@ -82,9 +82,9 @@ public class WXPayClientConfig implements PayClientConfig {
     @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class)
     private String privateCertContent;
     /**
-     * apiV3 钥值
+     * apiV3 钥值
      */
-    @NotBlank(message = "apiV3 钥值 不能为空", groups = V3.class)
+    @NotBlank(message = "apiV3 钥值 不能为空", groups = V3.class)
     private String apiV3Key;
 
     /**

+ 5 - 1
yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml

@@ -12,7 +12,7 @@
     <packaging>jar</packaging>
 
     <name>${project.artifactId}</name>
-    <description>短信拓展,支持阿里云、云片</description>
+    <description>短信拓展,支持阿里云、云片、腾讯云</description>
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
     <dependencies>
@@ -77,6 +77,10 @@
             <groupId>com.aliyun</groupId>
             <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java</artifactId>
+        </dependency>
         <!-- SMS SDK end -->
     </dependencies>
 

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java

@@ -11,7 +11,7 @@ import java.util.List;
  * 短信客户端,用于对接各短信平台的 SDK,实现短信发送等功能
  *
  * @author zzf
- * @date 2021/1/25 14:14
+ * @since 2021/1/25 14:14
  */
 public interface SmsClient {
 

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java

@@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
  * 短信客户端的工厂接口
  *
  * @author zzf
- * @date 2021/1/28 14:01
+ * @since 2021/1/28 14:01
  */
 public interface SmsClientFactory {
 

+ 13 - 3
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java

@@ -16,7 +16,7 @@ import java.util.List;
  * 短信客户端的抽象类,提供模板方法,减少子类的冗余代码
  *
  * @author zzf
- * @date 2021/2/1 9:28
+ * @since 2021/2/1 9:28
  */
 @Slf4j
 public abstract class AbstractSmsClient implements SmsClient {
@@ -31,7 +31,7 @@ public abstract class AbstractSmsClient implements SmsClient {
     protected final SmsCodeMapping codeMapping;
 
     public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) {
-        this.properties = properties;
+        this.properties = prepareProperties(properties);
         this.codeMapping = codeMapping;
     }
 
@@ -54,11 +54,21 @@ public abstract class AbstractSmsClient implements SmsClient {
             return;
         }
         log.info("[refresh][配置({})发生变化,重新初始化]", properties);
-        this.properties = properties;
+        this.properties = prepareProperties(properties);
         // 初始化
         this.init();
     }
 
+    /**
+     * 在赋值给{@link this#properties}前,子类可根据需要预处理短信渠道配置
+     *
+     * @param properties 数据库中存储的短信渠道配置
+     * @return 满足子类实现的短信渠道配置
+     */
+    protected SmsChannelProperties prepareProperties(SmsChannelProperties properties) {
+        return properties;
+    }
+
     @Override
     public Long getId() {
         return properties.getId();

+ 3 - 1
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.sms.core.client.SmsClient;
 import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;
 import cn.iocoder.yudao.framework.sms.core.client.impl.aliyun.AliyunSmsClient;
 import cn.iocoder.yudao.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient;
+import cn.iocoder.yudao.framework.sms.core.client.impl.tencent.TencentSmsClient;
 import cn.iocoder.yudao.framework.sms.core.client.impl.yunpian.YunpianSmsClient;
 import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum;
 import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
@@ -44,7 +45,7 @@ public class SmsClientFactoryImpl implements SmsClientFactory {
         Arrays.stream(SmsChannelEnum.values()).forEach(channel -> {
             // 创建一个空的 SmsChannelProperties 对象
             SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode())
-                    .setApiKey("default").setApiSecret("default");
+                    .setApiKey("default default").setApiSecret("default");
             // 创建 Sms 客户端
             AbstractSmsClient smsClient = createSmsClient(properties);
             channelCodeClients.put(channel.getCode(), smsClient);
@@ -81,6 +82,7 @@ public class SmsClientFactoryImpl implements SmsClientFactory {
             case ALIYUN: return new AliyunSmsClient(properties);
             case YUN_PIAN: return new YunpianSmsClient(properties);
             case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties);
+            case TENCENT: return new TencentSmsClient(properties);
         }
         // 创建失败,错误日志 + 抛出异常
         log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties);

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java

@@ -41,7 +41,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE
  * 阿里短信客户端的实现类
  *
  * @author zzf
- * @date 2021/1/25 14:17
+ * @since 2021/1/25 14:17
  */
 @Slf4j
 public class AliyunSmsClient extends AbstractSmsClient {

+ 41 - 0
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsChannelProperties.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.framework.sms.core.client.impl.tencent;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.Assert;
+import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
+import lombok.Data;
+
+/**
+ * 腾讯云短信配置实现类
+ * 腾讯云发送短信时,需要额外的参数 sdkAppId,
+ *
+ * @author shiwp
+ */
+@Data
+public class TencentSmsChannelProperties extends SmsChannelProperties {
+
+    /**
+     * 应用 id
+     */
+    private String sdkAppId;
+
+    /**
+     * 考虑到不破坏原有的 apiKey + apiSecret 的结构,
+     * 所以腾讯云短信存储时,将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。
+     * 因此在使用时,需要将 secretId 和 sdkAppId 解析出来,分别存储到对应字段中。
+     */
+    public static TencentSmsChannelProperties build(SmsChannelProperties properties) {
+        if (properties instanceof TencentSmsChannelProperties) {
+            return (TencentSmsChannelProperties) properties;
+        }
+        TencentSmsChannelProperties result = BeanUtil.toBean(properties, TencentSmsChannelProperties.class);
+        String combineKey = properties.getApiKey();
+        Assert.notEmpty(combineKey, "apiKey 不能为空");
+        String[] keys = combineKey.trim().split(" ");
+        Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]");
+        Assert.notBlank(keys[0], "腾讯云短信 secretId 不能为空");
+        Assert.notBlank(keys[1], "腾讯云短信 sdkAppId 不能为空");
+        result.setSdkAppId(keys[1]).setApiKey(keys[0]);
+        return result;
+    }
+}

+ 302 - 0
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java

@@ -0,0 +1,302 @@
+package cn.iocoder.yudao.framework.sms.core.client.impl.tencent;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.core.KeyValue;
+import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
+import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO;
+import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
+import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient;
+import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
+import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.annotations.VisibleForTesting;
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import com.tencentcloudapi.sms.v20210111.SmsClient;
+import com.tencentcloudapi.sms.v20210111.models.*;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
+
+/**
+ * 腾讯云短信功能实现
+ * <p>
+ * 参见 https://cloud.tencent.com/document/product/382/52077
+ *
+ * @author shiwp
+ */
+public class TencentSmsClient extends AbstractSmsClient {
+
+    /**
+     * 调用成功 code
+     */
+    public static final String API_SUCCESS_CODE = "Ok";
+
+    /**
+     * REGION,使用南京
+     */
+    private static final String ENDPOINT = "ap-nanjing";
+
+    /**
+     * 是否国际/港澳台短信:
+     * 0:表示国内短信。
+     * 1:表示国际/港澳台短信。
+     */
+    private static final long INTERNATIONAL = 0L;
+
+    private SmsClient client;
+
+    public TencentSmsClient(SmsChannelProperties properties) {
+        super(properties, new TencentSmsCodeMapping());
+        Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
+    }
+
+    @Override
+    protected void doInit() {
+        // 实例化一个认证对象,入参需要传入腾讯云账户密钥对 secretId,secretKey
+        Credential credential = new Credential(properties.getApiKey(), properties.getApiSecret());
+        client = new SmsClient(credential, ENDPOINT);
+    }
+
+    @Override
+    protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId,
+                                                        String mobile,
+                                                        String apiTemplateId,
+                                                        List<KeyValue<String, Object>> templateParams) throws Throwable {
+        return invoke(() -> buildSendSmsRequest(sendLogId, mobile, apiTemplateId, templateParams),
+                this::doSendSms0,
+                response -> {
+                    SendStatus sendStatus = response.getSendStatusSet()[0];
+                    return SmsCommonResult.build(sendStatus.getCode(), sendStatus.getMessage(), response.getRequestId(),
+                            new SmsSendRespDTO().setSerialNo(sendStatus.getSerialNo()), codeMapping);
+                });
+    }
+
+
+    /**
+     * 腾讯云发放短信的时候,需要额外的参数 sdkAppId。
+     * 考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。
+     * 因此,这边需要使用 TencentSmsChannelProperties 做拆分,重新封装到 properties 内。
+     *
+     * @param properties 数据库中存储的短信渠道配置
+     * @return TencentSmsChannelProperties
+     */
+    @Override
+    protected SmsChannelProperties prepareProperties(SmsChannelProperties properties) {
+        return TencentSmsChannelProperties.build(properties);
+    }
+
+    /**
+     * 调用腾讯云 SDK 发送短信
+     *
+     * @param request 发送短信请求
+     * @return 发送短信响应
+     * @throws TencentCloudSDKException SDK 用来封装发送短信失败
+     */
+    private SendSmsResponse doSendSms0(SendSmsRequest request) throws TencentCloudSDKException {
+        return client.SendSms(request);
+    }
+
+    /**
+     * 封装腾讯云发送短信请求
+     *
+     * @param sendLogId      日志编号
+     * @param mobile         手机号
+     * @param apiTemplateId  短信 API 的模板编号
+     * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序
+     * @return 腾讯云发送短信请求
+     */
+    private SendSmsRequest buildSendSmsRequest(Long sendLogId,
+                                               String mobile,
+                                               String apiTemplateId,
+                                               List<KeyValue<String, Object>> templateParams) {
+        SendSmsRequest request = new SendSmsRequest();
+        request.setSmsSdkAppId(((TencentSmsChannelProperties) properties).getSdkAppId());
+        request.setPhoneNumberSet(new String[]{mobile});
+        request.setSignName(properties.getSignature());
+        request.setTemplateId(apiTemplateId);
+        request.setTemplateParamSet(ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue())));
+        request.setSessionContext(JsonUtils.toJsonString(new SessionContext().setLogId(sendLogId)));
+        return request;
+    }
+
+    @Override
+    protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
+        List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class);
+        return CollectionUtils.convertList(callback, status -> {
+            SmsReceiveRespDTO data = new SmsReceiveRespDTO();
+            data.setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription());
+            data.setReceiveTime(status.getReceiveTime()).setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus()));
+            data.setMobile(status.getMobile()).setSerialNo(status.getSerialNo());
+            SessionContext context;
+            Long logId;
+            Assert.notNull(context = status.getSessionContext(), "回执信息中未解析出 context,请联系腾讯云小助手");
+            Assert.notNull(logId = context.getLogId(), "回执信息中未解析出 logId,请联系腾讯云小助手");
+            data.setLogId(logId);
+            return data;
+        });
+    }
+
+    @Override
+    protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable {
+        return invoke(() -> this.buildSmsTemplateStatusRequest(apiTemplateId),
+                this::doGetSmsTemplate0,
+                response -> {
+                    SmsTemplateRespDTO data = convertTemplateStatusDTO(response.getDescribeTemplateStatusSet()[0]);
+                    return SmsCommonResult.build(API_SUCCESS_CODE, null, response.getRequestId(), data, codeMapping);
+                });
+    }
+
+    @VisibleForTesting
+    SmsTemplateRespDTO convertTemplateStatusDTO(DescribeTemplateListStatus templateStatus) {
+        if (templateStatus == null) {
+            return null;
+        }
+        SmsTemplateAuditStatusEnum auditStatus;
+        Assert.notNull(templateStatus.getStatusCode(),
+                StrUtil.format("短信模版审核状态为 null,模版 id{}", templateStatus.getTemplateId()));
+        switch (templateStatus.getStatusCode().intValue()) {
+            case -1:
+                auditStatus = SmsTemplateAuditStatusEnum.FAIL;
+                break;
+            case 0:
+                auditStatus = SmsTemplateAuditStatusEnum.SUCCESS;
+                break;
+            case 1:
+                auditStatus = SmsTemplateAuditStatusEnum.CHECKING;
+                break;
+            default:
+                throw new IllegalStateException(StrUtil.format("不能解析短信模版审核状态{},模版 id{}",
+                        templateStatus.getStatusCode(), templateStatus.getTemplateId()));
+        }
+        SmsTemplateRespDTO data = new SmsTemplateRespDTO();
+        data.setId(String.valueOf(templateStatus.getTemplateId())).setContent(templateStatus.getTemplateContent());
+        data.setAuditStatus(auditStatus.getStatus()).setAuditReason(templateStatus.getReviewReply());
+        return data;
+    }
+
+    /**
+     * 封装查询模版审核状态请求
+     * @param apiTemplateId api 的模版 id
+     * @return 查询模版审核状态请求
+     */
+    private DescribeSmsTemplateListRequest buildSmsTemplateStatusRequest(String apiTemplateId) {
+        DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest();
+        request.setTemplateIdSet(new Long[]{Long.parseLong(apiTemplateId)});
+        // 地区 0:表示国内短信。1:表示国际/港澳台短信。
+        request.setInternational(INTERNATIONAL);
+        return request;
+    }
+
+    /**
+     * 调用腾讯云 SDK 查询短信模版状态
+     *
+     * @param request 查询短信模版状态请求
+     * @return 查询短信模版状态响应
+     * @throws TencentCloudSDKException SDK 用来封装查询短信模版状态失败
+     */
+    private DescribeSmsTemplateListResponse doGetSmsTemplate0(DescribeSmsTemplateListRequest request) throws TencentCloudSDKException {
+        return client.DescribeSmsTemplateList(request);
+    }
+
+    <Q, P, R> SmsCommonResult<R> invoke(Supplier<Q> requestSupplier,
+                                        SdkFunction<Q, P> responseSupplier,
+                                        Function<P, SmsCommonResult<R>> resultGen) {
+        // 构建请求body
+        Q request = requestSupplier.get();
+        P response;
+        // 调用腾讯云发送短信
+        try {
+            response = responseSupplier.apply(request);
+        } catch (TencentCloudSDKException e) {
+            // 调用异常,封装结果
+            return SmsCommonResult.build(e.getErrorCode(), e.getMessage(), e.getRequestId(), null, codeMapping);
+        }
+        return resultGen.apply(response);
+    }
+
+    @Data
+    private static class SmsReceiveStatus {
+
+        /**
+         * 短信接受成功 code
+         */
+        public static final String SUCCESS_CODE = "SUCCESS";
+
+        /**
+         * 用户实际接收到短信的时间
+         */
+        @JsonProperty("user_receive_time")
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
+        private Date receiveTime;
+
+        /**
+         * 国家(或地区)码
+         */
+        @JsonProperty("nationcode")
+        private String nationCode;
+
+        /**
+         * 手机号码
+         */
+        private String mobile;
+
+        /**
+         * 实际是否收到短信接收状态,SUCCESS(成功)、FAIL(失败)
+         */
+        @JsonProperty("report_status")
+        private String status;
+
+        /**
+         * 用户接收短信状态码错误信息
+         */
+        @JsonProperty("errmsg")
+        private String errCode;
+
+        /**
+         * 用户接收短信状态描述
+         */
+        @JsonProperty("description")
+        private String description;
+
+        /**
+         * 本次发送标识 ID(与发送接口返回的SerialNo对应)
+         */
+        @JsonProperty("sid")
+        private String serialNo;
+
+        /**
+         * 用户的 session 内容(与发送接口的请求参数SessionContext一致)
+         */
+        @JsonProperty("ext")
+        private SessionContext sessionContext;
+
+    }
+
+    @VisibleForTesting
+    @Data
+    static class SessionContext {
+
+        /**
+         * 发送短信记录id
+         */
+        private Long logId;
+    }
+
+    private interface SdkFunction<T, R> {
+        R apply(T t) throws TencentCloudSDKException;
+    }
+
+}

+ 50 - 0
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMapping.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.framework.sms.core.client.impl.tencent;
+
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
+import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping;
+import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
+
+import static cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*;
+
+/**
+ * 腾讯云的 SmsCodeMapping 实现类
+ *
+ * 参见 https://cloud.tencent.com/document/api/382/52075#.E5.85.AC.E5.85.B1.E9.94.99.E8.AF.AF.E7.A0.81
+ *
+ * @author : shiwp
+ */
+public class TencentSmsCodeMapping implements SmsCodeMapping {
+
+    @Override
+    public ErrorCode apply(String apiCode) {
+        switch (apiCode) {
+            case TencentSmsClient.API_SUCCESS_CODE: return GlobalErrorCodeConstants.SUCCESS;
+            case "FailedOperation.ContainSensitiveWord": return SMS_SEND_CONTENT_INVALID;
+            case "FailedOperation.JsonParseFail":
+            case "MissingParameter.EmptyPhoneNumberSet":
+            case "LimitExceeded.PhoneNumberCountLimit":
+            case "FailedOperation.FailResolvePacket": return GlobalErrorCodeConstants.BAD_REQUEST;
+            case "FailedOperation.InsufficientBalanceInSmsPackage": return SMS_ACCOUNT_MONEY_NOT_ENOUGH;
+            case "FailedOperation.MarketingSendTimeConstraint": return SMS_SEND_MARKET_LIMIT_CONTROL;
+            case "FailedOperation.PhoneNumberInBlacklist": return SMS_MOBILE_BLACK;
+            case "FailedOperation.SignatureIncorrectOrUnapproved": return SMS_SIGN_INVALID;
+            case "FailedOperation.MissingTemplateToModify":
+            case "FailedOperation.TemplateIncorrectOrUnapproved": return SMS_TEMPLATE_INVALID;
+            case "InvalidParameterValue.IncorrectPhoneNumber": return SMS_MOBILE_INVALID;
+            case "InvalidParameterValue.SdkAppIdNotExist": return SMS_APP_ID_INVALID;
+            case "InvalidParameterValue.TemplateParameterLengthLimit":
+            case "InvalidParameterValue.TemplateParameterFormatError": return SMS_TEMPLATE_PARAM_ERROR;
+            case "LimitExceeded.PhoneNumberDailyLimit": return SMS_SEND_DAY_LIMIT_CONTROL;
+            case "LimitExceeded.PhoneNumberThirtySecondLimit":
+            case "LimitExceeded.PhoneNumberOneHourLimit": return SMS_SEND_BUSINESS_LIMIT_CONTROL;
+            case "UnauthorizedOperation.RequestPermissionDeny":
+            case "FailedOperation.ForbidAddMarketingTemplates":
+            case "FailedOperation.NotEnterpriseCertification":
+            case "UnauthorizedOperation.IndividualUserMarketingSmsPermissionDeny": return SMS_PERMISSION_DENY;
+            case "UnauthorizedOperation.RequestIpNotInWhitelist": return SMS_IP_DENY;
+            case "AuthFailure.SecretIdNotFound": return SMS_ACCOUNT_INVALID;
+        }
+        return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
+    }
+}

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java

@@ -35,7 +35,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE
  * 云片短信客户端的实现类
  *
  * @author zzf
- * @date 9:48 2021/3/5
+ * @since 9:48 2021/3/5
  */
 @Slf4j
 public class YunpianSmsClient extends AbstractSmsClient {

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java

@@ -8,7 +8,7 @@ import lombok.Getter;
  * 短信渠道枚举
  *
  * @author zzf
- * @date 2021/1/25 10:56
+ * @since 2021/1/25 10:56
  */
 @Getter
 @AllArgsConstructor
@@ -17,7 +17,7 @@ public enum SmsChannelEnum {
     DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"),
     YUN_PIAN("YUN_PIAN", "云片"),
     ALIYUN("ALIYUN", "阿里云"),
-//    TENCENT("TENCENT", "腾讯云"),
+    TENCENT("TENCENT", "腾讯云"),
 //    HUA_WEI("HUA_WEI", "华为云"),
     ;
 

+ 4 - 0
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java

@@ -26,6 +26,9 @@ public interface SmsFrameworkErrorCodeConstants {
 
     ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词");
 
+    // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。
+    ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2001000105, "营销短信发送时间限制");
+
     // ========== 模板相关 2001000200 ==========
     ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在
     ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确");
@@ -41,6 +44,7 @@ public interface SmsFrameworkErrorCodeConstants {
     ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失");
     ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确");
     ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中");
+    ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2001000903, "SdkAppId不合法");
 
     ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常");
 

+ 3 - 3
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java

@@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
  * 短信渠道配置类
  *
  * @author zzf
- * @date 2021/1/25 17:01
+ * @since 2021/1/25 17:01
  */
 @Data
 @Validated
@@ -40,9 +40,9 @@ public class SmsChannelProperties {
     @NotEmpty(message = "短信 API 的账号不能为空")
     private String apiKey;
     /**
-     * 短信 API 的
+     * 短信 API 的
      */
-    @NotEmpty(message = "短信 API 的钥不能为空")
+    @NotEmpty(message = "短信 API 的钥不能为空")
     private String apiSecret;
     /**
      * 短信发送回调 URL

+ 222 - 0
yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java

@@ -0,0 +1,222 @@
+package cn.iocoder.yudao.framework.sms.core.client.impl.tencent;
+
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.core.KeyValue;
+import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
+import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.date.DateUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
+import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO;
+import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
+import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
+import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
+import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import com.google.common.collect.Lists;
+import com.tencentcloudapi.sms.v20210111.SmsClient;
+import com.tencentcloudapi.sms.v20210111.models.DescribeSmsTemplateListResponse;
+import com.tencentcloudapi.sms.v20210111.models.DescribeTemplateListStatus;
+import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
+import com.tencentcloudapi.sms.v20210111.models.SendStatus;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.when;
+
+/**
+ * {@link TencentSmsClient} 的单元测试
+ *
+ * @author shiwp
+ */
+public class TencentSmsClientTest extends BaseMockitoUnitTest {
+
+    private final SmsChannelProperties properties = new SmsChannelProperties()
+            .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
+            .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
+            .setSignature("芋道源码");
+
+    @InjectMocks
+    private TencentSmsClient smsClient = new TencentSmsClient(properties);
+
+    @Mock
+    private SmsClient client;
+
+    @Test
+    public void testDoInit() {
+        // 准备参数
+        // mock 方法
+
+        // 调用
+        smsClient.doInit();
+        // 断言
+        assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
+    }
+
+    @Test
+    public void testRefresh() {
+        // 准备参数
+        SmsChannelProperties p = new SmsChannelProperties()
+                .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
+                .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
+                .setSignature("芋道源码");
+        // 调用
+        smsClient.refresh(p);
+        // 断言
+        assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
+    }
+
+    @Test
+    public void testDoSendSms() throws Throwable {
+        // 准备参数
+        Long sendLogId = randomLongId();
+        String mobile = randomString();
+        String apiTemplateId = randomString();
+        List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
+                new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
+        String requestId = randomString();
+        String serialNo = randomString();
+        // mock 方法
+        SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
+            o.setRequestId(requestId);
+            SendStatus[] sendStatuses = new SendStatus[1];
+            o.setSendStatusSet(sendStatuses);
+            SendStatus sendStatus = new SendStatus();
+            sendStatuses[0] = sendStatus;
+            sendStatus.setCode(TencentSmsClient.API_SUCCESS_CODE);
+            sendStatus.setMessage("send success");
+            sendStatus.setSerialNo(serialNo);
+        });
+        when(client.SendSms(argThat(request -> {
+            assertEquals(mobile, request.getPhoneNumberSet()[0]);
+            assertEquals(properties.getSignature(), request.getSignName());
+            assertEquals(apiTemplateId, request.getTemplateId());
+            assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
+                    toJsonString(request.getTemplateParamSet()));
+            assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
+            return true;
+        }))).thenReturn(response);
+
+        // 调用
+        SmsCommonResult<SmsSendRespDTO> result = smsClient.doSendSms(sendLogId, mobile,
+                apiTemplateId, templateParams);
+        // 断言
+        assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
+        assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
+        assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode());
+        assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg());
+        assertEquals(response.getRequestId(), result.getApiRequestId());
+        // 断言结果
+        assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getData().getSerialNo());
+    }
+
+    @Test
+    public void testDoTParseSmsReceiveStatus() throws Throwable {
+        // 准备参数
+        String text = "[\n" +
+                "    {\n" +
+                "        \"user_receive_time\": \"2015-10-17 08:03:04\",\n" +
+                "        \"nationcode\": \"86\",\n" +
+                "        \"mobile\": \"13900000001\",\n" +
+                "        \"report_status\": \"SUCCESS\",\n" +
+                "        \"errmsg\": \"DELIVRD\",\n" +
+                "        \"description\": \"用户短信送达成功\",\n" +
+                "        \"sid\": \"12345\",\n" +
+                "        \"ext\": {\"logId\":\"67890\"}\n" +
+                "    }\n" +
+                "]";
+        // mock 方法
+
+        // 调用
+        List<SmsReceiveRespDTO> statuses = smsClient.doParseSmsReceiveStatus(text);
+        // 断言
+        assertEquals(1, statuses.size());
+        assertTrue(statuses.get(0).getSuccess());
+        assertEquals("DELIVRD", statuses.get(0).getErrorCode());
+        assertEquals("用户短信送达成功", statuses.get(0).getErrorMsg());
+        assertEquals("13900000001", statuses.get(0).getMobile());
+        assertEquals(DateUtils.buildTime(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime());
+        assertEquals("12345", statuses.get(0).getSerialNo());
+        assertEquals(67890L, statuses.get(0).getLogId());
+    }
+
+    @Test
+    public void testDoGetSmsTemplate() throws Throwable {
+        // 准备参数
+        Long apiTemplateId = randomLongId();
+        String requestId = randomString();
+
+        // mock 方法
+        DescribeSmsTemplateListResponse response = randomPojo(DescribeSmsTemplateListResponse.class, o -> {
+            DescribeTemplateListStatus[] describeTemplateListStatuses = new DescribeTemplateListStatus[1];
+            DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus();
+            templateStatus.setTemplateId(apiTemplateId);
+            templateStatus.setStatusCode(0L);// 设置模板通过
+            describeTemplateListStatuses[0] = templateStatus;
+            o.setDescribeTemplateStatusSet(describeTemplateListStatuses);
+            o.setRequestId(requestId);
+        });
+        when(client.DescribeSmsTemplateList(argThat(request -> {
+            assertEquals(apiTemplateId, request.getTemplateIdSet()[0]);
+            return true;
+        }))).thenReturn(response);
+
+        // 调用
+        SmsCommonResult<SmsTemplateRespDTO> result = smsClient.doGetSmsTemplate(apiTemplateId.toString());
+        // 断言
+        assertEquals(TencentSmsClient.API_SUCCESS_CODE, result.getApiCode());
+        assertNull(result.getApiMsg());
+        assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode());
+        assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg());
+        assertEquals(response.getRequestId(), result.getApiRequestId());
+        // 断言结果
+        assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getData().getId());
+        assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getData().getContent());
+        assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus());
+        assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getData().getAuditReason());
+    }
+
+    @Test
+    public void testConvertSuccessTemplateStatus() {
+        testTemplateStatus(SmsTemplateAuditStatusEnum.SUCCESS, 0L);
+    }
+
+    @Test
+    public void testConvertCheckingTemplateStatus() {
+        testTemplateStatus(SmsTemplateAuditStatusEnum.CHECKING, 1L);
+    }
+
+    @Test
+    public void testConvertFailTemplateStatus() {
+        testTemplateStatus(SmsTemplateAuditStatusEnum.FAIL, -1L);
+    }
+
+    @Test
+    public void testConvertUnknownTemplateStatus() {
+        DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus();
+        templateStatus.setStatusCode(3L);
+        Long templateId = randomLongId();
+        // 调用,并断言结果
+        assertThrows(IllegalStateException.class, () -> smsClient.convertTemplateStatusDTO(templateStatus),
+                StrUtil.format("不能解析短信模版审核状态[3],模版id[{}]", templateId));
+    }
+
+    private void testTemplateStatus(SmsTemplateAuditStatusEnum expected, Long value) {
+        DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus();
+        templateStatus.setStatusCode(value);
+        SmsTemplateRespDTO result = smsClient.convertTemplateStatusDTO(templateStatus);
+        assertEquals(expected.getStatus(), result.getAuditStatus());
+    }
+
+}

+ 50 - 0
yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMappingTest.java

@@ -0,0 +1,50 @@
+package cn.iocoder.yudao.framework.sms.core.client.impl.tencent;
+
+import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
+import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * {@link TencentSmsCodeMapping} 的单元测试
+ *
+ * @author : shiwp
+ */
+public class TencentSmsCodeMappingTest extends BaseMockitoUnitTest {
+
+    @InjectMocks
+    private TencentSmsCodeMapping codeMapping;
+
+    @Test
+    public void testApply() {
+        assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(TencentSmsClient.API_SUCCESS_CODE));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("FailedOperation.ContainSensitiveWord"));
+        assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("FailedOperation.JsonParseFail"));
+        assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("MissingParameter.EmptyPhoneNumberSet"));
+        assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("LimitExceeded.PhoneNumberCountLimit"));
+        assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("FailedOperation.FailResolvePacket"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("FailedOperation.InsufficientBalanceInSmsPackage"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_MARKET_LIMIT_CONTROL, codeMapping.apply("FailedOperation.MarketingSendTimeConstraint"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply("FailedOperation.PhoneNumberInBlacklist"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("FailedOperation.SignatureIncorrectOrUnapproved"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("FailedOperation.MissingTemplateToModify"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("FailedOperation.TemplateIncorrectOrUnapproved"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("InvalidParameterValue.IncorrectPhoneNumber"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_APP_ID_INVALID, codeMapping.apply("InvalidParameterValue.SdkAppIdNotExist"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("InvalidParameterValue.TemplateParameterLengthLimit"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("InvalidParameterValue.TemplateParameterFormatError"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberDailyLimit"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberThirtySecondLimit"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberOneHourLimit"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("UnauthorizedOperation.RequestPermissionDeny"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("FailedOperation.ForbidAddMarketingTemplates"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("FailedOperation.NotEnterpriseCertification"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("UnauthorizedOperation.IndividualUserMarketingSmsPermissionDeny"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply("UnauthorizedOperation.RequestIpNotInWhitelist"));
+        assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("AuthFailure.SecretIdNotFound"));
+    }
+
+}

+ 5 - 1
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java

@@ -75,7 +75,7 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
             }
         }
 
-        //检查是否是忽略的 URL, 如果是则允许访问
+        // 如果非允许忽略租户的 URL,则校验租户是否合法
         if (!isIgnoreUrl(request)) {
             // 2. 如果请求未带租户的编号,不允许访问。
             if (tenantId == null) {
@@ -92,6 +92,10 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
                 ServletUtils.writeJSON(response, result);
                 return;
             }
+        } else { // 如果是允许忽略租户的 URL,若未传递租户编号,则默认忽略租户编号,避免报错
+            if (tenantId == null) {
+                TenantContextHolder.setIgnore(true);
+            }
         }
 
         // 继续过滤

+ 58 - 0
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/StringLiSTTypeHandler.java

@@ -0,0 +1,58 @@
+package cn.iocoder.yudao.framework.mybatis.core.type;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+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;
+
+/**
+ * List<String> 的类型转换器实现类,对应数据库的 varchar 类型
+ *
+ * @author 永不言败
+ * @since 2022 3/23 12:50:15
+ */
+@MappedJdbcTypes(JdbcType.VARCHAR)
+@MappedTypes(List.class)
+public class StringLiSTTypeHandler implements TypeHandler<List<String>> {
+
+    private static final String COMMA = ",";
+
+    @Override
+    public void setParameter(PreparedStatement ps, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
+        // 设置占位符
+        ps.setString(i, CollUtil.join(strings, COMMA));
+    }
+
+    @Override
+    public List<String> getResult(ResultSet rs, String columnName) throws SQLException {
+        String value = rs.getString(columnName);
+        return getResult(value);
+    }
+
+    @Override
+    public List<String> getResult(ResultSet rs, int columnIndex) throws SQLException {
+        String value = rs.getString(columnIndex);
+        return getResult(value);
+    }
+
+    @Override
+    public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
+        String value = cs.getString(columnIndex);
+        return getResult(value);
+    }
+
+    private List<String> getResult(String value) {
+        if (value == null) {
+            return null;
+        }
+        return StrUtil.splitTrim(value, COMMA);
+    }
+}

+ 3 - 3
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java

@@ -37,10 +37,10 @@ public class SecurityProperties {
     @NotNull(message = "mock 模式的开关不能为空")
     private Boolean mockEnable;
     /**
-     * mock 模式的
-     * 一定要配置钥,保证安全性
+     * mock 模式的
+     * 一定要配置钥,保证安全性
      */
-    @NotEmpty(message = "mock 模式的钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。
+    @NotEmpty(message = "mock 模式的钥不能为空") // 这里设置了一个默认值,因为实际上只有 mockEnable 为 true 时才需要配置。
     private String mockSecret = "yudaoyuanma";
 
 }

+ 5 - 5
yudao-module-bpm/pom.xml

@@ -11,8 +11,8 @@
     <modules>
         <module>yudao-module-bpm-api</module>
         <module>yudao-module-bpm-base</module>
-        <module>yudao-module-bpm-impl-flowable</module>
-        <module>yudao-module-bpm-impl-activiti</module>
+        <module>yudao-module-bpm-biz-flowable</module>
+        <module>yudao-module-bpm-biz-activiti</module>
     </modules>
     <artifactId>yudao-module-bpm</artifactId>
     <packaging>pom</packaging>
@@ -24,9 +24,9 @@
         bpm 解释:https://baike.baidu.com/item/BPM/1933
 
         目前提供两套实现方案:
-            1. 基于 Activiti 7 实现的 yudao-module-bpm-impl-activiti
-            2. 基于 Flowable 6 实现的 yudao-module-bpm-impl-flowable
-        两套实现会存在共享的逻辑,所以会继承 yudao-module-impl-base
+            1. 基于 Activiti 7 实现的 yudao-module-bpm-biz-activiti
+            2. 基于 Flowable 6 实现的 yudao-module-bpm-biz-flowable
+        两套实现会存在共享的逻辑,所以会继承 yudao-module-bpm-base
     </description>
 
 </project>

+ 1 - 0
yudao-module-bpm/yudao-module-bpm-base/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/definition/BpmProcessDefinitionExtMapper.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.bpm.dal.mysql.definition;
 
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import org.apache.ibatis.annotations.Mapper;

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-impl-activiti/pom.xml → yudao-module-bpm/yudao-module-bpm-biz-activiti/pom.xml

@@ -8,7 +8,7 @@
         <version>${revision}</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>yudao-module-bpm-impl-activiti</artifactId>
+    <artifactId>yudao-module-bpm-biz-activiti</artifactId>
     <packaging>jar</packaging>
 
     <name>${project.artifactId}</name>

+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.http → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.http


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.http → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.http


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.http


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.http → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.http


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmProcessDefinitionConvert.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmTaskAssignRuleConvert.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmActivityConvert.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmProcessInstanceConvert.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/config/BpmActivitiConfiguration.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/config/BpmActivitiConfiguration.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmActivityBehaviorFactory.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehavior.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehavior.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/BpmTaskAssignScript.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderAbstractScript.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX1Script.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2Script.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignStartUserScript.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/identity/EmptyUserGroupManager.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmProcessInstanceEventListener.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTackActivitiEventListener.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTaskEventListener.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/BpmTaskEventListener.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/listener/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/framework/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java


+ 3 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java

@@ -215,6 +215,9 @@ public class BpmModelServiceImpl  implements BpmModelService {
         if (oldDefinition == null) {
             return;
         }
+        if(oldDefinition.isSuspended()) {
+            return;
+        }
         processDefinitionService.updateProcessDefinitionState(oldDefinition.getId(), SuspensionState.SUSPENDED.getStateCode());
     }
 

+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionService.java


+ 3 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java

@@ -103,6 +103,9 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
         }
         // 执行查询
         List<ProcessDefinition> processDefinitions = definitionQuery.list();
+        if (CollUtil.isEmpty(processDefinitions)) {
+            return Collections.emptyList();
+        }
 
         // 获得 BpmProcessDefinitionDO Map
         List<BpmProcessDefinitionExtDO> processDefinitionDOs = processDefinitionMapper.selectListByProcessDefinitionIds(

+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleService.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmTaskAssignRuleServiceImpl.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityService.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmActivityServiceImpl.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehaviorTest.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/BpmUserTaskActivityBehaviorTest.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/java/cn/iocoder/yudao/module/bpm/framework/activiti/core/behavior/script/impl/BpmTaskAssignLeaderX2ScriptTest.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/java/cn/iocoder/yudao/module/bpm/service/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/java/cn/iocoder/yudao/module/bpm/service/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/application-unit-test.yaml → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/application-unit-test.yaml


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/logback.xml → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/logback.xml


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/clean.sql → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/sql/clean.sql


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-activiti/src/test/resources/sql/create_tables.sql → yudao-module-bpm/yudao-module-bpm-biz-activiti/src/test/resources/sql/create_tables.sql


+ 1 - 1
yudao-module-bpm/yudao-module-bpm-impl-flowable/pom.xml → yudao-module-bpm/yudao-module-bpm-biz-flowable/pom.xml

@@ -8,7 +8,7 @@
         <version>${revision}</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>yudao-module-bpm-impl-flowable</artifactId>
+    <artifactId>yudao-module-bpm-biz-flowable</artifactId>
     <packaging>jar</packaging>
 
     <name>${project.artifactId}</name>

+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmProcessDefinitionController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmTaskAssignRuleController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmActivityController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/app/package-info.java


+ 0 - 0
yudao-module-bpm/yudao-module-bpm-impl-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java → yudao-module-bpm/yudao-module-bpm-biz-flowable/src/main/java/cn/iocoder/yudao/module/bpm/controller/package-info.java


Деякі файли не було показано, через те що забагато файлів було змінено