Commit f21ce954ec9492b7ab9a8256bf200df6459b525e

Authored by ex_yang.li@ca-nio.com
2 parents 5889093a e1e55dc8

Merge remote-tracking branch 'origin/feature/1.8.0-uniapp' into ly_uniapp

# Conflicts:
#	yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/api/price/PriceApiImpl.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderItemConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
#	yudao-server/src/main/resources/application.yaml
Showing 762 changed files with 52194 additions and 3808 deletions

Too many changes.

To preserve performance only 100 of 762 files are displayed.

README.md
@@ -23,8 +23,8 @@ @@ -23,8 +23,8 @@
23 > 23 >
24 > 😜 给项目点点 Star 吧,这对我们真的很重要! 24 > 😜 给项目点点 Star 吧,这对我们真的很重要!
25 25
26 -* 前端 Vue2 版本采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)  
27 -* 前端 Vue3 版本采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) 26 +* 管理后台的 Vue3 版本采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) ,Vue2 版本采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
  27 +* 管理后台的移动端采用 [uni-app](https://github.com/dcloudio/uni-app) 方案,一份代码多终端适配,同时支持 APP、小程序、H5!
28 * 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson 28 * 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson
29 * 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等 29 * 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等
30 * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录 30 * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录
@@ -156,8 +156,9 @@ ps:核心功能已经实现,正在对接微信小程序中... @@ -156,8 +156,9 @@ ps:核心功能已经实现,正在对接微信小程序中...
156 | `yudao-dependencies` | Maven 依赖版本管理 | 156 | `yudao-dependencies` | Maven 依赖版本管理 |
157 | `yudao-framework` | Java 框架拓展 | 157 | `yudao-framework` | Java 框架拓展 |
158 | `yudao-server` | 管理后台 + 用户 APP 的服务端 | 158 | `yudao-server` | 管理后台 + 用户 APP 的服务端 |
159 -| `yudao-ui-admin` | Vue2 管理后台的 UI 界面 |  
160 -| `yudao-ui-admin-vue3` | Vue3 管理后台的 UI 界面 | 159 +| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 |
  160 +| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 |
  161 +| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 |
161 | `yudao-ui-app` | 用户 APP 的 UI 界面 | 162 | `yudao-ui-app` | 用户 APP 的 UI 界面 |
162 | `yudao-module-system` | 系统功能的 Module 模块 | 163 | `yudao-module-system` | 系统功能的 Module 模块 |
163 | `yudao-module-member` | 会员中心的 Module 模块 | 164 | `yudao-module-member` | 会员中心的 Module 模块 |
@@ -169,48 +170,55 @@ ps:核心功能已经实现,正在对接微信小程序中... @@ -169,48 +170,55 @@ ps:核心功能已经实现,正在对接微信小程序中...
169 ### 后端 170 ### 后端
170 171
171 | 框架 | 说明 | 版本 | 学习指南 | 172 | 框架 | 说明 | 版本 | 学习指南 |
172 -|---------------------------------------------------------------------------------------------|-----------------------|-----------|----------------------------------------------------------------|  
173 -| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.6.10 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |  
174 -| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | |  
175 -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.11 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |  
176 -| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |  
177 -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |  
178 -| [Redis](https://redis.io/) | key-value 数据库 | 5.0 | |  
179 -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.17.4 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |  
180 -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.20 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |  
181 -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.6.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |  
182 -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.3 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |  
183 -| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.0 | [文档](https://doc.iocoder.cn/bpm/) |  
184 -| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |  
185 -| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.3 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |  
186 -| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |  
187 -| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |  
188 -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.6.7 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |  
189 -| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |  
190 -| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |  
191 -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |  
192 -| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |  
193 -| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.0.0 | - |  
194 -  
195 -### Vue2 前端 173 +|---------------------------------------------------------------------------------------------|-----------------------|---------|----------------------------------------------------------------|
  174 +| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.6.10 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
  175 +| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | |
  176 +| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.11 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
  177 +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
  178 +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
  179 +| [Redis](https://redis.io/) | key-value 数据库 | 5.0 | |
  180 +| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.17.4 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
  181 +| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.20 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
  182 +| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.6.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
  183 +| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.3 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
  184 +| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.2 | [文档](https://doc.iocoder.cn/bpm/) |
  185 +| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
  186 +| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.3 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
  187 +| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
  188 +| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
  189 +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.6.7 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
  190 +| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
  191 +| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
  192 +| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
  193 +| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
  194 +| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.0.0 | - |
  195 +
  196 +### [管理后台 Vue2 前端](./yudao-ui-admin)
196 197
197 | 框架 | 说明 | 版本 | 198 | 框架 | 说明 | 版本 |
198 |------------------------------------------------------------------------------|---------------|--------| 199 |------------------------------------------------------------------------------|---------------|--------|
199 | [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.6.12 | 200 | [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.6.12 |
200 | [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案 | - | 201 | [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案 | - |
201 202
202 -### Vue3 前端 203 +### [管理后台 Vue3 前端](./yudao-ui-admin-vue3)
  204 +
  205 +| 框架 | 说明 | 版本 |
  206 +|----------------------------------------------------------------------|-----------------|--------|
  207 +| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.37 |
  208 +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.0.4 |
  209 +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.12 |
  210 +| [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.7.4 |
  211 +| [pinia](https://pinia.vuejs.org/) | vuex5 | 2.0.17 |
  212 +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
  213 +| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 |
  214 +| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.1 |
  215 +
  216 +### [管理后台 uni-app 跨端](./yudao-ui-admin-uniapp)
203 217
204 | 框架 | 说明 | 版本 | 218 | 框架 | 说明 | 版本 |
205 |----------------------------------------------------------------------|------------------|--------| 219 |----------------------------------------------------------------------|------------------|--------|
206 -| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.37 |  
207 -| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.0.3 |  
208 -| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.11 |  
209 -| [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.7.4 |  
210 -| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.17 |  
211 -| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.1.10 |  
212 -| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 |  
213 -| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.1 | 220 +| [uni-app](hhttps://github.com/dcloudio/uni-app) | 跨平台框架 | 2.0.0 |
  221 +| [uni-ui](https://github.com/dcloudio/uni-ui) | 基于 uni-app 的 UI 框架 | 1.4.20 |
214 222
215 ## 🐷 演示图 223 ## 🐷 演示图
216 224
@@ -262,3 +270,13 @@ ps:核心功能已经实现,正在对接微信小程序中... @@ -262,3 +270,13 @@ ps:核心功能已经实现,正在对接微信小程序中...
262 | 模块 | biu | biu | biu | 270 | 模块 | biu | biu | biu |
263 |---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------| 271 |---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
264 | 报表设计器 | ![数据报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-数据报表.jpg?imageView2/2/format/webp/w/1280) | ![图形报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-图形报表.jpg?imageView2/2/format/webp/w/1280) | ![报表设计器-打印设计](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-打印设计.jpg?imageView2/2/format/webp/w/1280) | 272 | 报表设计器 | ![数据报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-数据报表.jpg?imageView2/2/format/webp/w/1280) | ![图形报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-图形报表.jpg?imageView2/2/format/webp/w/1280) | ![报表设计器-打印设计](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-打印设计.jpg?imageView2/2/format/webp/w/1280) |
  273 +
  274 +### 移动端(管理后台)
  275 +
  276 +| biu | biu | biu |
  277 +|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
  278 +| ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/01.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/02.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/03.png?imageView2/2/format/webp) |
  279 +| ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/04.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/05.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/06.png?imageView2/2/format/webp) |
  280 +| ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/07.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/08.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/09.png?imageView2/2/format/webp) |
  281 +
  282 +目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 27 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
28 28
29 <properties> 29 <properties>
30 - <revision>1.6.3-snapshot</revision> 30 + <revision>1.6.4-snapshot</revision>
31 <!-- Maven 相关 --> 31 <!-- Maven 相关 -->
32 <java.version>1.8</java.version> 32 <java.version>1.8</java.version>
33 <maven.compiler.source>${java.version}</maven.compiler.source> 33 <maven.compiler.source>${java.version}</maven.compiler.source>
sql/mysql/ruoyi-vue-pro.sql
@@ -2657,8 +2657,3 @@ INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, @@ -2657,8 +2657,3 @@ INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`,
2657 COMMIT; 2657 COMMIT;
2658 2658
2659 SET FOREIGN_KEY_CHECKS = 1; 2659 SET FOREIGN_KEY_CHECKS = 1;
2660 -  
2661 -  
2662 --- 积木报表菜单  
2663 -INSERT INTO `system_menu` VALUES (1281, '可视化报表', '', 1, 12, 0, '/visualization', 'chart', NULL, 0, b'1', b'1', '1', '2022-07-10 20:22:15', '1', '2022-07-10 20:33:30', b'0');  
2664 -INSERT INTO `system_menu` VALUES (1282, '积木报表', '', 2, 1, 1281, 'jm-report', '#', 'visualization/jm/index', 0, b'1', b'1', '1', '2022-07-10 20:26:36', '1', '2022-07-10 20:33:26', b'0');  
2665 \ No newline at end of file 2660 \ No newline at end of file
sql/mysql/update.sql 0 → 100644
  1 +-- ----------------------------
  2 +-- 升级SQL文件,全新安装只需要执行ruoyi-vue-pro.sql文件即可
  3 +-- 1.6.2 ==> 1.6.3
  4 +-- ----------------------------
  5 +-- 积木报表菜单
  6 +INSERT INTO `system_menu` VALUES (1281, '可视化报表', '', 1, 12, 0, '/visualization', 'chart', NULL, 0, b'1', b'1', '1', '2022-07-10 20:22:15', '1', '2022-07-10 20:33:30', b'0');
  7 +INSERT INTO `system_menu` VALUES (1282, '积木报表', '', 2, 1, 1281, 'jm-report', '#', 'visualization/jm/index', 0, b'1', b'1', '1', '2022-07-10 20:26:36', '1', '2022-07-10 20:33:26', b'0');
0 \ No newline at end of file 8 \ No newline at end of file
sql/mysql/vue3-menu.sql
@@ -257,5 +257,7 @@ INSERT INTO `system_menu` VALUES (1264, &#39;客户端查询&#39;, &#39;system:oauth2-client @@ -257,5 +257,7 @@ INSERT INTO `system_menu` VALUES (1264, &#39;客户端查询&#39;, &#39;system:oauth2-client
257 INSERT INTO `system_menu` VALUES (1265, '客户端创建', 'system:oauth2-client:create', 3, 2, 1263, '', '', '', 0, b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:23', b'0'); 257 INSERT INTO `system_menu` VALUES (1265, '客户端创建', 'system:oauth2-client:create', 3, 2, 1263, '', '', '', 0, b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:23', b'0');
258 INSERT INTO `system_menu` VALUES (1266, '客户端更新', 'system:oauth2-client:update', 3, 3, 1263, '', '', '', 0, b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:28', b'0'); 258 INSERT INTO `system_menu` VALUES (1266, '客户端更新', 'system:oauth2-client:update', 3, 3, 1263, '', '', '', 0, b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:28', b'0');
259 INSERT INTO `system_menu` VALUES (1267, '客户端删除', 'system:oauth2-client:delete', 3, 4, 1263, '', '', '', 0, b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:33', b'0'); 259 INSERT INTO `system_menu` VALUES (1267, '客户端删除', 'system:oauth2-client:delete', 3, 4, 1263, '', '', '', 0, b'1', b'1', '', '2022-05-10 16:26:33', '1', '2022-05-11 00:31:33', b'0');
  260 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1281, '可视化报表', '', 1, 12, 0, '/visualization', 'ep:histogram', NULL, 0, b'1', b'1', '1', '2022-07-10 20:22:15', '1', '2022-07-10 20:33:30', b'0');
  261 +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1282, '积木报表', '', 2, 1, 1281, 'jimu-report', 'ep:histogram', 'visualization/jmreport/index', 0, b'1', b'1', '1', '2022-07-10 20:26:36', '1', '2022-07-28 21:17:34', b'0');
260 262
261 SET FOREIGN_KEY_CHECKS = 1; 263 SET FOREIGN_KEY_CHECKS = 1;
sql/optional/mall/mall.sql
@@ -22,24 +22,24 @@ SET FOREIGN_KEY_CHECKS = 0; @@ -22,24 +22,24 @@ SET FOREIGN_KEY_CHECKS = 0;
22 -- ---------------------------- 22 -- ----------------------------
23 DROP TABLE IF EXISTS `market_activity`; 23 DROP TABLE IF EXISTS `market_activity`;
24 CREATE TABLE `market_activity` ( 24 CREATE TABLE `market_activity` (
25 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动编号',  
26 - `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '活动标题',  
27 - `activity_type` tinyint NOT NULL COMMENT '活动类型',  
28 - `status` tinyint NOT NULL DEFAULT -1 COMMENT '活动状态',  
29 - `start_time` datetime NOT NULL COMMENT '开始时间',  
30 - `end_time` datetime NOT NULL COMMENT '结束时间',  
31 - `invalid_time` datetime NULL DEFAULT NULL COMMENT '失效时间',  
32 - `delete_time` datetime NULL DEFAULT NULL COMMENT '删除时间',  
33 - `time_limited_discount` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',  
34 - `full_privilege` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',  
35 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',  
36 - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
37 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',  
38 - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
39 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
40 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
41 - PRIMARY KEY (`id`) USING BTREE  
42 -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '促销活动'; 25 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '活动编号',
  26 + `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '活动标题',
  27 + `activity_type` tinyint NOT NULL COMMENT '活动类型',
  28 + `status` tinyint NOT NULL DEFAULT -1 COMMENT '活动状态',
  29 + `start_time` datetime NOT NULL COMMENT '开始时间',
  30 + `end_time` datetime NOT NULL COMMENT '结束时间',
  31 + `invalid_time` datetime NULL DEFAULT NULL COMMENT '失效时间',
  32 + `delete_time` datetime NULL DEFAULT NULL COMMENT '删除时间',
  33 + `time_limited_discount` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',
  34 + `full_privilege` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '限制折扣字符串,使用 JSON 序列化成字符串存储',
  35 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
  36 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  37 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
  38 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  39 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  40 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  41 + PRIMARY KEY (`id`) USING BTREE
  42 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '促销活动';
43 43
44 -- ---------------------------- 44 -- ----------------------------
45 -- Records of market_activity 45 -- Records of market_activity
@@ -52,21 +52,21 @@ COMMIT; @@ -52,21 +52,21 @@ COMMIT;
52 -- ---------------------------- 52 -- ----------------------------
53 DROP TABLE IF EXISTS `market_banner`; 53 DROP TABLE IF EXISTS `market_banner`;
54 CREATE TABLE `market_banner` ( 54 CREATE TABLE `market_banner` (
55 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Banner编号',  
56 - `title` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'Banner标题',  
57 - `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '图片URL',  
58 - `status` tinyint NOT NULL DEFAULT -1 COMMENT '活动状态',  
59 - `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '跳转地址',  
60 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',  
61 - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
62 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',  
63 - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
64 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
65 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
66 - `sort` tinyint NULL DEFAULT NULL COMMENT '排序',  
67 - `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述',  
68 - PRIMARY KEY (`id`) USING BTREE  
69 -) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = 'Banner管理'; 55 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Banner编号',
  56 + `title` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'Banner标题',
  57 + `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '图片URL',
  58 + `status` tinyint NOT NULL DEFAULT -1 COMMENT '活动状态',
  59 + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '跳转地址',
  60 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者',
  61 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  62 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者',
  63 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  64 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  65 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  66 + `sort` tinyint NULL DEFAULT NULL COMMENT '排序',
  67 + `memo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '描述',
  68 + PRIMARY KEY (`id`) USING BTREE
  69 +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Banner管理';
70 70
71 -- ---------------------------- 71 -- ----------------------------
72 -- Records of market_banner 72 -- Records of market_banner
@@ -79,22 +79,22 @@ COMMIT; @@ -79,22 +79,22 @@ COMMIT;
79 -- ---------------------------- 79 -- ----------------------------
80 DROP TABLE IF EXISTS `member_address`; 80 DROP TABLE IF EXISTS `member_address`;
81 CREATE TABLE `member_address` ( 81 CREATE TABLE `member_address` (
82 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '收件地址编号',  
83 - `user_id` bigint NOT NULL COMMENT '用户编号',  
84 - `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '收件人名称',  
85 - `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '手机号',  
86 - `area_id` bigint NOT NULL COMMENT '地区编码',  
87 - `post_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '邮编',  
88 - `detail_address` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '收件详细地址',  
89 - `defaulted` bit(1) NOT NULL COMMENT '是否默认',  
90 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',  
91 - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
92 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',  
93 - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
94 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
95 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
96 - PRIMARY KEY (`id`) USING BTREE,  
97 - INDEX `idx_userId`(`user_id` ASC) USING BTREE 82 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '收件地址编号',
  83 + `user_id` bigint NOT NULL COMMENT '用户编号',
  84 + `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '收件人名称',
  85 + `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '手机号',
  86 + `area_id` bigint NOT NULL COMMENT '地区编码',
  87 + `post_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '邮编',
  88 + `detail_address` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '收件详细地址',
  89 + `defaulted` bit(1) NOT NULL COMMENT '是否默认',
  90 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  91 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  92 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  93 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  94 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  95 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  96 + PRIMARY KEY (`id`) USING BTREE,
  97 + INDEX `idx_userId`(`user_id` ASC) USING BTREE
98 ) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址'; 98 ) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址';
99 99
100 -- ---------------------------- 100 -- ----------------------------
@@ -109,19 +109,19 @@ COMMIT; @@ -109,19 +109,19 @@ COMMIT;
109 -- ---------------------------- 109 -- ----------------------------
110 DROP TABLE IF EXISTS `product_brand`; 110 DROP TABLE IF EXISTS `product_brand`;
111 CREATE TABLE `product_brand` ( 111 CREATE TABLE `product_brand` (
112 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号',  
113 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌名称',  
114 - `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌图片',  
115 - `sort` int NULL DEFAULT 0 COMMENT '品牌排序',  
116 - `description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '品牌描述',  
117 - `status` tinyint NOT NULL COMMENT '状态',  
118 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',  
119 - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
120 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',  
121 - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
122 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
123 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
124 - PRIMARY KEY (`id`) USING BTREE 112 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌编号',
  113 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌名称',
  114 + `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '品牌图片',
  115 + `sort` int NULL DEFAULT 0 COMMENT '品牌排序',
  116 + `description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '品牌描述',
  117 + `status` tinyint NOT NULL COMMENT '状态',
  118 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  119 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  120 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  121 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  122 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  123 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  124 + PRIMARY KEY (`id`) USING BTREE
125 ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品品牌'; 125 ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品品牌';
126 126
127 -- ---------------------------- 127 -- ----------------------------
@@ -136,20 +136,20 @@ COMMIT; @@ -136,20 +136,20 @@ COMMIT;
136 -- ---------------------------- 136 -- ----------------------------
137 DROP TABLE IF EXISTS `product_category`; 137 DROP TABLE IF EXISTS `product_category`;
138 CREATE TABLE `product_category` ( 138 CREATE TABLE `product_category` (
139 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',  
140 - `parent_id` bigint NOT NULL COMMENT '父分类编号',  
141 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类名称',  
142 - `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类图片',  
143 - `sort` int NULL DEFAULT 0 COMMENT '分类排序',  
144 - `description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '分类描述',  
145 - `status` tinyint NOT NULL COMMENT '开启状态',  
146 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',  
147 - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
148 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',  
149 - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
150 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
151 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
152 - PRIMARY KEY (`id`) USING BTREE 139 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
  140 + `parent_id` bigint NOT NULL COMMENT '父分类编号',
  141 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类名称',
  142 + `pic_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类图片',
  143 + `sort` int NULL DEFAULT 0 COMMENT '分类排序',
  144 + `description` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '分类描述',
  145 + `status` tinyint NOT NULL COMMENT '开启状态',
  146 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
  147 + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  148 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
  149 + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  150 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  151 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  152 + PRIMARY KEY (`id`) USING BTREE
153 ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品分类'; 153 ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品分类';
154 154
155 -- ---------------------------- 155 -- ----------------------------
@@ -164,17 +164,17 @@ COMMIT; @@ -164,17 +164,17 @@ COMMIT;
164 -- ---------------------------- 164 -- ----------------------------
165 DROP TABLE IF EXISTS `product_property`; 165 DROP TABLE IF EXISTS `product_property`;
166 CREATE TABLE `product_property` ( 166 CREATE TABLE `product_property` (
167 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',  
168 - `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格名称',  
169 - `status` tinyint NULL DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用',  
170 - `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
171 - `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
172 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',  
173 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',  
174 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
175 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
176 - PRIMARY KEY (`id`) USING BTREE,  
177 - INDEX `idx_name`(`name`(32) ASC) USING BTREE COMMENT '规格名称索引' 167 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  168 + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格名称',
  169 + `status` tinyint NULL DEFAULT NULL COMMENT '状态: 0 开启 ,1 禁用',
  170 + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  171 + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  172 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
  173 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
  174 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  175 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  176 + PRIMARY KEY (`id`) USING BTREE,
  177 + INDEX `idx_name`(`name`(32) ASC) USING BTREE COMMENT '规格名称索引'
178 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格名称'; 178 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格名称';
179 179
180 -- ---------------------------- 180 -- ----------------------------
@@ -188,17 +188,17 @@ COMMIT; @@ -188,17 +188,17 @@ COMMIT;
188 -- ---------------------------- 188 -- ----------------------------
189 DROP TABLE IF EXISTS `product_property_value`; 189 DROP TABLE IF EXISTS `product_property_value`;
190 CREATE TABLE `product_property_value` ( 190 CREATE TABLE `product_property_value` (
191 - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',  
192 - `property_id` bigint NULL DEFAULT NULL COMMENT '规格键id',  
193 - `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格值名字',  
194 - `status` tinyint NULL DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用',  
195 - `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
196 - `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
197 - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',  
198 - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',  
199 - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',  
200 - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
201 - PRIMARY KEY (`id`) USING BTREE 191 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  192 + `property_id` bigint NULL DEFAULT NULL COMMENT '规格键id',
  193 + `name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规格值名字',
  194 + `status` tinyint NULL DEFAULT NULL COMMENT '状态: 1 开启 ,2 禁用',
  195 + `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  196 + `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  197 + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
  198 + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
  199 + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
  200 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  201 + PRIMARY KEY (`id`) USING BTREE
202 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格值'; 202 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格值';
203 203
204 -- ---------------------------- 204 -- ----------------------------
@@ -212,25 +212,25 @@ COMMIT; @@ -212,25 +212,25 @@ COMMIT;
212 -- ---------------------------- 212 -- ----------------------------
213 DROP TABLE IF EXISTS `product_sku`; 213 DROP TABLE IF EXISTS `product_sku`;
214 CREATE TABLE `product_sku` ( 214 CREATE TABLE `product_sku` (
215 -`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',  
216 -`spu_id` bigint NOT NULL COMMENT 'spu编号',  
217 -`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',  
218 -`name` varchar(128) DEFAULT NULL COMMENT '商品 SKU 名字',  
219 -`properties` varchar(128) DEFAULT NULL COMMENT '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]',  
220 -`price` int NOT NULL DEFAULT '-1' COMMENT '销售价格,单位:分',  
221 -`market_price` int DEFAULT NULL COMMENT '市场价',  
222 -`cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分',  
223 -`pic_url` varchar(128) NOT NULL COMMENT '图片地址',  
224 -`stock` int DEFAULT NULL COMMENT '库存',  
225 -`warn_stock` int DEFAULT NULL COMMENT '预警库存',  
226 -`volume` double DEFAULT NULL COMMENT '商品体积',  
227 -`weight` double DEFAULT NULL COMMENT '商品重量',  
228 -`bar_code` varchar(64) DEFAULT NULL COMMENT '条形码',  
229 -`status` tinyint DEFAULT NULL COMMENT '状态: 0-正常 1-禁用',  
230 -`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
231 -`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
232 -`creator` varchar(64) DEFAULT NULL COMMENT '创建人',  
233 -`updater` double(64,0) DEFAULT NULL COMMENT '更新人', 215 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  216 + `spu_id` bigint NOT NULL COMMENT 'spu编号',
  217 + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  218 + `name` varchar(128) DEFAULT NULL COMMENT '商品 SKU 名字',
  219 + `properties` varchar(128) DEFAULT NULL COMMENT '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]',
  220 + `price` int NOT NULL DEFAULT '-1' COMMENT '销售价格,单位:分',
  221 + `market_price` int DEFAULT NULL COMMENT '市场价',
  222 + `cost_price` int NOT NULL DEFAULT '-1' COMMENT '成本价,单位: 分',
  223 + `pic_url` varchar(128) NOT NULL COMMENT '图片地址',
  224 + `stock` int DEFAULT NULL COMMENT '库存',
  225 + `warn_stock` int DEFAULT NULL COMMENT '预警库存',
  226 + `volume` double DEFAULT NULL COMMENT '商品体积',
  227 + `weight` double DEFAULT NULL COMMENT '商品重量',
  228 + `bar_code` varchar(64) DEFAULT NULL COMMENT '条形码',
  229 + `status` tinyint DEFAULT NULL COMMENT '状态: 0-正常 1-禁用',
  230 + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  231 + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  232 + `creator` varchar(64) DEFAULT NULL COMMENT '创建人',
  233 + `updater` double(64,0) DEFAULT NULL COMMENT '更新人',
234 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', 234 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
235 PRIMARY KEY (`id`) USING BTREE 235 PRIMARY KEY (`id`) USING BTREE
236 ) ENGINE=InnoDB COMMENT='商品sku'; 236 ) ENGINE=InnoDB COMMENT='商品sku';
@@ -246,33 +246,33 @@ COMMIT; @@ -246,33 +246,33 @@ COMMIT;
246 -- ---------------------------- 246 -- ----------------------------
247 DROP TABLE IF EXISTS `product_spu`; 247 DROP TABLE IF EXISTS `product_spu`;
248 CREATE TABLE `product_spu` ( 248 CREATE TABLE `product_spu` (
249 -`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',  
250 -`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',  
251 -`brand_id` int DEFAULT NULL COMMENT '商品品牌编号',  
252 -`category_id` bigint NOT NULL COMMENT '分类id',  
253 -`spec_type` int NOT NULL COMMENT '规格类型:0 单规格 1 多规格',  
254 -`code` varchar(128) DEFAULT NULL COMMENT '商品编码',  
255 -`name` varchar(128) NOT NULL COMMENT '商品名称',  
256 -`sell_point` varchar(128) DEFAULT NULL COMMENT '卖点',  
257 -`description` text COMMENT '描述',  
258 -`pic_urls` varchar(1024) DEFAULT '' COMMENT '商品轮播图地址\n 数组,以逗号分隔\n 最多上传15张',  
259 -`video_url` varchar(128) DEFAULT NULL COMMENT '商品视频',  
260 -`market_price` int DEFAULT NULL COMMENT '市场价,单位使用:分',  
261 -`min_price` int DEFAULT NULL COMMENT '最小价格,单位使用:分',  
262 -`max_price` int DEFAULT NULL COMMENT '最大价格,单位使用:分',  
263 -`total_stock` int NOT NULL DEFAULT '0' COMMENT '总库存',  
264 -`show_stock` int DEFAULT '0' COMMENT '是否展示库存',  
265 -`sales_count` int DEFAULT '0' COMMENT '商品销量',  
266 -`virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量',  
267 -`click_count` int DEFAULT '0' COMMENT '商品点击量',  
268 -`status` bit(1) DEFAULT NULL COMMENT '上下架状态: 0 上架(开启) 1 下架(禁用)-1 回收',  
269 -`sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',  
270 -`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
271 -`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  
272 -`creator` varchar(64) DEFAULT NULL COMMENT '创建人',  
273 -`updater` varchar(64) DEFAULT NULL COMMENT '更新人',  
274 -`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',  
275 -PRIMARY KEY (`id`) USING BTREE 249 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  250 + `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号',
  251 + `brand_id` int DEFAULT NULL COMMENT '商品品牌编号',
  252 + `category_id` bigint NOT NULL COMMENT '分类id',
  253 + `spec_type` int NOT NULL COMMENT '规格类型:0 单规格 1 多规格',
  254 + `code` varchar(128) DEFAULT NULL COMMENT '商品编码',
  255 + `name` varchar(128) NOT NULL COMMENT '商品名称',
  256 + `sell_point` varchar(128) DEFAULT NULL COMMENT '卖点',
  257 + `description` text COMMENT '描述',
  258 + `pic_urls` varchar(1024) DEFAULT '' COMMENT '商品轮播图地址\n 数组,以逗号分隔\n 最多上传15张',
  259 + `video_url` varchar(128) DEFAULT NULL COMMENT '商品视频',
  260 + `market_price` int DEFAULT NULL COMMENT '市场价,单位使用:分',
  261 + `min_price` int DEFAULT NULL COMMENT '最小价格,单位使用:分',
  262 + `max_price` int DEFAULT NULL COMMENT '最大价格,单位使用:分',
  263 + `total_stock` int NOT NULL DEFAULT '0' COMMENT '总库存',
  264 + `show_stock` int DEFAULT '0' COMMENT '是否展示库存',
  265 + `sales_count` int DEFAULT '0' COMMENT '商品销量',
  266 + `virtual_sales_count` int DEFAULT '0' COMMENT '虚拟销量',
  267 + `click_count` int DEFAULT '0' COMMENT '商品点击量',
  268 + `status` bit(1) DEFAULT NULL COMMENT '上下架状态: 0 上架(开启) 1 下架(禁用)-1 回收',
  269 + `sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
  270 + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  271 + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  272 + `creator` varchar(64) DEFAULT NULL COMMENT '创建人',
  273 + `updater` varchar(64) DEFAULT NULL COMMENT '更新人',
  274 + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  275 + PRIMARY KEY (`id`) USING BTREE
276 ) ENGINE=InnoDB COMMENT='商品spu'; 276 ) ENGINE=InnoDB COMMENT='商品spu';
277 277
278 -- ---------------------------- 278 -- ----------------------------
yudao-dependencies/pom.xml
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.6.3-snapshot</revision> 17 + <revision>1.6.4-snapshot</revision>
18 <!-- 统一依赖管理 --> 18 <!-- 统一依赖管理 -->
19 <spring.boot.version>2.6.10</spring.boot.version> 19 <spring.boot.version>2.6.10</spring.boot.version>
20 <!-- Web 相关 --> 20 <!-- Web 相关 -->
@@ -41,14 +41,14 @@ @@ -41,14 +41,14 @@
41 <jedis-mock.version>0.1.16</jedis-mock.version> 41 <jedis-mock.version>0.1.16</jedis-mock.version>
42 <mockito-inline.version>4.0.0</mockito-inline.version> 42 <mockito-inline.version>4.0.0</mockito-inline.version>
43 <!-- Bpm 工作流相关 --> 43 <!-- Bpm 工作流相关 -->
44 - <flowable.version>6.7.0</flowable.version> 44 + <flowable.version>6.7.2</flowable.version>
45 <!-- 工具类相关 --> 45 <!-- 工具类相关 -->
46 <jasypt-spring-boot-starter.version>3.0.4</jasypt-spring-boot-starter.version> 46 <jasypt-spring-boot-starter.version>3.0.4</jasypt-spring-boot-starter.version>
47 <lombok.version>1.18.20</lombok.version> 47 <lombok.version>1.18.20</lombok.version>
48 <mapstruct.version>1.4.1.Final</mapstruct.version> 48 <mapstruct.version>1.4.1.Final</mapstruct.version>
49 - <hutool.version>5.7.22</hutool.version> 49 + <hutool.version>5.8.5</hutool.version>
50 <easyexcel.verion>3.1.1</easyexcel.verion> 50 <easyexcel.verion>3.1.1</easyexcel.verion>
51 - <velocity.version>2.2</velocity.version> 51 + <velocity.version>2.3</velocity.version>
52 <screw.version>1.0.5</screw.version> 52 <screw.version>1.0.5</screw.version>
53 <fastjson.version>1.2.83</fastjson.version> 53 <fastjson.version>1.2.83</fastjson.version>
54 <guava.version>30.1.1-jre</guava.version> 54 <guava.version>30.1.1-jre</guava.version>
@@ -57,14 +57,16 @@ @@ -57,14 +57,16 @@
57 <commons-net.version>3.8.0</commons-net.version> 57 <commons-net.version>3.8.0</commons-net.version>
58 <jsch.version>0.1.55</jsch.version> 58 <jsch.version>0.1.55</jsch.version>
59 <tika-core.version>2.4.1</tika-core.version> 59 <tika-core.version>2.4.1</tika-core.version>
  60 + <aj-captcha.version>1.3.0</aj-captcha.version>
60 <!-- 三方云服务相关 --> 61 <!-- 三方云服务相关 -->
61 <minio.version>8.2.2</minio.version> 62 <minio.version>8.2.2</minio.version>
62 - <aliyun-java-sdk-core.version>4.5.25</aliyun-java-sdk-core.version>  
63 - <aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>  
64 - <tencentcloud-sdk-java.version>3.1.471</tencentcloud-sdk-java.version> 63 + <aliyun-java-sdk-core.version>4.6.0</aliyun-java-sdk-core.version>
  64 + <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
  65 + <tencentcloud-sdk-java.version>3.1.561</tencentcloud-sdk-java.version>
65 <yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version> 66 <yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
66 <justauth.version>1.4.0</justauth.version> 67 <justauth.version>1.4.0</justauth.version>
67 <jimureport.version>1.5.2</jimureport.version> 68 <jimureport.version>1.5.2</jimureport.version>
  69 + <xercesImpl.version>2.12.0</xercesImpl.version>
68 </properties> 70 </properties>
69 71
70 <dependencyManagement> 72 <dependencyManagement>
@@ -129,6 +131,11 @@ @@ -129,6 +131,11 @@
129 <artifactId>yudao-spring-boot-starter-biz-error-code</artifactId> 131 <artifactId>yudao-spring-boot-starter-biz-error-code</artifactId>
130 <version>${revision}</version> 132 <version>${revision}</version>
131 </dependency> 133 </dependency>
  134 + <dependency>
  135 + <groupId>cn.iocoder.boot</groupId>
  136 + <artifactId>yudao-spring-boot-starter-captcha</artifactId>
  137 + <version>${revision}</version>
  138 + </dependency>
132 139
133 <!-- Spring 核心 --> 140 <!-- Spring 核心 -->
134 <dependency> 141 <dependency>
@@ -452,6 +459,12 @@ @@ -452,6 +459,12 @@
452 </dependency> 459 </dependency>
453 460
454 <dependency> 461 <dependency>
  462 + <groupId>com.anji-plus</groupId>
  463 + <artifactId>spring-boot-starter-captcha</artifactId>
  464 + <version>${aj-captcha.version}</version>
  465 + </dependency>
  466 +
  467 + <dependency>
455 <groupId>org.apache.velocity</groupId> 468 <groupId>org.apache.velocity</groupId>
456 <artifactId>velocity-engine-core</artifactId> 469 <artifactId>velocity-engine-core</artifactId>
457 <version>${velocity.version}</version> 470 <version>${velocity.version}</version>
@@ -565,6 +578,11 @@ @@ -565,6 +578,11 @@
565 <artifactId>jimureport-spring-boot-starter</artifactId> 578 <artifactId>jimureport-spring-boot-starter</artifactId>
566 <version>${jimureport.version}</version> 579 <version>${jimureport.version}</version>
567 </dependency> 580 </dependency>
  581 + <dependency>
  582 + <groupId>xerces</groupId>
  583 + <artifactId>xercesImpl</artifactId>
  584 + <version>${xercesImpl.version}</version>
  585 + </dependency>
568 </dependencies> 586 </dependencies>
569 </dependencyManagement> 587 </dependencyManagement>
570 588
yudao-framework/pom.xml
@@ -39,6 +39,7 @@ @@ -39,6 +39,7 @@
39 <module>yudao-spring-boot-starter-biz-error-code</module> 39 <module>yudao-spring-boot-starter-biz-error-code</module>
40 40
41 <module>yudao-spring-boot-starter-flowable</module> 41 <module>yudao-spring-boot-starter-flowable</module>
  42 + <module>yudao-spring-boot-starter-captcha</module>
42 </modules> 43 </modules>
43 44
44 <artifactId>yudao-framework</artifactId> 45 <artifactId>yudao-framework</artifactId>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java
1 package cn.iocoder.yudao.framework.common.util.collection; 1 package cn.iocoder.yudao.framework.common.util.collection;
2 2
3 import cn.hutool.core.collection.CollectionUtil; 3 import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.hutool.core.collection.IterUtil;
4 import cn.hutool.core.util.ArrayUtil; 5 import cn.hutool.core.util.ArrayUtil;
5 6
6 import java.util.Collection; 7 import java.util.Collection;
@@ -44,7 +45,7 @@ public class ArrayUtils { @@ -44,7 +45,7 @@ public class ArrayUtils {
44 if (CollectionUtil.isEmpty(from)) { 45 if (CollectionUtil.isEmpty(from)) {
45 return (T[]) (new Object[0]); 46 return (T[]) (new Object[0]);
46 } 47 }
47 - return ArrayUtil.toArray(from, (Class<T>) CollectionUtil.getElementType(from.iterator())); 48 + return ArrayUtil.toArray(from, (Class<T>) IterUtil.getElementType(from.iterator()));
48 } 49 }
49 50
50 public static <T> T get(T[] array, int index) { 51 public static <T> T get(T[] array, int index) {
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java
@@ -17,16 +17,15 @@ import java.util.regex.Pattern; @@ -17,16 +17,15 @@ import java.util.regex.Pattern;
17 */ 17 */
18 public class ValidationUtils { 18 public class ValidationUtils {
19 19
  20 + private static final Pattern PATTERN_MOBILE = Pattern.compile("^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[189]))\\d{8}$");
  21 +
20 private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); 22 private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");
21 23
22 private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*"); 24 private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*");
23 25
24 public static boolean isMobile(String mobile) { 26 public static boolean isMobile(String mobile) {
25 - if (StrUtil.length(mobile) != 11) {  
26 - return false;  
27 - }  
28 - // TODO 芋艿,后面完善手机校验  
29 - return true; 27 + return StringUtils.hasText(mobile)
  28 + && PATTERN_MOBILE.matcher(mobile).matches();
30 } 29 }
31 30
32 public static boolean isURL(String url) { 31 public static boolean isURL(String url) {
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptor.java
@@ -18,7 +18,6 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression; @@ -18,7 +18,6 @@ import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
18 import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; 18 import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
19 import net.sf.jsqlparser.expression.operators.relational.ExpressionList; 19 import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
20 import net.sf.jsqlparser.expression.operators.relational.InExpression; 20 import net.sf.jsqlparser.expression.operators.relational.InExpression;
21 -import net.sf.jsqlparser.expression.operators.relational.ItemsList;  
22 import net.sf.jsqlparser.schema.Table; 21 import net.sf.jsqlparser.schema.Table;
23 import net.sf.jsqlparser.statement.delete.Delete; 22 import net.sf.jsqlparser.statement.delete.Delete;
24 import net.sf.jsqlparser.statement.select.*; 23 import net.sf.jsqlparser.statement.select.*;
@@ -37,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; @@ -37,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
37 36
38 /** 37 /**
39 * 数据权限拦截器,通过 {@link DataPermissionRule} 数据权限规则,重写 SQL 的方式来实现 38 * 数据权限拦截器,通过 {@link DataPermissionRule} 数据权限规则,重写 SQL 的方式来实现
40 - * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, Table)} 方法 39 + * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, List)} 方法
41 * 40 *
42 * 整体的代码实现上,参考 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} 实现。 41 * 整体的代码实现上,参考 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} 实现。
43 * 所以每次 MyBatis Plus 升级时,需要 Review 下其具体的实现是否有变更! 42 * 所以每次 MyBatis Plus 升级时,需要 Review 下其具体的实现是否有变更!
@@ -53,8 +52,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -53,8 +52,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
53 private final MappedStatementCache mappedStatementCache = new MappedStatementCache(); 52 private final MappedStatementCache mappedStatementCache = new MappedStatementCache();
54 53
55 @Override // SELECT 场景 54 @Override // SELECT 场景
56 - public void beforeQuery(Executor executor, MappedStatement ms, Object parameter,  
57 - RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 55 + public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
58 // 获得 Mapper 对应的数据权限的规则 56 // 获得 Mapper 对应的数据权限的规则
59 List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(ms.getId()); 57 List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(ms.getId());
60 if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过 58 if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过
@@ -68,12 +66,14 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -68,12 +66,14 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
68 // 处理 SQL 66 // 处理 SQL
69 mpBs.sql(parserSingle(mpBs.sql(), null)); 67 mpBs.sql(parserSingle(mpBs.sql(), null));
70 } finally { 68 } finally {
  69 + // 添加是否需要重写的缓存
71 addMappedStatementCache(ms); 70 addMappedStatementCache(ms);
  71 + // 清空上下文
72 ContextHolder.clear(); 72 ContextHolder.clear();
73 } 73 }
74 } 74 }
75 75
76 - @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景 76 + @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景(因为 INSERT 不需要数据权限)
77 public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { 77 public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
78 PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); 78 PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
79 MappedStatement ms = mpSh.mappedStatement(); 79 MappedStatement ms = mpSh.mappedStatement();
@@ -92,7 +92,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -92,7 +92,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
92 // 处理 SQL 92 // 处理 SQL
93 mpBs.sql(parserMulti(mpBs.sql(), null)); 93 mpBs.sql(parserMulti(mpBs.sql(), null));
94 } finally { 94 } finally {
  95 + // 添加是否需要重写的缓存
95 addMappedStatementCache(ms); 96 addMappedStatementCache(ms);
  97 + // 清空上下文
96 ContextHolder.clear(); 98 ContextHolder.clear();
97 } 99 }
98 } 100 }
@@ -107,24 +109,6 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -107,24 +109,6 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
107 } 109 }
108 } 110 }
109 111
110 - protected void processSelectBody(SelectBody selectBody) {  
111 - if (selectBody == null) {  
112 - return;  
113 - }  
114 - if (selectBody instanceof PlainSelect) {  
115 - processPlainSelect((PlainSelect) selectBody);  
116 - } else if (selectBody instanceof WithItem) {  
117 - WithItem withItem = (WithItem) selectBody;  
118 - processSelectBody(withItem.getSubSelect().getSelectBody());  
119 - } else {  
120 - SetOperationList operationList = (SetOperationList) selectBody;  
121 - List<SelectBody> selectBodys = operationList.getSelects();  
122 - if (CollectionUtils.isNotEmpty(selectBodys)) {  
123 - selectBodys.forEach(this::processSelectBody);  
124 - }  
125 - }  
126 - }  
127 -  
128 /** 112 /**
129 * update 语句处理 113 * update 语句处理
130 */ 114 */
@@ -142,28 +126,77 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -142,28 +126,77 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
142 delete.setWhere(this.builderExpression(delete.getWhere(), delete.getTable())); 126 delete.setWhere(this.builderExpression(delete.getWhere(), delete.getTable()));
143 } 127 }
144 128
  129 + // ========== 和 TenantLineInnerInterceptor 一致的逻辑 ==========
  130 +
  131 + protected void processSelectBody(SelectBody selectBody) {
  132 + if (selectBody == null) {
  133 + return;
  134 + }
  135 + if (selectBody instanceof PlainSelect) {
  136 + processPlainSelect((PlainSelect) selectBody);
  137 + } else if (selectBody instanceof WithItem) {
  138 + WithItem withItem = (WithItem) selectBody;
  139 + processSelectBody(withItem.getSubSelect().getSelectBody());
  140 + } else {
  141 + SetOperationList operationList = (SetOperationList) selectBody;
  142 + List<SelectBody> selectBodyList = operationList.getSelects();
  143 + if (CollectionUtils.isNotEmpty(selectBodyList)) {
  144 + selectBodyList.forEach(this::processSelectBody);
  145 + }
  146 + }
  147 + }
  148 +
145 /** 149 /**
146 * 处理 PlainSelect 150 * 处理 PlainSelect
147 */ 151 */
148 protected void processPlainSelect(PlainSelect plainSelect) { 152 protected void processPlainSelect(PlainSelect plainSelect) {
149 - FromItem fromItem = plainSelect.getFromItem();  
150 - Expression where = plainSelect.getWhere();  
151 - processWhereSubSelect(where);  
152 - if (fromItem instanceof Table) {  
153 - Table fromTable = (Table) fromItem;  
154 - plainSelect.setWhere(builderExpression(where, fromTable));  
155 - } else {  
156 - processFromItem(fromItem);  
157 - }  
158 //#3087 github 153 //#3087 github
159 List<SelectItem> selectItems = plainSelect.getSelectItems(); 154 List<SelectItem> selectItems = plainSelect.getSelectItems();
160 if (CollectionUtils.isNotEmpty(selectItems)) { 155 if (CollectionUtils.isNotEmpty(selectItems)) {
161 selectItems.forEach(this::processSelectItem); 156 selectItems.forEach(this::processSelectItem);
162 } 157 }
  158 +
  159 + // 处理 where 中的子查询
  160 + Expression where = plainSelect.getWhere();
  161 + processWhereSubSelect(where);
  162 +
  163 + // 处理 fromItem
  164 + FromItem fromItem = plainSelect.getFromItem();
  165 + List<Table> list = processFromItem(fromItem);
  166 + List<Table> mainTables = new ArrayList<>(list);
  167 +
  168 + // 处理 join
163 List<Join> joins = plainSelect.getJoins(); 169 List<Join> joins = plainSelect.getJoins();
164 if (CollectionUtils.isNotEmpty(joins)) { 170 if (CollectionUtils.isNotEmpty(joins)) {
165 - processJoins(joins); 171 + mainTables = processJoins(mainTables, joins);
  172 + }
  173 +
  174 + // 当有 mainTable 时,进行 where 条件追加
  175 + if (CollectionUtils.isNotEmpty(mainTables)) {
  176 + plainSelect.setWhere(builderExpression(where, mainTables));
  177 + }
  178 + }
  179 +
  180 + private List<Table> processFromItem(FromItem fromItem) {
  181 + // 处理括号括起来的表达式
  182 + while (fromItem instanceof ParenthesisFromItem) {
  183 + fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
  184 + }
  185 +
  186 + List<Table> mainTables = new ArrayList<>();
  187 + // 无 join 时的处理逻辑
  188 + if (fromItem instanceof Table) {
  189 + Table fromTable = (Table) fromItem;
  190 + mainTables.add(fromTable);
  191 + } else if (fromItem instanceof SubJoin) {
  192 + // SubJoin 类型则还需要添加上 where 条件
  193 + List<Table> tables = processSubJoin((SubJoin) fromItem);
  194 + mainTables.addAll(tables);
  195 + } else {
  196 + // 处理下 fromItem
  197 + processOtherFromItem(fromItem);
166 } 198 }
  199 + return mainTables;
167 } 200 }
168 201
169 /** 202 /**
@@ -191,7 +224,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -191,7 +224,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
191 return; 224 return;
192 } 225 }
193 if (where instanceof FromItem) { 226 if (where instanceof FromItem) {
194 - processFromItem((FromItem) where); 227 + processOtherFromItem((FromItem) where);
195 return; 228 return;
196 } 229 }
197 if (where.toString().indexOf("SELECT") > 0) { 230 if (where.toString().indexOf("SELECT") > 0) {
@@ -204,9 +237,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -204,9 +237,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
204 } else if (where instanceof InExpression) { 237 } else if (where instanceof InExpression) {
205 // in 238 // in
206 InExpression expression = (InExpression) where; 239 InExpression expression = (InExpression) where;
207 - ItemsList itemsList = expression.getRightItemsList();  
208 - if (itemsList instanceof SubSelect) {  
209 - processSelectBody(((SubSelect) itemsList).getSelectBody()); 240 + Expression inExpression = expression.getRightExpression();
  241 + if (inExpression instanceof SubSelect) {
  242 + processSelectBody(((SubSelect) inExpression).getSelectBody());
210 } 243 }
211 } else if (where instanceof ExistsExpression) { 244 } else if (where instanceof ExistsExpression) {
212 // exists 245 // exists
@@ -239,7 +272,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -239,7 +272,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
239 * <p>支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)<p> 272 * <p>支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)<p>
240 * <p> fixed gitee pulls/141</p> 273 * <p> fixed gitee pulls/141</p>
241 * 274 *
242 - * @param function 函数 275 + * @param function
243 */ 276 */
244 protected void processFunction(Function function) { 277 protected void processFunction(Function function) {
245 ExpressionList parameters = function.getParameters(); 278 ExpressionList parameters = function.getParameters();
@@ -257,22 +290,19 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -257,22 +290,19 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
257 /** 290 /**
258 * 处理子查询等 291 * 处理子查询等
259 */ 292 */
260 - protected void processFromItem(FromItem fromItem) {  
261 - if (fromItem instanceof SubJoin) {  
262 - SubJoin subJoin = (SubJoin) fromItem;  
263 - if (subJoin.getJoinList() != null) {  
264 - processJoins(subJoin.getJoinList());  
265 - }  
266 - if (subJoin.getLeft() != null) {  
267 - processFromItem(subJoin.getLeft());  
268 - }  
269 - } else if (fromItem instanceof SubSelect) { 293 + protected void processOtherFromItem(FromItem fromItem) {
  294 + // 去除括号
  295 + while (fromItem instanceof ParenthesisFromItem) {
  296 + fromItem = ((ParenthesisFromItem) fromItem).getFromItem();
  297 + }
  298 +
  299 + if (fromItem instanceof SubSelect) {
270 SubSelect subSelect = (SubSelect) fromItem; 300 SubSelect subSelect = (SubSelect) fromItem;
271 if (subSelect.getSelectBody() != null) { 301 if (subSelect.getSelectBody() != null) {
272 processSelectBody(subSelect.getSelectBody()); 302 processSelectBody(subSelect.getSelectBody());
273 } 303 }
274 } else if (fromItem instanceof ValuesList) { 304 } else if (fromItem instanceof ValuesList) {
275 - logger.debug("Perform a subquery, if you do not give us feedback"); 305 + logger.debug("Perform a subQuery, if you do not give us feedback");
276 } else if (fromItem instanceof LateralSubSelect) { 306 } else if (fromItem instanceof LateralSubSelect) {
277 LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; 307 LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
278 if (lateralSubSelect.getSubSelect() != null) { 308 if (lateralSubSelect.getSubSelect() != null) {
@@ -285,74 +315,175 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme @@ -285,74 +315,175 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme
285 } 315 }
286 316
287 /** 317 /**
  318 + * 处理 sub join
  319 + *
  320 + * @param subJoin subJoin
  321 + * @return Table subJoin 中的主表
  322 + */
  323 + private List<Table> processSubJoin(SubJoin subJoin) {
  324 + List<Table> mainTables = new ArrayList<>();
  325 + if (subJoin.getJoinList() != null) {
  326 + List<Table> list = processFromItem(subJoin.getLeft());
  327 + mainTables.addAll(list);
  328 + mainTables = processJoins(mainTables, subJoin.getJoinList());
  329 + }
  330 + return mainTables;
  331 + }
  332 +
  333 + /**
288 * 处理 joins 334 * 处理 joins
289 * 335 *
290 - * @param joins join 集合 336 + * @param mainTables 可以为 null
  337 + * @param joins join 集合
  338 + * @return List<Table> 右连接查询的 Table 列表
291 */ 339 */
292 - private void processJoins(List<Join> joins) { 340 + private List<Table> processJoins(List<Table> mainTables, List<Join> joins) {
  341 + // join 表达式中最终的主表
  342 + Table mainTable = null;
  343 + // 当前 join 的左表
  344 + Table leftTable = null;
  345 +
  346 + if (mainTables == null) {
  347 + mainTables = new ArrayList<>();
  348 + } else if (mainTables.size() == 1) {
  349 + mainTable = mainTables.get(0);
  350 + leftTable = mainTable;
  351 + }
  352 +
293 //对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名 353 //对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名
294 - Deque<Table> tables = new LinkedList<>(); 354 + Deque<List<Table>> onTableDeque = new LinkedList<>();
295 for (Join join : joins) { 355 for (Join join : joins) {
296 // 处理 on 表达式 356 // 处理 on 表达式
297 - FromItem fromItem = join.getRightItem();  
298 - if (fromItem instanceof Table) {  
299 - Table fromTable = (Table) fromItem; 357 + FromItem joinItem = join.getRightItem();
  358 +
  359 + // 获取当前 join 的表,subJoint 可以看作是一张表
  360 + List<Table> joinTables = null;
  361 + if (joinItem instanceof Table) {
  362 + joinTables = new ArrayList<>();
  363 + joinTables.add((Table) joinItem);
  364 + } else if (joinItem instanceof SubJoin) {
  365 + joinTables = processSubJoin((SubJoin) joinItem);
  366 + }
  367 +
  368 + if (joinTables != null) {
  369 +
  370 + // 如果是隐式内连接
  371 + if (join.isSimple()) {
  372 + mainTables.addAll(joinTables);
  373 + continue;
  374 + }
  375 +
  376 + // 当前表是否忽略
  377 + Table joinTable = joinTables.get(0);
  378 +
  379 + List<Table> onTables = null;
  380 + // 如果不要忽略,且是右连接,则记录下当前表
  381 + if (join.isRight()) {
  382 + mainTable = joinTable;
  383 + if (leftTable != null) {
  384 + onTables = Collections.singletonList(leftTable);
  385 + }
  386 + } else if (join.isLeft()) {
  387 + onTables = Collections.singletonList(joinTable);
  388 + } else if (join.isInner()) {
  389 + if (mainTable == null) {
  390 + onTables = Collections.singletonList(joinTable);
  391 + } else {
  392 + onTables = Arrays.asList(mainTable, joinTable);
  393 + }
  394 + mainTable = null;
  395 + }
  396 +
  397 + mainTables = new ArrayList<>();
  398 + if (mainTable != null) {
  399 + mainTables.add(mainTable);
  400 + }
  401 +
300 // 获取 join 尾缀的 on 表达式列表 402 // 获取 join 尾缀的 on 表达式列表
301 Collection<Expression> originOnExpressions = join.getOnExpressions(); 403 Collection<Expression> originOnExpressions = join.getOnExpressions();
302 // 正常 join on 表达式只有一个,立刻处理 404 // 正常 join on 表达式只有一个,立刻处理
303 - if (originOnExpressions.size() == 1) {  
304 - processJoin(join); 405 + if (originOnExpressions.size() == 1 && onTables != null) {
  406 + List<Expression> onExpressions = new LinkedList<>();
  407 + onExpressions.add(builderExpression(originOnExpressions.iterator().next(), onTables));
  408 + join.setOnExpressions(onExpressions);
  409 + leftTable = joinTable;
305 continue; 410 continue;
306 } 411 }
307 - tables.push(fromTable); 412 + // 表名压栈,忽略的表压入 null,以便后续不处理
  413 + onTableDeque.push(onTables);
308 // 尾缀多个 on 表达式的时候统一处理 414 // 尾缀多个 on 表达式的时候统一处理
309 if (originOnExpressions.size() > 1) { 415 if (originOnExpressions.size() > 1) {
310 Collection<Expression> onExpressions = new LinkedList<>(); 416 Collection<Expression> onExpressions = new LinkedList<>();
311 for (Expression originOnExpression : originOnExpressions) { 417 for (Expression originOnExpression : originOnExpressions) {
312 - Table currentTable = tables.poll();  
313 - onExpressions.add(builderExpression(originOnExpression, currentTable)); 418 + List<Table> currentTableList = onTableDeque.poll();
  419 + if (CollectionUtils.isEmpty(currentTableList)) {
  420 + onExpressions.add(originOnExpression);
  421 + } else {
  422 + onExpressions.add(builderExpression(originOnExpression, currentTableList));
  423 + }
314 } 424 }
315 join.setOnExpressions(onExpressions); 425 join.setOnExpressions(onExpressions);
316 } 426 }
  427 + leftTable = joinTable;
317 } else { 428 } else {
318 - // 处理右边连接的子表达式  
319 - processFromItem(fromItem); 429 + processOtherFromItem(joinItem);
  430 + leftTable = null;
320 } 431 }
321 } 432 }
  433 +
  434 + return mainTables;
322 } 435 }
323 436
  437 + // ========== 和 TenantLineInnerInterceptor 存在差异的逻辑:关键,实现权限条件的拼接 ==========
  438 +
324 /** 439 /**
325 - * 处理联接语句 440 + * 处理条件
  441 + *
  442 + * @param currentExpression 当前 where 条件
  443 + * @param table 单个表
326 */ 444 */
327 - protected void processJoin(Join join) {  
328 - if (join.getRightItem() instanceof Table) {  
329 - Table fromTable = (Table) join.getRightItem();  
330 - Expression originOnExpression = CollUtil.getFirst(join.getOnExpressions());  
331 - originOnExpression = builderExpression(originOnExpression, fromTable);  
332 - join.setOnExpressions(CollUtil.newArrayList(originOnExpression));  
333 - } 445 + protected Expression builderExpression(Expression currentExpression, Table table) {
  446 + return this.builderExpression(currentExpression, Collections.singletonList(table));
334 } 447 }
335 448
336 /** 449 /**
337 * 处理条件 450 * 处理条件
  451 + *
  452 + * @param currentExpression 当前 where 条件
  453 + * @param tables 多个表
338 */ 454 */
339 - protected Expression builderExpression(Expression currentExpression, Table table) {  
340 - // 获得 Table 对应的数据权限条件  
341 - Expression equalsTo = buildDataPermissionExpression(table);  
342 - if (equalsTo == null) { // 如果没条件,则返回 currentExpression 默认 455 + protected Expression builderExpression(Expression currentExpression, List<Table> tables) {
  456 + // 没有表需要处理直接返回
  457 + if (CollectionUtils.isEmpty(tables)) {
343 return currentExpression; 458 return currentExpression;
344 } 459 }
345 460
346 - // 表达式为空,则直接返回 equalsTo 461 + // 第一步,获得 Table 对应的数据权限条件
  462 + Expression dataPermissionExpression = null;
  463 + for (Table table : tables) {
  464 + // 构建每个表的权限 Expression 条件
  465 + Expression expression = buildDataPermissionExpression(table);
  466 + if (expression == null) {
  467 + continue;
  468 + }
  469 + // 合并到 dataPermissionExpression 中
  470 + dataPermissionExpression = dataPermissionExpression == null ? expression
  471 + : new AndExpression(dataPermissionExpression, expression);
  472 + }
  473 +
  474 + // 第二步,合并多个 Expression 条件
  475 + if (dataPermissionExpression == null) {
  476 + return currentExpression;
  477 + }
347 if (currentExpression == null) { 478 if (currentExpression == null) {
348 - return equalsTo; 479 + return dataPermissionExpression;
349 } 480 }
350 - // 如果表达式为 Or,则需要 (currentExpression) AND equalsTo 481 + // ① 如果表达式为 Or,则需要 (currentExpression) AND dataPermissionExpression
351 if (currentExpression instanceof OrExpression) { 482 if (currentExpression instanceof OrExpression) {
352 - return new AndExpression(new Parenthesis(currentExpression), equalsTo); 483 + return new AndExpression(new Parenthesis(currentExpression), dataPermissionExpression);
353 } 484 }
354 - // 如果表达式为 And,则直接返回 currentExpression AND equalsTo  
355 - return new AndExpression(currentExpression, equalsTo); 485 + // ② 如果表达式为 And,则直接返回 where AND dataPermissionExpression
  486 + return new AndExpression(currentExpression, dataPermissionExpression);
356 } 487 }
357 488
358 /** 489 /**
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionDatabaseInterceptorTest2.java
@@ -46,7 +46,7 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -46,7 +46,7 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
46 46
47 @Override 47 @Override
48 public Set<String> getTableNames() { 48 public Set<String> getTableNames() {
49 - return asSet("entity", "entity1", "entity2", "t1", "t2", // 支持 MyBatis Plus 的单元测试 49 + return asSet("entity", "entity1", "entity2", "entity3", "t1", "t2", "sys_dict_item", // 支持 MyBatis Plus 的单元测试
50 "t_user", "t_role"); // 满足自己的单元测试 50 "t_user", "t_role"); // 满足自己的单元测试
51 } 51 }
52 52
@@ -84,30 +84,30 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -84,30 +84,30 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
84 @Test 84 @Test
85 void delete() { 85 void delete() {
86 assertSql("delete from entity where id = ?", 86 assertSql("delete from entity where id = ?",
87 - "DELETE FROM entity WHERE id = ? AND tenant_id = 1"); 87 + "DELETE FROM entity WHERE id = ? AND entity.tenant_id = 1");
88 } 88 }
89 89
90 @Test 90 @Test
91 void update() { 91 void update() {
92 assertSql("update entity set name = ? where id = ?", 92 assertSql("update entity set name = ? where id = ?",
93 - "UPDATE entity SET name = ? WHERE id = ? AND tenant_id = 1"); 93 + "UPDATE entity SET name = ? WHERE id = ? AND entity.tenant_id = 1");
94 } 94 }
95 95
96 @Test 96 @Test
97 void selectSingle() { 97 void selectSingle() {
98 // 单表 98 // 单表
99 assertSql("select * from entity where id = ?", 99 assertSql("select * from entity where id = ?",
100 - "SELECT * FROM entity WHERE id = ? AND tenant_id = 1"); 100 + "SELECT * FROM entity WHERE id = ? AND entity.tenant_id = 1");
101 101
102 assertSql("select * from entity where id = ? or name = ?", 102 assertSql("select * from entity where id = ? or name = ?",
103 - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); 103 + "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
104 104
105 assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)", 105 assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)",
106 - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND tenant_id = 1"); 106 + "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1");
107 107
108 /* not */ 108 /* not */
109 assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)", 109 assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)",
110 - "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND tenant_id = 1"); 110 + "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND entity.tenant_id = 1");
111 } 111 }
112 112
113 @Test 113 @Test
@@ -167,10 +167,12 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -167,10 +167,12 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
167 assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)", 167 assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)",
168 "SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); 168 "SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
169 169
  170 +
170 /* <= */ 171 /* <= */
171 assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)", 172 assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)",
172 "SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); 173 "SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
173 174
  175 +
174 /* <> */ 176 /* <> */
175 assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)", 177 assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)",
176 "SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); 178 "SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1");
@@ -204,6 +206,14 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -204,6 +206,14 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
204 "SELECT * FROM entity e " + 206 "SELECT * FROM entity e " +
205 "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + 207 "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
206 "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); 208 "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");
  209 +
  210 + assertSql("SELECT * FROM entity e " +
  211 + "left join entity1 e1 on e1.id = e.id " +
  212 + "left join entity2 e2 on e1.id = e2.id",
  213 + "SELECT * FROM entity e " +
  214 + "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
  215 + "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
  216 + "WHERE e.tenant_id = 1");
207 } 217 }
208 218
209 @Test 219 @Test
@@ -212,17 +222,125 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -212,17 +222,125 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
212 assertSql("SELECT * FROM entity e " + 222 assertSql("SELECT * FROM entity e " +
213 "right join entity1 e1 on e1.id = e.id", 223 "right join entity1 e1 on e1.id = e.id",
214 "SELECT * FROM entity e " + 224 "SELECT * FROM entity e " +
215 - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
216 - "WHERE e.tenant_id = 1"); 225 + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
  226 + "WHERE e1.tenant_id = 1");
  227 +
  228 + assertSql("SELECT * FROM with_as_1 e " +
  229 + "right join entity1 e1 on e1.id = e.id",
  230 + "SELECT * FROM with_as_1 e " +
  231 + "RIGHT JOIN entity1 e1 ON e1.id = e.id " +
  232 + "WHERE e1.tenant_id = 1");
217 233
218 assertSql("SELECT * FROM entity e " + 234 assertSql("SELECT * FROM entity e " +
219 "right join entity1 e1 on e1.id = e.id " + 235 "right join entity1 e1 on e1.id = e.id " +
220 "WHERE e.id = ? OR e.name = ?", 236 "WHERE e.id = ? OR e.name = ?",
221 "SELECT * FROM entity e " + 237 "SELECT * FROM entity e " +
222 - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
223 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); 238 + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
  239 + "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
  240 +
  241 + assertSql("SELECT * FROM entity e " +
  242 + "right join entity1 e1 on e1.id = e.id " +
  243 + "right join entity2 e2 on e1.id = e2.id ",
  244 + "SELECT * FROM entity e " +
  245 + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
  246 + "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
  247 + "WHERE e2.tenant_id = 1");
  248 + }
  249 +
  250 + @Test
  251 + void selectMixJoin() {
  252 + assertSql("SELECT * FROM entity e " +
  253 + "right join entity1 e1 on e1.id = e.id " +
  254 + "left join entity2 e2 on e1.id = e2.id",
  255 + "SELECT * FROM entity e " +
  256 + "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " +
  257 + "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " +
  258 + "WHERE e1.tenant_id = 1");
  259 +
  260 + assertSql("SELECT * FROM entity e " +
  261 + "left join entity1 e1 on e1.id = e.id " +
  262 + "right join entity2 e2 on e1.id = e2.id",
  263 + "SELECT * FROM entity e " +
  264 + "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
  265 + "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " +
  266 + "WHERE e2.tenant_id = 1");
  267 +
  268 + assertSql("SELECT * FROM entity e " +
  269 + "left join entity1 e1 on e1.id = e.id " +
  270 + "inner join entity2 e2 on e1.id = e2.id",
  271 + "SELECT * FROM entity e " +
  272 + "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +
  273 + "INNER JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 AND e2.tenant_id = 1");
224 } 274 }
225 275
  276 +
  277 + @Test
  278 + void selectJoinSubSelect() {
  279 + assertSql("select * from (select * from entity) e1 " +
  280 + "left join entity2 e2 on e1.id = e2.id",
  281 + "SELECT * FROM (SELECT * FROM entity WHERE entity.tenant_id = 1) e1 " +
  282 + "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1");
  283 +
  284 + assertSql("select * from entity1 e1 " +
  285 + "left join (select * from entity2) e2 " +
  286 + "on e1.id = e2.id",
  287 + "SELECT * FROM entity1 e1 " +
  288 + "LEFT JOIN (SELECT * FROM entity2 WHERE entity2.tenant_id = 1) e2 " +
  289 + "ON e1.id = e2.id " +
  290 + "WHERE e1.tenant_id = 1");
  291 + }
  292 +
  293 + @Test
  294 + void selectSubJoin() {
  295 +
  296 + assertSql("select * FROM " +
  297 + "(entity1 e1 right JOIN entity2 e2 ON e1.id = e2.id)",
  298 + "SELECT * FROM " +
  299 + "(entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
  300 + "WHERE e2.tenant_id = 1");
  301 +
  302 + assertSql("select * FROM " +
  303 + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id)",
  304 + "SELECT * FROM " +
  305 + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
  306 + "WHERE e1.tenant_id = 1");
  307 +
  308 +
  309 + assertSql("select * FROM " +
  310 + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id) " +
  311 + "right join entity3 e3 on e1.id = e3.id",
  312 + "SELECT * FROM " +
  313 + "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
  314 + "RIGHT JOIN entity3 e3 ON e1.id = e3.id AND e1.tenant_id = 1 " +
  315 + "WHERE e3.tenant_id = 1");
  316 +
  317 +
  318 + assertSql("select * FROM entity e " +
  319 + "LEFT JOIN (entity1 e1 right join entity2 e2 ON e1.id = e2.id) " +
  320 + "on e.id = e2.id",
  321 + "SELECT * FROM entity e " +
  322 + "LEFT JOIN (entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " +
  323 + "ON e.id = e2.id AND e2.tenant_id = 1 " +
  324 + "WHERE e.tenant_id = 1");
  325 +
  326 + assertSql("select * FROM entity e " +
  327 + "LEFT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
  328 + "on e.id = e2.id",
  329 + "SELECT * FROM entity e " +
  330 + "LEFT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
  331 + "ON e.id = e2.id AND e1.tenant_id = 1 " +
  332 + "WHERE e.tenant_id = 1");
  333 +
  334 + assertSql("select * FROM entity e " +
  335 + "RIGHT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " +
  336 + "on e.id = e2.id",
  337 + "SELECT * FROM entity e " +
  338 + "RIGHT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " +
  339 + "ON e.id = e2.id AND e.tenant_id = 1 " +
  340 + "WHERE e1.tenant_id = 1");
  341 + }
  342 +
  343 +
226 @Test 344 @Test
227 void selectLeftJoinMultipleTrailingOn() { 345 void selectLeftJoinMultipleTrailingOn() {
228 // 多个 on 尾缀的 346 // 多个 on 尾缀的
@@ -256,51 +374,97 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -256,51 +374,97 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
256 "inner join entity1 e1 on e1.id = e.id " + 374 "inner join entity1 e1 on e1.id = e.id " +
257 "WHERE e.id = ? OR e.name = ?", 375 "WHERE e.id = ? OR e.name = ?",
258 "SELECT * FROM entity e " + 376 "SELECT * FROM entity e " +
259 - "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
260 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); 377 + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
  378 + "WHERE e.id = ? OR e.name = ?");
261 379
262 assertSql("SELECT * FROM entity e " + 380 assertSql("SELECT * FROM entity e " +
263 "inner join entity1 e1 on e1.id = e.id " + 381 "inner join entity1 e1 on e1.id = e.id " +
264 "WHERE (e.id = ? OR e.name = ?)", 382 "WHERE (e.id = ? OR e.name = ?)",
265 "SELECT * FROM entity e " + 383 "SELECT * FROM entity e " +
266 - "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
267 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); 384 + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " +
  385 + "WHERE (e.id = ? OR e.name = ?)");
  386 +
  387 + // 隐式内连接
  388 + assertSql("SELECT * FROM entity,entity1 " +
  389 + "WHERE entity.id = entity1.id",
  390 + "SELECT * FROM entity, entity1 " +
  391 + "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
  392 +
  393 + // 隐式内连接
  394 + assertSql("SELECT * FROM entity a, with_as_entity1 b " +
  395 + "WHERE a.id = b.id",
  396 + "SELECT * FROM entity a, with_as_entity1 b " +
  397 + "WHERE a.id = b.id AND a.tenant_id = 1");
  398 +
  399 + assertSql("SELECT * FROM with_as_entity a, with_as_entity1 b " +
  400 + "WHERE a.id = b.id",
  401 + "SELECT * FROM with_as_entity a, with_as_entity1 b " +
  402 + "WHERE a.id = b.id");
  403 +
  404 + // SubJoin with 隐式内连接
  405 + assertSql("SELECT * FROM (entity,entity1) " +
  406 + "WHERE entity.id = entity1.id",
  407 + "SELECT * FROM (entity, entity1) " +
  408 + "WHERE entity.id = entity1.id " +
  409 + "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
  410 +
  411 + assertSql("SELECT * FROM ((entity,entity1),entity2) " +
  412 + "WHERE entity.id = entity1.id and entity.id = entity2.id",
  413 + "SELECT * FROM ((entity, entity1), entity2) " +
  414 + "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
  415 + "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
  416 +
  417 + assertSql("SELECT * FROM (entity,(entity1,entity2)) " +
  418 + "WHERE entity.id = entity1.id and entity.id = entity2.id",
  419 + "SELECT * FROM (entity, (entity1, entity2)) " +
  420 + "WHERE entity.id = entity1.id AND entity.id = entity2.id " +
  421 + "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1");
  422 +
  423 + // 沙雕的括号写法
  424 + assertSql("SELECT * FROM (((entity,entity1))) " +
  425 + "WHERE entity.id = entity1.id",
  426 + "SELECT * FROM (((entity, entity1))) " +
  427 + "WHERE entity.id = entity1.id " +
  428 + "AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
268 429
269 - // 垃圾 inner join todo  
270 -// assertSql("SELECT * FROM entity,entity1 " +  
271 -// "WHERE entity.id = entity1.id",  
272 -// "SELECT * FROM entity e " +  
273 -// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
274 -// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1");  
275 } 430 }
276 431
  432 +
277 @Test 433 @Test
278 void selectWithAs() { 434 void selectWithAs() {
279 assertSql("with with_as_A as (select * from entity) select * from with_as_A", 435 assertSql("with with_as_A as (select * from entity) select * from with_as_A",
280 - "WITH with_as_A AS (SELECT * FROM entity WHERE tenant_id = 1) SELECT * FROM with_as_A"); 436 + "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A");
  437 + }
  438 +
  439 +
  440 + @Test
  441 + void selectIgnoreTable() {
  442 + assertSql(" SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)",
  443 + "SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id AND item.tenant_id = 1 WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)");
281 } 444 }
282 445
283 private void assertSql(String sql, String targetSql) { 446 private void assertSql(String sql, String targetSql) {
284 assertEquals(targetSql, interceptor.parserSingle(sql, null)); 447 assertEquals(targetSql, interceptor.parserSingle(sql, null));
285 } 448 }
286 449
  450 +
287 // ========== 额外的测试 ========== 451 // ========== 额外的测试 ==========
288 452
289 @Test 453 @Test
290 public void testSelectSingle() { 454 public void testSelectSingle() {
291 // 单表 455 // 单表
292 assertSql("select * from t_user where id = ?", 456 assertSql("select * from t_user where id = ?",
293 - "SELECT * FROM t_user WHERE id = ? AND tenant_id = 1 AND dept_id IN (10, 20)"); 457 + "SELECT * FROM t_user WHERE id = ? AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
294 458
295 assertSql("select * from t_user where id = ? or name = ?", 459 assertSql("select * from t_user where id = ? or name = ?",
296 - "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)"); 460 + "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
297 461
298 assertSql("SELECT * FROM t_user WHERE (id = ? OR name = ?)", 462 assertSql("SELECT * FROM t_user WHERE (id = ? OR name = ?)",
299 - "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)"); 463 + "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
300 464
301 /* not */ 465 /* not */
302 assertSql("SELECT * FROM t_user WHERE not (id = ? OR name = ?)", 466 assertSql("SELECT * FROM t_user WHERE not (id = ? OR name = ?)",
303 - "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND tenant_id = 1 AND dept_id IN (10, 20)"); 467 + "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)");
304 } 468 }
305 469
306 @Test 470 @Test
@@ -329,16 +493,16 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -329,16 +493,16 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
329 "right join t_role e1 on e1.id = e.id " + 493 "right join t_role e1 on e1.id = e.id " +
330 "WHERE e.id = ? OR e.name = ?", 494 "WHERE e.id = ? OR e.name = ?",
331 "SELECT * FROM t_user e " + 495 "SELECT * FROM t_user e " +
332 - "RIGHT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
333 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); 496 + "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " +
  497 + "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
334 498
335 // 条件 e.id = ? OR e.name = ? 带括号 499 // 条件 e.id = ? OR e.name = ? 带括号
336 assertSql("SELECT * FROM t_user e " + 500 assertSql("SELECT * FROM t_user e " +
337 "right join t_role e1 on e1.id = e.id " + 501 "right join t_role e1 on e1.id = e.id " +
338 "WHERE (e.id = ? OR e.name = ?)", 502 "WHERE (e.id = ? OR e.name = ?)",
339 "SELECT * FROM t_user e " + 503 "SELECT * FROM t_user e " +
340 - "RIGHT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
341 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); 504 + "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " +
  505 + "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1");
342 } 506 }
343 507
344 @Test 508 @Test
@@ -348,23 +512,22 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest @@ -348,23 +512,22 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest
348 "inner join entity1 e1 on e1.id = e.id " + 512 "inner join entity1 e1 on e1.id = e.id " +
349 "WHERE e.id = ? OR e.name = ?", 513 "WHERE e.id = ? OR e.name = ?",
350 "SELECT * FROM t_user e " + 514 "SELECT * FROM t_user e " +
351 - "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
352 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); 515 + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " +
  516 + "WHERE e.id = ? OR e.name = ?");
353 517
354 // 条件 e.id = ? OR e.name = ? 带括号 518 // 条件 e.id = ? OR e.name = ? 带括号
355 assertSql("SELECT * FROM t_user e " + 519 assertSql("SELECT * FROM t_user e " +
356 - "inner join t_role e1 on e1.id = e.id " + 520 + "inner join entity1 e1 on e1.id = e.id " +
357 "WHERE (e.id = ? OR e.name = ?)", 521 "WHERE (e.id = ? OR e.name = ?)",
358 "SELECT * FROM t_user e " + 522 "SELECT * FROM t_user e " +
359 - "INNER JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
360 - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)");  
361 -  
362 - // 垃圾 inner join todo  
363 -// assertSql("SELECT * FROM entity,entity1 " +  
364 -// "WHERE entity.id = entity1.id",  
365 -// "SELECT * FROM entity e " +  
366 -// "INNER JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " +  
367 -// "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); 523 + "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " +
  524 + "WHERE (e.id = ? OR e.name = ?)");
  525 +
  526 + // 没有 On 的 inner join
  527 + assertSql("SELECT * FROM entity,entity1 " +
  528 + "WHERE entity.id = entity1.id",
  529 + "SELECT * FROM entity, entity1 " +
  530 + "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
368 } 531 }
369 532
370 } 533 }
yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtils.java
@@ -27,7 +27,7 @@ public class DictFrameworkUtils { @@ -27,7 +27,7 @@ public class DictFrameworkUtils {
27 /** 27 /**
28 * 针对 {@link #getDictDataLabel(String, String)} 的缓存 28 * 针对 {@link #getDictDataLabel(String, String)} 的缓存
29 */ 29 */
30 - private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> getDictDataCache = CacheUtils.buildAsyncReloadingCache( 30 + private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
31 Duration.ofMinutes(1L), // 过期时间 1 分钟 31 Duration.ofMinutes(1L), // 过期时间 1 分钟
32 new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() { 32 new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() {
33 33
@@ -41,7 +41,7 @@ public class DictFrameworkUtils { @@ -41,7 +41,7 @@ public class DictFrameworkUtils {
41 /** 41 /**
42 * 针对 {@link #parseDictDataValue(String, String)} 的缓存 42 * 针对 {@link #parseDictDataValue(String, String)} 的缓存
43 */ 43 */
44 - private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> parseDictDataCache = CacheUtils.buildAsyncReloadingCache( 44 + private static final LoadingCache<KeyValue<String, String>, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache(
45 Duration.ofMinutes(1L), // 过期时间 1 分钟 45 Duration.ofMinutes(1L), // 过期时间 1 分钟
46 new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() { 46 new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() {
47 47
@@ -59,12 +59,12 @@ public class DictFrameworkUtils { @@ -59,12 +59,12 @@ public class DictFrameworkUtils {
59 59
60 @SneakyThrows 60 @SneakyThrows
61 public static String getDictDataLabel(String dictType, String value) { 61 public static String getDictDataLabel(String dictType, String value) {
62 - return getDictDataCache.get(new KeyValue<>(dictType, value)).getLabel(); 62 + return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel();
63 } 63 }
64 64
65 @SneakyThrows 65 @SneakyThrows
66 public static String parseDictDataValue(String dictType, String label) { 66 public static String parseDictDataValue(String dictType, String label) {
67 - return parseDictDataCache.get(new KeyValue<>(dictType, label)).getValue(); 67 + return PARSE_DICT_DATA_CACHE.get(new KeyValue<>(dictType, label)).getValue();
68 } 68 }
69 69
70 } 70 }
yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml
@@ -52,12 +52,18 @@ @@ -52,12 +52,18 @@
52 <dependency> 52 <dependency>
53 <groupId>com.alipay.sdk</groupId> 53 <groupId>com.alipay.sdk</groupId>
54 <artifactId>alipay-sdk-java</artifactId> 54 <artifactId>alipay-sdk-java</artifactId>
55 - <version>4.17.9.ALL</version> 55 + <version>4.31.72.ALL</version>
  56 + <exclusions>
  57 + <exclusion>
  58 + <groupId>org.bouncycastle</groupId>
  59 + <artifactId>bcprov-jdk15on</artifactId>
  60 + </exclusion>
  61 + </exclusions>
56 </dependency> 62 </dependency>
57 <dependency> 63 <dependency>
58 <groupId>com.github.binarywang</groupId> 64 <groupId>com.github.binarywang</groupId>
59 <artifactId>weixin-java-pay</artifactId> 65 <artifactId>weixin-java-pay</artifactId>
60 - <version>4.1.9.B</version> 66 + <version>4.3.8.B</version>
61 </dependency> 67 </dependency>
62 <!-- TODO 芋艿:清理 --> 68 <!-- TODO 芋艿:清理 -->
63 69
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
1 package cn.iocoder.yudao.framework.pay.core.client.impl; 1 package cn.iocoder.yudao.framework.pay.core.client.impl;
2 2
3 -import cn.hutool.extra.validation.ValidationUtil;  
4 import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; 3 import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping;
5 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 4 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
6 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 5 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
@@ -10,6 +9,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO; @@ -10,6 +9,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedReqDTO;
10 import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; 9 import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO;
11 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
12 11
  12 +import javax.validation.Validation;
  13 +
13 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 14 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
14 15
15 /** 16 /**
@@ -79,7 +80,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen @@ -79,7 +80,7 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
79 80
80 @Override 81 @Override
81 public final PayCommonResult<?> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { 82 public final PayCommonResult<?> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
82 - ValidationUtil.validate(reqDTO); 83 + Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
83 // 执行短信发送 84 // 执行短信发送
84 PayCommonResult<?> result; 85 PayCommonResult<?> result;
85 try { 86 try {
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java
@@ -53,9 +53,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest { @@ -53,9 +53,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
53 "lrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZ" + 53 "lrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZ" +
54 "ikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); 54 "ikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB");
55 55
56 - // TODO @tina:= 前后要有空格哈  
57 @InjectMocks 56 @InjectMocks
58 - AlipayQrPayClient client=new AlipayQrPayClient(10L,config); 57 + AlipayQrPayClient client = new AlipayQrPayClient(10L,config);
59 58
60 @Mock 59 @Mock
61 private DefaultAlipayClient defaultAlipayClient; 60 private DefaultAlipayClient defaultAlipayClient;
yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml
@@ -35,12 +35,12 @@ @@ -35,12 +35,12 @@
35 <dependency> 35 <dependency>
36 <groupId>com.github.binarywang</groupId> 36 <groupId>com.github.binarywang</groupId>
37 <artifactId>wx-java-mp-spring-boot-starter</artifactId> 37 <artifactId>wx-java-mp-spring-boot-starter</artifactId>
38 - <version>4.3.4.B</version> 38 + <version>4.3.8.B</version>
39 </dependency> 39 </dependency>
40 <dependency> 40 <dependency>
41 <groupId>com.github.binarywang</groupId> 41 <groupId>com.github.binarywang</groupId>
42 <artifactId>wx-java-miniapp-spring-boot-starter</artifactId> 42 <artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
43 - <version>4.3.4.B</version> 43 + <version>4.3.8.B</version>
44 </dependency> 44 </dependency>
45 <!-- TODO 芋艿:清理 --> 45 <!-- TODO 芋艿:清理 -->
46 </dependencies> 46 </dependencies>
yudao-framework/yudao-spring-boot-starter-captcha/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao-framework</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <artifactId>yudao-spring-boot-starter-captcha</artifactId>
  12 + <packaging>jar</packaging>
  13 +
  14 + <name>${project.artifactId}</name>
  15 + <description>验证码拓展
  16 + 1. 基于 aj-captcha 实现滑块验证码,文档:https://ajcaptcha.beliefteam.cn/captcha-doc/
  17 + </description>
  18 +
  19 + <dependencies>
  20 + <!-- Spring 核心 -->
  21 + <dependency>
  22 + <groupId>org.springframework.boot</groupId>
  23 + <artifactId>spring-boot-starter</artifactId>
  24 + </dependency>
  25 +
  26 + <!-- DB 相关 -->
  27 + <dependency>
  28 + <groupId>cn.iocoder.boot</groupId>
  29 + <artifactId>yudao-spring-boot-starter-redis</artifactId>
  30 + </dependency>
  31 +
  32 + <!-- 验证码相关 -->
  33 + <dependency>
  34 + <groupId>com.anji-plus</groupId>
  35 + <artifactId>spring-boot-starter-captcha</artifactId>
  36 + </dependency>
  37 + </dependencies>
  38 +
  39 +</project>
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.captcha.config;
  2 +
  3 +import cn.hutool.core.util.ClassUtil;
  4 +import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants;
  5 +import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
  6 +import com.anji.captcha.service.CaptchaCacheService;
  7 +import org.springframework.context.annotation.Bean;
  8 +import org.springframework.context.annotation.Configuration;
  9 +import org.springframework.data.redis.core.StringRedisTemplate;
  10 +
  11 +@Configuration
  12 +public class YudaoCaptchaConfiguration {
  13 +
  14 + static {
  15 + // 手动加载 Lock4jRedisKeyConstants 类,因为它不会被使用到
  16 + // 如果不加载,会导致 Redis 监控,看到它的 Redis Key 枚举
  17 + ClassUtil.loadClass(CaptchaRedisKeyConstants.class.getName());
  18 + }
  19 +
  20 + @Bean
  21 + public CaptchaCacheService captchaCacheService(StringRedisTemplate stringRedisTemplate) {
  22 + return new RedisCaptchaServiceImpl(stringRedisTemplate);
  23 + }
  24 +
  25 +}
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/core/enums/CaptchaRedisKeyConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.captcha.core.enums;
  2 +
  3 +import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
  4 +import com.anji.captcha.model.vo.PointVO;
  5 +import org.redisson.api.RLock;
  6 +
  7 +import java.time.Duration;
  8 +import java.util.Map;
  9 +
  10 +import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH;
  11 +import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
  12 +
  13 +/**
  14 + * 验证码 Redis Key 枚举类
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +public interface CaptchaRedisKeyConstants {
  19 +
  20 + RedisKeyDefine AJ_CAPTCHA_REQ_LIMIT = new RedisKeyDefine("验证码的请求限流",
  21 + "AJ.CAPTCHA.REQ.LIMIT-%s-%s",
  22 + STRING, Integer.class, Duration.ofSeconds(60)); // 例如说:验证失败 5 次,get 接口锁定
  23 +
  24 + RedisKeyDefine AJ_CAPTCHA_RUNNING = new RedisKeyDefine("验证码的坐标",
  25 + "RUNNING:CAPTCHA:%s", // AbstractCaptchaService.REDIS_CAPTCHA_KEY
  26 + STRING, PointVO.class, Duration.ofSeconds(120)); // {"secretKey":"PP1w2Frr2KEejD2m","x":162,"y":5}
  27 +
  28 +}
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/core/service/RedisCaptchaServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.captcha.core.service;
  2 +
  3 +import com.anji.captcha.service.CaptchaCacheService;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.NoArgsConstructor;
  6 +import lombok.RequiredArgsConstructor;
  7 +import org.springframework.data.redis.core.StringRedisTemplate;
  8 +
  9 +import javax.annotation.Resource;
  10 +import java.util.concurrent.TimeUnit;
  11 +
  12 +/**
  13 + * 基于 Redis 实现验证码的存储
  14 + *
  15 + * @author 星语
  16 + */
  17 +@NoArgsConstructor // 保证 aj-captcha 的 SPI 创建
  18 +@AllArgsConstructor
  19 +public class RedisCaptchaServiceImpl implements CaptchaCacheService {
  20 +
  21 + @Resource // 保证 aj-captcha 的 SPI 创建时的注入
  22 + private StringRedisTemplate stringRedisTemplate;
  23 +
  24 + @Override
  25 + public String type() {
  26 + return "redis";
  27 + }
  28 +
  29 + @Override
  30 + public void set(String key, String value, long expiresInSeconds) {
  31 + stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
  32 + }
  33 +
  34 + @Override
  35 + public boolean exists(String key) {
  36 + return Boolean.TRUE.equals(stringRedisTemplate.hasKey(key));
  37 + }
  38 +
  39 + @Override
  40 + public void delete(String key) {
  41 + stringRedisTemplate.delete(key);
  42 + }
  43 +
  44 + @Override
  45 + public String get(String key) {
  46 + return stringRedisTemplate.opsForValue().get(key);
  47 + }
  48 +
  49 + @Override
  50 + public Long increment(String key, long val) {
  51 + return stringRedisTemplate.opsForValue().increment(key,val);
  52 + }
  53 +
  54 +}
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/package-info.java 0 → 100644
  1 +/**
  2 + * 验证码拓展
  3 + * 1. 基于 aj-captcha 实现滑块验证码,文档:https://ajcaptcha.beliefteam.cn/captcha-doc/
  4 + *
  5 + * @author 星语
  6 + */
  7 +package cn.iocoder.yudao.framework.captcha;
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService 0 → 100644
  1 +cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories 0 → 100644
  1 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2 + cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg1.png 0 → 100644

17.4 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg2.png 0 → 100644

28.1 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg3.png 0 → 100644

25.2 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg4.png 0 → 100644

27.2 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg5.png 0 → 100644

23.5 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg6.png 0 → 100644

18.7 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg7.png 0 → 100644

20.9 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg8.png 0 → 100644

29.6 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/original/bg9.png 0 → 100644

26.3 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/1.png 0 → 100644

2.11 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/10.png 0 → 100644

1.62 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/11.png 0 → 100644

1.62 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/12.png 0 → 100644

1.62 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/13.png 0 → 100644

1.83 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/14.png 0 → 100644

1.83 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/15.png 0 → 100644

1.83 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/16.png 0 → 100644

1.79 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/17.png 0 → 100644

1.8 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/18.png 0 → 100644

1.79 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/19.png 0 → 100644

1.79 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/8.png 0 → 100644

1.62 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/11/9.png 0 → 100644

1.62 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/2.png 0 → 100644

2.24 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/3.png 0 → 100644

2.19 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/jigsaw/slidingBlock/4.png 0 → 100644

2.2 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg1.png 0 → 100644

23.5 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg10.png 0 → 100644

27.2 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg2.png 0 → 100644

27.7 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg3.png 0 → 100644

22.9 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg4.png 0 → 100644

24.8 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg5.png 0 → 100644

16 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg6.png 0 → 100644

23.1 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg7.png 0 → 100644

25.5 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg8.png 0 → 100644

26.6 KB

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/images/pic-click/bg9.png 0 → 100644

29.2 KB

yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/JsonLongSetTypeHandler.java
@@ -16,11 +16,11 @@ import java.util.Set; @@ -16,11 +16,11 @@ import java.util.Set;
16 */ 16 */
17 public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler<Object> { 17 public class JsonLongSetTypeHandler extends AbstractJsonTypeHandler<Object> {
18 18
19 - private static final TypeReference<Set<Long>> typeReference = new TypeReference<Set<Long>>(){}; 19 + private static final TypeReference<Set<Long>> TYPE_REFERENCE = new TypeReference<Set<Long>>(){};
20 20
21 @Override 21 @Override
22 protected Object parse(String json) { 22 protected Object parse(String json) {
23 - return JsonUtils.parseObject(json, typeReference); 23 + return JsonUtils.parseObject(json, TYPE_REFERENCE);
24 } 24 }
25 25
26 @Override 26 @Override
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil; @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageParam; 4 import cn.iocoder.yudao.framework.common.pojo.PageParam;
5 import cn.iocoder.yudao.framework.common.pojo.SortingField; 5 import cn.iocoder.yudao.framework.common.pojo.SortingField;
6 import com.baomidou.mybatisplus.core.metadata.OrderItem; 6 import com.baomidou.mybatisplus.core.metadata.OrderItem;
  7 +import com.baomidou.mybatisplus.core.toolkit.StringPool;
7 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 8 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
8 import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; 9 import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
9 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 10 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -78,7 +79,10 @@ public class MyBatisUtils { @@ -78,7 +79,10 @@ public class MyBatisUtils {
78 * @return Column 对象 79 * @return Column 对象
79 */ 80 */
80 public static Column buildColumn(String tableName, Alias tableAlias, String column) { 81 public static Column buildColumn(String tableName, Alias tableAlias, String column) {
81 - return new Column(tableAlias != null ? tableAlias.getName() + "." + column : column); 82 + if (tableAlias != null) {
  83 + tableName = tableAlias.getName();
  84 + }
  85 + return new Column(tableName + StringPool.DOT + column);
82 } 86 }
83 87
84 } 88 }
yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/core/RedisKeyRegistry.java
@@ -11,18 +11,18 @@ public class RedisKeyRegistry { @@ -11,18 +11,18 @@ public class RedisKeyRegistry {
11 /** 11 /**
12 * Redis RedisKeyDefine 数组 12 * Redis RedisKeyDefine 数组
13 */ 13 */
14 - private static final List<RedisKeyDefine> defines = new ArrayList<>(); 14 + private static final List<RedisKeyDefine> DEFINES = new ArrayList<>();
15 15
16 public static void add(RedisKeyDefine define) { 16 public static void add(RedisKeyDefine define) {
17 - defines.add(define); 17 + DEFINES.add(define);
18 } 18 }
19 19
20 public static List<RedisKeyDefine> list() { 20 public static List<RedisKeyDefine> list() {
21 - return defines; 21 + return DEFINES;
22 } 22 }
23 23
24 public static int size() { 24 public static int size() {
25 - return defines.size(); 25 + return DEFINES.size();
26 } 26 }
27 27
28 } 28 }
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
@@ -81,7 +81,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -81,7 +81,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
81 81
82 /** 82 /**
83 * 配置 URL 的安全配置 83 * 配置 URL 的安全配置
84 - * 84 + * <p>
85 * anyRequest | 匹配所有请求路径 85 * anyRequest | 匹配所有请求路径
86 * access | SpringEl表达式结果为true时可以访问 86 * access | SpringEl表达式结果为true时可以访问
87 * anonymous | 匿名可以访问 87 * anonymous | 匿名可以访问
@@ -109,8 +109,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -109,8 +109,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
109 .headers().frameOptions().disable().and() 109 .headers().frameOptions().disable().and()
110 // 一堆自定义的 Spring Security 处理器 110 // 一堆自定义的 Spring Security 处理器
111 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) 111 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
112 - .accessDeniedHandler(accessDeniedHandler);  
113 - // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高 112 + .accessDeniedHandler(accessDeniedHandler);
  113 + // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高
114 114
115 // 获得 @PermitAll 带来的 URL 列表,免登录 115 // 获得 @PermitAll 带来的 URL 列表,免登录
116 Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations(); 116 Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations();
@@ -118,23 +118,25 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -118,23 +118,25 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
118 httpSecurity 118 httpSecurity
119 // ①:全局共享规则 119 // ①:全局共享规则
120 .authorizeRequests() 120 .authorizeRequests()
121 - // 1.1 静态资源,可匿名访问  
122 - .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()  
123 - // 1.2 设置 @PermitAll 无需认证  
124 - .antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()  
125 - .antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()  
126 - .antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()  
127 - .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()  
128 - // 1.3 基于 yudao.security.permit-all-urls 无需认证  
129 - .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()  
130 - // 1.4 设置 App API 无需认证  
131 - .antMatchers(buildAppApi("/**")).permitAll() 121 + // 1.1 静态资源,可匿名访问
  122 + .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
  123 + // 1.2 设置 @PermitAll 无需认证
  124 + .antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
  125 + .antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
  126 + .antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
  127 + .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
  128 + // 1.3 基于 yudao.security.permit-all-urls 无需认证
  129 + .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
  130 + // 1.4 设置 App API 无需认证
  131 + .antMatchers(buildAppApi("/**")).permitAll()
  132 + // 1.5 验证码captcha 允许匿名访问
  133 + .antMatchers("/captcha/get", "/captcha/check").permitAll()
132 // ②:每个项目的自定义规则 134 // ②:每个项目的自定义规则
133 .and().authorizeRequests(registry -> // 下面,循环设置自定义规则 135 .and().authorizeRequests(registry -> // 下面,循环设置自定义规则
134 authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry))) 136 authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry)))
135 // ③:兜底规则,必须认证 137 // ③:兜底规则,必须认证
136 .authorizeRequests() 138 .authorizeRequests()
137 - .anyRequest().authenticated() 139 + .anyRequest().authenticated()
138 ; 140 ;
139 141
140 // 添加 Token Filter 142 // 添加 Token Filter
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java
@@ -17,19 +17,19 @@ public class TransmittableThreadLocalSecurityContextHolderStrategy implements Se @@ -17,19 +17,19 @@ public class TransmittableThreadLocalSecurityContextHolderStrategy implements Se
17 /** 17 /**
18 * 使用 TransmittableThreadLocal 作为上下文 18 * 使用 TransmittableThreadLocal 作为上下文
19 */ 19 */
20 - private static final ThreadLocal<SecurityContext> contextHolder = new TransmittableThreadLocal<>(); 20 + private static final ThreadLocal<SecurityContext> CONTEXT_HOLDER = new TransmittableThreadLocal<>();
21 21
22 @Override 22 @Override
23 public void clearContext() { 23 public void clearContext() {
24 - contextHolder.remove(); 24 + CONTEXT_HOLDER.remove();
25 } 25 }
26 26
27 @Override 27 @Override
28 public SecurityContext getContext() { 28 public SecurityContext getContext() {
29 - SecurityContext ctx = contextHolder.get(); 29 + SecurityContext ctx = CONTEXT_HOLDER.get();
30 if (ctx == null) { 30 if (ctx == null) {
31 ctx = createEmptyContext(); 31 ctx = createEmptyContext();
32 - contextHolder.set(ctx); 32 + CONTEXT_HOLDER.set(ctx);
33 } 33 }
34 return ctx; 34 return ctx;
35 } 35 }
@@ -37,7 +37,7 @@ public class TransmittableThreadLocalSecurityContextHolderStrategy implements Se @@ -37,7 +37,7 @@ public class TransmittableThreadLocalSecurityContextHolderStrategy implements Se
37 @Override 37 @Override
38 public void setContext(SecurityContext context) { 38 public void setContext(SecurityContext context) {
39 Assert.notNull(context, "Only non-null SecurityContext instances are permitted"); 39 Assert.notNull(context, "Only non-null SecurityContext instances are permitted");
40 - contextHolder.set(context); 40 + CONTEXT_HOLDER.set(context);
41 } 41 }
42 42
43 @Override 43 @Override
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/message/BpmMessageServiceImpl.java
@@ -57,7 +57,7 @@ public class BpmMessageServiceImpl implements BpmMessageService { @@ -57,7 +57,7 @@ public class BpmMessageServiceImpl implements BpmMessageService {
57 templateParams.put("taskName", reqDTO.getTaskName()); 57 templateParams.put("taskName", reqDTO.getTaskName());
58 templateParams.put("startUserNickname", reqDTO.getStartUserNickname()); 58 templateParams.put("startUserNickname", reqDTO.getStartUserNickname());
59 templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); 59 templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId()));
60 - smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), 60 + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getAssigneeUserId(),
61 BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams)); 61 BpmMessageEnum.TASK_ASSIGNED.getSmsTemplateCode(), templateParams));
62 } 62 }
63 63
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java
@@ -154,12 +154,12 @@ public class CodegenServiceImpl implements CodegenService { @@ -154,12 +154,12 @@ public class CodegenServiceImpl implements CodegenService {
154 // 构建 CodegenColumnDO 数组,只同步新增的字段 154 // 构建 CodegenColumnDO 数组,只同步新增的字段
155 List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId); 155 List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId);
156 Set<String> codegenColumnNames = CollectionUtils.convertSet(codegenColumns, CodegenColumnDO::getColumnName); 156 Set<String> codegenColumnNames = CollectionUtils.convertSet(codegenColumns, CodegenColumnDO::getColumnName);
157 - // 移除已经存在的字段  
158 - tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName()));  
159 // 计算需要删除的字段 157 // 计算需要删除的字段
160 Set<String> tableFieldNames = CollectionUtils.convertSet(tableFields, TableField::getName); 158 Set<String> tableFieldNames = CollectionUtils.convertSet(tableFields, TableField::getName);
161 Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !tableFieldNames.contains(column.getColumnName())) 159 Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !tableFieldNames.contains(column.getColumnName()))
162 .map(CodegenColumnDO::getId).collect(Collectors.toSet()); 160 .map(CodegenColumnDO::getId).collect(Collectors.toSet());
  161 + // 移除已经存在的字段
  162 + tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName()));
163 if (CollUtil.isEmpty(tableFields) && CollUtil.isEmpty(deleteColumnIds)) { 163 if (CollUtil.isEmpty(tableFields) && CollUtil.isEmpty(deleteColumnIds)) {
164 throw exception(CODEGEN_SYNC_NONE_CHANGE); 164 throw exception(CODEGEN_SYNC_NONE_CHANGE);
165 } 165 }
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
@@ -31,7 +31,7 @@ public class CodegenBuilder { @@ -31,7 +31,7 @@ public class CodegenBuilder {
31 * 字段名与 {@link CodegenColumnListConditionEnum} 的默认映射 31 * 字段名与 {@link CodegenColumnListConditionEnum} 的默认映射
32 * 注意,字段的匹配以后缀的方式 32 * 注意,字段的匹配以后缀的方式
33 */ 33 */
34 - private static final Map<String, CodegenColumnListConditionEnum> columnListOperationConditionMappings = 34 + private static final Map<String, CodegenColumnListConditionEnum> COLUMN_LIST_OPERATION_CONDITION_MAPPINGS =
35 MapUtil.<String, CodegenColumnListConditionEnum>builder() 35 MapUtil.<String, CodegenColumnListConditionEnum>builder()
36 .put("name", CodegenColumnListConditionEnum.LIKE) 36 .put("name", CodegenColumnListConditionEnum.LIKE)
37 .put("time", CodegenColumnListConditionEnum.BETWEEN) 37 .put("time", CodegenColumnListConditionEnum.BETWEEN)
@@ -42,7 +42,7 @@ public class CodegenBuilder { @@ -42,7 +42,7 @@ public class CodegenBuilder {
42 * 字段名与 {@link CodegenColumnHtmlTypeEnum} 的默认映射 42 * 字段名与 {@link CodegenColumnHtmlTypeEnum} 的默认映射
43 * 注意,字段的匹配以后缀的方式 43 * 注意,字段的匹配以后缀的方式
44 */ 44 */
45 - private static final Map<String, CodegenColumnHtmlTypeEnum> columnHtmlTypeMappings = 45 + private static final Map<String, CodegenColumnHtmlTypeEnum> COLUMN_HTML_TYPE_MAPPINGS =
46 MapUtil.<String, CodegenColumnHtmlTypeEnum>builder() 46 MapUtil.<String, CodegenColumnHtmlTypeEnum>builder()
47 .put("status", CodegenColumnHtmlTypeEnum.RADIO) 47 .put("status", CodegenColumnHtmlTypeEnum.RADIO)
48 .put("sex", CodegenColumnHtmlTypeEnum.RADIO) 48 .put("sex", CodegenColumnHtmlTypeEnum.RADIO)
@@ -143,7 +143,7 @@ public class CodegenBuilder { @@ -143,7 +143,7 @@ public class CodegenBuilder {
143 column.setListOperation(!LIST_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField()) 143 column.setListOperation(!LIST_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField())
144 && !column.getPrimaryKey()); // 对于主键,列表过滤不需要传递 144 && !column.getPrimaryKey()); // 对于主键,列表过滤不需要传递
145 // 处理 listOperationCondition 字段 145 // 处理 listOperationCondition 字段
146 - columnListOperationConditionMappings.entrySet().stream() 146 + COLUMN_LIST_OPERATION_CONDITION_MAPPINGS.entrySet().stream()
147 .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) 147 .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey()))
148 .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition())); 148 .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition()));
149 if (column.getListOperationCondition() == null) { 149 if (column.getListOperationCondition() == null) {
@@ -155,7 +155,7 @@ public class CodegenBuilder { @@ -155,7 +155,7 @@ public class CodegenBuilder {
155 155
156 private void processColumnUI(CodegenColumnDO column) { 156 private void processColumnUI(CodegenColumnDO column) {
157 // 基于后缀进行匹配 157 // 基于后缀进行匹配
158 - columnHtmlTypeMappings.entrySet().stream() 158 + COLUMN_HTML_TYPE_MAPPINGS.entrySet().stream()
159 .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) 159 .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey()))
160 .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType())); 160 .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType()));
161 // 如果是 Boolean 类型时,设置为 radio 类型. 161 // 如果是 Boolean 类型时,设置为 radio 类型.
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm
@@ -96,7 +96,7 @@ @@ -96,7 +96,7 @@
96 @pagination="getList"/> 96 @pagination="getList"/>
97 97
98 <!-- 对话框(添加 / 修改) --> 98 <!-- 对话框(添加 / 修改) -->
99 - <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> 99 + <el-dialog :title="title" :visible.sync="open" width="500px" v-dialogDrag append-to-body>
100 <el-form ref="form" :model="form" :rules="rules" label-width="80px"> 100 <el-form ref="form" :model="form" :rules="rules" label-width="80px">
101 #foreach($column in $columns) 101 #foreach($column in $columns)
102 #if ($column.createOperation || $column.updateOperation) 102 #if ($column.createOperation || $column.updateOperation)
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm
@@ -5,31 +5,31 @@ const request = useAxios() @@ -5,31 +5,31 @@ const request = useAxios()
5 5
6 #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") 6 #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
7 // 查询${table.classComment}列表 7 // 查询${table.classComment}列表
8 -export const getPostPageApi = async (params: ${simpleClassName}PageReqVO) => { 8 +export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => {
9 return await request.get({ url: '${baseURL}/page', params }) 9 return await request.get({ url: '${baseURL}/page', params })
10 } 10 }
11 11
12 // 查询${table.classComment}详情 12 // 查询${table.classComment}详情
13 -export const getPostApi = async (id: number) => { 13 +export const get${simpleClassName}Api = async (id: number) => {
14 return await request.get({ url: '${baseURL}/get?id=' + id }) 14 return await request.get({ url: '${baseURL}/get?id=' + id })
15 } 15 }
16 16
17 // 新增${table.classComment} 17 // 新增${table.classComment}
18 -export const createPostApi = async (data: ${simpleClassName}VO) => { 18 +export const create${simpleClassName}Api = async (data: ${simpleClassName}VO) => {
19 return await request.post({ url: '${baseURL}/create', data }) 19 return await request.post({ url: '${baseURL}/create', data })
20 } 20 }
21 21
22 // 修改${table.classComment} 22 // 修改${table.classComment}
23 -export const updatePostApi = async (data: ${simpleClassName}VO) => { 23 +export const update${simpleClassName}Api = async (data: ${simpleClassName}VO) => {
24 return await request.put({ url: '${baseURL}/update', data }) 24 return await request.put({ url: '${baseURL}/update', data })
25 } 25 }
26 26
27 // 删除${table.classComment} 27 // 删除${table.classComment}
28 -export const deletePostApi = async (id: number) => { 28 +export const delete${simpleClassName}Api = async (id: number) => {
29 return await request.delete({ url: '${baseURL}/delete?id=' + id }) 29 return await request.delete({ url: '${baseURL}/delete?id=' + id })
30 } 30 }
31 31
32 // 导出${table.classComment} Excel 32 // 导出${table.classComment} Excel
33 -export const exportPostApi = async (params: ${simpleClassName}ExcelReqVO) => { 33 +export const export${simpleClassName}Api = async (params: ${simpleClassName}ExcelReqVO) => {
34 return await request.download({ url: '${baseURL}/export-excel', params }) 34 return await request.download({ url: '${baseURL}/export-excel', params })
35 } 35 }
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
@@ -6,9 +6,9 @@ @@ -6,9 +6,9 @@
6 import { useTable } from '@/hooks/web/useTable' 6 import { useTable } from '@/hooks/web/useTable'
7 import { useI18n } from '@/hooks/web/useI18n' 7 import { useI18n } from '@/hooks/web/useI18n'
8 import { FormExpose } from '@/components/Form' 8 import { FormExpose } from '@/components/Form'
9 - import type { ${simpleClassName}VO } from '@/api/system/post/types'  
10 - import { rules, allSchemas } from './post.data'  
11 - import * as ${simpleClassName}Api from '@/api/system/post' 9 + import type { ${simpleClassName}VO } from '@/api/${table.moduleName}/${simpleClassName}/types'
  10 + import { rules, allSchemas } from './${simpleClassName}.data'
  11 + import * as ${simpleClassName}Api from '@/api/${table.moduleName}/${simpleClassName}'
12 const { t } = useI18n() // 国际化 12 const { t } = useI18n() // 国际化
13 13
14 // ========== 列表相关 ========== 14 // ========== 列表相关 ==========
yudao-module-mall/pom.xml
@@ -15,17 +15,18 @@ @@ -15,17 +15,18 @@
15 <name>${project.artifactId}</name> 15 <name>${project.artifactId}</name>
16 16
17 <description> 17 <description>
18 - 商城大模块,由 product 商品、market 营销、trade 交易等组成 18 + 商城大模块,由 product 商品、market 营销、trade 交易 coupon等组成
19 </description> 19 </description>
20 <modules> 20 <modules>
  21 + <module>yudao-module-coupon-api</module>
  22 + <module>yudao-module-coupon-biz</module>
21 <module>yudao-module-market-api</module> 23 <module>yudao-module-market-api</module>
22 <module>yudao-module-market-biz</module> 24 <module>yudao-module-market-biz</module>
23 <module>yudao-module-product-api</module> 25 <module>yudao-module-product-api</module>
24 <module>yudao-module-product-biz</module> 26 <module>yudao-module-product-biz</module>
25 <module>yudao-module-trade-api</module> 27 <module>yudao-module-trade-api</module>
26 <module>yudao-module-trade-biz</module> 28 <module>yudao-module-trade-biz</module>
27 - <module>yudao-module-coupon-api</module>  
28 - <module>yudao-module-coupon-biz</module> 29 +
29 </modules> 30 </modules>
30 31
31 </project> 32 </project>
yudao-module-mall/yudao-module-coupon-api/pom.xml
@@ -23,6 +23,13 @@ @@ -23,6 +23,13 @@
23 <groupId>cn.iocoder.boot</groupId> 23 <groupId>cn.iocoder.boot</groupId>
24 <artifactId>yudao-common</artifactId> 24 <artifactId>yudao-common</artifactId>
25 </dependency> 25 </dependency>
  26 +
  27 + <!-- 参数校验 -->
  28 + <dependency>
  29 + <groupId>org.springframework.boot</groupId>
  30 + <artifactId>spring-boot-starter-validation</artifactId>
  31 + <optional>true</optional>
  32 + </dependency>
26 </dependencies> 33 </dependencies>
27 34
28 </project> 35 </project>
29 \ No newline at end of file 36 \ No newline at end of file
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponExpireTimeTypeEnum.java
@@ -14,7 +14,8 @@ import lombok.RequiredArgsConstructor; @@ -14,7 +14,8 @@ import lombok.RequiredArgsConstructor;
14 @Getter 14 @Getter
15 public enum CouponExpireTimeTypeEnum { 15 public enum CouponExpireTimeTypeEnum {
16 16
17 - OPEN(1,"不开启"),CLOSE(0,"开启"),; 17 + OPEN(1,"不开启"),
  18 + CLOSE(0,"开启"),;
18 19
19 /** 20 /**
20 * 是否开启过期提醒 21 * 是否开启过期提醒
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponFetchTypeEnum.java
@@ -14,7 +14,8 @@ import lombok.RequiredArgsConstructor; @@ -14,7 +14,8 @@ import lombok.RequiredArgsConstructor;
14 @Getter 14 @Getter
15 public enum CouponFetchTypeEnum { 15 public enum CouponFetchTypeEnum {
16 16
17 - LIMIT(0,"否"),NOT_LIMIT(0,"开启"),; 17 + LIMIT(1,"限制"),
  18 + NOT_LIMIT(0,"不限制"),;
18 19
19 /** 20 /**
20 * 是否开启过期提醒 21 * 是否开启过期提醒
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponProductTypeEnum.java renamed to yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponForbidPreferenceEnum.java
@@ -6,17 +6,16 @@ import lombok.RequiredArgsConstructor; @@ -6,17 +6,16 @@ import lombok.RequiredArgsConstructor;
6 6
7 7
8 /** 8 /**
9 - * 优惠券 - 优惠券类型 9 + * 优惠券 - 优惠叠加类型
10 * 10 *
11 * @author Sin 11 * @author Sin
12 */ 12 */
13 @RequiredArgsConstructor 13 @RequiredArgsConstructor
14 @Getter 14 @Getter
15 -public enum CouponProductTypeEnum { 15 +public enum CouponForbidPreferenceEnum {
16 16
17 - PROCESSING(1,"进行中"),  
18 - END(2,"已结束"),  
19 - CLOSE(3,"已关闭"),; 17 + UN_FORBID(0,"不限制"),
  18 + FORBID(1,"优惠券仅原价购买商品时可用");
20 19
21 /** 20 /**
22 * 优惠券类型 21 * 优惠券类型
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponGoodsTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.CouponTemplete.enums;
  2 +
  3 +
  4 +import lombok.Getter;
  5 +import lombok.RequiredArgsConstructor;
  6 +
  7 +
  8 +/**
  9 + * 优惠券 - 优惠券商品使用类型
  10 + *
  11 + * @author Sin
  12 + */
  13 +@RequiredArgsConstructor
  14 +@Getter
  15 +public enum CouponGoodsTypeEnum {
  16 +
  17 + ALL(1,"全部商品可用"),
  18 + POINT_PRODUCT(2,"指定商品可用"),
  19 + POINT_PRODUCT_NOT(3,"指定商品不可用"),;
  20 +
  21 + /**
  22 + * 优惠券商品使用类型
  23 + */
  24 + private final Integer type;
  25 + /**
  26 + * 优惠券商品使用类型名
  27 + */
  28 + private final String name;
  29 +
  30 +}
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponStatusTypeEnum.java
@@ -6,7 +6,7 @@ import lombok.RequiredArgsConstructor; @@ -6,7 +6,7 @@ import lombok.RequiredArgsConstructor;
6 6
7 7
8 /** 8 /**
9 - * 优惠券 - 优惠券类型 9 + * 优惠券 - 优惠券状态类型
10 * 10 *
11 * @author Sin 11 * @author Sin
12 */ 12 */
@@ -14,9 +14,9 @@ import lombok.RequiredArgsConstructor; @@ -14,9 +14,9 @@ import lombok.RequiredArgsConstructor;
14 @Getter 14 @Getter
15 public enum CouponStatusTypeEnum { 15 public enum CouponStatusTypeEnum {
16 16
17 - ALL(1,"全部商品可用"),  
18 - POINT_PRODUCT(2,"指定商品可用"),  
19 - POINT_PRODUCT_NOT(3,"指定商品不可用不能为空"),; 17 + PROCESSING(1,"进行中"),
  18 + END(2,"已结束"),
  19 + CLOSE(3,"已关闭"),;
20 20
21 /** 21 /**
22 * 优惠券类型 22 * 优惠券类型
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponUseLimitEnum.java
@@ -6,7 +6,7 @@ import lombok.RequiredArgsConstructor; @@ -6,7 +6,7 @@ import lombok.RequiredArgsConstructor;
6 6
7 7
8 /** 8 /**
9 - * 优惠券 - 优惠券类型 9 + * 优惠券使用类型 - 优惠券使用类型类型
10 * 10 *
11 * @author Sin 11 * @author Sin
12 */ 12 */
@@ -18,11 +18,11 @@ public enum CouponUseLimitEnum { @@ -18,11 +18,11 @@ public enum CouponUseLimitEnum {
18 NO_LIMIT(2,"有门槛"),; 18 NO_LIMIT(2,"有门槛"),;
19 19
20 /** 20 /**
21 - * 优惠券类型 21 + * 优惠券使用类型
22 */ 22 */
23 private final Integer type; 23 private final Integer type;
24 /** 24 /**
25 - * 优惠券类型名 25 + * 优惠券使用类型名
26 */ 26 */
27 private final String name; 27 private final String name;
28 28
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponValidityTypeEnum.java
@@ -14,7 +14,7 @@ public enum CouponValidityTypeEnum { @@ -14,7 +14,7 @@ public enum CouponValidityTypeEnum {
14 14
15 TIME_RANGE_EXPIRTED(1,"时间范围过期"), 15 TIME_RANGE_EXPIRTED(1,"时间范围过期"),
16 EXPIRES_AFTER_FIXED_DATE(2,"领取之日固定日期后过期"), 16 EXPIRES_AFTER_FIXED_DATE(2,"领取之日固定日期后过期"),
17 - EXPIRES_DATE_NEXT_FIEXD_DATE(3,"领取次日固定日期后过期不能为空"),; 17 + EXPIRES_DATE_NEXT_FIEXD_DATE(3,"领取次日固定日期后过期"),;
18 18
19 19
20 /** 20 /**
yudao-module-mall/yudao-module-coupon-biz/pom.xml
@@ -3,19 +3,18 @@ @@ -3,19 +3,18 @@
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent> 5 <parent>
6 - <artifactId>yudao-module-mall</artifactId>  
7 <groupId>cn.iocoder.boot</groupId> 6 <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao-module-mall</artifactId>
8 <version>${revision}</version> 8 <version>${revision}</version>
9 </parent> 9 </parent>
10 <modelVersion>4.0.0</modelVersion> 10 <modelVersion>4.0.0</modelVersion>
11 - <artifactId>yudao-module-coupon-biz</artifactId>  
12 <packaging>jar</packaging> 11 <packaging>jar</packaging>
13 - 12 + <artifactId>yudao-module-coupon-biz</artifactId>
14 13
15 <name>${project.artifactId}</name> 14 <name>${project.artifactId}</name>
  15 +
16 <description> 16 <description>
17 - trade 模块,主要实现交易相关功能  
18 - 例如:订单、退款、购物车等功能。 17 + coupon模块,主要负责优惠券的一些业务,含发布优惠券模板,分发优惠券等
19 </description> 18 </description>
20 19
21 <dependencies> 20 <dependencies>
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/CouponController.java
@@ -21,7 +21,7 @@ import cn.iocoder.yudao.module.coupon.service.coupon.CouponService; @@ -21,7 +21,7 @@ import cn.iocoder.yudao.module.coupon.service.coupon.CouponService;
21 21
22 @Api(tags = "管理后台 - 优惠券") 22 @Api(tags = "管理后台 - 优惠券")
23 @RestController 23 @RestController
24 -@RequestMapping("/coupon/coupon/") 24 +@RequestMapping("/coupon/item")
25 @Validated 25 @Validated
26 public class CouponController { 26 public class CouponController {
27 27
@@ -69,7 +69,7 @@ public class CouponController { @@ -69,7 +69,7 @@ public class CouponController {
69 69
70 @GetMapping("/list") 70 @GetMapping("/list")
71 @ApiOperation("获得优惠券列表") 71 @ApiOperation("获得优惠券列表")
72 -// @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) 72 + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
73 @PreAuthorize("@ss.hasPermission('coupon::query')") 73 @PreAuthorize("@ss.hasPermission('coupon::query')")
74 public CommonResult<List<CouponRespVO>> getList(@RequestParam("ids") Collection<Long> ids) { 74 public CommonResult<List<CouponRespVO>> getList(@RequestParam("ids") Collection<Long> ids) {
75 List<CouponDO> list = couponService.getList(ids); 75 List<CouponDO> list = couponService.getList(ids);
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupon/vo/CouponBaseVO.java
@@ -68,7 +68,7 @@ public class CouponBaseVO { @@ -68,7 +68,7 @@ public class CouponBaseVO {
68 private Boolean whetherForbidPreference; 68 private Boolean whetherForbidPreference;
69 69
70 @ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启", required = true) 70 @ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启", required = true)
71 - @NotNull(message = "是否开启过期提醒0-不开启 1-开启不能为空") 71 + @NotNull(message = "是否开启过期提醒0-不开启 1-开启")
72 private Boolean whetherExpireNotice; 72 private Boolean whetherExpireNotice;
73 73
74 @ApiModelProperty(value = "过期前N天提醒", required = true) 74 @ApiModelProperty(value = "过期前N天提醒", required = true)
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/CouponTempleteController.java deleted
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete;  
2 -  
3 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.*;  
4 -import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert;  
5 -import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;  
6 -import cn.iocoder.yudao.module.coupon.service.CouponTemplete.CouponTempleteService;  
7 -import org.springframework.web.bind.annotation.*;  
8 -import javax.annotation.Resource;  
9 -import org.springframework.validation.annotation.Validated;  
10 -import org.springframework.security.access.prepost.PreAuthorize;  
11 -import io.swagger.annotations.*;  
12 -  
13 -import javax.validation.*;  
14 -import java.util.*;  
15 -  
16 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
17 -import cn.iocoder.yudao.framework.common.pojo.CommonResult;  
18 -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;  
19 -  
20 -@Api(tags = "管理后台 - 优惠券模板")  
21 -@RestController  
22 -@RequestMapping("/coupon/CouponTemplete/")  
23 -@Validated  
24 -public class CouponTempleteController {  
25 -  
26 - @Resource  
27 - private CouponTempleteService Service;  
28 -  
29 - @PostMapping("/create")  
30 - @ApiOperation("创建优惠券模板")  
31 - @PreAuthorize("@ss.hasPermission('CouponTemplete::create')")  
32 - public CommonResult<Long> create(@Valid @RequestBody CouponTempleteCreateReqVO createReqVO) {  
33 - return success(Service.create(createReqVO));  
34 - }  
35 -  
36 - @PutMapping("/update")  
37 - @ApiOperation("更新优惠券模板")  
38 - @PreAuthorize("@ss.hasPermission('CouponTemplete::update')")  
39 - public CommonResult<Boolean> update(@Valid @RequestBody CouponTempleteUpdateReqVO updateReqVO) {  
40 - Service.update(updateReqVO);  
41 - return success(true);  
42 - }  
43 -  
44 - @DeleteMapping("/delete")  
45 - @ApiOperation("删除优惠券模板")  
46 - @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)  
47 - @PreAuthorize("@ss.hasPermission('CouponTemplete::delete')")  
48 - public CommonResult<Boolean> delete(@RequestParam("id") Long id) {  
49 - Service.delete(id);  
50 - return success(true);  
51 - }  
52 -  
53 - @GetMapping("/get")  
54 - @ApiOperation("获得优惠券模板")  
55 -// @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)  
56 - @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")  
57 - public CommonResult<CouponTempleteRespVO> get(@RequestParam("id") Long id) {  
58 - CouponTempleteDO couponTempleteDO = Service.get(id);  
59 - return success(CouponTempleteConvert.INSTANCE.convert(couponTempleteDO));  
60 - }  
61 -  
62 - @GetMapping("/list")  
63 - @ApiOperation("获得优惠券模板列表")  
64 -// @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)  
65 - @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")  
66 - public CommonResult<List<CouponTempleteRespVO>> getList(@RequestParam("ids") Collection<Long> ids) {  
67 - List<CouponTempleteDO> list = Service.getList(ids);  
68 - return success(CouponTempleteConvert.INSTANCE.convertList(list));  
69 - }  
70 -  
71 - @GetMapping("/page")  
72 - @ApiOperation("获得优惠券模板分页")  
73 - @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")  
74 - public CommonResult<PageResult<CouponTempleteRespVO>> getPage(@Valid CouponTempletePageReqVO pageVO) {  
75 - PageResult<CouponTempleteDO> pageResult = Service.getPage(pageVO);  
76 - return success(CouponTempleteConvert.INSTANCE.convertPage(pageResult));  
77 - }  
78 -  
79 -  
80 -  
81 -}  
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/CouponTempleteController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete;
  2 +
  3 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.*;
  4 +import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert;
  5 +import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
  6 +import cn.iocoder.yudao.module.coupon.service.CouponTemplete.CouponTempleteService;
  7 +import org.springframework.web.bind.annotation.*;
  8 +import javax.annotation.Resource;
  9 +import org.springframework.validation.annotation.Validated;
  10 +import org.springframework.security.access.prepost.PreAuthorize;
  11 +import io.swagger.annotations.*;
  12 +
  13 +import javax.validation.*;
  14 +import java.util.*;
  15 +
  16 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  17 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  18 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  19 +
  20 +@Api(tags = "管理后台 - 优惠券模板")
  21 +@RestController
  22 +@RequestMapping("/coupon/template")
  23 +@Validated
  24 +public class CouponTempleteController {
  25 +
  26 + @Resource
  27 + private CouponTempleteService couponTempleteServiceService;
  28 +
  29 + @PostMapping("/create")
  30 + @ApiOperation("创建优惠券模板")
  31 + @PreAuthorize("@ss.hasPermission('CouponTemplete::create')")
  32 + public CommonResult<Long> create(@Valid @RequestBody CouponTempleteCreateReqVO createReqVO) {
  33 + return success(couponTempleteServiceService.create(createReqVO));
  34 + }
  35 +
  36 +// @PutMapping("/update")
  37 +// @ApiOperation("更新优惠券模板")
  38 +// @PreAuthorize("@ss.hasPermission('CouponTemplete::update')")
  39 +// public CommonResult<Boolean> update(@Valid @RequestBody CouponTempleteUpdateReqVO updateReqVO) {
  40 +// couponTempleteServiceService.update(updateReqVO);
  41 +// return success(true);
  42 +// }
  43 +//
  44 +// @DeleteMapping("/delete")
  45 +// @ApiOperation("删除优惠券模板")
  46 +// @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  47 +// @PreAuthorize("@ss.hasPermission('CouponTemplete::delete')")
  48 +// public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
  49 +// couponTempleteServiceService.delete(id);
  50 +// return success(true);
  51 +// }
  52 +//
  53 +// @GetMapping("/get")
  54 +// @ApiOperation("获得优惠券模板")
  55 +// @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  56 +// @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
  57 +// public CommonResult<CouponTempleteRespVO> get(@RequestParam("id") Long id) {
  58 +// CouponTempleteDO couponTempleteDO = couponTempleteServiceService.get(id);
  59 +// return success(CouponTempleteConvert.INSTANCE.convert(couponTempleteDO));
  60 +// }
  61 +//
  62 +// @GetMapping("/list")
  63 +// @ApiOperation("获得优惠券模板列表")
  64 +// @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
  65 +// @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
  66 +// public CommonResult<List<CouponTempleteRespVO>> getList(@RequestParam("ids") Collection<Long> ids) {
  67 +// List<CouponTempleteDO> list = couponTempleteServiceService.getList(ids);
  68 +// return success(CouponTempleteConvert.INSTANCE.convertList(list));
  69 +// }
  70 +//
  71 + @GetMapping("/page")
  72 + @ApiOperation("获得优惠券模板分页")
  73 + @PreAuthorize("@ss.hasPermission('CouponTemplete::query')")
  74 + public CommonResult<PageResult<CouponTempleteRespVO>> getPage(@Valid CouponTempletePageReqVO pageVO) {
  75 + PageResult<CouponTempleteDO> pageResult = couponTempleteServiceService.getPage(pageVO);
  76 + return success(CouponTempleteConvert.INSTANCE.convertPage(pageResult));
  77 + }
  78 +
  79 +
  80 +
  81 +}
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempleteBaseVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteBaseVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import java.util.*; 4 import java.util.*;
@@ -34,7 +34,7 @@ public class CouponTempleteBaseVO { @@ -34,7 +34,7 @@ public class CouponTempleteBaseVO {
34 34
35 @ApiModelProperty(value = "适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用", required = true) 35 @ApiModelProperty(value = "适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用", required = true)
36 @NotNull(message = "适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用不能为空") 36 @NotNull(message = "适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用不能为空")
37 - private Boolean goodsType; 37 + private Integer goodsType;
38 38
39 @ApiModelProperty(value = "适用商品id") 39 @ApiModelProperty(value = "适用商品id")
40 private String productIds; 40 private String productIds;
@@ -104,7 +104,7 @@ public class CouponTempleteBaseVO { @@ -104,7 +104,7 @@ public class CouponTempleteBaseVO {
104 104
105 105
106 @ApiModelProperty(value = "领取是否无限制0-否 1是", required = true) 106 @ApiModelProperty(value = "领取是否无限制0-否 1是", required = true)
107 - @NotNull(message = "是否无限制0-否 1是 不能为空") 107 + @NotNull(message = "是否无限制0-否 1是")
108 private Boolean whetherLimitless; 108 private Boolean whetherLimitless;
109 109
110 @ApiModelProperty(value = "每人最大领取个数", required = true) 110 @ApiModelProperty(value = "每人最大领取个数", required = true)
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempleteCreateReqVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteCreateReqVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import io.swagger.annotations.*; 4 import io.swagger.annotations.*;
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempleteExcelVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExcelVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import java.util.*; 4 import java.util.*;
@@ -39,7 +39,7 @@ public class CouponTempleteExcelVO { @@ -39,7 +39,7 @@ public class CouponTempleteExcelVO {
39 private Integer usedCount; 39 private Integer usedCount;
40 40
41 @ExcelProperty("适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用") 41 @ExcelProperty("适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用")
42 - private Boolean goodsType; 42 + private Integer goodsType;
43 43
44 @ExcelProperty("适用商品id") 44 @ExcelProperty("适用商品id")
45 private String productIds; 45 private String productIds;
@@ -66,7 +66,7 @@ public class CouponTempleteExcelVO { @@ -66,7 +66,7 @@ public class CouponTempleteExcelVO {
66 private BigDecimal maxMoney; 66 private BigDecimal maxMoney;
67 67
68 @ExcelProperty("过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期") 68 @ExcelProperty("过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期")
69 - private Boolean validityType; 69 + private Integer validityType;
70 70
71 @ExcelProperty("使用开始日期 过期类型1时必填") 71 @ExcelProperty("使用开始日期 过期类型1时必填")
72 private Date startUseTime; 72 private Date startUseTime;
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempleteExportReqVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteExportReqVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 4
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempletePageReqVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempletePageReqVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 4
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempleteRespVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteRespVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import java.util.*; 4 import java.util.*;
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/coupontemplete/vo/CouponTempleteUpdateReqVO.java renamed to yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/controller/admin/templete/vo/CouponTempleteUpdateReqVO.java
1 -package cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo; 1 +package cn.iocoder.yudao.module.coupon.controller.admin.templete.vo;
2 2
3 import lombok.*; 3 import lombok.*;
4 import io.swagger.annotations.*; 4 import io.swagger.annotations.*;
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/convert/CouponTemplete/CouponTempleteConvert.java
@@ -4,10 +4,10 @@ import java.util.*; @@ -4,10 +4,10 @@ import java.util.*;
4 4
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6
7 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteCreateReqVO;  
8 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteExcelVO;  
9 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteRespVO;  
10 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteUpdateReqVO; 7 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteCreateReqVO;
  8 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteExcelVO;
  9 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteRespVO;
  10 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteUpdateReqVO;
11 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; 11 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
12 import org.mapstruct.Mapper; 12 import org.mapstruct.Mapper;
13 import org.mapstruct.factory.Mappers; 13 import org.mapstruct.factory.Mappers;
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/dataobject/CouponTemplete/CouponTempleteDO.java
@@ -57,7 +57,7 @@ public class CouponTempleteDO extends BaseDO { @@ -57,7 +57,7 @@ public class CouponTempleteDO extends BaseDO {
57 /** 57 /**
58 * 适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用 58 * 适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用
59 */ 59 */
60 - private Boolean goodsType; 60 + private Integer goodsType;
61 /** 61 /**
62 * 适用商品id 62 * 适用商品id
63 */ 63 */
@@ -93,7 +93,7 @@ public class CouponTempleteDO extends BaseDO { @@ -93,7 +93,7 @@ public class CouponTempleteDO extends BaseDO {
93 /** 93 /**
94 * 过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期 94 * 过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期
95 */ 95 */
96 - private Boolean validityType; 96 + private Integer validityType;
97 /** 97 /**
98 * 使用开始日期 过期类型1时必填 98 * 使用开始日期 过期类型1时必填
99 */ 99 */
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/dal/mysql/CouponTemplete/CouponTempleteMapper.java
@@ -5,8 +5,8 @@ import java.util.*; @@ -5,8 +5,8 @@ import java.util.*;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
8 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteExportReqVO;  
9 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempletePageReqVO; 8 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteExportReqVO;
  9 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempletePageReqVO;
10 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; 10 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
11 import org.apache.ibatis.annotations.Mapper; 11 import org.apache.ibatis.annotations.Mapper;
12 12
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/package-info.java 0 → 100644
  1 +/**
  2 + * coupon模块,主要负责麦一些优惠券的额增删
  3 + *
  4 + * 1. Controller URL:以 /coumon/ 开头,避免和其它 Module 冲突
  5 + */
  6 +package cn.iocoder.yudao.module.coupon;
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteService.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.coupon.service.CouponTemplete; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.coupon.service.CouponTemplete;
2 2
3 import java.util.*; 3 import java.util.*;
4 import javax.validation.*; 4 import javax.validation.*;
5 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.*; 5 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.*;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; 7 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
8 8
yudao-module-mall/yudao-module-coupon-biz/src/main/java/cn/iocoder/yudao/module/coupon/service/CouponTemplete/CouponTempleteServiceImpl.java
@@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.coupon.service.CouponTemplete; @@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.coupon.service.CouponTemplete;
2 2
3 import cn.iocoder.yudao.module.CouponTemplete.enums.CouponTypeEnum; 3 import cn.iocoder.yudao.module.CouponTemplete.enums.CouponTypeEnum;
4 import cn.iocoder.yudao.module.CouponTemplete.enums.CouponValidityTypeEnum; 4 import cn.iocoder.yudao.module.CouponTemplete.enums.CouponValidityTypeEnum;
5 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteCreateReqVO;  
6 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteExportReqVO;  
7 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempletePageReqVO;  
8 -import cn.iocoder.yudao.module.coupon.controller.admin.coupontemplete.vo.CouponTempleteUpdateReqVO; 5 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteCreateReqVO;
  6 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteExportReqVO;
  7 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempletePageReqVO;
  8 +import cn.iocoder.yudao.module.coupon.controller.admin.templete.vo.CouponTempleteUpdateReqVO;
9 import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert; 9 import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert;
10 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; 10 import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO;
11 import cn.iocoder.yudao.module.coupon.dal.mysql.CouponTemplete.CouponTempleteMapper; 11 import cn.iocoder.yudao.module.coupon.dal.mysql.CouponTemplete.CouponTempleteMapper;
12 -import cn.iocoder.yudao.module.coupon.service.CouponTemplete.CouponTempleteService;  
13 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
14 import javax.annotation.Resource; 13 import javax.annotation.Resource;
15 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
@@ -41,7 +40,7 @@ public class CouponTempleteServiceImpl implements CouponTempleteService { @@ -41,7 +40,7 @@ public class CouponTempleteServiceImpl implements CouponTempleteService {
41 /* 验证类型、判断必填*/ 40 /* 验证类型、判断必填*/
42 checkCouponType(createReqVO); 41 checkCouponType(createReqVO);
43 42
44 - /*todo 验证过期类型、判断必填*/ 43 + /*验证过期类型、判断必填*/
45 checkValidityType(createReqVO); 44 checkValidityType(createReqVO);
46 45
47 46
yudao-module-mall/yudao-module-market-api/src/main/java/cn/iocoder/yudao/module/market/api/price/dto/PriceCalculateRespDTO.java
@@ -20,14 +20,9 @@ public class PriceCalculateRespDTO { @@ -20,14 +20,9 @@ public class PriceCalculateRespDTO {
20 private Order order; 20 private Order order;
21 21
22 /** 22 /**
23 - * 商品 SKU 数组  
24 - */  
25 - private List<Item> items;  
26 -  
27 - /**  
28 * 营销活动数组 23 * 营销活动数组
29 * 24 *
30 - * 只对应 {@link #items} 商品匹配的活动 25 + * 只对应 {@link Order#items} 商品匹配的活动
31 */ 26 */
32 private List<Promotion> promotions; 27 private List<Promotion> promotions;
33 28
@@ -40,13 +35,13 @@ public class PriceCalculateRespDTO { @@ -40,13 +35,13 @@ public class PriceCalculateRespDTO {
40 /** 35 /**
41 * 商品原价(总),单位:分 36 * 商品原价(总),单位:分
42 * 37 *
43 - * 基于 {@link Item#getTotalOriginalPrice()} 求和 38 + * 基于 {@link OrderItem#getTotalOriginalPrice()} 求和
44 */ 39 */
45 private Integer skuOriginalPrice; 40 private Integer skuOriginalPrice;
46 /** 41 /**
47 * 商品优惠(总),单位:分 42 * 商品优惠(总),单位:分
48 * 43 *
49 - * 基于 {@link Item#getTotalPromotionPrice()} 求和 44 + * 基于 {@link OrderItem#getTotalPromotionPrice()} 求和
50 */ 45 */
51 private Integer skuPromotionPrice; 46 private Integer skuPromotionPrice;
52 /** 47 /**
@@ -69,6 +64,10 @@ public class PriceCalculateRespDTO { @@ -69,6 +64,10 @@ public class PriceCalculateRespDTO {
69 */ 64 */
70 // * - {@link #couponPrice} // TODO 芋艿:靠营销表记录 65 // * - {@link #couponPrice} // TODO 芋艿:靠营销表记录
71 private Integer payPrice; 66 private Integer payPrice;
  67 + /**
  68 + * 商品 SKU 数组
  69 + */
  70 + private List<OrderItem> items;
72 71
73 // ========== 营销基本信息 ========== 72 // ========== 营销基本信息 ==========
74 /** 73 /**
@@ -85,10 +84,15 @@ public class PriceCalculateRespDTO { @@ -85,10 +84,15 @@ public class PriceCalculateRespDTO {
85 } 84 }
86 85
87 /** 86 /**
88 - * 商品 SKU 87 + * 订单商品 SKU
89 */ 88 */
90 @Data 89 @Data
91 - public static class Item extends PriceCalculateReqDTO.Item { 90 + public static class OrderItem extends PriceCalculateReqDTO.Item {
  91 +
  92 + /**
  93 + * 购买数量
  94 + */
  95 + private Integer count;
92 96
93 /** 97 /**
94 * 商品原价(单),单位:分 98 * 商品原价(单),单位:分
@@ -141,6 +145,10 @@ public class PriceCalculateRespDTO { @@ -141,6 +145,10 @@ public class PriceCalculateRespDTO {
141 */ 145 */
142 private Long id; 146 private Long id;
143 /** 147 /**
  148 + * 营销名字
  149 + */
  150 + private String name;
  151 + /**
144 * 营销类型 152 * 营销类型
145 * 153 *
146 * 枚举 {@link PromotionTypeEnum} 154 * 枚举 {@link PromotionTypeEnum}
@@ -153,10 +161,6 @@ public class PriceCalculateRespDTO { @@ -153,10 +161,6 @@ public class PriceCalculateRespDTO {
153 */ 161 */
154 private Integer level; 162 private Integer level;
155 /** 163 /**
156 - * 匹配的商品 SKU 数组  
157 - */  
158 - private List<Item> items;  
159 - /**  
160 * 计算时的原价(总),单位:分 164 * 计算时的原价(总),单位:分
161 */ 165 */
162 private Integer totalOriginalPrice; 166 private Integer totalOriginalPrice;
@@ -165,6 +169,13 @@ public class PriceCalculateRespDTO { @@ -165,6 +169,13 @@ public class PriceCalculateRespDTO {
165 */ 169 */
166 private Integer totalPromotionPrice; 170 private Integer totalPromotionPrice;
167 /** 171 /**
  172 + * 匹配的商品 SKU 数组
  173 + */
  174 + private List<PromotionItem> items;
  175 +
  176 + // ========== 匹配情况 ==========
  177 +
  178 + /**
168 * 是否满足优惠条件 179 * 是否满足优惠条件
169 */ 180 */
170 private Boolean meet; 181 private Boolean meet;
@@ -176,26 +187,26 @@ public class PriceCalculateRespDTO { @@ -176,26 +187,26 @@ public class PriceCalculateRespDTO {
176 */ 187 */
177 private String meetTip; 188 private String meetTip;
178 189
179 - /**  
180 - * 匹配的商品 SKU  
181 - */  
182 - @Data  
183 - public static class Item { 190 + }
184 191
185 - /**  
186 - * 商品 SKU 编号  
187 - */  
188 - private Long skuId;  
189 - /**  
190 - * 计算时的原价(总),单位:分  
191 - */  
192 - private Integer totalOriginalPrice;  
193 - /**  
194 - * 计算时的优惠(总),单位:分  
195 - */  
196 - private Integer totalPromotionPrice; 192 + /**
  193 + * 营销匹配的商品 SKU
  194 + */
  195 + @Data
  196 + public static class PromotionItem {
197 197
198 - } 198 + /**
  199 + * 商品 SKU 编号
  200 + */
  201 + private Long skuId;
  202 + /**
  203 + * 计算时的原价(总),单位:分
  204 + */
  205 + private Integer totalOriginalPrice;
  206 + /**
  207 + * 计算时的优惠(总),单位:分
  208 + */
  209 + private Integer totalPromotionPrice;
199 210
200 } 211 }
201 212
yudao-module-mall/yudao-module-market-biz/pom.xml
@@ -24,6 +24,11 @@ @@ -24,6 +24,11 @@
24 <artifactId>yudao-module-market-api</artifactId> 24 <artifactId>yudao-module-market-api</artifactId>
25 <version>${revision}</version> 25 <version>${revision}</version>
26 </dependency> 26 </dependency>
  27 + <dependency>
  28 + <groupId>cn.iocoder.boot</groupId>
  29 + <artifactId>yudao-module-product-api</artifactId>
  30 + <version>${revision}</version>
  31 + </dependency>
27 32
28 <!-- 业务组件 --> 33 <!-- 业务组件 -->
29 <dependency> 34 <dependency>
yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/api/discount/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.market.api.discount;