Bläddra i källkod

Merge remote-tracking branch 'origin/pay_extension' into pay_extension

# Conflicts:
#	yudao-admin-server/src/test/resources/sql/create_tables.sql
chen quan 3 år sedan
förälder
incheckning
aad85337ce
100 ändrade filer med 3059 tillägg och 730 borttagningar
  1. 1 0
      .gitattributes
  2. 9 8
      README.md
  3. BIN
      img.png
  4. 31 0
      mini-program-test/.eslintrc.js
  5. 1 0
      mini-program-test/README.md
  6. 19 0
      mini-program-test/app.js
  7. 14 0
      mini-program-test/app.json
  8. 10 0
      mini-program-test/app.wxss
  9. 91 0
      mini-program-test/pages/index/index.js
  10. 3 0
      mini-program-test/pages/index/index.json
  11. 29 0
      mini-program-test/pages/index/index.wxml
  12. 19 0
      mini-program-test/pages/index/index.wxss
  13. 18 0
      mini-program-test/pages/logs/logs.js
  14. 4 0
      mini-program-test/pages/logs/logs.json
  15. 6 0
      mini-program-test/pages/logs/logs.wxml
  16. 8 0
      mini-program-test/pages/logs/logs.wxss
  17. 75 0
      mini-program-test/project.config.json
  18. 7 0
      mini-program-test/sitemap.json
  19. 3 0
      mini-program-test/utils/common.js
  20. 19 0
      mini-program-test/utils/util.js
  21. 3 3
      pom.xml
  22. 38 35
      sql/quartz.sql
  23. 31 631
      sql/ruoyi-vue-pro.sql
  24. 13 0
      yudao-admin-server/pom.xml
  25. 0 9
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/config/AsyncConfiguration.java
  26. 0 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/package-info.java
  27. 4 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java
  28. 100 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/WlFormController.java
  29. 28 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormBaseVO.java
  30. 12 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormCreateReqVO.java
  31. 34 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormExcelVO.java
  32. 33 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormExportReqVO.java
  33. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormPageReqVO.java
  34. 19 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormRespVO.java
  35. 17 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormUpdateReqVO.java
  36. 114 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/OaLeaveController.java
  37. 48 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveBaseVO.java
  38. 15 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveCreateReqVO.java
  39. 44 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveExcelVO.java
  40. 54 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveExportReqVO.java
  41. 56 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeavePageReqVO.java
  42. 16 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveRespVO.java
  43. 32 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveUpdateReqVO.java
  44. 34 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/ProcessDefinitionController.java
  45. 60 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/TaskController.java
  46. 19 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskHandleVO.java
  47. 15 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskQueryReqVO.java
  48. 17 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskReqVO.java
  49. 24 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskStepVO.java
  50. 16 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TodoTaskPageReqVO.java
  51. 33 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TodoTaskRespVO.java
  52. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/form/WfFormConvert.java
  53. 34 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/oa/OaLeaveConvert.java
  54. 9 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/workflow/TodoTaskConvert.java
  55. 57 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/form/WfForm.java
  56. 55 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/form/WfFormData.java
  57. 60 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/oa/OaLeaveDO.java
  58. 29 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/process/ProcessDefinitionDO.java
  59. 43 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/mysql/form/WfFormMapper.java
  60. 46 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/mysql/oa/OaLeaveMapper.java
  61. 13 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/enums/OaErrorCodeConstants.java
  62. 14 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/enums/form/WfFormErrorCodeConstants.java
  63. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/package-info.java
  64. 62 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/config/UserGroupManagerService.java
  65. 31 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/config/UserGroupsProvider.java
  66. 75 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/form/WfFormService.java
  67. 86 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/form/impl/WfFormServiceImpl.java
  68. 76 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/OaLeaveService.java
  69. 43 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/ReportBackEndProcessor.java
  70. 141 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/impl/OaLeaveServiceImpl.java
  71. 29 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/process/ProcessService.java
  72. 109 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/process/impl/ProcessServiceImpl.java
  73. 26 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/workflow/TaskService.java
  74. 266 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/workflow/impl/TaskServiceImpl.java
  75. 2 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java
  76. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java
  77. 3 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java
  78. 8 7
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java
  79. 5 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http
  80. 5 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
  81. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java
  82. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java
  83. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java
  84. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java
  85. 3 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictTypeController.java
  86. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/SysNoticeController.java
  87. 106 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java
  88. 30 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java
  89. 14 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java
  90. 39 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java
  91. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java
  92. 41 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java
  93. 19 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java
  94. 18 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java
  95. 2 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http
  96. 5 4
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java
  97. 36 0
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java
  98. 1 1
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java
  99. 2 2
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java
  100. 2 3
      yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java

+ 1 - 0
.gitattributes

@@ -0,0 +1 @@
+*.sql linguist-language=java

+ 9 - 8
README.md

@@ -33,6 +33,7 @@
 |  | 菜单管理 | 配置系统菜单,操作权限,按钮权限标识等 |
 |  | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
 |  | 岗位管理 | 配置系统用户所属担任职务 |
+|  | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
 |  | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
 | 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 |
 | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
@@ -96,21 +97,21 @@
 
 | 框架 | 说明 |  版本 | 学习指南 |
 | --- | --- | --- | --- |
-| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.5 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
+| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.12 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
 | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 |  |
-| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.4 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
-| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
-| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
+| [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.4.3.4 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
+| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
 | [Redis](https://redis.io/) | key-value 数据库 | 5.0 |  |
-| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.1.46 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
-| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架  | 5.4.6 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
-| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.4.6 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
+| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.16.6 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
+| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架  | 5.3.13 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
+| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.4.9 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
 | [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.1.7 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
 | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
 | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
 | [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
 | [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
-| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
+| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.4.2 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
 | [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.11.4 |  |
 | [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
 | [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |

BIN
img.png


+ 31 - 0
mini-program-test/.eslintrc.js

@@ -0,0 +1,31 @@
+/*
+ * Eslint config file
+ * Documentation: https://eslint.org/docs/user-guide/configuring/
+ * Install the Eslint extension before using this feature.
+ */
+module.exports = {
+  env: {
+    es6: true,
+    browser: true,
+    node: true,
+  },
+  ecmaFeatures: {
+    modules: true,
+  },
+  parserOptions: {
+    ecmaVersion: 2018,
+    sourceType: 'module',
+  },
+  globals: {
+    wx: true,
+    App: true,
+    Page: true,
+    getCurrentPages: true,
+    getApp: true,
+    Component: true,
+    requirePlugin: true,
+    requireMiniProgram: true,
+  },
+  // extends: 'eslint:recommended',
+  rules: {},
+}

+ 1 - 0
mini-program-test/README.md

@@ -0,0 +1 @@
+临时项目,作为测试微信小程序登陆之用

+ 19 - 0
mini-program-test/app.js

@@ -0,0 +1,19 @@
+// app.js
+App({
+  onLaunch() {
+    // 展示本地存储能力
+    const logs = wx.getStorageSync('logs') || []
+    logs.unshift(Date.now())
+    wx.setStorageSync('logs', logs)
+
+    // 登录
+    wx.login({
+      success: res => {
+        // 发送 res.code 到后台换取 openId, sessionKey, unionId
+      }
+    })
+  },
+  globalData: {
+    userInfo: null
+  }
+})

+ 14 - 0
mini-program-test/app.json

@@ -0,0 +1,14 @@
+{
+  "pages":[
+    "pages/index/index",
+    "pages/logs/logs"
+  ],
+  "window":{
+    "backgroundTextStyle":"light",
+    "navigationBarBackgroundColor": "#fff",
+    "navigationBarTitleText": "Weixin",
+    "navigationBarTextStyle":"black"
+  },
+  "style": "v2",
+  "sitemapLocation": "sitemap.json"
+}

+ 10 - 0
mini-program-test/app.wxss

@@ -0,0 +1,10 @@
+/**app.wxss**/
+.container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: space-between;
+  padding: 200rpx 0;
+  box-sizing: border-box;
+} 

+ 91 - 0
mini-program-test/pages/index/index.js

@@ -0,0 +1,91 @@
+// index.js
+
+const common=require('../../utils/common.js')
+// 获取应用实例
+const app = getApp()
+
+Page({
+  data: {
+    motto: 'Hello World',
+    userInfo: {},
+    hasUserInfo: false,
+    canIUse: wx.canIUse('button.open-type.getUserInfo'),
+    canIUseGetUserProfile: false,
+    canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName'), // 如需尝试获取用户信息可改为false
+    holderText: 'to be auth'
+  },
+  // 事件处理函数
+  bindViewTap() {
+    wx.navigateTo({
+      url: '../logs/logs'
+    })
+  },
+  onLoad() {
+    if (wx.getUserProfile) {
+      this.setData({
+        canIUseGetUserProfile: true
+      })
+    }
+  },
+  getUserProfile(e) {
+    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
+    wx.getUserProfile({
+      desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
+      success: (res) => {
+        console.log(res)
+        this.setData({
+          userInfo: res.userInfo,
+          hasUserInfo: true
+        })
+      }
+    })
+  },
+  getUserInfo(e) {
+    // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
+    console.log(e)
+    this.setData({
+      userInfo: e.detail.userInfo,
+      hasUserInfo: true
+    })
+  },
+  // 小程序登录 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
+  wxLogin(e){
+    let page=this;
+    wx.login({
+      success (res) {
+        console.log("res:")
+        console.log(res)
+        if (res.code) {
+          //发起网络请求
+          console.log('发起网络请求'+common.baseurl)
+          wx.request({
+            url: common.baseurl+'/api/social-login2',
+            method: "POST",
+            data: {
+              code: res.code,
+              state: 'empty',
+              type: 33,
+              username: '15601691300',
+              password: 'admin123'
+            },
+            header: {
+              'content-type': 'application/json' // 默认值
+            },
+            success: function(res) {
+              console.log(res.data)
+              let holder="auth success, token:"+res.data.data.token
+              page.setData({holderText: holder})
+            },
+            fail: function(data){
+              console.error("请求出错");
+              console.error(data)
+            }
+            
+          })
+        } else {
+          console.log('登录失败!' + res.errMsg)
+        }
+      }
+    })
+  }
+})

+ 3 - 0
mini-program-test/pages/index/index.json

@@ -0,0 +1,3 @@
+{
+  "usingComponents": {}
+}

+ 29 - 0
mini-program-test/pages/index/index.wxml

@@ -0,0 +1,29 @@
+<!--index.wxml-->
+<view class="container">
+  <view class="userinfo">
+    <block wx:if="{{canIUseOpenData}}">
+
+
+    </block>
+    <block wx:elif="{{!hasUserInfo}}">
+      <button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
+      <button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
+      <view wx:else> 请使用1.4.4及以上版本基础库 </view>
+    </block>
+    <block wx:else>
+      <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
+      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
+    </block>
+  </view>
+  <view class="usermotto">
+    
+  </view>
+
+
+
+  <text style="position: relative; left: 1rpx; top: -476rpx">授权登录测试1024</text>
+
+  <button style="position: relative; left: 0rpx; top: -361rpx" type="primary" id="login-button" bindtap="wxLogin">点击授权登录</button>
+
+  <text style="position: relative; left: 1rpx; top: -272rpx" id="login-user-id">{{holderText}}</text>
+</view>

+ 19 - 0
mini-program-test/pages/index/index.wxss

@@ -0,0 +1,19 @@
+/**index.wxss**/
+.userinfo {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  color: #aaa;
+}
+
+.userinfo-avatar {
+  overflow: hidden;
+  width: 128rpx;
+  height: 128rpx;
+  margin: 20rpx;
+  border-radius: 50%;
+}
+
+.usermotto {
+  margin-top: 200px;
+}

+ 18 - 0
mini-program-test/pages/logs/logs.js

@@ -0,0 +1,18 @@
+// logs.js
+const util = require('../../utils/util.js')
+
+Page({
+  data: {
+    logs: []
+  },
+  onLoad() {
+    this.setData({
+      logs: (wx.getStorageSync('logs') || []).map(log => {
+        return {
+          date: util.formatTime(new Date(log)),
+          timeStamp: log
+        }
+      })
+    })
+  }
+})

+ 4 - 0
mini-program-test/pages/logs/logs.json

@@ -0,0 +1,4 @@
+{
+  "navigationBarTitleText": "查看启动日志",
+  "usingComponents": {}
+}

+ 6 - 0
mini-program-test/pages/logs/logs.wxml

@@ -0,0 +1,6 @@
+<!--logs.wxml-->
+<view class="container log-list">
+  <block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
+    <text class="log-item">{{index + 1}}. {{log.date}}</text>
+  </block>
+</view>

+ 8 - 0
mini-program-test/pages/logs/logs.wxss

@@ -0,0 +1,8 @@
+.log-list {
+  display: flex;
+  flex-direction: column;
+  padding: 40rpx;
+}
+.log-item {
+  margin: 10rpx;
+}

+ 75 - 0
mini-program-test/project.config.json

@@ -0,0 +1,75 @@
+{
+  "description": "项目配置文件",
+  "packOptions": {
+    "ignore": [
+      {
+        "type": "file",
+        "value": ".eslintrc.js"
+      }
+    ]
+  },
+  "setting": {
+    "bundle": false,
+    "userConfirmedBundleSwitch": false,
+    "urlCheck": true,
+    "scopeDataCheck": false,
+    "coverView": true,
+    "es6": true,
+    "postcss": true,
+    "compileHotReLoad": false,
+    "lazyloadPlaceholderEnable": false,
+    "preloadBackgroundData": false,
+    "minified": true,
+    "autoAudits": false,
+    "newFeature": false,
+    "uglifyFileName": false,
+    "uploadWithSourceMap": true,
+    "useIsolateContext": true,
+    "nodeModules": false,
+    "enhance": true,
+    "useMultiFrameRuntime": true,
+    "useApiHook": true,
+    "useApiHostProcess": true,
+    "showShadowRootInWxmlPanel": true,
+    "packNpmManually": false,
+    "enableEngineNative": false,
+    "packNpmRelationList": [],
+    "minifyWXSS": true,
+    "showES6CompileOption": false,
+    "minifyWXML": true
+  },
+  "compileType": "miniprogram",
+  "libVersion": "2.19.4",
+  "appid": "wx44d047d87e6284d8",
+  "appid1": "wx63c280fe3248a3e7",
+  "projectname": "mini-program-test",
+  "debugOptions": {
+    "hidedInDevtools": []
+  },
+  "scripts": {},
+  "staticServerOptions": {
+    "baseURL": "",
+    "servePath": ""
+  },
+  "isGameTourist": false,
+  "condition": {
+    "search": {
+      "list": []
+    },
+    "conversation": {
+      "list": []
+    },
+    "game": {
+      "list": []
+    },
+    "plugin": {
+      "list": []
+    },
+    "gamePlugin": {
+      "list": []
+    },
+    "miniprogram": {
+      "list": []
+    }
+  }
+}

+ 7 - 0
mini-program-test/sitemap.json

@@ -0,0 +1,7 @@
+{
+  "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
+  "rules": [{
+  "action": "allow",
+  "page": "*"
+  }]
+}

+ 3 - 0
mini-program-test/utils/common.js

@@ -0,0 +1,3 @@
+module.exports = {
+  baseurl: "http://127.0.0.1:28080"
+}

+ 19 - 0
mini-program-test/utils/util.js

@@ -0,0 +1,19 @@
+const formatTime = date => {
+  const year = date.getFullYear()
+  const month = date.getMonth() + 1
+  const day = date.getDate()
+  const hour = date.getHours()
+  const minute = date.getMinutes()
+  const second = date.getSeconds()
+
+  return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
+}
+
+const formatNumber = n => {
+  n = n.toString()
+  return n[1] ? n : `0${n}`
+}
+
+module.exports = {
+  formatTime
+}

+ 3 - 3
pom.xml

@@ -20,7 +20,7 @@
     <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
 
     <properties>
-        <revision>1.2.0-snapshot</revision>
+        <revision>1.3.0-snapshot</revision>
         <!-- Maven 相关 -->
         <java.version>1.8</java.version>
         <maven.compiler.source>${java.version}</maven.compiler.source>
@@ -58,9 +58,9 @@
     <!-- 使用 aliyun 的 Maven 源,提升下载速度 -->
     <repositories>
         <repository>
-            <id>aliyun</id>
+            <id>aliyunmaven</id>
             <name>aliyun</name>
-            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
+            <url>https://maven.aliyun.com/repository/public</url>
         </repository>
     </repositories>
 

+ 38 - 35
sql/quartz.sql

@@ -1,17 +1,17 @@
 /*
  Navicat Premium Data Transfer
 
- Source Server         : local-mysql001
+ Source Server         : 127.0.0.1
  Source Server Type    : MySQL
- Source Server Version : 50718
+ Source Server Version : 80026
  Source Host           : localhost:3306
  Source Schema         : ruoyi-vue-pro
 
  Target Server Type    : MySQL
- Target Server Version : 50718
+ Target Server Version : 80026
  File Encoding         : 65001
 
- Date: 03/05/2021 12:01:37
+ Date: 30/10/2021 13:46:03
 */
 
 SET NAMES utf8mb4;
@@ -29,7 +29,7 @@ CREATE TABLE `QRTZ_BLOB_TRIGGERS` (
   PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_BLOB_TRIGGERS
@@ -46,7 +46,7 @@ CREATE TABLE `QRTZ_CALENDARS` (
   `CALENDAR_NAME` varchar(190) NOT NULL,
   `CALENDAR` blob NOT NULL,
   PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_CALENDARS
@@ -66,12 +66,13 @@ CREATE TABLE `QRTZ_CRON_TRIGGERS` (
   `TIME_ZONE_ID` varchar(80) DEFAULT NULL,
   PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_CRON_TRIGGERS
 -- ----------------------------
 BEGIN;
+INSERT INTO `QRTZ_CRON_TRIGGERS` VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', '* * * * * ?', 'Asia/Shanghai');
 INSERT INTO `QRTZ_CRON_TRIGGERS` VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', '0 * * * * ? *', 'Asia/Shanghai');
 COMMIT;
 
@@ -85,9 +86,9 @@ CREATE TABLE `QRTZ_FIRED_TRIGGERS` (
   `TRIGGER_NAME` varchar(190) NOT NULL,
   `TRIGGER_GROUP` varchar(190) NOT NULL,
   `INSTANCE_NAME` varchar(190) NOT NULL,
-  `FIRED_TIME` bigint(13) NOT NULL,
-  `SCHED_TIME` bigint(13) NOT NULL,
-  `PRIORITY` int(11) NOT NULL,
+  `FIRED_TIME` bigint NOT NULL,
+  `SCHED_TIME` bigint NOT NULL,
+  `PRIORITY` int NOT NULL,
   `STATE` varchar(16) NOT NULL,
   `JOB_NAME` varchar(190) DEFAULT NULL,
   `JOB_GROUP` varchar(190) DEFAULT NULL,
@@ -100,7 +101,7 @@ CREATE TABLE `QRTZ_FIRED_TRIGGERS` (
   KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
   KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_FIRED_TRIGGERS
@@ -126,12 +127,13 @@ CREATE TABLE `QRTZ_JOB_DETAILS` (
   PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
   KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
   KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_JOB_DETAILS
 -- ----------------------------
 BEGIN;
+INSERT INTO `QRTZ_JOB_DETAILS` VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000057400104A4F425F48414E444C45525F4E414D4574000C7061794E6F746966794A6F627800);
 INSERT INTO `QRTZ_JOB_DETAILS` VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 'cn.iocoder.yudao.framework.quartz.core.handler.JobHandlerInvoker', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000027400064A4F425F49447372000E6A6176612E6C616E672E4C6F6E673B8BE490CC8F23DF0200014A000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000000000000037400104A4F425F48414E444C45525F4E414D457400187379735573657253657373696F6E54696D656F75744A6F627800);
 COMMIT;
 
@@ -143,7 +145,7 @@ CREATE TABLE `QRTZ_LOCKS` (
   `SCHED_NAME` varchar(120) NOT NULL,
   `LOCK_NAME` varchar(40) NOT NULL,
   PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_LOCKS
@@ -161,7 +163,7 @@ CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` (
   `SCHED_NAME` varchar(120) NOT NULL,
   `TRIGGER_GROUP` varchar(190) NOT NULL,
   PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_PAUSED_TRIGGER_GRPS
@@ -176,16 +178,16 @@ DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;
 CREATE TABLE `QRTZ_SCHEDULER_STATE` (
   `SCHED_NAME` varchar(120) NOT NULL,
   `INSTANCE_NAME` varchar(190) NOT NULL,
-  `LAST_CHECKIN_TIME` bigint(13) NOT NULL,
-  `CHECKIN_INTERVAL` bigint(13) NOT NULL,
+  `LAST_CHECKIN_TIME` bigint NOT NULL,
+  `CHECKIN_INTERVAL` bigint NOT NULL,
   PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_SCHEDULER_STATE
 -- ----------------------------
 BEGIN;
-INSERT INTO `QRTZ_SCHEDULER_STATE` VALUES ('schedulerName', 'Yunai1620010117445', 1620010210071, 15000);
+INSERT INTO `QRTZ_SCHEDULER_STATE` VALUES ('schedulerName', 'Yunai.local1635571630493', 1635572537879, 15000);
 COMMIT;
 
 -- ----------------------------
@@ -196,12 +198,12 @@ CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` (
   `SCHED_NAME` varchar(120) NOT NULL,
   `TRIGGER_NAME` varchar(190) NOT NULL,
   `TRIGGER_GROUP` varchar(190) NOT NULL,
-  `REPEAT_COUNT` bigint(7) NOT NULL,
-  `REPEAT_INTERVAL` bigint(12) NOT NULL,
-  `TIMES_TRIGGERED` bigint(10) NOT NULL,
+  `REPEAT_COUNT` bigint NOT NULL,
+  `REPEAT_INTERVAL` bigint NOT NULL,
+  `TIMES_TRIGGERED` bigint NOT NULL,
   PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_SIMPLE_TRIGGERS
@@ -220,17 +222,17 @@ CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` (
   `STR_PROP_1` varchar(512) DEFAULT NULL,
   `STR_PROP_2` varchar(512) DEFAULT NULL,
   `STR_PROP_3` varchar(512) DEFAULT NULL,
-  `INT_PROP_1` int(11) DEFAULT NULL,
-  `INT_PROP_2` int(11) DEFAULT NULL,
-  `LONG_PROP_1` bigint(20) DEFAULT NULL,
-  `LONG_PROP_2` bigint(20) DEFAULT NULL,
+  `INT_PROP_1` int DEFAULT NULL,
+  `INT_PROP_2` int DEFAULT NULL,
+  `LONG_PROP_1` bigint DEFAULT NULL,
+  `LONG_PROP_2` bigint DEFAULT NULL,
   `DEC_PROP_1` decimal(13,4) DEFAULT NULL,
   `DEC_PROP_2` decimal(13,4) DEFAULT NULL,
   `BOOL_PROP_1` varchar(1) DEFAULT NULL,
   `BOOL_PROP_2` varchar(1) DEFAULT NULL,
   PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_SIMPROP_TRIGGERS
@@ -249,15 +251,15 @@ CREATE TABLE `QRTZ_TRIGGERS` (
   `JOB_NAME` varchar(190) NOT NULL,
   `JOB_GROUP` varchar(190) NOT NULL,
   `DESCRIPTION` varchar(250) DEFAULT NULL,
-  `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
-  `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
-  `PRIORITY` int(11) DEFAULT NULL,
+  `NEXT_FIRE_TIME` bigint DEFAULT NULL,
+  `PREV_FIRE_TIME` bigint DEFAULT NULL,
+  `PRIORITY` int DEFAULT NULL,
   `TRIGGER_STATE` varchar(16) NOT NULL,
   `TRIGGER_TYPE` varchar(8) NOT NULL,
-  `START_TIME` bigint(13) NOT NULL,
-  `END_TIME` bigint(13) DEFAULT NULL,
+  `START_TIME` bigint NOT NULL,
+  `END_TIME` bigint DEFAULT NULL,
   `CALENDAR_NAME` varchar(190) DEFAULT NULL,
-  `MISFIRE_INSTR` smallint(2) DEFAULT NULL,
+  `MISFIRE_INSTR` smallint DEFAULT NULL,
   `JOB_DATA` blob,
   PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
   KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
@@ -273,13 +275,14 @@ CREATE TABLE `QRTZ_TRIGGERS` (
   KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
   KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
   CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 
 -- ----------------------------
 -- Records of QRTZ_TRIGGERS
 -- ----------------------------
 BEGIN;
-INSERT INTO `QRTZ_TRIGGERS` VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 1620010260000, 1620010200000, 5, 'WAITING', 'CRON', 1613649236000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000007D074000F4A4F425F52455452595F434F554E547371007E0009000000037800);
+INSERT INTO `QRTZ_TRIGGERS` VALUES ('schedulerName', 'payNotifyJob', 'DEFAULT', 'payNotifyJob', 'DEFAULT', NULL, 1635572540000, 1635572539000, 5, 'WAITING', 'CRON', 1635294882000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000000074000F4A4F425F52455452595F434F554E5471007E000B7800);
+INSERT INTO `QRTZ_TRIGGERS` VALUES ('schedulerName', 'sysUserSessionTimeoutJob', 'DEFAULT', 'sysUserSessionTimeoutJob', 'DEFAULT', NULL, 1635572580000, 1635572520000, 5, 'WAITING', 'CRON', 1613649236000, 0, NULL, 0, 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C770800000010000000037400114A4F425F48414E444C45525F504152414D707400124A4F425F52455452595F494E54455256414C737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B0200007870000007D074000F4A4F425F52455452595F434F554E547371007E0009000000037800);
 COMMIT;
 
 SET FOREIGN_KEY_CHECKS = 1;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 31 - 631
sql/ruoyi-vue-pro.sql


+ 13 - 0
yudao-admin-server/pom.xml

@@ -35,6 +35,19 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-activiti</artifactId>
+        </dependency>
 
         <!-- Web 相关 -->
         <dependency>

+ 0 - 9
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/config/AsyncConfiguration.java

@@ -1,9 +0,0 @@
-package cn.iocoder.yudao.adminserver.framework.async.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.EnableAsync;
-
-@Configuration
-@EnableAsync
-public class AsyncConfiguration {
-}

+ 0 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/package-info.java

@@ -1,4 +0,0 @@
-/**
- * 异步执行,基于 Spring @Async 实现
- */
-package cn.iocoder.yudao.adminserver.framework.async;

+ 4 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java

@@ -22,9 +22,11 @@ public class SecurityConfiguration {
     @Bean
     public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
         return registry -> {
-            // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
+            // 验证码的接口
             registry.antMatchers(api("/system/captcha/**")).anonymous();
-            // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
+            // 获得租户编号的接口
+            registry.antMatchers(api("/system/tenant/get-id-by-name")).anonymous();
+            // Spring Boot Admin Server 的安全配置
             registry.antMatchers(adminSeverContextPath).anonymous()
                     .antMatchers(adminSeverContextPath + "/**").anonymous();
             // 短信回调 API

+ 100 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/WlFormController.java

@@ -0,0 +1,100 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.*;
+import cn.iocoder.yudao.adminserver.modules.activiti.convert.form.WfFormConvert;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form.WfForm;
+import cn.iocoder.yudao.adminserver.modules.activiti.service.form.WfFormService;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+// TODO @风里雾里: Os=》Wf,/os 改成 /wl 开头。目前这个模块,咱先定位成给工作流用的
+@Api(tags = "动态表单")
+@RestController
+@RequestMapping("/wl/form")
+@Validated
+public class WlFormController {
+
+    @Resource
+    private WfFormService formService;
+
+    @PostMapping("/create")
+    @ApiOperation("创建动态表单")
+    @PreAuthorize("@ss.hasPermission('os:form:create')")
+    public CommonResult<Long> createForm(@Valid @RequestBody WfFormCreateReqVO createReqVO) {
+        return success(formService.createForm(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("更新动态表单")
+    @PreAuthorize("@ss.hasPermission('os:form:update')")
+    public CommonResult<Boolean> updateForm(@Valid @RequestBody WfFormUpdateReqVO updateReqVO) {
+        formService.updateForm(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除动态表单")
+    @ApiImplicitParam(name = "id", value = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('os:form:delete')")
+    public CommonResult<Boolean> deleteForm(@RequestParam("id") Long id) {
+        formService.deleteForm(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得动态表单")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('os:form:query')")
+    public CommonResult<WfFormRespVO> getForm(@RequestParam("id") Long id) {
+        WfForm form = formService.getForm(id);
+        return success(WfFormConvert.INSTANCE.convert(form));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获得动态表单列表")
+    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
+    @PreAuthorize("@ss.hasPermission('os:form:query')")
+    public CommonResult<List<WfFormRespVO>> getFormList(@RequestParam("ids") Collection<Long> ids) {
+        List<WfForm> list = formService.getFormList(ids);
+        return success(WfFormConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得动态表单分页")
+    @PreAuthorize("@ss.hasPermission('os:form:query')")
+    public CommonResult<PageResult<WfFormRespVO>> getFormPage(@Valid WfFormPageReqVO pageVO) {
+        PageResult<WfForm> pageResult = formService.getFormPage(pageVO);
+        return success(WfFormConvert.INSTANCE.convertPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @ApiOperation("导出动态表单 Excel")
+    @PreAuthorize("@ss.hasPermission('os:form:export')")
+    @OperateLog(type = EXPORT)
+    public void exportFormExcel(@Valid WfFormExportReqVO exportReqVO,
+              HttpServletResponse response) throws IOException {
+        List<WfForm> list = formService.getFormList(exportReqVO);
+        // 导出 Excel
+        List<WfFormExcelVO> datas = WfFormConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "动态表单.xls", "数据", WfFormExcelVO.class, datas);
+    }
+
+}

+ 28 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormBaseVO.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+/**
+* 动态表单 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class WfFormBaseVO {
+
+    @ApiModelProperty(value = "表单名称", required = true)
+    @NotNull(message = "表单名称不能为空")
+    private String name;
+
+    @ApiModelProperty(value = "商户状态", required = true)
+    @NotNull(message = "商户状态不能为空")
+    private Integer status;
+
+    @ApiModelProperty(value = "表单JSON")
+    private String formJson;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+}

+ 12 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormCreateReqVO.java

@@ -0,0 +1,12 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import io.swagger.annotations.*;
+
+@ApiModel("动态表单创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class WfFormCreateReqVO extends WfFormBaseVO {
+
+}

+ 34 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormExcelVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import java.util.*;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+/**
+ * 动态表单 Excel VO
+ *
+ * @author 芋艿
+ */
+@Data
+public class WfFormExcelVO {
+
+    @ExcelProperty("表单编号")
+    private Long id;
+
+    @ExcelProperty("表单名称")
+    private String name;
+
+    @ExcelProperty("商户状态")
+    private Integer status;
+
+    @ExcelProperty("表单JSON")
+    private String formJson;
+
+    @ExcelProperty("备注")
+    private String remark;
+
+    @ExcelProperty("创建时间")
+    private Date createTime;
+
+}

+ 33 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormExportReqVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel(value = "动态表单 Excel 导出 Request VO", description = "参数和 OsFormPageReqVO 是一致的")
+@Data
+public class WfFormExportReqVO {
+
+    @ApiModelProperty(value = "表单名称")
+    private String name;
+
+    @ApiModelProperty(value = "商户状态")
+    private Integer status;
+
+    @ApiModelProperty(value = "表单JSON")
+    private String formJson;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 36 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormPageReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("动态表单分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class WfFormPageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "表单名称")
+    private String name;
+
+    @ApiModelProperty(value = "商户状态")
+    private Integer status;
+
+    @ApiModelProperty(value = "表单JSON")
+    private String formJson;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 19 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormRespVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+@ApiModel("动态表单 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class WfFormRespVO extends WfFormBaseVO {
+
+    @ApiModelProperty(value = "表单编号", required = true)
+    private Long id;
+
+    @ApiModelProperty(value = "创建时间", required = true)
+    private Date createTime;
+
+}

+ 17 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/form/vo/WfFormUpdateReqVO.java

@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo;
+
+import lombok.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("动态表单更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class WfFormUpdateReqVO extends WfFormBaseVO {
+
+    @ApiModelProperty(value = "表单编号", required = true)
+    @NotNull(message = "表单编号不能为空")
+    private Long id;
+
+}

+ 114 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/OaLeaveController.java

@@ -0,0 +1,114 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
+import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
+import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+// TODO @jason:Oa=》OA 会不会好点,名词缩写哈
+@Api(tags = "请假申请")
+@RestController
+@RequestMapping("/oa/leave")
+@Validated
+public class OaLeaveController {
+
+    @Resource
+    private OaLeaveService leaveService;
+
+    @PostMapping("/create")
+    @ApiOperation("创建请假申请")
+    @PreAuthorize("@ss.hasPermission('oa:leave:create')")
+    public CommonResult<Long> createLeave(@Valid @RequestBody OaLeaveCreateReqVO createReqVO) {
+        // TODO @芋艿:processKey 自己去理解下。不过得把 leave 变成枚举
+        createReqVO.setProcessKey("leave");
+        return success(leaveService.createLeave(createReqVO));
+    }
+
+    @PostMapping("/form-key/create")
+    @ApiOperation("创建外置请假申请")
+    public CommonResult<Long> createFormKeyLeave(@Valid @RequestBody OaLeaveCreateReqVO createReqVO) {
+        // TODO @芋艿:processKey 自己去理解下。不过得把 formkey 变成枚举
+        createReqVO.setProcessKey("leave-formkey");
+        return success(leaveService.createLeave(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("更新请假申请")
+    @PreAuthorize("@ss.hasPermission('oa:leave:update')")
+    public CommonResult<Boolean> updateLeave(@Valid @RequestBody OaLeaveUpdateReqVO updateReqVO) {
+        leaveService.updateLeave(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除请假申请")
+    @ApiImplicitParam(name = "id", value = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('oa:leave:delete')")
+    public CommonResult<Boolean> deleteLeave(@RequestParam("id") Long id) {
+        leaveService.deleteLeave(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得请假申请")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('oa:leave:query')")
+    public CommonResult<OaLeaveRespVO> getLeave(@RequestParam("id") Long id) {
+        OaLeaveDO leave = leaveService.getLeave(id);
+        return success(OaLeaveConvert.INSTANCE.convert(leave));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获得请假申请列表")
+    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
+    @PreAuthorize("@ss.hasPermission('oa:leave:query')")
+    public CommonResult<List<OaLeaveRespVO>> getLeaveList(@RequestParam("ids") Collection<Long> ids) {
+        List<OaLeaveDO> list = leaveService.getLeaveList(ids);
+        return success(OaLeaveConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得请假申请分页")
+    @PreAuthorize("@ss.hasPermission('oa:leave:query')")
+    public CommonResult<PageResult<OaLeaveRespVO>> getLeavePage(@Valid OaLeavePageReqVO pageVO) {
+        //值查询自己申请请假
+        // TODO @芋艿:这里的传值,到底前端搞,还是后端搞。
+        pageVO.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
+        PageResult<OaLeaveDO> pageResult = leaveService.getLeavePage(pageVO);
+        return success(OaLeaveConvert.INSTANCE.convertPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @ApiOperation("导出请假申请 Excel")
+    @PreAuthorize("@ss.hasPermission('oa:leave:export')")
+    @OperateLog(type = EXPORT)
+    public void exportLeaveExcel(@Valid OaLeaveExportReqVO exportReqVO,
+              HttpServletResponse response) throws IOException {
+        List<OaLeaveDO> list = leaveService.getLeaveList(exportReqVO);
+        // 导出 Excel
+        List<OaLeaveExcelVO> datas = OaLeaveConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "请假申请.xls", "数据", OaLeaveExcelVO.class, datas);
+    }
+
+}

+ 48 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveBaseVO.java

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+* 请假申请 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class OaLeaveBaseVO {
+
+    @ApiModelProperty(value = "流程id")
+    private String processInstanceId;
+
+    @ApiModelProperty(value = "状态", required = true)
+    private Integer status;
+
+    @ApiModelProperty(value = "申请人id", required = true)
+    private String userId;
+
+    @ApiModelProperty(value = "开始时间", required = true)
+    @NotNull(message = "开始时间不能为空")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private Date startTime;
+
+    @ApiModelProperty(value = "结束时间", required = true)
+    @NotNull(message = "结束时间不能为空")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private Date endTime;
+
+    @ApiModelProperty(value = "请假类型")
+    private String leaveType;
+
+    @ApiModelProperty(value = "原因")
+    private String reason;
+
+    @ApiModelProperty(value = "申请时间", required = true)
+    @NotNull(message = "申请时间不能为空")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private Date applyTime;
+
+}

+ 15 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveCreateReqVO.java

@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("请假申请创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class OaLeaveCreateReqVO extends OaLeaveBaseVO {
+
+    private String processKey;
+}

+ 44 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveExcelVO.java

@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+/**
+ * 请假申请 Excel VO
+ *
+ * @author 芋艿
+ */
+@Data
+public class OaLeaveExcelVO {
+
+    @ExcelProperty("请假表单主键")
+    private Long id;
+
+    @ExcelProperty("流程id")
+    private String processInstanceId;
+
+    @ExcelProperty("状态")
+    private Integer status;
+
+    @ExcelProperty("申请人id")
+    private String userId;
+
+    @ExcelProperty("开始时间")
+    private Date startTime;
+
+    @ExcelProperty("结束时间")
+    private Date endTime;
+
+    @ExcelProperty("请假类型")
+    private String leaveType;
+
+    @ExcelProperty("原因")
+    private String reason;
+
+    @ExcelProperty("申请时间")
+    private Date applyTime;
+
+}

+ 54 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveExportReqVO.java

@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel(value = "请假申请 Excel 导出 Request VO", description = "参数和 OaLeavePageReqVO 是一致的")
+@Data
+public class OaLeaveExportReqVO {
+
+    @ApiModelProperty(value = "流程id")
+    private String processInstanceId;
+
+    @ApiModelProperty(value = "状态")
+    private Integer status;
+
+    @ApiModelProperty(value = "申请人id")
+    private String userId;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始开始时间")
+    private Date beginStartTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束开始时间")
+    private Date endStartTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始结束时间")
+    private Date beginEndTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束结束时间")
+    private Date endEndTime;
+
+    @ApiModelProperty(value = "请假类型")
+    private String leaveType;
+
+    @ApiModelProperty(value = "原因")
+    private String reason;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始申请时间")
+    private Date beginApplyTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束申请时间")
+    private Date endApplyTime;
+
+}

+ 56 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeavePageReqVO.java

@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("请假申请分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class OaLeavePageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "流程id")
+    private String processInstanceId;
+
+    @ApiModelProperty(value = "状态")
+    private Integer status;
+
+    @ApiModelProperty(value = "申请人id")
+    private String userId;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始开始时间")
+    private Date beginStartTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束开始时间")
+    private Date endStartTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始结束时间")
+    private Date beginEndTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束结束时间")
+    private Date endEndTime;
+
+    @ApiModelProperty(value = "请假类型")
+    private String leaveType;
+
+    @ApiModelProperty(value = "原因")
+    private String reason;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始申请时间")
+    private Date beginApplyTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束申请时间")
+    private Date endApplyTime;
+
+}

+ 16 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveRespVO.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+@ApiModel("请假申请 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class OaLeaveRespVO extends OaLeaveBaseVO {
+
+    @ApiModelProperty(value = "请假表单主键", required = true)
+    private Long id;
+
+}

+ 32 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/oa/vo/OaLeaveUpdateReqVO.java

@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+import java.util.Map;
+
+@ApiModel("请假申请更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class OaLeaveUpdateReqVO extends OaLeaveBaseVO {
+
+    @ApiModelProperty(value = "请假表单主键", required = true)
+    @NotNull(message = "请假表单主键不能为空")
+    private Long id;
+
+    // TODO @json:swagger 和 validator 的注解要加哈。
+
+    private String taskId;
+
+    private String comment;
+
+    private Map<String,Object> variables;
+
+    // TODO @芋艿:variables 的作用是啥。
+
+}

+ 34 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/ProcessDefinitionController.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.activiti.api.process.runtime.ProcessRuntime;
+import org.activiti.engine.RepositoryService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+// TODO @json:swagger 和 validation 的注解,后续要补全下哈。可以等 workflow 基本写的差不多之后
+@RestController
+@RequestMapping("/workflow/process/definition")
+public class ProcessDefinitionController {
+
+    @Resource
+    private RepositoryService repositoryService;
+
+    @Resource
+    private ProcessRuntime processRuntime;
+
+
+    @GetMapping(value = "/getStartForm")
+    public CommonResult<String> getStartForm(@RequestParam("processKey") String processKey){
+        //这样查似乎有问题??, 暂时写死
+//        final ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().
+//                processDefinitionKey(processKey).latestVersion().singleResult();
+//        processRuntime.processDefinition(processDefinition.getId()).getFormKey();
+        return CommonResult.success("/flow/leave/apply");
+    }
+
+}

+ 60 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/TaskController.java

@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
+import cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.TaskService;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+// TODO @json:swagger 和 validation 的注解,后续要补全下哈。可以等 workflow 基本写的差不多之后
+@Api(tags = "工作流待办任务")
+@RestController
+@RequestMapping("/workflow/task")
+public class TaskController {
+
+    @Resource
+    private TaskService taskService;
+
+    @GetMapping("/todo/page")
+    @ApiOperation("获取待办任务分页")
+    public CommonResult<PageResult<TodoTaskRespVO>> getTodoTaskPage(@Valid TodoTaskPageReqVO pageVO) {
+        return success(taskService.getTodoTaskPage(pageVO));
+    }
+
+    @GetMapping("/claim")
+    @ApiOperation("签收任务")
+    public CommonResult<Boolean> claimTask(@RequestParam("id") String taskId) {
+        taskService.claimTask(taskId);
+        return success(true);
+    }
+
+    @PostMapping("/task-steps")
+    public CommonResult<TaskHandleVO> getTaskSteps(@RequestBody TaskQueryReqVO taskQuery) {
+        return success(taskService.getTaskSteps(taskQuery));
+    }
+
+    @PostMapping("/formKey")
+    public CommonResult<TodoTaskRespVO> getTaskFormKey(@RequestBody TaskQueryReqVO taskQuery) {
+        return success(taskService.getTaskFormKey(taskQuery));
+    }
+
+    @PostMapping("/complete")
+    public CommonResult<Boolean> complete(@RequestBody TaskReqVO taskReq) {
+        taskService.completeTask(taskReq);
+        return success(true);
+    }
+
+    @GetMapping("/process/history-steps")
+    public CommonResult<List<TaskStepVO>> getHistorySteps(@RequestParam("id") String processInstanceId) {
+        return success(taskService.getHistorySteps(processInstanceId));
+    }
+
+}

+ 19 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskHandleVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.List;
+
+@Data
+@ToString
+public class TaskHandleVO {
+
+    private Object formObject;
+
+
+    private List<TaskStepVO> historyTask;
+
+
+    private String taskVariable;
+}

+ 15 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskQueryReqVO.java

@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
+
+import lombok.Data;
+import lombok.ToString;
+
+@Data
+@ToString
+public class TaskQueryReqVO {
+
+    private String processKey;
+
+    private String taskId;
+
+    private String businessKey;
+}

+ 17 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskReqVO.java

@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Map;
+
+@Data
+@ToString
+public class TaskReqVO {
+
+    private String taskId;
+
+    private Map<String,Object> variables;
+
+    private String comment;
+}

+ 24 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TaskStepVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.util.Date;
+
+@Data
+@ToString
+public class TaskStepVO {
+
+    private String stepName;
+
+    private Date startTime;
+
+    private Date endTime;
+
+    private String assignee;
+
+    private String comment;
+
+    private Integer status;
+
+}

+ 16 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TodoTaskPageReqVO.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@ApiModel("待办任务申请分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class TodoTaskPageReqVO extends PageParam {
+
+    private String assignee;
+}

+ 33 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/controller/workflow/vo/TodoTaskRespVO.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@ApiModel("待办任务 Response VO")
+@Data
+@ToString
+public class TodoTaskRespVO {
+
+    private String id;
+
+    /**
+     * 1:未签收
+     * 2:已签收
+     */
+    private Integer status;
+
+
+    private String processName;
+
+
+    private String processKey;
+
+
+    private String businessKey;
+
+
+    private String formKey;
+
+}

+ 36 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/form/WfFormConvert.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.convert.form;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormExcelVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormRespVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form.WfForm;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 动态表单 Convert
+ *
+ * @author 芋艿
+ */
+@Mapper
+public interface WfFormConvert {
+
+    WfFormConvert INSTANCE = Mappers.getMapper(WfFormConvert.class);
+
+    WfForm convert(WfFormCreateReqVO bean);
+
+    WfForm convert(WfFormUpdateReqVO bean);
+
+    WfFormRespVO convert(WfForm bean);
+
+    List<WfFormRespVO> convertList(List<WfForm> list);
+
+    PageResult<WfFormRespVO> convertPage(PageResult<WfForm> page);
+
+    List<WfFormExcelVO> convertList02(List<WfForm> list);
+
+}

+ 34 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/oa/OaLeaveConvert.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.convert.oa;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
+
+/**
+ * 请假申请 Convert
+ *
+ * @author 芋艿
+ */
+@Mapper
+public interface OaLeaveConvert {
+
+    OaLeaveConvert INSTANCE = Mappers.getMapper(OaLeaveConvert.class);
+
+    OaLeaveDO convert(OaLeaveCreateReqVO bean);
+
+    OaLeaveDO convert(OaLeaveUpdateReqVO bean);
+
+    OaLeaveRespVO convert(OaLeaveDO bean);
+
+    List<OaLeaveRespVO> convertList(List<OaLeaveDO> list);
+
+    PageResult<OaLeaveRespVO> convertPage(PageResult<OaLeaveDO> page);
+
+    List<OaLeaveExcelVO> convertList02(List<OaLeaveDO> list);
+
+}

+ 9 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/convert/workflow/TodoTaskConvert.java

@@ -0,0 +1,9 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.convert.workflow;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+@Mapper
+public interface TodoTaskConvert {
+    TodoTaskConvert INSTANCE = Mappers.getMapper(TodoTaskConvert.class);
+}

+ 57 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/form/WfForm.java

@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import lombok.*;
+
+import java.util.List;
+
+/**
+ * 工作流的表单定义
+ * 用于工作流的申请表单,需要动态配置的场景
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "wf_form", autoResultMap = true)
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WfForm extends BaseDO {
+
+    /**
+     * 编号
+     */
+    @TableId
+    private Long id;
+    /**
+     * 表单名
+     */
+    private String name;
+    /**
+     * 状态
+     */
+    private Integer status;
+    /**
+     * 表单JSON
+     */
+    private String formJson;
+    /**
+     * 表单配置
+     *
+     * 目前直接将 https://github.com/JakHuang/form-generator 生成的 JSON 串,直接保存
+     * 定义:https://github.com/JakHuang/form-generator/issues/46
+     */
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private List<String> fields;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 55 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/form/WfFormData.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
+import lombok.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 工作流的表单结果
+ * 用户每次填写工作流的申请表单时,会保存一条记录到该表】
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "wf_form", autoResultMap = true)
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WfFormData extends BaseDO {
+
+    /**
+     * 编号
+     */
+    private Long id;
+    /**
+     * 表单编号
+     *
+     * 关联 {@link WfForm#getId()}
+     */
+    private Long formId;
+    /**
+     * 状态
+     */
+    private Integer status;
+    /**
+     * 表单配置
+     *
+     * 冗余 {@link WfForm#getFields()}
+     * 主要考虑,表单是可以修改的
+     */
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private List<String> fields;
+    /**
+     * 表单值
+     */
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private Map<String, Object> values;
+
+}

+ 60 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/oa/OaLeaveDO.java

@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa;
+
+import lombok.*;
+import java.util.*;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 请假申请 DO
+ *
+ * @author 芋艿
+ */
+@TableName("oa_leave")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OaLeaveDO extends BaseDO {
+
+    /**
+     * 请假表单主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 流程id
+     */
+    private String processInstanceId;
+    /**
+     * 状态
+     */
+    private Integer status;
+    /**
+     * 申请人id
+     */
+    private String userId;
+    /**
+     * 开始时间
+     */
+    private Date startTime;
+    /**
+     * 结束时间
+     */
+    private Date endTime;
+    /**
+     * 请假类型
+     */
+    private String leaveType;
+    /**
+     * 原因
+     */
+    private String reason;
+    /**
+     * 申请时间
+     */
+    private Date applyTime;
+
+}

+ 29 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/dataobject/process/ProcessDefinitionDO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.process;
+
+/**
+ * 流程模型实体类 映射  activiti ProcessDefinition接口
+ *
+ * @author ZJQ
+ * @date 2021/9/7 23:23
+ */
+public class ProcessDefinitionDO {
+
+    private String id;
+
+    private String category;
+
+    private String key;
+
+    private String name;
+
+    private String version;
+
+    private String resourceName;
+
+    private String deploymentId;
+
+    private String diagramResourceName;
+
+    private boolean suspended;
+
+}

+ 43 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/mysql/form/WfFormMapper.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.form;
+
+
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormPageReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form.WfForm;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 动态表单 Mapper
+ *
+ * @author 风里雾里
+ */
+@Mapper
+public interface WfFormMapper extends BaseMapperX<WfForm> {
+
+    default PageResult<WfForm> selectPage(WfFormPageReqVO reqVO) {
+        return selectPage(reqVO, new QueryWrapperX<WfForm>()
+                .likeIfPresent("name", reqVO.getName())
+                .eqIfPresent("status", reqVO.getStatus())
+                .eqIfPresent("form_json", reqVO.getFormJson())
+                .eqIfPresent("remark", reqVO.getRemark())
+                .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc("id")        );
+    }
+
+    default List<WfForm> selectList(WfFormExportReqVO reqVO) {
+        return selectList(new QueryWrapperX<WfForm>()
+                .likeIfPresent("name", reqVO.getName())
+                .eqIfPresent("status", reqVO.getStatus())
+                .eqIfPresent("form_json", reqVO.getFormJson())
+                .eqIfPresent("remark", reqVO.getRemark())
+                .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc("id")        );
+    }
+
+}

+ 46 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/dal/mysql/oa/OaLeaveMapper.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.*;
+
+/**
+ * 请假申请 Mapper
+ *
+ * @author 芋艿
+ */
+@Mapper
+public interface OaLeaveMapper extends BaseMapperX<OaLeaveDO> {
+
+    default PageResult<OaLeaveDO> selectPage(OaLeavePageReqVO reqVO) {
+        return selectPage(reqVO, new QueryWrapperX<OaLeaveDO>()
+                .eqIfPresent("process_instance_id", reqVO.getProcessInstanceId())
+                .eqIfPresent("status", reqVO.getStatus())
+                .eqIfPresent("user_id", reqVO.getUserId())
+                .betweenIfPresent("start_time", reqVO.getBeginStartTime(), reqVO.getEndStartTime())
+                .betweenIfPresent("end_time", reqVO.getBeginEndTime(), reqVO.getEndEndTime())
+                .eqIfPresent("leave_type", reqVO.getLeaveType())
+                .eqIfPresent("reason", reqVO.getReason())
+                .betweenIfPresent("apply_time", reqVO.getBeginApplyTime(), reqVO.getEndApplyTime())
+                .orderByDesc("id")        );
+    }
+
+    default List<OaLeaveDO> selectList(OaLeaveExportReqVO reqVO) {
+        return selectList(new QueryWrapperX<OaLeaveDO>()
+                .eqIfPresent("process_instance_id", reqVO.getProcessInstanceId())
+                .eqIfPresent("status", reqVO.getStatus())
+                .eqIfPresent("user_id", reqVO.getUserId())
+                .betweenIfPresent("start_time", reqVO.getBeginStartTime(), reqVO.getEndStartTime())
+                .betweenIfPresent("end_time", reqVO.getBeginEndTime(), reqVO.getEndEndTime())
+                .eqIfPresent("leave_type", reqVO.getLeaveType())
+                .eqIfPresent("reason", reqVO.getReason())
+                .betweenIfPresent("apply_time", reqVO.getBeginApplyTime(), reqVO.getEndApplyTime())
+                .orderByDesc("id")        );
+    }
+
+}

+ 13 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/enums/OaErrorCodeConstants.java

@@ -0,0 +1,13 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.enums;
+
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+/**
+ * activiti 系统 错误码枚举类
+ *
+ * 003 activiti
+ * 001 oa
+ * activiti 系统,使用 1-003-000-000 段
+ */
+public interface OaErrorCodeConstants {
+    ErrorCode LEAVE_NOT_EXISTS = new ErrorCode(1003001001, "请假申请不存在");
+}

+ 14 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/enums/form/WfFormErrorCodeConstants.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.enums.form;
+
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+
+/**
+ * activiti 系统 错误码枚举类
+ *
+ * 003 activiti
+ * 001 oa
+ * activiti 系统,使用 1-003-000-000 段
+ */
+public interface WfFormErrorCodeConstants {
+    ErrorCode FORM_NOT_EXISTS = new ErrorCode(1003001002, "动态表单不存在");
+}

+ 2 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/package-info.java

@@ -0,0 +1,2 @@
+// TODO @芋艿:思考下 activiti、oa 的定位,边界,模块的拆分
+package cn.iocoder.yudao.adminserver.modules.activiti;

+ 62 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/config/UserGroupManagerService.java

@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.config;
+
+
+import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
+import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
+import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import org.activiti.api.runtime.shared.identity.UserGroupManager;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.stereotype.Service;
+
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static java.util.Collections.singleton;
+
+@Service
+public class UserGroupManagerService implements UserGroupManager {
+
+    @Resource
+    private  UserDetailsService userDetailsService;
+
+    @Resource
+    private SysUserService userService;
+
+    @Resource
+    private SysPostService  sysPostService;
+
+    /**
+     * 暂时使用岗位来代替
+     * @param userId
+     * @return
+     */
+    @Override
+    public List<String> getUserGroups(String userId) {
+//        final LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(userId);
+//        final Long id = loginUser.getId();
+        final SysUserDO user = userService.getUserByUsername(userId);
+        return  sysPostService.getPosts(user.getPostIds()).stream().map(post -> post.getCode()).collect(Collectors.toList());
+
+    }
+
+    @Override
+    public List<String> getUserRoles(String userId) {
+       return Arrays.asList("ROLE_ACTIVITI_USER");
+    }
+
+    @Override
+    public List<String> getGroups() {
+        throw new UnsupportedOperationException("getGroups is now un supported");
+    }
+
+    @Override
+    public List<String> getUsers() {
+        throw new UnsupportedOperationException("getGroups is now un supported");
+    }
+}

+ 31 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/config/UserGroupsProvider.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.config;
+
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import org.activiti.api.runtime.shared.security.PrincipalGroupsProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Service;
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.List;
+
+@Service
+public class UserGroupsProvider implements PrincipalGroupsProvider {
+
+    @Override
+    public List<String> getGroups(Principal principal) {
+
+        if(principal instanceof Authentication){
+            Authentication authentication = (Authentication) principal;
+            final Object user = authentication.getPrincipal();
+            if(  user instanceof LoginUser){
+                return ((LoginUser) user).getGroups();
+            }else{
+                return Collections.emptyList();
+            }
+        }else{
+            return Collections.emptyList();
+        }
+
+    }
+}

+ 75 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/form/WfFormService.java

@@ -0,0 +1,75 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.form;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormPageReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form.WfForm;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import java.util.*;
+import javax.validation.*;
+
+
+/**
+ * 动态表单 Service 接口
+ *
+ * TODO @风里雾里
+ */
+public interface WfFormService {
+
+    /**
+     * 创建动态表单
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createForm(@Valid WfFormCreateReqVO createReqVO);
+
+    /**
+     * 更新动态表单
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateForm(@Valid WfFormUpdateReqVO updateReqVO);
+
+    /**
+     * 删除动态表单
+     *
+     * @param id 编号
+     */
+    void deleteForm(Long id);
+
+    /**
+     * 获得动态表单
+     *
+     * @param id 编号
+     * @return 动态表单
+     */
+    WfForm getForm(Long id);
+
+    /**
+     * 获得动态表单列表
+     *
+     * @param ids 编号
+     * @return 动态表单列表
+     */
+    List<WfForm> getFormList(Collection<Long> ids);
+
+    /**
+     * 获得动态表单分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 动态表单分页
+     */
+    PageResult<WfForm> getFormPage(WfFormPageReqVO pageReqVO);
+
+    /**
+     * 获得动态表单列表, 用于 Excel 导出
+     *
+     * @param exportReqVO 查询条件
+     * @return 动态表单列表
+     */
+    List<WfForm> getFormList(WfFormExportReqVO exportReqVO);
+
+}

+ 86 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/form/impl/WfFormServiceImpl.java

@@ -0,0 +1,86 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.form.impl;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormPageReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.form.vo.WfFormUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.convert.form.WfFormConvert;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.form.WfForm;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.form.WfFormMapper;
+import cn.iocoder.yudao.adminserver.modules.activiti.service.form.WfFormService;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.adminserver.modules.activiti.enums.form.WfFormErrorCodeConstants.FORM_NOT_EXISTS;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+
+/**
+ * 动态表单 Service 实现类
+ *
+ * TODO @风里雾里
+ */
+@Service
+@Validated
+public class WfFormServiceImpl implements WfFormService {
+
+    @Resource
+    private WfFormMapper formMapper;
+
+    @Override
+    public Long createForm(WfFormCreateReqVO createReqVO) {
+        // 插入
+        WfForm form = WfFormConvert.INSTANCE.convert(createReqVO);
+        formMapper.insert(form);
+        // 返回
+        return form.getId();
+    }
+
+    @Override
+    public void updateForm(WfFormUpdateReqVO updateReqVO) {
+        // 校验存在
+        this.validateFormExists(updateReqVO.getId());
+        // 更新
+        WfForm updateObj = WfFormConvert.INSTANCE.convert(updateReqVO);
+        formMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteForm(Long id) {
+        // 校验存在
+        this.validateFormExists(id);
+        // 删除
+        formMapper.deleteById(id);
+    }
+
+    private void validateFormExists(Long id) {
+        if (formMapper.selectById(id) == null) {
+            throw exception(FORM_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public WfForm getForm(Long id) {
+        return formMapper.selectById(id);
+    }
+
+    @Override
+    public List<WfForm> getFormList(Collection<Long> ids) {
+        return formMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<WfForm> getFormPage(WfFormPageReqVO pageReqVO) {
+        return formMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<WfForm> getFormList(WfFormExportReqVO exportReqVO) {
+        return formMapper.selectList(exportReqVO);
+    }
+
+}

+ 76 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/OaLeaveService.java

@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.oa;
+
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeavePageReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 请假申请 Service 接口
+ *
+ * @author 芋艿
+ */
+public interface OaLeaveService {
+
+    /**
+     * 创建请假申请
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createLeave(@Valid OaLeaveCreateReqVO createReqVO);
+
+    /**
+     * 更新请假申请
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateLeave(@Valid OaLeaveUpdateReqVO updateReqVO);
+
+    /**
+     * 删除请假申请
+     *
+     * @param id 编号
+     */
+    void deleteLeave(Long id);
+
+    /**
+     * 获得请假申请
+     *
+     * @param id 编号
+     * @return 请假申请
+     */
+    OaLeaveDO getLeave(Long id);
+
+    /**
+     * 获得请假申请列表
+     *
+     * @param ids 编号
+     * @return 请假申请列表
+     */
+    List<OaLeaveDO> getLeaveList(Collection<Long> ids);
+
+    /**
+     * 获得请假申请分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 请假申请分页
+     */
+    PageResult<OaLeaveDO> getLeavePage(OaLeavePageReqVO pageReqVO);
+
+    /**
+     * 获得请假申请列表, 用于 Excel 导出
+     *
+     * @param exportReqVO 查询条件
+     * @return 请假申请列表
+     */
+    List<OaLeaveDO> getLeaveList(OaLeaveExportReqVO exportReqVO);
+
+}

+ 43 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/ReportBackEndProcessor.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.oa;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import org.activiti.engine.delegate.DelegateExecution;
+import org.activiti.engine.delegate.ExecutionListener;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+@Component
+public class ReportBackEndProcessor implements ExecutionListener {
+
+    @Resource
+    private OaLeaveMapper leaveMapper;
+
+
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public void notify(DelegateTask delegateTask) {
+//        final String businessKey = delegateTask.getExecution().getProcessInstanceBusinessKey();
+//        UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
+//        updateWrapper.eq("id", Long.valueOf(businessKey));
+//        OaLeaveDO updateDo = new OaLeaveDO();
+//        updateDo.setStatus(2);
+//        leaveMapper.update(updateDo, updateWrapper);
+//    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void notify(DelegateExecution delegateExecution) {
+        final String businessKey = delegateExecution.getProcessInstanceBusinessKey();
+        // TODO @json:service 不要出现 dao 的元素,例如说 UpdateWrapper。这里,我们可以调用 updateById 方法
+        UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("id", Long.valueOf(businessKey));
+        OaLeaveDO updateDo = new OaLeaveDO();
+        updateDo.setStatus(2);  // TODO @json:status 要枚举起来,不要出现 magic number
+        leaveMapper.update(updateDo, updateWrapper);
+    }
+
+}

+ 141 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/oa/impl/OaLeaveServiceImpl.java

@@ -0,0 +1,141 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.oa.impl;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeavePageReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.oa.vo.OaLeaveUpdateReqVO;
+import cn.iocoder.yudao.adminserver.modules.activiti.convert.oa.OaLeaveConvert;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.dataobject.oa.OaLeaveDO;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
+import cn.iocoder.yudao.adminserver.modules.activiti.service.oa.OaLeaveService;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import org.activiti.api.task.model.Task;
+import org.activiti.api.task.model.builders.TaskPayloadBuilder;
+import org.activiti.api.task.runtime.TaskRuntime;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.adminserver.modules.activiti.enums.OaErrorCodeConstants.LEAVE_NOT_EXISTS;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+
+/**
+ * 请假申请 Service 实现类
+ *
+ * @author 芋艿
+ */
+@Service
+@Validated
+public class OaLeaveServiceImpl implements OaLeaveService {
+
+    @Resource
+    private OaLeaveMapper leaveMapper;
+
+    @Resource
+    private RuntimeService runtimeService;
+
+    @Resource
+    private org.activiti.engine.TaskService activitiTaskService;
+
+    @Resource
+    private TaskRuntime taskRuntime;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createLeave(OaLeaveCreateReqVO createReqVO) {
+        // 插入 OA 请假单
+        OaLeaveDO leave = OaLeaveConvert.INSTANCE.convert(createReqVO);
+        leave.setStatus(1);
+        leave.setUserId(SecurityFrameworkUtils.getLoginUser().getUsername());
+        leaveMapper.insert(leave);
+
+        // 创建工作流
+        Map<String, Object> variables = new HashMap<>();
+        // 如何得到部门领导人,暂时写死
+        variables.put("deptLeader", "admin"); // TODO @芋艿:需要部门的负责人
+        Long id = leave.getId();
+        String businessKey = String.valueOf(id);
+        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(createReqVO.getProcessKey(), businessKey, variables);
+        String processInstanceId = processInstance.getProcessInstanceId();
+
+        // TODO @json:service 不要出现 dao 的元素,例如说 UpdateWrapper。这里,我们可以调用 updateById 方法
+        // 将工作流的编号,更新到 OA 请假单中
+        UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("id", id);
+        OaLeaveDO updateDo = new OaLeaveDO();
+        updateDo.setProcessInstanceId(processInstanceId);
+        leaveMapper.update(updateDo, updateWrapper);
+        return id;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateLeave(OaLeaveUpdateReqVO updateReqVO) {
+        // 校验存在
+        this.validateLeaveExists(updateReqVO.getId());
+
+        final Task task = taskRuntime.task(updateReqVO.getTaskId());
+        activitiTaskService.addComment(task.getId(), task.getProcessInstanceId(), updateReqVO.getComment());
+        Map<String, Object> variables = updateReqVO.getVariables();
+
+        //如何得到部门领导人, 暂时写死
+        variables.put("deptLeader", "admin");
+        taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
+                .withVariables(variables)
+                .build());
+        // TODO @jason:不需要加 final 哈。虽然是不变,但是代码比较少这么去写
+        final Object reApply = variables.get("reApply");
+        // TODO @jason:直接使用 Objects.equals(reApply, true) 就可以
+        if((reApply instanceof Boolean) && (Boolean)reApply){
+            // 更新 表单
+            OaLeaveDO updateObj = OaLeaveConvert.INSTANCE.convert(updateReqVO);
+            leaveMapper.updateById(updateObj);
+        }
+    }
+
+    @Override
+    public void deleteLeave(Long id) {
+        // 校验存在
+        this.validateLeaveExists(id);
+        // 删除
+        leaveMapper.deleteById(id);
+        // TODO @jason:需要调用 runtimeService 的 delete 方法,删除???
+    }
+
+    private void validateLeaveExists(Long id) {
+        if (leaveMapper.selectById(id) == null) {
+            throw exception(LEAVE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public OaLeaveDO getLeave(Long id) {
+        return leaveMapper.selectById(id);
+    }
+
+    @Override
+    public List<OaLeaveDO> getLeaveList(Collection<Long> ids) {
+        return leaveMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<OaLeaveDO> getLeavePage(OaLeavePageReqVO pageReqVO) {
+        return leaveMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<OaLeaveDO> getLeaveList(OaLeaveExportReqVO exportReqVO) {
+        return leaveMapper.selectList(exportReqVO);
+    }
+
+}

+ 29 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/process/ProcessService.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.process;
+
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 流程基础管理
+ *
+ * @author ZJQ
+ * @date 2021/9/5 21:00
+ */
+public interface ProcessService {
+
+    /**
+     * 上传流程文件,进行流程模型部署
+     * @param multipartFile 上传文件
+     */
+    void deployProcess(MultipartFile multipartFile);
+
+
+    /**
+     * 激活或者挂起流程模型实体
+     * @param processDefinitionId 流程模型实体id
+     * @param type 类型
+     * @return 状态
+     */
+    String setActivOrHang(String processDefinitionId,String type);
+
+
+}

+ 109 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/process/impl/ProcessServiceImpl.java

@@ -0,0 +1,109 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.process.impl;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.service.process.ProcessService;
+import lombok.extern.slf4j.Slf4j;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.repository.Deployment;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.zip.ZipInputStream;
+import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.FILE_UPLOAD_FAILED;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+
+/**
+ * 流程基础管理
+ *
+ * @author ZJQ
+ * @date 2021/9/5 21:04
+ */
+@Service
+@Slf4j
+public class ProcessServiceImpl implements ProcessService {
+
+    private static final String BPMN20_XML = "bpmn20.xml";
+
+    @Resource
+    private RepositoryService repositoryService;
+
+    /**
+     * 上传流程文件,进行流程部署
+     * @param multipartFile 上传文件
+     */
+    @Override
+    public void deployProcess(MultipartFile multipartFile) {
+        String fileName = multipartFile.getOriginalFilename();
+        try (InputStream inputStream = multipartFile.getInputStream()){
+            Deployment deployment = getDeplymentByType(inputStream,fileName);
+            //获取部署成功的流程模型
+            List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
+            processDefinitions.forEach((processDefinition)->{
+                //设置线上部署流程模型名字
+                String proDefId = processDefinition.getId();
+                repositoryService.setProcessDefinitionCategory(proDefId,fileName);
+                log.info("流程文件部署成功,流程ID="+proDefId);
+            });
+        } catch (IOException e) {
+           log.error("流程部署出现异常"+e);
+        }
+    }
+
+    /**
+     * 激活或者挂起流程模型实体
+     * @param processDefinitionId 流程模型实体id
+     * @param type 类型
+     * @return 提示
+     */
+    @Override
+    public String setActivOrHang(String processDefinitionId, String type) {
+        String result = "无操作";
+        switch (type){
+            case "active":
+                repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
+                result = "已激活ID为【"+processDefinitionId+"】的流程模型实例";
+                break;
+            case "suspend":
+                repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
+                result = "已挂起ID为【"+processDefinitionId+"】的流程模型实例";
+                break;
+            default:
+                break;
+        }
+        return result;
+    }
+
+
+    /**
+     * 根据上传文件类型对应实现不同方式的流程部署
+     * @param inputStream 文件输入流
+     * @param fileName 文件名
+     * @return 文件部署流程
+     */
+    public Deployment getDeplymentByType(InputStream inputStream,String fileName){
+        Deployment deployment;
+        String type = FilenameUtils.getExtension(fileName);
+        switch (type){
+            case "bpmn":
+                String baseName = FilenameUtils.getBaseName(fileName);
+                deployment = repositoryService.createDeployment().addInputStream(baseName+"."+BPMN20_XML,inputStream).deploy();
+                break;
+            case "png":
+                deployment = repositoryService.createDeployment().addInputStream(fileName,inputStream).deploy();
+                break;
+            case "zip":
+            case "bar":
+                ZipInputStream zipInputStream = new ZipInputStream(inputStream);
+                deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
+                break;
+            default:
+                throw exception(FILE_UPLOAD_FAILED);
+        }
+        return deployment;
+    }
+}

+ 26 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/workflow/TaskService.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.workflow;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import java.util.List;
+
+// TODO @芋艿:前缀,注释
+public interface TaskService {
+
+    PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO);
+
+    void claimTask(String taskId);
+
+    void getTaskHistory(String taskId);
+
+    void completeTask(TaskReqVO taskReq);
+
+//    void flowImage(String taskId, HttpServletResponse response);
+    TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery);
+
+    List<TaskStepVO> getHistorySteps(String processInstanceId);
+
+    TodoTaskRespVO getTaskFormKey(TaskQueryReqVO taskQuery);
+
+}

+ 266 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/activiti/service/workflow/impl/TaskServiceImpl.java

@@ -0,0 +1,266 @@
+package cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.impl;
+
+import cn.iocoder.yudao.adminserver.modules.activiti.controller.workflow.vo.*;
+import cn.iocoder.yudao.adminserver.modules.activiti.dal.mysql.oa.OaLeaveMapper;
+import cn.iocoder.yudao.adminserver.modules.activiti.service.workflow.TaskService;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import com.google.common.collect.ImmutableMap;
+import org.activiti.api.runtime.shared.query.Page;
+import org.activiti.api.runtime.shared.query.Pageable;
+import org.activiti.api.task.model.Task;
+import org.activiti.api.task.model.builders.ClaimTaskPayloadBuilder;
+import org.activiti.api.task.model.builders.TaskPayloadBuilder;
+import org.activiti.api.task.runtime.TaskRuntime;
+import org.activiti.engine.HistoryService;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.history.HistoricActivityInstance;
+import org.activiti.engine.history.HistoricProcessInstance;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.task.Comment;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+public class TaskServiceImpl implements TaskService {
+
+    @Resource
+    private  TaskRuntime taskRuntime;
+
+    @Resource
+    private org.activiti.engine.TaskService activitiTaskService;
+
+    @Resource
+    private HistoryService  historyService;
+
+    @Resource
+    private RepositoryService repositoryService;
+
+    @Resource
+    private OaLeaveMapper leaveMapper;
+
+    private static Map<String,String>  taskVariable =  ImmutableMap.<String,String>builder()
+                    .put("deptLeaderVerify","deptLeaderApproved")
+                    .put("hrVerify","hrApproved")
+                    .build();
+
+    public TaskServiceImpl() {
+
+    }
+
+    @Override
+    public PageResult<TodoTaskRespVO> getTodoTaskPage(TodoTaskPageReqVO pageReqVO) {
+        final LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
+        // TODO @jason:封装一个方法,用于转换成 activiti 的分页对象
+        final Pageable pageable = Pageable.of((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), pageReqVO.getPageSize());
+        Page<Task> pageTasks = taskRuntime.tasks(pageable);
+        // TODO @jason:convert 里转换
+        List<Task> tasks = pageTasks.getContent();
+        int totalItems = pageTasks.getTotalItems();
+        final List<TodoTaskRespVO> respVOList = tasks.stream().map(task -> {
+            TodoTaskRespVO respVO = new TodoTaskRespVO();
+            respVO.setId(task.getId());
+            final ProcessDefinition definition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
+            respVO.setProcessName(definition.getName());
+            respVO.setProcessKey(definition.getKey());
+            respVO.setBusinessKey(task.getBusinessKey());
+            respVO.setStatus(task.getAssignee() == null ? 1 : 2);
+            return respVO;
+        }).collect(Collectors.toList());
+        // TODO @jason:要注意泛型哈。
+        return new PageResult(respVOList, Long.valueOf(totalItems)); // TODO @jason:(long) 转换即可
+    }
+
+
+    @Override
+    public void claimTask(String taskId) {
+        taskRuntime.claim(new ClaimTaskPayloadBuilder()
+                                .withTaskId(taskId)
+                                .withAssignee(SecurityFrameworkUtils.getLoginUser().getUsername())
+                                .build());
+    }
+
+    @Override
+    public void getTaskHistory(String taskId) {
+        final List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().
+                processInstanceId("8e2801fc-1a38-11ec-98ce-74867a13730f").list();
+    }
+
+    // TODO @jason:一个方法里,会有多个方法的调用,最好写下对应的注释。这样容易理解
+    @Override
+    @Transactional
+    public void completeTask(TaskReqVO taskReq) {
+        final Task task = taskRuntime.task(taskReq.getTaskId());
+
+        final Map<String, Object> variables = taskReq.getVariables();
+
+        activitiTaskService.addComment(taskReq.getTaskId(), task.getProcessInstanceId(), taskReq.getComment());
+
+        taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskReq.getTaskId())
+                .withVariables(taskReq.getVariables())
+                .build());
+
+//        if(variables.containsValue(Boolean.FALSE)){
+//            final String businessKey = task.getBusinessKey();
+//            UpdateWrapper<OaLeaveDO> updateWrapper = new UpdateWrapper<>();
+//            updateWrapper.eq("id", Long.valueOf(businessKey));
+//            OaLeaveDO updateDo = new OaLeaveDO();
+//            updateDo.setStatus(2);
+//            leaveMapper.update(updateDo, updateWrapper);
+//        }
+
+    }
+
+//    @Override
+//    public void flowImage(String taskId, HttpServletResponse response) {
+//
+//        final Task task = taskRuntime.task(taskId);
+//        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
+//        final Process process = bpmnModel.getMainProcess();
+//        ProcessDefinitionEntity processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
+//        List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
+//        List<String> highLightedFlows = getHighLightedFlows(processDefinition, processInstance.getId());
+//        ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
+//        InputStream imageStream =diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, highLightedFlows);
+//
+//        // 输出资源内容到相应对象
+//        byte[] b = new byte[1024];
+//        int len;
+//        while ((len = imageStream.read(b, 0, 1024)) != -1) {
+//            response.getOutputStream().write(b, 0, len);
+//        }
+//    }
+
+    @Override
+    public TaskHandleVO getTaskSteps(TaskQueryReqVO taskQuery) {
+        TaskHandleVO handleVO = new TaskHandleVO();
+
+//        String processKey = taskQuery.getProcessKey();
+//        if ("leave".equals(processKey)) {
+//            String businessKey = taskQuery.getBusinessKey();
+//            final OaLeaveDO leave = leaveMapper.selectById(Long.valueOf(businessKey));
+//            handleVO.setFormObject( OaLeaveConvert.INSTANCE.convert(leave));
+//        }
+
+//
+//        final String taskDefKey = task.getTaskDefinitionKey();
+//        final String variableName = Optional.ofNullable(taskVariable.get(taskDefKey)).orElse("");
+//        handleVO.setTaskVariable(variableName);
+        final Task task = taskRuntime.task(taskQuery.getTaskId());
+
+        List<TaskStepVO> steps = getTaskSteps(task.getProcessInstanceId());
+
+        handleVO.setHistoryTask(steps);
+        return handleVO;
+    }
+
+
+    private List<TaskStepVO> getTaskSteps(String processInstanceId) {
+        // 获得已完成的活动
+        List<HistoricActivityInstance> finished = historyService.createHistoricActivityInstanceQuery()
+                .processInstanceId(processInstanceId)
+                .activityType("userTask")
+                .finished()
+                .orderByHistoricActivityInstanceStartTime().asc().list();
+        // 获得对应的步骤
+        List<TaskStepVO> steps = new ArrayList<>();
+        finished.forEach(instance -> {
+            // TODO @jason:放到 convert 里
+            TaskStepVO step = new TaskStepVO();
+            step.setStepName(instance.getActivityName());
+            step.setStartTime(instance.getStartTime());
+            step.setEndTime(instance.getEndTime());
+            step.setAssignee(instance.getAssignee());
+            step.setStatus(1);
+            // TODO @jason:一般判数组为空,使用 CollUtil.isEmpty 会好点哈。另外,null 时候,不用填写 "" 的哈
+            List<Comment> comments = activitiTaskService.getTaskComments(instance.getTaskId());
+            if (comments.size() > 0) {
+                step.setComment(comments.get(0).getFullMessage());
+            } else {
+                step.setComment("");
+            }
+            steps.add(step);
+        });
+
+        // 获得未完成的活动
+        List<HistoricActivityInstance> unfinished = historyService
+                .createHistoricActivityInstanceQuery()
+                .processInstanceId(processInstanceId)
+                .activityType("userTask")
+                .unfinished().list();
+        // 获得对应的步骤
+        // TODO @json:其实已完成和未完成,它们的 convert 的逻辑,是一致的
+        for (HistoricActivityInstance instance : unfinished) {
+            TaskStepVO step = new TaskStepVO();
+            step.setStepName(instance.getActivityName());
+            step.setStartTime(instance.getStartTime());
+            step.setEndTime(instance.getEndTime());
+            step.setAssignee(Optional.ofNullable(instance.getAssignee()).orElse(""));
+            step.setComment("");
+            step.setStatus(0);
+            steps.add(step);
+        }
+        return steps;
+    }
+
+
+    @Override
+    public List<TaskStepVO> getHistorySteps(String processInstanceId) {
+        return getTaskSteps(processInstanceId);
+    }
+
+    @Override
+    public TodoTaskRespVO getTaskFormKey(TaskQueryReqVO taskQuery) {
+        final Task task = taskRuntime.task(taskQuery.getTaskId());
+        // 转换结果
+        TodoTaskRespVO respVO = new TodoTaskRespVO();
+        respVO.setFormKey(task.getFormKey());
+        respVO.setBusinessKey(task.getBusinessKey());
+        respVO.setId(task.getId());
+        return respVO;
+    }
+
+//    private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) {
+//
+//        List<String> highLightedFlows = new ArrayList<String>();
+//        List<HistoricActivityInstance> historicActivityInstances = historyService
+//                .createHistoricActivityInstanceQuery()
+//                .processInstanceId(processInstanceId)
+//                .orderByHistoricActivityInstanceStartTime().asc().list();
+//
+//        List<String> historicActivityInstanceList = new ArrayList<String>();
+//        for (HistoricActivityInstance hai : historicActivityInstances) {
+//            historicActivityInstanceList.add(hai.getActivityId());
+//        }
+
+//        // add current activities to list
+//        List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
+//        historicActivityInstanceList.addAll(highLightedActivities);
+
+        // activities and their sequence-flows
+//        for (ActivityImpl activity : processDefinition.getActivities()) {
+//            int index = historicActivityInstanceList.indexOf(activity.getId());
+//
+//            if (index >= 0 && index + 1 < historicActivityInstanceList.size()) {
+//                List<PvmTransition> pvmTransitionList = activity
+//                        .getOutgoingTransitions();
+//                for (PvmTransition pvmTransition : pvmTransitionList) {
+//                    String destinationFlowId = pvmTransition.getDestination().getId();
+//                    if (destinationFlowId.equals(historicActivityInstanceList.get(index + 1))) {
+//                        highLightedFlows.add(pvmTransition.getId());
+//                    }
+//                }
+//            }
+//        }
+//        return highLightedFlows;
+//    }
+
+}

+ 2 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -64,6 +65,7 @@ public class InfFileController {
     @ApiOperation("下载文件")
     @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
     public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
+        TenantContextHolder.setNullTenantId();
         InfFileDO file = fileCoreService.getFile(path);
         if (file == null) {
             log.warn("[getFile][path({}) 文件不存在]", path);

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java

@@ -1,13 +1,13 @@
 package cn.iocoder.yudao.adminserver.modules.infra.mq.message.config;
 
-import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
+import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 import lombok.Data;
 
 /**
  * 配置数据刷新 Message
  */
 @Data
-public class InfConfigRefreshMessage implements ChannelMessage {
+public class InfConfigRefreshMessage extends AbstractChannelMessage {
 
     @Override
     public String getChannel() {

+ 3 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config;
 
 import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage;
-import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
@@ -14,14 +13,14 @@ import javax.annotation.Resource;
 public class InfConfigProducer {
 
     @Resource
-    private StringRedisTemplate stringRedisTemplate;
+    private RedisMQTemplate redisMQTemplate;
 
     /**
      * 发送 {@link InfConfigRefreshMessage} 消息
      */
     public void sendConfigRefreshMessage() {
         InfConfigRefreshMessage message = new InfConfigRefreshMessage();
-        RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+        redisMQTemplate.send(message);
     }
 
 }

+ 8 - 7
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java

@@ -1,14 +1,16 @@
 package cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel;
 
-import java.util.*;
-
+import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
+import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
-import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.*;
+
+import java.util.Collection;
+import java.util.List;
 
 /**
  * 支付渠道
@@ -53,13 +55,12 @@ public interface PayChannelMapper extends BaseMapperX<PayChannelDO> {
      * @param code       通道编码
      * @return 数量
      */
+    // TODO @aquan:Mapper 的操作,和 db 保持一致
     default Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
-
         return this.selectCount(new QueryWrapper<PayChannelDO>().lambda()
                 .eq(PayChannelDO::getMerchantId, merchantId)
                 .eq(PayChannelDO::getAppId, appid)
-                .eq(PayChannelDO::getCode, code)
-        );
+                .eq(PayChannelDO::getCode, code)).intValue();
     }
 
     /**

+ 5 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http

@@ -1,21 +1,25 @@
 ### 请求 /login 接口 => 成功
 POST {{baseUrl}}/login
 Content-Type: application/json
+tenant-id: 1
 
 {
   "username": "admin",
   "password": "admin123",
-  "uuid": "9b2ffbc1-7425-4155-9894-9d5c08541d62",
+  "uuid": "3acd87a09a4f48fb9118333780e94883",
   "code": "1024"
 }
 
 ### 请求 /get-permission-info 接口 => 成功
 GET {{baseUrl}}/get-permission-info
 Authorization: Bearer {{token}}
+tenant-id: 1
 
 ### 请求 /list-menus 接口 => 成功
 GET {{baseUrl}}/list-menus
 Authorization: Bearer {{token}}
+#Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a
+tenant-id: 1
 
 ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
 GET http://127.0.0.1:8080/druid/123

+ 5 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java

@@ -8,10 +8,11 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum
 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
-import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
@@ -49,7 +50,7 @@ public class SysAuthController {
     @Resource
     private SysPermissionService permissionService;
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialCoreService;
 
     @PostMapping("/login")
     @ApiOperation("使用账号密码登录")
@@ -101,7 +102,7 @@ public class SysAuthController {
     })
     public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
                                                     @RequestParam("redirectUri") String redirectUri) {
-        return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
+        return CommonResult.success(socialCoreService.getAuthorizeUrl(type, redirectUri));
     }
 
     @PostMapping("/social-login")
@@ -132,7 +133,7 @@ public class SysAuthController {
     @DeleteMapping("/social-unbind")
     @ApiOperation("取消社交绑定")
     public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
-        socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId());
+        socialCoreService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
         return CommonResult.success(true);
     }
 

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
 
-import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum;
+import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
 
-import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum;
+import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
 
-import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum;
+import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
 
-import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum;
+import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
 import cn.iocoder.yudao.framework.common.validation.InEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;

+ 3 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/dict/SysDictTypeController.java

@@ -60,7 +60,7 @@ public class SysDictTypeController {
 
     @ApiOperation("/获得字典类型的分页列表")
     @GetMapping("/page")
-    @PreAuthorize("@ss.hasPermission('system:dict:quey')")
+    @PreAuthorize("@ss.hasPermission('system:dict:query')")
     public CommonResult<PageResult<SysDictTypeRespVO>> pageDictTypes(@Valid SysDictTypePageReqVO reqVO) {
         return success(SysDictTypeConvert.INSTANCE.convertPage(dictTypeService.getDictTypePage(reqVO)));
     }
@@ -68,7 +68,7 @@ public class SysDictTypeController {
     @ApiOperation("/查询字典类型详细")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
     @GetMapping(value = "/get")
-    @PreAuthorize("@ss.hasPermission('system:dict:quey')")
+    @PreAuthorize("@ss.hasPermission('system:dict:query')")
     public CommonResult<SysDictTypeRespVO> getDictType(@RequestParam("id") Long id) {
         return success(SysDictTypeConvert.INSTANCE.convert(dictTypeService.getDictType(id)));
     }
@@ -83,7 +83,7 @@ public class SysDictTypeController {
 
     @ApiOperation("导出数据类型")
     @GetMapping("/export")
-    @PreAuthorize("@ss.hasPermission('system:dict:quey')")
+    @PreAuthorize("@ss.hasPermission('system:dict:query')")
     @OperateLog(type = EXPORT)
     public void export(HttpServletResponse response, @Valid SysDictTypeExportReqVO reqVO) throws IOException {
         List<SysDictTypeDO> list = dictTypeService.getDictTypeList(reqVO);

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/notice/SysNoticeController.java

@@ -56,7 +56,7 @@ public class SysNoticeController {
 
     @GetMapping("/page")
     @ApiOperation("获取通知公告列表")
-    @PreAuthorize("@ss.hasPermission('system:notice:quey')")
+    @PreAuthorize("@ss.hasPermission('system:notice:query')")
     public CommonResult<PageResult<SysNoticeRespVO>> pageNotices(@Validated SysNoticePageReqVO reqVO) {
         return success(SysNoticeConvert.INSTANCE.convertPage(noticeService.pageNotices(reqVO)));
     }
@@ -64,7 +64,7 @@ public class SysNoticeController {
     @GetMapping("/get")
     @ApiOperation("获得通知公告")
     @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @PreAuthorize("@ss.hasPermission('system:notice:quey')")
+    @PreAuthorize("@ss.hasPermission('system:notice:query')")
     public CommonResult<SysNoticeRespVO> getNotice(@RequestParam("id") Long id) {
         return success(SysNoticeConvert.INSTANCE.convert(noticeService.getNotice(id)));
     }

+ 106 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java

@@ -0,0 +1,106 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.*;
+import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
+import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+@Api(tags = "租户")
+@RestController
+@RequestMapping("/system/tenant")
+public class SysTenantController {
+
+    @Resource
+    private SysTenantService tenantService;
+
+    @GetMapping("/get-id-by-name")
+    @ApiOperation(value = "使用租户名,获得租户编号", notes = "登录界面,根据用户的租户名,获得租户编号")
+    @ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class)
+    public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
+        SysTenantDO tenantDO = tenantService.getTenantByName(name);
+        return success(tenantDO != null ? tenantDO.getId() : null);
+    }
+
+    @PostMapping("/create")
+    @ApiOperation("创建租户")
+    @PreAuthorize("@ss.hasPermission('system:tenant:create')")
+    public CommonResult<Long> createTenant(@Valid @RequestBody SysTenantCreateReqVO createReqVO) {
+        return success(tenantService.createTenant(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("更新租户")
+    @PreAuthorize("@ss.hasPermission('system:tenant:update')")
+    public CommonResult<Boolean> updateTenant(@Valid @RequestBody SysTenantUpdateReqVO updateReqVO) {
+        tenantService.updateTenant(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除租户")
+    @ApiImplicitParam(name = "id", value = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('system:tenant:delete')")
+    public CommonResult<Boolean> deleteTenant(@RequestParam("id") Long id) {
+        tenantService.deleteTenant(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得租户")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
+    public CommonResult<SysTenantRespVO> getTenant(@RequestParam("id") Long id) {
+        SysTenantDO tenant = tenantService.getTenant(id);
+        return success(SysTenantConvert.INSTANCE.convert(tenant));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获得租户列表")
+    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
+    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
+    public CommonResult<List<SysTenantRespVO>> getTenantList(@RequestParam("ids") Collection<Long> ids) {
+        List<SysTenantDO> list = tenantService.getTenantList(ids);
+        return success(SysTenantConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得租户分页")
+    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
+    public CommonResult<PageResult<SysTenantRespVO>> getTenantPage(@Valid SysTenantPageReqVO pageVO) {
+        PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(pageVO);
+        return success(SysTenantConvert.INSTANCE.convertPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @ApiOperation("导出租户 Excel")
+    @PreAuthorize("@ss.hasPermission('system:tenant:export')")
+    @OperateLog(type = EXPORT)
+    public void exportTenantExcel(@Valid SysTenantExportReqVO exportReqVO,
+                                  HttpServletResponse response) throws IOException {
+        List<SysTenantDO> list = tenantService.getTenantList(exportReqVO);
+        // 导出 Excel
+        List<SysTenantExcelVO> datas = SysTenantConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "租户.xls", "数据", SysTenantExcelVO.class, datas);
+    }
+
+
+}

+ 30 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+/**
+* 租户 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class SysTenantBaseVO {
+
+    @ApiModelProperty(value = "租户名", required = true, example = "芋道")
+    @NotNull(message = "租户名不能为空")
+    private String name;
+
+    @ApiModelProperty(value = "联系人", required = true, example = "芋艿")
+    @NotNull(message = "联系人不能为空")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系手机", example = "15601691300")
+    private String contactMobile;
+
+    @ApiModelProperty(value = "租户状态(0正常 1停用)", required = true, example = "1")
+    @NotNull(message = "租户状态(0正常 1停用)不能为空")
+    private Integer status;
+
+}

+ 14 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("租户创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantCreateReqVO extends SysTenantBaseVO {
+
+}

+ 39 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+
+/**
+ * 租户 Excel VO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class SysTenantExcelVO {
+
+    @ExcelProperty("租户编号")
+    private Long id;
+
+    @ExcelProperty("租户名")
+    private String name;
+
+    @ExcelProperty("联系人")
+    private String contactName;
+
+    @ExcelProperty("联系手机")
+    private String contactMobile;
+
+    @ExcelProperty(value = "租户状态(0正常 1停用)", converter = DictConvert.class)
+    @DictFormat("sys_common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
+    private Integer status;
+
+    @ExcelProperty("创建时间")
+    private Date createTime;
+
+}

+ 36 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel(value = "租户 Excel 导出 Request VO", description = "参数和 SysTenantPageReqVO 是一致的")
+@Data
+public class SysTenantExportReqVO {
+
+    @ApiModelProperty(value = "租户名", example = "芋道")
+    private String name;
+
+    @ApiModelProperty(value = "联系人", example = "芋艿")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系手机", example = "15601691300")
+    private String contactMobile;
+
+    @ApiModelProperty(value = "租户状态(0正常 1停用)", example = "1")
+    private Integer status;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 41 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("租户分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantPageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "租户名", example = "芋道")
+    private String name;
+
+    @ApiModelProperty(value = "联系人", example = "芋艿")
+    private String contactName;
+
+    @ApiModelProperty(value = "联系手机", example = "15601691300")
+    private String contactMobile;
+
+    @ApiModelProperty(value = "租户状态(0正常 1停用)", example = "1")
+    private Integer status;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 19 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+@ApiModel("租户 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantRespVO extends SysTenantBaseVO {
+
+    @ApiModelProperty(value = "租户编号", required = true, example = "1024")
+    private Long id;
+
+    @ApiModelProperty(value = "创建时间", required = true)
+    private Date createTime;
+
+}

+ 18 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("租户更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class SysTenantUpdateReqVO extends SysTenantBaseVO {
+
+    @ApiModelProperty(value = "租户编号", required = true, example = "1024")
+    @NotNull(message = "租户编号不能为空")
+    private Long id;
+
+}

+ 2 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http

@@ -1,3 +1,4 @@
 ### 请求 /system/user/page 接口 => 没有权限
 GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
-Authorization: Bearer test104 # 使用测试账号
+Authorization: Bearer test1 # 使用测试账号
+tenant-id: 1

+ 5 - 4
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java

@@ -8,15 +8,16 @@ import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
-import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
-import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;
 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import io.swagger.annotations.Api;
@@ -55,7 +56,7 @@ public class SysUserProfileController {
     @Resource
     private SysRoleService roleService;
     @Resource
-    private SysSocialService socialService;
+    private SysSocialCoreService socialService;
 
     @GetMapping("/get")
     @ApiOperation("获得登录用户信息")
@@ -77,7 +78,7 @@ public class SysUserProfileController {
             resp.setPosts(SysUserConvert.INSTANCE.convertList02(posts));
         }
         // 获得社交用户信息
-        List<SysSocialUserDO> socialUsers = socialService.getSocialUserList(user.getId());
+        List<SysSocialUserDO> socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN);
         resp.setSocialUsers(SysUserConvert.INSTANCE.convertList03(socialUsers));
         return success(resp);
     }

+ 36 - 0
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.adminserver.modules.system.convert.tenant;
+
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExcelVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantRespVO;
+import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 租户 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface SysTenantConvert {
+
+    SysTenantConvert INSTANCE = Mappers.getMapper(SysTenantConvert.class);
+
+    SysTenantDO convert(SysTenantCreateReqVO bean);
+
+    SysTenantDO convert(SysTenantUpdateReqVO bean);
+
+    SysTenantRespVO convert(SysTenantDO bean);
+
+    List<SysTenantRespVO> convertList(List<SysTenantDO> list);
+
+    PageResult<SysTenantRespVO> convertPage(PageResult<SysTenantDO> page);
+
+    List<SysTenantExcelVO> convertList02(List<SysTenantDO> list);
+
+}

+ 1 - 1
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java

@@ -7,7 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
-import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;
+import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;

+ 2 - 2
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
@@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
 @TableName("sys_dept")
 @Data
 @EqualsAndHashCode(callSuper = true)
-public class SysDeptDO extends BaseDO {
+public class SysDeptDO extends TenantBaseDO {
 
     /**
      * 部门ID

+ 2 - 3
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
@@ -15,14 +15,13 @@ import lombok.EqualsAndHashCode;
 @TableName("sys_post")
 @Data
 @EqualsAndHashCode(callSuper = true)
-public class SysPostDO extends BaseDO {
+public class SysPostDO extends TenantBaseDO {
 
     /**
      * 岗位序号
      */
     @TableId
     private Long id;
-
     /**
      * 岗位名称
      */

Vissa filer visades inte eftersom för många filer har ändrats