Commit f21ce954ec9492b7ab9a8256bf200df6459b525e
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 | 23 | > |
| 24 | 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 | 28 | * 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson |
| 29 | 29 | * 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等 |
| 30 | 30 | * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录 |
| ... | ... | @@ -156,8 +156,9 @@ ps:核心功能已经实现,正在对接微信小程序中... |
| 156 | 156 | | `yudao-dependencies` | Maven 依赖版本管理 | |
| 157 | 157 | | `yudao-framework` | Java 框架拓展 | |
| 158 | 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 | 162 | | `yudao-ui-app` | 用户 APP 的 UI 界面 | |
| 162 | 163 | | `yudao-module-system` | 系统功能的 Module 模块 | |
| 163 | 164 | | `yudao-module-member` | 会员中心的 Module 模块 | |
| ... | ... | @@ -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 | 200 | | [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.6.12 | |
| 200 | 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 | 270 | | 模块 | biu | biu | biu | |
| 263 | 271 | |---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------| |
| 264 | 272 | | 报表设计器 |  |  |  | |
| 273 | + | |
| 274 | +### 移动端(管理后台) | |
| 275 | + | |
| 276 | +| biu | biu | biu | | |
| 277 | +|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------| | |
| 278 | +|  |  |  | | |
| 279 | +|  |  |  | | |
| 280 | +|  |  |  | | |
| 281 | + | |
| 282 | +目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。 | ... | ... |
pom.xml
| ... | ... | @@ -27,7 +27,7 @@ |
| 27 | 27 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 28 | 28 | |
| 29 | 29 | <properties> |
| 30 | - <revision>1.6.3-snapshot</revision> | |
| 30 | + <revision>1.6.4-snapshot</revision> | |
| 31 | 31 | <!-- Maven 相关 --> |
| 32 | 32 | <java.version>1.8</java.version> |
| 33 | 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 | 2657 | COMMIT; |
| 2658 | 2658 | |
| 2659 | 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 | 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 | 8 | \ No newline at end of file | ... | ... |
sql/mysql/vue3-menu.sql
| ... | ... | @@ -257,5 +257,7 @@ INSERT INTO `system_menu` VALUES (1264, '客户端查询', 'system:oauth2-client |
| 257 | 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 | 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 | 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 | 263 | SET FOREIGN_KEY_CHECKS = 1; | ... | ... |
sql/optional/mall/mall.sql
| ... | ... | @@ -22,24 +22,24 @@ SET FOREIGN_KEY_CHECKS = 0; |
| 22 | 22 | -- ---------------------------- |
| 23 | 23 | DROP TABLE IF EXISTS `market_activity`; |
| 24 | 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 | 45 | -- Records of market_activity |
| ... | ... | @@ -52,21 +52,21 @@ COMMIT; |
| 52 | 52 | -- ---------------------------- |
| 53 | 53 | DROP TABLE IF EXISTS `market_banner`; |
| 54 | 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 | 72 | -- Records of market_banner |
| ... | ... | @@ -79,22 +79,22 @@ COMMIT; |
| 79 | 79 | -- ---------------------------- |
| 80 | 80 | DROP TABLE IF EXISTS `member_address`; |
| 81 | 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 | 98 | ) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址'; |
| 99 | 99 | |
| 100 | 100 | -- ---------------------------- |
| ... | ... | @@ -109,19 +109,19 @@ COMMIT; |
| 109 | 109 | -- ---------------------------- |
| 110 | 110 | DROP TABLE IF EXISTS `product_brand`; |
| 111 | 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 | 125 | ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品品牌'; |
| 126 | 126 | |
| 127 | 127 | -- ---------------------------- |
| ... | ... | @@ -136,20 +136,20 @@ COMMIT; |
| 136 | 136 | -- ---------------------------- |
| 137 | 137 | DROP TABLE IF EXISTS `product_category`; |
| 138 | 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 | 153 | ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品分类'; |
| 154 | 154 | |
| 155 | 155 | -- ---------------------------- |
| ... | ... | @@ -164,17 +164,17 @@ COMMIT; |
| 164 | 164 | -- ---------------------------- |
| 165 | 165 | DROP TABLE IF EXISTS `product_property`; |
| 166 | 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 | 178 | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格名称'; |
| 179 | 179 | |
| 180 | 180 | -- ---------------------------- |
| ... | ... | @@ -188,17 +188,17 @@ COMMIT; |
| 188 | 188 | -- ---------------------------- |
| 189 | 189 | DROP TABLE IF EXISTS `product_property_value`; |
| 190 | 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 | 202 | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '规格值'; |
| 203 | 203 | |
| 204 | 204 | -- ---------------------------- |
| ... | ... | @@ -212,25 +212,25 @@ COMMIT; |
| 212 | 212 | -- ---------------------------- |
| 213 | 213 | DROP TABLE IF EXISTS `product_sku`; |
| 214 | 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 | 234 | `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', |
| 235 | 235 | PRIMARY KEY (`id`) USING BTREE |
| 236 | 236 | ) ENGINE=InnoDB COMMENT='商品sku'; |
| ... | ... | @@ -246,33 +246,33 @@ COMMIT; |
| 246 | 246 | -- ---------------------------- |
| 247 | 247 | DROP TABLE IF EXISTS `product_spu`; |
| 248 | 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 | 276 | ) ENGINE=InnoDB COMMENT='商品spu'; |
| 277 | 277 | |
| 278 | 278 | -- ---------------------------- | ... | ... |
yudao-dependencies/pom.xml
| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 15 | 15 | |
| 16 | 16 | <properties> |
| 17 | - <revision>1.6.3-snapshot</revision> | |
| 17 | + <revision>1.6.4-snapshot</revision> | |
| 18 | 18 | <!-- 统一依赖管理 --> |
| 19 | 19 | <spring.boot.version>2.6.10</spring.boot.version> |
| 20 | 20 | <!-- Web 相关 --> |
| ... | ... | @@ -41,14 +41,14 @@ |
| 41 | 41 | <jedis-mock.version>0.1.16</jedis-mock.version> |
| 42 | 42 | <mockito-inline.version>4.0.0</mockito-inline.version> |
| 43 | 43 | <!-- Bpm 工作流相关 --> |
| 44 | - <flowable.version>6.7.0</flowable.version> | |
| 44 | + <flowable.version>6.7.2</flowable.version> | |
| 45 | 45 | <!-- 工具类相关 --> |
| 46 | 46 | <jasypt-spring-boot-starter.version>3.0.4</jasypt-spring-boot-starter.version> |
| 47 | 47 | <lombok.version>1.18.20</lombok.version> |
| 48 | 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 | 50 | <easyexcel.verion>3.1.1</easyexcel.verion> |
| 51 | - <velocity.version>2.2</velocity.version> | |
| 51 | + <velocity.version>2.3</velocity.version> | |
| 52 | 52 | <screw.version>1.0.5</screw.version> |
| 53 | 53 | <fastjson.version>1.2.83</fastjson.version> |
| 54 | 54 | <guava.version>30.1.1-jre</guava.version> |
| ... | ... | @@ -57,14 +57,16 @@ |
| 57 | 57 | <commons-net.version>3.8.0</commons-net.version> |
| 58 | 58 | <jsch.version>0.1.55</jsch.version> |
| 59 | 59 | <tika-core.version>2.4.1</tika-core.version> |
| 60 | + <aj-captcha.version>1.3.0</aj-captcha.version> | |
| 60 | 61 | <!-- 三方云服务相关 --> |
| 61 | 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 | 66 | <yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version> |
| 66 | 67 | <justauth.version>1.4.0</justauth.version> |
| 67 | 68 | <jimureport.version>1.5.2</jimureport.version> |
| 69 | + <xercesImpl.version>2.12.0</xercesImpl.version> | |
| 68 | 70 | </properties> |
| 69 | 71 | |
| 70 | 72 | <dependencyManagement> |
| ... | ... | @@ -129,6 +131,11 @@ |
| 129 | 131 | <artifactId>yudao-spring-boot-starter-biz-error-code</artifactId> |
| 130 | 132 | <version>${revision}</version> |
| 131 | 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 | 140 | <!-- Spring 核心 --> |
| 134 | 141 | <dependency> |
| ... | ... | @@ -452,6 +459,12 @@ |
| 452 | 459 | </dependency> |
| 453 | 460 | |
| 454 | 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 | 468 | <groupId>org.apache.velocity</groupId> |
| 456 | 469 | <artifactId>velocity-engine-core</artifactId> |
| 457 | 470 | <version>${velocity.version}</version> |
| ... | ... | @@ -565,6 +578,11 @@ |
| 565 | 578 | <artifactId>jimureport-spring-boot-starter</artifactId> |
| 566 | 579 | <version>${jimureport.version}</version> |
| 567 | 580 | </dependency> |
| 581 | + <dependency> | |
| 582 | + <groupId>xerces</groupId> | |
| 583 | + <artifactId>xercesImpl</artifactId> | |
| 584 | + <version>${xercesImpl.version}</version> | |
| 585 | + </dependency> | |
| 568 | 586 | </dependencies> |
| 569 | 587 | </dependencyManagement> |
| 570 | 588 | ... | ... |
yudao-framework/pom.xml
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/ArrayUtils.java
| 1 | 1 | package cn.iocoder.yudao.framework.common.util.collection; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | +import cn.hutool.core.collection.IterUtil; | |
| 4 | 5 | import cn.hutool.core.util.ArrayUtil; |
| 5 | 6 | |
| 6 | 7 | import java.util.Collection; |
| ... | ... | @@ -44,7 +45,7 @@ public class ArrayUtils { |
| 44 | 45 | if (CollectionUtil.isEmpty(from)) { |
| 45 | 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 | 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 | 17 | */ |
| 18 | 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 | 22 | private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); |
| 21 | 23 | |
| 22 | 24 | private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*"); |
| 23 | 25 | |
| 24 | 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 | 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 | 18 | import net.sf.jsqlparser.expression.operators.relational.ExistsExpression; |
| 19 | 19 | import net.sf.jsqlparser.expression.operators.relational.ExpressionList; |
| 20 | 20 | import net.sf.jsqlparser.expression.operators.relational.InExpression; |
| 21 | -import net.sf.jsqlparser.expression.operators.relational.ItemsList; | |
| 22 | 21 | import net.sf.jsqlparser.schema.Table; |
| 23 | 22 | import net.sf.jsqlparser.statement.delete.Delete; |
| 24 | 23 | import net.sf.jsqlparser.statement.select.*; |
| ... | ... | @@ -37,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap; |
| 37 | 36 | |
| 38 | 37 | /** |
| 39 | 38 | * 数据权限拦截器,通过 {@link DataPermissionRule} 数据权限规则,重写 SQL 的方式来实现 |
| 40 | - * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, Table)} 方法 | |
| 39 | + * 主要的 SQL 重写方法,可见 {@link #builderExpression(Expression, List)} 方法 | |
| 41 | 40 | * |
| 42 | 41 | * 整体的代码实现上,参考 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor} 实现。 |
| 43 | 42 | * 所以每次 MyBatis Plus 升级时,需要 Review 下其具体的实现是否有变更! |
| ... | ... | @@ -53,8 +52,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme |
| 53 | 52 | private final MappedStatementCache mappedStatementCache = new MappedStatementCache(); |
| 54 | 53 | |
| 55 | 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 | 56 | // 获得 Mapper 对应的数据权限的规则 |
| 59 | 57 | List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(ms.getId()); |
| 60 | 58 | if (mappedStatementCache.noRewritable(ms, rules)) { // 如果无需重写,则跳过 |
| ... | ... | @@ -68,12 +66,14 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme |
| 68 | 66 | // 处理 SQL |
| 69 | 67 | mpBs.sql(parserSingle(mpBs.sql(), null)); |
| 70 | 68 | } finally { |
| 69 | + // 添加是否需要重写的缓存 | |
| 71 | 70 | addMappedStatementCache(ms); |
| 71 | + // 清空上下文 | |
| 72 | 72 | ContextHolder.clear(); |
| 73 | 73 | } |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | - @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景 | |
| 76 | + @Override // 只处理 UPDATE / DELETE 场景,不处理 INSERT 场景(因为 INSERT 不需要数据权限) | |
| 77 | 77 | public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) { |
| 78 | 78 | PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh); |
| 79 | 79 | MappedStatement ms = mpSh.mappedStatement(); |
| ... | ... | @@ -92,7 +92,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme |
| 92 | 92 | // 处理 SQL |
| 93 | 93 | mpBs.sql(parserMulti(mpBs.sql(), null)); |
| 94 | 94 | } finally { |
| 95 | + // 添加是否需要重写的缓存 | |
| 95 | 96 | addMappedStatementCache(ms); |
| 97 | + // 清空上下文 | |
| 96 | 98 | ContextHolder.clear(); |
| 97 | 99 | } |
| 98 | 100 | } |
| ... | ... | @@ -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 | 113 | * update 语句处理 |
| 130 | 114 | */ |
| ... | ... | @@ -142,28 +126,77 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme |
| 142 | 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 | 150 | * 处理 PlainSelect |
| 147 | 151 | */ |
| 148 | 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 | 153 | //#3087 github |
| 159 | 154 | List<SelectItem> selectItems = plainSelect.getSelectItems(); |
| 160 | 155 | if (CollectionUtils.isNotEmpty(selectItems)) { |
| 161 | 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 | 169 | List<Join> joins = plainSelect.getJoins(); |
| 164 | 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 | 224 | return; |
| 192 | 225 | } |
| 193 | 226 | if (where instanceof FromItem) { |
| 194 | - processFromItem((FromItem) where); | |
| 227 | + processOtherFromItem((FromItem) where); | |
| 195 | 228 | return; |
| 196 | 229 | } |
| 197 | 230 | if (where.toString().indexOf("SELECT") > 0) { |
| ... | ... | @@ -204,9 +237,9 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme |
| 204 | 237 | } else if (where instanceof InExpression) { |
| 205 | 238 | // in |
| 206 | 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 | 244 | } else if (where instanceof ExistsExpression) { |
| 212 | 245 | // exists |
| ... | ... | @@ -239,7 +272,7 @@ public class DataPermissionDatabaseInterceptor extends JsqlParserSupport impleme |
| 239 | 272 | * <p>支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)<p> |
| 240 | 273 | * <p> fixed gitee pulls/141</p> |
| 241 | 274 | * |
| 242 | - * @param function 函数 | |
| 275 | + * @param function | |
| 243 | 276 | */ |
| 244 | 277 | protected void processFunction(Function function) { |
| 245 | 278 | ExpressionList parameters = function.getParameters(); |
| ... | ... | @@ -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 | 300 | SubSelect subSelect = (SubSelect) fromItem; |
| 271 | 301 | if (subSelect.getSelectBody() != null) { |
| 272 | 302 | processSelectBody(subSelect.getSelectBody()); |
| 273 | 303 | } |
| 274 | 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 | 306 | } else if (fromItem instanceof LateralSubSelect) { |
| 277 | 307 | LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; |
| 278 | 308 | if (lateralSubSelect.getSubSelect() != null) { |
| ... | ... | @@ -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 | 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 | 353 | //对于 on 表达式写在最后的 join,需要记录下前面多个 on 的表名 |
| 294 | - Deque<Table> tables = new LinkedList<>(); | |
| 354 | + Deque<List<Table>> onTableDeque = new LinkedList<>(); | |
| 295 | 355 | for (Join join : joins) { |
| 296 | 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 | 402 | // 获取 join 尾缀的 on 表达式列表 |
| 301 | 403 | Collection<Expression> originOnExpressions = join.getOnExpressions(); |
| 302 | 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 | 410 | continue; |
| 306 | 411 | } |
| 307 | - tables.push(fromTable); | |
| 412 | + // 表名压栈,忽略的表压入 null,以便后续不处理 | |
| 413 | + onTableDeque.push(onTables); | |
| 308 | 414 | // 尾缀多个 on 表达式的时候统一处理 |
| 309 | 415 | if (originOnExpressions.size() > 1) { |
| 310 | 416 | Collection<Expression> onExpressions = new LinkedList<>(); |
| 311 | 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 | 425 | join.setOnExpressions(onExpressions); |
| 316 | 426 | } |
| 427 | + leftTable = joinTable; | |
| 317 | 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 | 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 | 478 | if (currentExpression == null) { |
| 348 | - return equalsTo; | |
| 479 | + return dataPermissionExpression; | |
| 349 | 480 | } |
| 350 | - // 如果表达式为 Or,则需要 (currentExpression) AND equalsTo | |
| 481 | + // ① 如果表达式为 Or,则需要 (currentExpression) AND dataPermissionExpression | |
| 351 | 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 | 46 | |
| 47 | 47 | @Override |
| 48 | 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 | 50 | "t_user", "t_role"); // 满足自己的单元测试 |
| 51 | 51 | } |
| 52 | 52 | |
| ... | ... | @@ -84,30 +84,30 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest |
| 84 | 84 | @Test |
| 85 | 85 | void delete() { |
| 86 | 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 | 90 | @Test |
| 91 | 91 | void update() { |
| 92 | 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 | 96 | @Test |
| 97 | 97 | void selectSingle() { |
| 98 | 98 | // 单表 |
| 99 | 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 | 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 | 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 | 108 | /* not */ |
| 109 | 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 | 113 | @Test |
| ... | ... | @@ -167,10 +167,12 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest |
| 167 | 167 | assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)", |
| 168 | 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 | 172 | assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)", |
| 172 | 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 | 177 | assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)", |
| 176 | 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 | 206 | "SELECT * FROM entity e " + |
| 205 | 207 | "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + |
| 206 | 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 | 219 | @Test |
| ... | ... | @@ -212,17 +222,125 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest |
| 212 | 222 | assertSql("SELECT * FROM entity e " + |
| 213 | 223 | "right join entity1 e1 on e1.id = e.id", |
| 214 | 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 | 234 | assertSql("SELECT * FROM entity e " + |
| 219 | 235 | "right join entity1 e1 on e1.id = e.id " + |
| 220 | 236 | "WHERE e.id = ? OR e.name = ?", |
| 221 | 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 | 344 | @Test |
| 227 | 345 | void selectLeftJoinMultipleTrailingOn() { |
| 228 | 346 | // 多个 on 尾缀的 |
| ... | ... | @@ -256,51 +374,97 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest |
| 256 | 374 | "inner join entity1 e1 on e1.id = e.id " + |
| 257 | 375 | "WHERE e.id = ? OR e.name = ?", |
| 258 | 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 | 380 | assertSql("SELECT * FROM entity e " + |
| 263 | 381 | "inner join entity1 e1 on e1.id = e.id " + |
| 264 | 382 | "WHERE (e.id = ? OR e.name = ?)", |
| 265 | 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 | 433 | @Test |
| 278 | 434 | void selectWithAs() { |
| 279 | 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 | 446 | private void assertSql(String sql, String targetSql) { |
| 284 | 447 | assertEquals(targetSql, interceptor.parserSingle(sql, null)); |
| 285 | 448 | } |
| 286 | 449 | |
| 450 | + | |
| 287 | 451 | // ========== 额外的测试 ========== |
| 288 | 452 | |
| 289 | 453 | @Test |
| 290 | 454 | public void testSelectSingle() { |
| 291 | 455 | // 单表 |
| 292 | 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 | 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 | 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 | 465 | /* not */ |
| 302 | 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 | 470 | @Test |
| ... | ... | @@ -329,16 +493,16 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest |
| 329 | 493 | "right join t_role e1 on e1.id = e.id " + |
| 330 | 494 | "WHERE e.id = ? OR e.name = ?", |
| 331 | 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 | 499 | // 条件 e.id = ? OR e.name = ? 带括号 |
| 336 | 500 | assertSql("SELECT * FROM t_user e " + |
| 337 | 501 | "right join t_role e1 on e1.id = e.id " + |
| 338 | 502 | "WHERE (e.id = ? OR e.name = ?)", |
| 339 | 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 | 508 | @Test |
| ... | ... | @@ -348,23 +512,22 @@ public class DataPermissionDatabaseInterceptorTest2 extends BaseMockitoUnitTest |
| 348 | 512 | "inner join entity1 e1 on e1.id = e.id " + |
| 349 | 513 | "WHERE e.id = ? OR e.name = ?", |
| 350 | 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 | 518 | // 条件 e.id = ? OR e.name = ? 带括号 |
| 355 | 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 | 521 | "WHERE (e.id = ? OR e.name = ?)", |
| 358 | 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 | 27 | /** |
| 28 | 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 | 31 | Duration.ofMinutes(1L), // 过期时间 1 分钟 |
| 32 | 32 | new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() { |
| 33 | 33 | |
| ... | ... | @@ -41,7 +41,7 @@ public class DictFrameworkUtils { |
| 41 | 41 | /** |
| 42 | 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 | 45 | Duration.ofMinutes(1L), // 过期时间 1 分钟 |
| 46 | 46 | new CacheLoader<KeyValue<String, String>, DictDataRespDTO>() { |
| 47 | 47 | |
| ... | ... | @@ -59,12 +59,12 @@ public class DictFrameworkUtils { |
| 59 | 59 | |
| 60 | 60 | @SneakyThrows |
| 61 | 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 | 65 | @SneakyThrows |
| 66 | 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 | 52 | <dependency> |
| 53 | 53 | <groupId>com.alipay.sdk</groupId> |
| 54 | 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 | 62 | </dependency> |
| 57 | 63 | <dependency> |
| 58 | 64 | <groupId>com.github.binarywang</groupId> |
| 59 | 65 | <artifactId>weixin-java-pay</artifactId> |
| 60 | - <version>4.1.9.B</version> | |
| 66 | + <version>4.3.8.B</version> | |
| 61 | 67 | </dependency> |
| 62 | 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 | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl; |
| 2 | 2 | |
| 3 | -import cn.hutool.extra.validation.ValidationUtil; | |
| 4 | 3 | import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping; |
| 5 | 4 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 6 | 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 | 9 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayRefundUnifiedRespDTO; |
| 11 | 10 | import lombok.extern.slf4j.Slf4j; |
| 12 | 11 | |
| 12 | +import javax.validation.Validation; | |
| 13 | + | |
| 13 | 14 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 14 | 15 | |
| 15 | 16 | /** |
| ... | ... | @@ -79,7 +80,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen |
| 79 | 80 | |
| 80 | 81 | @Override |
| 81 | 82 | public final PayCommonResult<?> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |
| 82 | - ValidationUtil.validate(reqDTO); | |
| 83 | + Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); | |
| 83 | 84 | // 执行短信发送 |
| 84 | 85 | PayCommonResult<?> result; |
| 85 | 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 | 53 | "lrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZ" + |
| 54 | 54 | "ikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); |
| 55 | 55 | |
| 56 | - // TODO @tina:= 前后要有空格哈 | |
| 57 | 56 | @InjectMocks |
| 58 | - AlipayQrPayClient client=new AlipayQrPayClient(10L,config); | |
| 57 | + AlipayQrPayClient client = new AlipayQrPayClient(10L,config); | |
| 59 | 58 | |
| 60 | 59 | @Mock |
| 61 | 60 | private DefaultAlipayClient defaultAlipayClient; | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml
| ... | ... | @@ -35,12 +35,12 @@ |
| 35 | 35 | <dependency> |
| 36 | 36 | <groupId>com.github.binarywang</groupId> |
| 37 | 37 | <artifactId>wx-java-mp-spring-boot-starter</artifactId> |
| 38 | - <version>4.3.4.B</version> | |
| 38 | + <version>4.3.8.B</version> | |
| 39 | 39 | </dependency> |
| 40 | 40 | <dependency> |
| 41 | 41 | <groupId>com.github.binarywang</groupId> |
| 42 | 42 | <artifactId>wx-java-miniapp-spring-boot-starter</artifactId> |
| 43 | - <version>4.3.4.B</version> | |
| 43 | + <version>4.3.8.B</version> | |
| 44 | 44 | </dependency> |
| 45 | 45 | <!-- TODO 芋艿:清理 --> |
| 46 | 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
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
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 | 16 | */ |
| 17 | 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 | 21 | @Override |
| 22 | 22 | protected Object parse(String json) { |
| 23 | - return JsonUtils.parseObject(json, typeReference); | |
| 23 | + return JsonUtils.parseObject(json, TYPE_REFERENCE); | |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 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 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.SortingField; |
| 6 | 6 | import com.baomidou.mybatisplus.core.metadata.OrderItem; |
| 7 | +import com.baomidou.mybatisplus.core.toolkit.StringPool; | |
| 7 | 8 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
| 8 | 9 | import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; |
| 9 | 10 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| ... | ... | @@ -78,7 +79,10 @@ public class MyBatisUtils { |
| 78 | 79 | * @return Column 对象 |
| 79 | 80 | */ |
| 80 | 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 | 11 | /** |
| 12 | 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 | 16 | public static void add(RedisKeyDefine define) { |
| 17 | - defines.add(define); | |
| 17 | + DEFINES.add(define); | |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | public static List<RedisKeyDefine> list() { |
| 21 | - return defines; | |
| 21 | + return DEFINES; | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 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 | 81 | |
| 82 | 82 | /** |
| 83 | 83 | * 配置 URL 的安全配置 |
| 84 | - * | |
| 84 | + * <p> | |
| 85 | 85 | * anyRequest | 匹配所有请求路径 |
| 86 | 86 | * access | SpringEl表达式结果为true时可以访问 |
| 87 | 87 | * anonymous | 匿名可以访问 |
| ... | ... | @@ -109,8 +109,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap |
| 109 | 109 | .headers().frameOptions().disable().and() |
| 110 | 110 | // 一堆自定义的 Spring Security 处理器 |
| 111 | 111 | .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) |
| 112 | - .accessDeniedHandler(accessDeniedHandler); | |
| 113 | - // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高 | |
| 112 | + .accessDeniedHandler(accessDeniedHandler); | |
| 113 | + // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高 | |
| 114 | 114 | |
| 115 | 115 | // 获得 @PermitAll 带来的 URL 列表,免登录 |
| 116 | 116 | Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations(); |
| ... | ... | @@ -118,23 +118,25 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap |
| 118 | 118 | httpSecurity |
| 119 | 119 | // ①:全局共享规则 |
| 120 | 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 | 135 | .and().authorizeRequests(registry -> // 下面,循环设置自定义规则 |
| 134 | 136 | authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry))) |
| 135 | 137 | // ③:兜底规则,必须认证 |
| 136 | 138 | .authorizeRequests() |
| 137 | - .anyRequest().authenticated() | |
| 139 | + .anyRequest().authenticated() | |
| 138 | 140 | ; |
| 139 | 141 | |
| 140 | 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 | 17 | /** |
| 18 | 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 | 22 | @Override |
| 23 | 23 | public void clearContext() { |
| 24 | - contextHolder.remove(); | |
| 24 | + CONTEXT_HOLDER.remove(); | |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | @Override |
| 28 | 28 | public SecurityContext getContext() { |
| 29 | - SecurityContext ctx = contextHolder.get(); | |
| 29 | + SecurityContext ctx = CONTEXT_HOLDER.get(); | |
| 30 | 30 | if (ctx == null) { |
| 31 | 31 | ctx = createEmptyContext(); |
| 32 | - contextHolder.set(ctx); | |
| 32 | + CONTEXT_HOLDER.set(ctx); | |
| 33 | 33 | } |
| 34 | 34 | return ctx; |
| 35 | 35 | } |
| ... | ... | @@ -37,7 +37,7 @@ public class TransmittableThreadLocalSecurityContextHolderStrategy implements Se |
| 37 | 37 | @Override |
| 38 | 38 | public void setContext(SecurityContext context) { |
| 39 | 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 | 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 | 57 | templateParams.put("taskName", reqDTO.getTaskName()); |
| 58 | 58 | templateParams.put("startUserNickname", reqDTO.getStartUserNickname()); |
| 59 | 59 | templateParams.put("detailUrl", getProcessInstanceDetailUrl(reqDTO.getProcessInstanceId())); |
| 60 | - smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getStartUserId(), | |
| 60 | + smsSendApi.sendSingleSmsToAdmin(BpmMessageConvert.INSTANCE.convert(reqDTO.getAssigneeUserId(), | |
| 61 | 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 | 154 | // 构建 CodegenColumnDO 数组,只同步新增的字段 |
| 155 | 155 | List<CodegenColumnDO> codegenColumns = codegenColumnMapper.selectListByTableId(tableId); |
| 156 | 156 | Set<String> codegenColumnNames = CollectionUtils.convertSet(codegenColumns, CodegenColumnDO::getColumnName); |
| 157 | - // 移除已经存在的字段 | |
| 158 | - tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName())); | |
| 159 | 157 | // 计算需要删除的字段 |
| 160 | 158 | Set<String> tableFieldNames = CollectionUtils.convertSet(tableFields, TableField::getName); |
| 161 | 159 | Set<Long> deleteColumnIds = codegenColumns.stream().filter(column -> !tableFieldNames.contains(column.getColumnName())) |
| 162 | 160 | .map(CodegenColumnDO::getId).collect(Collectors.toSet()); |
| 161 | + // 移除已经存在的字段 | |
| 162 | + tableFields.removeIf(column -> codegenColumnNames.contains(column.getColumnName())); | |
| 163 | 163 | if (CollUtil.isEmpty(tableFields) && CollUtil.isEmpty(deleteColumnIds)) { |
| 164 | 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 | 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 | 35 | MapUtil.<String, CodegenColumnListConditionEnum>builder() |
| 36 | 36 | .put("name", CodegenColumnListConditionEnum.LIKE) |
| 37 | 37 | .put("time", CodegenColumnListConditionEnum.BETWEEN) |
| ... | ... | @@ -42,7 +42,7 @@ public class CodegenBuilder { |
| 42 | 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 | 46 | MapUtil.<String, CodegenColumnHtmlTypeEnum>builder() |
| 47 | 47 | .put("status", CodegenColumnHtmlTypeEnum.RADIO) |
| 48 | 48 | .put("sex", CodegenColumnHtmlTypeEnum.RADIO) |
| ... | ... | @@ -143,7 +143,7 @@ public class CodegenBuilder { |
| 143 | 143 | column.setListOperation(!LIST_OPERATION_EXCLUDE_COLUMN.contains(column.getJavaField()) |
| 144 | 144 | && !column.getPrimaryKey()); // 对于主键,列表过滤不需要传递 |
| 145 | 145 | // 处理 listOperationCondition 字段 |
| 146 | - columnListOperationConditionMappings.entrySet().stream() | |
| 146 | + COLUMN_LIST_OPERATION_CONDITION_MAPPINGS.entrySet().stream() | |
| 147 | 147 | .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) |
| 148 | 148 | .findFirst().ifPresent(entry -> column.setListOperationCondition(entry.getValue().getCondition())); |
| 149 | 149 | if (column.getListOperationCondition() == null) { |
| ... | ... | @@ -155,7 +155,7 @@ public class CodegenBuilder { |
| 155 | 155 | |
| 156 | 156 | private void processColumnUI(CodegenColumnDO column) { |
| 157 | 157 | // 基于后缀进行匹配 |
| 158 | - columnHtmlTypeMappings.entrySet().stream() | |
| 158 | + COLUMN_HTML_TYPE_MAPPINGS.entrySet().stream() | |
| 159 | 159 | .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) |
| 160 | 160 | .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType())); |
| 161 | 161 | // 如果是 Boolean 类型时,设置为 radio 类型. | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm
| ... | ... | @@ -96,7 +96,7 @@ |
| 96 | 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 | 100 | <el-form ref="form" :model="form" :rules="rules" label-width="80px"> |
| 101 | 101 | #foreach($column in $columns) |
| 102 | 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 | 5 | |
| 6 | 6 | #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") |
| 7 | 7 | // 查询${table.classComment}列表 |
| 8 | -export const getPostPageApi = async (params: ${simpleClassName}PageReqVO) => { | |
| 8 | +export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => { | |
| 9 | 9 | return await request.get({ url: '${baseURL}/page', params }) |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | 12 | // 查询${table.classComment}详情 |
| 13 | -export const getPostApi = async (id: number) => { | |
| 13 | +export const get${simpleClassName}Api = async (id: number) => { | |
| 14 | 14 | return await request.get({ url: '${baseURL}/get?id=' + id }) |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | 17 | // 新增${table.classComment} |
| 18 | -export const createPostApi = async (data: ${simpleClassName}VO) => { | |
| 18 | +export const create${simpleClassName}Api = async (data: ${simpleClassName}VO) => { | |
| 19 | 19 | return await request.post({ url: '${baseURL}/create', data }) |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | // 修改${table.classComment} |
| 23 | -export const updatePostApi = async (data: ${simpleClassName}VO) => { | |
| 23 | +export const update${simpleClassName}Api = async (data: ${simpleClassName}VO) => { | |
| 24 | 24 | return await request.put({ url: '${baseURL}/update', data }) |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | // 删除${table.classComment} |
| 28 | -export const deletePostApi = async (id: number) => { | |
| 28 | +export const delete${simpleClassName}Api = async (id: number) => { | |
| 29 | 29 | return await request.delete({ url: '${baseURL}/delete?id=' + id }) |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | // 导出${table.classComment} Excel |
| 33 | -export const exportPostApi = async (params: ${simpleClassName}ExcelReqVO) => { | |
| 33 | +export const export${simpleClassName}Api = async (params: ${simpleClassName}ExcelReqVO) => { | |
| 34 | 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 | 6 | import { useTable } from '@/hooks/web/useTable' |
| 7 | 7 | import { useI18n } from '@/hooks/web/useI18n' |
| 8 | 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 | 12 | const { t } = useI18n() // 国际化 |
| 13 | 13 | |
| 14 | 14 | // ========== 列表相关 ========== | ... | ... |
yudao-module-mall/pom.xml
| ... | ... | @@ -15,17 +15,18 @@ |
| 15 | 15 | <name>${project.artifactId}</name> |
| 16 | 16 | |
| 17 | 17 | <description> |
| 18 | - 商城大模块,由 product 商品、market 营销、trade 交易等组成 | |
| 18 | + 商城大模块,由 product 商品、market 营销、trade 交易 coupon等组成 | |
| 19 | 19 | </description> |
| 20 | 20 | <modules> |
| 21 | + <module>yudao-module-coupon-api</module> | |
| 22 | + <module>yudao-module-coupon-biz</module> | |
| 21 | 23 | <module>yudao-module-market-api</module> |
| 22 | 24 | <module>yudao-module-market-biz</module> |
| 23 | 25 | <module>yudao-module-product-api</module> |
| 24 | 26 | <module>yudao-module-product-biz</module> |
| 25 | 27 | <module>yudao-module-trade-api</module> |
| 26 | 28 | <module>yudao-module-trade-biz</module> |
| 27 | - <module>yudao-module-coupon-api</module> | |
| 28 | - <module>yudao-module-coupon-biz</module> | |
| 29 | + | |
| 29 | 30 | </modules> |
| 30 | 31 | |
| 31 | 32 | </project> | ... | ... |
yudao-module-mall/yudao-module-coupon-api/pom.xml
| ... | ... | @@ -23,6 +23,13 @@ |
| 23 | 23 | <groupId>cn.iocoder.boot</groupId> |
| 24 | 24 | <artifactId>yudao-common</artifactId> |
| 25 | 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 | 33 | </dependencies> |
| 27 | 34 | |
| 28 | 35 | </project> |
| 29 | 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
yudao-module-mall/yudao-module-coupon-api/src/main/java/cn/iocoder/yudao/module/CouponTemplete/enums/CouponFetchTypeEnum.java
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 | 6 | |
| 7 | 7 | |
| 8 | 8 | /** |
| 9 | - * 优惠券 - 优惠券类型 | |
| 9 | + * 优惠券 - 优惠叠加类型 | |
| 10 | 10 | * |
| 11 | 11 | * @author Sin |
| 12 | 12 | */ |
| 13 | 13 | @RequiredArgsConstructor |
| 14 | 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 | 6 | |
| 7 | 7 | |
| 8 | 8 | /** |
| 9 | - * 优惠券 - 优惠券类型 | |
| 9 | + * 优惠券 - 优惠券状态类型 | |
| 10 | 10 | * |
| 11 | 11 | * @author Sin |
| 12 | 12 | */ |
| ... | ... | @@ -14,9 +14,9 @@ import lombok.RequiredArgsConstructor; |
| 14 | 14 | @Getter |
| 15 | 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 | 6 | |
| 7 | 7 | |
| 8 | 8 | /** |
| 9 | - * 优惠券 - 优惠券类型 | |
| 9 | + * 优惠券使用类型 - 优惠券使用类型类型 | |
| 10 | 10 | * |
| 11 | 11 | * @author Sin |
| 12 | 12 | */ |
| ... | ... | @@ -18,11 +18,11 @@ public enum CouponUseLimitEnum { |
| 18 | 18 | NO_LIMIT(2,"有门槛"),; |
| 19 | 19 | |
| 20 | 20 | /** |
| 21 | - * 优惠券类型 | |
| 21 | + * 优惠券使用类型 | |
| 22 | 22 | */ |
| 23 | 23 | private final Integer type; |
| 24 | 24 | /** |
| 25 | - * 优惠券类型名 | |
| 25 | + * 优惠券使用类型名 | |
| 26 | 26 | */ |
| 27 | 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
yudao-module-mall/yudao-module-coupon-biz/pom.xml
| ... | ... | @@ -3,19 +3,18 @@ |
| 3 | 3 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 4 | 4 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| 5 | 5 | <parent> |
| 6 | - <artifactId>yudao-module-mall</artifactId> | |
| 7 | 6 | <groupId>cn.iocoder.boot</groupId> |
| 7 | + <artifactId>yudao-module-mall</artifactId> | |
| 8 | 8 | <version>${revision}</version> |
| 9 | 9 | </parent> |
| 10 | 10 | <modelVersion>4.0.0</modelVersion> |
| 11 | - <artifactId>yudao-module-coupon-biz</artifactId> | |
| 12 | 11 | <packaging>jar</packaging> |
| 13 | - | |
| 12 | + <artifactId>yudao-module-coupon-biz</artifactId> | |
| 14 | 13 | |
| 15 | 14 | <name>${project.artifactId}</name> |
| 15 | + | |
| 16 | 16 | <description> |
| 17 | - trade 模块,主要实现交易相关功能 | |
| 18 | - 例如:订单、退款、购物车等功能。 | |
| 17 | + coupon模块,主要负责优惠券的一些业务,含发布优惠券模板,分发优惠券等 | |
| 19 | 18 | </description> |
| 20 | 19 | |
| 21 | 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 | 21 | |
| 22 | 22 | @Api(tags = "管理后台 - 优惠券") |
| 23 | 23 | @RestController |
| 24 | -@RequestMapping("/coupon/coupon/") | |
| 24 | +@RequestMapping("/coupon/item") | |
| 25 | 25 | @Validated |
| 26 | 26 | public class CouponController { |
| 27 | 27 | |
| ... | ... | @@ -69,7 +69,7 @@ public class CouponController { |
| 69 | 69 | |
| 70 | 70 | @GetMapping("/list") |
| 71 | 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 | 73 | @PreAuthorize("@ss.hasPermission('coupon::query')") |
| 74 | 74 | public CommonResult<List<CouponRespVO>> getList(@RequestParam("ids") Collection<Long> ids) { |
| 75 | 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 | 68 | private Boolean whetherForbidPreference; |
| 69 | 69 | |
| 70 | 70 | @ApiModelProperty(value = "是否开启过期提醒0-不开启 1-开启", required = true) |
| 71 | - @NotNull(message = "是否开启过期提醒0-不开启 1-开启不能为空") | |
| 71 | + @NotNull(message = "是否开启过期提醒0-不开启 1-开启") | |
| 72 | 72 | private Boolean whetherExpireNotice; |
| 73 | 73 | |
| 74 | 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 | 3 | import lombok.*; |
| 4 | 4 | import java.util.*; |
| ... | ... | @@ -34,7 +34,7 @@ public class CouponTempleteBaseVO { |
| 34 | 34 | |
| 35 | 35 | @ApiModelProperty(value = "适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用", required = true) |
| 36 | 36 | @NotNull(message = "适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用不能为空") |
| 37 | - private Boolean goodsType; | |
| 37 | + private Integer goodsType; | |
| 38 | 38 | |
| 39 | 39 | @ApiModelProperty(value = "适用商品id") |
| 40 | 40 | private String productIds; |
| ... | ... | @@ -104,7 +104,7 @@ public class CouponTempleteBaseVO { |
| 104 | 104 | |
| 105 | 105 | |
| 106 | 106 | @ApiModelProperty(value = "领取是否无限制0-否 1是", required = true) |
| 107 | - @NotNull(message = "是否无限制0-否 1是 不能为空") | |
| 107 | + @NotNull(message = "是否无限制0-否 1是") | |
| 108 | 108 | private Boolean whetherLimitless; |
| 109 | 109 | |
| 110 | 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
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 | 3 | import lombok.*; |
| 4 | 4 | import java.util.*; |
| ... | ... | @@ -39,7 +39,7 @@ public class CouponTempleteExcelVO { |
| 39 | 39 | private Integer usedCount; |
| 40 | 40 | |
| 41 | 41 | @ExcelProperty("适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用") |
| 42 | - private Boolean goodsType; | |
| 42 | + private Integer goodsType; | |
| 43 | 43 | |
| 44 | 44 | @ExcelProperty("适用商品id") |
| 45 | 45 | private String productIds; |
| ... | ... | @@ -66,7 +66,7 @@ public class CouponTempleteExcelVO { |
| 66 | 66 | private BigDecimal maxMoney; |
| 67 | 67 | |
| 68 | 68 | @ExcelProperty("过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期") |
| 69 | - private Boolean validityType; | |
| 69 | + private Integer validityType; | |
| 70 | 70 | |
| 71 | 71 | @ExcelProperty("使用开始日期 过期类型1时必填") |
| 72 | 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
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
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
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
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 | 4 | |
| 5 | 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 | 11 | import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; |
| 12 | 12 | import org.mapstruct.Mapper; |
| 13 | 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 | 57 | /** |
| 58 | 58 | * 适用商品类型1-全部商品可用;2-指定商品可用;3-指定商品不可用 |
| 59 | 59 | */ |
| 60 | - private Boolean goodsType; | |
| 60 | + private Integer goodsType; | |
| 61 | 61 | /** |
| 62 | 62 | * 适用商品id |
| 63 | 63 | */ |
| ... | ... | @@ -93,7 +93,7 @@ public class CouponTempleteDO extends BaseDO { |
| 93 | 93 | /** |
| 94 | 94 | * 过期类型1-时间范围过期 2-领取之日固定日期后过期 3-领取次日固定日期后过期 |
| 95 | 95 | */ |
| 96 | - private Boolean validityType; | |
| 96 | + private Integer validityType; | |
| 97 | 97 | /** |
| 98 | 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 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 7 | 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 | 10 | import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; |
| 11 | 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
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 | 2 | |
| 3 | 3 | import java.util.*; |
| 4 | 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 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.CouponTemplete.enums.CouponTypeEnum; |
| 4 | 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 | 9 | import cn.iocoder.yudao.module.coupon.convert.CouponTemplete.CouponTempleteConvert; |
| 10 | 10 | import cn.iocoder.yudao.module.coupon.dal.dataobject.CouponTemplete.CouponTempleteDO; |
| 11 | 11 | import cn.iocoder.yudao.module.coupon.dal.mysql.CouponTemplete.CouponTempleteMapper; |
| 12 | -import cn.iocoder.yudao.module.coupon.service.CouponTemplete.CouponTempleteService; | |
| 13 | 12 | import org.springframework.stereotype.Service; |
| 14 | 13 | import javax.annotation.Resource; |
| 15 | 14 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -41,7 +40,7 @@ public class CouponTempleteServiceImpl implements CouponTempleteService { |
| 41 | 40 | /* 验证类型、判断必填*/ |
| 42 | 41 | checkCouponType(createReqVO); |
| 43 | 42 | |
| 44 | - /*todo 验证过期类型、判断必填*/ | |
| 43 | + /*验证过期类型、判断必填*/ | |
| 45 | 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 | 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 | 27 | private List<Promotion> promotions; |
| 33 | 28 | |
| ... | ... | @@ -40,13 +35,13 @@ public class PriceCalculateRespDTO { |
| 40 | 35 | /** |
| 41 | 36 | * 商品原价(总),单位:分 |
| 42 | 37 | * |
| 43 | - * 基于 {@link Item#getTotalOriginalPrice()} 求和 | |
| 38 | + * 基于 {@link OrderItem#getTotalOriginalPrice()} 求和 | |
| 44 | 39 | */ |
| 45 | 40 | private Integer skuOriginalPrice; |
| 46 | 41 | /** |
| 47 | 42 | * 商品优惠(总),单位:分 |
| 48 | 43 | * |
| 49 | - * 基于 {@link Item#getTotalPromotionPrice()} 求和 | |
| 44 | + * 基于 {@link OrderItem#getTotalPromotionPrice()} 求和 | |
| 50 | 45 | */ |
| 51 | 46 | private Integer skuPromotionPrice; |
| 52 | 47 | /** |
| ... | ... | @@ -69,6 +64,10 @@ public class PriceCalculateRespDTO { |
| 69 | 64 | */ |
| 70 | 65 | // * - {@link #couponPrice} // TODO 芋艿:靠营销表记录 |
| 71 | 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 | 84 | } |
| 86 | 85 | |
| 87 | 86 | /** |
| 88 | - * 商品 SKU | |
| 87 | + * 订单商品 SKU | |
| 89 | 88 | */ |
| 90 | 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 | 145 | */ |
| 142 | 146 | private Long id; |
| 143 | 147 | /** |
| 148 | + * 营销名字 | |
| 149 | + */ | |
| 150 | + private String name; | |
| 151 | + /** | |
| 144 | 152 | * 营销类型 |
| 145 | 153 | * |
| 146 | 154 | * 枚举 {@link PromotionTypeEnum} |
| ... | ... | @@ -153,10 +161,6 @@ public class PriceCalculateRespDTO { |
| 153 | 161 | */ |
| 154 | 162 | private Integer level; |
| 155 | 163 | /** |
| 156 | - * 匹配的商品 SKU 数组 | |
| 157 | - */ | |
| 158 | - private List<Item> items; | |
| 159 | - /** | |
| 160 | 164 | * 计算时的原价(总),单位:分 |
| 161 | 165 | */ |
| 162 | 166 | private Integer totalOriginalPrice; |
| ... | ... | @@ -165,6 +169,13 @@ public class PriceCalculateRespDTO { |
| 165 | 169 | */ |
| 166 | 170 | private Integer totalPromotionPrice; |
| 167 | 171 | /** |
| 172 | + * 匹配的商品 SKU 数组 | |
| 173 | + */ | |
| 174 | + private List<PromotionItem> items; | |
| 175 | + | |
| 176 | + // ========== 匹配情况 ========== | |
| 177 | + | |
| 178 | + /** | |
| 168 | 179 | * 是否满足优惠条件 |
| 169 | 180 | */ |
| 170 | 181 | private Boolean meet; |
| ... | ... | @@ -176,26 +187,26 @@ public class PriceCalculateRespDTO { |
| 176 | 187 | */ |
| 177 | 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 | 24 | <artifactId>yudao-module-market-api</artifactId> |
| 25 | 25 | <version>${revision}</version> |
| 26 | 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 | 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; | ... | ... |