diff --git a/README.md b/README.md index aa81ed5e6..80b60d900 100644 --- a/README.md +++ b/README.md @@ -35,14 +35,15 @@ * 工作流使用 Flowable,支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式 * 高效率开发,使用代码生成器可以一键生成前后端代码 + 单元测试 + Swagger 接口文档 + Validator 参数校验 * 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款 -* 集成阿里云、腾讯云、云片等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务 +* 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务 * 集成报表设计器,支持数据报表、图形报表、打印设计等 -| 项目名 | 说明 | 传说门 | -|--------------------|------------------------|-------------------------------------------------------------------------------------------------------------------------------------| -| `ruoyi-vue-pro` | Spring Boot 多模块 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro)**     [Github](https://github.com/YunaiV/ruoyi-vue-pro) | -| `yudao-cloud` | Spring Cloud 微服务 | **[Gitee](https://gitee.com/zhijiantianya/yudao-cloud)**     [Github](https://github.com/YunaiV/yudao-cloud) | +| 项目名 | 说明 | 传送门 | +|--------------------|------------------------|-----------------------------------------------------------------------------------------------------------------------------------| +| `ruoyi-vue-pro` | Spring Boot 多模块 | **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro)**     [Github](https://github.com/YunaiV/ruoyi-vue-pro) | +| `yudao-cloud` | Spring Cloud 微服务 | **[Gitee](https://gitee.com/zhijiantianya/yudao-cloud)**     [Github](https://github.com/YunaiV/yudao-cloud) | | `Spring-Boot-Labs` | Spring Boot & Cloud 入门 | **[Gitee](https://gitee.com/zhijiantianya/SpringBoot-Labs)**     [Github](https://github.com/YunaiV/SpringBoot-Labs) | + | `ruoyi-vue-pro-mini` | 精简版 移除工作流 支付等模块| **[Gitee](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/mini)** | ## 😎 开源协议 @@ -90,12 +91,12 @@ | 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 | | 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 | | | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | -| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 | +| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 | | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | | ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 | | 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 | | | 通知公告 | 系统通知公告信息发布维护 | -| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 | +| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 | | 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 | ### 工作流程 @@ -168,42 +169,42 @@ ps:核心功能已经实现,正在对接微信小程序中... ## 🐨 技术栈 -| 项目 | 说明 | -|-----------------------|--------------------| -| `yudao-dependencies` | Maven 依赖版本管理 | -| `yudao-framework` | Java 框架拓展 | -| `yudao-server` | 管理后台 + 用户 APP 的服务端 | -| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 | -| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 | -| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 | -| `yudao-ui-app` | 用户 APP 的 UI 界面 | -| `yudao-module-system` | 系统功能的 Module 模块 | -| `yudao-module-member` | 会员中心的 Module 模块 | -| `yudao-module-infra` | 基础设施的 Module 模块 | -| `yudao-module-tool` | 研发工具的 Module 模块 | -| `yudao-module-bpm` | 工作流程的 Module 模块 | -| `yudao-module-pay` | 支付系统的 Module 模块 | +| 项目 | 说明 | +|-------------------------|-----------------------| +| `yudao-dependencies` | Maven 依赖版本管理 | +| `yudao-framework` | Java 框架拓展 | +| `yudao-server` | 管理后台 + 用户 APP 的服务端 | +| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 | +| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 | +| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 | +| `yudao-ui-app` | 用户 APP 的 UI 界面 | +| `yudao-module-system` | 系统功能的 Module 模块 | +| `yudao-module-member` | 会员中心的 Module 模块 | +| `yudao-module-infra` | 基础设施的 Module 模块 | +| `yudao-module-tool` | 研发工具的 Module 模块 | +| `yudao-module-bpm` | 工作流程的 Module 模块 | +| `yudao-module-pay` | 支付系统的 Module 模块 | ### 后端 | 框架 | 说明 | 版本 | 学习指南 | |---------------------------------------------------------------------------------------------|-----------------------|-------------|----------------------------------------------------------------| -| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.6.13 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | +| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.6 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | | -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.14 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | +| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.15 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | | [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | | [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | | -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.17.7 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.23 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.6.8 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.3 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | +| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | +| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | +| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | +| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | | [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.7.2 | [文档](https://doc.iocoder.cn/bpm/) | | [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | | [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.3 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | | [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) | -| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.6.9 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | +| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.9 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | | [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | | | [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.3.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) | | [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.24 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | @@ -212,23 +213,22 @@ ps:核心功能已经实现,正在对接微信小程序中... ### [管理后台 Vue2 前端](./yudao-ui-admin) -| 框架 | 说明 | 版本 | -|------------------------------------------------------------------------------|---------------|-------| -| [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.7.0 | -| [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案 | - | +| 框架 | 说明 | 版本 | +|------------------------------------------------------------------------------|---------------|--------| +| [Vue](https://cn.vuejs.org/index.html) | JavaScript 框架 | 2.7.14 | +| [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案 | - | ### [管理后台 Vue3 前端](./yudao-ui-admin-vue3) -| 框架 | 说明 | 版本 | -|----------------------------------------------------------------------|-----------------|--------| -| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.44 | -| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.2.3 | -| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.20 | -| [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.8.4 | -| [pinia](https://pinia.vuejs.org/) | vuex5 | 2.0.23 | -| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 | -| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 | -| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.0.0 | +| 框架 | 说明 | 版本 | +|----------------------------------------------------------------------|:------------:|:------:| +| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.45 | +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.3 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.27 | +| [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.9.4 | +| [pinia](https://pinia.vuejs.org/) | vuex5 | 2.0.28 | +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 | +| [vxe-table](https://vxetable.cn/) | vue最强表单 | 4.3.7 | ### [管理后台 uni-app 跨端](./yudao-ui-admin-uniapp) @@ -242,15 +242,15 @@ ps:核心功能已经实现,正在对接微信小程序中... ### 系统功能 | 模块 | biu | biu | biu | -|----------|--------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------| +|------------|--------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------| | 登录 & 首页 | ![登录](https://static.iocoder.cn/images/ruoyi-vue-pro/登录.jpg?imageView2/2/format/webp/w/1280) | ![首页](https://static.iocoder.cn/images/ruoyi-vue-pro/首页.jpg?imageView2/2/format/webp/w/1280) | ![个人中心](https://static.iocoder.cn/images/ruoyi-vue-pro/个人中心.jpg?imageView2/2/format/webp/w/1280) | -| 用户 & 应用 | ![用户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/用户管理.jpg?imageView2/2/format/webp/w/1280) | ![令牌管理](https://static.iocoder.cn/images/ruoyi-vue-pro/令牌管理.jpg?imageView2/2/format/webp/w/1280) | ![应用管理](https://static.iocoder.cn/images/ruoyi-vue-pro/应用管理.jpg?imageView2/2/format/webp/w/1280) | +| 用户 & 应用 | ![用户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/用户管理.jpg?imageView2/2/format/webp/w/1280) | ![令牌管理](https://static.iocoder.cn/images/ruoyi-vue-pro/令牌管理.jpg?imageView2/2/format/webp/w/1280) | ![应用管理](https://static.iocoder.cn/images/ruoyi-vue-pro/应用管理.jpg?imageView2/2/format/webp/w/1280) | | 租户 & 套餐 | ![租户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/租户管理.jpg?imageView2/2/format/webp/w/1280) | ![租户套餐](https://static.iocoder.cn/images/ruoyi-vue-pro/租户套餐.png) | - | | 部门 & 岗位 | ![部门管理](https://static.iocoder.cn/images/ruoyi-vue-pro/部门管理.jpg?imageView2/2/format/webp/w/1280) | ![岗位管理](https://static.iocoder.cn/images/ruoyi-vue-pro/岗位管理.jpg?imageView2/2/format/webp/w/1280) | - | | 菜单 & 角色 | ![菜单管理](https://static.iocoder.cn/images/ruoyi-vue-pro/菜单管理.jpg?imageView2/2/format/webp/w/1280) | ![角色管理](https://static.iocoder.cn/images/ruoyi-vue-pro/角色管理.jpg?imageView2/2/format/webp/w/1280) | - | | 审计日志 | ![操作日志](https://static.iocoder.cn/images/ruoyi-vue-pro/操作日志.jpg?imageView2/2/format/webp/w/1280) | ![登录日志](https://static.iocoder.cn/images/ruoyi-vue-pro/登录日志.jpg?imageView2/2/format/webp/w/1280) | - | | 短信 | ![短信渠道](https://static.iocoder.cn/images/ruoyi-vue-pro/短信渠道.jpg?imageView2/2/format/webp/w/1280) | ![短信模板](https://static.iocoder.cn/images/ruoyi-vue-pro/短信模板.jpg?imageView2/2/format/webp/w/1280) | ![短信日志](https://static.iocoder.cn/images/ruoyi-vue-pro/短信日志.jpg?imageView2/2/format/webp/w/1280) | -| 字典 & 敏感词 | ![字典类型](https://static.iocoder.cn/images/ruoyi-vue-pro/字典类型.jpg?imageView2/2/format/webp/w/1280) | ![字典数据](https://static.iocoder.cn/images/ruoyi-vue-pro/字典数据.jpg?imageView2/2/format/webp/w/1280) | ![敏感词](https://static.iocoder.cn/images/ruoyi-vue-pro/敏感词.jpg?imageView2/2/format/webp/w/1280) | +| 字典 & 敏感词 | ![字典类型](https://static.iocoder.cn/images/ruoyi-vue-pro/字典类型.jpg?imageView2/2/format/webp/w/1280) | ![字典数据](https://static.iocoder.cn/images/ruoyi-vue-pro/字典数据.jpg?imageView2/2/format/webp/w/1280) | ![敏感词](https://static.iocoder.cn/images/ruoyi-vue-pro/敏感词.jpg?imageView2/2/format/webp/w/1280) | | 错误码 & 通知 | ![错误码管理](https://static.iocoder.cn/images/ruoyi-vue-pro/错误码管理.jpg?imageView2/2/format/webp/w/1280) | ![通知公告](https://static.iocoder.cn/images/ruoyi-vue-pro/通知公告.jpg?imageView2/2/format/webp/w/1280) | - | ### 工作流程 diff --git a/http-client.env.json b/http-client.env.json index d2ad9e7c2..78f3ead46 100644 --- a/http-client.env.json +++ b/http-client.env.json @@ -5,7 +5,7 @@ "adminTenentId": "1", "appApi": "http://127.0.0.1:48080/app-api", - "appToken": "test1", + "appToken": "test247", "appTenentId": "1" }, "gateway": { diff --git a/pom.xml b/pom.xml index a5cce914d..8f8f62990 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ yudao-module-system yudao-module-infra yudao-module-pay - yudao-module-mall + yudao-module-visualization yudao-example @@ -29,7 +29,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.6.4-snapshot + 1.6.5-snapshot 1.8 ${java.version} diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 6a25c70d4..39cb52afe 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80026 File Encoding : 65001 - Date: 29/07/2022 00:33:25 + Date: 20/12/2022 00:33:25 */ SET NAMES utf8mb4; @@ -300,7 +300,7 @@ CREATE TABLE `bpm_form` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义'; -- ---------------------------- -- Records of bpm_form @@ -329,7 +329,7 @@ CREATE TABLE `bpm_oa_leave` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 33 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表'; -- ---------------------------- -- Records of bpm_oa_leave @@ -359,7 +359,7 @@ CREATE TABLE `bpm_process_definition_ext` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 135 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n'; -- ---------------------------- -- Records of bpm_process_definition_ext @@ -389,7 +389,7 @@ CREATE TABLE `bpm_process_instance_ext` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 290 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展'; -- ---------------------------- -- Records of bpm_process_instance_ext @@ -415,7 +415,7 @@ CREATE TABLE `bpm_task_assign_rule` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 265 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表'; -- ---------------------------- -- Records of bpm_task_assign_rule @@ -444,7 +444,7 @@ CREATE TABLE `bpm_task_ext` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 341 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表'; -- ---------------------------- -- Records of bpm_task_ext @@ -469,7 +469,7 @@ CREATE TABLE `bpm_user_group` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 111 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组'; -- ---------------------------- -- Records of bpm_user_group @@ -504,7 +504,7 @@ CREATE TABLE `infra_api_access_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 35822 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; -- ---------------------------- -- Records of infra_api_access_log @@ -546,7 +546,7 @@ CREATE TABLE `infra_api_error_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 647 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -584,7 +584,7 @@ CREATE TABLE `infra_codegen_column` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1126 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; -- ---------------------------- -- Records of infra_codegen_column @@ -616,7 +616,7 @@ CREATE TABLE `infra_codegen_table` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 99 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; -- ---------------------------- -- Records of infra_codegen_table @@ -673,7 +673,7 @@ CREATE TABLE `infra_data_source_config` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '数据源配置表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '数据源配置表'; -- ---------------------------- -- Records of infra_data_source_config @@ -699,7 +699,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 93 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -753,7 +753,7 @@ CREATE TABLE `infra_file_content` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file_content @@ -781,13 +781,13 @@ CREATE TABLE `infra_job` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表'; -- ---------------------------- -- Records of infra_job -- ---------------------------- BEGIN; -INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2022-04-03 20:35:25', b'0'); +INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2022-04-03 20:35:25', b'0'); COMMIT; -- ---------------------------- @@ -811,7 +811,7 @@ CREATE TABLE `infra_job_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 25295 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; -- ---------------------------- -- Records of infra_job_log @@ -836,7 +836,7 @@ CREATE TABLE `infra_test_demo` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 108 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of infra_test_demo @@ -866,7 +866,7 @@ CREATE TABLE `member_user` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `uk_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号' -) ENGINE = InnoDB AUTO_INCREMENT = 248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户'; -- ---------------------------- -- Records of member_user @@ -893,7 +893,7 @@ CREATE TABLE `pay_app` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付应用信息'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付应用信息'; -- ---------------------------- -- Records of pay_app @@ -921,7 +921,7 @@ CREATE TABLE `pay_channel` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付渠道\n'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付渠道\n'; -- ---------------------------- -- Records of pay_channel @@ -947,7 +947,7 @@ CREATE TABLE `pay_merchant` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付商户信息'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付商户信息'; -- ---------------------------- -- Records of pay_merchant @@ -972,7 +972,7 @@ CREATE TABLE `pay_notify_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 363051 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付通知 App 的日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付通知 App 的日志'; -- ---------------------------- -- Records of pay_notify_log @@ -1004,7 +1004,7 @@ CREATE TABLE `pay_notify_task` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 112 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商户支付、退款等的通知\n'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商户支付、退款等的通知\n'; -- ---------------------------- -- Records of pay_notify_task @@ -1048,7 +1048,7 @@ CREATE TABLE `pay_order` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 125 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n'; -- ---------------------------- -- Records of pay_order @@ -1077,7 +1077,7 @@ CREATE TABLE `pay_order_extension` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 124 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n'; -- ---------------------------- -- Records of pay_order_extension @@ -1166,8 +1166,6 @@ INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (107, '运维部门', 101, 5, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:33', b'0', 1); INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (108, '市场部门', 102, 1, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-02-16 08:35:45', b'0', 1); INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, '财务部门', 102, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:29', b'0', 1); -INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (110, '新部门', 0, 1, NULL, NULL, NULL, 0, '110', '2022-02-23 20:46:30', '110', '2022-02-23 20:46:30', b'0', 121); -INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (111, '顶级部门', 0, 1, NULL, NULL, NULL, 0, '113', '2022-03-07 21:44:50', '113', '2022-03-07 21:44:50', b'0', 122); COMMIT; -- ---------------------------- @@ -1245,7 +1243,6 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (62, 0, '未处理', '0', 'infra_api_error_log_process_status', 0, 'primary', '', NULL, '', '2021-02-26 07:07:19', '1', '2022-02-16 20:14:17', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (63, 1, '已处理', '1', 'infra_api_error_log_process_status', 0, 'success', '', NULL, '', '2021-02-26 07:07:26', '1', '2022-02-16 20:14:08', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (64, 2, '已忽略', '2', 'infra_api_error_log_process_status', 0, 'danger', '', NULL, '', '2021-02-26 07:07:34', '1', '2022-02-16 20:14:14', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (65, 1, '云片', 'YUN_PIAN', 'system_sms_channel_code', 0, 'success', '', NULL, '1', '2021-04-05 01:05:14', '1', '2022-02-16 10:09:55', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (66, 2, '阿里云', 'ALIYUN', 'system_sms_channel_code', 0, 'primary', '', NULL, '1', '2021-04-05 01:05:26', '1', '2022-02-16 10:09:52', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (67, 1, '验证码', '1', 'system_sms_template_type', 0, 'warning', '', NULL, '1', '2021-04-05 21:50:57', '1', '2022-02-16 12:48:30', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (68, 2, '通知', '2', 'system_sms_template_type', 0, 'primary', '', NULL, '1', '2021-04-05 21:51:08', '1', '2022-02-16 12:48:27', b'0'); @@ -1336,19 +1333,20 @@ COMMIT; -- Table structure for system_dict_type -- ---------------------------- DROP TABLE IF EXISTS `system_dict_type`; -CREATE TABLE `system_dict_type` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键', - `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典名称', - `type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典类型', - `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', - `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE +CREATE TABLE `system_dict_type`( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典名称', + `type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典类型', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted_time` datetime DEFAULT NULL COMMENT '删除时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `dict_type`(`type` ASC,`deleted_time` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 149 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- @@ -1414,7 +1412,7 @@ CREATE TABLE `system_error_code` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 5832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表'; -- ---------------------------- -- Records of system_error_code @@ -1443,7 +1441,7 @@ CREATE TABLE `system_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1670 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1762,7 +1760,7 @@ CREATE TABLE `system_oauth2_access_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 404 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -1789,7 +1787,7 @@ CREATE TABLE `system_oauth2_approve` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 79 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 批准表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 批准表'; -- ---------------------------- -- Records of system_oauth2_approve @@ -1855,7 +1853,7 @@ CREATE TABLE `system_oauth2_code` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 103 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 授权码表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 授权码表'; -- ---------------------------- -- Records of system_oauth2_code @@ -1882,7 +1880,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 295 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -1922,7 +1920,7 @@ CREATE TABLE `system_operate_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2764 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; -- ---------------------------- -- Records of system_operate_log @@ -1948,7 +1946,7 @@ CREATE TABLE `system_post` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表'; +) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表'; -- ---------------------------- -- Records of system_post @@ -2277,7 +2275,6 @@ CREATE TABLE `system_sms_channel` ( -- Records of system_sms_channel -- ---------------------------- BEGIN; -INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道', 'YUN_PIAN', 0, '呵呵呵哒', '1555a14277cb8a608cf45a9e6a80d510', NULL, 'http://vdwapu.natappfree.cc/admin-api/system/sms/callback/yunpian', '', '2021-03-31 06:12:20', '1', '2022-02-23 16:48:44', b'0'); INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 'Ballcat', 'ALIYUN', 0, '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2021-04-14 00:08:37', b'0'); INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2022-03-27 20:29:49', b'0'); INSERT INTO `system_sms_channel` (`id`, `signature`, `code`, `status`, `remark`, `api_key`, `api_secret`, `callback_url`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (6, '测试演示', 'DEBUG_DING_TALK', 0, NULL, '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2022-04-10 23:07:59', '1', '2022-06-19 00:33:54', b'0'); @@ -2305,7 +2302,7 @@ CREATE TABLE `system_sms_code` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号' -) ENGINE = InnoDB AUTO_INCREMENT = 480 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; -- ---------------------------- -- Records of system_sms_code @@ -2348,7 +2345,7 @@ CREATE TABLE `system_sms_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 337 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; -- ---------------------------- -- Records of system_sms_log @@ -2418,7 +2415,7 @@ CREATE TABLE `system_social_user` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; -- ---------------------------- -- Records of system_social_user @@ -2443,7 +2440,7 @@ CREATE TABLE `system_social_user_bind` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; -- ---------------------------- -- Records of system_social_user_bind @@ -2529,12 +2526,7 @@ CREATE TABLE `system_user_post` ( -- Records of system_user_post -- ---------------------------- BEGIN; -INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (112, 1, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1); -INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (113, 100, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1); -INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (114, 114, 3, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1); -INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (115, 104, 1, '1', '2022-05-16 19:36:28', '1', '2022-05-16 19:36:28', b'0', 1); -INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (116, 117, 2, '1', '2022-07-09 17:40:26', '1', '2022-07-09 17:40:26', b'0', 1); -INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (117, 118, 1, '1', '2022-07-09 17:44:44', '1', '2022-07-09 17:44:44', b'0', 1); +INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1); COMMIT; -- ---------------------------- @@ -2552,7 +2544,7 @@ CREATE TABLE `system_user_role` ( `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表'; +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表'; -- ---------------------------- -- Records of system_user_role @@ -2560,21 +2552,6 @@ CREATE TABLE `system_user_role` ( BEGIN; INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:17', b'0', 1); INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 100, 101, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 100, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:12', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 100, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:11', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 103, 1, '1', '2022-01-11 13:19:45', '1', '2022-01-11 13:19:45', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 107, 106, '1', '2022-02-20 22:59:33', '1', '2022-02-20 22:59:33', b'0', 118); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 108, 107, '1', '2022-02-20 23:00:50', '1', '2022-02-20 23:00:50', b'0', 119); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (13, 109, 108, '1', '2022-02-20 23:11:50', '1', '2022-02-20 23:11:50', b'0', 120); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (14, 110, 109, '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', b'0', 121); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (15, 111, 110, '110', '2022-02-23 13:14:38', '110', '2022-02-23 13:14:38', b'0', 121); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (16, 113, 111, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0', 122); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (17, 114, 101, '1', '2022-03-19 21:51:13', '1', '2022-03-19 21:51:13', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (18, 1, 2, '1', '2022-05-12 20:39:29', '1', '2022-05-12 20:39:29', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (19, 116, 113, '1', '2022-05-17 10:07:10', '1', '2022-05-17 10:07:10', b'0', 124); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (20, 104, 101, '1', '2022-05-28 15:43:57', '1', '2022-05-28 15:43:57', b'0', 1); -INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (22, 115, 2, '1', '2022-07-21 22:08:30', '1', '2022-07-21 22:08:30', b'0', 1); COMMIT; -- ---------------------------- @@ -2597,7 +2574,7 @@ CREATE TABLE `system_user_session` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户在线 Session'; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户在线 Session'; -- ---------------------------- -- Records of system_user_session diff --git a/sql/optional/visualization/jimureport.mysql5.7.create.sql b/sql/optional/visualization/jimureport.mysql5.7.create.sql index 7c4a8405c..e32134005 100644 --- a/sql/optional/visualization/jimureport.mysql5.7.create.sql +++ b/sql/optional/visualization/jimureport.mysql5.7.create.sql @@ -418,17 +418,19 @@ CREATE TABLE `jimu_report_data_source` ( `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', `update_time` datetime NULL DEFAULT NULL COMMENT '更新日期', `connect_times` int(1) UNSIGNED NULL DEFAULT 0 COMMENT '连接失败次数', + `tenant_id` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '多租户标识', + `type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型(report:报表;drag:仪表盘)', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_jmdatasource_report_id`(`report_id`) USING BTREE, INDEX `idx_jmdatasource_code`(`code`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of jimu_report_data_source -- ---------------------------- -INSERT INTO `jimu_report_data_source` VALUES ('1324261983692902402', 'jeewx', '1324261770294071296', '', NULL, 'MYSQL', 'com.mysql.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeewx-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'jeecg', '2020-11-05 16:07:15', NULL, '2020-11-05 16:07:15', 0); -INSERT INTO `jimu_report_data_source` VALUES ('26d21fe4f27920d2f56abc8d90a8e527', 'oracle', '1308645288868712448', '', NULL, 'ORACLE', 'oracle.jdbc.OracleDriver', 'jdbc:oracle:thin:@192.168.1.199:1521:helowin', 'jeecgbootbpm', 'jeecg196283', 'admin', '2021-01-05 19:26:24', NULL, '2021-01-05 19:26:24', 1); -INSERT INTO `jimu_report_data_source` VALUES ('8f90daf47d15d35ca6cf420748b8b9ba', 'localhost', '1316944968992034816', '', NULL, 'MYSQL5.7', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'admin', '2021-01-13 14:34:00', NULL, '2021-01-13 14:34:00', 0); +INSERT INTO `jimu_report_data_source` VALUES ('1324261983692902402', 'jeewx', '1324261770294071296', '', NULL, 'MYSQL', 'com.mysql.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeewx-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'jeecg', '2020-11-05 16:07:15', NULL, '2020-11-05 16:07:15', 0, NULL, 'report'); +INSERT INTO `jimu_report_data_source` VALUES ('26d21fe4f27920d2f56abc8d90a8e527', 'oracle', '1308645288868712448', '', NULL, 'ORACLE', 'oracle.jdbc.OracleDriver', 'jdbc:oracle:thin:@192.168.1.199:1521:helowin', 'jeecgbootbpm', 'jeecg196283', 'admin', '2021-01-05 19:26:24', NULL, '2021-01-05 19:26:24', 1, NULL, 'report'); +INSERT INTO `jimu_report_data_source` VALUES ('8f90daf47d15d35ca6cf420748b8b9ba', 'localhost', '1316944968992034816', '', NULL, 'MYSQL5.7', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'admin', '2021-01-13 14:34:00', NULL, '2021-01-13 14:34:00', 0, NULL, 'report'); -- ---------------------------- -- Table structure for jimu_report_db diff --git a/sql/oracle/ruoyi-vue-pro.sql b/sql/oracle/ruoyi-vue-pro.sql index 07e0a85e3..46481ae2f 100644 --- a/sql/oracle/ruoyi-vue-pro.sql +++ b/sql/oracle/ruoyi-vue-pro.sql @@ -38,8 +38,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -96,8 +96,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -159,8 +159,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -224,8 +224,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -284,8 +284,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -342,8 +342,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -400,8 +400,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -463,8 +463,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -543,8 +543,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -645,8 +645,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -718,8 +718,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -780,8 +780,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -839,8 +839,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -892,8 +892,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -945,8 +945,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -999,8 +999,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1053,8 +1053,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1113,8 +1113,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1169,8 +1169,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1226,8 +1226,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1284,8 +1284,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1341,8 +1341,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1398,8 +1398,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1451,8 +1451,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1510,8 +1510,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1589,8 +1589,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1665,8 +1665,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1742,8 +1742,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1807,8 +1807,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1840,8 +1840,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1875,8 +1875,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1919,8 +1919,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1959,8 +1959,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -1992,8 +1992,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2026,8 +2026,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2060,8 +2060,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2097,8 +2097,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2141,8 +2141,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2187,8 +2187,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2232,8 +2232,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2303,8 +2303,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2454,7 +2454,6 @@ INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "ST INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('62', '0', '未处理', '0', 'infra_api_error_log_process_status', '0', 'primary', NULL, NULL, NULL, TO_DATE('2021-02-26 07:07:19', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 20:14:17', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('63', '1', '已处理', '1', 'infra_api_error_log_process_status', '0', 'success', NULL, NULL, NULL, TO_DATE('2021-02-26 07:07:26', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 20:14:08', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('64', '2', '已忽略', '2', 'infra_api_error_log_process_status', '0', 'danger', NULL, NULL, NULL, TO_DATE('2021-02-26 07:07:34', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 20:14:14', 'SYYYY-MM-DD HH24:MI:SS'), '0'); -INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('65', '1', '云片', 'YUN_PIAN', 'system_sms_channel_code', '0', 'success', NULL, NULL, '1', TO_DATE('2021-04-05 01:05:14', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 10:09:55', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('66', '2', '阿里云', 'ALIYUN', 'system_sms_channel_code', '0', 'primary', NULL, NULL, '1', TO_DATE('2021-04-05 01:05:26', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 10:09:52', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('67', '1', '验证码', '1', 'system_sms_template_type', '0', 'warning', NULL, NULL, '1', TO_DATE('2021-04-05 21:50:57', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 12:48:30', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_DATA" ("ID", "SORT", "LABEL", "VALUE", "DICT_TYPE", "STATUS", "COLOR_TYPE", "CSS_CLASS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('68', '2', '通知', '2', 'system_sms_template_type', '0', 'primary', NULL, NULL, '1', TO_DATE('2021-04-05 21:51:08', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 12:48:27', 'SYYYY-MM-DD HH24:MI:SS'), '0'); @@ -2475,25 +2474,26 @@ COMMIT; -- Table structure for SYSTEM_DICT_TYPE -- ---------------------------- DROP TABLE "SYSTEM_DICT_TYPE"; -CREATE TABLE "SYSTEM_DICT_TYPE" ( - "ID" NUMBER(20,0) NOT NULL, - "NAME" NVARCHAR2(100), - "TYPE" NVARCHAR2(100), - "STATUS" NUMBER(4,0) NOT NULL, - "REMARK" NVARCHAR2(500), - "CREATOR" NVARCHAR2(64), - "CREATE_TIME" DATE NOT NULL, - "UPDATER" NVARCHAR2(64), - "UPDATE_TIME" DATE NOT NULL, - "DELETED" NUMBER(1,0) DEFAULT 0 NOT NULL +CREATE TABLE "SYSTEM_DICT_TYPE"( + "ID" NUMBER(20,0) NOT NULL, + "NAME" NVARCHAR2(100), + "TYPE" NVARCHAR2(100), + "STATUS" NUMBER(4,0) NOT NULL, + "REMARK" NVARCHAR2(500), + "CREATOR" NVARCHAR2(64), + "CREATE_TIME" DATE NOT NULL, + "UPDATER" NVARCHAR2(64), + "UPDATE_TIME" DATE NOT NULL, + "DELETED_TIME" DATE, + "DELETED" NUMBER(1,0) DEFAULT 0 NOT NULL ) LOGGING NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2504,25 +2504,54 @@ PARALLEL 1 NOCACHE DISABLE ROW MOVEMENT ; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."ID" IS '字典主键'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."NAME" IS '字典名称'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."TYPE" IS '字典类型'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."STATUS" IS '状态(0正常 1停用)'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."REMARK" IS '备注'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."CREATOR" IS '创建者'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."CREATE_TIME" IS '创建时间'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."UPDATER" IS '更新者'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."UPDATE_TIME" IS '更新时间'; -COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."DELETED" IS '是否删除'; -COMMENT ON TABLE "SYSTEM_DICT_TYPE" IS '字典类型表'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."ID" IS '字典主键'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."NAME" IS '字典名称'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."TYPE" IS '字典类型'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."STATUS" IS '状态(0正常 1停用)'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."REMARK" IS '备注'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."CREATOR" IS '创建者'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."CREATE_TIME" IS '创建时间'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."UPDATER" IS '更新者'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."UPDATE_TIME" IS '更新时间'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."DELETED_TIME" IS '删除时间'; +COMMENT +ON COLUMN "SYSTEM_DICT_TYPE"."DELETED" IS '是否删除'; +COMMENT +ON TABLE "SYSTEM_DICT_TYPE" IS '字典类型表'; -- ---------------------------- -- Records of SYSTEM_DICT_TYPE -- ---------------------------- -INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('1', '用户性别', 'system_user_sex', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-05-01 12:55:56', 'SYYYY-MM-DD HH24:MI:SS'), '0'); -INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('6', '参数类型', 'infra_config_type', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:36:54', 'SYYYY-MM-DD HH24:MI:SS'), '0'); -INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('7', '通知类型', 'system_notice_type', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:35:26', 'SYYYY-MM-DD HH24:MI:SS'), '0'); -INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('9', '操作类型', 'system_operate_type', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 09:32:21', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", + "UPDATE_TIME", "DELETED") +VALUES ('1', '用户性别', 'system_user_sex', '0', NULL, 'admin', + TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1', + TO_DATE('2022-05-01 12:55:56', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", + "UPDATE_TIME", "DELETED") +VALUES ('6', '参数类型', 'infra_config_type', '0', NULL, 'admin', + TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, + TO_DATE('2022-02-01 16:36:54', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", + "UPDATE_TIME", "DELETED") +VALUES ('7', '通知类型', 'system_notice_type', '0', NULL, 'admin', + TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, + TO_DATE('2022-02-01 16:35:26', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", + "UPDATE_TIME", "DELETED") +VALUES ('9', '操作类型', 'system_operate_type', '0', NULL, 'admin', + TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1', + TO_DATE('2022-02-16 09:32:21', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('10', '系统状态', 'common_status', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:21:28', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('11', 'Boolean 是否类型', 'infra_boolean_string', '0', 'boolean 转是否', NULL, TO_DATE('2021-01-19 03:20:08', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:37:10', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('104', '登陆结果', 'system_login_result', '0', '登陆结果', NULL, TO_DATE('2021-01-18 06:17:11', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:36:00', 'SYYYY-MM-DD HH24:MI:SS'), '0'); @@ -2583,8 +2612,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2642,8 +2671,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2706,8 +2735,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -2995,8 +3024,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3051,8 +3080,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3109,8 +3138,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3176,8 +3205,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3245,8 +3274,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3307,8 +3336,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3377,8 +3406,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3446,8 +3475,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3508,8 +3537,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3569,8 +3598,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3759,8 +3788,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3815,8 +3844,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3845,7 +3874,6 @@ COMMENT ON TABLE "SYSTEM_SMS_CHANNEL" IS '短信渠道'; -- ---------------------------- -- Records of SYSTEM_SMS_CHANNEL -- ---------------------------- -INSERT INTO "SYSTEM_SMS_CHANNEL" ("ID", "SIGNATURE", "CODE", "STATUS", "REMARK", "API_KEY", "API_SECRET", "CALLBACK_URL", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('1', '芋道', 'YUN_PIAN', '0', '呵呵呵哒', '1555a14277cb8a608cf45a9e6a80d510', NULL, 'http://vdwapu.natappfree.cc/admin-api/system/sms/callback/yunpian', NULL, TO_DATE('2021-03-31 06:12:20', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-23 16:48:44', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_SMS_CHANNEL" ("ID", "SIGNATURE", "CODE", "STATUS", "REMARK", "API_KEY", "API_SECRET", "CALLBACK_URL", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('2', 'Ballcat', 'ALIYUN', '0', '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, NULL, TO_DATE('2021-03-31 11:53:10', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2021-04-14 00:08:37', 'SYYYY-MM-DD HH24:MI:SS'), '0'); INSERT INTO "SYSTEM_SMS_CHANNEL" ("ID", "SIGNATURE", "CODE", "STATUS", "REMARK", "API_KEY", "API_SECRET", "CALLBACK_URL", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('4', '测试渠道', 'DEBUG_DING_TALK', '0', '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', TO_DATE('2021-04-13 00:23:14', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2021-04-14 00:07:10', 'SYYYY-MM-DD HH24:MI:SS'), '0'); COMMIT; @@ -3877,8 +3905,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -3953,8 +3981,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4029,8 +4057,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4102,8 +4130,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4165,8 +4193,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4224,8 +4252,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4286,8 +4314,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4360,8 +4388,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -4412,8 +4440,8 @@ NOCOMPRESS PCTFREE 10 INITRANS 1 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5401,8 +5429,8 @@ CREATE INDEX "IDX_QRTZ_FT_INST_JOB_REQ_RCVRY" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5418,8 +5446,8 @@ CREATE INDEX "IDX_QRTZ_FT_JG" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5433,8 +5461,8 @@ CREATE INDEX "IDX_QRTZ_FT_J_G" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5449,8 +5477,8 @@ CREATE INDEX "IDX_QRTZ_FT_TG" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5485,8 +5513,8 @@ CREATE INDEX "IDX_QRTZ_J_GRP" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5500,8 +5528,8 @@ CREATE INDEX "IDX_QRTZ_J_REQ_RECOVERY" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5625,8 +5653,8 @@ CREATE INDEX "IDX_QRTZ_T_C" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5640,8 +5668,8 @@ CREATE INDEX "IDX_QRTZ_T_J" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5657,8 +5685,8 @@ CREATE INDEX "IDX_QRTZ_T_JG" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5672,8 +5700,8 @@ CREATE INDEX "IDX_QRTZ_T_NEXT_FIRE_TIME" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5687,8 +5715,8 @@ CREATE INDEX "IDX_QRTZ_T_NFT_ST" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5704,8 +5732,8 @@ CREATE INDEX "IDX_QRTZ_T_NFT_ST_MISFIRE" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 @@ -5719,8 +5747,8 @@ CREATE INDEX "IDX_QRTZ_T_STATE" PCTFREE 10 INITRANS 2 STORAGE ( - INITIAL 65536 - NEXT 1048576 + INITIAL 65536 + NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 diff --git a/sql/postgresql/ruoyi-vue-pro.sql b/sql/postgresql/ruoyi-vue-pro.sql index 06779a06f..7484486c2 100644 --- a/sql/postgresql/ruoyi-vue-pro.sql +++ b/sql/postgresql/ruoyi-vue-pro.sql @@ -20,7 +20,7 @@ -- Sequence structure for bpm_form_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_form_seq"; -CREATE SEQUENCE "bpm_form_seq" +CREATE SEQUENCE "bpm_form_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -29,7 +29,7 @@ CACHE 1; -- Sequence structure for bpm_oa_leave_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_oa_leave_seq"; -CREATE SEQUENCE "bpm_oa_leave_seq" +CREATE SEQUENCE "bpm_oa_leave_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -38,7 +38,7 @@ CACHE 1; -- Sequence structure for bpm_process_definition_ext_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_process_definition_ext_seq"; -CREATE SEQUENCE "bpm_process_definition_ext_seq" +CREATE SEQUENCE "bpm_process_definition_ext_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -47,7 +47,7 @@ CACHE 1; -- Sequence structure for bpm_process_instance_ext_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_process_instance_ext_seq"; -CREATE SEQUENCE "bpm_process_instance_ext_seq" +CREATE SEQUENCE "bpm_process_instance_ext_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -56,7 +56,7 @@ CACHE 1; -- Sequence structure for bpm_task_assign_rule_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_task_assign_rule_seq"; -CREATE SEQUENCE "bpm_task_assign_rule_seq" +CREATE SEQUENCE "bpm_task_assign_rule_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -65,7 +65,7 @@ CACHE 1; -- Sequence structure for bpm_task_ext_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_task_ext_seq"; -CREATE SEQUENCE "bpm_task_ext_seq" +CREATE SEQUENCE "bpm_task_ext_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -74,7 +74,7 @@ CACHE 1; -- Sequence structure for bpm_user_group_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "bpm_user_group_seq"; -CREATE SEQUENCE "bpm_user_group_seq" +CREATE SEQUENCE "bpm_user_group_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -83,7 +83,7 @@ CACHE 1; -- Sequence structure for infra_api_access_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_api_access_log_seq"; -CREATE SEQUENCE "infra_api_access_log_seq" +CREATE SEQUENCE "infra_api_access_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -92,7 +92,7 @@ CACHE 1; -- Sequence structure for infra_api_error_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_api_error_log_seq"; -CREATE SEQUENCE "infra_api_error_log_seq" +CREATE SEQUENCE "infra_api_error_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -101,7 +101,7 @@ CACHE 1; -- Sequence structure for infra_codegen_column_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_codegen_column_seq"; -CREATE SEQUENCE "infra_codegen_column_seq" +CREATE SEQUENCE "infra_codegen_column_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -110,7 +110,7 @@ CACHE 1; -- Sequence structure for infra_codegen_table_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_codegen_table_seq"; -CREATE SEQUENCE "infra_codegen_table_seq" +CREATE SEQUENCE "infra_codegen_table_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -119,7 +119,7 @@ CACHE 1; -- Sequence structure for infra_config_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_config_seq"; -CREATE SEQUENCE "infra_config_seq" +CREATE SEQUENCE "infra_config_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -128,7 +128,7 @@ CACHE 1; -- Sequence structure for infra_data_source_config_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_data_source_config_seq"; -CREATE SEQUENCE "infra_data_source_config_seq" +CREATE SEQUENCE "infra_data_source_config_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -137,7 +137,7 @@ CACHE 1; -- Sequence structure for infra_file_config_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_file_config_seq"; -CREATE SEQUENCE "infra_file_config_seq" +CREATE SEQUENCE "infra_file_config_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -146,7 +146,7 @@ CACHE 1; -- Sequence structure for infra_file_content_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_file_content_seq"; -CREATE SEQUENCE "infra_file_content_seq" +CREATE SEQUENCE "infra_file_content_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -155,7 +155,7 @@ CACHE 1; -- Sequence structure for infra_file_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_file_seq"; -CREATE SEQUENCE "infra_file_seq" +CREATE SEQUENCE "infra_file_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -164,7 +164,7 @@ CACHE 1; -- Sequence structure for infra_job_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_job_log_seq"; -CREATE SEQUENCE "infra_job_log_seq" +CREATE SEQUENCE "infra_job_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -173,7 +173,7 @@ CACHE 1; -- Sequence structure for infra_job_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_job_seq"; -CREATE SEQUENCE "infra_job_seq" +CREATE SEQUENCE "infra_job_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -182,7 +182,7 @@ CACHE 1; -- Sequence structure for infra_test_demo_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "infra_test_demo_seq"; -CREATE SEQUENCE "infra_test_demo_seq" +CREATE SEQUENCE "infra_test_demo_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -191,7 +191,7 @@ CACHE 1; -- Sequence structure for member_user_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "member_user_seq"; -CREATE SEQUENCE "member_user_seq" +CREATE SEQUENCE "member_user_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -200,7 +200,7 @@ CACHE 1; -- Sequence structure for pay_app_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_app_seq"; -CREATE SEQUENCE "pay_app_seq" +CREATE SEQUENCE "pay_app_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -209,7 +209,7 @@ CACHE 1; -- Sequence structure for pay_channel_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_channel_seq"; -CREATE SEQUENCE "pay_channel_seq" +CREATE SEQUENCE "pay_channel_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -218,7 +218,7 @@ CACHE 1; -- Sequence structure for pay_merchant_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_merchant_seq"; -CREATE SEQUENCE "pay_merchant_seq" +CREATE SEQUENCE "pay_merchant_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -227,7 +227,7 @@ CACHE 1; -- Sequence structure for pay_notify_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_notify_log_seq"; -CREATE SEQUENCE "pay_notify_log_seq" +CREATE SEQUENCE "pay_notify_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -236,7 +236,7 @@ CACHE 1; -- Sequence structure for pay_notify_task_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_notify_task_seq"; -CREATE SEQUENCE "pay_notify_task_seq" +CREATE SEQUENCE "pay_notify_task_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -245,7 +245,7 @@ CACHE 1; -- Sequence structure for pay_order_extension_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_order_extension_seq"; -CREATE SEQUENCE "pay_order_extension_seq" +CREATE SEQUENCE "pay_order_extension_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -254,7 +254,7 @@ CACHE 1; -- Sequence structure for pay_order_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_order_seq"; -CREATE SEQUENCE "pay_order_seq" +CREATE SEQUENCE "pay_order_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -263,7 +263,7 @@ CACHE 1; -- Sequence structure for pay_refund_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "pay_refund_seq"; -CREATE SEQUENCE "pay_refund_seq" +CREATE SEQUENCE "pay_refund_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -272,7 +272,7 @@ CACHE 1; -- Sequence structure for system_dept_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_dept_seq"; -CREATE SEQUENCE "system_dept_seq" +CREATE SEQUENCE "system_dept_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -281,7 +281,7 @@ CACHE 1; -- Sequence structure for system_dict_data_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_dict_data_seq"; -CREATE SEQUENCE "system_dict_data_seq" +CREATE SEQUENCE "system_dict_data_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -290,7 +290,7 @@ CACHE 1; -- Sequence structure for system_dict_type_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_dict_type_seq"; -CREATE SEQUENCE "system_dict_type_seq" +CREATE SEQUENCE "system_dict_type_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -299,7 +299,7 @@ CACHE 1; -- Sequence structure for system_error_code_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_error_code_seq"; -CREATE SEQUENCE "system_error_code_seq" +CREATE SEQUENCE "system_error_code_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -308,7 +308,7 @@ CACHE 1; -- Sequence structure for system_login_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_login_log_seq"; -CREATE SEQUENCE "system_login_log_seq" +CREATE SEQUENCE "system_login_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -317,7 +317,7 @@ CACHE 1; -- Sequence structure for system_menu_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_menu_seq"; -CREATE SEQUENCE "system_menu_seq" +CREATE SEQUENCE "system_menu_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -326,7 +326,7 @@ CACHE 1; -- Sequence structure for system_notice_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_notice_seq"; -CREATE SEQUENCE "system_notice_seq" +CREATE SEQUENCE "system_notice_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -335,7 +335,7 @@ CACHE 1; -- Sequence structure for system_oauth2_access_token_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_oauth2_access_token_seq"; -CREATE SEQUENCE "system_oauth2_access_token_seq" +CREATE SEQUENCE "system_oauth2_access_token_seq" INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 @@ -346,7 +346,7 @@ CACHE 1; -- Sequence structure for system_oauth2_approve_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_oauth2_approve_seq"; -CREATE SEQUENCE "system_oauth2_approve_seq" +CREATE SEQUENCE "system_oauth2_approve_seq" INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 @@ -357,7 +357,7 @@ CACHE 1; -- Sequence structure for system_oauth2_client_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_oauth2_client_seq"; -CREATE SEQUENCE "system_oauth2_client_seq" +CREATE SEQUENCE "system_oauth2_client_seq" INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 @@ -368,7 +368,7 @@ CACHE 1; -- Sequence structure for system_oauth2_code_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_oauth2_code_seq"; -CREATE SEQUENCE "system_oauth2_code_seq" +CREATE SEQUENCE "system_oauth2_code_seq" INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 @@ -379,7 +379,7 @@ CACHE 1; -- Sequence structure for system_oauth2_refresh_token_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_oauth2_refresh_token_seq"; -CREATE SEQUENCE "system_oauth2_refresh_token_seq" +CREATE SEQUENCE "system_oauth2_refresh_token_seq" INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 @@ -390,7 +390,7 @@ CACHE 1; -- Sequence structure for system_operate_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_operate_log_seq"; -CREATE SEQUENCE "system_operate_log_seq" +CREATE SEQUENCE "system_operate_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -399,7 +399,7 @@ CACHE 1; -- Sequence structure for system_post_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_post_seq"; -CREATE SEQUENCE "system_post_seq" +CREATE SEQUENCE "system_post_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -408,7 +408,7 @@ CACHE 1; -- Sequence structure for system_role_menu_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_role_menu_seq"; -CREATE SEQUENCE "system_role_menu_seq" +CREATE SEQUENCE "system_role_menu_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -417,7 +417,7 @@ CACHE 1; -- Sequence structure for system_role_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_role_seq"; -CREATE SEQUENCE "system_role_seq" +CREATE SEQUENCE "system_role_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -426,7 +426,7 @@ CACHE 1; -- Sequence structure for system_sensitive_word_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_sensitive_word_seq"; -CREATE SEQUENCE "system_sensitive_word_seq" +CREATE SEQUENCE "system_sensitive_word_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -435,7 +435,7 @@ CACHE 1; -- Sequence structure for system_sms_channel_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_sms_channel_seq"; -CREATE SEQUENCE "system_sms_channel_seq" +CREATE SEQUENCE "system_sms_channel_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -444,7 +444,7 @@ CACHE 1; -- Sequence structure for system_sms_code_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_sms_code_seq"; -CREATE SEQUENCE "system_sms_code_seq" +CREATE SEQUENCE "system_sms_code_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -453,7 +453,7 @@ CACHE 1; -- Sequence structure for system_sms_log_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_sms_log_seq"; -CREATE SEQUENCE "system_sms_log_seq" +CREATE SEQUENCE "system_sms_log_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -462,7 +462,7 @@ CACHE 1; -- Sequence structure for system_sms_template_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_sms_template_seq"; -CREATE SEQUENCE "system_sms_template_seq" +CREATE SEQUENCE "system_sms_template_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -471,7 +471,7 @@ CACHE 1; -- Sequence structure for system_social_user_bind_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_social_user_bind_seq"; -CREATE SEQUENCE "system_social_user_bind_seq" +CREATE SEQUENCE "system_social_user_bind_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -480,7 +480,7 @@ CACHE 1; -- Sequence structure for system_social_user_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_social_user_seq"; -CREATE SEQUENCE "system_social_user_seq" +CREATE SEQUENCE "system_social_user_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -489,7 +489,7 @@ CACHE 1; -- Sequence structure for system_tenant_package_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_tenant_package_seq"; -CREATE SEQUENCE "system_tenant_package_seq" +CREATE SEQUENCE "system_tenant_package_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -498,7 +498,7 @@ CACHE 1; -- Sequence structure for system_tenant_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_tenant_seq"; -CREATE SEQUENCE "system_tenant_seq" +CREATE SEQUENCE "system_tenant_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -507,7 +507,7 @@ CACHE 1; -- Sequence structure for system_user_post_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_user_post_seq"; -CREATE SEQUENCE "system_user_post_seq" +CREATE SEQUENCE "system_user_post_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -516,7 +516,7 @@ CACHE 1; -- Sequence structure for system_user_role_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_user_role_seq"; -CREATE SEQUENCE "system_user_role_seq" +CREATE SEQUENCE "system_user_role_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -525,7 +525,7 @@ CACHE 1; -- Sequence structure for system_user_seq -- ---------------------------- DROP SEQUENCE IF EXISTS "system_user_seq"; -CREATE SEQUENCE "system_user_seq" +CREATE SEQUENCE "system_user_seq" INCREMENT 1 MAXVALUE 9223372036854775807 CACHE 1; @@ -2267,7 +2267,6 @@ INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "st INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (62, 0, '未处理', '0', 'infra_api_error_log_process_status', 0, 'primary', '', NULL, '', '2021-02-26 07:07:19', '1', '2022-02-16 20:14:17', 0); INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (63, 1, '已处理', '1', 'infra_api_error_log_process_status', 0, 'success', '', NULL, '', '2021-02-26 07:07:26', '1', '2022-02-16 20:14:08', 0); INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (64, 2, '已忽略', '2', 'infra_api_error_log_process_status', 0, 'danger', '', NULL, '', '2021-02-26 07:07:34', '1', '2022-02-16 20:14:14', 0); -INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (65, 1, '云片', 'YUN_PIAN', 'system_sms_channel_code', 0, 'success', '', NULL, '1', '2021-04-05 01:05:14', '1', '2022-02-16 10:09:55', 0); INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (66, 2, '阿里云', 'ALIYUN', 'system_sms_channel_code', 0, 'primary', '', NULL, '1', '2021-04-05 01:05:26', '1', '2022-02-16 10:09:52', 0); INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (67, 1, '验证码', '1', 'system_sms_template_type', 0, 'warning', '', NULL, '1', '2021-04-05 21:50:57', '1', '2022-02-16 12:48:30', 0); INSERT INTO "system_dict_data" ("id", "sort", "label", "value", "dict_type", "status", "color_type", "css_class", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (68, 2, '通知', '2', 'system_sms_template_type', 0, 'primary', '', NULL, '1', '2021-04-05 21:51:08', '1', '2022-02-16 12:48:27', 0); @@ -2358,38 +2357,58 @@ COMMIT; -- Table structure for system_dict_type -- ---------------------------- DROP TABLE IF EXISTS "system_dict_type"; -CREATE TABLE "system_dict_type" ( - "id" int8 NOT NULL, - "name" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, - "type" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, - "status" int2 NOT NULL, - "remark" varchar(500) COLLATE "pg_catalog"."default", - "creator" varchar(64) COLLATE "pg_catalog"."default", - "create_time" timestamp(6) NOT NULL, - "updater" varchar(64) COLLATE "pg_catalog"."default", - "update_time" timestamp(6) NOT NULL, - "deleted" int2 NOT NULL DEFAULT 0 +CREATE TABLE "system_dict_type"( + "id" int8 NOT NULL, + "name" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "type" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "status" int2 NOT NULL, + "remark" varchar(500) COLLATE "pg_catalog"."default", + "creator" varchar(64) COLLATE "pg_catalog"."default", + "create_time" timestamp(6) NOT NULL, + "updater" varchar(64) COLLATE "pg_catalog"."default", + "update_time" timestamp(6) NOT NULL, + "deleted_time" timestamp(6), + "deleted" int2 NOT NULL DEFAULT 0 ) ; -COMMENT ON COLUMN "system_dict_type"."id" IS '字典主键'; -COMMENT ON COLUMN "system_dict_type"."name" IS '字典名称'; -COMMENT ON COLUMN "system_dict_type"."type" IS '字典类型'; -COMMENT ON COLUMN "system_dict_type"."status" IS '状态(0正常 1停用)'; -COMMENT ON COLUMN "system_dict_type"."remark" IS '备注'; -COMMENT ON COLUMN "system_dict_type"."creator" IS '创建者'; -COMMENT ON COLUMN "system_dict_type"."create_time" IS '创建时间'; -COMMENT ON COLUMN "system_dict_type"."updater" IS '更新者'; -COMMENT ON COLUMN "system_dict_type"."update_time" IS '更新时间'; -COMMENT ON COLUMN "system_dict_type"."deleted" IS '是否删除'; -COMMENT ON TABLE "system_dict_type" IS '字典类型表'; +COMMENT +ON COLUMN "system_dict_type"."id" IS '字典主键'; +COMMENT +ON COLUMN "system_dict_type"."name" IS '字典名称'; +COMMENT +ON COLUMN "system_dict_type"."type" IS '字典类型'; +COMMENT +ON COLUMN "system_dict_type"."status" IS '状态(0正常 1停用)'; +COMMENT +ON COLUMN "system_dict_type"."remark" IS '备注'; +COMMENT +ON COLUMN "system_dict_type"."creator" IS '创建者'; +COMMENT +ON COLUMN "system_dict_type"."create_time" IS '创建时间'; +COMMENT +ON COLUMN "system_dict_type"."updater" IS '更新者'; +COMMENT +ON COLUMN "system_dict_type"."update_time" IS '更新时间'; +COMMENT +ON COLUMN "system_dict_type"."deleted_time" IS '删除时间'; +COMMENT +ON COLUMN "system_dict_type"."deleted" IS '是否删除'; +COMMENT +ON TABLE "system_dict_type" IS '字典类型表'; -- ---------------------------- -- Records of system_dict_type -- ---------------------------- BEGIN; -INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (1, '用户性别', 'system_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:31', 0); -INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (6, '参数类型', 'infra_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:36:54', 0); -INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (7, '通知类型', 'system_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:26', 0); +INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", + "update_time", "deleted") +VALUES (1, '用户性别', 'system_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:31', 0); +INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", + "update_time", "deleted") +VALUES (6, '参数类型', 'infra_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:36:54', 0); +INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", + "update_time", "deleted") +VALUES (7, '通知类型', 'system_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:26', 0); INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (9, '操作类型', 'system_operate_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 09:32:21', 0); INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (10, '系统状态', 'common_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:21:28', 0); INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (11, 'Boolean 是否类型', 'infra_boolean_string', 0, 'boolean 转是否', '', '2021-01-19 03:20:08', '', '2022-02-01 16:37:10', 0); @@ -3519,7 +3538,6 @@ COMMENT ON TABLE "system_sms_channel" IS '短信渠道'; -- Records of system_sms_channel -- ---------------------------- BEGIN; -INSERT INTO "system_sms_channel" ("id", "signature", "code", "status", "remark", "api_key", "api_secret", "callback_url", "creator", "create_time", "updater", "update_time", "deleted") VALUES (1, '芋道', 'YUN_PIAN', 0, '呵呵呵哒', '1555a14277cb8a608cf45a9e6a80d510', NULL, 'http://vdwapu.natappfree.cc/admin-api/system/sms/callback/yunpian', '', '2021-03-31 06:12:20', '1', '2022-02-23 16:48:44', 0); INSERT INTO "system_sms_channel" ("id", "signature", "code", "status", "remark", "api_key", "api_secret", "callback_url", "creator", "create_time", "updater", "update_time", "deleted") VALUES (2, 'Ballcat', 'ALIYUN', 0, '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2021-04-14 00:08:37', 0); INSERT INTO "system_sms_channel" ("id", "signature", "code", "status", "remark", "api_key", "api_secret", "callback_url", "creator", "create_time", "updater", "update_time", "deleted") VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2022-03-27 20:29:49', 0); INSERT INTO "system_sms_channel" ("id", "signature", "code", "status", "remark", "api_key", "api_secret", "callback_url", "creator", "create_time", "updater", "update_time", "deleted") VALUES (6, '测试演示', 'DEBUG_DING_TALK', 0, NULL, '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2022-04-10 23:07:59', '1', '2022-04-10 23:07:59', 0); diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql index 1c0d93776..386e9bd2e 100644 --- a/sql/sqlserver/ruoyi-vue-pro.sql +++ b/sql/sqlserver/ruoyi-vue-pro.sql @@ -5545,11 +5545,7 @@ GO INSERT INTO [dbo].[system_dict_data] ([id], [sort], [label], [value], [dict_type], [status], [color_type], [css_class], [remark], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'63', N'1', N'已处理', N'1', N'infra_api_error_log_process_status', N'0', N'success', N'', NULL, N'', N'2021-02-26 07:07:26.0000000', N'1', N'2022-02-16 20:14:08.0000000', N'0') GO -INSERT INTO [dbo].[system_dict_data] ([id], [sort], [label], [value], [dict_type], [status], [color_type], [css_class], [remark], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'64', N'2', N'已忽略', N'2', N'infra_api_error_log_process_status', N'0', N'danger', N'', NULL, N'', N'2021-02-26 07:07:34.0000000', N'1', N'2022-02-16 20:14:14.0000000', N'0') -GO -INSERT INTO [dbo].[system_dict_data] ([id], [sort], [label], [value], [dict_type], [status], [color_type], [css_class], [remark], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'65', N'1', N'云片', N'YUN_PIAN', N'system_sms_channel_code', N'0', N'success', N'', NULL, N'1', N'2021-04-05 01:05:14.0000000', N'1', N'2022-02-16 10:09:55.0000000', N'0') -GO INSERT INTO [dbo].[system_dict_data] ([id], [sort], [label], [value], [dict_type], [status], [color_type], [css_class], [remark], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'66', N'2', N'阿里云', N'ALIYUN', N'system_sms_channel_code', N'0', N'primary', N'', NULL, N'1', N'2021-04-05 01:05:26.0000000', N'1', N'2022-02-16 10:09:52.0000000', N'0') GO @@ -5817,18 +5813,51 @@ IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[sy DROP TABLE [dbo].[system_dict_type] GO -CREATE TABLE [dbo].[system_dict_type] ( - [id] bigint IDENTITY(1,1) NOT NULL, - [name] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, - [type] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, - [status] tinyint NOT NULL, - [remark] nvarchar(500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, - [creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, - [create_time] datetime2(7) NOT NULL, - [updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, - [update_time] datetime2(7) NOT NULL, - [deleted] bit DEFAULT 0 NOT NULL -) +CREATE TABLE [dbo].[system_dict_type] +( + [ + id] + bigint + IDENTITY +( + 1, + 1 +) NOT NULL, + [name] nvarchar +( + 100 +) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + [type] nvarchar +( + 100 +) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + [status] tinyint NOT NULL, + [remark] nvarchar +( + 500 +) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [creator] nvarchar +( + 64 +) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [create_time] datetime2 +( + 7 +) NOT NULL, + [updater] nvarchar +( + 64 +) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [update_time] datetime2 +( + 7 +) NOT NULL, + [deleted_time] datetime2 +( + 7 +), + [deleted] bit DEFAULT 0 NOT NULL + ) GO ALTER TABLE [dbo].[system_dict_type] SET (LOCK_ESCALATION = TABLE) @@ -5886,26 +5915,29 @@ GO EXEC sp_addextendedproperty 'MS_Description', N'更新者', 'SCHEMA', N'dbo', -'TABLE', N'system_dict_type', -'COLUMN', N'updater' -GO - -EXEC sp_addextendedproperty -'MS_Description', N'更新时间', -'SCHEMA', N'dbo', -'TABLE', N'system_dict_type', -'COLUMN', N'update_time' -GO - -EXEC sp_addextendedproperty -'MS_Description', N'是否删除', -'SCHEMA', N'dbo', -'TABLE', N'system_dict_type', -'COLUMN', N'deleted' -GO - -EXEC sp_addextendedproperty -'MS_Description', N'字典类型表', + 'TABLE', N'system_dict_type', + 'COLUMN', N'updater' + GO + EXEC sp_addextendedproperty + 'MS_Description', N'更新时间', + 'SCHEMA', N'dbo', + 'TABLE', N'system_dict_type', + 'COLUMN', N'update_time' + GO + EXEC sp_addextendedproperty + 'MS_Description', N'删除时间', + 'SCHEMA', N'dbo', + 'TABLE', N'system_dict_type', + 'COLUMN', N'deleted_time' + GO + EXEC sp_addextendedproperty + 'MS_Description', N'是否删除', + 'SCHEMA', N'dbo', + 'TABLE', N'system_dict_type', + 'COLUMN', N'deleted' + GO + EXEC sp_addextendedproperty + 'MS_Description', N'字典类型表', 'SCHEMA', N'dbo', 'TABLE', N'system_dict_type' GO @@ -9623,9 +9655,6 @@ GO SET IDENTITY_INSERT [dbo].[system_sms_channel] ON GO -INSERT INTO [dbo].[system_sms_channel] ([id], [signature], [code], [status], [remark], [api_key], [api_secret], [callback_url], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'1', N'芋道', N'YUN_PIAN', N'0', N'呵呵呵哒', N'1555a14277cb8a608cf45a9e6a80d510', NULL, N'http://vdwapu.natappfree.cc/admin-api/system/sms/callback/yunpian', N'', N'2021-03-31 06:12:20.0000000', N'1', N'2022-02-23 16:48:44.0000000', N'0') -GO - INSERT INTO [dbo].[system_sms_channel] ([id], [signature], [code], [status], [remark], [api_key], [api_secret], [callback_url], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'2', N'Ballcat', N'ALIYUN', N'0', N'啦啦啦', N'LTAI5tCnKso2uG3kJ5gRav88', N'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, N'', N'2021-03-31 11:53:10.0000000', N'1', N'2021-04-14 00:08:37.0000000', N'0') GO @@ -11348,7 +11377,7 @@ GO -- Primary Key structure for table QRTZ_CALENDARS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_CALENDARS] ADD CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [CALENDAR_NAME]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11369,7 +11398,7 @@ GO -- Primary Key structure for table QRTZ_CRON_TRIGGERS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [TRIGGER_NAME], [TRIGGER_GROUP]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11378,7 +11407,7 @@ GO -- Primary Key structure for table QRTZ_FIRED_TRIGGERS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] ADD CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [ENTRY_ID]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11387,7 +11416,7 @@ GO -- Primary Key structure for table QRTZ_JOB_DETAILS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] ADD CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [JOB_NAME], [JOB_GROUP]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11396,7 +11425,7 @@ GO -- Primary Key structure for table QRTZ_LOCKS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_LOCKS] ADD CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [LOCK_NAME]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11405,7 +11434,7 @@ GO -- Primary Key structure for table QRTZ_PAUSED_TRIGGER_GRPS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] ADD CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [TRIGGER_GROUP]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11414,7 +11443,7 @@ GO -- Primary Key structure for table QRTZ_SCHEDULER_STATE -- ---------------------------- ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] ADD CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY CLUSTERED ([SCHED_NAME], [INSTANCE_NAME]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11435,7 +11464,7 @@ GO -- Primary Key structure for table QRTZ_SIMPLE_TRIGGERS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [TRIGGER_NAME], [TRIGGER_GROUP]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11456,7 +11485,7 @@ GO -- Primary Key structure for table QRTZ_SIMPROP_TRIGGERS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [TRIGGER_NAME], [TRIGGER_GROUP]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11477,7 +11506,7 @@ GO -- Primary Key structure for table QRTZ_TRIGGERS -- ---------------------------- ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY CLUSTERED ([SCHED_NAME], [TRIGGER_NAME], [TRIGGER_GROUP]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11493,7 +11522,7 @@ GO -- Primary Key structure for table bpm_form -- ---------------------------- ALTER TABLE [dbo].[bpm_form] ADD CONSTRAINT [PK__bpm_form__3213E83F86C2B27F] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11509,7 +11538,7 @@ GO -- Primary Key structure for table bpm_oa_leave -- ---------------------------- ALTER TABLE [dbo].[bpm_oa_leave] ADD CONSTRAINT [PK__bpm_oa_l__3213E83F3569F596] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11525,7 +11554,7 @@ GO -- Primary Key structure for table bpm_process_definition_ext -- ---------------------------- ALTER TABLE [dbo].[bpm_process_definition_ext] ADD CONSTRAINT [PK__bpm_proc__3213E83F0A8AB015] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11541,7 +11570,7 @@ GO -- Primary Key structure for table bpm_process_instance_ext -- ---------------------------- ALTER TABLE [dbo].[bpm_process_instance_ext] ADD CONSTRAINT [PK__bpm_proc__3213E83FFD88328F] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11557,7 +11586,7 @@ GO -- Primary Key structure for table bpm_task_assign_rule -- ---------------------------- ALTER TABLE [dbo].[bpm_task_assign_rule] ADD CONSTRAINT [PK__bpm_task__3213E83F474371C5] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11573,7 +11602,7 @@ GO -- Primary Key structure for table bpm_task_ext -- ---------------------------- ALTER TABLE [dbo].[bpm_task_ext] ADD CONSTRAINT [PK__bpm_task__3213E83FD8AFE1F9] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11589,7 +11618,7 @@ GO -- Primary Key structure for table bpm_user_group -- ---------------------------- ALTER TABLE [dbo].[bpm_user_group] ADD CONSTRAINT [PK__bpm_user__3213E83F25E4725B] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11605,7 +11634,7 @@ GO -- Primary Key structure for table infra_api_access_log -- ---------------------------- ALTER TABLE [dbo].[infra_api_access_log] ADD CONSTRAINT [PK__infra_ap__3213E83F04F27A05] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11621,7 +11650,7 @@ GO -- Primary Key structure for table infra_api_error_log -- ---------------------------- ALTER TABLE [dbo].[infra_api_error_log] ADD CONSTRAINT [PK__infra_ap__3213E83FCA2446D4] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11637,7 +11666,7 @@ GO -- Primary Key structure for table infra_codegen_column -- ---------------------------- ALTER TABLE [dbo].[infra_codegen_column] ADD CONSTRAINT [PK__infra_co__3213E83FA9EC5005] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11653,7 +11682,7 @@ GO -- Primary Key structure for table infra_codegen_table -- ---------------------------- ALTER TABLE [dbo].[infra_codegen_table] ADD CONSTRAINT [PK__infra_co__3213E83F555031D0] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11662,7 +11691,7 @@ GO -- Primary Key structure for table infra_config -- ---------------------------- ALTER TABLE [dbo].[infra_config] ADD CONSTRAINT [PK__infra_co__3213E83FF4C71E85] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11678,7 +11707,7 @@ GO -- Primary Key structure for table infra_data_source_config -- ---------------------------- ALTER TABLE [dbo].[infra_data_source_config] ADD CONSTRAINT [PK__infra_da__3213E83F02D21AEB] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11701,7 +11730,7 @@ GO -- Primary Key structure for table infra_file_config -- ---------------------------- ALTER TABLE [dbo].[infra_file_config] ADD CONSTRAINT [PK__infra_fi__3213E83F8A7903EA] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11717,7 +11746,7 @@ GO -- Primary Key structure for table infra_file_content -- ---------------------------- ALTER TABLE [dbo].[infra_file_content] ADD CONSTRAINT [PK__infra_fi__3213E83F033E6045] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11733,7 +11762,7 @@ GO -- Primary Key structure for table infra_job -- ---------------------------- ALTER TABLE [dbo].[infra_job] ADD CONSTRAINT [PK__infra_jo__3213E83F3C7DE10C] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11749,7 +11778,7 @@ GO -- Primary Key structure for table infra_job_log -- ---------------------------- ALTER TABLE [dbo].[infra_job_log] ADD CONSTRAINT [PK__infra_jo__3213E83F4CA8F353] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11772,7 +11801,7 @@ GO -- Primary Key structure for table member_user -- ---------------------------- ALTER TABLE [dbo].[member_user] ADD CONSTRAINT [PK__member_u__3213E83F0A9AEC0B] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11788,7 +11817,7 @@ GO -- Primary Key structure for table pay_app -- ---------------------------- ALTER TABLE [dbo].[pay_app] ADD CONSTRAINT [PK__pay_app__3213E83FB26E0A6B] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11804,7 +11833,7 @@ GO -- Primary Key structure for table pay_channel -- ---------------------------- ALTER TABLE [dbo].[pay_channel] ADD CONSTRAINT [PK__pay_chan__3213E83F2556A7FC] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11820,7 +11849,7 @@ GO -- Primary Key structure for table pay_merchant -- ---------------------------- ALTER TABLE [dbo].[pay_merchant] ADD CONSTRAINT [PK__pay_merc__3213E83F010D02B8] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11836,7 +11865,7 @@ GO -- Primary Key structure for table pay_notify_log -- ---------------------------- ALTER TABLE [dbo].[pay_notify_log] ADD CONSTRAINT [PK__pay_noti__3213E83F5F4B3447] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11852,7 +11881,7 @@ GO -- Primary Key structure for table pay_notify_task -- ---------------------------- ALTER TABLE [dbo].[pay_notify_task] ADD CONSTRAINT [PK__pay_noti__3213E83FB9215103] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11868,7 +11897,7 @@ GO -- Primary Key structure for table pay_order -- ---------------------------- ALTER TABLE [dbo].[pay_order] ADD CONSTRAINT [PK__pay_orde__3213E83F34C95271] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11884,7 +11913,7 @@ GO -- Primary Key structure for table pay_order_extension -- ---------------------------- ALTER TABLE [dbo].[pay_order_extension] ADD CONSTRAINT [PK__pay_orde__3213E83F5ACB776F] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11900,7 +11929,7 @@ GO -- Primary Key structure for table pay_refund -- ---------------------------- ALTER TABLE [dbo].[pay_refund] ADD CONSTRAINT [PK__pay_refu__3213E83FBE1B54AC] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11916,7 +11945,7 @@ GO -- Primary Key structure for table system_dept -- ---------------------------- ALTER TABLE [dbo].[system_dept] ADD CONSTRAINT [PK__system_d__3213E83FFA72847C] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11932,7 +11961,7 @@ GO -- Primary Key structure for table system_dict_data -- ---------------------------- ALTER TABLE [dbo].[system_dict_data] ADD CONSTRAINT [PK__system_d__3213E83F20407597] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11948,7 +11977,7 @@ GO -- Primary Key structure for table system_dict_type -- ---------------------------- ALTER TABLE [dbo].[system_dict_type] ADD CONSTRAINT [PK__system_d__3213E83F7C36B1FD] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11964,7 +11993,7 @@ GO -- Primary Key structure for table system_error_code -- ---------------------------- ALTER TABLE [dbo].[system_error_code] ADD CONSTRAINT [PK__system_e__3213E83F68B8DFD0] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11980,7 +12009,7 @@ GO -- Primary Key structure for table system_login_log -- ---------------------------- ALTER TABLE [dbo].[system_login_log] ADD CONSTRAINT [PK__system_l__3213E83F717953E9] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -11996,7 +12025,7 @@ GO -- Primary Key structure for table system_menu -- ---------------------------- ALTER TABLE [dbo].[system_menu] ADD CONSTRAINT [PK__system_m__3213E83F14175801] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12012,7 +12041,7 @@ GO -- Primary Key structure for table system_notice -- ---------------------------- ALTER TABLE [dbo].[system_notice] ADD CONSTRAINT [PK__system_n__3213E83FA158BA8D] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12035,7 +12064,7 @@ GO -- Primary Key structure for table system_oauth2_approve -- ---------------------------- ALTER TABLE [dbo].[system_oauth2_approve] ADD CONSTRAINT [PK__system_o__3213E83F7CC08ED6] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12058,7 +12087,7 @@ GO -- Primary Key structure for table system_oauth2_code -- ---------------------------- ALTER TABLE [dbo].[system_oauth2_code] ADD CONSTRAINT [PK__system_o__3213E83F38C13543] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12074,7 +12103,7 @@ GO -- Primary Key structure for table system_oauth2_refresh_token -- ---------------------------- ALTER TABLE [dbo].[system_oauth2_refresh_token] ADD CONSTRAINT [PK__system_o__3213E83FCFB541CC] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12090,7 +12119,7 @@ GO -- Primary Key structure for table system_operate_log -- ---------------------------- ALTER TABLE [dbo].[system_operate_log] ADD CONSTRAINT [PK__system_o__3213E83F85EC81FD] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12106,7 +12135,7 @@ GO -- Primary Key structure for table system_post -- ---------------------------- ALTER TABLE [dbo].[system_post] ADD CONSTRAINT [PK__system_p__3213E83FBC098F34] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12122,7 +12151,7 @@ GO -- Primary Key structure for table system_role -- ---------------------------- ALTER TABLE [dbo].[system_role] ADD CONSTRAINT [PK__system_r__3213E83F209B43F2] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12138,7 +12167,7 @@ GO -- Primary Key structure for table system_role_menu -- ---------------------------- ALTER TABLE [dbo].[system_role_menu] ADD CONSTRAINT [PK__system_r__3213E83F6F1E4A9B] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12154,7 +12183,7 @@ GO -- Primary Key structure for table system_sensitive_word -- ---------------------------- ALTER TABLE [dbo].[system_sensitive_word] ADD CONSTRAINT [PK__system_s__3213E83FFFD8E555] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12170,7 +12199,7 @@ GO -- Primary Key structure for table system_sms_channel -- ---------------------------- ALTER TABLE [dbo].[system_sms_channel] ADD CONSTRAINT [PK__system_s__3213E83FA96B966E] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12186,7 +12215,7 @@ GO -- Primary Key structure for table system_sms_code -- ---------------------------- ALTER TABLE [dbo].[system_sms_code] ADD CONSTRAINT [PK__system_s__3213E83F825CBCB9] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12202,7 +12231,7 @@ GO -- Primary Key structure for table system_sms_log -- ---------------------------- ALTER TABLE [dbo].[system_sms_log] ADD CONSTRAINT [PK__system_s__3213E83F5F1968A9] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12218,7 +12247,7 @@ GO -- Primary Key structure for table system_sms_template -- ---------------------------- ALTER TABLE [dbo].[system_sms_template] ADD CONSTRAINT [PK__system_s__3213E83F5C91CA37] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12234,7 +12263,7 @@ GO -- Primary Key structure for table system_social_user -- ---------------------------- ALTER TABLE [dbo].[system_social_user] ADD CONSTRAINT [PK__system_s__3213E83F6EF3863C] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12250,7 +12279,7 @@ GO -- Primary Key structure for table system_social_user_bind -- ---------------------------- ALTER TABLE [dbo].[system_social_user_bind] ADD CONSTRAINT [PK__system_s__3213E83F21F44049] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12266,7 +12295,7 @@ GO -- Primary Key structure for table system_tenant -- ---------------------------- ALTER TABLE [dbo].[system_tenant] ADD CONSTRAINT [PK__system_t__3213E83FAF444092] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12282,7 +12311,7 @@ GO -- Primary Key structure for table system_tenant_package -- ---------------------------- ALTER TABLE [dbo].[system_tenant_package] ADD CONSTRAINT [PK__system_t__3213E83FA2213DB5] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12298,7 +12327,7 @@ GO -- Primary Key structure for table system_user_post -- ---------------------------- ALTER TABLE [dbo].[system_user_post] ADD CONSTRAINT [PK__system_u__3213E83F56DD4107] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12314,7 +12343,7 @@ GO -- Primary Key structure for table system_user_role -- ---------------------------- ALTER TABLE [dbo].[system_user_role] ADD CONSTRAINT [PK__system_u__3213E83F3593F652] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO @@ -12330,7 +12359,7 @@ GO -- Primary Key structure for table system_users -- ---------------------------- ALTER TABLE [dbo].[system_users] ADD CONSTRAINT [PK__system_u__3213E83F7CF2516E] PRIMARY KEY CLUSTERED ([id]) -WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) +WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 09b74a9e9..78d3bcf34 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,57 +14,57 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.6.4-snapshot + 1.6.5-snapshot - 2.6.13 + 2.7.6 3.0.3 - 1.6.7 + 1.6.8 2.5 - 1.2.14 + 1.2.15 3.5.2 3.5.2 - 3.5.2 - 3.17.7 - + 3.6.0 + 3.18.0 - 2.2.2 + 2.2.3 1.7.1 8.12.0 - 2.6.9 + 2.7.9 0.33.0 - 7.2.9.RELEASE - 1.0.4 + 7.2.11.RELEASE + 1.0.5 4.8.0 6.7.2 1.18.24 1.5.3.Final - 5.8.9 - 3.1.2 + 5.8.10 + 3.1.3 2.3 1.0.5 1.2.83 31.1-jre 5.1.0 - 2.14.0 + 2.14.2 3.8.0 0.1.55 - 2.5.0 + 2.6.0 1.3.0 - 4.1.82.Final + 4.1.85.Final - 8.2.2 - 4.6.2 + 3.0.0 + 4.10.0 + 8.4.6 + 4.6.3 2.2.1 - 3.1.561 - 1.2.7 + 3.1.637 1.4.0 - 1.5.3 + 1.5.6 2.12.2 @@ -130,6 +130,11 @@ yudao-spring-boot-starter-biz-error-code ${revision} + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + ${revision} + cn.iocoder.boot yudao-spring-boot-starter-captcha @@ -497,6 +502,7 @@ commons-net ${commons-net.version} + com.jcraft jsch @@ -510,6 +516,16 @@ + + com.squareup.okio + okio + ${okio.version} + + + com.squareup.okhttp3 + okhttp + ${okhttp3.version} + cn.iocoder.boot yudao-spring-boot-starter-file @@ -522,11 +538,6 @@ - - com.yunpian.sdk - yunpian-java-sdk - ${yunpian-java-sdk.version} - com.aliyun aliyun-java-sdk-core @@ -549,7 +560,7 @@ com.tencentcloudapi - tencentcloud-sdk-java + tencentcloud-sdk-java-sms ${tencentcloud-sdk-java.version} @@ -565,6 +576,12 @@ org.jeecgframework.jimureport jimureport-spring-boot-starter ${jimureport.version} + + + com.alibaba + druid + + xerces diff --git a/yudao-example/yudao-sso-demo-by-code/pom.xml b/yudao-example/yudao-sso-demo-by-code/pom.xml index d1303da79..f6a168f76 100644 --- a/yudao-example/yudao-sso-demo-by-code/pom.xml +++ b/yudao-example/yudao-sso-demo-by-code/pom.xml @@ -21,7 +21,7 @@ 8 UTF-8 - 2.6.13 + 2.7.6 @@ -52,7 +52,7 @@ cn.hutool hutool-all - 5.8.9 + 5.8.10 diff --git a/yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java b/yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java index a81330fd2..0a71a650f 100644 --- a/yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java +++ b/yudao-example/yudao-sso-demo-by-code/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java @@ -2,17 +2,20 @@ package cn.iocoder.yudao.ssodemo.framework.config; import cn.iocoder.yudao.ssodemo.framework.core.filter.TokenAuthenticationFilter; import cn.iocoder.yudao.ssodemo.framework.core.handler.AccessDeniedHandlerImpl; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.annotation.Resource; @Configuration(proxyBeanMethods = false) -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { +@EnableWebSecurity +public class SecurityConfiguration{ @Resource private TokenAuthenticationFilter tokenAuthenticationFilter; @@ -22,8 +25,8 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Resource private AuthenticationEntryPoint authenticationEntryPoint; - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { + @Bean + protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { // 设置 URL 安全权限 httpSecurity.csrf().disable() // 禁用 CSRF 保护 .authorizeRequests() @@ -43,6 +46,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { // 添加 Token Filter httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + return httpSecurity.build(); } } diff --git a/yudao-example/yudao-sso-demo-by-password/pom.xml b/yudao-example/yudao-sso-demo-by-password/pom.xml index 4f05d375a..c00032169 100644 --- a/yudao-example/yudao-sso-demo-by-password/pom.xml +++ b/yudao-example/yudao-sso-demo-by-password/pom.xml @@ -21,7 +21,7 @@ 8 UTF-8 - 2.6.13 + 2.7.6 @@ -52,7 +52,7 @@ cn.hutool hutool-all - 5.8.9 + 5.8.10 diff --git a/yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java b/yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java index a81330fd2..19631a3a4 100644 --- a/yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java +++ b/yudao-example/yudao-sso-demo-by-password/src/main/java/cn/iocoder/yudao/ssodemo/framework/config/SecurityConfiguration.java @@ -2,17 +2,20 @@ package cn.iocoder.yudao.ssodemo.framework.config; import cn.iocoder.yudao.ssodemo.framework.core.filter.TokenAuthenticationFilter; import cn.iocoder.yudao.ssodemo.framework.core.handler.AccessDeniedHandlerImpl; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.annotation.Resource; @Configuration(proxyBeanMethods = false) -public class SecurityConfiguration extends WebSecurityConfigurerAdapter { +@EnableWebSecurity +public class SecurityConfiguration { @Resource private TokenAuthenticationFilter tokenAuthenticationFilter; @@ -22,8 +25,8 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Resource private AuthenticationEntryPoint authenticationEntryPoint; - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { + @Bean + protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { // 设置 URL 安全权限 httpSecurity.csrf().disable() // 禁用 CSRF 保护 .authorizeRequests() @@ -43,6 +46,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { // 添加 Token Filter httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + return httpSecurity.build(); } } diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index d95fdda02..1928aa88c 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -36,6 +36,7 @@ yudao-spring-boot-starter-biz-tenant yudao-spring-boot-starter-biz-data-permission yudao-spring-boot-starter-biz-error-code + yudao-spring-boot-starter-biz-ip yudao-spring-boot-starter-flowable yudao-spring-boot-starter-captcha diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/CommonStatusEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/CommonStatusEnum.java index cd1b9dc5e..7b07fa1f5 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/CommonStatusEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/CommonStatusEnum.java @@ -20,7 +20,6 @@ public enum CommonStatusEnum implements IntArrayValuable { public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getStatus).toArray(); - /** * 状态值 */ diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java index cb9e530b7..91597748d 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java @@ -15,11 +15,12 @@ import java.util.Arrays; @Getter public enum TerminalEnum implements IntArrayValuable { - //TODO terminal 重复,请参考 '订单来源终端:[1:小程序 2:H5 3:iOS 4:安卓]' - MINI_PROGRAM(1, "小程序"), - H5(2, "H5"), - IOS(3, "iOS"), - ANDROID(3, "安卓"),; + WECHAT_MINI_PROGRAM(10, "微信小程序"), + WECHAT_WAP(11, "微信公众号"), + H5(20, "H5 网页"), + IOS(31, "苹果 App"), + ANDROID(32, "安卓 App"), + ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TerminalEnum::getTerminal).toArray(); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java index ec380032a..bc5bc5cb8 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/SetUtils.java @@ -11,6 +11,7 @@ import java.util.Set; */ public class SetUtils { + @SafeVarargs public static Set asSet(T... objs) { return new HashSet<>(Arrays.asList(objs)); } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index b4cb94e1f..a329fb177 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -25,6 +25,8 @@ public class DateUtils { public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss"; + public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss"; + /** * 将 LocalDateTime 转换成 Date * @@ -83,11 +85,6 @@ public class DateUtils { return buildTime(year, mouth, day, 0, 0, 0); } - @Deprecated - public static LocalDateTime buildLocalDateTime(int year, int mouth, int day) { - return LocalDateTime.of(year, mouth, day, 0, 0, 0); - } - /** * 创建指定时间 * @@ -132,11 +129,6 @@ public class DateUtils { return a.isAfter(b) ? a : b; } - @Deprecated - public static boolean afterNow(LocalDateTime localDateTime) { - return localDateTime.isAfter(LocalDateTime.now()); - } - /** * 计算当期时间相差的日期 * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 7af32ea82..a29d5fb2e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -12,6 +12,11 @@ import java.time.LocalDateTime; */ public class LocalDateTimeUtils { + /** + * 空的 LocalDateTime 对象,主要用于 DB 唯一索引的默认值 + */ + public static LocalDateTime EMPTY = buildTime(1970, 1, 1); + public static LocalDateTime addTime(Duration duration) { return LocalDateTime.now().plus(duration); } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java index a2f241d4c..c08316dc2 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java @@ -1,12 +1,10 @@ package cn.iocoder.yudao.framework.common.util.object; -import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Objects; import java.util.function.Consumer; /** @@ -47,6 +45,7 @@ public class ObjectUtils { return obj1.compareTo(obj2) > 0 ? obj1 : obj2; } + @SafeVarargs public static T defaultIfNull(T... array) { for (T item : array) { if (item != null) { @@ -56,6 +55,7 @@ public class ObjectUtils { return null; } + @SafeVarargs public static boolean equalsAny(T obj, T... array) { return Arrays.asList(array).contains(obj); } diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java index 203b324af..a8b66787c 100644 --- a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java @@ -1,15 +1,15 @@ package cn.iocoder.yudao.framework.banner.config; import cn.iocoder.yudao.framework.banner.core.BannerApplicationRunner; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * Banner 的自动配置类 * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoBannerAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 416b89477..000000000 --- a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..e04c9b42c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDataPermissionAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDataPermissionAutoConfiguration.java index a3cac7d82..445319883 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDataPermissionAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDataPermissionAutoConfiguration.java @@ -7,8 +7,8 @@ import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRuleFac import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRuleFactoryImpl; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import java.util.List; @@ -17,7 +17,7 @@ import java.util.List; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoDataPermissionAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java index 642c40d51..6016fcdad 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissi import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import java.util.List; @@ -16,7 +16,7 @@ import java.util.List; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @ConditionalOnClass(LoginUser.class) @ConditionalOnBean(value = {PermissionApi.class, DeptDataPermissionRuleCustomizer.class}) public class YudaoDeptDataPermissionAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java index 7f9a74a61..ae73963c4 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule; +import cn.iocoder.yudao.framework.expression.OrExpressionX; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.yudao.framework.security.core.LoginUser; @@ -20,7 +21,6 @@ import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.NullValue; -import net.sf.jsqlparser.expression.operators.conditional.OrExpression; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.InExpression; @@ -143,8 +143,8 @@ public class DeptDataPermissionRule implements DataPermissionRule { if (userExpression == null) { return deptExpression; } - // 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE dept_id IN ? OR user_id = ? - return new OrExpression(deptExpression, userExpression); + // 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE (dept_id IN ? OR user_id = ?) + return new OrExpressionX(deptExpression, userExpression); } private Expression buildDeptExpression(String tableName, Alias tableAlias, Set deptIds) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 1a4c029c9..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.datapermission.config.YudaoDataPermissionAutoConfiguration,\ - cn.iocoder.yudao.framework.datapermission.config.YudaoDeptDataPermissionAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..c5d0cd35d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.datapermission.config.YudaoDataPermissionAutoConfiguration +cn.iocoder.yudao.framework.datapermission.config.YudaoDeptDataPermissionAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/YudaoDictAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/YudaoDictAutoConfiguration.java index d0b985cd5..1b29fd165 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/YudaoDictAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/java/cn/iocoder/yudao/framework/dict/config/YudaoDictAutoConfiguration.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.framework.dict.config; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.module.system.api.dict.DictDataApi; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoDictAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 3986b1c2b..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.dict.config.YudaoDictAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..2125cee93 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.dict.config.YudaoDictAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeConfiguration.java index 85711d3d7..74c21f189 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeConfiguration.java @@ -6,10 +6,10 @@ import cn.iocoder.yudao.framework.errorcode.core.loader.ErrorCodeLoader; import cn.iocoder.yudao.framework.errorcode.core.loader.ErrorCodeLoaderImpl; import cn.iocoder.yudao.module.system.api.errorcode.ErrorCodeApi; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; /** @@ -17,7 +17,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @ConditionalOnProperty(prefix = "yudao.error-code", value = "enable", matchIfMissing = true) // 允许使用 yudao.error-code.enable=false 禁用访问日志 @EnableConfigurationProperties(ErrorCodeProperties.class) @EnableScheduling // 开启调度任务的功能,因为 ErrorCodeRemoteLoader 通过定时刷新错误码 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring.factories deleted file mode 100644 index ab9528c6e..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..69aa25696 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml new file mode 100644 index 000000000..f30ce1255 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml @@ -0,0 +1,59 @@ + + + + yudao-framework + cn.iocoder.boot + ${revision} + + 4.0.0 + yudao-spring-boot-starter-biz-ip + jar + + ${project.artifactId} + IP 拓展,支持如下功能: + 1. IP 功能:查询 IP 对应的城市信息 + 基于 https://gitee.com/lionsoul/ip2region 实现 + 2. 城市功能:查询城市编码对应的城市信息 + 基于 https://github.com/modood/Administrative-divisions-of-China 实现 + + https://github.com/YunaiV/ruoyi-vue-pro + + + 2.6.6 + + + + + cn.iocoder.boot + yudao-common + + + + + org.lionsoul + ip2region + ${ip2region.version} + + + + org.projectlombok + lombok + + + + org.slf4j + slf4j-api + provided + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/Area.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/Area.java new file mode 100644 index 000000000..dcc94422a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/Area.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.framework.ip.core; + +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 区域节点,包括国家、省份、城市、地区等信息 + * + * 数据可见 resources/area.csv 文件 + * + * @author 芋道源码 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Area { + + /** + * 编号 - 全球,即根目录 + */ + public static final Integer ID_GLOBAL = 0; + /** + * 编号 - 中国 + */ + public static final Integer ID_CHINA = 1; + + /** + * 编号 + */ + private Integer id; + /** + * 名字 + */ + private String name; + /** + * 类型 + * + * 枚举 {@link AreaTypeEnum} + */ + private Integer type; + + /** + * 父节点 + */ + private Area parent; + /** + * 子节点 + */ + private List children; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/enums/AreaTypeEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/enums/AreaTypeEnum.java new file mode 100644 index 000000000..916d88505 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/enums/AreaTypeEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.framework.ip.core.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * 区域类型枚举 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum AreaTypeEnum implements IntArrayValuable { + + COUNTRY(1, "国家"), + PROVINCE(2, "省份"), + CITY(3, "城市"), + DISTRICT(4, "地区"), // 县、镇、区等 + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AreaTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java new file mode 100644 index 000000000..c77f8be30 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.framework.ip.core.utils; + +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.text.csv.CsvRow; +import cn.hutool.core.text.csv.CsvUtil; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 区域工具类 + * + * @author 芋道源码 + */ +@Slf4j +public class AreaUtils { + + /** + * 初始化 SEARCHER + */ + @SuppressWarnings("InstantiationOfUtilityClass") + private final static AreaUtils INSTANCE = new AreaUtils(); + + + private static Map areas; + + private AreaUtils() { + long now = System.currentTimeMillis(); + areas = new HashMap<>(); + areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0, + null, new ArrayList<>())); + // 从 csv 中加载数据 + List rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows(); + rows.remove(0); // 删除 header + for (CsvRow row : rows) { + // 创建 Area 对象 + Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)), + null, new ArrayList<>()); + // 添加到 areas 中 + areas.put(area.getId(), area); + } + + // 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取 + for (CsvRow row : rows) { + Area area = areas.get(Integer.valueOf(row.get(0))); // 自己 + Area parent = areas.get(Integer.valueOf(row.get(3))); // 父 + Assert.isTrue(area != parent, "{}:父子节点相同", area.getName()); + area.setParent(parent); + parent.getChildren().add(area); + } + log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now); + } + + /** + * 获得指定编号对应的区域 + * + * @param id 区域编号 + * @return 区域 + */ + public static Area getArea(Integer id) { + return areas.get(id); + } + + /** + * 格式化区域 + * + * @param id 区域编号 + * @return 格式化后的区域 + */ + public static String format(Integer id) { + return format(id, " "); + } + + /** + * 格式化区域 + * + * 例如说: + * 1. id = “静安区”时:上海 上海市 静安区 + * 2. id = “上海市”时:上海 上海市 + * 3. id = “上海”时:上海 + * 4. id = “美国”时:美国 + * 当区域在中国时,默认不显示中国 + * + * @param id 区域编号 + * @param separator 分隔符 + * @return 格式化后的区域 + */ + public static String format(Integer id, String separator) { + // 获得区域 + Area area = areas.get(id); + if (area == null) { + return null; + } + + // 格式化 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < AreaTypeEnum.values().length; i++) { // 避免死循环 + sb.insert(0, area.getName()); + // “递归”父节点 + area = area.getParent(); + if (area == null + || ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况 + break; + } + sb.insert(0, separator); + } + return sb.toString(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java new file mode 100644 index 000000000..8ad794637 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtils.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.framework.ip.core.utils; + +import cn.hutool.core.io.resource.ResourceUtil; +import cn.iocoder.yudao.framework.ip.core.Area; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.lionsoul.ip2region.xdb.Searcher; + +import java.io.IOException; + +/** + * IP 工具类 + * + * IP 数据源来自 ip2region.xdb 精简版,基于 项目 + * + * @author wanglhup + */ +@Slf4j +public class IPUtils { + + /** + * 初始化 SEARCHER + */ + @SuppressWarnings("InstantiationOfUtilityClass") + private final static IPUtils INSTANCE = new IPUtils(); + + /** + * IP 查询器,启动加载到内存中 + */ + private static Searcher SEARCHER; + + /** + * 私有化构造 + */ + private IPUtils() { + try { + long now = System.currentTimeMillis(); + byte[] bytes = ResourceUtil.readBytes("ip2region.xdb"); + SEARCHER = Searcher.newWithBuffer(bytes); + log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now); + } catch (IOException e) { + log.error("启动加载 IPUtils 失败", e); + } + } + + /** + * 查询 IP 对应的地区编号 + * + * @param ip IP 地址,格式为 127.0.0.1 + * @return 地区id + */ + @SneakyThrows + public static Integer getAreaId(String ip) { + return Integer.parseInt(SEARCHER.search(ip)); + } + + /** + * 查询 IP 对应的地区编号 + * + * @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回 + * @return 地区编号 + */ + @SneakyThrows + public static Integer getAreaId(long ip) { + return Integer.parseInt(SEARCHER.search(ip)); + } + + /** + * 查询 IP 对应的地区 + * + * @param ip IP 地址,格式为 127.0.0.1 + * @return 地区 + */ + public static Area getArea(String ip) { + return AreaUtils.getArea(getAreaId(ip)); + } + + /** + * 查询 IP 对应的地区 + * + * @param ip IP 地址的时间戳,格式参考{@link Searcher#checkIP(String)} 的返回 + * @return 地区 + */ + public static Area getArea(long ip) { + return AreaUtils.getArea(getAreaId(ip)); + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/package-info.java new file mode 100644 index 000000000..9d422f594 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/package-info.java @@ -0,0 +1,11 @@ +/** + * IP 拓展,支持如下功能: + * + * 1. IP 功能:查询 IP 对应的城市信息 + * 基于 https://gitee.com/lionsoul/ip2region 实现 + * 2. 城市功能:查询城市编码对应的城市信息 + * 基于 https://github.com/modood/Administrative-divisions-of-China 实现 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.framework.ip; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv new file mode 100644 index 000000000..27e753c90 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv @@ -0,0 +1,3608 @@ +id,name,type,parentId +1,中国,1,0 +2,蒙古,1,0 +3,朝鲜,1,0 +4,韩国,1,0 +5,日本,1,0 +6,菲律宾,1,0 +7,越南,1,0 +8,老挝,1,0 +9,柬埔寨,1,0 +10,缅甸,1,0 +11,泰国,1,0 +12,马来西亚,1,0 +13,文莱,1,0 +14,新加坡,1,0 +15,印度尼西亚,1,0 +16,东帝汶,1,0 +17,尼泊尔,1,0 +18,不丹,1,0 +19,孟加拉国,1,0 +20,印度,1,0 +21,巴基斯坦,1,0 +22,斯里兰卡,1,0 +23,马尔代夫,1,0 +24,哈萨克斯坦,1,0 +25,吉尔吉斯斯坦,1,0 +26,塔吉克斯坦,1,0 +27,乌兹别克斯坦,1,0 +28,土库曼斯坦,1,0 +29,阿富汗,1,0 +30,伊拉克,1,0 +31,伊朗,1,0 +32,叙利亚,1,0 +33,约旦,1,0 +34,黎巴嫩,1,0 +35,以色列,1,0 +36,巴勒斯坦,1,0 +37,沙特阿拉伯,1,0 +38,巴林,1,0 +39,卡塔尔,1,0 +40,科威特,1,0 +41,阿拉伯联合酋长国,1,0 +42,阿曼,1,0 +43,也门,1,0 +44,格鲁吉亚,1,0 +45,亚美尼亚,1,0 +46,阿塞拜疆,1,0 +47,土耳其,1,0 +48,塞浦路斯,1,0 +49,芬兰,1,0 +50,瑞典,1,0 +51,挪威,1,0 +52,冰岛,1,0 +53,丹麦,1,0 +54,爱沙尼亚,1,0 +55,拉脱维亚,1,0 +56,立陶宛,1,0 +57,白俄罗斯,1,0 +58,俄罗斯,1,0 +59,乌克兰,1,0 +60,摩尔多瓦,1,0 +61,波兰,1,0 +62,捷克,1,0 +63,斯洛伐克,1,0 +64,匈牙利,1,0 +65,德国,1,0 +66,奥地利,1,0 +67,瑞士,1,0 +68,列支敦士登,1,0 +69,英国,1,0 +70,爱尔兰,1,0 +71,荷兰,1,0 +72,比利时,1,0 +73,卢森堡,1,0 +74,法国,1,0 +75,摩纳哥,1,0 +76,罗马尼亚,1,0 +77,保加利亚,1,0 +78,塞尔维亚,1,0 +79,马其顿,1,0 +80,阿尔巴尼亚,1,0 +81,希腊,1,0 +82,斯洛文尼亚,1,0 +83,克罗地亚,1,0 +84,波斯尼亚和墨塞哥维那,1,0 +85,意大利,1,0 +86,梵蒂冈,1,0 +87,圣马力诺,1,0 +88,马耳他,1,0 +89,西班牙,1,0 +90,葡萄牙,1,0 +91,安道尔共和国,1,0 +92,埃及,1,0 +93,利比亚,1,0 +94,苏丹,1,0 +95,突尼斯,1,0 +96,阿尔及利亚,1,0 +97,摩洛哥,1,0 +98,亚速尔群岛,1,0 +99,马德拉群岛,1,0 +100,埃塞俄比亚,1,0 +101,厄立特里亚,1,0 +102,索马里,1,0 +103,吉布提,1,0 +104,肯尼亚,1,0 +105,坦桑尼亚,1,0 +106,乌干达,1,0 +107,卢旺达,1,0 +108,布隆迪,1,0 +109,塞舌尔,1,0 +110,圣多美及普林西比,1,0 +111,塞内加尔,1,0 +112,冈比亚,1,0 +113,马里,1,0 +114,布基纳法索,1,0 +115,几内亚,1,0 +116,几内亚比绍,1,0 +117,佛得角,1,0 +118,塞拉利昂,1,0 +119,利比里亚,1,0 +120,科特迪瓦,1,0 +121,加纳,1,0 +122,多哥,1,0 +123,贝宁,1,0 +124,尼日尔,1,0 +125,加那利群岛,1,0 +126,赞比亚,1,0 +127,安哥拉,1,0 +128,津巴布韦,1,0 +129,马拉维,1,0 +130,莫桑比克,1,0 +131,博茨瓦纳,1,0 +132,纳米比亚,1,0 +133,南非,1,0 +134,斯威士兰,1,0 +135,莱索托,1,0 +136,马达加斯加,1,0 +137,科摩罗,1,0 +138,毛里求斯,1,0 +139,留尼旺,1,0 +140,圣赫勒拿,1,0 +141,澳大利亚,1,0 +142,新西兰,1,0 +143,巴布亚新几内亚,1,0 +144,所罗门群岛,1,0 +145,瓦努阿图共和国,1,0 +146,密克罗尼西亚,1,0 +147,马绍尔群岛,1,0 +148,帕劳,1,0 +149,瑙鲁,1,0 +150,基里巴斯,1,0 +151,图瓦卢,1,0 +152,萨摩亚,1,0 +153,斐济,1,0 +154,汤加,1,0 +155,库克群岛,1,0 +156,关岛,1,0 +157,新喀里多尼亚,1,0 +158,法属波利尼西亚,1,0 +159,皮特凯恩岛,1,0 +160,瓦利斯与富图纳,1,0 +161,纽埃,1,0 +162,托克劳,1,0 +163,美属萨摩亚,1,0 +164,北马里亚纳,1,0 +165,加拿大,1,0 +166,美国,1,0 +167,墨西哥,1,0 +168,格陵兰,1,0 +169,危地马拉,1,0 +170,伯利兹,1,0 +171,萨尔瓦多,1,0 +172,洪都拉斯,1,0 +173,尼加拉瓜,1,0 +174,哥斯达黎加,1,0 +175,巴拿马,1,0 +176,巴哈马,1,0 +177,古巴,1,0 +178,牙买加,1,0 +179,海地,1,0 +180,多米尼加共和国,1,0 +181,安提瓜和巴布达,1,0 +182,圣基茨和尼维斯,1,0 +183,多米尼克,1,0 +184,圣卢西亚,1,0 +185,圣文森特和格林纳丁斯,1,0 +186,格林纳达,1,0 +187,巴巴多斯,1,0 +188,特立尼达和多巴哥,1,0 +189,波多黎各,1,0 +190,英属维尔京群岛,1,0 +191,美属维尔京群岛,1,0 +192,安圭拉,1,0 +193,蒙特塞拉特岛,1,0 +194,瓜德罗普,1,0 +195,马提尼克,1,0 +196,荷属安的列斯,1,0 +197,阿鲁巴,1,0 +198,特克斯和凯科斯群岛,1,0 +199,开曼群岛,1,0 +200,百慕大,1,0 +201,哥伦比亚,1,0 +202,委内瑞拉,1,0 +203,圭亚那,1,0 +204,法属圭亚那,1,0 +205,苏里南,1,0 +206,厄瓜多尔,1,0 +207,秘鲁,1,0 +208,玻利维亚,1,0 +209,巴西,1,0 +210,智利,1,0 +211,阿根廷,1,0 +212,乌拉圭,1,0 +213,巴拉圭,1,0 +214,波黑,1,0 +215,直布罗陀,1,0 +216,新喀里多尼亚群岛,1,0 +217,瓦利斯和富图纳群岛,1,0 +218,泽西岛,1,0 +219,黑山,1,0 +220,英属马恩岛,1,0 +221,尼日利亚,1,0 +222,喀麦隆,1,0 +223,加蓬,1,0 +224,乍得,1,0 +225,刚果共和国,1,0 +226,中非共和国,1,0 +227,南苏丹,1,0 +228,赤道几内亚,1,0 +229,毛里塔尼亚,1,0 +230,刚果民主共和国,1,0 +231,留尼汪岛,1,0 +232,格陵兰岛,1,0 +233,法罗群岛,1,0 +234,根西岛,1,0 +235,百慕大群岛,1,0 +236,圣皮埃尔和密克隆群岛,1,0 +237,法属圣马丁,1,0 +238,奥兰群岛,1,0 +239,北马里亚纳群岛,1,0 +240,库拉索,1,0 +241,博内尔岛,1,0 +242,圣马丁岛,1,0 +243,圣巴泰勒米岛,1,0 +244,福克兰群岛,1,0 +245,圣多美和普林西比,1,0 +246,英属印度洋领地,1,0 +247,东萨摩亚,1,0 +248,诺福克岛,1,0 +110000,北京,2,1 +120000,天津,2,1 +130000,河北省,2,1 +140000,山西省,2,1 +150000,内蒙古自治区,2,1 +210000,辽宁省,2,1 +220000,吉林省,2,1 +230000,黑龙江省,2,1 +310000,上海,2,1 +320000,江苏省,2,1 +330000,浙江省,2,1 +340000,安徽省,2,1 +350000,福建省,2,1 +360000,江西省,2,1 +370000,山东省,2,1 +410000,河南省,2,1 +420000,湖北省,2,1 +430000,湖南省,2,1 +440000,广东省,2,1 +450000,广西壮族自治区,2,1 +460000,海南省,2,1 +500000,重庆,2,1 +510000,四川省,2,1 +520000,贵州省,2,1 +530000,云南省,2,1 +540000,西藏自治区,2,1 +610000,陕西省,2,1 +620000,甘肃省,2,1 +630000,青海省,2,1 +640000,宁夏回族自治区,2,1 +650000,新疆维吾尔自治区,2,1 +110100,北京市,3,110000 +120100,天津市,3,120000 +130100,石家庄市,3,130000 +130200,唐山市,3,130000 +130300,秦皇岛市,3,130000 +130400,邯郸市,3,130000 +130500,邢台市,3,130000 +130600,保定市,3,130000 +130700,张家口市,3,130000 +130800,承德市,3,130000 +130900,沧州市,3,130000 +131000,廊坊市,3,130000 +131100,衡水市,3,130000 +140100,太原市,3,140000 +140200,大同市,3,140000 +140300,阳泉市,3,140000 +140400,长治市,3,140000 +140500,晋城市,3,140000 +140600,朔州市,3,140000 +140700,晋中市,3,140000 +140800,运城市,3,140000 +140900,忻州市,3,140000 +141000,临汾市,3,140000 +141100,吕梁市,3,140000 +150100,呼和浩特市,3,150000 +150200,包头市,3,150000 +150300,乌海市,3,150000 +150400,赤峰市,3,150000 +150500,通辽市,3,150000 +150600,鄂尔多斯市,3,150000 +150700,呼伦贝尔市,3,150000 +150800,巴彦淖尔市,3,150000 +150900,乌兰察布市,3,150000 +152200,兴安盟,3,150000 +152500,锡林郭勒盟,3,150000 +152900,阿拉善盟,3,150000 +210100,沈阳市,3,210000 +210200,大连市,3,210000 +210300,鞍山市,3,210000 +210400,抚顺市,3,210000 +210500,本溪市,3,210000 +210600,丹东市,3,210000 +210700,锦州市,3,210000 +210800,营口市,3,210000 +210900,阜新市,3,210000 +211000,辽阳市,3,210000 +211100,盘锦市,3,210000 +211200,铁岭市,3,210000 +211300,朝阳市,3,210000 +211400,葫芦岛市,3,210000 +220100,长春市,3,220000 +220200,吉林市,3,220000 +220300,四平市,3,220000 +220400,辽源市,3,220000 +220500,通化市,3,220000 +220600,白山市,3,220000 +220700,松原市,3,220000 +220800,白城市,3,220000 +222400,延边朝鲜族自治州,3,220000 +230100,哈尔滨市,3,230000 +230200,齐齐哈尔市,3,230000 +230300,鸡西市,3,230000 +230400,鹤岗市,3,230000 +230500,双鸭山市,3,230000 +230600,大庆市,3,230000 +230700,伊春市,3,230000 +230800,佳木斯市,3,230000 +230900,七台河市,3,230000 +231000,牡丹江市,3,230000 +231100,黑河市,3,230000 +231200,绥化市,3,230000 +232700,大兴安岭地区,3,230000 +310100,上海市,3,310000 +320100,南京市,3,320000 +320200,无锡市,3,320000 +320300,徐州市,3,320000 +320400,常州市,3,320000 +320500,苏州市,3,320000 +320600,南通市,3,320000 +320700,连云港市,3,320000 +320800,淮安市,3,320000 +320900,盐城市,3,320000 +321000,扬州市,3,320000 +321100,镇江市,3,320000 +321200,泰州市,3,320000 +321300,宿迁市,3,320000 +330100,杭州市,3,330000 +330200,宁波市,3,330000 +330300,温州市,3,330000 +330400,嘉兴市,3,330000 +330500,湖州市,3,330000 +330600,绍兴市,3,330000 +330700,金华市,3,330000 +330800,衢州市,3,330000 +330900,舟山市,3,330000 +331000,台州市,3,330000 +331100,丽水市,3,330000 +340100,合肥市,3,340000 +340200,芜湖市,3,340000 +340300,蚌埠市,3,340000 +340400,淮南市,3,340000 +340500,马鞍山市,3,340000 +340600,淮北市,3,340000 +340700,铜陵市,3,340000 +340800,安庆市,3,340000 +341000,黄山市,3,340000 +341100,滁州市,3,340000 +341200,阜阳市,3,340000 +341300,宿州市,3,340000 +341500,六安市,3,340000 +341600,亳州市,3,340000 +341700,池州市,3,340000 +341800,宣城市,3,340000 +350100,福州市,3,350000 +350200,厦门市,3,350000 +350300,莆田市,3,350000 +350400,三明市,3,350000 +350500,泉州市,3,350000 +350600,漳州市,3,350000 +350700,南平市,3,350000 +350800,龙岩市,3,350000 +350900,宁德市,3,350000 +360100,南昌市,3,360000 +360200,景德镇市,3,360000 +360300,萍乡市,3,360000 +360400,九江市,3,360000 +360500,新余市,3,360000 +360600,鹰潭市,3,360000 +360700,赣州市,3,360000 +360800,吉安市,3,360000 +360900,宜春市,3,360000 +361000,抚州市,3,360000 +361100,上饶市,3,360000 +370100,济南市,3,370000 +370200,青岛市,3,370000 +370300,淄博市,3,370000 +370400,枣庄市,3,370000 +370500,东营市,3,370000 +370600,烟台市,3,370000 +370700,潍坊市,3,370000 +370800,济宁市,3,370000 +370900,泰安市,3,370000 +371000,威海市,3,370000 +371100,日照市,3,370000 +371300,临沂市,3,370000 +371400,德州市,3,370000 +371500,聊城市,3,370000 +371600,滨州市,3,370000 +371700,菏泽市,3,370000 +410100,郑州市,3,410000 +410200,开封市,3,410000 +410300,洛阳市,3,410000 +410400,平顶山市,3,410000 +410500,安阳市,3,410000 +410600,鹤壁市,3,410000 +410700,新乡市,3,410000 +410800,焦作市,3,410000 +410900,濮阳市,3,410000 +411000,许昌市,3,410000 +411100,漯河市,3,410000 +411200,三门峡市,3,410000 +411300,南阳市,3,410000 +411400,商丘市,3,410000 +411500,信阳市,3,410000 +411600,周口市,3,410000 +411700,驻马店市,3,410000 +419000,省直辖县级行政区划,3,410000 +420100,武汉市,3,420000 +420200,黄石市,3,420000 +420300,十堰市,3,420000 +420500,宜昌市,3,420000 +420600,襄阳市,3,420000 +420700,鄂州市,3,420000 +420800,荆门市,3,420000 +420900,孝感市,3,420000 +421000,荆州市,3,420000 +421100,黄冈市,3,420000 +421200,咸宁市,3,420000 +421300,随州市,3,420000 +422800,恩施土家族苗族自治州,3,420000 +429000,省直辖县级行政区划,3,420000 +430100,长沙市,3,430000 +430200,株洲市,3,430000 +430300,湘潭市,3,430000 +430400,衡阳市,3,430000 +430500,邵阳市,3,430000 +430600,岳阳市,3,430000 +430700,常德市,3,430000 +430800,张家界市,3,430000 +430900,益阳市,3,430000 +431000,郴州市,3,430000 +431100,永州市,3,430000 +431200,怀化市,3,430000 +431300,娄底市,3,430000 +433100,湘西土家族苗族自治州,3,430000 +440100,广州市,3,440000 +440200,韶关市,3,440000 +440300,深圳市,3,440000 +440400,珠海市,3,440000 +440500,汕头市,3,440000 +440600,佛山市,3,440000 +440700,江门市,3,440000 +440800,湛江市,3,440000 +440900,茂名市,3,440000 +441200,肇庆市,3,440000 +441300,惠州市,3,440000 +441400,梅州市,3,440000 +441500,汕尾市,3,440000 +441600,河源市,3,440000 +441700,阳江市,3,440000 +441800,清远市,3,440000 +441900,东莞市,3,440000 +442000,中山市,3,440000 +445100,潮州市,3,440000 +445200,揭阳市,3,440000 +445300,云浮市,3,440000 +450100,南宁市,3,450000 +450200,柳州市,3,450000 +450300,桂林市,3,450000 +450400,梧州市,3,450000 +450500,北海市,3,450000 +450600,防城港市,3,450000 +450700,钦州市,3,450000 +450800,贵港市,3,450000 +450900,玉林市,3,450000 +451000,百色市,3,450000 +451100,贺州市,3,450000 +451200,河池市,3,450000 +451300,来宾市,3,450000 +451400,崇左市,3,450000 +460100,海口市,3,460000 +460200,三亚市,3,460000 +460300,三沙市,3,460000 +460400,儋州市,3,460000 +469000,省直辖县级行政区划,3,460000 +500100,重庆市,3,500000 +510100,成都市,3,510000 +510300,自贡市,3,510000 +510400,攀枝花市,3,510000 +510500,泸州市,3,510000 +510600,德阳市,3,510000 +510700,绵阳市,3,510000 +510800,广元市,3,510000 +510900,遂宁市,3,510000 +511000,内江市,3,510000 +511100,乐山市,3,510000 +511300,南充市,3,510000 +511400,眉山市,3,510000 +511500,宜宾市,3,510000 +511600,广安市,3,510000 +511700,达州市,3,510000 +511800,雅安市,3,510000 +511900,巴中市,3,510000 +512000,资阳市,3,510000 +513200,阿坝藏族羌族自治州,3,510000 +513300,甘孜藏族自治州,3,510000 +513400,凉山彝族自治州,3,510000 +520100,贵阳市,3,520000 +520200,六盘水市,3,520000 +520300,遵义市,3,520000 +520400,安顺市,3,520000 +520500,毕节市,3,520000 +520600,铜仁市,3,520000 +522300,黔西南布依族苗族自治州,3,520000 +522600,黔东南苗族侗族自治州,3,520000 +522700,黔南布依族苗族自治州,3,520000 +530100,昆明市,3,530000 +530300,曲靖市,3,530000 +530400,玉溪市,3,530000 +530500,保山市,3,530000 +530600,昭通市,3,530000 +530700,丽江市,3,530000 +530800,普洱市,3,530000 +530900,临沧市,3,530000 +532300,楚雄彝族自治州,3,530000 +532500,红河哈尼族彝族自治州,3,530000 +532600,文山壮族苗族自治州,3,530000 +532800,西双版纳傣族自治州,3,530000 +532900,大理白族自治州,3,530000 +533100,德宏傣族景颇族自治州,3,530000 +533300,怒江傈僳族自治州,3,530000 +533400,迪庆藏族自治州,3,530000 +540100,拉萨市,3,540000 +540200,日喀则市,3,540000 +540300,昌都市,3,540000 +540400,林芝市,3,540000 +540500,山南市,3,540000 +540600,那曲市,3,540000 +542500,阿里地区,3,540000 +610100,西安市,3,610000 +610200,铜川市,3,610000 +610300,宝鸡市,3,610000 +610400,咸阳市,3,610000 +610500,渭南市,3,610000 +610600,延安市,3,610000 +610700,汉中市,3,610000 +610800,榆林市,3,610000 +610900,安康市,3,610000 +611000,商洛市,3,610000 +620100,兰州市,3,620000 +620200,嘉峪关市,3,620000 +620300,金昌市,3,620000 +620400,白银市,3,620000 +620500,天水市,3,620000 +620600,武威市,3,620000 +620700,张掖市,3,620000 +620800,平凉市,3,620000 +620900,酒泉市,3,620000 +621000,庆阳市,3,620000 +621100,定西市,3,620000 +621200,陇南市,3,620000 +622900,临夏回族自治州,3,620000 +623000,甘南藏族自治州,3,620000 +630100,西宁市,3,630000 +630200,海东市,3,630000 +632200,海北藏族自治州,3,630000 +632300,黄南藏族自治州,3,630000 +632500,海南藏族自治州,3,630000 +632600,果洛藏族自治州,3,630000 +632700,玉树藏族自治州,3,630000 +632800,海西蒙古族藏族自治州,3,630000 +640100,银川市,3,640000 +640200,石嘴山市,3,640000 +640300,吴忠市,3,640000 +640400,固原市,3,640000 +640500,中卫市,3,640000 +650100,乌鲁木齐市,3,650000 +650200,克拉玛依市,3,650000 +650400,吐鲁番市,3,650000 +650500,哈密市,3,650000 +652300,昌吉回族自治州,3,650000 +652700,博尔塔拉蒙古自治州,3,650000 +652800,巴音郭楞蒙古自治州,3,650000 +652900,阿克苏地区,3,650000 +653000,克孜勒苏柯尔克孜自治州,3,650000 +653100,喀什地区,3,650000 +653200,和田地区,3,650000 +654000,伊犁哈萨克自治州,3,650000 +654200,塔城地区,3,650000 +654300,阿勒泰地区,3,650000 +659000,自治区直辖县级行政区划,3,650000 +110101,东城区,4,110100 +110102,西城区,4,110100 +110105,朝阳区,4,110100 +110106,丰台区,4,110100 +110107,石景山区,4,110100 +110108,海淀区,4,110100 +110109,门头沟区,4,110100 +110111,房山区,4,110100 +110112,通州区,4,110100 +110113,顺义区,4,110100 +110114,昌平区,4,110100 +110115,大兴区,4,110100 +110116,怀柔区,4,110100 +110117,平谷区,4,110100 +110118,密云区,4,110100 +110119,延庆区,4,110100 +120101,和平区,4,120100 +120102,河东区,4,120100 +120103,河西区,4,120100 +120104,南开区,4,120100 +120105,河北区,4,120100 +120106,红桥区,4,120100 +120110,东丽区,4,120100 +120111,西青区,4,120100 +120112,津南区,4,120100 +120113,北辰区,4,120100 +120114,武清区,4,120100 +120115,宝坻区,4,120100 +120116,滨海新区,4,120100 +120117,宁河区,4,120100 +120118,静海区,4,120100 +120119,蓟州区,4,120100 +130102,长安区,4,130100 +130104,桥西区,4,130100 +130105,新华区,4,130100 +130107,井陉矿区,4,130100 +130108,裕华区,4,130100 +130109,藁城区,4,130100 +130110,鹿泉区,4,130100 +130111,栾城区,4,130100 +130121,井陉县,4,130100 +130123,正定县,4,130100 +130125,行唐县,4,130100 +130126,灵寿县,4,130100 +130127,高邑县,4,130100 +130128,深泽县,4,130100 +130129,赞皇县,4,130100 +130130,无极县,4,130100 +130131,平山县,4,130100 +130132,元氏县,4,130100 +130133,赵县,4,130100 +130171,石家庄高新技术产业开发区,4,130100 +130172,石家庄循环化工园区,4,130100 +130181,辛集市,4,130100 +130183,晋州市,4,130100 +130184,新乐市,4,130100 +130202,路南区,4,130200 +130203,路北区,4,130200 +130204,古冶区,4,130200 +130205,开平区,4,130200 +130207,丰南区,4,130200 +130208,丰润区,4,130200 +130209,曹妃甸区,4,130200 +130224,滦南县,4,130200 +130225,乐亭县,4,130200 +130227,迁西县,4,130200 +130229,玉田县,4,130200 +130271,河北唐山芦台经济开发区,4,130200 +130272,唐山市汉沽管理区,4,130200 +130273,唐山高新技术产业开发区,4,130200 +130274,河北唐山海港经济开发区,4,130200 +130281,遵化市,4,130200 +130283,迁安市,4,130200 +130284,滦州市,4,130200 +130302,海港区,4,130300 +130303,山海关区,4,130300 +130304,北戴河区,4,130300 +130306,抚宁区,4,130300 +130321,青龙满族自治县,4,130300 +130322,昌黎县,4,130300 +130324,卢龙县,4,130300 +130371,秦皇岛市经济技术开发区,4,130300 +130372,北戴河新区,4,130300 +130402,邯山区,4,130400 +130403,丛台区,4,130400 +130404,复兴区,4,130400 +130406,峰峰矿区,4,130400 +130407,肥乡区,4,130400 +130408,永年区,4,130400 +130423,临漳县,4,130400 +130424,成安县,4,130400 +130425,大名县,4,130400 +130426,涉县,4,130400 +130427,磁县,4,130400 +130430,邱县,4,130400 +130431,鸡泽县,4,130400 +130432,广平县,4,130400 +130433,馆陶县,4,130400 +130434,魏县,4,130400 +130435,曲周县,4,130400 +130471,邯郸经济技术开发区,4,130400 +130473,邯郸冀南新区,4,130400 +130481,武安市,4,130400 +130502,襄都区,4,130500 +130503,信都区,4,130500 +130505,任泽区,4,130500 +130506,南和区,4,130500 +130522,临城县,4,130500 +130523,内丘县,4,130500 +130524,柏乡县,4,130500 +130525,隆尧县,4,130500 +130528,宁晋县,4,130500 +130529,巨鹿县,4,130500 +130530,新河县,4,130500 +130531,广宗县,4,130500 +130532,平乡县,4,130500 +130533,威县,4,130500 +130534,清河县,4,130500 +130535,临西县,4,130500 +130571,河北邢台经济开发区,4,130500 +130581,南宫市,4,130500 +130582,沙河市,4,130500 +130602,竞秀区,4,130600 +130606,莲池区,4,130600 +130607,满城区,4,130600 +130608,清苑区,4,130600 +130609,徐水区,4,130600 +130623,涞水县,4,130600 +130624,阜平县,4,130600 +130626,定兴县,4,130600 +130627,唐县,4,130600 +130628,高阳县,4,130600 +130629,容城县,4,130600 +130630,涞源县,4,130600 +130631,望都县,4,130600 +130632,安新县,4,130600 +130633,易县,4,130600 +130634,曲阳县,4,130600 +130635,蠡县,4,130600 +130636,顺平县,4,130600 +130637,博野县,4,130600 +130638,雄县,4,130600 +130671,保定高新技术产业开发区,4,130600 +130672,保定白沟新城,4,130600 +130681,涿州市,4,130600 +130682,定州市,4,130600 +130683,安国市,4,130600 +130684,高碑店市,4,130600 +130702,桥东区,4,130700 +130703,桥西区,4,130700 +130705,宣化区,4,130700 +130706,下花园区,4,130700 +130708,万全区,4,130700 +130709,崇礼区,4,130700 +130722,张北县,4,130700 +130723,康保县,4,130700 +130724,沽源县,4,130700 +130725,尚义县,4,130700 +130726,蔚县,4,130700 +130727,阳原县,4,130700 +130728,怀安县,4,130700 +130730,怀来县,4,130700 +130731,涿鹿县,4,130700 +130732,赤城县,4,130700 +130771,张家口经济开发区,4,130700 +130772,张家口市察北管理区,4,130700 +130773,张家口市塞北管理区,4,130700 +130802,双桥区,4,130800 +130803,双滦区,4,130800 +130804,鹰手营子矿区,4,130800 +130821,承德县,4,130800 +130822,兴隆县,4,130800 +130824,滦平县,4,130800 +130825,隆化县,4,130800 +130826,丰宁满族自治县,4,130800 +130827,宽城满族自治县,4,130800 +130828,围场满族蒙古族自治县,4,130800 +130871,承德高新技术产业开发区,4,130800 +130881,平泉市,4,130800 +130902,新华区,4,130900 +130903,运河区,4,130900 +130921,沧县,4,130900 +130922,青县,4,130900 +130923,东光县,4,130900 +130924,海兴县,4,130900 +130925,盐山县,4,130900 +130926,肃宁县,4,130900 +130927,南皮县,4,130900 +130928,吴桥县,4,130900 +130929,献县,4,130900 +130930,孟村回族自治县,4,130900 +130971,河北沧州经济开发区,4,130900 +130972,沧州高新技术产业开发区,4,130900 +130973,沧州渤海新区,4,130900 +130981,泊头市,4,130900 +130982,任丘市,4,130900 +130983,黄骅市,4,130900 +130984,河间市,4,130900 +131002,安次区,4,131000 +131003,广阳区,4,131000 +131022,固安县,4,131000 +131023,永清县,4,131000 +131024,香河县,4,131000 +131025,大城县,4,131000 +131026,文安县,4,131000 +131028,大厂回族自治县,4,131000 +131071,廊坊经济技术开发区,4,131000 +131081,霸州市,4,131000 +131082,三河市,4,131000 +131102,桃城区,4,131100 +131103,冀州区,4,131100 +131121,枣强县,4,131100 +131122,武邑县,4,131100 +131123,武强县,4,131100 +131124,饶阳县,4,131100 +131125,安平县,4,131100 +131126,故城县,4,131100 +131127,景县,4,131100 +131128,阜城县,4,131100 +131171,河北衡水高新技术产业开发区,4,131100 +131172,衡水滨湖新区,4,131100 +131182,深州市,4,131100 +140105,小店区,4,140100 +140106,迎泽区,4,140100 +140107,杏花岭区,4,140100 +140108,尖草坪区,4,140100 +140109,万柏林区,4,140100 +140110,晋源区,4,140100 +140121,清徐县,4,140100 +140122,阳曲县,4,140100 +140123,娄烦县,4,140100 +140171,山西转型综合改革示范区,4,140100 +140181,古交市,4,140100 +140212,新荣区,4,140200 +140213,平城区,4,140200 +140214,云冈区,4,140200 +140215,云州区,4,140200 +140221,阳高县,4,140200 +140222,天镇县,4,140200 +140223,广灵县,4,140200 +140224,灵丘县,4,140200 +140225,浑源县,4,140200 +140226,左云县,4,140200 +140271,山西大同经济开发区,4,140200 +140302,城区,4,140300 +140303,矿区,4,140300 +140311,郊区,4,140300 +140321,平定县,4,140300 +140322,盂县,4,140300 +140403,潞州区,4,140400 +140404,上党区,4,140400 +140405,屯留区,4,140400 +140406,潞城区,4,140400 +140423,襄垣县,4,140400 +140425,平顺县,4,140400 +140426,黎城县,4,140400 +140427,壶关县,4,140400 +140428,长子县,4,140400 +140429,武乡县,4,140400 +140430,沁县,4,140400 +140431,沁源县,4,140400 +140471,山西长治高新技术产业园区,4,140400 +140502,城区,4,140500 +140521,沁水县,4,140500 +140522,阳城县,4,140500 +140524,陵川县,4,140500 +140525,泽州县,4,140500 +140581,高平市,4,140500 +140602,朔城区,4,140600 +140603,平鲁区,4,140600 +140621,山阴县,4,140600 +140622,应县,4,140600 +140623,右玉县,4,140600 +140671,山西朔州经济开发区,4,140600 +140681,怀仁市,4,140600 +140702,榆次区,4,140700 +140703,太谷区,4,140700 +140721,榆社县,4,140700 +140722,左权县,4,140700 +140723,和顺县,4,140700 +140724,昔阳县,4,140700 +140725,寿阳县,4,140700 +140727,祁县,4,140700 +140728,平遥县,4,140700 +140729,灵石县,4,140700 +140781,介休市,4,140700 +140802,盐湖区,4,140800 +140821,临猗县,4,140800 +140822,万荣县,4,140800 +140823,闻喜县,4,140800 +140824,稷山县,4,140800 +140825,新绛县,4,140800 +140826,绛县,4,140800 +140827,垣曲县,4,140800 +140828,夏县,4,140800 +140829,平陆县,4,140800 +140830,芮城县,4,140800 +140881,永济市,4,140800 +140882,河津市,4,140800 +140902,忻府区,4,140900 +140921,定襄县,4,140900 +140922,五台县,4,140900 +140923,代县,4,140900 +140924,繁峙县,4,140900 +140925,宁武县,4,140900 +140926,静乐县,4,140900 +140927,神池县,4,140900 +140928,五寨县,4,140900 +140929,岢岚县,4,140900 +140930,河曲县,4,140900 +140931,保德县,4,140900 +140932,偏关县,4,140900 +140971,五台山风景名胜区,4,140900 +140981,原平市,4,140900 +141002,尧都区,4,141000 +141021,曲沃县,4,141000 +141022,翼城县,4,141000 +141023,襄汾县,4,141000 +141024,洪洞县,4,141000 +141025,古县,4,141000 +141026,安泽县,4,141000 +141027,浮山县,4,141000 +141028,吉县,4,141000 +141029,乡宁县,4,141000 +141030,大宁县,4,141000 +141031,隰县,4,141000 +141032,永和县,4,141000 +141033,蒲县,4,141000 +141034,汾西县,4,141000 +141081,侯马市,4,141000 +141082,霍州市,4,141000 +141102,离石区,4,141100 +141121,文水县,4,141100 +141122,交城县,4,141100 +141123,兴县,4,141100 +141124,临县,4,141100 +141125,柳林县,4,141100 +141126,石楼县,4,141100 +141127,岚县,4,141100 +141128,方山县,4,141100 +141129,中阳县,4,141100 +141130,交口县,4,141100 +141181,孝义市,4,141100 +141182,汾阳市,4,141100 +150102,新城区,4,150100 +150103,回民区,4,150100 +150104,玉泉区,4,150100 +150105,赛罕区,4,150100 +150121,土默特左旗,4,150100 +150122,托克托县,4,150100 +150123,和林格尔县,4,150100 +150124,清水河县,4,150100 +150125,武川县,4,150100 +150172,呼和浩特经济技术开发区,4,150100 +150202,东河区,4,150200 +150203,昆都仑区,4,150200 +150204,青山区,4,150200 +150205,石拐区,4,150200 +150206,白云鄂博矿区,4,150200 +150207,九原区,4,150200 +150221,土默特右旗,4,150200 +150222,固阳县,4,150200 +150223,达尔罕茂明安联合旗,4,150200 +150271,包头稀土高新技术产业开发区,4,150200 +150302,海勃湾区,4,150300 +150303,海南区,4,150300 +150304,乌达区,4,150300 +150402,红山区,4,150400 +150403,元宝山区,4,150400 +150404,松山区,4,150400 +150421,阿鲁科尔沁旗,4,150400 +150422,巴林左旗,4,150400 +150423,巴林右旗,4,150400 +150424,林西县,4,150400 +150425,克什克腾旗,4,150400 +150426,翁牛特旗,4,150400 +150428,喀喇沁旗,4,150400 +150429,宁城县,4,150400 +150430,敖汉旗,4,150400 +150502,科尔沁区,4,150500 +150521,科尔沁左翼中旗,4,150500 +150522,科尔沁左翼后旗,4,150500 +150523,开鲁县,4,150500 +150524,库伦旗,4,150500 +150525,奈曼旗,4,150500 +150526,扎鲁特旗,4,150500 +150571,通辽经济技术开发区,4,150500 +150581,霍林郭勒市,4,150500 +150602,东胜区,4,150600 +150603,康巴什区,4,150600 +150621,达拉特旗,4,150600 +150622,准格尔旗,4,150600 +150623,鄂托克前旗,4,150600 +150624,鄂托克旗,4,150600 +150625,杭锦旗,4,150600 +150626,乌审旗,4,150600 +150627,伊金霍洛旗,4,150600 +150702,海拉尔区,4,150700 +150703,扎赉诺尔区,4,150700 +150721,阿荣旗,4,150700 +150722,莫力达瓦达斡尔族自治旗,4,150700 +150723,鄂伦春自治旗,4,150700 +150724,鄂温克族自治旗,4,150700 +150725,陈巴尔虎旗,4,150700 +150726,新巴尔虎左旗,4,150700 +150727,新巴尔虎右旗,4,150700 +150781,满洲里市,4,150700 +150782,牙克石市,4,150700 +150783,扎兰屯市,4,150700 +150784,额尔古纳市,4,150700 +150785,根河市,4,150700 +150802,临河区,4,150800 +150821,五原县,4,150800 +150822,磴口县,4,150800 +150823,乌拉特前旗,4,150800 +150824,乌拉特中旗,4,150800 +150825,乌拉特后旗,4,150800 +150826,杭锦后旗,4,150800 +150902,集宁区,4,150900 +150921,卓资县,4,150900 +150922,化德县,4,150900 +150923,商都县,4,150900 +150924,兴和县,4,150900 +150925,凉城县,4,150900 +150926,察哈尔右翼前旗,4,150900 +150927,察哈尔右翼中旗,4,150900 +150928,察哈尔右翼后旗,4,150900 +150929,四子王旗,4,150900 +150981,丰镇市,4,150900 +152201,乌兰浩特市,4,152200 +152202,阿尔山市,4,152200 +152221,科尔沁右翼前旗,4,152200 +152222,科尔沁右翼中旗,4,152200 +152223,扎赉特旗,4,152200 +152224,突泉县,4,152200 +152501,二连浩特市,4,152500 +152502,锡林浩特市,4,152500 +152522,阿巴嘎旗,4,152500 +152523,苏尼特左旗,4,152500 +152524,苏尼特右旗,4,152500 +152525,东乌珠穆沁旗,4,152500 +152526,西乌珠穆沁旗,4,152500 +152527,太仆寺旗,4,152500 +152528,镶黄旗,4,152500 +152529,正镶白旗,4,152500 +152530,正蓝旗,4,152500 +152531,多伦县,4,152500 +152571,乌拉盖管委会,4,152500 +152921,阿拉善左旗,4,152900 +152922,阿拉善右旗,4,152900 +152923,额济纳旗,4,152900 +152971,内蒙古阿拉善高新技术产业开发区,4,152900 +210102,和平区,4,210100 +210103,沈河区,4,210100 +210104,大东区,4,210100 +210105,皇姑区,4,210100 +210106,铁西区,4,210100 +210111,苏家屯区,4,210100 +210112,浑南区,4,210100 +210113,沈北新区,4,210100 +210114,于洪区,4,210100 +210115,辽中区,4,210100 +210123,康平县,4,210100 +210124,法库县,4,210100 +210181,新民市,4,210100 +210202,中山区,4,210200 +210203,西岗区,4,210200 +210204,沙河口区,4,210200 +210211,甘井子区,4,210200 +210212,旅顺口区,4,210200 +210213,金州区,4,210200 +210214,普兰店区,4,210200 +210224,长海县,4,210200 +210281,瓦房店市,4,210200 +210283,庄河市,4,210200 +210302,铁东区,4,210300 +210303,铁西区,4,210300 +210304,立山区,4,210300 +210311,千山区,4,210300 +210321,台安县,4,210300 +210323,岫岩满族自治县,4,210300 +210381,海城市,4,210300 +210402,新抚区,4,210400 +210403,东洲区,4,210400 +210404,望花区,4,210400 +210411,顺城区,4,210400 +210421,抚顺县,4,210400 +210422,新宾满族自治县,4,210400 +210423,清原满族自治县,4,210400 +210502,平山区,4,210500 +210503,溪湖区,4,210500 +210504,明山区,4,210500 +210505,南芬区,4,210500 +210521,本溪满族自治县,4,210500 +210522,桓仁满族自治县,4,210500 +210602,元宝区,4,210600 +210603,振兴区,4,210600 +210604,振安区,4,210600 +210624,宽甸满族自治县,4,210600 +210681,东港市,4,210600 +210682,凤城市,4,210600 +210702,古塔区,4,210700 +210703,凌河区,4,210700 +210711,太和区,4,210700 +210726,黑山县,4,210700 +210727,义县,4,210700 +210781,凌海市,4,210700 +210782,北镇市,4,210700 +210802,站前区,4,210800 +210803,西市区,4,210800 +210804,鲅鱼圈区,4,210800 +210811,老边区,4,210800 +210881,盖州市,4,210800 +210882,大石桥市,4,210800 +210902,海州区,4,210900 +210903,新邱区,4,210900 +210904,太平区,4,210900 +210905,清河门区,4,210900 +210911,细河区,4,210900 +210921,阜新蒙古族自治县,4,210900 +210922,彰武县,4,210900 +211002,白塔区,4,211000 +211003,文圣区,4,211000 +211004,宏伟区,4,211000 +211005,弓长岭区,4,211000 +211011,太子河区,4,211000 +211021,辽阳县,4,211000 +211081,灯塔市,4,211000 +211102,双台子区,4,211100 +211103,兴隆台区,4,211100 +211104,大洼区,4,211100 +211122,盘山县,4,211100 +211202,银州区,4,211200 +211204,清河区,4,211200 +211221,铁岭县,4,211200 +211223,西丰县,4,211200 +211224,昌图县,4,211200 +211281,调兵山市,4,211200 +211282,开原市,4,211200 +211302,双塔区,4,211300 +211303,龙城区,4,211300 +211321,朝阳县,4,211300 +211322,建平县,4,211300 +211324,喀喇沁左翼蒙古族自治县,4,211300 +211381,北票市,4,211300 +211382,凌源市,4,211300 +211402,连山区,4,211400 +211403,龙港区,4,211400 +211404,南票区,4,211400 +211421,绥中县,4,211400 +211422,建昌县,4,211400 +211481,兴城市,4,211400 +220102,南关区,4,220100 +220103,宽城区,4,220100 +220104,朝阳区,4,220100 +220105,二道区,4,220100 +220106,绿园区,4,220100 +220112,双阳区,4,220100 +220113,九台区,4,220100 +220122,农安县,4,220100 +220171,长春经济技术开发区,4,220100 +220172,长春净月高新技术产业开发区,4,220100 +220173,长春高新技术产业开发区,4,220100 +220174,长春汽车经济技术开发区,4,220100 +220182,榆树市,4,220100 +220183,德惠市,4,220100 +220184,公主岭市,4,220100 +220202,昌邑区,4,220200 +220203,龙潭区,4,220200 +220204,船营区,4,220200 +220211,丰满区,4,220200 +220221,永吉县,4,220200 +220271,吉林经济开发区,4,220200 +220272,吉林高新技术产业开发区,4,220200 +220273,吉林中国新加坡食品区,4,220200 +220281,蛟河市,4,220200 +220282,桦甸市,4,220200 +220283,舒兰市,4,220200 +220284,磐石市,4,220200 +220302,铁西区,4,220300 +220303,铁东区,4,220300 +220322,梨树县,4,220300 +220323,伊通满族自治县,4,220300 +220382,双辽市,4,220300 +220402,龙山区,4,220400 +220403,西安区,4,220400 +220421,东丰县,4,220400 +220422,东辽县,4,220400 +220502,东昌区,4,220500 +220503,二道江区,4,220500 +220521,通化县,4,220500 +220523,辉南县,4,220500 +220524,柳河县,4,220500 +220581,梅河口市,4,220500 +220582,集安市,4,220500 +220602,浑江区,4,220600 +220605,江源区,4,220600 +220621,抚松县,4,220600 +220622,靖宇县,4,220600 +220623,长白朝鲜族自治县,4,220600 +220681,临江市,4,220600 +220702,宁江区,4,220700 +220721,前郭尔罗斯蒙古族自治县,4,220700 +220722,长岭县,4,220700 +220723,乾安县,4,220700 +220771,吉林松原经济开发区,4,220700 +220781,扶余市,4,220700 +220802,洮北区,4,220800 +220821,镇赉县,4,220800 +220822,通榆县,4,220800 +220871,吉林白城经济开发区,4,220800 +220881,洮南市,4,220800 +220882,大安市,4,220800 +222401,延吉市,4,222400 +222402,图们市,4,222400 +222403,敦化市,4,222400 +222404,珲春市,4,222400 +222405,龙井市,4,222400 +222406,和龙市,4,222400 +222424,汪清县,4,222400 +222426,安图县,4,222400 +230102,道里区,4,230100 +230103,南岗区,4,230100 +230104,道外区,4,230100 +230108,平房区,4,230100 +230109,松北区,4,230100 +230110,香坊区,4,230100 +230111,呼兰区,4,230100 +230112,阿城区,4,230100 +230113,双城区,4,230100 +230123,依兰县,4,230100 +230124,方正县,4,230100 +230125,宾县,4,230100 +230126,巴彦县,4,230100 +230127,木兰县,4,230100 +230128,通河县,4,230100 +230129,延寿县,4,230100 +230183,尚志市,4,230100 +230184,五常市,4,230100 +230202,龙沙区,4,230200 +230203,建华区,4,230200 +230204,铁锋区,4,230200 +230205,昂昂溪区,4,230200 +230206,富拉尔基区,4,230200 +230207,碾子山区,4,230200 +230208,梅里斯达斡尔族区,4,230200 +230221,龙江县,4,230200 +230223,依安县,4,230200 +230224,泰来县,4,230200 +230225,甘南县,4,230200 +230227,富裕县,4,230200 +230229,克山县,4,230200 +230230,克东县,4,230200 +230231,拜泉县,4,230200 +230281,讷河市,4,230200 +230302,鸡冠区,4,230300 +230303,恒山区,4,230300 +230304,滴道区,4,230300 +230305,梨树区,4,230300 +230306,城子河区,4,230300 +230307,麻山区,4,230300 +230321,鸡东县,4,230300 +230381,虎林市,4,230300 +230382,密山市,4,230300 +230402,向阳区,4,230400 +230403,工农区,4,230400 +230404,南山区,4,230400 +230405,兴安区,4,230400 +230406,东山区,4,230400 +230407,兴山区,4,230400 +230421,萝北县,4,230400 +230422,绥滨县,4,230400 +230502,尖山区,4,230500 +230503,岭东区,4,230500 +230505,四方台区,4,230500 +230506,宝山区,4,230500 +230521,集贤县,4,230500 +230522,友谊县,4,230500 +230523,宝清县,4,230500 +230524,饶河县,4,230500 +230602,萨尔图区,4,230600 +230603,龙凤区,4,230600 +230604,让胡路区,4,230600 +230605,红岗区,4,230600 +230606,大同区,4,230600 +230621,肇州县,4,230600 +230622,肇源县,4,230600 +230623,林甸县,4,230600 +230624,杜尔伯特蒙古族自治县,4,230600 +230671,大庆高新技术产业开发区,4,230600 +230717,伊美区,4,230700 +230718,乌翠区,4,230700 +230719,友好区,4,230700 +230722,嘉荫县,4,230700 +230723,汤旺县,4,230700 +230724,丰林县,4,230700 +230725,大箐山县,4,230700 +230726,南岔县,4,230700 +230751,金林区,4,230700 +230781,铁力市,4,230700 +230803,向阳区,4,230800 +230804,前进区,4,230800 +230805,东风区,4,230800 +230811,郊区,4,230800 +230822,桦南县,4,230800 +230826,桦川县,4,230800 +230828,汤原县,4,230800 +230881,同江市,4,230800 +230882,富锦市,4,230800 +230883,抚远市,4,230800 +230902,新兴区,4,230900 +230903,桃山区,4,230900 +230904,茄子河区,4,230900 +230921,勃利县,4,230900 +231002,东安区,4,231000 +231003,阳明区,4,231000 +231004,爱民区,4,231000 +231005,西安区,4,231000 +231025,林口县,4,231000 +231071,牡丹江经济技术开发区,4,231000 +231081,绥芬河市,4,231000 +231083,海林市,4,231000 +231084,宁安市,4,231000 +231085,穆棱市,4,231000 +231086,东宁市,4,231000 +231102,爱辉区,4,231100 +231123,逊克县,4,231100 +231124,孙吴县,4,231100 +231181,北安市,4,231100 +231182,五大连池市,4,231100 +231183,嫩江市,4,231100 +231202,北林区,4,231200 +231221,望奎县,4,231200 +231222,兰西县,4,231200 +231223,青冈县,4,231200 +231224,庆安县,4,231200 +231225,明水县,4,231200 +231226,绥棱县,4,231200 +231281,安达市,4,231200 +231282,肇东市,4,231200 +231283,海伦市,4,231200 +232701,漠河市,4,232700 +232721,呼玛县,4,232700 +232722,塔河县,4,232700 +232761,加格达奇区,4,232700 +232762,松岭区,4,232700 +232763,新林区,4,232700 +232764,呼中区,4,232700 +310101,黄浦区,4,310100 +310104,徐汇区,4,310100 +310105,长宁区,4,310100 +310106,静安区,4,310100 +310107,普陀区,4,310100 +310109,虹口区,4,310100 +310110,杨浦区,4,310100 +310112,闵行区,4,310100 +310113,宝山区,4,310100 +310114,嘉定区,4,310100 +310115,浦东新区,4,310100 +310116,金山区,4,310100 +310117,松江区,4,310100 +310118,青浦区,4,310100 +310120,奉贤区,4,310100 +310151,崇明区,4,310100 +320102,玄武区,4,320100 +320104,秦淮区,4,320100 +320105,建邺区,4,320100 +320106,鼓楼区,4,320100 +320111,浦口区,4,320100 +320113,栖霞区,4,320100 +320114,雨花台区,4,320100 +320115,江宁区,4,320100 +320116,六合区,4,320100 +320117,溧水区,4,320100 +320118,高淳区,4,320100 +320205,锡山区,4,320200 +320206,惠山区,4,320200 +320211,滨湖区,4,320200 +320213,梁溪区,4,320200 +320214,新吴区,4,320200 +320281,江阴市,4,320200 +320282,宜兴市,4,320200 +320302,鼓楼区,4,320300 +320303,云龙区,4,320300 +320305,贾汪区,4,320300 +320311,泉山区,4,320300 +320312,铜山区,4,320300 +320321,丰县,4,320300 +320322,沛县,4,320300 +320324,睢宁县,4,320300 +320371,徐州经济技术开发区,4,320300 +320381,新沂市,4,320300 +320382,邳州市,4,320300 +320402,天宁区,4,320400 +320404,钟楼区,4,320400 +320411,新北区,4,320400 +320412,武进区,4,320400 +320413,金坛区,4,320400 +320481,溧阳市,4,320400 +320505,虎丘区,4,320500 +320506,吴中区,4,320500 +320507,相城区,4,320500 +320508,姑苏区,4,320500 +320509,吴江区,4,320500 +320571,苏州工业园区,4,320500 +320581,常熟市,4,320500 +320582,张家港市,4,320500 +320583,昆山市,4,320500 +320585,太仓市,4,320500 +320612,通州区,4,320600 +320613,崇川区,4,320600 +320614,海门区,4,320600 +320623,如东县,4,320600 +320671,南通经济技术开发区,4,320600 +320681,启东市,4,320600 +320682,如皋市,4,320600 +320685,海安市,4,320600 +320703,连云区,4,320700 +320706,海州区,4,320700 +320707,赣榆区,4,320700 +320722,东海县,4,320700 +320723,灌云县,4,320700 +320724,灌南县,4,320700 +320771,连云港经济技术开发区,4,320700 +320772,连云港高新技术产业开发区,4,320700 +320803,淮安区,4,320800 +320804,淮阴区,4,320800 +320812,清江浦区,4,320800 +320813,洪泽区,4,320800 +320826,涟水县,4,320800 +320830,盱眙县,4,320800 +320831,金湖县,4,320800 +320871,淮安经济技术开发区,4,320800 +320902,亭湖区,4,320900 +320903,盐都区,4,320900 +320904,大丰区,4,320900 +320921,响水县,4,320900 +320922,滨海县,4,320900 +320923,阜宁县,4,320900 +320924,射阳县,4,320900 +320925,建湖县,4,320900 +320971,盐城经济技术开发区,4,320900 +320981,东台市,4,320900 +321002,广陵区,4,321000 +321003,邗江区,4,321000 +321012,江都区,4,321000 +321023,宝应县,4,321000 +321071,扬州经济技术开发区,4,321000 +321081,仪征市,4,321000 +321084,高邮市,4,321000 +321102,京口区,4,321100 +321111,润州区,4,321100 +321112,丹徒区,4,321100 +321171,镇江新区,4,321100 +321181,丹阳市,4,321100 +321182,扬中市,4,321100 +321183,句容市,4,321100 +321202,海陵区,4,321200 +321203,高港区,4,321200 +321204,姜堰区,4,321200 +321271,泰州医药高新技术产业开发区,4,321200 +321281,兴化市,4,321200 +321282,靖江市,4,321200 +321283,泰兴市,4,321200 +321302,宿城区,4,321300 +321311,宿豫区,4,321300 +321322,沭阳县,4,321300 +321323,泗阳县,4,321300 +321324,泗洪县,4,321300 +321371,宿迁经济技术开发区,4,321300 +330102,上城区,4,330100 +330105,拱墅区,4,330100 +330106,西湖区,4,330100 +330108,滨江区,4,330100 +330109,萧山区,4,330100 +330110,余杭区,4,330100 +330111,富阳区,4,330100 +330112,临安区,4,330100 +330113,临平区,4,330100 +330114,钱塘区,4,330100 +330122,桐庐县,4,330100 +330127,淳安县,4,330100 +330182,建德市,4,330100 +330203,海曙区,4,330200 +330205,江北区,4,330200 +330206,北仑区,4,330200 +330211,镇海区,4,330200 +330212,鄞州区,4,330200 +330213,奉化区,4,330200 +330225,象山县,4,330200 +330226,宁海县,4,330200 +330281,余姚市,4,330200 +330282,慈溪市,4,330200 +330302,鹿城区,4,330300 +330303,龙湾区,4,330300 +330304,瓯海区,4,330300 +330305,洞头区,4,330300 +330324,永嘉县,4,330300 +330326,平阳县,4,330300 +330327,苍南县,4,330300 +330328,文成县,4,330300 +330329,泰顺县,4,330300 +330371,温州经济技术开发区,4,330300 +330381,瑞安市,4,330300 +330382,乐清市,4,330300 +330383,龙港市,4,330300 +330402,南湖区,4,330400 +330411,秀洲区,4,330400 +330421,嘉善县,4,330400 +330424,海盐县,4,330400 +330481,海宁市,4,330400 +330482,平湖市,4,330400 +330483,桐乡市,4,330400 +330502,吴兴区,4,330500 +330503,南浔区,4,330500 +330521,德清县,4,330500 +330522,长兴县,4,330500 +330523,安吉县,4,330500 +330602,越城区,4,330600 +330603,柯桥区,4,330600 +330604,上虞区,4,330600 +330624,新昌县,4,330600 +330681,诸暨市,4,330600 +330683,嵊州市,4,330600 +330702,婺城区,4,330700 +330703,金东区,4,330700 +330723,武义县,4,330700 +330726,浦江县,4,330700 +330727,磐安县,4,330700 +330781,兰溪市,4,330700 +330782,义乌市,4,330700 +330783,东阳市,4,330700 +330784,永康市,4,330700 +330802,柯城区,4,330800 +330803,衢江区,4,330800 +330822,常山县,4,330800 +330824,开化县,4,330800 +330825,龙游县,4,330800 +330881,江山市,4,330800 +330902,定海区,4,330900 +330903,普陀区,4,330900 +330921,岱山县,4,330900 +330922,嵊泗县,4,330900 +331002,椒江区,4,331000 +331003,黄岩区,4,331000 +331004,路桥区,4,331000 +331022,三门县,4,331000 +331023,天台县,4,331000 +331024,仙居县,4,331000 +331081,温岭市,4,331000 +331082,临海市,4,331000 +331083,玉环市,4,331000 +331102,莲都区,4,331100 +331121,青田县,4,331100 +331122,缙云县,4,331100 +331123,遂昌县,4,331100 +331124,松阳县,4,331100 +331125,云和县,4,331100 +331126,庆元县,4,331100 +331127,景宁畲族自治县,4,331100 +331181,龙泉市,4,331100 +340102,瑶海区,4,340100 +340103,庐阳区,4,340100 +340104,蜀山区,4,340100 +340111,包河区,4,340100 +340121,长丰县,4,340100 +340122,肥东县,4,340100 +340123,肥西县,4,340100 +340124,庐江县,4,340100 +340171,合肥高新技术产业开发区,4,340100 +340172,合肥经济技术开发区,4,340100 +340173,合肥新站高新技术产业开发区,4,340100 +340181,巢湖市,4,340100 +340202,镜湖区,4,340200 +340207,鸠江区,4,340200 +340209,弋江区,4,340200 +340210,湾沚区,4,340200 +340212,繁昌区,4,340200 +340223,南陵县,4,340200 +340271,芜湖经济技术开发区,4,340200 +340272,安徽芜湖三山经济开发区,4,340200 +340281,无为市,4,340200 +340302,龙子湖区,4,340300 +340303,蚌山区,4,340300 +340304,禹会区,4,340300 +340311,淮上区,4,340300 +340321,怀远县,4,340300 +340322,五河县,4,340300 +340323,固镇县,4,340300 +340371,蚌埠市高新技术开发区,4,340300 +340372,蚌埠市经济开发区,4,340300 +340402,大通区,4,340400 +340403,田家庵区,4,340400 +340404,谢家集区,4,340400 +340405,八公山区,4,340400 +340406,潘集区,4,340400 +340421,凤台县,4,340400 +340422,寿县,4,340400 +340503,花山区,4,340500 +340504,雨山区,4,340500 +340506,博望区,4,340500 +340521,当涂县,4,340500 +340522,含山县,4,340500 +340523,和县,4,340500 +340602,杜集区,4,340600 +340603,相山区,4,340600 +340604,烈山区,4,340600 +340621,濉溪县,4,340600 +340705,铜官区,4,340700 +340706,义安区,4,340700 +340711,郊区,4,340700 +340722,枞阳县,4,340700 +340802,迎江区,4,340800 +340803,大观区,4,340800 +340811,宜秀区,4,340800 +340822,怀宁县,4,340800 +340825,太湖县,4,340800 +340826,宿松县,4,340800 +340827,望江县,4,340800 +340828,岳西县,4,340800 +340871,安徽安庆经济开发区,4,340800 +340881,桐城市,4,340800 +340882,潜山市,4,340800 +341002,屯溪区,4,341000 +341003,黄山区,4,341000 +341004,徽州区,4,341000 +341021,歙县,4,341000 +341022,休宁县,4,341000 +341023,黟县,4,341000 +341024,祁门县,4,341000 +341102,琅琊区,4,341100 +341103,南谯区,4,341100 +341122,来安县,4,341100 +341124,全椒县,4,341100 +341125,定远县,4,341100 +341126,凤阳县,4,341100 +341171,中新苏滁高新技术产业开发区,4,341100 +341172,滁州经济技术开发区,4,341100 +341181,天长市,4,341100 +341182,明光市,4,341100 +341202,颍州区,4,341200 +341203,颍东区,4,341200 +341204,颍泉区,4,341200 +341221,临泉县,4,341200 +341222,太和县,4,341200 +341225,阜南县,4,341200 +341226,颍上县,4,341200 +341271,阜阳合肥现代产业园区,4,341200 +341272,阜阳经济技术开发区,4,341200 +341282,界首市,4,341200 +341302,埇桥区,4,341300 +341321,砀山县,4,341300 +341322,萧县,4,341300 +341323,灵璧县,4,341300 +341324,泗县,4,341300 +341371,宿州马鞍山现代产业园区,4,341300 +341372,宿州经济技术开发区,4,341300 +341502,金安区,4,341500 +341503,裕安区,4,341500 +341504,叶集区,4,341500 +341522,霍邱县,4,341500 +341523,舒城县,4,341500 +341524,金寨县,4,341500 +341525,霍山县,4,341500 +341602,谯城区,4,341600 +341621,涡阳县,4,341600 +341622,蒙城县,4,341600 +341623,利辛县,4,341600 +341702,贵池区,4,341700 +341721,东至县,4,341700 +341722,石台县,4,341700 +341723,青阳县,4,341700 +341802,宣州区,4,341800 +341821,郎溪县,4,341800 +341823,泾县,4,341800 +341824,绩溪县,4,341800 +341825,旌德县,4,341800 +341871,宣城市经济开发区,4,341800 +341881,宁国市,4,341800 +341882,广德市,4,341800 +350102,鼓楼区,4,350100 +350103,台江区,4,350100 +350104,仓山区,4,350100 +350105,马尾区,4,350100 +350111,晋安区,4,350100 +350112,长乐区,4,350100 +350121,闽侯县,4,350100 +350122,连江县,4,350100 +350123,罗源县,4,350100 +350124,闽清县,4,350100 +350125,永泰县,4,350100 +350128,平潭县,4,350100 +350181,福清市,4,350100 +350203,思明区,4,350200 +350205,海沧区,4,350200 +350206,湖里区,4,350200 +350211,集美区,4,350200 +350212,同安区,4,350200 +350213,翔安区,4,350200 +350302,城厢区,4,350300 +350303,涵江区,4,350300 +350304,荔城区,4,350300 +350305,秀屿区,4,350300 +350322,仙游县,4,350300 +350404,三元区,4,350400 +350405,沙县区,4,350400 +350421,明溪县,4,350400 +350423,清流县,4,350400 +350424,宁化县,4,350400 +350425,大田县,4,350400 +350426,尤溪县,4,350400 +350428,将乐县,4,350400 +350429,泰宁县,4,350400 +350430,建宁县,4,350400 +350481,永安市,4,350400 +350502,鲤城区,4,350500 +350503,丰泽区,4,350500 +350504,洛江区,4,350500 +350505,泉港区,4,350500 +350521,惠安县,4,350500 +350524,安溪县,4,350500 +350525,永春县,4,350500 +350526,德化县,4,350500 +350527,金门县,4,350500 +350581,石狮市,4,350500 +350582,晋江市,4,350500 +350583,南安市,4,350500 +350602,芗城区,4,350600 +350603,龙文区,4,350600 +350604,龙海区,4,350600 +350605,长泰区,4,350600 +350622,云霄县,4,350600 +350623,漳浦县,4,350600 +350624,诏安县,4,350600 +350626,东山县,4,350600 +350627,南靖县,4,350600 +350628,平和县,4,350600 +350629,华安县,4,350600 +350702,延平区,4,350700 +350703,建阳区,4,350700 +350721,顺昌县,4,350700 +350722,浦城县,4,350700 +350723,光泽县,4,350700 +350724,松溪县,4,350700 +350725,政和县,4,350700 +350781,邵武市,4,350700 +350782,武夷山市,4,350700 +350783,建瓯市,4,350700 +350802,新罗区,4,350800 +350803,永定区,4,350800 +350821,长汀县,4,350800 +350823,上杭县,4,350800 +350824,武平县,4,350800 +350825,连城县,4,350800 +350881,漳平市,4,350800 +350902,蕉城区,4,350900 +350921,霞浦县,4,350900 +350922,古田县,4,350900 +350923,屏南县,4,350900 +350924,寿宁县,4,350900 +350925,周宁县,4,350900 +350926,柘荣县,4,350900 +350981,福安市,4,350900 +350982,福鼎市,4,350900 +360102,东湖区,4,360100 +360103,西湖区,4,360100 +360104,青云谱区,4,360100 +360111,青山湖区,4,360100 +360112,新建区,4,360100 +360113,红谷滩区,4,360100 +360121,南昌县,4,360100 +360123,安义县,4,360100 +360124,进贤县,4,360100 +360202,昌江区,4,360200 +360203,珠山区,4,360200 +360222,浮梁县,4,360200 +360281,乐平市,4,360200 +360302,安源区,4,360300 +360313,湘东区,4,360300 +360321,莲花县,4,360300 +360322,上栗县,4,360300 +360323,芦溪县,4,360300 +360402,濂溪区,4,360400 +360403,浔阳区,4,360400 +360404,柴桑区,4,360400 +360423,武宁县,4,360400 +360424,修水县,4,360400 +360425,永修县,4,360400 +360426,德安县,4,360400 +360428,都昌县,4,360400 +360429,湖口县,4,360400 +360430,彭泽县,4,360400 +360481,瑞昌市,4,360400 +360482,共青城市,4,360400 +360483,庐山市,4,360400 +360502,渝水区,4,360500 +360521,分宜县,4,360500 +360602,月湖区,4,360600 +360603,余江区,4,360600 +360681,贵溪市,4,360600 +360702,章贡区,4,360700 +360703,南康区,4,360700 +360704,赣县区,4,360700 +360722,信丰县,4,360700 +360723,大余县,4,360700 +360724,上犹县,4,360700 +360725,崇义县,4,360700 +360726,安远县,4,360700 +360728,定南县,4,360700 +360729,全南县,4,360700 +360730,宁都县,4,360700 +360731,于都县,4,360700 +360732,兴国县,4,360700 +360733,会昌县,4,360700 +360734,寻乌县,4,360700 +360735,石城县,4,360700 +360781,瑞金市,4,360700 +360783,龙南市,4,360700 +360802,吉州区,4,360800 +360803,青原区,4,360800 +360821,吉安县,4,360800 +360822,吉水县,4,360800 +360823,峡江县,4,360800 +360824,新干县,4,360800 +360825,永丰县,4,360800 +360826,泰和县,4,360800 +360827,遂川县,4,360800 +360828,万安县,4,360800 +360829,安福县,4,360800 +360830,永新县,4,360800 +360881,井冈山市,4,360800 +360902,袁州区,4,360900 +360921,奉新县,4,360900 +360922,万载县,4,360900 +360923,上高县,4,360900 +360924,宜丰县,4,360900 +360925,靖安县,4,360900 +360926,铜鼓县,4,360900 +360981,丰城市,4,360900 +360982,樟树市,4,360900 +360983,高安市,4,360900 +361002,临川区,4,361000 +361003,东乡区,4,361000 +361021,南城县,4,361000 +361022,黎川县,4,361000 +361023,南丰县,4,361000 +361024,崇仁县,4,361000 +361025,乐安县,4,361000 +361026,宜黄县,4,361000 +361027,金溪县,4,361000 +361028,资溪县,4,361000 +361030,广昌县,4,361000 +361102,信州区,4,361100 +361103,广丰区,4,361100 +361104,广信区,4,361100 +361123,玉山县,4,361100 +361124,铅山县,4,361100 +361125,横峰县,4,361100 +361126,弋阳县,4,361100 +361127,余干县,4,361100 +361128,鄱阳县,4,361100 +361129,万年县,4,361100 +361130,婺源县,4,361100 +361181,德兴市,4,361100 +370102,历下区,4,370100 +370103,市中区,4,370100 +370104,槐荫区,4,370100 +370105,天桥区,4,370100 +370112,历城区,4,370100 +370113,长清区,4,370100 +370114,章丘区,4,370100 +370115,济阳区,4,370100 +370116,莱芜区,4,370100 +370117,钢城区,4,370100 +370124,平阴县,4,370100 +370126,商河县,4,370100 +370171,济南高新技术产业开发区,4,370100 +370202,市南区,4,370200 +370203,市北区,4,370200 +370211,黄岛区,4,370200 +370212,崂山区,4,370200 +370213,李沧区,4,370200 +370214,城阳区,4,370200 +370215,即墨区,4,370200 +370271,青岛高新技术产业开发区,4,370200 +370281,胶州市,4,370200 +370283,平度市,4,370200 +370285,莱西市,4,370200 +370302,淄川区,4,370300 +370303,张店区,4,370300 +370304,博山区,4,370300 +370305,临淄区,4,370300 +370306,周村区,4,370300 +370321,桓台县,4,370300 +370322,高青县,4,370300 +370323,沂源县,4,370300 +370402,市中区,4,370400 +370403,薛城区,4,370400 +370404,峄城区,4,370400 +370405,台儿庄区,4,370400 +370406,山亭区,4,370400 +370481,滕州市,4,370400 +370502,东营区,4,370500 +370503,河口区,4,370500 +370505,垦利区,4,370500 +370522,利津县,4,370500 +370523,广饶县,4,370500 +370571,东营经济技术开发区,4,370500 +370572,东营港经济开发区,4,370500 +370602,芝罘区,4,370600 +370611,福山区,4,370600 +370612,牟平区,4,370600 +370613,莱山区,4,370600 +370614,蓬莱区,4,370600 +370671,烟台高新技术产业开发区,4,370600 +370672,烟台经济技术开发区,4,370600 +370681,龙口市,4,370600 +370682,莱阳市,4,370600 +370683,莱州市,4,370600 +370685,招远市,4,370600 +370686,栖霞市,4,370600 +370687,海阳市,4,370600 +370702,潍城区,4,370700 +370703,寒亭区,4,370700 +370704,坊子区,4,370700 +370705,奎文区,4,370700 +370724,临朐县,4,370700 +370725,昌乐县,4,370700 +370772,潍坊滨海经济技术开发区,4,370700 +370781,青州市,4,370700 +370782,诸城市,4,370700 +370783,寿光市,4,370700 +370784,安丘市,4,370700 +370785,高密市,4,370700 +370786,昌邑市,4,370700 +370811,任城区,4,370800 +370812,兖州区,4,370800 +370826,微山县,4,370800 +370827,鱼台县,4,370800 +370828,金乡县,4,370800 +370829,嘉祥县,4,370800 +370830,汶上县,4,370800 +370831,泗水县,4,370800 +370832,梁山县,4,370800 +370871,济宁高新技术产业开发区,4,370800 +370881,曲阜市,4,370800 +370883,邹城市,4,370800 +370902,泰山区,4,370900 +370911,岱岳区,4,370900 +370921,宁阳县,4,370900 +370923,东平县,4,370900 +370982,新泰市,4,370900 +370983,肥城市,4,370900 +371002,环翠区,4,371000 +371003,文登区,4,371000 +371071,威海火炬高技术产业开发区,4,371000 +371072,威海经济技术开发区,4,371000 +371073,威海临港经济技术开发区,4,371000 +371082,荣成市,4,371000 +371083,乳山市,4,371000 +371102,东港区,4,371100 +371103,岚山区,4,371100 +371121,五莲县,4,371100 +371122,莒县,4,371100 +371171,日照经济技术开发区,4,371100 +371302,兰山区,4,371300 +371311,罗庄区,4,371300 +371312,河东区,4,371300 +371321,沂南县,4,371300 +371322,郯城县,4,371300 +371323,沂水县,4,371300 +371324,兰陵县,4,371300 +371325,费县,4,371300 +371326,平邑县,4,371300 +371327,莒南县,4,371300 +371328,蒙阴县,4,371300 +371329,临沭县,4,371300 +371371,临沂高新技术产业开发区,4,371300 +371402,德城区,4,371400 +371403,陵城区,4,371400 +371422,宁津县,4,371400 +371423,庆云县,4,371400 +371424,临邑县,4,371400 +371425,齐河县,4,371400 +371426,平原县,4,371400 +371427,夏津县,4,371400 +371428,武城县,4,371400 +371471,德州经济技术开发区,4,371400 +371472,德州运河经济开发区,4,371400 +371481,乐陵市,4,371400 +371482,禹城市,4,371400 +371502,东昌府区,4,371500 +371503,茌平区,4,371500 +371521,阳谷县,4,371500 +371522,莘县,4,371500 +371524,东阿县,4,371500 +371525,冠县,4,371500 +371526,高唐县,4,371500 +371581,临清市,4,371500 +371602,滨城区,4,371600 +371603,沾化区,4,371600 +371621,惠民县,4,371600 +371622,阳信县,4,371600 +371623,无棣县,4,371600 +371625,博兴县,4,371600 +371681,邹平市,4,371600 +371702,牡丹区,4,371700 +371703,定陶区,4,371700 +371721,曹县,4,371700 +371722,单县,4,371700 +371723,成武县,4,371700 +371724,巨野县,4,371700 +371725,郓城县,4,371700 +371726,鄄城县,4,371700 +371728,东明县,4,371700 +371771,菏泽经济技术开发区,4,371700 +371772,菏泽高新技术开发区,4,371700 +410102,中原区,4,410100 +410103,二七区,4,410100 +410104,管城回族区,4,410100 +410105,金水区,4,410100 +410106,上街区,4,410100 +410108,惠济区,4,410100 +410122,中牟县,4,410100 +410171,郑州经济技术开发区,4,410100 +410172,郑州高新技术产业开发区,4,410100 +410173,郑州航空港经济综合实验区,4,410100 +410181,巩义市,4,410100 +410182,荥阳市,4,410100 +410183,新密市,4,410100 +410184,新郑市,4,410100 +410185,登封市,4,410100 +410202,龙亭区,4,410200 +410203,顺河回族区,4,410200 +410204,鼓楼区,4,410200 +410205,禹王台区,4,410200 +410212,祥符区,4,410200 +410221,杞县,4,410200 +410222,通许县,4,410200 +410223,尉氏县,4,410200 +410225,兰考县,4,410200 +410302,老城区,4,410300 +410303,西工区,4,410300 +410304,瀍河回族区,4,410300 +410305,涧西区,4,410300 +410307,偃师区,4,410300 +410308,孟津区,4,410300 +410311,洛龙区,4,410300 +410323,新安县,4,410300 +410324,栾川县,4,410300 +410325,嵩县,4,410300 +410326,汝阳县,4,410300 +410327,宜阳县,4,410300 +410328,洛宁县,4,410300 +410329,伊川县,4,410300 +410371,洛阳高新技术产业开发区,4,410300 +410402,新华区,4,410400 +410403,卫东区,4,410400 +410404,石龙区,4,410400 +410411,湛河区,4,410400 +410421,宝丰县,4,410400 +410422,叶县,4,410400 +410423,鲁山县,4,410400 +410425,郏县,4,410400 +410471,平顶山高新技术产业开发区,4,410400 +410472,平顶山市城乡一体化示范区,4,410400 +410481,舞钢市,4,410400 +410482,汝州市,4,410400 +410502,文峰区,4,410500 +410503,北关区,4,410500 +410505,殷都区,4,410500 +410506,龙安区,4,410500 +410522,安阳县,4,410500 +410523,汤阴县,4,410500 +410526,滑县,4,410500 +410527,内黄县,4,410500 +410571,安阳高新技术产业开发区,4,410500 +410581,林州市,4,410500 +410602,鹤山区,4,410600 +410603,山城区,4,410600 +410611,淇滨区,4,410600 +410621,浚县,4,410600 +410622,淇县,4,410600 +410671,鹤壁经济技术开发区,4,410600 +410702,红旗区,4,410700 +410703,卫滨区,4,410700 +410704,凤泉区,4,410700 +410711,牧野区,4,410700 +410721,新乡县,4,410700 +410724,获嘉县,4,410700 +410725,原阳县,4,410700 +410726,延津县,4,410700 +410727,封丘县,4,410700 +410771,新乡高新技术产业开发区,4,410700 +410772,新乡经济技术开发区,4,410700 +410773,新乡市平原城乡一体化示范区,4,410700 +410781,卫辉市,4,410700 +410782,辉县市,4,410700 +410783,长垣市,4,410700 +410802,解放区,4,410800 +410803,中站区,4,410800 +410804,马村区,4,410800 +410811,山阳区,4,410800 +410821,修武县,4,410800 +410822,博爱县,4,410800 +410823,武陟县,4,410800 +410825,温县,4,410800 +410871,焦作城乡一体化示范区,4,410800 +410882,沁阳市,4,410800 +410883,孟州市,4,410800 +410902,华龙区,4,410900 +410922,清丰县,4,410900 +410923,南乐县,4,410900 +410926,范县,4,410900 +410927,台前县,4,410900 +410928,濮阳县,4,410900 +410971,河南濮阳工业园区,4,410900 +410972,濮阳经济技术开发区,4,410900 +411002,魏都区,4,411000 +411003,建安区,4,411000 +411024,鄢陵县,4,411000 +411025,襄城县,4,411000 +411071,许昌经济技术开发区,4,411000 +411081,禹州市,4,411000 +411082,长葛市,4,411000 +411102,源汇区,4,411100 +411103,郾城区,4,411100 +411104,召陵区,4,411100 +411121,舞阳县,4,411100 +411122,临颍县,4,411100 +411171,漯河经济技术开发区,4,411100 +411202,湖滨区,4,411200 +411203,陕州区,4,411200 +411221,渑池县,4,411200 +411224,卢氏县,4,411200 +411271,河南三门峡经济开发区,4,411200 +411281,义马市,4,411200 +411282,灵宝市,4,411200 +411302,宛城区,4,411300 +411303,卧龙区,4,411300 +411321,南召县,4,411300 +411322,方城县,4,411300 +411323,西峡县,4,411300 +411324,镇平县,4,411300 +411325,内乡县,4,411300 +411326,淅川县,4,411300 +411327,社旗县,4,411300 +411328,唐河县,4,411300 +411329,新野县,4,411300 +411330,桐柏县,4,411300 +411371,南阳高新技术产业开发区,4,411300 +411372,南阳市城乡一体化示范区,4,411300 +411381,邓州市,4,411300 +411402,梁园区,4,411400 +411403,睢阳区,4,411400 +411421,民权县,4,411400 +411422,睢县,4,411400 +411423,宁陵县,4,411400 +411424,柘城县,4,411400 +411425,虞城县,4,411400 +411426,夏邑县,4,411400 +411471,豫东综合物流产业聚集区,4,411400 +411472,河南商丘经济开发区,4,411400 +411481,永城市,4,411400 +411502,浉河区,4,411500 +411503,平桥区,4,411500 +411521,罗山县,4,411500 +411522,光山县,4,411500 +411523,新县,4,411500 +411524,商城县,4,411500 +411525,固始县,4,411500 +411526,潢川县,4,411500 +411527,淮滨县,4,411500 +411528,息县,4,411500 +411571,信阳高新技术产业开发区,4,411500 +411602,川汇区,4,411600 +411603,淮阳区,4,411600 +411621,扶沟县,4,411600 +411622,西华县,4,411600 +411623,商水县,4,411600 +411624,沈丘县,4,411600 +411625,郸城县,4,411600 +411627,太康县,4,411600 +411628,鹿邑县,4,411600 +411671,河南周口经济开发区,4,411600 +411681,项城市,4,411600 +411702,驿城区,4,411700 +411721,西平县,4,411700 +411722,上蔡县,4,411700 +411723,平舆县,4,411700 +411724,正阳县,4,411700 +411725,确山县,4,411700 +411726,泌阳县,4,411700 +411727,汝南县,4,411700 +411728,遂平县,4,411700 +411729,新蔡县,4,411700 +411771,河南驻马店经济开发区,4,411700 +419001,济源市,4,419000 +420102,江岸区,4,420100 +420103,江汉区,4,420100 +420104,硚口区,4,420100 +420105,汉阳区,4,420100 +420106,武昌区,4,420100 +420107,青山区,4,420100 +420111,洪山区,4,420100 +420112,东西湖区,4,420100 +420113,汉南区,4,420100 +420114,蔡甸区,4,420100 +420115,江夏区,4,420100 +420116,黄陂区,4,420100 +420117,新洲区,4,420100 +420202,黄石港区,4,420200 +420203,西塞山区,4,420200 +420204,下陆区,4,420200 +420205,铁山区,4,420200 +420222,阳新县,4,420200 +420281,大冶市,4,420200 +420302,茅箭区,4,420300 +420303,张湾区,4,420300 +420304,郧阳区,4,420300 +420322,郧西县,4,420300 +420323,竹山县,4,420300 +420324,竹溪县,4,420300 +420325,房县,4,420300 +420381,丹江口市,4,420300 +420502,西陵区,4,420500 +420503,伍家岗区,4,420500 +420504,点军区,4,420500 +420505,猇亭区,4,420500 +420506,夷陵区,4,420500 +420525,远安县,4,420500 +420526,兴山县,4,420500 +420527,秭归县,4,420500 +420528,长阳土家族自治县,4,420500 +420529,五峰土家族自治县,4,420500 +420581,宜都市,4,420500 +420582,当阳市,4,420500 +420583,枝江市,4,420500 +420602,襄城区,4,420600 +420606,樊城区,4,420600 +420607,襄州区,4,420600 +420624,南漳县,4,420600 +420625,谷城县,4,420600 +420626,保康县,4,420600 +420682,老河口市,4,420600 +420683,枣阳市,4,420600 +420684,宜城市,4,420600 +420702,梁子湖区,4,420700 +420703,华容区,4,420700 +420704,鄂城区,4,420700 +420802,东宝区,4,420800 +420804,掇刀区,4,420800 +420822,沙洋县,4,420800 +420881,钟祥市,4,420800 +420882,京山市,4,420800 +420902,孝南区,4,420900 +420921,孝昌县,4,420900 +420922,大悟县,4,420900 +420923,云梦县,4,420900 +420981,应城市,4,420900 +420982,安陆市,4,420900 +420984,汉川市,4,420900 +421002,沙市区,4,421000 +421003,荆州区,4,421000 +421022,公安县,4,421000 +421024,江陵县,4,421000 +421071,荆州经济技术开发区,4,421000 +421081,石首市,4,421000 +421083,洪湖市,4,421000 +421087,松滋市,4,421000 +421088,监利市,4,421000 +421102,黄州区,4,421100 +421121,团风县,4,421100 +421122,红安县,4,421100 +421123,罗田县,4,421100 +421124,英山县,4,421100 +421125,浠水县,4,421100 +421126,蕲春县,4,421100 +421127,黄梅县,4,421100 +421171,龙感湖管理区,4,421100 +421181,麻城市,4,421100 +421182,武穴市,4,421100 +421202,咸安区,4,421200 +421221,嘉鱼县,4,421200 +421222,通城县,4,421200 +421223,崇阳县,4,421200 +421224,通山县,4,421200 +421281,赤壁市,4,421200 +421303,曾都区,4,421300 +421321,随县,4,421300 +421381,广水市,4,421300 +422801,恩施市,4,422800 +422802,利川市,4,422800 +422822,建始县,4,422800 +422823,巴东县,4,422800 +422825,宣恩县,4,422800 +422826,咸丰县,4,422800 +422827,来凤县,4,422800 +422828,鹤峰县,4,422800 +429004,仙桃市,4,429000 +429005,潜江市,4,429000 +429006,天门市,4,429000 +429021,神农架林区,4,429000 +430102,芙蓉区,4,430100 +430103,天心区,4,430100 +430104,岳麓区,4,430100 +430105,开福区,4,430100 +430111,雨花区,4,430100 +430112,望城区,4,430100 +430121,长沙县,4,430100 +430181,浏阳市,4,430100 +430182,宁乡市,4,430100 +430202,荷塘区,4,430200 +430203,芦淞区,4,430200 +430204,石峰区,4,430200 +430211,天元区,4,430200 +430212,渌口区,4,430200 +430223,攸县,4,430200 +430224,茶陵县,4,430200 +430225,炎陵县,4,430200 +430271,云龙示范区,4,430200 +430281,醴陵市,4,430200 +430302,雨湖区,4,430300 +430304,岳塘区,4,430300 +430321,湘潭县,4,430300 +430371,湖南湘潭高新技术产业园区,4,430300 +430372,湘潭昭山示范区,4,430300 +430373,湘潭九华示范区,4,430300 +430381,湘乡市,4,430300 +430382,韶山市,4,430300 +430405,珠晖区,4,430400 +430406,雁峰区,4,430400 +430407,石鼓区,4,430400 +430408,蒸湘区,4,430400 +430412,南岳区,4,430400 +430421,衡阳县,4,430400 +430422,衡南县,4,430400 +430423,衡山县,4,430400 +430424,衡东县,4,430400 +430426,祁东县,4,430400 +430471,衡阳综合保税区,4,430400 +430472,湖南衡阳高新技术产业园区,4,430400 +430473,湖南衡阳松木经济开发区,4,430400 +430481,耒阳市,4,430400 +430482,常宁市,4,430400 +430502,双清区,4,430500 +430503,大祥区,4,430500 +430511,北塔区,4,430500 +430522,新邵县,4,430500 +430523,邵阳县,4,430500 +430524,隆回县,4,430500 +430525,洞口县,4,430500 +430527,绥宁县,4,430500 +430528,新宁县,4,430500 +430529,城步苗族自治县,4,430500 +430581,武冈市,4,430500 +430582,邵东市,4,430500 +430602,岳阳楼区,4,430600 +430603,云溪区,4,430600 +430611,君山区,4,430600 +430621,岳阳县,4,430600 +430623,华容县,4,430600 +430624,湘阴县,4,430600 +430626,平江县,4,430600 +430671,岳阳市屈原管理区,4,430600 +430681,汨罗市,4,430600 +430682,临湘市,4,430600 +430702,武陵区,4,430700 +430703,鼎城区,4,430700 +430721,安乡县,4,430700 +430722,汉寿县,4,430700 +430723,澧县,4,430700 +430724,临澧县,4,430700 +430725,桃源县,4,430700 +430726,石门县,4,430700 +430771,常德市西洞庭管理区,4,430700 +430781,津市市,4,430700 +430802,永定区,4,430800 +430811,武陵源区,4,430800 +430821,慈利县,4,430800 +430822,桑植县,4,430800 +430902,资阳区,4,430900 +430903,赫山区,4,430900 +430921,南县,4,430900 +430922,桃江县,4,430900 +430923,安化县,4,430900 +430971,益阳市大通湖管理区,4,430900 +430972,湖南益阳高新技术产业园区,4,430900 +430981,沅江市,4,430900 +431002,北湖区,4,431000 +431003,苏仙区,4,431000 +431021,桂阳县,4,431000 +431022,宜章县,4,431000 +431023,永兴县,4,431000 +431024,嘉禾县,4,431000 +431025,临武县,4,431000 +431026,汝城县,4,431000 +431027,桂东县,4,431000 +431028,安仁县,4,431000 +431081,资兴市,4,431000 +431102,零陵区,4,431100 +431103,冷水滩区,4,431100 +431122,东安县,4,431100 +431123,双牌县,4,431100 +431124,道县,4,431100 +431125,江永县,4,431100 +431126,宁远县,4,431100 +431127,蓝山县,4,431100 +431128,新田县,4,431100 +431129,江华瑶族自治县,4,431100 +431171,永州经济技术开发区,4,431100 +431173,永州市回龙圩管理区,4,431100 +431181,祁阳市,4,431100 +431202,鹤城区,4,431200 +431221,中方县,4,431200 +431222,沅陵县,4,431200 +431223,辰溪县,4,431200 +431224,溆浦县,4,431200 +431225,会同县,4,431200 +431226,麻阳苗族自治县,4,431200 +431227,新晃侗族自治县,4,431200 +431228,芷江侗族自治县,4,431200 +431229,靖州苗族侗族自治县,4,431200 +431230,通道侗族自治县,4,431200 +431271,怀化市洪江管理区,4,431200 +431281,洪江市,4,431200 +431302,娄星区,4,431300 +431321,双峰县,4,431300 +431322,新化县,4,431300 +431381,冷水江市,4,431300 +431382,涟源市,4,431300 +433101,吉首市,4,433100 +433122,泸溪县,4,433100 +433123,凤凰县,4,433100 +433124,花垣县,4,433100 +433125,保靖县,4,433100 +433126,古丈县,4,433100 +433127,永顺县,4,433100 +433130,龙山县,4,433100 +440103,荔湾区,4,440100 +440104,越秀区,4,440100 +440105,海珠区,4,440100 +440106,天河区,4,440100 +440111,白云区,4,440100 +440112,黄埔区,4,440100 +440113,番禺区,4,440100 +440114,花都区,4,440100 +440115,南沙区,4,440100 +440117,从化区,4,440100 +440118,增城区,4,440100 +440203,武江区,4,440200 +440204,浈江区,4,440200 +440205,曲江区,4,440200 +440222,始兴县,4,440200 +440224,仁化县,4,440200 +440229,翁源县,4,440200 +440232,乳源瑶族自治县,4,440200 +440233,新丰县,4,440200 +440281,乐昌市,4,440200 +440282,南雄市,4,440200 +440303,罗湖区,4,440300 +440304,福田区,4,440300 +440305,南山区,4,440300 +440306,宝安区,4,440300 +440307,龙岗区,4,440300 +440308,盐田区,4,440300 +440309,龙华区,4,440300 +440310,坪山区,4,440300 +440311,光明区,4,440300 +440402,香洲区,4,440400 +440403,斗门区,4,440400 +440404,金湾区,4,440400 +440507,龙湖区,4,440500 +440511,金平区,4,440500 +440512,濠江区,4,440500 +440513,潮阳区,4,440500 +440514,潮南区,4,440500 +440515,澄海区,4,440500 +440523,南澳县,4,440500 +440604,禅城区,4,440600 +440605,南海区,4,440600 +440606,顺德区,4,440600 +440607,三水区,4,440600 +440608,高明区,4,440600 +440703,蓬江区,4,440700 +440704,江海区,4,440700 +440705,新会区,4,440700 +440781,台山市,4,440700 +440783,开平市,4,440700 +440784,鹤山市,4,440700 +440785,恩平市,4,440700 +440802,赤坎区,4,440800 +440803,霞山区,4,440800 +440804,坡头区,4,440800 +440811,麻章区,4,440800 +440823,遂溪县,4,440800 +440825,徐闻县,4,440800 +440881,廉江市,4,440800 +440882,雷州市,4,440800 +440883,吴川市,4,440800 +440902,茂南区,4,440900 +440904,电白区,4,440900 +440981,高州市,4,440900 +440982,化州市,4,440900 +440983,信宜市,4,440900 +441202,端州区,4,441200 +441203,鼎湖区,4,441200 +441204,高要区,4,441200 +441223,广宁县,4,441200 +441224,怀集县,4,441200 +441225,封开县,4,441200 +441226,德庆县,4,441200 +441284,四会市,4,441200 +441302,惠城区,4,441300 +441303,惠阳区,4,441300 +441322,博罗县,4,441300 +441323,惠东县,4,441300 +441324,龙门县,4,441300 +441402,梅江区,4,441400 +441403,梅县区,4,441400 +441422,大埔县,4,441400 +441423,丰顺县,4,441400 +441424,五华县,4,441400 +441426,平远县,4,441400 +441427,蕉岭县,4,441400 +441481,兴宁市,4,441400 +441502,城区,4,441500 +441521,海丰县,4,441500 +441523,陆河县,4,441500 +441581,陆丰市,4,441500 +441602,源城区,4,441600 +441621,紫金县,4,441600 +441622,龙川县,4,441600 +441623,连平县,4,441600 +441624,和平县,4,441600 +441625,东源县,4,441600 +441702,江城区,4,441700 +441704,阳东区,4,441700 +441721,阳西县,4,441700 +441781,阳春市,4,441700 +441802,清城区,4,441800 +441803,清新区,4,441800 +441821,佛冈县,4,441800 +441823,阳山县,4,441800 +441825,连山壮族瑶族自治县,4,441800 +441826,连南瑶族自治县,4,441800 +441881,英德市,4,441800 +441882,连州市,4,441800 +445102,湘桥区,4,445100 +445103,潮安区,4,445100 +445122,饶平县,4,445100 +445202,榕城区,4,445200 +445203,揭东区,4,445200 +445222,揭西县,4,445200 +445224,惠来县,4,445200 +445281,普宁市,4,445200 +445302,云城区,4,445300 +445303,云安区,4,445300 +445321,新兴县,4,445300 +445322,郁南县,4,445300 +445381,罗定市,4,445300 +450102,兴宁区,4,450100 +450103,青秀区,4,450100 +450105,江南区,4,450100 +450107,西乡塘区,4,450100 +450108,良庆区,4,450100 +450109,邕宁区,4,450100 +450110,武鸣区,4,450100 +450123,隆安县,4,450100 +450124,马山县,4,450100 +450125,上林县,4,450100 +450126,宾阳县,4,450100 +450181,横州市,4,450100 +450202,城中区,4,450200 +450203,鱼峰区,4,450200 +450204,柳南区,4,450200 +450205,柳北区,4,450200 +450206,柳江区,4,450200 +450222,柳城县,4,450200 +450223,鹿寨县,4,450200 +450224,融安县,4,450200 +450225,融水苗族自治县,4,450200 +450226,三江侗族自治县,4,450200 +450302,秀峰区,4,450300 +450303,叠彩区,4,450300 +450304,象山区,4,450300 +450305,七星区,4,450300 +450311,雁山区,4,450300 +450312,临桂区,4,450300 +450321,阳朔县,4,450300 +450323,灵川县,4,450300 +450324,全州县,4,450300 +450325,兴安县,4,450300 +450326,永福县,4,450300 +450327,灌阳县,4,450300 +450328,龙胜各族自治县,4,450300 +450329,资源县,4,450300 +450330,平乐县,4,450300 +450332,恭城瑶族自治县,4,450300 +450381,荔浦市,4,450300 +450403,万秀区,4,450400 +450405,长洲区,4,450400 +450406,龙圩区,4,450400 +450421,苍梧县,4,450400 +450422,藤县,4,450400 +450423,蒙山县,4,450400 +450481,岑溪市,4,450400 +450502,海城区,4,450500 +450503,银海区,4,450500 +450512,铁山港区,4,450500 +450521,合浦县,4,450500 +450602,港口区,4,450600 +450603,防城区,4,450600 +450621,上思县,4,450600 +450681,东兴市,4,450600 +450702,钦南区,4,450700 +450703,钦北区,4,450700 +450721,灵山县,4,450700 +450722,浦北县,4,450700 +450802,港北区,4,450800 +450803,港南区,4,450800 +450804,覃塘区,4,450800 +450821,平南县,4,450800 +450881,桂平市,4,450800 +450902,玉州区,4,450900 +450903,福绵区,4,450900 +450921,容县,4,450900 +450922,陆川县,4,450900 +450923,博白县,4,450900 +450924,兴业县,4,450900 +450981,北流市,4,450900 +451002,右江区,4,451000 +451003,田阳区,4,451000 +451022,田东县,4,451000 +451024,德保县,4,451000 +451026,那坡县,4,451000 +451027,凌云县,4,451000 +451028,乐业县,4,451000 +451029,田林县,4,451000 +451030,西林县,4,451000 +451031,隆林各族自治县,4,451000 +451081,靖西市,4,451000 +451082,平果市,4,451000 +451102,八步区,4,451100 +451103,平桂区,4,451100 +451121,昭平县,4,451100 +451122,钟山县,4,451100 +451123,富川瑶族自治县,4,451100 +451202,金城江区,4,451200 +451203,宜州区,4,451200 +451221,南丹县,4,451200 +451222,天峨县,4,451200 +451223,凤山县,4,451200 +451224,东兰县,4,451200 +451225,罗城仫佬族自治县,4,451200 +451226,环江毛南族自治县,4,451200 +451227,巴马瑶族自治县,4,451200 +451228,都安瑶族自治县,4,451200 +451229,大化瑶族自治县,4,451200 +451302,兴宾区,4,451300 +451321,忻城县,4,451300 +451322,象州县,4,451300 +451323,武宣县,4,451300 +451324,金秀瑶族自治县,4,451300 +451381,合山市,4,451300 +451402,江州区,4,451400 +451421,扶绥县,4,451400 +451422,宁明县,4,451400 +451423,龙州县,4,451400 +451424,大新县,4,451400 +451425,天等县,4,451400 +451481,凭祥市,4,451400 +460105,秀英区,4,460100 +460106,龙华区,4,460100 +460107,琼山区,4,460100 +460108,美兰区,4,460100 +460202,海棠区,4,460200 +460203,吉阳区,4,460200 +460204,天涯区,4,460200 +460205,崖州区,4,460200 +460321,西沙群岛,4,460300 +460322,南沙群岛,4,460300 +460323,中沙群岛的岛礁及其海域,4,460300 +469001,五指山市,4,469000 +469002,琼海市,4,469000 +469005,文昌市,4,469000 +469006,万宁市,4,469000 +469007,东方市,4,469000 +469021,定安县,4,469000 +469022,屯昌县,4,469000 +469023,澄迈县,4,469000 +469024,临高县,4,469000 +469025,白沙黎族自治县,4,469000 +469026,昌江黎族自治县,4,469000 +469027,乐东黎族自治县,4,469000 +469028,陵水黎族自治县,4,469000 +469029,保亭黎族苗族自治县,4,469000 +469030,琼中黎族苗族自治县,4,469000 +500101,万州区,4,500100 +500102,涪陵区,4,500100 +500103,渝中区,4,500100 +500104,大渡口区,4,500100 +500105,江北区,4,500100 +500106,沙坪坝区,4,500100 +500107,九龙坡区,4,500100 +500108,南岸区,4,500100 +500109,北碚区,4,500100 +500110,綦江区,4,500100 +500111,大足区,4,500100 +500112,渝北区,4,500100 +500113,巴南区,4,500100 +500114,黔江区,4,500100 +500115,长寿区,4,500100 +500116,江津区,4,500100 +500117,合川区,4,500100 +500118,永川区,4,500100 +500119,南川区,4,500100 +500120,璧山区,4,500100 +500151,铜梁区,4,500100 +500152,潼南区,4,500100 +500153,荣昌区,4,500100 +500154,开州区,4,500100 +500155,梁平区,4,500100 +500156,武隆区,4,500100 +500229,城口县,4,500100 +500230,丰都县,4,500100 +500231,垫江县,4,500100 +500233,忠县,4,500100 +500235,云阳县,4,500100 +500236,奉节县,4,500100 +500237,巫山县,4,500100 +500238,巫溪县,4,500100 +500240,石柱土家族自治县,4,500100 +500241,秀山土家族苗族自治县,4,500100 +500242,酉阳土家族苗族自治县,4,500100 +500243,彭水苗族土家族自治县,4,500100 +510104,锦江区,4,510100 +510105,青羊区,4,510100 +510106,金牛区,4,510100 +510107,武侯区,4,510100 +510108,成华区,4,510100 +510112,龙泉驿区,4,510100 +510113,青白江区,4,510100 +510114,新都区,4,510100 +510115,温江区,4,510100 +510116,双流区,4,510100 +510117,郫都区,4,510100 +510118,新津区,4,510100 +510121,金堂县,4,510100 +510129,大邑县,4,510100 +510131,蒲江县,4,510100 +510181,都江堰市,4,510100 +510182,彭州市,4,510100 +510183,邛崃市,4,510100 +510184,崇州市,4,510100 +510185,简阳市,4,510100 +510302,自流井区,4,510300 +510303,贡井区,4,510300 +510304,大安区,4,510300 +510311,沿滩区,4,510300 +510321,荣县,4,510300 +510322,富顺县,4,510300 +510402,东区,4,510400 +510403,西区,4,510400 +510411,仁和区,4,510400 +510421,米易县,4,510400 +510422,盐边县,4,510400 +510502,江阳区,4,510500 +510503,纳溪区,4,510500 +510504,龙马潭区,4,510500 +510521,泸县,4,510500 +510522,合江县,4,510500 +510524,叙永县,4,510500 +510525,古蔺县,4,510500 +510603,旌阳区,4,510600 +510604,罗江区,4,510600 +510623,中江县,4,510600 +510681,广汉市,4,510600 +510682,什邡市,4,510600 +510683,绵竹市,4,510600 +510703,涪城区,4,510700 +510704,游仙区,4,510700 +510705,安州区,4,510700 +510722,三台县,4,510700 +510723,盐亭县,4,510700 +510725,梓潼县,4,510700 +510726,北川羌族自治县,4,510700 +510727,平武县,4,510700 +510781,江油市,4,510700 +510802,利州区,4,510800 +510811,昭化区,4,510800 +510812,朝天区,4,510800 +510821,旺苍县,4,510800 +510822,青川县,4,510800 +510823,剑阁县,4,510800 +510824,苍溪县,4,510800 +510903,船山区,4,510900 +510904,安居区,4,510900 +510921,蓬溪县,4,510900 +510923,大英县,4,510900 +510981,射洪市,4,510900 +511002,市中区,4,511000 +511011,东兴区,4,511000 +511024,威远县,4,511000 +511025,资中县,4,511000 +511071,内江经济开发区,4,511000 +511083,隆昌市,4,511000 +511102,市中区,4,511100 +511111,沙湾区,4,511100 +511112,五通桥区,4,511100 +511113,金口河区,4,511100 +511123,犍为县,4,511100 +511124,井研县,4,511100 +511126,夹江县,4,511100 +511129,沐川县,4,511100 +511132,峨边彝族自治县,4,511100 +511133,马边彝族自治县,4,511100 +511181,峨眉山市,4,511100 +511302,顺庆区,4,511300 +511303,高坪区,4,511300 +511304,嘉陵区,4,511300 +511321,南部县,4,511300 +511322,营山县,4,511300 +511323,蓬安县,4,511300 +511324,仪陇县,4,511300 +511325,西充县,4,511300 +511381,阆中市,4,511300 +511402,东坡区,4,511400 +511403,彭山区,4,511400 +511421,仁寿县,4,511400 +511423,洪雅县,4,511400 +511424,丹棱县,4,511400 +511425,青神县,4,511400 +511502,翠屏区,4,511500 +511503,南溪区,4,511500 +511504,叙州区,4,511500 +511523,江安县,4,511500 +511524,长宁县,4,511500 +511525,高县,4,511500 +511526,珙县,4,511500 +511527,筠连县,4,511500 +511528,兴文县,4,511500 +511529,屏山县,4,511500 +511602,广安区,4,511600 +511603,前锋区,4,511600 +511621,岳池县,4,511600 +511622,武胜县,4,511600 +511623,邻水县,4,511600 +511681,华蓥市,4,511600 +511702,通川区,4,511700 +511703,达川区,4,511700 +511722,宣汉县,4,511700 +511723,开江县,4,511700 +511724,大竹县,4,511700 +511725,渠县,4,511700 +511771,达州经济开发区,4,511700 +511781,万源市,4,511700 +511802,雨城区,4,511800 +511803,名山区,4,511800 +511822,荥经县,4,511800 +511823,汉源县,4,511800 +511824,石棉县,4,511800 +511825,天全县,4,511800 +511826,芦山县,4,511800 +511827,宝兴县,4,511800 +511902,巴州区,4,511900 +511903,恩阳区,4,511900 +511921,通江县,4,511900 +511922,南江县,4,511900 +511923,平昌县,4,511900 +511971,巴中经济开发区,4,511900 +512002,雁江区,4,512000 +512021,安岳县,4,512000 +512022,乐至县,4,512000 +513201,马尔康市,4,513200 +513221,汶川县,4,513200 +513222,理县,4,513200 +513223,茂县,4,513200 +513224,松潘县,4,513200 +513225,九寨沟县,4,513200 +513226,金川县,4,513200 +513227,小金县,4,513200 +513228,黑水县,4,513200 +513230,壤塘县,4,513200 +513231,阿坝县,4,513200 +513232,若尔盖县,4,513200 +513233,红原县,4,513200 +513301,康定市,4,513300 +513322,泸定县,4,513300 +513323,丹巴县,4,513300 +513324,九龙县,4,513300 +513325,雅江县,4,513300 +513326,道孚县,4,513300 +513327,炉霍县,4,513300 +513328,甘孜县,4,513300 +513329,新龙县,4,513300 +513330,德格县,4,513300 +513331,白玉县,4,513300 +513332,石渠县,4,513300 +513333,色达县,4,513300 +513334,理塘县,4,513300 +513335,巴塘县,4,513300 +513336,乡城县,4,513300 +513337,稻城县,4,513300 +513338,得荣县,4,513300 +513401,西昌市,4,513400 +513402,会理市,4,513400 +513422,木里藏族自治县,4,513400 +513423,盐源县,4,513400 +513424,德昌县,4,513400 +513426,会东县,4,513400 +513427,宁南县,4,513400 +513428,普格县,4,513400 +513429,布拖县,4,513400 +513430,金阳县,4,513400 +513431,昭觉县,4,513400 +513432,喜德县,4,513400 +513433,冕宁县,4,513400 +513434,越西县,4,513400 +513435,甘洛县,4,513400 +513436,美姑县,4,513400 +513437,雷波县,4,513400 +520102,南明区,4,520100 +520103,云岩区,4,520100 +520111,花溪区,4,520100 +520112,乌当区,4,520100 +520113,白云区,4,520100 +520115,观山湖区,4,520100 +520121,开阳县,4,520100 +520122,息烽县,4,520100 +520123,修文县,4,520100 +520181,清镇市,4,520100 +520201,钟山区,4,520200 +520203,六枝特区,4,520200 +520204,水城区,4,520200 +520281,盘州市,4,520200 +520302,红花岗区,4,520300 +520303,汇川区,4,520300 +520304,播州区,4,520300 +520322,桐梓县,4,520300 +520323,绥阳县,4,520300 +520324,正安县,4,520300 +520325,道真仡佬族苗族自治县,4,520300 +520326,务川仡佬族苗族自治县,4,520300 +520327,凤冈县,4,520300 +520328,湄潭县,4,520300 +520329,余庆县,4,520300 +520330,习水县,4,520300 +520381,赤水市,4,520300 +520382,仁怀市,4,520300 +520402,西秀区,4,520400 +520403,平坝区,4,520400 +520422,普定县,4,520400 +520423,镇宁布依族苗族自治县,4,520400 +520424,关岭布依族苗族自治县,4,520400 +520425,紫云苗族布依族自治县,4,520400 +520502,七星关区,4,520500 +520521,大方县,4,520500 +520523,金沙县,4,520500 +520524,织金县,4,520500 +520525,纳雍县,4,520500 +520526,威宁彝族回族苗族自治县,4,520500 +520527,赫章县,4,520500 +520581,黔西市,4,520500 +520602,碧江区,4,520600 +520603,万山区,4,520600 +520621,江口县,4,520600 +520622,玉屏侗族自治县,4,520600 +520623,石阡县,4,520600 +520624,思南县,4,520600 +520625,印江土家族苗族自治县,4,520600 +520626,德江县,4,520600 +520627,沿河土家族自治县,4,520600 +520628,松桃苗族自治县,4,520600 +522301,兴义市,4,522300 +522302,兴仁市,4,522300 +522323,普安县,4,522300 +522324,晴隆县,4,522300 +522325,贞丰县,4,522300 +522326,望谟县,4,522300 +522327,册亨县,4,522300 +522328,安龙县,4,522300 +522601,凯里市,4,522600 +522622,黄平县,4,522600 +522623,施秉县,4,522600 +522624,三穗县,4,522600 +522625,镇远县,4,522600 +522626,岑巩县,4,522600 +522627,天柱县,4,522600 +522628,锦屏县,4,522600 +522629,剑河县,4,522600 +522630,台江县,4,522600 +522631,黎平县,4,522600 +522632,榕江县,4,522600 +522633,从江县,4,522600 +522634,雷山县,4,522600 +522635,麻江县,4,522600 +522636,丹寨县,4,522600 +522701,都匀市,4,522700 +522702,福泉市,4,522700 +522722,荔波县,4,522700 +522723,贵定县,4,522700 +522725,瓮安县,4,522700 +522726,独山县,4,522700 +522727,平塘县,4,522700 +522728,罗甸县,4,522700 +522729,长顺县,4,522700 +522730,龙里县,4,522700 +522731,惠水县,4,522700 +522732,三都水族自治县,4,522700 +530102,五华区,4,530100 +530103,盘龙区,4,530100 +530111,官渡区,4,530100 +530112,西山区,4,530100 +530113,东川区,4,530100 +530114,呈贡区,4,530100 +530115,晋宁区,4,530100 +530124,富民县,4,530100 +530125,宜良县,4,530100 +530126,石林彝族自治县,4,530100 +530127,嵩明县,4,530100 +530128,禄劝彝族苗族自治县,4,530100 +530129,寻甸回族彝族自治县,4,530100 +530181,安宁市,4,530100 +530302,麒麟区,4,530300 +530303,沾益区,4,530300 +530304,马龙区,4,530300 +530322,陆良县,4,530300 +530323,师宗县,4,530300 +530324,罗平县,4,530300 +530325,富源县,4,530300 +530326,会泽县,4,530300 +530381,宣威市,4,530300 +530402,红塔区,4,530400 +530403,江川区,4,530400 +530423,通海县,4,530400 +530424,华宁县,4,530400 +530425,易门县,4,530400 +530426,峨山彝族自治县,4,530400 +530427,新平彝族傣族自治县,4,530400 +530428,元江哈尼族彝族傣族自治县,4,530400 +530481,澄江市,4,530400 +530502,隆阳区,4,530500 +530521,施甸县,4,530500 +530523,龙陵县,4,530500 +530524,昌宁县,4,530500 +530581,腾冲市,4,530500 +530602,昭阳区,4,530600 +530621,鲁甸县,4,530600 +530622,巧家县,4,530600 +530623,盐津县,4,530600 +530624,大关县,4,530600 +530625,永善县,4,530600 +530626,绥江县,4,530600 +530627,镇雄县,4,530600 +530628,彝良县,4,530600 +530629,威信县,4,530600 +530681,水富市,4,530600 +530702,古城区,4,530700 +530721,玉龙纳西族自治县,4,530700 +530722,永胜县,4,530700 +530723,华坪县,4,530700 +530724,宁蒗彝族自治县,4,530700 +530802,思茅区,4,530800 +530821,宁洱哈尼族彝族自治县,4,530800 +530822,墨江哈尼族自治县,4,530800 +530823,景东彝族自治县,4,530800 +530824,景谷傣族彝族自治县,4,530800 +530825,镇沅彝族哈尼族拉祜族自治县,4,530800 +530826,江城哈尼族彝族自治县,4,530800 +530827,孟连傣族拉祜族佤族自治县,4,530800 +530828,澜沧拉祜族自治县,4,530800 +530829,西盟佤族自治县,4,530800 +530902,临翔区,4,530900 +530921,凤庆县,4,530900 +530922,云县,4,530900 +530923,永德县,4,530900 +530924,镇康县,4,530900 +530925,双江拉祜族佤族布朗族傣族自治县,4,530900 +530926,耿马傣族佤族自治县,4,530900 +530927,沧源佤族自治县,4,530900 +532301,楚雄市,4,532300 +532302,禄丰市,4,532300 +532322,双柏县,4,532300 +532323,牟定县,4,532300 +532324,南华县,4,532300 +532325,姚安县,4,532300 +532326,大姚县,4,532300 +532327,永仁县,4,532300 +532328,元谋县,4,532300 +532329,武定县,4,532300 +532501,个旧市,4,532500 +532502,开远市,4,532500 +532503,蒙自市,4,532500 +532504,弥勒市,4,532500 +532523,屏边苗族自治县,4,532500 +532524,建水县,4,532500 +532525,石屏县,4,532500 +532527,泸西县,4,532500 +532528,元阳县,4,532500 +532529,红河县,4,532500 +532530,金平苗族瑶族傣族自治县,4,532500 +532531,绿春县,4,532500 +532532,河口瑶族自治县,4,532500 +532601,文山市,4,532600 +532622,砚山县,4,532600 +532623,西畴县,4,532600 +532624,麻栗坡县,4,532600 +532625,马关县,4,532600 +532626,丘北县,4,532600 +532627,广南县,4,532600 +532628,富宁县,4,532600 +532801,景洪市,4,532800 +532822,勐海县,4,532800 +532823,勐腊县,4,532800 +532901,大理市,4,532900 +532922,漾濞彝族自治县,4,532900 +532923,祥云县,4,532900 +532924,宾川县,4,532900 +532925,弥渡县,4,532900 +532926,南涧彝族自治县,4,532900 +532927,巍山彝族回族自治县,4,532900 +532928,永平县,4,532900 +532929,云龙县,4,532900 +532930,洱源县,4,532900 +532931,剑川县,4,532900 +532932,鹤庆县,4,532900 +533102,瑞丽市,4,533100 +533103,芒市,4,533100 +533122,梁河县,4,533100 +533123,盈江县,4,533100 +533124,陇川县,4,533100 +533301,泸水市,4,533300 +533323,福贡县,4,533300 +533324,贡山独龙族怒族自治县,4,533300 +533325,兰坪白族普米族自治县,4,533300 +533401,香格里拉市,4,533400 +533422,德钦县,4,533400 +533423,维西傈僳族自治县,4,533400 +540102,城关区,4,540100 +540103,堆龙德庆区,4,540100 +540104,达孜区,4,540100 +540121,林周县,4,540100 +540122,当雄县,4,540100 +540123,尼木县,4,540100 +540124,曲水县,4,540100 +540127,墨竹工卡县,4,540100 +540171,格尔木藏青工业园区,4,540100 +540172,拉萨经济技术开发区,4,540100 +540173,西藏文化旅游创意园区,4,540100 +540174,达孜工业园区,4,540100 +540202,桑珠孜区,4,540200 +540221,南木林县,4,540200 +540222,江孜县,4,540200 +540223,定日县,4,540200 +540224,萨迦县,4,540200 +540225,拉孜县,4,540200 +540226,昂仁县,4,540200 +540227,谢通门县,4,540200 +540228,白朗县,4,540200 +540229,仁布县,4,540200 +540230,康马县,4,540200 +540231,定结县,4,540200 +540232,仲巴县,4,540200 +540233,亚东县,4,540200 +540234,吉隆县,4,540200 +540235,聂拉木县,4,540200 +540236,萨嘎县,4,540200 +540237,岗巴县,4,540200 +540302,卡若区,4,540300 +540321,江达县,4,540300 +540322,贡觉县,4,540300 +540323,类乌齐县,4,540300 +540324,丁青县,4,540300 +540325,察雅县,4,540300 +540326,八宿县,4,540300 +540327,左贡县,4,540300 +540328,芒康县,4,540300 +540329,洛隆县,4,540300 +540330,边坝县,4,540300 +540402,巴宜区,4,540400 +540421,工布江达县,4,540400 +540422,米林县,4,540400 +540423,墨脱县,4,540400 +540424,波密县,4,540400 +540425,察隅县,4,540400 +540426,朗县,4,540400 +540502,乃东区,4,540500 +540521,扎囊县,4,540500 +540522,贡嘎县,4,540500 +540523,桑日县,4,540500 +540524,琼结县,4,540500 +540525,曲松县,4,540500 +540526,措美县,4,540500 +540527,洛扎县,4,540500 +540528,加查县,4,540500 +540529,隆子县,4,540500 +540530,错那县,4,540500 +540531,浪卡子县,4,540500 +540602,色尼区,4,540600 +540621,嘉黎县,4,540600 +540622,比如县,4,540600 +540623,聂荣县,4,540600 +540624,安多县,4,540600 +540625,申扎县,4,540600 +540626,索县,4,540600 +540627,班戈县,4,540600 +540628,巴青县,4,540600 +540629,尼玛县,4,540600 +540630,双湖县,4,540600 +542521,普兰县,4,542500 +542522,札达县,4,542500 +542523,噶尔县,4,542500 +542524,日土县,4,542500 +542525,革吉县,4,542500 +542526,改则县,4,542500 +542527,措勤县,4,542500 +610102,新城区,4,610100 +610103,碑林区,4,610100 +610104,莲湖区,4,610100 +610111,灞桥区,4,610100 +610112,未央区,4,610100 +610113,雁塔区,4,610100 +610114,阎良区,4,610100 +610115,临潼区,4,610100 +610116,长安区,4,610100 +610117,高陵区,4,610100 +610118,鄠邑区,4,610100 +610122,蓝田县,4,610100 +610124,周至县,4,610100 +610202,王益区,4,610200 +610203,印台区,4,610200 +610204,耀州区,4,610200 +610222,宜君县,4,610200 +610302,渭滨区,4,610300 +610303,金台区,4,610300 +610304,陈仓区,4,610300 +610305,凤翔区,4,610300 +610323,岐山县,4,610300 +610324,扶风县,4,610300 +610326,眉县,4,610300 +610327,陇县,4,610300 +610328,千阳县,4,610300 +610329,麟游县,4,610300 +610330,凤县,4,610300 +610331,太白县,4,610300 +610402,秦都区,4,610400 +610403,杨陵区,4,610400 +610404,渭城区,4,610400 +610422,三原县,4,610400 +610423,泾阳县,4,610400 +610424,乾县,4,610400 +610425,礼泉县,4,610400 +610426,永寿县,4,610400 +610428,长武县,4,610400 +610429,旬邑县,4,610400 +610430,淳化县,4,610400 +610431,武功县,4,610400 +610481,兴平市,4,610400 +610482,彬州市,4,610400 +610502,临渭区,4,610500 +610503,华州区,4,610500 +610522,潼关县,4,610500 +610523,大荔县,4,610500 +610524,合阳县,4,610500 +610525,澄城县,4,610500 +610526,蒲城县,4,610500 +610527,白水县,4,610500 +610528,富平县,4,610500 +610581,韩城市,4,610500 +610582,华阴市,4,610500 +610602,宝塔区,4,610600 +610603,安塞区,4,610600 +610621,延长县,4,610600 +610622,延川县,4,610600 +610625,志丹县,4,610600 +610626,吴起县,4,610600 +610627,甘泉县,4,610600 +610628,富县,4,610600 +610629,洛川县,4,610600 +610630,宜川县,4,610600 +610631,黄龙县,4,610600 +610632,黄陵县,4,610600 +610681,子长市,4,610600 +610702,汉台区,4,610700 +610703,南郑区,4,610700 +610722,城固县,4,610700 +610723,洋县,4,610700 +610724,西乡县,4,610700 +610725,勉县,4,610700 +610726,宁强县,4,610700 +610727,略阳县,4,610700 +610728,镇巴县,4,610700 +610729,留坝县,4,610700 +610730,佛坪县,4,610700 +610802,榆阳区,4,610800 +610803,横山区,4,610800 +610822,府谷县,4,610800 +610824,靖边县,4,610800 +610825,定边县,4,610800 +610826,绥德县,4,610800 +610827,米脂县,4,610800 +610828,佳县,4,610800 +610829,吴堡县,4,610800 +610830,清涧县,4,610800 +610831,子洲县,4,610800 +610881,神木市,4,610800 +610902,汉滨区,4,610900 +610921,汉阴县,4,610900 +610922,石泉县,4,610900 +610923,宁陕县,4,610900 +610924,紫阳县,4,610900 +610925,岚皋县,4,610900 +610926,平利县,4,610900 +610927,镇坪县,4,610900 +610929,白河县,4,610900 +610981,旬阳市,4,610900 +611002,商州区,4,611000 +611021,洛南县,4,611000 +611022,丹凤县,4,611000 +611023,商南县,4,611000 +611024,山阳县,4,611000 +611025,镇安县,4,611000 +611026,柞水县,4,611000 +620102,城关区,4,620100 +620103,七里河区,4,620100 +620104,西固区,4,620100 +620105,安宁区,4,620100 +620111,红古区,4,620100 +620121,永登县,4,620100 +620122,皋兰县,4,620100 +620123,榆中县,4,620100 +620171,兰州新区,4,620100 +620201,嘉峪关市,4,620200 +620302,金川区,4,620300 +620321,永昌县,4,620300 +620402,白银区,4,620400 +620403,平川区,4,620400 +620421,靖远县,4,620400 +620422,会宁县,4,620400 +620423,景泰县,4,620400 +620502,秦州区,4,620500 +620503,麦积区,4,620500 +620521,清水县,4,620500 +620522,秦安县,4,620500 +620523,甘谷县,4,620500 +620524,武山县,4,620500 +620525,张家川回族自治县,4,620500 +620602,凉州区,4,620600 +620621,民勤县,4,620600 +620622,古浪县,4,620600 +620623,天祝藏族自治县,4,620600 +620702,甘州区,4,620700 +620721,肃南裕固族自治县,4,620700 +620722,民乐县,4,620700 +620723,临泽县,4,620700 +620724,高台县,4,620700 +620725,山丹县,4,620700 +620802,崆峒区,4,620800 +620821,泾川县,4,620800 +620822,灵台县,4,620800 +620823,崇信县,4,620800 +620825,庄浪县,4,620800 +620826,静宁县,4,620800 +620881,华亭市,4,620800 +620902,肃州区,4,620900 +620921,金塔县,4,620900 +620922,瓜州县,4,620900 +620923,肃北蒙古族自治县,4,620900 +620924,阿克塞哈萨克族自治县,4,620900 +620981,玉门市,4,620900 +620982,敦煌市,4,620900 +621002,西峰区,4,621000 +621021,庆城县,4,621000 +621022,环县,4,621000 +621023,华池县,4,621000 +621024,合水县,4,621000 +621025,正宁县,4,621000 +621026,宁县,4,621000 +621027,镇原县,4,621000 +621102,安定区,4,621100 +621121,通渭县,4,621100 +621122,陇西县,4,621100 +621123,渭源县,4,621100 +621124,临洮县,4,621100 +621125,漳县,4,621100 +621126,岷县,4,621100 +621202,武都区,4,621200 +621221,成县,4,621200 +621222,文县,4,621200 +621223,宕昌县,4,621200 +621224,康县,4,621200 +621225,西和县,4,621200 +621226,礼县,4,621200 +621227,徽县,4,621200 +621228,两当县,4,621200 +622901,临夏市,4,622900 +622921,临夏县,4,622900 +622922,康乐县,4,622900 +622923,永靖县,4,622900 +622924,广河县,4,622900 +622925,和政县,4,622900 +622926,东乡族自治县,4,622900 +622927,积石山保安族东乡族撒拉族自治县,4,622900 +623001,合作市,4,623000 +623021,临潭县,4,623000 +623022,卓尼县,4,623000 +623023,舟曲县,4,623000 +623024,迭部县,4,623000 +623025,玛曲县,4,623000 +623026,碌曲县,4,623000 +623027,夏河县,4,623000 +630102,城东区,4,630100 +630103,城中区,4,630100 +630104,城西区,4,630100 +630105,城北区,4,630100 +630106,湟中区,4,630100 +630121,大通回族土族自治县,4,630100 +630123,湟源县,4,630100 +630202,乐都区,4,630200 +630203,平安区,4,630200 +630222,民和回族土族自治县,4,630200 +630223,互助土族自治县,4,630200 +630224,化隆回族自治县,4,630200 +630225,循化撒拉族自治县,4,630200 +632221,门源回族自治县,4,632200 +632222,祁连县,4,632200 +632223,海晏县,4,632200 +632224,刚察县,4,632200 +632301,同仁市,4,632300 +632322,尖扎县,4,632300 +632323,泽库县,4,632300 +632324,河南蒙古族自治县,4,632300 +632521,共和县,4,632500 +632522,同德县,4,632500 +632523,贵德县,4,632500 +632524,兴海县,4,632500 +632525,贵南县,4,632500 +632621,玛沁县,4,632600 +632622,班玛县,4,632600 +632623,甘德县,4,632600 +632624,达日县,4,632600 +632625,久治县,4,632600 +632626,玛多县,4,632600 +632701,玉树市,4,632700 +632722,杂多县,4,632700 +632723,称多县,4,632700 +632724,治多县,4,632700 +632725,囊谦县,4,632700 +632726,曲麻莱县,4,632700 +632801,格尔木市,4,632800 +632802,德令哈市,4,632800 +632803,茫崖市,4,632800 +632821,乌兰县,4,632800 +632822,都兰县,4,632800 +632823,天峻县,4,632800 +632857,大柴旦行政委员会,4,632800 +640104,兴庆区,4,640100 +640105,西夏区,4,640100 +640106,金凤区,4,640100 +640121,永宁县,4,640100 +640122,贺兰县,4,640100 +640181,灵武市,4,640100 +640202,大武口区,4,640200 +640205,惠农区,4,640200 +640221,平罗县,4,640200 +640302,利通区,4,640300 +640303,红寺堡区,4,640300 +640323,盐池县,4,640300 +640324,同心县,4,640300 +640381,青铜峡市,4,640300 +640402,原州区,4,640400 +640422,西吉县,4,640400 +640423,隆德县,4,640400 +640424,泾源县,4,640400 +640425,彭阳县,4,640400 +640502,沙坡头区,4,640500 +640521,中宁县,4,640500 +640522,海原县,4,640500 +650102,天山区,4,650100 +650103,沙依巴克区,4,650100 +650104,新市区,4,650100 +650105,水磨沟区,4,650100 +650106,头屯河区,4,650100 +650107,达坂城区,4,650100 +650109,米东区,4,650100 +650121,乌鲁木齐县,4,650100 +650202,独山子区,4,650200 +650203,克拉玛依区,4,650200 +650204,白碱滩区,4,650200 +650205,乌尔禾区,4,650200 +650402,高昌区,4,650400 +650421,鄯善县,4,650400 +650422,托克逊县,4,650400 +650502,伊州区,4,650500 +650521,巴里坤哈萨克自治县,4,650500 +650522,伊吾县,4,650500 +652301,昌吉市,4,652300 +652302,阜康市,4,652300 +652323,呼图壁县,4,652300 +652324,玛纳斯县,4,652300 +652325,奇台县,4,652300 +652327,吉木萨尔县,4,652300 +652328,木垒哈萨克自治县,4,652300 +652701,博乐市,4,652700 +652702,阿拉山口市,4,652700 +652722,精河县,4,652700 +652723,温泉县,4,652700 +652801,库尔勒市,4,652800 +652822,轮台县,4,652800 +652823,尉犁县,4,652800 +652824,若羌县,4,652800 +652825,且末县,4,652800 +652826,焉耆回族自治县,4,652800 +652827,和静县,4,652800 +652828,和硕县,4,652800 +652829,博湖县,4,652800 +652871,库尔勒经济技术开发区,4,652800 +652901,阿克苏市,4,652900 +652902,库车市,4,652900 +652922,温宿县,4,652900 +652924,沙雅县,4,652900 +652925,新和县,4,652900 +652926,拜城县,4,652900 +652927,乌什县,4,652900 +652928,阿瓦提县,4,652900 +652929,柯坪县,4,652900 +653001,阿图什市,4,653000 +653022,阿克陶县,4,653000 +653023,阿合奇县,4,653000 +653024,乌恰县,4,653000 +653101,喀什市,4,653100 +653121,疏附县,4,653100 +653122,疏勒县,4,653100 +653123,英吉沙县,4,653100 +653124,泽普县,4,653100 +653125,莎车县,4,653100 +653126,叶城县,4,653100 +653127,麦盖提县,4,653100 +653128,岳普湖县,4,653100 +653129,伽师县,4,653100 +653130,巴楚县,4,653100 +653131,塔什库尔干塔吉克自治县,4,653100 +653201,和田市,4,653200 +653221,和田县,4,653200 +653222,墨玉县,4,653200 +653223,皮山县,4,653200 +653224,洛浦县,4,653200 +653225,策勒县,4,653200 +653226,于田县,4,653200 +653227,民丰县,4,653200 +654002,伊宁市,4,654000 +654003,奎屯市,4,654000 +654004,霍尔果斯市,4,654000 +654021,伊宁县,4,654000 +654022,察布查尔锡伯自治县,4,654000 +654023,霍城县,4,654000 +654024,巩留县,4,654000 +654025,新源县,4,654000 +654026,昭苏县,4,654000 +654027,特克斯县,4,654000 +654028,尼勒克县,4,654000 +654201,塔城市,4,654200 +654202,乌苏市,4,654200 +654203,沙湾市,4,654200 +654221,额敏县,4,654200 +654224,托里县,4,654200 +654225,裕民县,4,654200 +654226,和布克赛尔蒙古自治县,4,654200 +654301,阿勒泰市,4,654300 +654321,布尔津县,4,654300 +654322,富蕴县,4,654300 +654323,福海县,4,654300 +654324,哈巴河县,4,654300 +654325,青河县,4,654300 +654326,吉木乃县,4,654300 +659001,石河子市,4,659000 +659002,阿拉尔市,4,659000 +659003,图木舒克市,4,659000 +659004,五家渠市,4,659000 +659005,北屯市,4,659000 +659006,铁门关市,4,659000 +659007,双河市,4,659000 +659008,可克达拉市,4,659000 +659009,昆玉市,4,659000 +659010,胡杨河市,4,659000 +659011,新星市,4,659000 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/ip2region.xdb b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/ip2region.xdb new file mode 100644 index 000000000..58596a591 Binary files /dev/null and b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/ip2region.xdb differ diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java new file mode 100644 index 000000000..8f5646b33 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.framework.ip.core.utils; + + +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link AreaUtils} 的单元测试 + * + * @author 芋道源码 + */ +public class AreaUtilsTest { + + @Test + public void testGetArea() { + // 调用:北京 + Area area = AreaUtils.getArea(110100); + // 断言 + assertEquals(area.getId(), 110100); + assertEquals(area.getName(), "北京市"); + assertEquals(area.getType(), AreaTypeEnum.CITY.getType()); + assertEquals(area.getParent().getId(), 110000); + assertEquals(area.getChildren().size(), 16); + } + + @Test + public void testFormat() { + assertEquals(AreaUtils.format(110105), "北京 北京市 朝阳区"); + assertEquals(AreaUtils.format(1), "中国"); + assertEquals(AreaUtils.format(2), "蒙古"); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java new file mode 100644 index 000000000..761a1aa63 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.framework.ip.core.utils; + +import cn.iocoder.yudao.framework.ip.core.Area; +import org.junit.jupiter.api.Test; +import org.lionsoul.ip2region.xdb.Searcher; + + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link IPUtils} 的单元测试 + * + * @author wanglhup + */ +public class IPUtilsTest { + + @Test + public void testGetAreaId_string() { + // 120.202.4.0|120.202.4.255|420600 + Integer areaId = IPUtils.getAreaId("120.202.4.50"); + assertEquals(420600, areaId); + } + + @Test + public void testGetAreaId_long() throws Exception { + // 120.203.123.0|120.203.133.255|360900 + long ip = Searcher.checkIP("120.203.123.250"); + Integer areaId = IPUtils.getAreaId(ip); + assertEquals(360900, areaId); + } + + @Test + public void testGetArea_string() { + // 120.202.4.0|120.202.4.255|420600 + Area area = IPUtils.getArea("120.202.4.50"); + assertEquals("襄阳市", area.getName()); + } + + @Test + public void testGetArea_long() throws Exception { + // 120.203.123.0|120.203.133.255|360900 + long ip = Searcher.checkIP("120.203.123.252"); + Area area = IPUtils.getArea(ip); + assertEquals("宜春市", area.getName()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java index 27c45c068..441ec6bbd 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl; import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoOperateLogAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 529a47663..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..04ccab1cd --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml index 1c3a3bde1..03f0013aa 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml @@ -52,7 +52,7 @@ com.alipay.sdk alipay-sdk-java - 4.33.44.ALL + 4.35.0.ALL org.bouncycastle diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java index 057a75541..1ea788674 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java @@ -13,26 +13,23 @@ import javax.validation.constraints.NotEmpty; public class PayProperties { /** - * 支付回调地址 + * 回调地址 + * + * 实际上,对应的 PayNotifyController 的 notifyCallback 方法的 URL + * * 注意,支付渠道统一回调到 payNotifyUrl 地址,由支付模块统一处理;然后,自己的支付模块,在回调 PayAppDO.payNotifyUrl 地址 */ - @NotEmpty(message = "支付回调地址不能为空") - @URL(message = "支付回调地址的格式必须是 URL") - private String payNotifyUrl; - /** - * 退款回调地址 - * 注意点,同 {@link #payNotifyUrl} 属性 - */ - @NotEmpty(message = "退款回调地址不能为空") - @URL(message = "退款回调地址的格式必须是 URL") - private String refundNotifyUrl; - + @NotEmpty(message = "回调地址不能为空") + @URL(message = "回调地址的格式必须是 URL") + private String callbackUrl; /** - * 支付完成的返回地址 + * 回跳地址 + * + * 实际上,对应的 PayNotifyController 的 returnCallback 方法的 URL */ - @URL(message = "支付返回的地址的格式必须是 URL") - @NotEmpty(message = "支付返回的地址不能为空") - private String payReturnUrl; + @URL(message = "回跳地址的格式必须是 URL") + @NotEmpty(message = "回跳地址不能为空") + private String returnUrl; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java index b198d3876..704dab307 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java @@ -2,16 +2,16 @@ package cn.iocoder.yudao.framework.pay.config; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * 支付配置类 * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableConfigurationProperties(PayProperties.class) public class YudaoPayAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java index bbd237e9c..96425817a 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayNotifyDataDTO.java @@ -21,9 +21,9 @@ public class PayNotifyDataDTO { */ private String body; - /** * HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数 */ private Map params; + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java index ea3628931..5314453be 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java @@ -62,7 +62,7 @@ public class PayOrderUnifiedReqDTO { */ @NotNull(message = "支付金额不能为空") @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") - private Long amount; + private Integer amount; /** * 支付过期时间 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java index 79e11eaff..50c933aaa 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayRefundUnifiedReqDTO.java @@ -63,7 +63,7 @@ public class PayRefundUnifiedReqDTO { */ @NotNull(message = "退款金额不能为空") @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") - private Long amount; + private Integer amount; /** * 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java index 3253709c8..2ff978dba 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -69,7 +69,7 @@ public abstract class AbstractPayClient implemen this.init(); } - protected Double calculateAmount(Long amount) { + protected Double calculateAmount(Integer amount) { return amount / 100.0; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java index 5d079430b..bb485f41e 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXLitePayClient.java @@ -26,6 +26,8 @@ import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import lombok.extern.slf4j.Slf4j; +import java.time.ZoneId; +import java.util.Date; import java.util.Objects; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; @@ -119,7 +121,7 @@ public class WXLitePayClient extends AbstractPayClient { .setTotal(reqDTO .getAmount() .intValue())); // 单位分 - request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式 + request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式 request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO))); request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); request.setNotifyUrl(reqDTO.getNotifyUrl()); @@ -167,7 +169,8 @@ public class WXLitePayClient extends AbstractPayClient { return PayOrderNotifyRespDTO .builder() .orderExtensionNo(result.getOutTradeNo()) - .channelOrderNo(result.getTradeState()) + .channelOrderNo(result.getTransactionId()) + .channelUserId(result.getPayer().getOpenid()) .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) .data(data.getBody()) .build(); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java index f9ccd4629..b228213eb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXNativePayClient.java @@ -24,6 +24,8 @@ import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import lombok.extern.slf4j.Slf4j; +import java.time.ZoneId; +import java.util.Date; import java.util.Objects; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; @@ -98,7 +100,7 @@ public class WXNativePayClient extends AbstractPayClient { .outTradeNo(reqDTO.getMerchantOrderId()) .body(reqDTO.getBody()) .totalFee(reqDTO.getAmount().intValue()) // 单位分 - .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) + .timeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")) .spbillCreateIp(reqDTO.getUserIp()) .notifyUrl(reqDTO.getNotifyUrl()) .productId(tradeType) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java index 84e3064c3..88e7ac75f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java @@ -26,6 +26,8 @@ import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import lombok.extern.slf4j.Slf4j; +import java.time.ZoneId; +import java.util.Date; import java.util.Objects; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; @@ -99,7 +101,7 @@ public class WXPubPayClient extends AbstractPayClient { .outTradeNo(reqDTO.getMerchantOrderId()) .body(reqDTO.getBody()) .totalFee(reqDTO.getAmount().intValue()) // 单位分 - .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) + .timeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")) .spbillCreateIp(reqDTO.getUserIp()) .openid(getOpenid(reqDTO)) .notifyUrl(reqDTO.getNotifyUrl()) @@ -114,7 +116,7 @@ public class WXPubPayClient extends AbstractPayClient { request.setOutTradeNo(reqDTO.getMerchantOrderId()); request.setDescription(reqDTO.getBody()); request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分 - request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")); + request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO))); request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); request.setNotifyUrl(reqDTO.getNotifyUrl()); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring.factories deleted file mode 100644 index c135d7d79..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.pay.config.YudaoPayAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..f2a8bf146 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.pay.config.YudaoPayAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test-integration/java/cn/iocoder/yudao/framework/core/client/impl/PayClientFactoryImplTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java similarity index 96% rename from yudao-framework/yudao-spring-boot-starter-biz-pay/src/test-integration/java/cn/iocoder/yudao/framework/core/client/impl/PayClientFactoryImplTest.java rename to yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java index 582840e4e..975483954 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test-integration/java/cn/iocoder/yudao/framework/core/client/impl/PayClientFactoryImplTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.core.client.impl; +package cn.iocoder.yudao.framework.pay.core.client.impl; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.RandomUtil; @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; -import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient; @@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; import com.alipay.api.response.AlipayTradePrecreateResponse; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import java.io.FileInputStream; @@ -24,7 +24,8 @@ import java.io.FileNotFoundException; * * @author 芋道源码 */ -public class PayClientFactoryImplTest { +@Disabled +public class PayClientFactoryImplIntegrationTest { private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl(); @@ -91,7 +92,7 @@ public class PayClientFactoryImplTest { PayClient client = payClientFactory.getPayClient(channelId); // 发起支付 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); - reqDTO.setNotifyUrl("http://niubi.natapp1.cc/api/pay/order/notify/alipay-qr/1"); // TODO @tina: 这里改成你的 natapp 回调地址 + reqDTO.setNotifyUrl("http://yunai.natapp1.cc/admin-api/pay/notify/callback/18"); // TODO @tina: 这里改成你的 natapp 回调地址 CommonResult result = (CommonResult) client.unifiedOrder(reqDTO); System.out.println(JsonUtils.toJsonString(result)); System.out.println(result.getData().getQrCode()); @@ -121,7 +122,7 @@ public class PayClientFactoryImplTest { private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() { PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO(); - reqDTO.setAmount(123L); + reqDTO.setAmount(123); reqDTO.setSubject("IPhone 13"); reqDTO.setBody("biubiubiu"); reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java index 9ded6f026..f3950792d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java @@ -73,7 +73,7 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest { Long shopOrderId = System.currentTimeMillis(); PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO(); reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); - reqDTO.setAmount(1L); + reqDTO.setAmount(1); reqDTO.setBody("内容:" + shopOrderId); reqDTO.setSubject("标题:"+shopOrderId); String notify="http://niubi.natapp1.cc/api/pay/order/notify"; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml index 3eb3e5442..faa6a8d34 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml @@ -12,7 +12,7 @@ jar ${project.artifactId} - 短信拓展,支持阿里云、云片、腾讯云 + 短信拓展,支持阿里云、腾讯云 https://github.com/YunaiV/ruoyi-vue-pro @@ -64,11 +64,6 @@ - - com.yunpian.sdk - yunpian-java-sdk - - com.aliyun aliyun-java-sdk-core @@ -79,7 +74,7 @@ com.tencentcloudapi - tencentcloud-sdk-java + tencentcloud-sdk-java-sms diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java index e2a3e3732..9873c80d5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java @@ -2,15 +2,15 @@ package cn.iocoder.yudao.framework.sms.config; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.client.impl.SmsClientFactoryImpl; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * 短信配置类 * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoSmsAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java index eaaa4b27a..abb7dda1b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.client.impl.aliyun.AliyunSmsClient; import cn.iocoder.yudao.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; import cn.iocoder.yudao.framework.sms.core.client.impl.tencent.TencentSmsClient; -import cn.iocoder.yudao.framework.sms.core.client.impl.yunpian.YunpianSmsClient; import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; @@ -80,7 +79,6 @@ public class SmsClientFactoryImpl implements SmsClientFactory { // 创建客户端 switch (channelEnum) { case ALIYUN: return new AliyunSmsClient(properties); - case YUN_PIAN: return new YunpianSmsClient(properties); case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties); case TENCENT: return new TencentSmsClient(properties); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java deleted file mode 100644 index cad5cad2c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java +++ /dev/null @@ -1,210 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.NumberUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.URLUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.annotations.VisibleForTesting; -import com.yunpian.sdk.YunpianClient; -import com.yunpian.sdk.constant.YunpianConstant; -import com.yunpian.sdk.model.Result; -import com.yunpian.sdk.model.Template; -import lombok.Data; -import lombok.extern.slf4j.Slf4j; - -import java.time.LocalDateTime; -import java.util.*; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; - -/** - * 云片短信客户端的实现类 - * - * @author zzf - * @since 9:48 2021/3/5 - */ -@Slf4j -public class YunpianSmsClient extends AbstractSmsClient { - - /** - * 云信短信客户端 - */ - private volatile YunpianClient client; - - public YunpianSmsClient(SmsChannelProperties properties) { - super(properties, new YunpianSmsCodeMapping()); - Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); - } - - @Override - public void doInit() { - YunpianClient oldClient = client; - // 初始化新的客户端 - YunpianClient newClient = new YunpianClient(properties.getApiKey()); - newClient.init(); - this.client = newClient; - // 销毁老的客户端 - if (oldClient != null) { - oldClient.close(); - } - } - - @Override - protected SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) throws Throwable { - return invoke(() -> { - Map request = new HashMap<>(); - request.put(YunpianConstant.MOBILE, mobile); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - request.put(YunpianConstant.TPL_VALUE, formatTplValue(templateParams)); - request.put(YunpianConstant.UID, String.valueOf(sendLogId)); - request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl()); - return client.sms().tpl_single_send(request); - }, response -> new SmsSendRespDTO().setSerialNo(String.valueOf(response.getSid()))); - } - - private static String formatTplValue(List> templateParams) { - if (CollUtil.isEmpty(templateParams)) { - return ""; - } - // 参考 https://www.yunpian.com/official/document/sms/zh_cn/introduction_demos_encode_sample 格式化 - StringJoiner joiner = new StringJoiner("&"); - templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), - URLUtil.encode(String.valueOf(param.getValue()))))); - return joiner.toString(); - } - - @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { - List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); - return statuses.stream().map(status -> { - SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); - resp.setSuccess(Objects.equals(status.getReportStatus(), "SUCCESS")); - resp.setErrorCode(status.getErrorMsg()).setErrorMsg(status.getErrorDetail()); - resp.setMobile(status.getMobile()).setReceiveTime(status.getUserReceiveTime()); - resp.setSerialNo(String.valueOf(status.getSid())).setLogId(status.getUid()); - return resp; - }).collect(Collectors.toList()); - } - - @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable { - return invoke(() -> { - if (!NumberUtil.isNumber(apiTemplateId)) { - throw new IllegalArgumentException("云片的 API 模板编号必须为整数"); - } - Map request = new HashMap<>(); - request.put(YunpianConstant.APIKEY, properties.getApiKey()); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - return client.tpl().get(request); - }, response -> { - Template template = response.get(0); - return new SmsTemplateRespDTO().setId(String.valueOf(template.getTpl_id())).setContent(template.getTpl_content()) - .setAuditStatus(convertSmsTemplateAuditStatus(template.getCheck_status())).setAuditReason(template.getReason()); - }); - } - - @VisibleForTesting - Integer convertSmsTemplateAuditStatus(String checkStatus) { - switch (checkStatus) { - case "CHECKING": return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); - case "SUCCESS": return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); - case "FAIL": return SmsTemplateAuditStatusEnum.FAIL.getStatus(); - default: throw new IllegalArgumentException(String.format("未知审核状态(%s)", checkStatus)); - } - } - - @VisibleForTesting - SmsCommonResult invoke(Supplier> requestConsumer, Function responseConsumer) throws Throwable { - // 执行请求 - Result result = requestConsumer.get(); - if (result.getThrowable() != null) { - throw result.getThrowable(); - } - // 解析结果 - R data = null; - if (result.getData() != null) { - data = responseConsumer.apply(result.getData()); - } - // 拼接结果 - return SmsCommonResult.build(String.valueOf(result.getCode()), formatResultMsg(result), null, data, codeMapping); - } - - private static String formatResultMsg(Result sendResult) { - if (StrUtil.isEmpty(sendResult.getDetail())) { - return sendResult.getMsg(); - } - return sendResult.getMsg() + " => " + sendResult.getDetail(); - } - - /** - * 短信接收状态 - * - * 参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档 - * - * @author 芋道源码 - */ - @Data - public static class SmsReceiveStatus { - - /** - * 接收状态 - * - * 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收 - */ - @JsonProperty("report_status") - private String reportStatus; - /** - * 接收手机号 - */ - private String mobile; - /** - * 运营商返回的代码,如:"DB:0103" - * - * 由于不同运营商信息不同,此字段仅供参考; - */ - @JsonProperty("error_msg") - private String errorMsg; - /** - * 运营商反馈代码的中文解释 - * - * 默认不推送此字段,如需推送,请联系客服 - */ - @JsonProperty("error_detail") - private String errorDetail; - /** - * 短信编号 - */ - private Long sid; - /** - * 用户自定义 id - * - * 这里我们传递的是 SysSmsLogDO 的日志编号 - */ - private Long uid; - /** - * 用户接收时间 - */ - @JsonProperty("user_receive_time") - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private LocalDateTime userReceiveTime; - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java deleted file mode 100644 index f467ceb4f..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMapping.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; -import static com.yunpian.sdk.constant.Code.*; - -/** - * 云片的 SmsCodeMapping 实现类 - *

- * 参见 https://www.yunpian.com/official/document/sms/zh_CN/returnvalue_common 文档 - * - * @author 芋道源码 - */ -public class YunpianSmsCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - int code = Integer.parseInt(apiCode); - switch (code) { - case OK: - return SUCCESS; - case ARGUMENT_MISSING: - return SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR; - case BAD_ARGUMENT_FORMAT: - return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR; - case TPL_NOT_FOUND: - case TPL_NOT_VALID: - return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID; - case MONEY_NOT_ENOUGH: - return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH; - case BLACK_WORD: - return SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID; - case DUP_IN_SHORT_TIME: - case TOO_MANY_TIME_IN_5: - case DAY_LIMIT_PER_MOBILE: - case HOUR_LIMIT_PER_MOBILE: - return SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL; - case BLACK_PHONE_FILTER: - return SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK; - case SIGN_NOT_MATCH: - case BAD_SIGN_FORMAT: - case SIGN_NOT_VALID: - return SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID; - case BAD_API_KEY: - return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID; - case API_NOT_ALLOWED: - return SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY; - case IP_NOT_ALLOWED: - return SmsFrameworkErrorCodeConstants.SMS_IP_DENY; - default: - break; - } - return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java index b1b386b98..66410bd2c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java @@ -15,7 +15,6 @@ import lombok.Getter; public enum SmsChannelEnum { DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"), - YUN_PIAN("YUN_PIAN", "云片"), ALIYUN("ALIYUN", "阿里云"), TENCENT("TENCENT", "腾讯云"), // HUA_WEI("HUA_WEI", "华为云"), diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java index 7af1dd21c..852f4e29b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java @@ -16,7 +16,6 @@ public interface SmsFrameworkErrorCodeConstants { // ========== 权限 / 限流等相关 2001000100 ========== ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); - // 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信 ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring.factories deleted file mode 100644 index bb26b5327..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..7c9b740ca --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java deleted file mode 100644 index a23094a88..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientIntegrationTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian; - -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.yunpian.YunpianSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link YunpianSmsClient} 的集成测试 - */ -public class YunpianSmsClientIntegrationTest { - - private static YunpianSmsClient smsClient; - - @BeforeAll - public static void init() { - // 创建配置类 - SmsChannelProperties properties = new SmsChannelProperties(); - properties.setId(1L); - properties.setSignature("芋道"); - properties.setCode(SmsChannelEnum.YUN_PIAN.getCode()); - properties.setApiKey("1555a14277cb8a608cf45a9e6a80d510"); - // 创建客户端 - smsClient = new YunpianSmsClient(properties); - smsClient.init(); - } - - @Test - public void testSendSms() { - List> templateParams = new ArrayList<>(); - templateParams.add(new KeyValue<>("code", "1024")); - templateParams.add(new KeyValue<>("operation", "嘿嘿")); -// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); - SmsCommonResult result = smsClient.sendSms(1L, "15601691399", "4383920", templateParams); - System.out.println(result); - } - - @Test - public void testGetSmsTemplate() { - String apiTemplateId = "4383920"; - SmsCommonResult result = smsClient.getSmsTemplate(apiTemplateId); - System.out.println(result); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java deleted file mode 100644 index 3fc05ce77..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClientTest.java +++ /dev/null @@ -1,202 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian; - -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import com.google.common.collect.Lists; -import com.yunpian.sdk.YunpianClient; -import com.yunpian.sdk.api.SmsApi; -import com.yunpian.sdk.api.TplApi; -import com.yunpian.sdk.constant.YunpianConstant; -import com.yunpian.sdk.model.Result; -import com.yunpian.sdk.model.SmsSingleSend; -import com.yunpian.sdk.model.Template; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Supplier; - -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static com.yunpian.sdk.constant.Code.OK; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * 对 {@link YunpianSmsClient} 的单元测试 - * - * @author 芋道源码 - */ -public class YunpianSmsClientTest extends BaseMockitoUnitTest { - - private final SmsChannelProperties properties = new SmsChannelProperties() - .setApiKey(randomString()); // 随机一个 apiKey,避免构建报错 - - @InjectMocks - private final YunpianSmsClient smsClient = new YunpianSmsClient(properties); - - @Mock - private YunpianClient client; - - @Test - public void testDoInit() { - // 准备参数 - // mock 方法 - - // 调用 - smsClient.doInit(); - // 断言 - assertNotEquals(client, ReflectUtil.getFieldValue(smsClient, "client")); - verify(client, times(1)).close(); - } - - @Test - @SuppressWarnings("unchecked") - public void testDoSendSms() throws Throwable { - // 准备参数 - Long sendLogId = randomLongId(); - String mobile = randomString(); - String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); - // mock sms 方法 - SmsApi smsApi = mock(SmsApi.class); - when(client.sms()).thenReturn(smsApi); - // mock tpl_single_send 方法 - Map request = new HashMap<>(); - request.put(YunpianConstant.MOBILE, mobile); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - request.put(YunpianConstant.TPL_VALUE, "#code#=1234&#op#=login"); - request.put(YunpianConstant.UID, String.valueOf(sendLogId)); - request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl()); - Result responseResult = randomPojo(Result.class, SmsSingleSend.class, - o -> o.setCode(OK)); // API 发送成功的 code - when(smsApi.tpl_single_send(eq(request))).thenReturn(responseResult); - - // 调用 - SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, - apiTemplateId, templateParams); - // 断言 - assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); - assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertNull(result.getApiRequestId()); - // 断言结果 - assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo()); - } - - @Test - public void testDoParseSmsReceiveStatus() throws Throwable { - // 准备参数 - String text = "[{\"sid\":9527,\"uid\":1024,\"user_receive_time\":\"2014-03-17 22:55:21\",\"error_msg\":\"\",\"mobile\":\"15205201314\",\"report_status\":\"SUCCESS\"}]"; - // mock 方法 - - // 调用 - - // 断言 - // 调用 - List statuses = smsClient.doParseSmsReceiveStatus(text); - // 断言 - assertEquals(1, statuses.size()); - assertTrue(statuses.get(0).getSuccess()); - assertEquals("", statuses.get(0).getErrorCode()); - assertNull(statuses.get(0).getErrorMsg()); - assertEquals("15205201314", statuses.get(0).getMobile()); - assertEquals(LocalDateTime.of(2014, 3, 17, 22, 55, 21), statuses.get(0).getReceiveTime()); - assertEquals("9527", statuses.get(0).getSerialNo()); - assertEquals(1024L, statuses.get(0).getLogId()); - } - - @Test - @SuppressWarnings("unchecked") - public void testDoGetSmsTemplate() throws Throwable { - // 准备参数 - String apiTemplateId = String.valueOf(randomLongId()); - // mock tpl 方法 - TplApi tplApi = mock(TplApi.class); - when(client.tpl()).thenReturn(tplApi); - // mock get 方法 - Map request = new HashMap<>(); - request.put(YunpianConstant.APIKEY, properties.getApiKey()); - request.put(YunpianConstant.TPL_ID, apiTemplateId); - Result> responseResult = randomPojo(Result.class, List.class, o -> { - o.setCode(OK); // API 发送成功的 code - o.setData(randomPojoList(Template.class, t -> t.setCheck_status("SUCCESS"))); - }); - when(tplApi.get(eq(request))).thenReturn(responseResult); - - // 调用 - SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId); - // 断言 - assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); - assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertNull(result.getApiRequestId()); - // 断言结果 - Template template = responseResult.getData().get(0); - assertEquals(template.getTpl_id().toString(), result.getData().getId()); - assertEquals(template.getTpl_content(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(template.getReason(), result.getData().getAuditReason()); - } - - @Test - public void testConvertSmsTemplateAuditStatus() { - assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), - smsClient.convertSmsTemplateAuditStatus("CHECKING")); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), - smsClient.convertSmsTemplateAuditStatus("SUCCESS")); - assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), - smsClient.convertSmsTemplateAuditStatus("FAIL")); - assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus("test"), - "未知审核状态(test)"); - } - - @Test - public void testInvoke_throwable() { - // 准备参数 - Supplier> requestConsumer = - () -> new Result<>().setThrowable(new NullPointerException()); - // mock 方法 - - // 调用,并断言异常 - assertThrows(NullPointerException.class, - () -> smsClient.invoke(requestConsumer, null)); - } - - @Test - @SuppressWarnings("unchecked") - public void testInvoke_success() throws Throwable { - // 准备参数 - Result responseResult = randomPojo(Result.class, SmsSingleSend.class, o -> o.setCode(OK)); - Supplier> requestConsumer = () -> responseResult; - Function responseConsumer = - smsSingleSend -> new SmsSendRespDTO().setSerialNo(String.valueOf(responseResult.getData().getSid())); - // mock 方法 - - // 调用 - SmsCommonResult result = smsClient.invoke(requestConsumer, responseConsumer); - // 断言 - assertEquals(String.valueOf(responseResult.getCode()), result.getApiCode()); - assertEquals(responseResult.getMsg() + " => " + responseResult.getDetail(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertNull(result.getApiRequestId()); - assertEquals(String.valueOf(responseResult.getData().getSid()), result.getData().getSerialNo()); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java deleted file mode 100644 index 8a292e325..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsCodeMappingTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.yunpian; - -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; - -import static com.yunpian.sdk.constant.Code.*; -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link YunpianSmsCodeMapping} 的单元测试 - * - * @author 芋道源码 - */ -class YunpianSmsCodeMappingTest extends BaseMockitoUnitTest { - - @InjectMocks - private YunpianSmsCodeMapping codeMapping; - - @Test - public void testApply() { - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(String.valueOf(OK))); - Assertions.assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply(String.valueOf(ARGUMENT_MISSING))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply(String.valueOf(BAD_ARGUMENT_FORMAT))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply(String.valueOf(MONEY_NOT_ENOUGH))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_FOUND))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply(String.valueOf(TPL_NOT_VALID))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DUP_IN_SHORT_TIME))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(TOO_MANY_TIME_IN_5))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(DAY_LIMIT_PER_MOBILE))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply(String.valueOf(HOUR_LIMIT_PER_MOBILE))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply(String.valueOf(BLACK_PHONE_FILTER))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_MATCH))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(SIGN_NOT_VALID))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply(String.valueOf(BAD_SIGN_FORMAT))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply(String.valueOf(BAD_API_KEY))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply(String.valueOf(API_NOT_ALLOWED))); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply(String.valueOf(IP_NOT_ALLOWED))); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java index 976f677ce..5c2f7f8bb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java @@ -6,10 +6,10 @@ import com.xkcoding.http.support.hutool.HutoolImpl; import com.xkcoding.justauth.autoconfigure.JustAuthProperties; import lombok.extern.slf4j.Slf4j; import me.zhyd.oauth.cache.AuthStateCache; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; /** @@ -19,7 +19,7 @@ import org.springframework.context.annotation.Primary; * @date 2021-10-30 */ @Slf4j -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableConfigurationProperties(JustAuthProperties.class) public class YudaoSocialAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java index b2cd28ec6..22be344d9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java @@ -43,6 +43,7 @@ public class YudaoAuthRequestFactory extends AuthRequestFactory { * @param source {@link AuthSource} * @return {@link AuthRequest} */ + @Override public AuthRequest get(String source) { // 先尝试获取自定义扩展的 AuthRequest authRequest = getExtendRequest(source); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories deleted file mode 100644 index dcd4dcf71..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.social.config.YudaoSocialAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..5d9b35599 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.social.config.YudaoSocialAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java index e351d82e1..bc53c244e 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java @@ -21,11 +21,11 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; @@ -35,7 +35,7 @@ import org.springframework.data.redis.core.RedisTemplate; import java.util.Objects; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户 @EnableConfigurationProperties(TenantProperties.class) public class YudaoTenantAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java index 89dfeff4b..b7d0fa362 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/aop/TenantIgnoreAspect.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.tenant.core.aop; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -11,6 +12,8 @@ import org.aspectj.lang.annotation.Aspect; * 例如说,一个定时任务,读取所有数据,进行处理。 * 又例如说,读取所有数据,进行缓存。 * + * 整体逻辑的实现,和 {@link TenantUtils#executeIgnore(Runnable)} 需要保持一致 + * * @author 芋道源码 */ @Aspect diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java index 3ea29b227..e45822b7e 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java @@ -2,6 +2,10 @@ package cn.iocoder.yudao.framework.tenant.core.util; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import java.util.Map; + +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; + /** * 多租户 Util * @@ -32,4 +36,32 @@ public class TenantUtils { } } + /** + * 忽略租户,执行对应的逻辑 + * + * @param runnable 逻辑 + */ + public static void executeIgnore(Runnable runnable) { + Boolean oldIgnore = TenantContextHolder.isIgnore(); + try { + TenantContextHolder.setIgnore(true); + // 执行逻辑 + runnable.run(); + } finally { + TenantContextHolder.setIgnore(oldIgnore); + } + } + + /** + * 将多租户编号,添加到 header 中 + * + * @param headers HTTP 请求 headers + */ + public static void addTenantHeader(Map headers) { + Long tenantId = TenantContextHolder.getTenantId(); + if (tenantId != null) { + headers.put(HEADER_TENANT_ID, tenantId.toString()); + } + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 95ab510a4..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.tenant.config.YudaoTenantAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..603831e3f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.tenant.config.YudaoTenantAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java index 314368d32..f446819e7 100644 --- a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java @@ -4,11 +4,11 @@ import cn.hutool.core.util.ClassUtil; import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants; import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl; import com.anji.captcha.service.CaptchaCacheService; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.StringRedisTemplate; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoCaptchaConfiguration { static { diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories deleted file mode 100644 index ed8b528ff..000000000 --- a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..8411d2cc3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java index c7aa832bf..e22ee3dd0 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java @@ -2,15 +2,15 @@ package cn.iocoder.yudao.framework.file.config; import cn.iocoder.yudao.framework.file.core.client.FileClientFactory; import cn.iocoder.yudao.framework.file.core.client.FileClientFactoryImpl; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * 文件配置类 * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoFileAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java index 178c27d4c..fb576d508 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java @@ -22,7 +22,7 @@ public interface FileClient { * @return 完整路径,即 HTTP 访问地址 * @throws Exception 上传文件时,抛出 Exception 异常 */ - String upload(byte[] content, String path) throws Exception; + String upload(byte[] content, String path, String type) throws Exception; /** * 删除文件 diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java index a227cc314..1e2c082fe 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java @@ -21,7 +21,7 @@ public class DBFileClient extends AbstractFileClient { } @Override - public String upload(byte[] content, String path) { + public String upload(byte[] content, String path, String type) { getDao().insert(getId(), path, content); // 拼接返回路径 return super.formatFileUrl(config.getDomain(), path); diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java index e9c837dfd..796044f3f 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java @@ -38,7 +38,7 @@ public class FtpFileClient extends AbstractFileClient { } @Override - public String upload(byte[] content, String path) { + public String upload(byte[] content, String path, String type) { // 执行写入 String filePath = getFilePath(path); String fileName = FileUtil.getName(filePath); diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java index 1c79f8999..cac13f1fb 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java @@ -25,7 +25,7 @@ public class LocalFileClient extends AbstractFileClient { } @Override - public String upload(byte[] content, String path) { + public String upload(byte[] content, String path, String type) { // 执行写入 String filePath = getFilePath(path); FileUtil.writeBytes(content, filePath); diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java index ab95d4bda..a2b11b1dc 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -82,10 +82,11 @@ public class S3FileClient extends AbstractFileClient { } @Override - public String upload(byte[] content, String path) throws Exception { + public String upload(byte[] content, String path, String type) throws Exception { // 执行上传 client.putObject(PutObjectArgs.builder() .bucket(config.getBucket()) // bucket 必须传递 + .contentType(type) .object(path) // 相对路径作为 key .stream(new ByteArrayInputStream(content), content.length, -1) // 文件内容 .build()); diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java index 3e18e888d..facddcea0 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java @@ -31,7 +31,7 @@ public class SftpFileClient extends AbstractFileClient { } @Override - public String upload(byte[] content, String path) { + public String upload(byte[] content, String path, String type) { // 执行写入 String filePath = getFilePath(path); File file = FileUtils.createTempFile(content); diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 8d2a4be45..000000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.file.config.YudaoFileAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..9e5f42239 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.file.config.YudaoFileAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java index 00a3a268e..619e52db8 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java @@ -25,7 +25,7 @@ public class FtpFileClientTest { // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - String fullPath = client.upload(content, path); + String fullPath = client.upload(content, path, "image/jpeg"); System.out.println("访问地址:" + fullPath); if (false) { byte[] bytes = client.getContent(path); diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java index 2062d63d7..d48609bc6 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java @@ -19,7 +19,7 @@ public class LocalFileClientTest { // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - String fullPath = client.upload(content, path); + String fullPath = client.upload(content, path, "image/jpeg"); System.out.println("访问地址:" + fullPath); client.delete(path); } diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java index de77477cd..1d0ed2091 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java @@ -101,7 +101,7 @@ public class S3FileClientTest { // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - String fullPath = client.upload(content, path); + String fullPath = client.upload(content, path, "image/jpeg"); System.out.println("访问地址:" + fullPath); // 读取文件 if (true) { diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java index 412df1ea8..4785c0d89 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java @@ -23,7 +23,7 @@ public class SftpFileClientTest { // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - String fullPath = client.upload(content, path); + String fullPath = client.upload(content, path, "image/jpeg"); System.out.println("访问地址:" + fullPath); if (false) { byte[] bytes = client.getContent(path); diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java index ef6720d16..7c29a6462 100644 --- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java @@ -2,13 +2,13 @@ package cn.iocoder.yudao.framework.flowable.config; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoFlowableConfiguration { /** diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories deleted file mode 100644 index c667d5e55..000000000 --- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..1df61598c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.flowable.config.YudaoFlowableConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java index f1eef178c..6d517e5e4 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java @@ -3,15 +3,15 @@ package cn.iocoder.yudao.framework.quartz.config; import com.alibaba.ttl.TtlRunnable; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * 异步任务 Configuration */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableAsync public class YudaoAsyncAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java index 881e59913..f414e989a 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoQuartzAutoConfiguration.java @@ -2,14 +2,14 @@ package cn.iocoder.yudao.framework.quartz.config; import cn.iocoder.yudao.framework.quartz.core.scheduler.SchedulerManager; import org.quartz.Scheduler; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; /** * 定时任务 Configuration */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableScheduling // 开启 Spring 自带的定时任务 public class YudaoQuartzAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories deleted file mode 100644 index cecc4094c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.quartz.config.YudaoQuartzAutoConfiguration,\ - cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..4086f7a4a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.quartz.config.YudaoQuartzAutoConfiguration +cn.iocoder.yudao.framework.quartz.config.YudaoAsyncAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java index 7537f3eae..cc2a0df4e 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoMetricsAutoConfiguration.java @@ -3,17 +3,17 @@ package cn.iocoder.yudao.framework.tracer.config; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * Metrics 配置类 * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @ConditionalOnClass({MeterRegistryCustomizer.class}) @ConditionalOnProperty(prefix = "yudao.metrics", value = "enable", matchIfMissing = true) // 允许使用 yudao.metrics.enable=false 禁用 Metrics public class YudaoMetricsAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java index 74bbf1ed7..c7d9e2c0d 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java @@ -3,19 +3,19 @@ package cn.iocoder.yudao.framework.tracer.config; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect; import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; /** * Tracer 配置类 * * @author mashu */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @ConditionalOnClass({BizTraceAspect.class}) @EnableConfigurationProperties(TracerProperties.class) @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 9b69f01ea..000000000 --- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.tracer.config.YudaoTracerAutoConfiguration,\ - cn.iocoder.yudao.framework.tracer.config.YudaoMetricsAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..218ee31a2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.tracer.config.YudaoTracerAutoConfiguration +cn.iocoder.yudao.framework.tracer.config.YudaoMetricsAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java index 89c2d4e59..c369d49d6 100644 --- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/config/YudaoMQAutoConfiguration.java @@ -10,9 +10,8 @@ import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisServerCommands; import org.springframework.data.redis.connection.stream.Consumer; import org.springframework.data.redis.connection.stream.ObjectRecord; @@ -35,9 +34,8 @@ import java.util.Properties; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) -@AutoConfigureAfter(YudaoRedisAutoConfiguration.class) @Slf4j +@AutoConfiguration(after = YudaoRedisAutoConfiguration.class) public class YudaoMQAutoConfiguration { @Bean @@ -55,7 +53,6 @@ public class YudaoMQAutoConfiguration { * 创建 Redis Pub/Sub 广播消费的容器 */ @Bean - @Async // 异步化,可降低 2 秒左右的启动时间 public RedisMessageListenerContainer redisMessageListenerContainer( RedisMQTemplate redisMQTemplate, List> listeners) { // 创建 RedisMessageListenerContainer 对象 diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java index 8585aafe6..e7d737d1b 100644 --- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java +++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/pubsub/AbstractChannelMessageListener.java @@ -39,7 +39,7 @@ public abstract class AbstractChannelMessageListener - mysql - mysql-connector-java + com.mysql + mysql-connector-j com.oracle.database.jdbc diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java index 3e237f232..71d4ea466 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.framework.datasource.config; import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter; import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; /** @@ -14,7 +14,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理 @EnableConfigurationProperties(DruidStatProperties.class) public class YudaoDataSourceAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/AndExpressionX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/AndExpressionX.java new file mode 100644 index 000000000..54198e496 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/AndExpressionX.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.expression; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; + +/** + * AndExpression 的扩展类(会在原有表达式两端加上括号) + */ +public class AndExpressionX extends AndExpression { + + public AndExpressionX() { + } + + public AndExpressionX(Expression leftExpression, Expression rightExpression) { + this.setLeftExpression(leftExpression); + this.setRightExpression(rightExpression); + } + + @Override + public String toString() { + return "(" + super.toString() + ")"; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/OrExpressionX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/OrExpressionX.java new file mode 100644 index 000000000..19b4695cf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/expression/OrExpressionX.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.expression; + +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; + +/** + * OrExpression 的扩展类(会在原有表达式两端加上括号) + */ +public class OrExpressionX extends OrExpression { + + public OrExpressionX() { + } + + public OrExpressionX(Expression leftExpression, Expression rightExpression) { + this.setLeftExpression(leftExpression); + this.setRightExpression(rightExpression); + } + + @Override + public String toString() { + return "(" + super.toString() + ")"; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java index ce0596498..78ee259c8 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java @@ -13,9 +13,9 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.apache.ibatis.annotations.Mapper; import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; /** @@ -23,7 +23,7 @@ import org.springframework.core.env.ConfigurableEnvironment; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @MapperScan(value = "${yudao.info.base-package}", annotationClass = Mapper.class, lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试 public class YudaoMybatisAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index fb4af6d69..e220d011d 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.mybatis.core.mapper; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -75,9 +76,13 @@ public interface BaseMapperX extends BaseMapper { return selectList(new LambdaQueryWrapper().in(field, values)); } + default List selectList(SFunction leField, SFunction geField, Object value) { + return selectList(new LambdaQueryWrapper().le(leField, value).ge(geField, value)); + } + /** * 逐条插入,适合少量数据插入,或者对性能要求不高的场景 - * + *

* 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法 * 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类 * diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories index 96e3d8bcd..eb172e4ce 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring.factories @@ -1,5 +1,2 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration,\ - cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration org.springframework.boot.env.EnvironmentPostProcessor=\ cn.iocoder.yudao.framework.mybatis.config.IdTypeEnvironmentPostProcessor diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..1c159fd6f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration +cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java index 3760bed19..23a75588f 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/config/YudaoIdempotentConfiguration.java @@ -5,16 +5,14 @@ import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.DefaultIdempo import cn.iocoder.yudao.framework.idempotent.core.keyresolver.impl.ExpressionIdempotentKeyResolver; import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; import cn.iocoder.yudao.framework.idempotent.core.redis.IdempotentRedisDAO; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfiguration; import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.StringRedisTemplate; import java.util.List; -@Configuration(proxyBeanMethods = false) -@AutoConfigureAfter(YudaoRedisAutoConfiguration.class) +@AutoConfiguration(after = YudaoRedisAutoConfiguration.class) public class YudaoIdempotentConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java index 2d2f4fd2f..2986da6c8 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/lock4j/config/YudaoLock4jConfiguration.java @@ -4,12 +4,10 @@ import cn.hutool.core.util.ClassUtil; import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration; import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy; import cn.iocoder.yudao.framework.lock4j.core.Lock4jRedisKeyConstants; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -@Configuration(proxyBeanMethods = false) -@AutoConfigureBefore(LockAutoConfiguration.class) +@AutoConfiguration(before = LockAutoConfiguration.class) public class YudaoLock4jConfiguration { static { diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 0e55a1f2a..000000000 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration,\ - cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..be5c0990d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration +cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java index 3814d487a..0b837569e 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.redis.config; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.cache.CacheProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.serializer.RedisSerializationContext; @@ -13,7 +13,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; /** * Cache 配置类,基于 Redis 实现 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableConfigurationProperties({CacheProperties.class}) @EnableCaching public class YudaoCacheAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java index d814afe16..901830c69 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.redis.config; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; @@ -9,7 +9,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; /** * Redis 配置类 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration public class YudaoRedisAutoConfiguration { /** diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring.factories deleted file mode 100644 index e4cefbab1..000000000 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration,\ - cn.iocoder.yudao.framework.redis.config.YudaoCacheAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..02d4a6835 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration +cn.iocoder.yudao.framework.redis.config.YudaoCacheAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java index e9045c76f..7a766eb83 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java @@ -11,9 +11,9 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @@ -30,7 +30,7 @@ import javax.annotation.Resource; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableConfigurationProperties(SecurityProperties.class) public class YudaoSecurityAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index fd1773c37..c3715c185 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java @@ -4,17 +4,17 @@ import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter import cn.iocoder.yudao.framework.web.config.WebProperties; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.method.HandlerMethod; @@ -32,9 +32,9 @@ import java.util.Set; * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { +public class YudaoWebSecurityConfigurerAdapter { @Resource private WebProperties webProperties; @@ -72,11 +72,9 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 * 通过覆写父类的该方法,添加 @Bean 注解,解决该问题 */ - @Override @Bean - @ConditionalOnMissingBean(AuthenticationManager.class) - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); + public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); } /** @@ -96,8 +94,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap * rememberMe | 允许通过remember-me登录的用户访问 * authenticated | 用户登录后可访问 */ - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { + @Bean + protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { // 登出 httpSecurity // 开启跨域 @@ -141,6 +139,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap // 添加 Token Filter httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + + return httpSecurity.build(); } private String buildAppApi(String url) { diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 564bb0f78..000000000 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.security.config.YudaoSecurityAutoConfiguration,\ - cn.iocoder.yudao.framework.security.config.YudaoWebSecurityConfigurerAdapter diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..f64277f01 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,2 @@ +cn.iocoder.yudao.framework.security.config.YudaoSecurityAutoConfiguration +cn.iocoder.yudao.framework.security.config.YudaoWebSecurityConfigurerAdapter \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java index c18bd248c..e98f4980f 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java @@ -33,6 +33,10 @@ public class AssertUtils { public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) { Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); Arrays.stream(expectedFields).forEach(expectedField -> { + // 忽略 jacoco 自动生成的 $jacocoData 属性的情况 + if (expectedField.isSynthetic()) { + return; + } // 如果是忽略的属性,则不进行比对 if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { return; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java index e4f644173..6ced68756 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -11,16 +11,14 @@ import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import javax.servlet.Filter; -@Configuration(proxyBeanMethods = false) -@AutoConfigureAfter(YudaoWebAutoConfiguration.class) +@AutoConfiguration(after = YudaoWebAutoConfiguration.class) public class YudaoApiLogAutoConfiguration { @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java index c44e770a1..c9dc5a2d9 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.jackson.config; +import cn.iocoder.yudao.framework.jackson.core.databind.NumberSerializer; import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer; import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeSerializer; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -8,12 +9,12 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import java.time.LocalDateTime; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @Slf4j public class YudaoJacksonAutoConfiguration { @@ -32,8 +33,8 @@ public class YudaoJacksonAutoConfiguration { * 2. 新增LocalDateTime序列化、反序列化规则 */ simpleModule -// .addSerializer(Long.class, ToStringSerializer.instance) -// .addSerializer(Long.TYPE, ToStringSerializer.instance) + .addSerializer(Long.class, NumberSerializer.INSTANCE) + .addSerializer(Long.TYPE, NumberSerializer.INSTANCE) .addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE) .addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java new file mode 100644 index 000000000..f9ff37511 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.jackson.core.databind; + +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; + +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND; + +public class LocalTimeJson { + + public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter + .ofPattern(FORMAT_HOUR_MINUTE_SECOND) + .withZone(ZoneId.systemDefault())); + + public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter + .ofPattern(FORMAT_HOUR_MINUTE_SECOND) + .withZone(ZoneId.systemDefault())); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/NumberSerializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/NumberSerializer.java new file mode 100644 index 000000000..f6ddd3f27 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/NumberSerializer.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.jackson.core.databind; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; + +import java.io.IOException; + +/** + * Long 序列化规则 + * + * 会将超长 long 值转换为 string,解决前端 JavaScript 最大安全整数是 2^53-1 的问题 + * + * @author 星语 + */ +@JacksonStdImpl +public class NumberSerializer extends com.fasterxml.jackson.databind.ser.std.NumberSerializer { + + private static final long MAX_SAFE_INTEGER = 9007199254740991L; + private static final long MIN_SAFE_INTEGER = -9007199254740991L; + + public static final NumberSerializer INSTANCE = new NumberSerializer(Number.class); + + public NumberSerializer(Class rawType) { + super(rawType); + } + + @Override + public void serialize(Number value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + // 超出范围 序列化位字符串 + if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { + super.serialize(value, gen, serializers); + } else { + gen.writeString(value.toString()); + } + } +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java index 9e4233baf..240f0f284 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.framework.swagger.config; import cn.iocoder.yudao.framework.swagger.core.SpringFoxHandlerProviderBeanPostProcessor; import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ExampleBuilder; @@ -29,7 +29,7 @@ import static springfox.documentation.builders.RequestHandlerSelectors.basePacka * * @author 芋道源码 */ -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableSwagger2 @EnableKnife4j @ConditionalOnClass({Docket.class, ApiInfoBuilder.class}) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index d5ad84eab..d2bffb166 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -9,11 +9,11 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.bind.annotation.RestController; @@ -26,7 +26,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.annotation.Resource; import javax.servlet.Filter; -@Configuration(proxyBeanMethods = false) +@AutoConfiguration @EnableConfigurationProperties({WebProperties.class, XssProperties.class}) public class YudaoWebAutoConfiguration implements WebMvcConfigurer { diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 3b0e1d772..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,5 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration,\ - cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration,\ - cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration,\ - cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..2a422bfa2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,4 @@ +cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration +cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration +cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration +cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java index a4ba5cc85..015fd0fd9 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java @@ -48,7 +48,7 @@ public interface BpmTaskConvert { return null; } try { - T newInstance = target.newInstance(); + T newInstance = target.getDeclaredConstructor().newInstance(); BeanUtils.copyProperties(source, newInstance); return newInstance; } catch (Exception e) { @@ -77,6 +77,8 @@ public interface BpmTaskConvert { } @Mapping(source = "suspended", target = "suspensionState", qualifiedByName = "convertSuspendedToSuspensionState") + @Mapping(target = "claimTime", expression = "java(bean.getClaimTime()==null?null: LocalDateTime.ofInstant(bean.getClaimTime().toInstant(),ZoneId.systemDefault()))") + @Mapping(target = "createTime", expression = "java(bean.getCreateTime()==null?null:LocalDateTime.ofInstant(bean.getCreateTime().toInstant(),ZoneId.systemDefault()))") BpmTaskTodoPageItemRespVO convert1(Task bean); @Named("convertSuspendedToSuspensionState") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index bb027d80e..abf4f4579 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1 +1 @@ -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. * * HistoricProcessInstance & ProcessInstance 的关系: * 1. * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String)event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java index de62eb28a..36541f1ab 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/definition/BpmUserGroupServiceTest.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.service.definition; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.framework.test.core.util.AssertUtils; import cn.iocoder.yudao.framework.test.core.util.RandomUtils; @@ -19,7 +18,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.USER_GROUP_NOT_EXISTS; @@ -106,7 +105,7 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { BpmUserGroupDO dbUserGroup = RandomUtils.randomPojo(BpmUserGroupDO.class, o -> { // 等会查询到 o.setName("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(DateUtils.buildLocalDateTime(2021, 11, 11)); + o.setCreateTime(buildTime(2021, 11, 11)); }); userGroupMapper.insert(dbUserGroup); // 测试 name 不匹配 @@ -114,12 +113,12 @@ public class BpmUserGroupServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2021, 12, 12)))); + userGroupMapper.insert(cloneIgnoreId(dbUserGroup, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 BpmUserGroupPageReqVO reqVO = new BpmUserGroupPageReqVO(); reqVO.setName("源码"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10),buildLocalDateTime(2021, 11, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)})); // 调用 PageResult pageResult = userGroupService.getUserGroupPage(reqVO); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java index 90f5816f3..8293ffef0 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java @@ -18,6 +18,8 @@ import org.springframework.stereotype.Component; import java.util.*; import static cn.hutool.core.text.CharSequenceUtil.*; +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.hutool.core.util.RandomUtil.randomInt; /** * 代码生成器的 Builder,负责: @@ -128,6 +130,7 @@ public class CodegenBuilder { // 初始化 Column 列的默认字段 processColumnOperation(column); // 处理 CRUD 相关的字段的默认值 processColumnUI(column); // 处理 UI 相关的字段的默认值 + processColumnExample(column); // 处理字段的 swagger example 示例 } return columns; } @@ -169,4 +172,42 @@ public class CodegenBuilder { } } + /** + * 处理字段的 swagger example 示例 + * + * @param column 字段 + */ + private void processColumnExample(CodegenColumnDO column) { + // id、price、count 等可能是整数的后缀 + if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "id", "price", "count")) { + column.setExample(String.valueOf(randomInt(1, Short.MAX_VALUE))); + return; + } + // name + if (StrUtil.endWithIgnoreCase(column.getJavaField(), "name")) { + column.setExample(randomEle(new String[]{"张三", "李四", "王五", "赵六", "芋艿"})); + return; + } + // status + if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "status", "type")) { + column.setExample(randomEle(new String[]{"1", "2"})); + return; + } + // url + if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) { + column.setExample("https://www.iocoder.cn"); + return; + } + // reason + if (StrUtil.endWithIgnoreCase(column.getColumnName(), "reason")) { + column.setExample(randomEle(new String[]{"不喜欢", "不对", "不好", "不香"})); + return; + } + // description、memo、remark + if (StrUtil.endWithAnyIgnoreCase(column.getColumnName(), "description", "memo", "remark")) { + column.setExample(randomEle(new String[]{"你猜", "随便", "你说的对"})); + return; + } + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index cec246bfc..132e903d9 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -91,8 +91,6 @@ public class CodegenEngine { vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) .put(vue3TemplatePath("api/api.ts"), vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) - .put(vue3TemplatePath("api/types.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/types.ts")) // SQL .put("codegen/sql/sql.vm", "sql/sql.sql") .put("codegen/sql/h2.vm", "sql/h2.sql") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java index 88a0ff59e..48361c14c 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.infra.service.file; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.IdUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -20,7 +19,6 @@ import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -79,20 +77,36 @@ public class FileConfigServiceImpl implements FileConfigService { @Resource private Validator validator; - @Resource - @Lazy // 注入自己,所以延迟加载 - private FileConfigService self; - @Override @PostConstruct public void initFileClients() { - // 获取文件配置,如果有更新 - List configs = loadFileConfigIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(configs)) { + initLocalCacheIfUpdate(null); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initLocalCacheIfUpdate(this.maxUpdateTime); + } + + /** + * 刷新本地缓存 + * + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 + */ + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); return; } + List configs = fileConfigMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存文件配置,数量为:{}]", configs.size()); - // 创建或更新支付 Client + // 第二步:构建缓存。创建或更新文件 Client configs.forEach(config -> { fileClientFactory.createOrUpdateFileClient(config.getId(), config.getStorage(), config.getConfig()); // 如果是 master,进行设置 @@ -101,35 +115,8 @@ public class FileConfigServiceImpl implements FileConfigService { } }); - // 写入缓存 - maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime); - log.info("[initFileClients][初始化 FileConfig 数量为 {}]", configs.size()); - } - - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - self.initFileClients(); - } - - /** - * 如果文件配置发生变化,从数据库中获取最新的全量文件配置。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前文件配置的最大更新时间 - * @return 文件配置列表 - */ - private List loadFileConfigIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadFileConfigIfUpdate][首次加载全量文件配置]"); - } else { // 判断数据库中是否有更新的文件配置 - if (fileConfigMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; - } - log.info("[loadFileConfigIfUpdate][增量加载全量文件配置]"); - } - // 第二步,如果有更新,则从数据库加载所有文件配置 - return fileConfigMapper.selectList(); + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(configs, FileConfigDO::getUpdateTime); } @Override @@ -230,7 +217,7 @@ public class FileConfigServiceImpl implements FileConfigService { this.validateFileConfigExists(id); // 上传文件 byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); - return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg"); + return fileClientFactory.getFileClient(id).upload(content, IdUtil.fastSimpleUUID() + ".jpg", "image/jpeg"); } @Override diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 493a9ed1f..2226e7bae 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -52,7 +52,7 @@ public class FileServiceImpl implements FileService { // 上传到文件存储器 FileClient client = fileConfigService.getMasterFileClient(); Assert.notNull(client, "客户端(master) 不能为空"); - String url = client.upload(content, path); + String url = client.upload(content, path, type); // 保存到数据库 FileDO file = new FileDO(); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm index dc6cee6b6..bf6408c9c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm @@ -9,7 +9,7 @@ import javax.validation.constraints.*; #if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}) && ${column.javaType} == "LocalDateTime")## 时间类型 import org.springframework.format.annotation.DateTimeFormat; - +import java.time.LocalDateTime; import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; #break #end diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm index 4034b6f63..19bc32db6 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm @@ -1,7 +1,12 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; import lombok.*; -import java.util.*; +#foreach ($column in $columns) +#if (${column.javaType} == "LocalDateTime") +import java.time.LocalDateTime; +#break +#end +#end import io.swagger.annotations.*; @ApiModel("${sceneEnum.name} - ${table.classComment} Response VO") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm index d1099ecbf..df49a002b 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm @@ -1,7 +1,48 @@ import request from '@/config/axios' -import { ${simpleClassName}VO, ${simpleClassName}PageReqVO, ${simpleClassName}ExcelReqVO } from './types' +export interface ${simpleClassName}VO { +#foreach ($column in $columns) +#if ($column.createOperation || $column.updateOperation) +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") + ${column.javaField}: number +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") + ${column.javaField}: Date +#else + ${column.javaField}: ${column.javaType.toLowerCase()} +#end +#end +#end +} + +export interface ${simpleClassName}PageReqVO extends PageParam { +#foreach ($column in $columns) +#if (${column.listOperation})##查询操作 +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") + ${column.javaField}?: number +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") + ${column.javaField}?: Date[] +#else + ${column.javaField}?: ${column.javaType.toLowerCase()} +#end +#end +#end +} + +export interface ${simpleClassName}ExcelReqVO { +#foreach ($column in $columns) +#if (${column.listOperation})##查询操作 +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") + ${column.javaField}?: number +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") + ${column.javaField}?: Date[] +#else + ${column.javaField}?: ${column.javaType.toLowerCase()} +#end +#end +#end +} #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") + // 查询${table.classComment}列表 export const get${simpleClassName}PageApi = async (params: ${simpleClassName}PageReqVO) => { return await request.get({ url: '${baseURL}/page', params }) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm deleted file mode 100644 index 54ab47e02..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/types.ts.vm +++ /dev/null @@ -1,41 +0,0 @@ -export type ${simpleClassName}VO = { -#foreach ($column in $columns) -#if ($column.createOperation || $column.updateOperation) -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer") - ${column.javaField}: number -#elseif(${column.javaType.toLowerCase()} == "date") - ${column.javaField}: string -#else - ${column.javaField}: ${column.javaType.toLowerCase()} -#end -#end -#end -} - -export type ${simpleClassName}PageReqVO = { -#foreach ($column in $columns) -#if (${column.listOperation})##查询操作 -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer") - ${column.javaField}: number -#elseif(${column.javaType.toLowerCase()} == "date") - ${column.javaField}: string -#else - ${column.javaField}: ${column.javaType.toLowerCase()} -#end -#end -#end -} - -export type ${simpleClassName}ExcelReqVO = { -#foreach ($column in $columns) -#if (${column.listOperation})##查询操作 -#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer") - ${column.javaField}: number -#elseif(${column.javaType.toLowerCase()} == "date") - ${column.javaField}: string -#else - ${column.javaField}: ${column.javaType.toLowerCase()} -#end -#end -#end -} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm index fa64bc883..33e204a46 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm @@ -1,111 +1,110 @@ import { reactive } from 'vue' import { useI18n } from '@/hooks/web/useI18n' -import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas' import { DICT_TYPE } from '@/utils/dict' +import { required } from '@/utils/formRules' +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas' const { t } = useI18n() // 国际化 // 表单校验 export const rules = reactive({ #foreach ($column in $columns) #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 #set($comment=$column.columnComment) - $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == "select")'change'#else'blur'#end }], + $column.javaField: [required], #end #end }) // CrudSchema -const crudSchemas = reactive([ -#foreach($column in $columns) - #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation) - #set ($dictType = $column.dictType) - { - label: '${column.columnComment}', - field: '${column.javaField}', - #if ("" != $dictType)## 有数据字典 - dictType: DICT_TYPE.$dictType.toUpperCase(), - #end - #if($column.primaryKey) - type: 'index', - form: { - show: false - }, - detail: { - show: false - } - #else - #if (!$column.createOperation && !$column.updateOperation) - form: { - show: false - }, - #elseif(!("" != $column.dictType)) - form: { - show: true, - #if ($column.htmlType == "datetime")## 时间框 - component: 'DatePicker', - componentProps: { - type: 'datetime', - valueFormat: 'YYYY-MM-DD HH:mm:ss' - } +const crudSchemas = reactive({ + primaryKey: 'id', // 默认的主键ID + primaryTitle: t('common.index'), // 默认显示的值 + primaryType: 'seq', // 默认为seq,序号模式 + action: true, + actionWidth: '200', // 3个按钮默认200,如有删减对应增减即可 + columns: [ + #foreach($column in $columns) + #if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation) + #set ($dictType = $column.dictType) + #if(!$column.primaryKey) + { + title: '${column.columnComment}', + field: '${column.javaField}', + #if (!$column.listOperationResult) + isTable: false, + #end + #if ("" != $dictType)## 有数据字典 + dictType: DICT_TYPE.$dictType.toUpperCase(), + #if (${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer") + dictClass: 'number', + #else + dictClass: 'string', + #end + #end + #if (!$column.createOperation && !$column.updateOperation) + isForm: false, + #elseif(!("" != $column.dictType)) + #if (${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") + form: { + component: 'DatePicker', + componentProps: { + type: 'datetime', + valueFormat: 'x' + } + }, #elseif($column.htmlType == "editor")## 文本编辑器 - component: 'Editor', - colProps: { - span: 24 + form: { + component: 'Editor', + colProps: { + span: 24 + }, + componentProps: { + valueHtml: '' + } }, - componentProps: { - valueHtml: '' - } #elseif($column.htmlType == "textarea")## 文本框 - component: 'Input', - componentProps: { - type: 'textarea', - rows: 4 + form: { + component: 'Input', + componentProps: { + type: 'textarea', + rows: 4 + }, + colProps: { + span: 24 + } + }, + #elseif(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")## 数字类型 + form: { + component: 'InputNumber', + value: 0 + }, + #elseif($column.htmlType == "imageUpload")## 图片上传 + form: { + component: 'UploadImg' // 单图上传,多图为UploadImgs + }, + #elseif($column.htmlType == "fileUpload")## 图片上传 + form: { + component: 'UploadFile' }, - colProps: { - span: 24 - } #end - }, - #end - #if ($column.listOperationResult) - search: { + #end + #if ($column.listOperation) #if($column.htmlType == "input") - show: true - #else - #if($column.htmlType == "datetime") - show: true, - component: 'DatePicker', - componentProps: { - type: 'datetimerange', - valueFormat: 'YYYY-MM-DD HH:mm:ss' - } - #elseif($column.htmlType == "select" || $column.htmlType == "radio") - #if ("" == $dictType)## 没有数据字典 - show: true, - component: 'Select', - componentProps: { - option: [{'','请选择字典生成'}] - } - #else - show: true + isSearch: true, + #elseif("" != $dictType) + isSearch: true, + #elseif($column.htmlType == "datetime") + formatter: 'formatDate', + search: { + show: true, + itemRender: { + name: 'XDataTimePicker' + } + }, #end #end - #end - } - #end - #end - }, - #end -#end - { - label: t('table.action'), - field: 'action', - width: '240px', - form: { - show: false }, - detail: { - show: false - } - } -]) - -export const { allSchemas } = useCrudSchemas(crudSchemas) \ No newline at end of file + #end + #end + #end + ] +}) +export const { allSchemas } = useVxeCrudSchemas(crudSchemas) \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm index 509f1493f..06fe3002a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm @@ -1,51 +1,151 @@ - - - diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java index 5220a8cad..5f29e79ec 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceTest.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -153,7 +153,7 @@ public class ConfigServiceTest extends BaseDbUnitTest { o.setName("芋艿"); o.setConfigKey("yunai"); o.setType(ConfigTypeEnum.SYSTEM.getType()); - o.setCreateTime(buildLocalDateTime(2021, 2, 1)); + o.setCreateTime(buildTime(2021, 2, 1)); }); configMapper.insert(dbConfig); // 测试 name 不匹配 @@ -163,13 +163,13 @@ public class ConfigServiceTest extends BaseDbUnitTest { // 测试 type 不匹配 configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType()))); // 测试 createTime 不匹配 - configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildLocalDateTime(2021, 1, 1)))); + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 ConfigPageReqVO reqVO = new ConfigPageReqVO(); reqVO.setName("艿"); reqVO.setKey("nai"); reqVO.setType(ConfigTypeEnum.SYSTEM.getType()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 15),buildLocalDateTime(2021, 2, 15)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 15),buildTime(2021, 2, 15)})); // 调用 PageResult pageResult = configService.getConfigPage(reqVO); @@ -186,7 +186,7 @@ public class ConfigServiceTest extends BaseDbUnitTest { o.setName("芋艿"); o.setConfigKey("yunai"); o.setType(ConfigTypeEnum.SYSTEM.getType()); - o.setCreateTime(buildLocalDateTime(2021, 2, 1)); + o.setCreateTime(buildTime(2021, 2, 1)); }); configMapper.insert(dbConfig); // 测试 name 不匹配 @@ -196,13 +196,13 @@ public class ConfigServiceTest extends BaseDbUnitTest { // 测试 type 不匹配 configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(ConfigTypeEnum.CUSTOM.getType()))); // 测试 createTime 不匹配 - configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildLocalDateTime(2021, 1, 1)))); + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 ConfigExportReqVO reqVO = new ConfigExportReqVO(); reqVO.setName("艿"); reqVO.setKey("nai"); reqVO.setType(ConfigTypeEnum.SYSTEM.getType()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 15),buildLocalDateTime(2021, 2, 15)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 15),buildTime(2021, 2, 15)})); // 调用 List list = configService.getConfigList(reqVO); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java index 1b28b0e12..33d0d1ad7 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImplTest.java @@ -28,7 +28,7 @@ import java.time.LocalDateTime; import java.util.Map; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -219,8 +219,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { FileConfigPageReqVO reqVO = new FileConfigPageReqVO(); reqVO.setName("芋道"); reqVO.setStorage(FileStorageEnum.LOCAL.getStorage()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 1, 1), - buildLocalDateTime(2020, 1, 24)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 1, 1), + buildTime(2020, 1, 24)})); // 调用 PageResult pageResult = fileConfigService.getFileConfigPage(reqVO); @@ -240,7 +240,7 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest { // mock 获得 Client FileClient fileClient = mock(FileClient.class); when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient); - when(fileClient.upload(any(), any())).thenReturn("https://www.iocoder.cn"); + when(fileClient.upload(any(), any(), any())).thenReturn("https://www.iocoder.cn"); // 调用,并断言 assertEquals("https://www.iocoder.cn", fileConfigService.testFileConfig(id)); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java index 80fd90ece..2d4285bee 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceTest.java @@ -17,7 +17,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS; @@ -43,7 +43,7 @@ public class FileServiceTest extends BaseDbUnitTest { FileDO dbFile = randomPojo(FileDO.class, o -> { // 等会查询到 o.setPath("yunai"); o.setType("image/jpg"); - o.setCreateTime(buildLocalDateTime(2021, 1, 15)); + o.setCreateTime(buildTime(2021, 1, 15)); }); fileMapper.insert(dbFile); // 测试 path 不匹配 @@ -54,13 +54,13 @@ public class FileServiceTest extends BaseDbUnitTest { })); // 测试 createTime 不匹配 fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> { - o.setCreateTime(buildLocalDateTime(2020, 1, 15)); + o.setCreateTime(buildTime(2020, 1, 15)); })); // 准备参数 FilePageReqVO reqVO = new FilePageReqVO(); reqVO.setPath("yunai"); reqVO.setType("jp"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 10), buildLocalDateTime(2021, 1, 20)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 10), buildTime(2021, 1, 20)})); // 调用 PageResult pageResult = fileService.getFilePage(reqVO); @@ -79,7 +79,7 @@ public class FileServiceTest extends BaseDbUnitTest { FileClient client = mock(FileClient.class); when(fileConfigService.getMasterFileClient()).thenReturn(client); String url = randomString(); - when(client.upload(same(content), same(path))).thenReturn(url); + when(client.upload(same(content), same(path), same("image/jpeg"))).thenReturn(url); when(client.getId()).thenReturn(10L); String name = "单测文件名"; // 调用 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java index 89323b142..665e9c509 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/job/JobLogServiceTest.java @@ -16,7 +16,7 @@ import java.util.ArrayList; import java.util.List; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -96,8 +96,8 @@ public class JobLogServiceTest extends BaseDbUnitTest { o.setExecuteIndex(1); o.setHandlerName("handlerName 单元测试"); o.setStatus(JobLogStatusEnum.SUCCESS.getStatus()); - o.setBeginTime(buildLocalDateTime(2021, 1, 8)); - o.setEndTime(buildLocalDateTime(2021, 1, 8)); + o.setBeginTime(buildTime(2021, 1, 8)); + o.setEndTime(buildTime(2021, 1, 8)); }); jobLogMapper.insert(dbJobLog); // 测试 jobId 不匹配 @@ -105,9 +105,9 @@ public class JobLogServiceTest extends BaseDbUnitTest { // 测试 handlerName 不匹配 jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString()))); // 测试 beginTime 不匹配 - jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildLocalDateTime(2021, 1, 7)))); + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7)))); // 测试 endTime 不匹配 - jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildLocalDateTime(2021, 1, 9)))); + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9)))); // 测试 status 不匹配 jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(JobLogStatusEnum.FAILURE.getStatus()))); // 准备参数 @@ -132,8 +132,8 @@ public class JobLogServiceTest extends BaseDbUnitTest { o.setExecuteIndex(1); o.setHandlerName("handlerName 单元测试"); o.setStatus(JobLogStatusEnum.SUCCESS.getStatus()); - o.setBeginTime(buildLocalDateTime(2021, 1, 8)); - o.setEndTime(buildLocalDateTime(2021, 1, 8)); + o.setBeginTime(buildTime(2021, 1, 8)); + o.setEndTime(buildTime(2021, 1, 8)); }); jobLogMapper.insert(dbJobLog); // 测试 jobId 不匹配 @@ -141,9 +141,9 @@ public class JobLogServiceTest extends BaseDbUnitTest { // 测试 handlerName 不匹配 jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString()))); // 测试 beginTime 不匹配 - jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildLocalDateTime(2021, 1, 7)))); + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7)))); // 测试 endTime 不匹配 - jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildLocalDateTime(2021, 1, 9)))); + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9)))); // 测试 status 不匹配 jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(JobLogStatusEnum.FAILURE.getStatus()))); // 准备参数 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java index cb1e52b23..b650fb603 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImplTest.java @@ -19,7 +19,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -40,7 +40,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { int userType = UserTypeEnum.ADMIN.getValue(); String applicationName = "yudao-test"; String requestUrl = "foo"; - LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13); + LocalDateTime beginTime = buildTime(2021, 3, 13); int duration = 1000; int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode(); @@ -65,7 +65,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { // requestUrl 不同的 apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); // 构造一个早期时间 2021-02-06 00:00:00 - apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildLocalDateTime(2021, 2, 6)))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); // duration 不同的 apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100))); // resultCode 不同的 @@ -77,7 +77,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); reqVO.setRequestUrl(requestUrl); - reqVO.setBeginTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)})); + reqVO.setBeginTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)})); reqVO.setDuration(duration); reqVO.setResultCode(resultCode); @@ -97,7 +97,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { int userType = UserTypeEnum.ADMIN.getValue(); String applicationName = "yudao-test"; String requestUrl = "foo"; - LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13); + LocalDateTime beginTime = buildTime(2021, 3, 13); int duration = 1000; int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode(); @@ -122,7 +122,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { // requestUrl 不同的 apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); // 构造一个早期时间 2021-02-06 00:00:00 - apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildLocalDateTime(2021, 2, 6)))); + apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); // duration 不同的 apiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100))); // resultCode 不同的 @@ -134,7 +134,7 @@ public class ApiAccessLogServiceImplTest extends BaseDbUnitTest { reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); reqVO.setRequestUrl(requestUrl); - reqVO.setBeginTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)})); + reqVO.setBeginTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)})); reqVO.setDuration(duration); reqVO.setResultCode(resultCode); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java index bffdf46e8..4e35ba7ea 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImplTest.java @@ -20,7 +20,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; @@ -44,7 +44,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { int userType = UserTypeEnum.ADMIN.getValue(); String applicationName = "yudao-test"; String requestUrl = "foo"; - LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13); + LocalDateTime beginTime = buildTime(2021, 3, 13); int progressStatus = ApiErrorLogProcessStatusEnum.INIT.getStatus(); ApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> { @@ -67,7 +67,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { // requestUrl 不同的 infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar"))); // 构造一个早期时间 2021-02-06 00:00:00 - infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildLocalDateTime(2021, 2, 6)))); + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6)))); // progressStatus 不同的 infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus()))); @@ -77,7 +77,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); reqVO.setRequestUrl(requestUrl); - reqVO.setExceptionTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)})); + reqVO.setExceptionTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)})); reqVO.setProcessStatus(progressStatus); // 调用service方法 @@ -96,7 +96,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { int userType = UserTypeEnum.ADMIN.getValue(); String applicationName = "yudao-test"; String requestUrl = "foo"; - LocalDateTime beginTime = buildLocalDateTime(2021, 3, 13); + LocalDateTime beginTime = buildTime(2021, 3, 13); int progressStatus = ApiErrorLogProcessStatusEnum.INIT.getStatus(); ApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(ApiErrorLogDO.class, logDO -> { @@ -119,7 +119,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { // requestUrl 不同的 infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar"))); // 构造一个早期时间 2021-02-06 00:00:00 - infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildLocalDateTime(2021, 2, 6)))); + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6)))); // progressStatus 不同的 infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(ApiErrorLogProcessStatusEnum.DONE.getStatus()))); @@ -129,7 +129,7 @@ public class ApiErrorLogServiceImplTest extends BaseDbUnitTest { reqVO.setUserType(userType); reqVO.setApplicationName(applicationName); reqVO.setRequestUrl(requestUrl); - reqVO.setExceptionTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 12),buildLocalDateTime(2021, 3, 14)})); + reqVO.setExceptionTime((new LocalDateTime[]{buildTime(2021, 3, 12),buildTime(2021, 3, 14)})); reqVO.setProcessStatus(progressStatus); // 调用service方法 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java index 356b98b00..c4a7fb46e 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImplTest.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.infra.service.test; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO; @@ -17,7 +16,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -112,7 +111,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest { o.setType(1); o.setCategory(2); o.setRemark("哈哈哈"); - o.setCreateTime(DateUtils.buildLocalDateTime(2021, 11, 11)); + o.setCreateTime(buildTime(2021, 11, 11)); }); testDemoMapper.insert(dbTestDemo); // 测试 name 不匹配 @@ -126,7 +125,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest { // 测试 remark 不匹配 testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark("呵呵呵"))); // 测试 createTime 不匹配 - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2021, 12, 12)))); + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 TestDemoPageReqVO reqVO = new TestDemoPageReqVO(); reqVO.setName("芋道"); @@ -134,7 +133,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest { reqVO.setType(1); reqVO.setCategory(2); reqVO.setRemark("哈哈哈"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10),buildLocalDateTime(2021, 11, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)})); // 调用 PageResult pageResult = testDemoService.getTestDemoPage(reqVO); @@ -153,7 +152,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest { o.setType(1); o.setCategory(2); o.setRemark("哈哈哈"); - o.setCreateTime(DateUtils.buildLocalDateTime(2021, 11, 11)); + o.setCreateTime(buildTime(2021, 11, 11)); }); testDemoMapper.insert(dbTestDemo); // 测试 name 不匹配 @@ -167,7 +166,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest { // 测试 remark 不匹配 testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark("呵呵呵"))); // 测试 createTime 不匹配 - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2021, 12, 12)))); + testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 TestDemoExportReqVO reqVO = new TestDemoExportReqVO(); reqVO.setName("芋道"); @@ -175,7 +174,7 @@ public class TestDemoServiceImplTest extends BaseDbUnitTest { reqVO.setType(1); reqVO.setCategory(2); reqVO.setRemark("哈哈哈"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 10),buildLocalDateTime(2021, 11, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 10),buildTime(2021, 11, 12)})); // 调用 List list = testDemoService.getTestDemoList(reqVO); diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java new file mode 100644 index 000000000..83269f91d --- /dev/null +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.product.api.property; + +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 商品属性值 API 接口 + * + * @author 芋道源码 + */ +public interface ProductPropertyValueApi { + + /** + * 根据编号数组,获得属性值列表 + * + * @param ids 编号数组 + * @return 属性值明细列表 + */ + List getPropertyValueDetailList(Collection ids); + +} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java new file mode 100644 index 000000000..2a1ab71a9 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.product.api.property.dto; + +import lombok.Data; + +/** + * 商品属性项的明细 Response DTO + * + * @author 芋道源码 + */ +@Data +public class ProductPropertyValueDetailRespDTO { + + /** + * 属性的编号 + */ + private Long propertyId; + + /** + * 属性的名称 + */ + private String propertyName; + + /** + * 属性值的编号 + */ + private Long valueId; + + /** + * 属性值的名称 + */ + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java index 4b324149b..aaaf767f2 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -18,17 +18,17 @@ public class ProductSkuRespDTO { * 商品 SKU 编号,自增 */ private Long id; - /** - * 商品 SKU 名字 - */ - private String name; /** * SPU 编号 */ private Long spuId; + /** + * SPU 名字 + */ + private String spuName; /** - * 规格值数组,JSON 格式 + * 属性数组,JSON 格式 */ private List properties; /** diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java index 86875b119..4adad0afc 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java @@ -15,28 +15,30 @@ public interface ErrorCodeConstants { ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类"); ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除"); ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用"); - ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下"); // ========== 商品品牌相关编号 1008002000 ========== ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在"); ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在"); ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在"); - // ========== 商品规格名称 1008003000 ========== - ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在"); - ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "规格名称已存在"); + // ========== 商品属性项 1008003000 ========== + ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在"); + ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在"); + ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除"); - // ========== 规格值 1008004000 ========== - ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在"); - ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "规格值已存在"); + // ========== 商品属性值 1008004000 ========== + ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在"); + ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在"); // ========== 商品 SPU 1008005000 ========== ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在"); + ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下"); + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态"); // ========== 商品 SKU 1008006000 ========== ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在"); ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复"); - ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致"); + ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致"); ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复"); ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足"); diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java index 30ece744d..fbc227b53 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java @@ -21,11 +21,11 @@ public enum ProductSpuSpecTypeEnum implements IntArrayValuable { public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray(); /** - * 规格 + * 规格类型 */ private final Integer type; /** - * 规格名 + * 规格名称 */ private final String name; diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java index 6b7f03ac2..2223cf23d 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java @@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable { return ARRAYS; } + /** + * 判断是否处于【上架】状态 + * + * @param status 状态 + * @return 是否处于【上架】状态 + */ + public static boolean isEnable(Integer status) { + return ENABLE.getStatus().equals(status); + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java new file mode 100644 index 000000000..9aab9e560 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.product.api.property; + +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 商品属性值 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ProductPropertyValueApiImpl implements ProductPropertyValueApi { + + @Resource + private ProductPropertyValueService productPropertyValueService; + + @Override + public List getPropertyValueDetailList(Collection ids) { + return ProductPropertyValueConvert.INSTANCE.convertList02( + productPropertyValueService.getPropertyValueDetailList(ids)); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java index 9a4c20c58..5efecd0c7 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java @@ -1,9 +1,14 @@ package cn.iocoder.yudao.module.product.controller.admin.property; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; @@ -13,12 +18,13 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; - +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -@Api(tags = "管理后台 - 规格名称") +@Api(tags = "管理后台 - 商品属性项") @RestController @RequestMapping("/product/property") @Validated @@ -26,16 +32,18 @@ public class ProductPropertyController { @Resource private ProductPropertyService productPropertyService; + @Resource + private ProductPropertyValueService productPropertyValueService; @PostMapping("/create") - @ApiOperation("创建规格名称") + @ApiOperation("创建属性项") @PreAuthorize("@ss.hasPermission('product:property:create')") public CommonResult createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) { return success(productPropertyService.createProperty(createReqVO)); } @PutMapping("/update") - @ApiOperation("更新规格名称") + @ApiOperation("更新属性项") @PreAuthorize("@ss.hasPermission('product:property:update')") public CommonResult updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) { productPropertyService.updateProperty(updateReqVO); @@ -43,7 +51,7 @@ public class ProductPropertyController { } @DeleteMapping("/delete") - @ApiOperation("删除规格名称") + @ApiOperation("删除属性项") @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:property:delete')") public CommonResult deleteProperty(@RequestParam("id") Long id) { @@ -52,32 +60,40 @@ public class ProductPropertyController { } @GetMapping("/get") - @ApiOperation("获得规格名称") + @ApiOperation("获得属性项") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:property:query')") public CommonResult getProperty(@RequestParam("id") Long id) { - return success(productPropertyService.getProperty(id)); + return success(ProductPropertyConvert.INSTANCE.convert(productPropertyService.getProperty(id))); } @GetMapping("/list") - @ApiOperation("获得规格名称列表") + @ApiOperation("获得属性项列表") @PreAuthorize("@ss.hasPermission('product:property:query')") public CommonResult> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) { - return success(productPropertyService.getPropertyList(listReqVO)); + return success(ProductPropertyConvert.INSTANCE.convertList(productPropertyService.getPropertyList(listReqVO))); } @GetMapping("/page") - @ApiOperation("获得规格名称分页") + @ApiOperation("获得属性项分页") @PreAuthorize("@ss.hasPermission('product:property:query')") public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { - return success(productPropertyService.getPropertyPage(pageVO)); + return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO))); } - @GetMapping("/listAndValue") - @ApiOperation("获得规格名称列表") + @GetMapping("/get-value-list") + @ApiOperation("获得属性项列表") @PreAuthorize("@ss.hasPermission('product:property:query')") public CommonResult> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) { - return success(productPropertyService.getPropertyAndValueList(listReqVO)); + // 查询属性项 + List keys = productPropertyService.getPropertyList(listReqVO); + if (CollUtil.isEmpty(keys)) { + return success(Collections.emptyList()); + } + // 查询属性值 + List values = productPropertyValueService.getPropertyValueListByPropertyId( + convertSet(keys, ProductPropertyDO::getId)); + return success(ProductPropertyConvert.INSTANCE.convertList(keys, values)); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java index e88c91415..fec327946 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.property; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; +import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -20,7 +20,7 @@ import javax.validation.Valid; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Api(tags = "管理后台 - 规格值名称") +@Api(tags = "管理后台 - 商品属性值") @RestController @RequestMapping("/product/property/value") @Validated @@ -30,14 +30,14 @@ public class ProductPropertyValueController { private ProductPropertyValueService productPropertyValueService; @PostMapping("/create") - @ApiOperation("创建规格名称") + @ApiOperation("创建属性值") @PreAuthorize("@ss.hasPermission('product:property:create')") public CommonResult createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) { return success(productPropertyValueService.createPropertyValue(createReqVO)); } @PutMapping("/update") - @ApiOperation("更新规格名称") + @ApiOperation("更新属性值") @PreAuthorize("@ss.hasPermission('product:property:update')") public CommonResult updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) { productPropertyValueService.updatePropertyValue(updateReqVO); @@ -45,7 +45,7 @@ public class ProductPropertyValueController { } @DeleteMapping("/delete") - @ApiOperation("删除规格名称") + @ApiOperation("删除属性值") @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:property:delete')") public CommonResult deleteProperty(@RequestParam("id") Long id) { @@ -54,17 +54,17 @@ public class ProductPropertyValueController { } @GetMapping("/get") - @ApiOperation("获得规格名称") + @ApiOperation("获得属性值") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:property:query')") public CommonResult getProperty(@RequestParam("id") Long id) { - return success(productPropertyValueService.getPropertyValue(id)); + return success(ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueService.getPropertyValue(id))); } @GetMapping("/page") - @ApiOperation("获得规格名称分页") + @ApiOperation("获得属性值分页") @PreAuthorize("@ss.hasPermission('product:property:query')") public CommonResult> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) { - return success(productPropertyValueService.getPropertyValueListPage(pageVO)); + return success(ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueService.getPropertyValuePage(pageVO))); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java deleted file mode 100644 index 9bdc70bd7..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.ToString; - -import java.util.List; - -/** - * @Description: ProductPropertyViewRespVO - * @Author: franky - * @CreateDate: 2022/7/5 21:29 - * @Version: 1.0.0 - */ -@ApiModel("管理后台 - 规格名称详情展示 Request VO") -@Data -@ToString(callSuper = true) -public class ProductPropertyViewRespVO { - - @ApiModelProperty(value = "规格名称id", example = "1") - public Long propertyId; - - @ApiModelProperty(value = "规格名称", example = "内存") - public String name; - - @ApiModelProperty(value = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]") - public List propertyValues; - - @Data - @ApiModel(value = "规格属性值元组") - public static class Tuple2 { - private final long id; - private final String name; - - public Tuple2(Long id, String name) { - this.id = id; - this.name = name; - } - - } - - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java index e7b3c352f..a739bc0f2 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java @@ -1,30 +1,36 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import java.time.LocalDateTime; import java.util.List; -@ApiModel("管理后台 - 规格 + 规格值 Response VO") +@ApiModel("管理后台 - 商品属性项 + 属性值 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO { +public class ProductPropertyAndValueRespVO { - @ApiModelProperty(value = "规格的编号", required = true, example = "1024") + @ApiModelProperty(value = "属性项的编号", required = true, example = "1024") private Long id; - @ApiModelProperty(value = "创建时间", required = true) - private LocalDateTime createTime; + @ApiModelProperty(value = "属性项的名称", required = true, example = "颜色") + private String name; /** - * 规格值的集合 + * 属性值的集合 */ - private List values; + private List values; + + @ApiModel("管理后台 - 属性值的简单 Response VO") + @Data + public static class Value { + + @ApiModelProperty(value = "属性值的编号", required = true, example = "2048") + private Long id; + + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色") + private String name; + + } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java index 25fc4c01a..fb089dce1 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java @@ -4,24 +4,19 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; /** - * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用 + * 商品属性项 Base VO,提供给添加、修改、详细的子 VO 使用 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data public class ProductPropertyBaseVO { - @ApiModelProperty(value = "规格名称", required = true, example = "颜色") - @NotBlank(message = "规格名称不能为空") + @ApiModelProperty(value = "名称", required = true, example = "颜色") + @NotBlank(message = "名称不能为空") private String name; @ApiModelProperty(value = "备注", example = "颜色") private String remark; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") - @NotNull(message = "状态不能为空") - private Integer status; - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java index 8dfd58a5d..2e68f21e3 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java @@ -5,7 +5,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@ApiModel("管理后台 - 规格名称创建 Request VO") +@ApiModel("管理后台 - 属性项创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java index 314288ffb..1233480d1 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java @@ -5,15 +5,12 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.ToString; -@ApiModel("管理后台 - 规格名称 List Request VO") +@ApiModel("管理后台 - 属性项 List Request VO") @Data @ToString(callSuper = true) public class ProductPropertyListReqVO { - @ApiModelProperty(value = "规格名称", example = "颜色") + @ApiModelProperty(value = "名称", example = "颜色") private String name; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") - private Integer status; - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java index 05a67e874..60bd7db5b 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java @@ -12,13 +12,13 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@ApiModel("管理后台 - 规格名称分页 Request VO") +@ApiModel("管理后台 - 属性项 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ProductPropertyPageReqVO extends PageParam { - @ApiModelProperty(value = "规格名称", example = "颜色") + @ApiModelProperty(value = "名称", example = "颜色") private String name; @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java index 75a9a5eea..299aa56e4 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java @@ -8,13 +8,13 @@ import lombok.ToString; import java.time.LocalDateTime; -@ApiModel("管理后台 - 规格 + 规格值 Response VO") +@ApiModel("管理后台 - 属性项 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ProductPropertyRespVO extends ProductPropertyBaseVO { - @ApiModelProperty(value = "规格的编号", required = true, example = "1024") + @ApiModelProperty(value = "编号", required = true, example = "1024") private Long id; @ApiModelProperty(value = "创建时间", required = true) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java index f4630d874..4dfa48366 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.property; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; -import lombok.*; -import io.swagger.annotations.*; -import javax.validation.constraints.*; -import java.util.List; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; -@ApiModel("管理后台 - 规格名称更新 Request VO") +import javax.validation.constraints.NotNull; + +@ApiModel("管理后台 - 属性项更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java index 142a8e6e2..76b2f1a8b 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java @@ -7,24 +7,20 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; /** -* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用 +* 属性值 Base VO,提供给添加、修改、详细的子 VO 使用 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 */ @Data public class ProductPropertyValueBaseVO { - @ApiModelProperty(value = "规格编号", required = true, example = "1024") - @NotNull(message = "规格编号不能为空") + @ApiModelProperty(value = "属性项的编号", required = true, example = "1024") + @NotNull(message = "属性项的编号不能为空") private Long propertyId; - @ApiModelProperty(value = "规格值名字", required = true, example = "红色") - @NotEmpty(message = "规格值名字不能为空") + @ApiModelProperty(value = "名称", required = true, example = "红色") + @NotEmpty(message = "名称名字不能为空") private String name; - @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") - @NotNull(message = "状态不能为空") - private Integer status; - @ApiModelProperty(value = "备注", example = "颜色") private String remark; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java index f7237f9cd..8930f6ba3 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; import lombok.*; import io.swagger.annotations.*; -@ApiModel("管理后台 - 规格值创建 Request VO") +@ApiModel("管理后台 - 商品属性值创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java new file mode 100644 index 000000000..55bae16df --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo.value; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("管理后台 - 商品属性值的明细 Response VO") +@Data +public class ProductPropertyValueDetailRespVO { + + @ApiModelProperty(value = "属性的编号", required = true, example = "1") + private Long propertyId; + + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色") + private String propertyName; + + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024") + private Long valueId; + + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色") + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java index ae77d822b..3f5ffee3d 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java @@ -6,23 +6,17 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; -import javax.validation.constraints.NotEmpty; -import java.util.Date; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@ApiModel("管理后台 - 规格名称值分页 Request VO") +@ApiModel("管理后台 - 商品属性值分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ProductPropertyValuePageReqVO extends PageParam { - @ApiModelProperty(value = "规格id", example = "1024") + @ApiModelProperty(value = "属性项的编号", example = "1024") private String propertyId; - @ApiModelProperty(value = "规格值", example = "红色") + @ApiModelProperty(value = "名称", example = "红色") private String name; @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java index 501afd752..fb5ecead9 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java @@ -8,13 +8,13 @@ import lombok.ToString; import java.time.LocalDateTime; -@ApiModel("管理后台 - 规格值 Response VO") +@ApiModel("管理后台 - 商品属性值 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO { - @ApiModelProperty(value = "主键", required = true, example = "10") + @ApiModelProperty(value = "编号", required = true, example = "10") private Long id; @ApiModelProperty(value = "创建时间") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java index 2437600a8..f13d434b3 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java @@ -4,7 +4,7 @@ import lombok.*; import io.swagger.annotations.*; import javax.validation.constraints.*; -@ApiModel("管理后台 - 规格值更新 Request VO") +@ApiModel("管理后台 - 商品属性值更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java index 45cb447b8..1bb08ff32 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java @@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; @@ -55,8 +57,10 @@ public class ProductSkuBaseVO { @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米") private Double volume; - @ApiModel("规格值") + @ApiModel("商品属性") @Data + @AllArgsConstructor + @NoArgsConstructor public static class Property { @ApiModelProperty(value = "属性编号", required = true, example = "1") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java index 6d5ce024d..ab83eeeac 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.product.controller.admin.sku.vo; import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -14,11 +13,8 @@ import java.util.List; @ToString(callSuper = true) public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO { - @ApiModelProperty(value = "商品 SKU 编号", example = "1") - private Long id; - /** - * 规格值数组 + * 属性数组 */ private List properties; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java index 1ac29724b..85f5903cc 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java @@ -22,7 +22,7 @@ public class ProductSkuRespVO extends ProductSkuBaseVO { private LocalDateTime createTime; /** - * 规格值数组 + * 属性数组 */ private List properties; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http new file mode 100644 index 000000000..4ab7b4f71 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http @@ -0,0 +1,4 @@ +### 获得商品 SPU 明细 +GET {{baseUrl}}/product/spu/get-detail?id=4 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java index 155fd0265..f19fde594 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java @@ -3,8 +3,13 @@ package cn.iocoder.yudao.module.product.controller.admin.spu; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -15,10 +20,11 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; -import java.util.Collection; import java.util.List; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; @Api(tags = "管理后台 - 商品 SPU") @RestController @@ -27,20 +33,24 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; public class ProductSpuController { @Resource - private ProductSpuService spuService; + private ProductSpuService productSpuService; + @Resource + private ProductSkuService productSkuService; + @Resource + private ProductPropertyValueService productPropertyValueService; @PostMapping("/create") @ApiOperation("创建商品 SPU") @PreAuthorize("@ss.hasPermission('product:spu:create')") public CommonResult createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) { - return success(spuService.createSpu(createReqVO)); + return success(productSpuService.createSpu(createReqVO)); } @PutMapping("/update") @ApiOperation("更新商品 SPU") @PreAuthorize("@ss.hasPermission('product:spu:update')") public CommonResult updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) { - spuService.updateSpu(updateReqVO); + productSpuService.updateSpu(updateReqVO); return success(true); } @@ -49,42 +59,35 @@ public class ProductSpuController { @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:spu:delete')") public CommonResult deleteSpu(@RequestParam("id") Long id) { - spuService.deleteSpu(id); + productSpuService.deleteSpu(id); return success(true); } - // TODO 芋艿:修改接口 - @GetMapping("/get/detail") - @ApiOperation("获得商品 SPU") + @GetMapping("/get-detail") + @ApiOperation("获得商品 SPU 明细") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:spu:query')") public CommonResult getSpuDetail(@RequestParam("id") Long id) { - return success(spuService.getSpuDetail(id)); - } + // 获得商品 SPU + ProductSpuDO spu = productSpuService.getSpu(id); + if (spu == null) { + throw exception(SPU_NOT_EXISTS); + } - @GetMapping("/get") - @ApiOperation("获得商品 SPU") - @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult getSpu(@RequestParam("id") Long id) { - return success(spuService.getSpu(id)); - } - - - @GetMapping("/list") - @ApiOperation("获得商品 SPU 列表") - @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getSpuList(@RequestParam("ids") Collection ids) { - List list = spuService.getSpuList(ids); - return success(ProductSpuConvert.INSTANCE.convertList(list)); + // 查询商品 SKU + List skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null); + // 查询商品属性 + List propertyValues = productPropertyValueService + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus)); + // 拼接 + return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues)); } @GetMapping("/get-simple-list") @ApiOperation("获得商品 SPU 精简列表") @PreAuthorize("@ss.hasPermission('product:spu:query')") public CommonResult> getSpuSimpleList() { - List list = spuService.getSpuList(); + List list = productSpuService.getSpuList(); return success(ProductSpuConvert.INSTANCE.convertList02(list)); } @@ -92,7 +95,7 @@ public class ProductSpuController { @ApiOperation("获得商品 SPU 分页") @PreAuthorize("@ss.hasPermission('product:spu:query')") public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) { - return success(spuService.getSpuPage(pageVO)); + return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO))); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java index 54f0986dd..5f9f8a24c 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java @@ -64,28 +64,13 @@ public class ProductSpuBaseVO { @NotNull(message = "是否展示库存不能为空") private Boolean showStock; - @ApiModelProperty(value = "库存", required = true, example = "true") - private Integer totalStock; - @ApiModelProperty(value = "市场价", example = "1024") private Integer marketPrice; - @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") - private Integer minPrice; - - @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024") - private Integer maxPrice; - // ========== 统计相关字段 ========= - @ApiModelProperty(value = "商品销量", example = "1024") - private Integer salesCount; - @ApiModelProperty(value = "虚拟销量", required = true, example = "1024") @NotNull(message = "虚拟销量不能为空") private Integer virtualSalesCount; - @ApiModelProperty(value = "点击量", example = "1024") - private Integer clickCount; - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java index de41d1416..65cdd22a2 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java @@ -1,27 +1,21 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.time.LocalDateTime; import java.util.List; @ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ProductSpuDetailRespVO extends ProductSpuBaseVO { +public class ProductSpuDetailRespVO extends ProductSpuRespVO { - @ApiModelProperty(value = "主键", required = true, example = "1") - private Long id; - - @ApiModelProperty(value = "创建时间") - private LocalDateTime createTime; + // ========== SKU 相关字段 ========= /** * SKU 数组 @@ -35,31 +29,10 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO { public static class Sku extends ProductSkuBaseVO { /** - * 规格的数组 + * 属性数组 */ - private List properties; + private List properties; } - @ApiModel(value = "管理后台 - 商品规格的详细 Response VO") - @Data - @EqualsAndHashCode(callSuper = true) - @ToString(callSuper = true) - public static class Property extends ProductSkuBaseVO.Property { - - @ApiModelProperty(value = "规格的名字", required = true, example = "颜色") - private String propertyName; - - @ApiModelProperty(value = "规格值的名字", required = true, example = "蓝色") - private String valueName; - - } - - @ApiModelProperty(value = "分类 id 数组,一直递归到一级父节点", example = "4") - private Long categoryId; - - // TODO @芋艿:在瞅瞅~ - @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]") - private List productPropertyViews; - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java index 8d1bbee5f..3d74dc80c 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java @@ -19,7 +19,7 @@ public class ProductSpuPageReqVO extends PageParam { @ApiModelProperty(value = "商品编码", example = "yudaoyuanma") private String code; - @ApiModelProperty(value = "分类id", example = "1") + @ApiModelProperty(value = "分类编号", example = "1") private Long categoryId; @ApiModelProperty(value = "商品品牌编号", example = "1") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java index a8dca328b..66b86e0a5 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java @@ -7,7 +7,6 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import java.time.LocalDateTime; -import java.util.List; @ApiModel("管理后台 - 商品 SPU Response VO") @Data @@ -21,4 +20,22 @@ public class ProductSpuRespVO extends ProductSpuBaseVO { @ApiModelProperty(value = "创建时间") private LocalDateTime createTime; + // ========== SKU 相关字段 ========= + + @ApiModelProperty(value = "库存", required = true, example = "true") + private Integer totalStock; + + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") + private Integer minPrice; + + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024") + private Integer maxPrice; + + @ApiModelProperty(value = "商品销量", example = "1024") + private Integer salesCount; + + // ========== 统计相关字段 ========= + + @ApiModelProperty(value = "点击量", example = "1024") + private Integer clickCount; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java new file mode 100644 index 000000000..379e85180 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位符,无时间作用,避免 package 缩进 + */ +package cn.iocoder.yudao.module.product.controller.app.property; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java new file mode 100644 index 000000000..6538bea3c --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位符,无时间作用,避免 package 缩进 + */ +package cn.iocoder.yudao.module.product.controller.app.property.vo.property; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java new file mode 100644 index 000000000..516dd077f --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.product.controller.app.property.vo.value; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("用户 App - 商品属性值的明细 Response VO") +@Data +public class AppProductPropertyValueDetailRespVO { + + @ApiModelProperty(value = "属性的编号", required = true, example = "1") + private Long propertyId; + + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色") + private String propertyName; + + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024") + private Long valueId; + + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色") + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http new file mode 100644 index 000000000..04df7bfec --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http @@ -0,0 +1,8 @@ +### 获得订单交易的分页 TODO +GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10 +Authorization: Bearer {{appToken}} +tenant-id: {{appTenentId}} + +### 获得商品 SPU 明细 +GET {{appApi}}/product/spu/get-detail?id=4 +tenant-id: {{appTenentId}} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java index 7e0f912b4..9116f29cf 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java @@ -1,13 +1,22 @@ package cn.iocoder.yudao.module.product.controller.app.spu; -import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -17,28 +26,54 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; +import java.util.List; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; -@Api(tags = "用户 APP - 商品spu") +@Api(tags = "用户 APP - 商品 SPU") @RestController @RequestMapping("/product/spu") @Validated public class AppProductSpuController { @Resource - private ProductSpuService spuService; + private ProductSpuService productSpuService; + @Resource + private ProductSkuService productSkuService; + @Resource + private ProductPropertyValueService productPropertyValueService; @GetMapping("/page") - @ApiOperation("获得商品spu分页") - public CommonResult> getSpuPage(@Valid AppSpuPageReqVO pageVO) { - return success(spuService.getSpuPage(pageVO)); + @ApiOperation("获得商品 SPU 分页") + public CommonResult> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) { + PageResult pageResult = productSpuService.getSpuPage(pageVO, ProductSpuStatusEnum.ENABLE.getStatus()); + return success(ProductSpuConvert.INSTANCE.convertPage02(pageResult)); } - @GetMapping("/") - @ApiOperation("获取商品 - 通过商品id") - public CommonResult getSpu(@RequestParam("spuId") Long spuId) { - AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class); - return success(appSpuRespVO); + @GetMapping("/get-detail") + @ApiOperation("获得商品 SPU 明细") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + public CommonResult getSpuDetail(@RequestParam("id") Long id) { + // 获得商品 SPU + ProductSpuDO spu = productSpuService.getSpu(id); + if (spu == null) { + throw exception(SPU_NOT_EXISTS); + } + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { + throw exception(SPU_NOT_ENABLE); + } + + // 查询商品 SKU + List skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), + CommonStatusEnum.ENABLE.getStatus()); + // 查询商品属性 + List propertyValues = productPropertyValueService + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus)); + // 拼接 + return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues)); } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java new file mode 100644 index 000000000..699ca1caa --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.product.controller.app.spu.vo; + +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("用户 App - 商品 SPU 明细 Response VO") +@Data +public class AppProductSpuDetailRespVO { + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + private Long id; + + // ========== 基本信息 ========= + + @ApiModelProperty(value = "商品名称", required = true, example = "芋道") + private String name; + + @ApiModelProperty(value = "促销语", example = "好吃!") + private String sellPoint; + + @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述") + private String description; + + @ApiModelProperty(value = "商品分类编号", required = true, example = "1") + private Long categoryId; + + @ApiModelProperty(value = "商品图片的数组", required = true) + private List picUrls; + + @ApiModelProperty(value = "商品视频", required = true) + private String videoUrl; + + // ========== SKU 相关字段 ========= + + @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类") + private Integer specType; + + @ApiModelProperty(value = "是否展示库存", required = true, example = "true") + private Boolean showStock; + + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") + private Integer minPrice; + + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024") + private Integer maxPrice; + + /** + * SKU 数组 + */ + private List skus; + + // ========== 统计相关字段 ========= + + @ApiModelProperty(value = "商品销量", required = true, example = "1024") + private Integer salesCount; + + @ApiModel("用户 App - 商品 SPU 明细的 SKU 信息") + @Data + public static class Sku { + + @ApiModelProperty(value = "商品 SKU 编号", example = "1") + private Long id; + + /** + * 商品属性数组 + */ + private List properties; + + @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分") + private Integer price; + + @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分") + private Integer marketPrice; + + @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png") + private String picUrl; + + @ApiModelProperty(value = "库存", required = true, example = "1") + private Integer stock; + + @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克") + private Double weight; + + @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米") + private Double volume; + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java new file mode 100644 index 000000000..60fc9235e --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.product.controller.app.spu.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@ApiModel("用户 App - 商品 SPU 分页项 Response VO") +@Data +public class AppProductSpuPageItemRespVO { + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "商品名称", required = true, example = "芋道") + @NotEmpty(message = "商品名称不能为空") + private String name; + + @ApiModelProperty(value = "分类编号", required = true) + @NotNull(message = "分类编号不能为空") + private Long categoryId; + + @ApiModelProperty(value = "商品图片的数组", required = true) + private List picUrls; + + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") + private Integer minPrice; + + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024") + private Integer maxPrice; + + // ========== 统计相关字段 ========= + + @ApiModelProperty(value = "商品销量", example = "1024") + private Integer salesCount; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java new file mode 100644 index 000000000..f19a7c21a --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.product.controller.app.spu.vo; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.AssertTrue; + +@ApiModel("用户 App - 商品 SPU 分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class AppProductSpuPageReqVO extends PageParam { + + public static final String SORT_FIELD_PRICE = "price"; + public static final String SORT_FIELD_SALES_COUNT = "salesCount"; + + @ApiModelProperty(value = "分类编号", example = "1") + private Long categoryId; + + @ApiModelProperty(value = "关键字", example = "好看") + private String keyword; + + @ApiModelProperty(value = "排序字段", example = "price", notes = "参见 AppSpuPageReqVO.SORT_FIELD_XXX 常量") + private String sortField; + + @ApiModelProperty(value = "排序方式", example = "true", notes = "true - 升序;false - 降序") + private Boolean sortAsc; + + @AssertTrue(message = "排序字段不合法") + @JsonIgnore + public boolean isSortFieldValid() { + if (StrUtil.isEmpty(sortField)) { + return true; + } + return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT); + } + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java deleted file mode 100644 index 38ed4975e..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@ApiModel("App - 商品spu分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class AppSpuPageReqVO extends PageParam { - - @ApiModelProperty(value = "分类id") - private Long categoryId; -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java deleted file mode 100644 index c0a0f0eb8..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.util.List; - -@ApiModel("App - 商品spu分页 Request VO") -@Data -public class AppSpuPageRespVO { - - @ApiModelProperty(value = "主键", required = true, example = "1") - private Long id; - - @ApiModelProperty(value = "商品名称") - private String name; - - @ApiModelProperty(value = "卖点", required = true) - @NotNull(message = "卖点不能为空") - private String sellPoint; - - @ApiModelProperty(value = "描述", required = true) - @NotNull(message = "描述不能为空") - private String description; - - @ApiModelProperty(value = "分类id", required = true) - @NotNull(message = "分类id不能为空") - private Long categoryId; - - @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true) - @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空") - private List picUrls; - - @ApiModelProperty(value = "排序字段", required = true) - @NotNull(message = "排序字段不能为空") - private Integer sort; - - @ApiModelProperty(value = "点赞初始人数") - private Integer likeCount; - - @ApiModelProperty(value = "价格 单位使用:分") - private Integer price; - - @ApiModelProperty(value = "库存数量") - private Integer quantity; - - @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)") - private Integer status; - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java deleted file mode 100644 index b45987370..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.app.spu.vo; - -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; -import io.swagger.annotations.ApiModel; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - *

- * - *

- * - * @author LuoWenFeng - */ -@ApiModel("App - 商品spu Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class AppSpuRespVO extends ProductSpuRespVO { - - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java index 91f811ad6..211bcc293 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java @@ -1,20 +1,21 @@ package cn.iocoder.yudao.module.product.convert.property; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import java.util.List; +import java.util.Map; /** - * 规格名称 Convert + * 属性项 Convert * * @author 芋道源码 */ @@ -27,12 +28,21 @@ public interface ProductPropertyConvert { ProductPropertyDO convert(ProductPropertyUpdateReqVO bean); - ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean); - ProductPropertyRespVO convert(ProductPropertyDO bean); List convertList(List list); PageResult convertPage(PageResult page); + default List convertList(List keys, List values) { + Map> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId); + return CollectionUtils.convertList(keys, key -> { + ProductPropertyAndValueRespVO respVO = convert02(key); + respVO.setValues(convertList02(valueMap.get(key.getId()))); + return respVO; + }); + } + ProductPropertyAndValueRespVO convert02(ProductPropertyDO bean); + List convertList02(List list); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java index 331ad623f..d6167c174 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java @@ -1,18 +1,25 @@ package cn.iocoder.yudao.module.product.convert.propertyvalue; -import java.util.*; - import cn.iocoder.yudao.framework.common.pojo.PageResult; - +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + /** - * 规格值 Convert + * 属性值 Convert * * @author 芋道源码 */ @@ -31,6 +38,18 @@ public interface ProductPropertyValueConvert { PageResult convertPage(PageResult page); - List convertList03(List list); + default List convertList(List values, List keys) { + Map keyMap = convertMap(keys, ProductPropertyDO::getId); + return CollectionUtils.convertList(values, value -> { + ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO() + .setValueId(value.getId()).setValueName(value.getName()); + // 设置属性项 + MapUtils.findAndThen(keyMap, value.getPropertyId(), + key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName())); + return valueDetail; + }); + } + + List convertList02(List list); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java index b29d612be..f397dfc48 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.product.convert.sku; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; @@ -10,9 +12,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; @@ -32,12 +33,16 @@ public interface ProductSkuConvert { List convertList(List list); - List convertSkuDOList(List list); + List convertList06(List list); + + default List convertList06(List list, Long spuId, String spuName) { + List result = convertList06(list); + result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName)); + return result; + } ProductSkuRespDTO convert02(ProductSkuDO bean); - List convertList02(List list); - List convertList03(List list); List convertList04(List list); @@ -66,4 +71,23 @@ public interface ProductSkuConvert { return spuIdAndStockMap; } + default Collection convertPropertyValueIds(List list) { + if (CollUtil.isEmpty(list)) { + return new HashSet<>(); + } + return list.stream().filter(item -> item.getProperties() != null) + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 + .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 + .collect(Collectors.toSet()); + } + + default String buildPropertyKey(ProductSkuDO bean) { + if (CollUtil.isEmpty(bean.getProperties())) { + return StrUtil.EMPTY; + } + List properties = new ArrayList<>(bean.getProperties()); + properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId)); + return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining()); + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java index 98b7d8837..fcf6d6436 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java @@ -1,18 +1,29 @@ package cn.iocoder.yudao.module.product.convert.spu; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.ArrayList; import java.util.List; +import java.util.Map; + +import static cn.hutool.core.util.ObjectUtil.defaultIfNull; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** - * 商品spu Convert + * 商品 SPU Convert * * @author 芋道源码 */ @@ -25,18 +36,73 @@ public interface ProductSpuConvert { ProductSpuDO convert(ProductSpuUpdateReqVO bean); - ProductSpuRespVO convert(ProductSpuDO bean); - - List convertList(List list); + List convertList(List list); PageResult convertPage(PageResult page); - ProductSpuPageReqVO convert(AppSpuPageReqVO bean); - - AppSpuPageRespVO convertAppResp(ProductSpuDO list); + ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean); List convertList2(List list); List convertList02(List list); + default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List skus, + List propertyValues) { + AppProductSpuDetailRespVO spuVO = convert02(spu) + .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0)); + spuVO.setSkus(convertList03(skus)); + // 处理商品属性 + Map propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId); + for (int i = 0; i < skus.size(); i++) { + List properties = skus.get(i).getProperties(); + if (CollUtil.isEmpty(properties)) { + continue; + } + AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i); + sku.setProperties(new ArrayList<>(properties.size())); + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中 + properties.forEach(property -> { + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId()); + if (propertyValue == null) { + return; + } + sku.getProperties().add(convert03(propertyValue)); + }); + } + return spuVO; + } + AppProductSpuDetailRespVO convert02(ProductSpuDO spu); + List convertList03(List skus); + AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue); + + PageResult convertPage02(PageResult page); + + default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List skus, + List propertyValues) { + ProductSpuDetailRespVO spuVO = convert03(spu); + spuVO.setSkus(convertList04(skus)); + // 处理商品属性 + Map propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId); + for (int i = 0; i < skus.size(); i++) { + List properties = skus.get(i).getProperties(); + if (CollUtil.isEmpty(properties)) { + continue; + } + ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i); + sku.setProperties(new ArrayList<>(properties.size())); + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中 + properties.forEach(property -> { + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId()); + if (propertyValue == null) { + return; + } + sku.getProperties().add(convert04(propertyValue)); + }); + } + return spuVO; + } + ProductSpuDetailRespVO convert03(ProductSpuDO spu); + List convertList04(List skus); + ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java index b3831491e..2976674c1 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.product.dal.dataobject.property; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -8,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; /** - * 规格名称 DO + * 商品属性项 DO * * @author 芋道源码 */ @@ -28,20 +27,12 @@ public class ProductPropertyDO extends BaseDO { @TableId private Long id; /** - * 规格名称 + * 名称 */ private String name; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; /** * 备注 */ private String remark; - // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索) - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java index b75f0d592..d73fe06b2 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.product.dal.dataobject.property; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -9,7 +8,7 @@ import lombok.*; /** - * 规格值 DO + * 商品属性值 DO * * @author 芋道源码 */ @@ -29,21 +28,15 @@ public class ProductPropertyValueDO extends BaseDO { @TableId private Long id; /** - * 规格键编号 + * 属性项的编号 * * 关联 {@link ProductPropertyDO#getId()} */ private Long propertyId; /** - * 规格值名字 + * 名称 */ private String name; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; /** * 备注 * diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java index f953534ed..3836f20e5 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java @@ -35,10 +35,6 @@ public class ProductSkuDO extends BaseDO { */ @TableId private Long id; - /** - * 商品 SKU 名字 - */ - private String name; /** * SPU 编号 *

@@ -46,7 +42,13 @@ public class ProductSkuDO extends BaseDO { */ private Long spuId; /** - * 规格值数组,JSON 格式 + * SPU 名字 + * + * 冗余 {@link ProductSkuDO#getSpuName()} + */ + private String spuName; + /** + * 属性数组,JSON 格式 */ @TableField(typeHandler = PropertyTypeHandler.class) private List properties; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java index 890df3477..26f8d5239 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java @@ -3,31 +3,30 @@ package cn.iocoder.yudao.module.product.dal.mysql.property; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; -/** - * 规格名称 Mapper - * - * @author 芋道源码 - */ @Mapper public interface ProductPropertyMapper extends BaseMapperX { default PageResult selectPage(ProductPropertyPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ProductPropertyDO::getName, reqVO.getName()) - .eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus()) .betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime()) .orderByDesc(ProductPropertyDO::getId)); } default ProductPropertyDO selectByName(String name) { - return selectOne(new LambdaQueryWrapperX() - .eqIfPresent(ProductPropertyDO::getName, name)); + return selectOne(ProductPropertyDO::getName, name); + } + + default List selectList(ProductPropertyListReqVO listReqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ProductPropertyDO::getName, listReqVO.getName())); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java index ca9bafab2..402df51e7 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java @@ -7,17 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; import java.util.List; -/** - * 规格值 Mapper - * - * @author 芋道源码 - */ @Mapper public interface ProductPropertyValueMapper extends BaseMapperX { - default List selectListByPropertyId(List propertyIds) { + default List selectListByPropertyId(Collection propertyIds) { return selectList(new LambdaQueryWrapperX() .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds)); } @@ -28,17 +24,20 @@ public interface ProductPropertyValueMapper extends BaseMapperX().eq(ProductPropertyValueDO::getPropertyId, propertyId) - .eq(ProductPropertyValueDO::getDeleted, false)); + default void deleteByPropertyId(Long propertyId) { + delete(new LambdaQueryWrapperX() + .eq(ProductPropertyValueDO::getPropertyId, propertyId)); } default PageResult selectPage(ProductPropertyValuePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId()) .likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName()) - .eqIfPresent(ProductPropertyValueDO::getStatus, reqVO.getStatus()) .orderByDesc(ProductPropertyValueDO::getId)); } + default Integer selectCountByPropertyId(Long propertyId) { + return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue(); + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java index 3e5a9ce8f..56bc54499 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; import java.util.List; /** @@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX { return selectList(ProductSkuDO::getSpuId, spuId); } + default List selectListBySpuIdAndStatus(Long spuId, + Integer status) { + return selectList(new LambdaQueryWrapperX() + .eq(ProductSkuDO::getSpuId, spuId) + .eqIfPresent(ProductSkuDO::getStatus, status)); + } + + default List selectListBySpuId(Collection spuIds) { + return selectList(ProductSkuDO::getSpuId, spuIds); + } + default void deleteBySpuId(Long spuId) { delete(new LambdaQueryWrapperX().eq(ProductSkuDO::getSpuId, spuId)); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java index a271b5051..57a3125d8 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java @@ -4,10 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.util.Objects; import java.util.Set; /** @@ -44,6 +46,19 @@ public interface ProductSpuMapper extends BaseMapperX { .orderByDesc(ProductSpuDO::getSort)); } + default PageResult selectPage(AppProductSpuPageReqVO pageReqVO, Integer status) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .eqIfPresent(ProductSpuDO::getCategoryId, pageReqVO.getCategoryId()) + .eqIfPresent(ProductSpuDO::getStatus, status); + // 排序逻辑 + if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) { + query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getMaxPrice); + } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) { + query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getSalesCount); + } + return selectPage(pageReqVO, query); + } + /** * 更新商品 SPU 库存 * diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java index 117f35931..01967857e 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java @@ -2,7 +2,7 @@ * trade 模块,主要实现交易相关功能 * 例如:订单、退款、购物车等功能。 * - * 1. Controller URL:以 /trade/ 开头,避免和其它 Module 冲突 - * 2. DataObject 表名:以 trade_ 开头,方便在数据库中区分 + * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 product_ 开头,方便在数据库中区分 */ package cn.iocoder.yudao.module.product; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java index 118e8118b..32a4c030d 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; import javax.validation.Valid; -import java.util.Collection; import java.util.List; /** @@ -47,12 +46,19 @@ public interface ProductCategoryService { ProductCategoryDO getCategory(Long id); /** - * 获得商品分类列表 + * 校验商品分类 * - * @param ids 编号 - * @return 商品分类列表 + * @param id 分类编号 */ - List getEnableCategoryList(Collection ids); + void validateCategory(Long id); + + /** + * 获得商品分类的层级 + * + * @param id 编号 + * @return 商品分类的层级 + */ + Integer getCategoryLevel(Long id); /** * 获得商品分类列表 @@ -62,14 +68,6 @@ public interface ProductCategoryService { */ List getEnableCategoryList(ProductCategoryListReqVO listReqVO); - /** - * 验证选择的商品分类的级别是否合法 - * 例如说,商品发布的时候,必须在第 3 级别 - * - * @param id 分类编号 - */ - void validateCategoryLevel(Long id); - /** * 获得开启状态的商品分类列表 * diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java index ffe55e9bf..f0d10b8b8 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.Collection; import java.util.List; import java.util.Objects; @@ -90,31 +89,40 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { } } - @Override - public void validateCategoryLevel(Long id) { - // TODO @芋艿:在看看,杂能优化下 - Long parentId = id; - int i = 2; - for (; i >= 0; --i) { - ProductCategoryDO category = productCategoryMapper.selectById(parentId); - parentId = category.getParentId(); - if(Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL)){ - break; - } - } - if (!Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL) || i != 0) { - throw exception(CATEGORY_LEVEL_ERROR); - } - } - @Override public ProductCategoryDO getCategory(Long id) { return productCategoryMapper.selectById(id); } @Override - public List getEnableCategoryList(Collection ids) { - return productCategoryMapper.selectBatchIds(ids); + public void validateCategory(Long id) { + ProductCategoryDO category = productCategoryMapper.selectById(id); + if (category == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + throw exception(CATEGORY_DISABLED, category.getName()); + } + } + + @Override + public Integer getCategoryLevel(Long id) { + if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) { + return 0; + } + int level = 1; + for (int i = 0; i < 100; i++) { + ProductCategoryDO category = productCategoryMapper.selectById(id); + // 如果没有父节点,break 结束 + if (category == null + || Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) { + break; + } + // 继续递归父节点 + level++; + id = category.getParentId(); + } + return level; } @Override diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java index 8780c7865..564bc82a9 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.product.service.property; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; @@ -10,14 +9,15 @@ import java.util.Collection; import java.util.List; /** - * 规格名称 Service 接口 + * 商品属性项 Service 接口 * * @author 芋道源码 */ public interface ProductPropertyService { /** - * 创建规格名称 + * 创建属性项 + * 注意,如果已经存在该属性项,直接返回它的编号即可 * * @param createReqVO 创建信息 * @return 编号 @@ -25,56 +25,48 @@ public interface ProductPropertyService { Long createProperty(@Valid ProductPropertyCreateReqVO createReqVO); /** - * 更新规格名称 + * 更新属性项 * * @param updateReqVO 更新信息 */ void updateProperty(@Valid ProductPropertyUpdateReqVO updateReqVO); /** - * 删除规格名称 + * 删除属性项 * * @param id 编号 */ void deleteProperty(Long id); /** - * 获得规格名称列表 + * 获得属性项列表 * @param listReqVO 集合查询 - * @return 规格名称集合 + * @return 属性项集合 */ - List getPropertyList(ProductPropertyListReqVO listReqVO); + List getPropertyList(ProductPropertyListReqVO listReqVO); /** * 获取属性名称分页 * * @param pageReqVO 分页条件 - * @return 规格名称分页 + * @return 属性项分页 */ - PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO); + PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO); /** - * 获得指定编号的规格名称 + * 获得指定编号的属性项 * * @param id 编号 - * @return 规格名称 + * @return 属性项 */ - ProductPropertyRespVO getProperty(Long id); + ProductPropertyDO getProperty(Long id); /** - * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合 + * 根据属性项的编号的集合,获得对应的属性项数组 * - * @param ids 规格编号的集合 - * @return 对应的规格 + * @param ids 属性项的编号的集合 + * @return 属性项数组 */ - List getPropertyList(Collection ids); - - /** - * 获得规格名称 + 值的列表 - * - * @param listReqVO 列表查询 - * @return 规格名称 + 值的列表 - */ - List getPropertyAndValueList(ProductPropertyListReqVO listReqVO); + List getPropertyList(Collection ids); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java index 74e370f9c..328c343d6 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java @@ -1,16 +1,15 @@ package cn.iocoder.yudao.module.product.service.property; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO; import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert; -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper; -import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -18,15 +17,12 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; /** - * 规格名称 Service 实现类 + * 商品属性项 Service 实现类 * * @author 芋道源码 */ @@ -38,15 +34,18 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { private ProductPropertyMapper productPropertyMapper; @Resource - private ProductPropertyValueMapper productPropertyValueMapper; + @Lazy // 延迟加载,解决循环依赖问题 + private ProductPropertyValueService productPropertyValueService; @Override @Transactional(rollbackFor = Exception.class) public Long createProperty(ProductPropertyCreateReqVO createReqVO) { - // 校验存在 - if (productPropertyMapper.selectByName(createReqVO.getName()) != null) { - throw exception(PROPERTY_EXISTS); + // 如果已经添加过该属性项,直接返回 + ProductPropertyDO dbProperty = productPropertyMapper.selectByName(createReqVO.getName()); + if (dbProperty != null) { + return dbProperty.getId(); } + // 插入 ProductPropertyDO property = ProductPropertyConvert.INSTANCE.convert(createReqVO); productPropertyMapper.insert(property); @@ -57,12 +56,14 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @Override @Transactional(rollbackFor = Exception.class) public void updateProperty(ProductPropertyUpdateReqVO updateReqVO) { - // 校验存在 - this.validatePropertyExists(updateReqVO.getId()); + validatePropertyExists(updateReqVO.getId()); + // 校验名字重复 ProductPropertyDO productPropertyDO = productPropertyMapper.selectByName(updateReqVO.getName()); - if (productPropertyDO != null && !productPropertyDO.getId().equals(updateReqVO.getId())) { + if (productPropertyDO != null && + ObjUtil.notEqual(productPropertyDO.getId(), updateReqVO.getId())) { throw exception(PROPERTY_EXISTS); } + // 更新 ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO); productPropertyMapper.updateById(updateObj); @@ -71,11 +72,16 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @Override public void deleteProperty(Long id) { // 校验存在 - this.validatePropertyExists(id); + validatePropertyExists(id); + // 校验其下是否有规格值 + if (productPropertyValueService.getPropertyValueCountByPropertyId(id) > 0) { + throw exception(PROPERTY_DELETE_FAIL_VALUE_EXISTS); + } + // 删除 productPropertyMapper.deleteById(id); - //同步删除属性值 - productPropertyValueMapper.deletePropertyValueByPropertyId(id); + // 同步删除属性值 + productPropertyValueService.deletePropertyValueByPropertyId(id); } private void validatePropertyExists(Long id) { @@ -85,41 +91,23 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { } @Override - public List getPropertyList(ProductPropertyListReqVO listReqVO) { - return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectList(new LambdaQueryWrapperX() - .likeIfPresent(ProductPropertyDO::getName, listReqVO.getName()) - .eqIfPresent(ProductPropertyDO::getStatus, listReqVO.getStatus()))); + public List getPropertyList(ProductPropertyListReqVO listReqVO) { + return productPropertyMapper.selectList(listReqVO); } @Override - public PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO) { - //获取属性列表 - PageResult pageResult = productPropertyMapper.selectPage(pageReqVO); - return ProductPropertyConvert.INSTANCE.convertPage(pageResult); + public PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO) { + return productPropertyMapper.selectPage(pageReqVO); } @Override - public ProductPropertyRespVO getProperty(Long id) { - ProductPropertyDO property = productPropertyMapper.selectById(id); - return ProductPropertyConvert.INSTANCE.convert(property); + public ProductPropertyDO getProperty(Long id) { + return productPropertyMapper.selectById(id); } @Override - public List getPropertyList(Collection ids) { - return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids)); + public List getPropertyList(Collection ids) { + return productPropertyMapper.selectBatchIds(ids); } - @Override - public List getPropertyAndValueList(ProductPropertyListReqVO listReqVO) { - List propertyList = getPropertyList(listReqVO); - - // 查询属性值 - List valueDOList = productPropertyValueMapper.selectListByPropertyId(CollectionUtils.convertList(propertyList, ProductPropertyRespVO::getId)); - Map> valueDOMap = CollectionUtils.convertMultiMap(valueDOList, ProductPropertyValueDO::getPropertyId); - return CollectionUtils.convertList(propertyList, m -> { - ProductPropertyAndValueRespVO productPropertyAndValueRespVO = ProductPropertyConvert.INSTANCE.convert(m); - productPropertyAndValueRespVO.setValues(ProductPropertyValueConvert.INSTANCE.convertList(valueDOMap.get(m.getId()))); - return productPropertyAndValueRespVO; - }); - } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java index 9dcbd72e7..553e2578d 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java @@ -3,22 +3,23 @@ package cn.iocoder.yudao.module.product.service.property; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; +import java.util.Collection; import java.util.List; /** - *

- * 规格值 Service 接口 - *

+ * 商品属性值 Service 接口 * * @author LuoWenFeng */ public interface ProductPropertyValueService { /** - * 创建规格值 + * 创建属性值 + * 注意,如果已经存在该属性值,直接返回它的编号即可 * * @param createReqVO 创建信息 * @return 编号 @@ -26,40 +27,64 @@ public interface ProductPropertyValueService { Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO); /** - * 更新规格值 + * 更新属性值 * * @param updateReqVO 更新信息 */ void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO); /** - * 删除规格值 + * 删除属性值 * * @param id 编号 */ void deletePropertyValue(Long id); /** - * 获得规格值 + * 获得属性值 * * @param id 编号 - * @return 规格名称 + * @return 属性值 */ - ProductPropertyValueRespVO getPropertyValue(Long id); + ProductPropertyValueDO getPropertyValue(Long id); /** - * 获得规格值 + * 根据属性项编号数组,获得属性值列表 * - * @param id 编号 - * @return 规格名称 + * @param propertyIds 属性项目编号数组 + * @return 属性值列表 */ - List getPropertyValueListByPropertyId(List id); + List getPropertyValueListByPropertyId(Collection propertyIds); /** - * 获取规格值 分页 + * 根据编号数组,获得属性值列表 + * + * @param ids 编号数组 + * @return 属性值明细列表 + */ + List getPropertyValueDetailList(Collection ids); + + /** + * 根据属性项编号,活的属性值数量 + * + * @param propertyId 属性项编号数 + * @return 属性值数量 + */ + Integer getPropertyValueCountByPropertyId(Long propertyId); + + /** + * 获取属性值的分页 * * @param pageReqVO 查询条件 - * @return + * @return 属性值的分页 */ - PageResult getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO); + PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO); + + /** + * 删除指定属性项编号下的属性值们 + * + * @param propertyId 属性项的编号 + */ + void deletePropertyValueByPropertyId(Long propertyId); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java index 5addb37e8..e5bc6874b 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java @@ -1,26 +1,31 @@ package cn.iocoder.yudao.module.product.service.property; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS; /** - * 规格值 Service 实现类 + * 商品属性值 Service 实现类 * * @author LuoWenFeng */ @@ -31,45 +36,92 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ @Resource private ProductPropertyValueMapper productPropertyValueMapper; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ProductPropertyService productPropertyService; + @Override public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) { - if (productPropertyValueMapper.selectByName(createReqVO.getPropertyId(), createReqVO.getName()) != null) { - throw exception(PROPERTY_VALUE_EXISTS); + // 如果已经添加过该属性值,直接返回 + ProductPropertyValueDO dbValue = productPropertyValueMapper.selectByName( + createReqVO.getPropertyId(), createReqVO.getName()); + if (dbValue != null) { + return dbValue.getId(); } - ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(createReqVO); - productPropertyValueMapper.insert(convert); - return convert.getId(); + + // 新增 + ProductPropertyValueDO value = ProductPropertyValueConvert.INSTANCE.convert(createReqVO); + productPropertyValueMapper.insert(value); + return value.getId(); } @Override public void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO) { - ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectByName(updateReqVO.getPropertyId(), updateReqVO.getName()); + validatePropertyValueExists(updateReqVO.getId()); + // 校验名字唯一 + ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectByName + (updateReqVO.getPropertyId(), updateReqVO.getName()); if (productPropertyValueDO != null && !productPropertyValueDO.getId().equals(updateReqVO.getId())) { throw exception(PROPERTY_VALUE_EXISTS); } - ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO); - productPropertyValueMapper.updateById(convert); + + // 更新 + ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO); + productPropertyValueMapper.updateById(updateObj); } @Override public void deletePropertyValue(Long id) { + validatePropertyValueExists(id); productPropertyValueMapper.deleteById(id); } - @Override - public ProductPropertyValueRespVO getPropertyValue(Long id) { - ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectOne(new LambdaQueryWrapper() - .eq(ProductPropertyValueDO::getId, id)); - return ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueDO); + private void validatePropertyValueExists(Long id) { + if (productPropertyValueMapper.selectById(id) == null) { + throw exception(PROPERTY_VALUE_NOT_EXISTS); + } } @Override - public List getPropertyValueListByPropertyId(List id) { - return ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueMapper.selectList("property_id", id)); + public ProductPropertyValueDO getPropertyValue(Long id) { + return productPropertyValueMapper.selectById(id); } @Override - public PageResult getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO) { - return ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueMapper.selectPage(pageReqVO)); + public List getPropertyValueListByPropertyId(Collection propertyIds) { + return productPropertyValueMapper.selectListByPropertyId(propertyIds); } + + @Override + public List getPropertyValueDetailList(Collection ids) { + // 获得属性值列表 + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List values = productPropertyValueMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(values)) { + return Collections.emptyList(); + } + // 获得属性项列表 + List keys = productPropertyService.getPropertyList( + convertSet(values, ProductPropertyValueDO::getPropertyId)); + // 组装明细 + return ProductPropertyValueConvert.INSTANCE.convertList(values, keys); + } + + @Override + public Integer getPropertyValueCountByPropertyId(Long propertyId) { + return productPropertyValueMapper.selectCountByPropertyId(propertyId); + } + + @Override + public PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO) { + return productPropertyValueMapper.selectPage(pageReqVO); + } + + @Override + public void deletePropertyValueByPropertyId(Long propertyId) { + productPropertyValueMapper.deleteByPropertyId(propertyId); + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java new file mode 100644 index 000000000..6776731f9 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.product.service.property.bo; + +import lombok.Data; + +/** + * 商品属性项的明细 Response BO + * + * @author 芋道源码 + */ +@Data +public class ProductPropertyValueDetailRespBO { + + /** + * 属性的编号 + */ + private Long propertyId; + + /** + * 属性的名称 + */ + private String propertyName; + + /** + * 属性值的编号 + */ + private Long valueId; + + /** + * 属性值的名称 + */ + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java index 1036d8348..621e12d9f 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; +import org.springframework.lang.Nullable; import java.util.Collection; import java.util.List; @@ -49,23 +50,25 @@ public interface ProductSkuService { * * @param list sku组合的集合 */ - void validateSkus(List list, Integer specType); + void validateSkuList(List list, Integer specType); /** * 批量创建 SKU * * @param spuId 商品 SPU 编号 + * @param spuName 商品 SPU 名称 * @param list SKU 对象集合 */ - void createSkus(Long spuId, List list); + void createSkuList(Long spuId, String spuName, List list); /** * 根据 SPU 编号,批量更新它的 SKU 信息 * * @param spuId SPU 编码 + * @param spuName 商品 SPU 名称 * @param skus SKU 的集合 */ - void updateSkus(Long spuId, List skus); + void updateSkuList(Long spuId, String spuName, List skus); /** * 更新 SKU 库存(增量) @@ -77,20 +80,30 @@ public interface ProductSkuService { void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); /** - * 获得商品 sku 集合 + * 获得商品 SKU 集合 * * @param spuId spu 编号 * @return 商品sku 集合 */ - List getSkusBySpuId(Long spuId); + List getSkuListBySpuId(Long spuId); /** - * 获得 spu 对应的 sku 集合 + * 基于 SPU 编号和状态,获得商品 SKU 集合 + * + * @param spuId SPU 编号 + * @param status 状态 + * @return 商品 SKU 集合 + */ + List getSkuListBySpuIdAndStatus(Long spuId, + @Nullable Integer status); + + /** + * 获得 spu 对应的 SKU 集合 * * @param spuIds spu 编码集合 * @return 商品 sku 集合 */ - List getSkusBySpuIds(List spuIds); + List getSkuListBySpuId(List spuIds); /** * 通过 spuId 删除 sku 信息 @@ -104,7 +117,6 @@ public interface ProductSkuService { * * @return SKU 数组 */ - List getSkusByAlarmStock(); - + List getSkuListByAlarmStock(); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java index 2791ae5d3..1ab2523cc 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.product.service.sku; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants; @@ -25,6 +25,7 @@ import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; @@ -78,22 +79,24 @@ public class ProductSkuServiceImpl implements ProductSkuService { } @Override - public void validateSkus(List skus, Integer specType) { + public void validateSkuList(List skus, Integer specType) { // 非多规格,不需要校验 if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) { return; } - // 1、校验规格属性存在 - Set propertyIds = skus.stream().filter(p -> p.getProperties() != null).flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 - .map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toSet()); // 将每个 Property 转换成对应的 propertyId,最后形成集合 - List propertyList = productPropertyService.getPropertyList(propertyIds); + // 1、校验属性项存在 + Set propertyIds = skus.stream().filter(p -> p.getProperties() != null) + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 + .map(ProductSkuBaseVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 + .collect(Collectors.toSet()); + List propertyList = productPropertyService.getPropertyList(propertyIds); if (propertyList.size() != propertyIds.size()) { throw exception(PROPERTY_NOT_EXISTS); } - // 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId - Map propertyValueMap = CollectionUtils.convertMap(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyIds)), ProductPropertyValueRespVO::getId); + // 2. 校验,一个 SKU 下,没有重复的属性。校验方式是,遍历每个 SKU ,看看是否有重复的属性 propertyId + Map propertyValueMap = convertMap(productPropertyValueService.getPropertyValueListByPropertyId(propertyIds), ProductPropertyValueDO::getId); skus.forEach(sku -> { Set skuPropertyIds = convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId()); if (skuPropertyIds.size() != sku.getProperties().size()) { @@ -101,7 +104,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { } }); - // 3. 再校验,每个 Sku 的规格值的数量,是一致的。 + // 3. 再校验,每个 Sku 的属性值的数量,是一致的。 int attrValueIdsSize = skus.get(0).getProperties().size(); for (int i = 1; i < skus.size(); i++) { if (attrValueIdsSize != skus.get(i).getProperties().size()) { @@ -119,21 +122,23 @@ public class ProductSkuServiceImpl implements ProductSkuService { } @Override - public void createSkus(Long spuId, List skuCreateReqList) { - // 批量插入 SKU - List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); - skuDOList.forEach(v -> v.setSpuId(spuId)); - productSkuMapper.insertBatch(skuDOList); + public void createSkuList(Long spuId, String spuName, List skuCreateReqList) { + productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId, spuName)); } @Override - public List getSkusBySpuId(Long spuId) { - return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuId); + public List getSkuListBySpuId(Long spuId) { + return productSkuMapper.selectListBySpuId(spuId); } @Override - public List getSkusBySpuIds(List spuIds) { - return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuIds); + public List getSkuListBySpuIdAndStatus(Long spuId, Integer status) { + return productSkuMapper.selectListBySpuIdAndStatus(spuId, status); + } + + @Override + public List getSkuListBySpuId(List spuIds) { + return productSkuMapper.selectListBySpuId(spuIds); } @Override @@ -142,59 +147,44 @@ public class ProductSkuServiceImpl implements ProductSkuService { } @Override - public List getSkusByAlarmStock() { + public List getSkuListByAlarmStock() { return productSkuMapper.selectListByAlarmStock(); } @Override - @Transactional - public void updateSkus(Long spuId, List skus) { - // 查询 SPU 下已经存在的 SKU 的集合 - List existsSkus = productSkuMapper.selectListBySpuId(spuId); - // 构建规格与 SKU 的映射关系; - // TODO @luowenfeng: 可以下 existsSkuMap2; 会简洁一点; 另外, 可以考虑抽一个小方法, 用于 Properties 生成一个串; 这样 177 也可以复用了 - Map existsSkuMap = existsSkus.stream() - .map(v -> { - String collect = v.getProperties() == null? "null": v.getProperties() - .stream() - .map(m -> String.valueOf(m.getValueId())) - .collect(Collectors.joining()); - return String.join("-", collect, String.valueOf(v.getId())); - }) - .collect(Collectors.toMap(v -> v.split("-")[0], v -> Long.valueOf(v.split("-")[1]))); + @Transactional(rollbackFor = Exception.class) + public void updateSkuList(Long spuId, String spuName, List skus) { + // 构建属性与 SKU 的映射关系; + Map existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId), + ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId); // 拆分三个集合,新插入的、需要更新的、需要删除的 List insertSkus = new ArrayList<>(); List updateSkus = new ArrayList<>(); - List deleteSkus = new ArrayList<>(); - - List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); - allUpdateSkus.forEach(p -> { - String propertiesKey = p.getProperties() == null? "null": p.getProperties().stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining()); + List allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null, spuName); + allUpdateSkus.forEach(sku -> { + String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku); // 1、找得到的,进行更新 - if (existsSkuMap.containsKey(propertiesKey)) { - updateSkus.add(p); - existsSkuMap.remove(propertiesKey); + Long existsSkuId = existsSkuMap.remove(propertiesKey); + if (existsSkuId != null) { + sku.setId(existsSkuId); + updateSkus.add(sku); return; } // 2、找不到,进行插入 - p.setSpuId(spuId); - insertSkus.add(p); + sku.setSpuId(spuId); + insertSkus.add(sku); }); - // 3、多余的,删除 - if(!existsSkuMap.isEmpty()){ - deleteSkus = new ArrayList<>(existsSkuMap.values()); - } - // 4、执行修改 Sku - if (!insertSkus.isEmpty()) { + // 执行最终的批量操作 + if (CollUtil.isNotEmpty(insertSkus)) { productSkuMapper.insertBatch(insertSkus); } - if (!updateSkus.isEmpty()) { - updateSkus.forEach(p -> productSkuMapper.updateById(p)); + if (CollUtil.isNotEmpty(updateSkus)) { + updateSkus.forEach(sku -> productSkuMapper.updateById(sku)); } - if (!deleteSkus.isEmpty()) { - productSkuMapper.deleteBatchIds(deleteSkus); + if (CollUtil.isNotEmpty(existsSkuMap)) { + productSkuMapper.deleteBatchIds(existsSkuMap.values()); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java index 151edbf86..0ae7359eb 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java @@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import javax.validation.Valid; @@ -42,21 +41,13 @@ public interface ProductSpuService { */ void deleteSpu(Long id); - /** - * 获得商品 SPU 详情 - * - * @param id 编号 - * @return 商品 SPU - */ - ProductSpuDetailRespVO getSpuDetail(Long id); - /** * 获得商品 SPU * * @param id 编号 * @return 商品 SPU */ - ProductSpuRespVO getSpu(Long id); + ProductSpuDO getSpu(Long id); /** * 获得商品 SPU 列表 @@ -89,15 +80,16 @@ public interface ProductSpuService { * @param pageReqVO 分页查询 * @return 商品spu分页 */ - PageResult getSpuPage(ProductSpuPageReqVO pageReqVO); + PageResult getSpuPage(ProductSpuPageReqVO pageReqVO); /** * 获得商品 SPU 分页 * * @param pageReqVO 分页查询 - * @return 商品spu分页 + * @param status 状态 + * @return 商品 SPU 分页 */ - PageResult getSpuPage(AppSpuPageReqVO pageReqVO); + PageResult getSpuPage(AppProductSpuPageReqVO pageReqVO, Integer status); /** * 更新商品 SPU 库存(增量) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index 4880d4948..0dd9cdf55 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -1,28 +1,19 @@ package cn.iocoder.yudao.module.product.service.spu; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -30,11 +21,15 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; -import java.util.stream.Collectors; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR; /** * 商品 SPU Service 实现类 @@ -48,68 +43,85 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Resource private ProductSpuMapper productSpuMapper; - @Resource - private ProductCategoryService categoryService; - @Resource @Lazy // 循环依赖,避免报错 private ProductSkuService productSkuService; @Resource - private ProductPropertyService productPropertyService; - @Resource - private ProductPropertyValueService productPropertyValueService; - @Resource private ProductBrandService brandService; + @Resource + private ProductCategoryService categoryService; @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public Long createSpu(ProductSpuCreateReqVO createReqVO) { // 校验分类 - categoryService.validateCategoryLevel(createReqVO.getCategoryId()); + validateCategory(createReqVO.getCategoryId()); // 校验品牌 brandService.validateProductBrand(createReqVO.getBrandId()); // 校验SKU - List skuCreateReqList = createReqVO.getSkus(); - productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType()); + List skuSaveReqList = createReqVO.getSkus(); + productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); + // 插入 SPU ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); - spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - spu.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - spu.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); + initSpuFromSkus(spu, skuSaveReqList); productSpuMapper.insert(spu); // 插入 SKU - productSkuService.createSkus(spu.getId(), skuCreateReqList); + productSkuService.createSkuList(spu.getId(), spu.getName(), skuSaveReqList); // 返回 return spu.getId(); } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateSpu(ProductSpuUpdateReqVO updateReqVO) { // 校验 SPU 是否存在 validateSpuExists(updateReqVO.getId()); // 校验分类 - categoryService.validateCategoryLevel(updateReqVO.getCategoryId()); + validateCategory(updateReqVO.getCategoryId()); // 校验品牌 brandService.validateProductBrand(updateReqVO.getBrandId()); // 校验SKU - List skuCreateReqList = updateReqVO.getSkus(); - productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType()); + List skuSaveReqList = updateReqVO.getSkus(); + productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType()); // 更新 SPU ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); - updateObj.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - updateObj.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - updateObj.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); + initSpuFromSkus(updateObj, skuSaveReqList); productSpuMapper.updateById(updateObj); // 批量更新 SKU - productSkuService.updateSkus(updateObj.getId(), updateReqVO.getSkus()); + productSkuService.updateSkuList(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus()); + } + + /** + * 基于 SKU 的信息,初始化 SPU 的信息 + * 主要是计数相关的字段,例如说市场价、最大最小价、库存等等 + * + * @param spu 商品 SPU + * @param skus 商品 SKU 数组 + */ + private void initSpuFromSkus(ProductSpuDO spu, List skus) { + spu.setMarketPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); + spu.setMaxPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice)); + spu.setMinPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice)); + spu.setTotalStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); + } + + /** + * 校验商品分类是否合法 + * + * @param id 商品分类编号 + */ + private void validateCategory(Long id) { + categoryService.validateCategory(id); + // 校验层级 + if (categoryService.getCategoryLevel(id) != 3) { + throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR); + } } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteSpu(Long id) { // 校验存在 validateSpuExists(id); @@ -126,48 +138,8 @@ public class ProductSpuServiceImpl implements ProductSpuService { } @Override - // TODO @芋艿:需要再 review 下 - public ProductSpuDetailRespVO getSpuDetail(Long id) { - ProductSpuDO spu = productSpuMapper.selectById(id); - ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class); - if (null != spu) { - List skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkusBySpuId(id)); - respVO.setSkus(skuReqs); - // 组合 sku 规格属性 - if (spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { - List properties = new ArrayList<>(); - for (ProductSpuDetailRespVO.Sku productSkuRespVO : skuReqs) { - properties.addAll(productSkuRespVO.getProperties()); - } - Map> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId)); - - List propertyValueList = productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyMaps.keySet())); - List propertyList = productPropertyService.getPropertyList(new ArrayList<>(propertyMaps.keySet())); - // 装载组装过后的属性 - List productPropertyViews = new ArrayList<>(); - propertyList.forEach(p -> { - ProductPropertyViewRespVO productPropertyViewRespVO = new ProductPropertyViewRespVO(); - productPropertyViewRespVO.setPropertyId(p.getId()); - productPropertyViewRespVO.setName(p.getName()); - List propertyValues = new ArrayList<>(); - // 转换成map是为了能快速获取 - Map propertyValueMaps = CollectionUtils.convertMap(propertyValueList, ProductPropertyValueRespVO::getId); - propertyMaps.get(p.getId()).forEach(pv -> { - ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName()); - propertyValues.add(tuple2); - }); - productPropertyViewRespVO.setPropertyValues(propertyValues.stream().distinct().collect(Collectors.toList())); - productPropertyViews.add(productPropertyViewRespVO); - }); - respVO.setProductPropertyViews(productPropertyViews); - } - } - return respVO; - } - - @Override - public ProductSpuRespVO getSpu(Long id) { - return ProductSpuConvert.INSTANCE.convert(productSpuMapper.selectById(id)); + public ProductSpuDO getSpu(Long id) { + return productSpuMapper.selectById(id); } @Override @@ -181,32 +153,22 @@ public class ProductSpuServiceImpl implements ProductSpuService { } @Override - public PageResult getSpuPage(ProductSpuPageReqVO pageReqVO) { + public PageResult getSpuPage(ProductSpuPageReqVO pageReqVO) { // 库存告警的 SPU 编号的集合 Set alarmStockSpuIds = null; if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) { - alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkusByAlarmStock(), ProductSkuDO::getSpuId); + alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId); if (CollUtil.isEmpty(alarmStockSpuIds)) { return PageResult.empty(); } } // 分页查询 - return ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds)); + return productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds); } @Override - public PageResult getSpuPage(AppSpuPageReqVO pageReqVO) { - // TODO 芋艿:貌似实现不太合理 - PageResult productSpuDOPageResult = productSpuMapper.selectPage(ProductSpuConvert.INSTANCE.convert(pageReqVO)); - PageResult pageResult = new PageResult<>(); - // TODO @芋艿 这里用convert如何解决 - List collect = productSpuDOPageResult.getList() - .stream() - .map(ProductSpuConvert.INSTANCE::convertAppResp) - .collect(Collectors.toList()); - pageResult.setList(collect); - pageResult.setTotal(productSpuDOPageResult.getTotal()); - return pageResult; + public PageResult getSpuPage(AppProductSpuPageReqVO pageReqVO, Integer status) { + return productSpuMapper.selectPage(pageReqVO, status); } @Override diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java index a6f8132ab..1b5c68ba4 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java @@ -15,7 +15,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -107,7 +107,7 @@ public class ProductBrandServiceImplTest extends BaseDbUnitTest { ProductBrandDO dbBrand = randomPojo(ProductBrandDO.class, o -> { // 等会查询到 o.setName("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2022, 2, 1)); + o.setCreateTime(buildTime(2022, 2, 1)); }); brandMapper.insert(dbBrand); // 测试 name 不匹配 @@ -115,12 +115,12 @@ public class ProductBrandServiceImplTest extends BaseDbUnitTest { // 测试 status 不匹配 brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(buildLocalDateTime(2022, 3, 1)))); + brandMapper.insert(cloneIgnoreId(dbBrand, o -> o.setCreateTime(buildTime(2022, 3, 1)))); // 准备参数 ProductBrandPageReqVO reqVO = new ProductBrandPageReqVO(); reqVO.setName("芋道"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2022, 1, 1), buildLocalDateTime(2022, 2, 25)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 2, 25)})); // 调用 PageResult pageResult = brandService.getBrandPage(reqVO); diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java index a56c1aa1a..a2963d498 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java @@ -103,6 +103,25 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); } + @Test + public void testGetCategoryLevel() { + // mock 数据 + ProductCategoryDO category1 = randomPojo(ProductCategoryDO.class, + o -> o.setParentId(ProductCategoryDO.PARENT_ID_NULL)); + productCategoryMapper.insert(category1); + ProductCategoryDO category2 = randomPojo(ProductCategoryDO.class, + o -> o.setParentId(category1.getId())); + productCategoryMapper.insert(category2); + ProductCategoryDO category3 = randomPojo(ProductCategoryDO.class, + o -> o.setParentId(category2.getId())); + productCategoryMapper.insert(category3); + + // 调用,并断言 + assertEquals(productCategoryService.getCategoryLevel(category1.getId()), 1); + assertEquals(productCategoryService.getCategoryLevel(category2.getId()), 2); + assertEquals(productCategoryService.getCategoryLevel(category3.getId()), 3); + } + @Test public void testGetCategoryList() { // mock 数据 diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java index 87ce87015..ec088cfdd 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.product.service.sku; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.framework.test.core.util.AssertUtils; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; @@ -13,11 +15,16 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; +import java.util.Arrays; +import java.util.List; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.verify; @@ -42,6 +49,50 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @MockBean private ProductPropertyValueService productPropertyValueService; + @Test + public void testUpdateSkuList() { + // mock 数据 + ProductSkuDO sku01 = randomPojo(ProductSkuDO.class, o -> { // 测试更新 + o.setSpuId(1L); + o.setProperties(singletonList(new ProductSkuDO.Property(10L, 20L))); + }); + productSkuMapper.insert(sku01); + ProductSkuDO sku02 = randomPojo(ProductSkuDO.class, o -> { // 测试删除 + o.setSpuId(1L); + o.setProperties(singletonList(new ProductSkuDO.Property(10L, 30L))); + }); + productSkuMapper.insert(sku02); + // 准备参数 + Long spuId = 1L; + String spuName = "测试商品"; + List skus = Arrays.asList( + randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试更新 + o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 20L))); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }), + randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试新增 + o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(10L, 40L))); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + }) + ); + + // 调用 + productSkuService.updateSkuList(spuId, spuName, skus); + // 断言 + List dbSkus = productSkuMapper.selectListBySpuId(spuId); + assertEquals(dbSkus.size(), 2); + // 断言更新的 + assertEquals(dbSkus.get(0).getId(), sku01.getId()); + assertPojoEquals(dbSkus.get(0), skus.get(0), "properties"); + assertEquals(skus.get(0).getProperties().size(), 1); + assertPojoEquals(dbSkus.get(0).getProperties().get(0), skus.get(0).getProperties().get(0)); + // 断言新增的 + assertNotEquals(dbSkus.get(1).getId(), sku02.getId()); + assertPojoEquals(dbSkus.get(1), skus.get(1), "properties"); + assertEquals(skus.get(1).getProperties().size(), 1); + assertPojoEquals(dbSkus.get(1).getProperties().get(0), skus.get(1).getProperties().get(0)); + } + @Test public void testUpdateSkuStock_incrSuccess() { // 准备参数 @@ -95,4 +146,26 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { SKU_STOCK_NOT_ENOUGH); } + @Test + public void testDeleteSku_success() { + // mock 数据 + ProductSkuDO dbSku = randomPojo(ProductSkuDO.class); + productSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbSku.getId(); + + // 调用 + productSkuService.deleteSku(id); + // 校验数据不存在了 + assertNull(productSkuMapper.selectById(id)); + } + + @Test + public void testDeleteSku_notExists() { + // 准备参数 + Long id = 1L; + + // 调用, 并断言异常 + assertServiceException(() -> productSkuService.deleteSku(id), SKU_NOT_EXISTS); + } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java deleted file mode 100755 index 1f04e9d35..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/SkuServiceImplTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package cn.iocoder.yudao.module.product.service.sku; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; -import static org.junit.jupiter.api.Assertions.assertNull; - -// TODO 芋艿:整合到 {@link ProductSkuServiceTest} 中 -/** -* {@link ProductSkuServiceImpl} 的单元测试类 -* -* @author 芋道源码 -*/ -@Import(ProductSkuServiceImpl.class) -@Disabled // TODO 芋艿:临时去掉 -public class SkuServiceImplTest extends BaseDbUnitTest { - - @Resource - private ProductSkuServiceImpl ProductSkuService; - - @Resource - private ProductSkuMapper ProductSkuMapper; - - @Test - public void testDeleteSku_success() { - // mock 数据 - ProductSkuDO dbSku = randomPojo(ProductSkuDO.class); - ProductSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbSku.getId(); - - // 调用 - ProductSkuService.deleteSku(id); - // 校验数据不存在了 - assertNull(ProductSkuMapper.selectById(id)); - } - - @Test - public void testDeleteSku_notExists() { - // 准备参数 - Long id = 1L; - - // 调用, 并断言异常 - assertServiceException(() -> ProductSkuService.deleteSku(id), SKU_NOT_EXISTS); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index c6408d965..1e029570c 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -8,12 +8,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; -import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; @@ -94,9 +94,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuDO productSpuDO = productSpuMapper.selectById(spu); createReqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); +// createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); +// createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); +// createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); assertPojoEquals(createReqVO, productSpuDO); @@ -118,9 +118,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { List skuCreateReqList = reqVO.getSkus(); reqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); - reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); +// reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); +// reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); +// reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); // 校验是否更新正确 ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的 @@ -149,60 +149,13 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId())); } - @Test - void getSpuDetail() { - // 准备spu参数 - ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o -> { - o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType()); - }); - productSpuMapper.insert(createReqVO); - - // 创建两个属性 - ArrayList productPropertyRespVOS = Lists.newArrayList( - randomPojo(ProductPropertyRespVO.class), - randomPojo(ProductPropertyRespVO.class)); - - // 所有属性值 - ArrayList productPropertyValueRespVO = new ArrayList<>(); - - // 每个属性创建属性值 - productPropertyRespVOS.forEach(v -> { - ProductPropertyValueRespVO productPropertyValueRespVO1 = randomPojo(ProductPropertyValueRespVO.class, o -> o.setPropertyId(v.getId())); - productPropertyValueRespVO.add(productPropertyValueRespVO1); - }); - - // 属性值建立笛卡尔积 - Map> collect = productPropertyValueRespVO.stream().collect(Collectors.groupingBy(ProductPropertyValueRespVO::getPropertyId)); - List> lists = cartesianProduct(Lists.newArrayList(collect.values())); - - // 准备sku参数 - ArrayList productSkuDOS = Lists.newArrayList(); - lists.forEach(pp -> { - List property = pp.stream().map(ppv -> new ProductSkuDO.Property(ppv.getPropertyId(), ppv.getId())).collect(Collectors.toList()); - ProductSkuDO productSkuDO = randomPojo(ProductSkuDO.class, o -> { - o.setProperties(property); - }); - productSkuDOS.add(productSkuDO); - - }); - - Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS); - Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO); - Mockito.when(productPropertyService.getPropertyList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS); - - // 调用 - ProductSpuDetailRespVO spuDetail = productSpuService.getSpuDetail(createReqVO.getId()); - - assertPojoEquals(createReqVO, spuDetail); - } - @Test void getSpu() { // 准备参数 ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class); productSpuMapper.insert(createReqVO); - ProductSpuRespVO spu = productSpuService.getSpu(createReqVO.getId()); + ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId()); assertPojoEquals(createReqVO, spu); } @@ -223,7 +176,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); productSpuPageReqVO.setAlarmStock(true); - PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); + PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); PageResult result = PageResult.empty(); Assertions.assertIterableEquals(result.getList(), spuPage.getList()); @@ -267,12 +220,12 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { o.setSpuId(createReqVO.getId()); })); - Mockito.when(productSkuService.getSkusByAlarmStock()).thenReturn(productSpuDOS); + Mockito.when(productSkuService.getSkuListByAlarmStock()).thenReturn(productSpuDOS); // 调用 ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); productSpuPageReqVO.setAlarmStock(true); - PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); + PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); PageResult result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds)); Assertions.assertIterableEquals(result.getList(), spuPage.getList()); @@ -324,7 +277,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); productSpuPageReqVO.setCategoryId(categoryId); - PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); + PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); PageResult result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set) null)); assertEquals(result, spuPage); @@ -339,21 +292,21 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { productSpuMapper.insert(createReqVO); // 调用 - AppSpuPageReqVO appSpuPageReqVO = new AppSpuPageReqVO(); + AppProductSpuPageReqVO appSpuPageReqVO = new AppProductSpuPageReqVO(); appSpuPageReqVO.setCategoryId(2L); - PageResult spuPage = productSpuService.getSpuPage(appSpuPageReqVO); - - PageResult result = productSpuMapper.selectPage( - ProductSpuConvert.INSTANCE.convert(appSpuPageReqVO)); - - List collect = result.getList() - .stream() - .map(ProductSpuConvert.INSTANCE::convertAppResp) - .collect(Collectors.toList()); - - Assertions.assertIterableEquals(collect, spuPage.getList()); - assertEquals(spuPage.getTotal(), result.getTotal()); +// PageResult spuPage = productSpuService.getSpuPage(appSpuPageReqVO); +// +// PageResult result = productSpuMapper.selectPage( +// ProductSpuConvert.INSTANCE.convert(appSpuPageReqVO)); +// +// List collect = result.getList() +// .stream() +// .map(ProductSpuConvert.INSTANCE::convertAppResp) +// .collect(Collectors.toList()); +// +// Assertions.assertIterableEquals(collect, spuPage.getList()); +// assertEquals(spuPage.getTotal(), result.getTotal()); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql index fd5abeed0..9d26cc733 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql @@ -1,8 +1,7 @@ CREATE TABLE IF NOT EXISTS `product_sku` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `spu_id` bigint NOT NULL COMMENT 'spu编号', - `tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户编号', - `name` varchar DEFAULT NULL COMMENT '商品 SKU 名字', + `spu_name` varchar DEFAULT NULL COMMENT '商品 SPU 名字', `properties` varchar DEFAULT NULL COMMENT '规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]', `price` int NOT NULL DEFAULT '-1' COMMENT '销售价格,单位:分', `market_price` int DEFAULT NULL COMMENT '市场价', @@ -52,3 +51,19 @@ CREATE TABLE IF NOT EXISTS `product_spu` ( `deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除', PRIMARY KEY (`id`) ) COMMENT '商品spu'; + +CREATE TABLE IF NOT EXISTS `product_category` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号', + `parent_id` bigint DEFAULT NULL COMMENT '父分类编号', + `name` varchar(128) NOT NULL COMMENT '分类名称', + `description` varchar(128) NOT NULL COMMENT '分类描述', + `pic_url` varchar DEFAULT NULL COMMENT '分类图片', + `sort` int NOT NULL DEFAULT '0' COMMENT '排序字段', + `status` bit(1) DEFAULT NULL COMMENT '状态', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` varchar DEFAULT NULL COMMENT '创建人', + `updater` varchar DEFAULT NULL COMMENT '更新人', + `deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除', + PRIMARY KEY (`id`) +) COMMENT '商品分类'; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 7e8fadede..47ce28b4b 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -45,4 +45,16 @@ public interface ErrorCodeConstants { // ========== Price 相关 1003007000 ============ ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1003007000, "支付价格计算异常,原因:价格小于等于 0"); + // ========== 秒杀活动 1003008000 ========== + ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1003008000, "秒杀活动不存在"); + ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1003008002, "存在商品参加了其它秒杀活动"); + ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1003008003, "秒杀活动已关闭,不能修改"); + ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1003008004, "秒杀活动未关闭或未结束,不能删除"); + ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1003008005, "秒杀活动已关闭,不能重复关闭"); + ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1003008006, "秒杀活动已结束,不能关闭"); + + // ========== 秒杀时段 1003009000 ========== + ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1003009000, "秒杀时段不存在"); + ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1003009001, "秒杀时段冲突"); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponController.java index 0a6facbc9..6b086f748 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/CouponController.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; @@ -66,7 +66,7 @@ public class CouponController { } // 读取用户信息,进行拼接 Set userIds = convertSet(pageResult.getList(), CouponDO::getUserId); - Map userMap = memberUserApi.getUserMap(userIds); + Map userMap = memberUserApi.getUserMap(userIds); pageResulVO.getList().forEach(itemRespVO -> MapUtils.findAndThen(userMap, itemRespVO.getUserId(), userRespDTO -> itemRespVO.setNickname(userRespDTO.getNickname()))); return success(pageResulVO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponPageReqVO.java index 0f9fbb40e..78ef1039f 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponPageReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/coupon/CouponPageReqVO.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -26,7 +26,7 @@ public class CouponPageReqVO extends PageParam { @ApiModelProperty(value = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] createTime; + private LocalDateTime[] createTime; @ApiModelProperty(value = "用户昵称", example = "芋艿", notes = "模糊匹配") private String nickname; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java index a6c3ec6ae..8fffe4db0 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/coupon/vo/template/CouponTemplatePageReqVO.java @@ -1,8 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template; import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,8 +8,7 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import javax.validation.constraints.NotNull; -import java.util.Date; +import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -32,6 +29,6 @@ public class CouponTemplatePageReqVO extends PageParam { @ApiModelProperty(value = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private Date[] createTime; + private LocalDateTime[] createTime; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java new file mode 100644 index 000000000..5acaf7cf0 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*; +import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; +import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Api(tags = "管理后台 - 秒杀活动") +@RestController +@RequestMapping("/promotion/seckill-activity") +@Validated +public class SeckillActivityController { + + @Resource + private SeckillActivityService seckillActivityService; + + @PostMapping("/create") + @ApiOperation("创建秒杀活动") + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:create')") + public CommonResult createSeckillActivity(@Valid @RequestBody SeckillActivityCreateReqVO createReqVO) { + return success(seckillActivityService.createSeckillActivity(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新秒杀活动") + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:update')") + public CommonResult updateSeckillActivity(@Valid @RequestBody SeckillActivityUpdateReqVO updateReqVO) { + seckillActivityService.updateSeckillActivity(updateReqVO); + return success(true); + } + + @PutMapping("/close") + @ApiOperation("关闭秒杀活动") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:close')") + public CommonResult closeSeckillActivity(@RequestParam("id") Long id) { + seckillActivityService.closeSeckillActivity(id); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除秒杀活动") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:delete')") + public CommonResult deleteSeckillActivity(@RequestParam("id") Long id) { + seckillActivityService.deleteSeckillActivity(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得秒杀活动") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") + public CommonResult getSeckillActivity(@RequestParam("id") Long id) { + SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id); + if (seckillActivity == null) { + return success(null); + } + List seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id); + return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity,seckillProducts)); + } + + @GetMapping("/list") + @ApiOperation("获得秒杀活动列表") + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") + public CommonResult> getSeckillActivityList(@RequestParam("ids") Collection ids) { + List list = seckillActivityService.getSeckillActivityList(ids); + return success(SeckillActivityConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @ApiOperation("获得秒杀活动分页") + @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") + public CommonResult> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) { + PageResult pageResult = seckillActivityService.getSeckillActivityPage(pageVO); + return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult)); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillTimeController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillTimeController.java new file mode 100644 index 000000000..3cb6d4ca6 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillTimeController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO; +import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO; +import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Api(tags = "管理后台 - 秒杀时段") +@RestController +@RequestMapping("/promotion/seckill-time") +@Validated +public class SeckillTimeController { + + @Resource + private SeckillTimeService seckillTimeService; + + @PostMapping("/create") + @ApiOperation("创建秒杀时段") + @PreAuthorize("@ss.hasPermission('promotion:seckill-time:create')") + public CommonResult createSeckillTime(@Valid @RequestBody SeckillTimeCreateReqVO createReqVO) { + return success(seckillTimeService.createSeckillTime(createReqVO)); + } + + @PutMapping("/update") + @ApiOperation("更新秒杀时段") + @PreAuthorize("@ss.hasPermission('promotion:seckill-time:update')") + public CommonResult updateSeckillTime(@Valid @RequestBody SeckillTimeUpdateReqVO updateReqVO) { + seckillTimeService.updateSeckillTime(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @ApiOperation("删除秒杀时段") + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:seckill-time:delete')") + public CommonResult deleteSeckillTime(@RequestParam("id") Long id) { + seckillTimeService.deleteSeckillTime(id); + return success(true); + } + + @GetMapping("/get") + @ApiOperation("获得秒杀时段") + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) + @PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')") + public CommonResult getSeckillTime(@RequestParam("id") Long id) { + SeckillTimeDO seckillTime = seckillTimeService.getSeckillTime(id); + return success(SeckillTimeConvert.INSTANCE.convert(seckillTime)); + } + + @GetMapping("/list") + @ApiOperation("获得所有秒杀时段列表") + @PreAuthorize("@ss.hasPermission('promotion:seckill-time:query')") + public CommonResult> getSeckillTimeList() { + List list = seckillTimeService.getSeckillTimeList(); + return success(SeckillTimeConvert.INSTANCE.convertList(list)); + } +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java new file mode 100644 index 000000000..877e7553a --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +/** + * 秒杀活动 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class SeckillActivityBaseVO { + + @ApiModelProperty(value = "秒杀活动名称", required = true, example = "晚九点限时秒杀") + @NotNull(message = "秒杀活动名称不能为空") + private String name; + + @ApiModelProperty(value = "活动开始时间", required = true) + @NotNull(message = "活动开始时间不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime startTime; + + @ApiModelProperty(value = "活动结束时间", required = true) + @NotNull(message = "活动结束时间不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime endTime; + + + @ApiModel("商品") + @Data + public static class Product { + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; + + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @ApiModelProperty(value = "秒杀金额", required = true, example = "12.00") + @NotNull(message = "秒杀金额不能为空") + private Integer seckillPrice; + + @ApiModelProperty(value = "秒杀库存", example = "80") + @Min(value = 0, message = "秒杀库存需要大于等于 0") + private Integer stock; + + @ApiModelProperty(value = "每人限购", example = "10", notes = "如果为0则不限购") + @Min(value = 0, message = "每人限购需要大于等于 0") + private Integer limitBuyCount; + + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java new file mode 100644 index 000000000..58dbd0dd9 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@ApiModel("管理后台 - 秒杀活动创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO { + + @ApiModelProperty(value = "备注", example = "限时秒杀活动") + private String remark; + + @ApiModelProperty(value = "排序", required = true, example = "1") + @NotNull(message = "排序不能为空") + private Integer sort; + + @ApiModelProperty(value = "秒杀时段id", required = true, example = "1,3") + @NotEmpty(message = "参与场次不能为空") + private List timeIds; + + /** + * 商品列表 + */ + @NotEmpty(message = "商品列表不能为空") + @Valid + private List products; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityDetailRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityDetailRespVO.java new file mode 100644 index 000000000..a8a079abf --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityDetailRespVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; + +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@ApiModel("管理后台 - 秒杀活动的详细 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillActivityDetailRespVO extends SeckillActivityRespVO { + + /** + * 商品列表 + */ + private List products; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityPageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityPageReqVO.java new file mode 100644 index 000000000..34808d523 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityPageReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +@ApiModel("管理后台 - 秒杀活动分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillActivityPageReqVO extends PageParam { + + @ApiModelProperty(value = "秒杀活动名称", example = "晚九点限时秒杀") + private String name; + + @ApiModelProperty(value = "活动状态", example = "进行中") + private Integer status; + + @ApiModelProperty(value = "秒杀时段id", example = "1") + private Long timeId; + + @ApiModelProperty(value = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java new file mode 100644 index 000000000..50055f8b0 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; +import java.util.List; + +@ApiModel("管理后台 - 秒杀活动 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillActivityRespVO extends SeckillActivityBaseVO { + + @ApiModelProperty(value = "秒杀活动id", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "付款订单数", required = true, example = "1") + private Integer orderCount; + + @ApiModelProperty(value = "付款人数", required = true, example = "1") + private Integer userCount; + + @ApiModelProperty(value = "创建时间", required = true) + private LocalDateTime createTime; + + @ApiModelProperty(value = "秒杀时段id", required = true, example = "1,3") + private List timeIds; + + @ApiModelProperty(value = "排序", required = true, example = "1") + private Integer sort; + + @ApiModelProperty(value = "备注", example = "限时秒杀活动") + private String remark; + + @ApiModelProperty(value = "活动状态", example = "进行中") + private Integer status; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java new file mode 100644 index 000000000..e55739a4b --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@ApiModel("管理后台 - 秒杀活动更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO { + + @ApiModelProperty(value = "秒杀活动编号", required = true, example = "224") + @NotNull(message = "秒杀活动编号不能为空") + private Long id; + + @ApiModelProperty(value = "备注", example = "限时秒杀活动") + private String remark; + + @ApiModelProperty(value = "排序", required = true, example = "1") + @NotNull(message = "排序不能为空") + private Integer sort; + + @ApiModelProperty(value = "秒杀时段id", required = true, example = "1,3") + @NotEmpty(message = "秒杀时段id不能为空") + private List timeIds; + + /** + * 商品列表 + */ + @NotEmpty(message = "商品列表不能为空") + @Valid + private List products; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeBaseVO.java new file mode 100644 index 000000000..4fc8c8f3c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeBaseVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalTime; + +/** + * 秒杀时段 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class SeckillTimeBaseVO { + + @ApiModelProperty(value = "秒杀时段名称", required = true, example = "上午场") + @NotNull(message = "秒杀时段名称不能为空") + private String name; + + @ApiModelProperty(value = "开始时间点", required = true, example = "16:30:40") + @NotNull(message = "开始时间点不能为空") + private LocalTime startTime; + + @ApiModelProperty(value = "结束时间点", required = true, example = "16:30:40") + @NotNull(message = "结束时间点不能为空") + private LocalTime endTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeCreateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeCreateReqVO.java new file mode 100644 index 000000000..197fb8a68 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeCreateReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time; + +import lombok.*; +import io.swagger.annotations.*; + +@ApiModel("管理后台 - 秒杀时段创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillTimeCreateReqVO extends SeckillTimeBaseVO { + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimePageReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimePageReqVO.java new file mode 100644 index 000000000..b482ca34e --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimePageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalTime; + +@ApiModel("管理后台 - 秒杀时段分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillTimePageReqVO extends PageParam { + + @ApiModelProperty(value = "秒杀时段名称", example = "上午场") + private String name; + + @ApiModelProperty(value = "开始时间点", example = "16:30:40") + @DateTimeFormat(pattern = "HH:mm:ss") + private LocalTime startTime; + + @ApiModelProperty(value = "结束时间点", example = "16:30:40") + @DateTimeFormat(pattern = "HH:mm:ss") + private LocalTime endTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeRespVO.java new file mode 100644 index 000000000..632020191 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeRespVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@ApiModel("管理后台 - 秒杀时段 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillTimeRespVO extends SeckillTimeBaseVO { + + @ApiModelProperty(value = "编号", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "秒杀活动数量", required = true, example = "1") + private Integer seckillActivityCount; + + @ApiModelProperty(value = "创建时间", required = true) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeUpdateReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeUpdateReqVO.java new file mode 100644 index 000000000..72931938d --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/time/SeckillTimeUpdateReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@ApiModel("管理后台 - 秒杀时段更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillTimeUpdateReqVO extends SeckillTimeBaseVO { + + @ApiModelProperty(value = "编号", required = true, example = "1") + @NotNull(message = "编号不能为空") + private Long id; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java new file mode 100644 index 000000000..1a00fdeb6 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 秒杀活动 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface SeckillActivityConvert { + + SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class); + + SeckillProductDO convert(SeckillActivityBaseVO.Product product); + + + SeckillActivityDO convert(SeckillActivityCreateReqVO bean); + + default String map(Long[] value) { + return value.toString(); + } + + SeckillActivityDO convert(SeckillActivityUpdateReqVO bean); + + SeckillActivityRespVO convert(SeckillActivityDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + @Mappings({@Mapping(target = "products", source = "seckillProducts")}) + SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List seckillProducts); + + + /** + * 比较两个秒杀商品对象是否相等 + * + * @param productDO 数据库中的商品 + * @param productVO 前端传入的商品 + * @return 是否匹配 + */ + default boolean isEquals(SeckillProductDO productDO, SeckillActivityBaseVO.Product productVO) { + return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId()) + && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId()) + && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice()) + && ObjectUtil.equals(productDO.getStock(), productVO.getStock()) + && ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount()); + } + + /** + * 比较两个秒杀商品对象是否相等 + * + * @param productDO 商品1 + * @param productVO 商品2 + * @return 是否匹配 + */ + default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) { + return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId()) + && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId()) + && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice()) + && ObjectUtil.equals(productDO.getStock(), productVO.getStock()) + && ObjectUtil.equals(productDO.getLimitBuyCount(), productVO.getLimitBuyCount()); + + } + + default List convertList(List products, SeckillActivityDO seckillActivity) { + return CollectionUtils.convertList(products, product -> convert(product) + .setActivityId(seckillActivity.getId()).setTimeIds(seckillActivity.getTimeIds())); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckilltime/SeckillTimeConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckilltime/SeckillTimeConvert.java new file mode 100644 index 000000000..4cea7a91c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckilltime/SeckillTimeConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeRespVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO; + +/** + * 秒杀时段 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface SeckillTimeConvert { + + SeckillTimeConvert INSTANCE = Mappers.getMapper(SeckillTimeConvert.class); + + SeckillTimeDO convert(SeckillTimeCreateReqVO bean); + + SeckillTimeDO convert(SeckillTimeUpdateReqVO bean); + + SeckillTimeRespVO convert(SeckillTimeDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java new file mode 100644 index 000000000..1d3b6da27 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 秒杀活动 DO + * + * @author halfninety + */ +@TableName(value = "promotion_seckill_activity", autoResultMap = true) +@KeySequence("promotion_seckill_activity_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillActivityDO extends BaseDO { + + /** + * 秒杀活动编号 + */ + @TableId + private Long id; + /** + * 秒杀活动名称 + */ + private String name; + /** + * 活动状态 + *

+ * 枚举 {@link PromotionActivityStatusEnum 对应的类} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 活动开始时间 + */ + private LocalDateTime startTime; + /** + * 活动结束时间 + */ + private LocalDateTime endTime; + /** + * 排序 + */ + private Integer sort; + /** + * 秒杀时段 id + */ + @TableField(typeHandler = LongListTypeHandler.class) + private List timeIds; + /** + * 付款订单数 + */ + private Integer orderCount; + /** + * 付款人数 + */ + private Integer userCount; + /** + * 订单实付金额,单位:分 + */ + private Long totalPrice; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java new file mode 100644 index 000000000..3783d6dda --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +/** + * 秒杀参与商品 + * + * @author halfninety + * @TableName promotion_seckill_product + */ +@TableName(value = "promotion_seckill_product", autoResultMap = true) +@KeySequence("promotion_seckill_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillProductDO extends BaseDO { + /** + * 秒杀参与商品编号 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 秒杀活动id + */ + private Long activityId; + + /** + * 秒杀时段id + */ + @TableField(typeHandler = LongListTypeHandler.class) + private List timeIds; + + /** + * 商品id + */ + private Long spuId; + + /** + * 商品sku_id + */ + private Long skuId; + + /** + * 秒杀金额 + */ + private Integer seckillPrice; + + /** + * 秒杀库存 + */ + private Integer stock; + + /** + * 每人限购 + */ + private Integer limitBuyCount; +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckilltime/SeckillTimeDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckilltime/SeckillTimeDO.java new file mode 100644 index 000000000..df338c0e6 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckilltime/SeckillTimeDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalTime; + +/** + * 秒杀时段 DO + * + * @author 芋道源码 + */ +@TableName("promotion_seckill_time") +@KeySequence("promotion_seckill_time_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SeckillTimeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 秒杀时段名称 + */ + private String name; + /** + * 开始时间点 + */ + private LocalTime startTime; + /** + * 结束时间点 + */ + private LocalTime endTime; + /** + * 秒杀活动数量 + */ + private Integer seckillActivityCount; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java new file mode 100644 index 000000000..c01676c2a --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 秒杀活动 Mapper + * + * @author halfninety + */ +@Mapper +public interface SeckillActivityMapper extends BaseMapperX { + default PageResult selectPage(SeckillActivityPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(SeckillActivityDO::getName, reqVO.getName()) + .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime()) + .apply(ObjectUtil.isNotNull(reqVO.getTimeId()),"FIND_IN_SET(" + reqVO.getTimeId() + ",time_ids) > 0") + .orderByDesc(SeckillActivityDO::getId)); + } +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java new file mode 100644 index 000000000..a590de1a5 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; +import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * 秒杀活动商品 Mapper + * + * @author halfninety + */ +@Mapper +public interface SeckillProductMapper extends BaseMapperX { + + default List selectListByActivityId(Long id) { + return selectList(SeckillProductDO::getActivityId, id); + } + + default List selectListBySkuIds(Collection skuIds) { + return selectList(SeckillProductDO::getSkuId, skuIds); + } + + default void updateTimeIdsByActivityId(Long id, List timeIds) { + new LambdaUpdateChainWrapper<>(this) + .set(SeckillProductDO::getTimeIds, CollUtil.join(timeIds, ",")) + .eq(SeckillProductDO::getActivityId, id) + .update(); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckilltime/SeckillTimeMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckilltime/SeckillTimeMapper.java new file mode 100644 index 000000000..c34484e8c --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckilltime/SeckillTimeMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.time.LocalTime; +import java.util.Collection; +import java.util.List; + +/** + * 秒杀时段 Mapper + * + * @author halfninety + */ +@Mapper +public interface SeckillTimeMapper extends BaseMapperX { + + default List selectListByTime(LocalTime time) { + return selectList(SeckillTimeDO::getStartTime, SeckillTimeDO::getEndTime, time); + } + + default List selectListByTime(LocalTime startTime, LocalTime endTime) { + return selectList(new LambdaQueryWrapper() + .ge(SeckillTimeDO::getStartTime, startTime) + .le(SeckillTimeDO::getEndTime, endTime)); + } + + default void updateActivityCount(Collection ids, String type, Integer count) { + new LambdaUpdateChainWrapper<>(this) + .in(SeckillTimeDO::getId, ids) + .setSql("`seckill_activity_count` = `seckill_activity_count` " + type + count) + .update(); + } +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 55133cded..a573e0d9c 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper; @@ -71,7 +71,7 @@ public class CouponServiceImpl implements CouponService { Set userIds = null; if (StrUtil.isNotEmpty(pageReqVO.getNickname())) { userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()), - UserRespDTO::getId); + MemberUserRespDTO::getId); if (CollUtil.isEmpty(userIds)) { return PageResult.empty(); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java index e384d1f81..03abb061f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java @@ -265,7 +265,7 @@ public class PriceServiceImpl implements PriceService { private void calculatePriceByRewardActivity(PriceCalculateRespDTO priceCalculate, List orderItems, RewardActivityDO rewardActivity) { - // 获得最大匹配的满减送活动的规格 + // 获得最大匹配的满减送活动的规则 RewardActivityDO.Rule rule = getLastMatchRewardActivityRule(rewardActivity, orderItems); if (rule == null) { // 获取不到的情况下,记录不满足的优惠明细 @@ -288,11 +288,11 @@ public class PriceServiceImpl implements PriceService { } /** - * 获得最大匹配的满减送活动的规格 + * 获得最大匹配的满减送活动的规则 * * @param rewardActivity 满减送活动 * @param orderItems 商品项 - * @return 匹配的活动规格 + * @return 匹配的活动规则 */ private RewardActivityDO.Rule getLastMatchRewardActivityRule(RewardActivityDO rewardActivity, List orderItems) { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java new file mode 100644 index 000000000..a0ff74dc8 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; + +import java.util.*; +import javax.validation.*; + +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; + +/** + * 秒杀活动 Service 接口 + * + * @author halfninety + */ +public interface SeckillActivityService { + + /** + * 创建秒杀活动 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSeckillActivity(@Valid SeckillActivityCreateReqVO createReqVO); + + /** + * 更新秒杀活动 + * + * @param updateReqVO 更新信息 + */ + void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); + + /** + * 关闭秒杀活动 + * + * @param id 编号 + */ + void closeSeckillActivity(Long id); + + /** + * 删除秒杀活动 + * + * @param id 编号 + */ + void deleteSeckillActivity(Long id); + + /** + * 获得秒杀活动 + * + * @param id 编号 + * @return 秒杀活动 + */ + SeckillActivityDO getSeckillActivity(Long id); + + /** + * 获得秒杀活动列表 + * + * @param ids 编号 + * @return 秒杀活动列表 + */ + List getSeckillActivityList(Collection ids); + + /** + * 获得秒杀活动分页 + * + * @param pageReqVO 分页查询 + * @return 秒杀活动分页 + */ + PageResult getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO); + + /** + * 通过活动编号获取活动商品 + * + * @param id 活动编号 + * @return 活动商品列表 + */ + List getSeckillProductListByActivityId(Long id); +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java new file mode 100644 index 000000000..45581d825 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java @@ -0,0 +1,226 @@ +package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityBaseVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; +import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; +import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeService; +import cn.iocoder.yudao.module.promotion.util.PromotionUtils; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; +import static java.util.Arrays.asList; + +/** + * 秒杀活动 Service 实现类 + * + * @author halfninety + */ +@Service +@Validated +public class SeckillActivityServiceImpl implements SeckillActivityService { + @Resource + private SeckillActivityMapper seckillActivityMapper; + @Resource + private SeckillProductMapper seckillProductMapper; + @Resource + private SeckillTimeService seckillTimeService; + + @Override + public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) { + // 校验商品是否冲突 + validateSeckillActivityProductConflicts(null, createReqVO.getProducts()); + // 校验秒杀时段是否存在 + seckillTimeService.validateSeckillTimeExists(createReqVO.getTimeIds()); + + // 插入秒杀活动 + SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO) + .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime())); + seckillActivityMapper.insert(seckillActivity); + // 插入商品 + List productDOS = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), seckillActivity); + seckillProductMapper.insertBatch(productDOS); + // 更新秒杀时段的秒杀活动数量 + seckillTimeService.sekillActivityCountIncr(createReqVO.getTimeIds()); + return seckillActivity.getId(); + } + + @Override + public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) { + // 校验存在 + SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId()); + if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) { + throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED); + } + // 校验商品是否冲突 + validateSeckillActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts()); + + // 更新活动 + SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) + .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime())); + seckillActivityMapper.updateById(updateObj); + // 更新商品 + updateSeckillProduct(updateReqVO); + // 更新秒杀时段的秒杀活动数量 + updateSeckillTimeActivityCount(seckillActivity, updateReqVO.getTimeIds()); + } + + + /** + * 更新秒杀时段的秒杀活动数量 + * + * @param seckillActivity 查询出的秒杀活动 + * @param updateTimeIds 更新后的秒杀时段id列表 + */ + private void updateSeckillTimeActivityCount(SeckillActivityDO seckillActivity, List updateTimeIds) { + // 查询出 timeIds + List existsTimeIds = seckillActivity.getTimeIds(); + // 需要减少的时间段 + Collection reduceIds = CollUtil.filterNew(existsTimeIds, existsTimeId -> !updateTimeIds.contains(existsTimeId)); + // 需要添加的时间段 + updateTimeIds.removeIf(existsTimeIds::contains); + // 更新减少时间段和增加时间段 + if (CollUtil.isNotEmpty(updateTimeIds)) { + seckillTimeService.sekillActivityCountIncr(updateTimeIds); + } + if (CollUtil.isNotEmpty(reduceIds)) { + seckillTimeService.sekillActivityCountDecr(reduceIds); + } + } + + /** + * 更新秒杀商品 + * 后台查出的数据和前台查出的数据进行遍历, + * 1. 对前台数据进行遍历:如果不存在于后台的 sku 中需要新增 + * 2. 对后台数据进行遍历:如果不存在于前台的 sku 中需要删除 + * 3. 最后对当前活动商品全部更新,更新秒杀时段id列表 + * + * @param updateReqVO 更新的请求VO + */ + private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) { + List seckillProductDOS = seckillProductMapper.selectListByActivityId(updateReqVO.getId()); + List products = updateReqVO.getProducts(); + + // 计算需要删除的数据 + List deleteIds = CollectionUtils.convertList(seckillProductDOS, SeckillProductDO::getId, + seckillProductDO -> products.stream() + .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product))); + if (CollUtil.isNotEmpty(deleteIds)) { + seckillProductMapper.deleteBatchIds(deleteIds); + } + + // 计算需要新增的数据 + List newSeckillProductDOs = CollectionUtils.convertList(products, + product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId())); + newSeckillProductDOs.removeIf(product -> seckillProductDOS.stream() + .anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product))); + if (CollUtil.isNotEmpty(newSeckillProductDOs)) { + seckillProductMapper.insertBatch(newSeckillProductDOs); + } + + //全量更新当前活动商品的秒杀时段id列表(timeIds) + seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getTimeIds()); + } + + /** + * 校验商品是否冲突 + * + * @param id 秒杀活动编号 + * @param products 商品列表 + */ + private void validateSeckillActivityProductConflicts(Long id, List products) { + if (CollUtil.isEmpty(products)) { + return; + } + List seckillProductDOS = seckillProductMapper + .selectListBySkuIds(CollectionUtils.convertSet(products, SeckillActivityBaseVO.Product::getSkuId)); + if (CollUtil.isEmpty(seckillProductDOS)) { + return; + } + List seckillActivityDOS = seckillActivityMapper + .selectBatchIds(CollectionUtils.convertSet(seckillProductDOS, SeckillProductDO::getActivityId)); + if (id != null) { // 排除自己这个活动 + seckillActivityDOS.removeIf(item -> id.equals(item.getId())); + } + // 排除不满足 status 的活动 + List statuses = asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()); + seckillActivityDOS.removeIf(item -> !statuses.contains(item.getStatus())); + // 如果非空,则说明冲突 + if (CollUtil.isNotEmpty(seckillActivityDOS)) { + throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); + } + } + + @Override + public void closeSeckillActivity(Long id) { + // 校验存在 + SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id); + if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) { + throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED); + } + if (PromotionActivityStatusEnum.END.getStatus().equals(seckillActivity.getStatus())) { + throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END); + } + // 更新 + SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); + seckillActivityMapper.updateById(updateObj); + } + + @Override + public void deleteSeckillActivity(Long id) { + // 校验存在 + SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id); + List statuses = asList(PromotionActivityStatusEnum.CLOSE.getStatus(), PromotionActivityStatusEnum.END.getStatus()); + if (!statuses.contains(seckillActivity.getStatus())) { + throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END); + } + // 更新秒杀时段的秒杀活动数量 + seckillTimeService.sekillActivityCountDecr(seckillActivity.getTimeIds()); + // 删除 + seckillActivityMapper.deleteById(id); + } + + private SeckillActivityDO validateSeckillActivityExists(Long id) { + SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(id); + if (seckillActivity == null) { + throw exception(SECKILL_ACTIVITY_NOT_EXISTS); + } + return seckillActivity; + } + + @Override + public SeckillActivityDO getSeckillActivity(Long id) { + return seckillActivityMapper.selectById(id); + } + + @Override + public List getSeckillActivityList(Collection ids) { + return seckillActivityMapper.selectBatchIds(ids); + } + + @Override + public PageResult getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) { + return seckillActivityMapper.selectPage(pageReqVO); + } + + @Override + public List getSeckillProductListByActivityId(Long id) { + return seckillProductMapper.selectListByActivityId(id); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeService.java new file mode 100644 index 000000000..2e9c21249 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime; + +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 秒杀时段 Service 接口 + * + * @author halfninety + */ +public interface SeckillTimeService { + + /** + * 创建秒杀时段 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSeckillTime(@Valid SeckillTimeCreateReqVO createReqVO); + + /** + * 更新秒杀时段 + * + * @param updateReqVO 更新信息 + */ + void updateSeckillTime(@Valid SeckillTimeUpdateReqVO updateReqVO); + + /** + * 删除秒杀时段 + * + * @param id 编号 + */ + void deleteSeckillTime(Long id); + + /** + * 获得秒杀时段 + * + * @param id 编号 + * @return 秒杀时段 + */ + SeckillTimeDO getSeckillTime(Long id); + + /** + * 获得所有秒杀时段列表 + * + * @return 所有秒杀时段列表 + */ + List getSeckillTimeList(); + + /** + * 校验秒杀时段是否存在 + * + * @param timeIds 秒杀时段id集合 + */ + void validateSeckillTimeExists(Collection timeIds); + + /** + * 秒杀时段列表的秒杀活动数量加 1 + * + * @param ids 秒杀时段id列表 + */ + void sekillActivityCountIncr(Collection ids); + + + /** + * 秒杀时段列表的秒杀活动数量减 1 + * + * @param ids 秒杀时段id列表 + */ + void sekillActivityCountDecr(Collection ids); +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeServiceImpl.java new file mode 100644 index 000000000..d38183860 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckilltime/SeckillTimeServiceImpl.java @@ -0,0 +1,124 @@ +package cn.iocoder.yudao.module.promotion.service.seckill.seckilltime; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO; +import cn.iocoder.yudao.module.promotion.convert.seckill.seckilltime.SeckillTimeConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalTime; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_CONFLICTS; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS; + +/** + * 秒杀时段 Service 实现类 + * + * @author halfninety + */ +@Service +@Validated +public class SeckillTimeServiceImpl implements SeckillTimeService { + + @Resource + private SeckillTimeMapper seckillTimeMapper; + + @Override + public Long createSeckillTime(SeckillTimeCreateReqVO createReqVO) { + // 校验时间段是否冲突 + validateSeckillTimeConflict(null, createReqVO.getStartTime(), createReqVO.getEndTime()); + // 插入 + SeckillTimeDO seckillTime = SeckillTimeConvert.INSTANCE.convert(createReqVO); + seckillTimeMapper.insert(seckillTime); + // 返回 + return seckillTime.getId(); + } + + @Override + public void updateSeckillTime(SeckillTimeUpdateReqVO updateReqVO) { + // 校验存在 + this.validateSeckillTimeExists(updateReqVO.getId()); + // 校验时间段是否冲突 + validateSeckillTimeConflict(updateReqVO.getId(), updateReqVO.getStartTime(), updateReqVO.getEndTime()); + // 更新 + SeckillTimeDO updateObj = SeckillTimeConvert.INSTANCE.convert(updateReqVO); + seckillTimeMapper.updateById(updateObj); + } + + @Override + public void deleteSeckillTime(Long id) { + // 校验存在 + this.validateSeckillTimeExists(id); + // 删除 + seckillTimeMapper.deleteById(id); + } + + private void validateSeckillTimeExists(Long id) { + if (seckillTimeMapper.selectById(id) == null) { + throw exception(SECKILL_TIME_NOT_EXISTS); + } + } + + /** + * 校验时间是否存在冲突 + * + * @param startTime 开始时间 + * @param endTime 结束时间 + */ + private void validateSeckillTimeConflict(Long id, LocalTime startTime, LocalTime endTime) { + //查询开始时间,结束时间,是否在别人的时间段内 + List startTimeList = seckillTimeMapper.selectListByTime(startTime); + List endTimeList = seckillTimeMapper.selectListByTime(endTime); + //查询自己时间段内是否有时间段 + List startEndTimeList = seckillTimeMapper.selectListByTime(startTime, endTime); + if (id != null) { + //移除自己 + startTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id)); + endTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id)); + startEndTimeList.removeIf(seckillTime -> Objects.equals(seckillTime.getId(), id)); + } + if (CollUtil.isNotEmpty(startTimeList) || CollUtil.isNotEmpty(endTimeList) + || CollUtil.isNotEmpty(startEndTimeList)) { + throw exception(SECKILL_TIME_CONFLICTS); + } + } + + @Override + public SeckillTimeDO getSeckillTime(Long id) { + return seckillTimeMapper.selectById(id); + } + + @Override + public List getSeckillTimeList() { + return seckillTimeMapper.selectList(); + } + + @Override + public void validateSeckillTimeExists(Collection timeIds) { + if (CollUtil.isEmpty(timeIds)) { + throw exception(SECKILL_TIME_NOT_EXISTS); + } + if (seckillTimeMapper.selectBatchIds(timeIds).size() != timeIds.size()) { + throw exception(SECKILL_TIME_NOT_EXISTS); + } + } + + @Override + public void sekillActivityCountIncr(Collection ids) { + seckillTimeMapper.updateActivityCount(ids, "+", 1); + } + + @Override + public void sekillActivityCountDecr(Collection ids) { + seckillTimeMapper.updateActivityCount(ids, "-", 1); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java index d77e29dee..5a41563e7 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImplTest.java @@ -15,11 +15,10 @@ import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import java.util.Date; +import java.time.LocalDateTime; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -119,7 +118,7 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { o.setName("芋艿"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()); - o.setCreateTime(buildLocalDateTime(2022, 2, 2)); + o.setCreateTime(buildTime(2022, 2, 2)); }); couponTemplateMapper.insert(dbCouponTemplate); // 测试 name 不匹配 @@ -129,13 +128,13 @@ public class CouponTemplateServiceImplTest extends BaseDbUnitTest { // 测试 type 不匹配 couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setDiscountType(PromotionDiscountTypeEnum.PRICE.getType()))); // 测试 createTime 不匹配 - couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(buildLocalDateTime(2022, 1, 1)))); + couponTemplateMapper.insert(cloneIgnoreId(dbCouponTemplate, o -> o.setCreateTime(buildTime(2022, 1, 1)))); // 准备参数 CouponTemplatePageReqVO reqVO = new CouponTemplatePageReqVO(); reqVO.setName("芋艿"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()); - reqVO.setCreateTime((new Date[]{buildTime(2022, 2, 1), buildTime(2022, 2, 3)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 2, 1), buildTime(2022, 2, 3)})); // 调用 PageResult pageResult = couponTemplateService.getCouponTemplatePage(reqVO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java new file mode 100644 index 000000000..853568077 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java @@ -0,0 +1,170 @@ +package cn.iocoder.yudao.module.promotion.service.seckillactivity; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper; +import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityServiceImpl; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** +* {@link SeckillActivityServiceImpl} 的单元测试类 +* +* @author 芋道源码 +*/ +@Import(SeckillActivityServiceImpl.class) +public class SeckillActivityServiceImplTest extends BaseDbUnitTest { + + @Resource + private SeckillActivityServiceImpl seckillActivityService; + + @Resource + private SeckillActivityMapper seckillActivityMapper; + + @Test + public void testCreateSeckillActivity_success() { + // 准备参数 + SeckillActivityCreateReqVO reqVO = randomPojo(SeckillActivityCreateReqVO.class); + + // 调用 + Long seckillActivityId = seckillActivityService.createSeckillActivity(reqVO); + // 断言 + assertNotNull(seckillActivityId); + // 校验记录的属性是否正确 + SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(seckillActivityId); + assertPojoEquals(reqVO, seckillActivity); + } + + @Test + public void testUpdateSeckillActivity_success() { + // mock 数据 + SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class); + seckillActivityMapper.insert(dbSeckillActivity);// @Sql: 先插入出一条存在的数据 + // 准备参数 + SeckillActivityUpdateReqVO reqVO = randomPojo(SeckillActivityUpdateReqVO.class, o -> { + o.setId(dbSeckillActivity.getId()); // 设置更新的 ID + }); + + // 调用 + seckillActivityService.updateSeckillActivity(reqVO); + // 校验是否更新正确 + SeckillActivityDO seckillActivity = seckillActivityMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, seckillActivity); + } + + @Test + public void testUpdateSeckillActivity_notExists() { + // 准备参数 + SeckillActivityUpdateReqVO reqVO = randomPojo(SeckillActivityUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> seckillActivityService.updateSeckillActivity(reqVO), SECKILL_ACTIVITY_NOT_EXISTS); + } + + @Test + public void testDeleteSeckillActivity_success() { + // mock 数据 + SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class); + seckillActivityMapper.insert(dbSeckillActivity);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbSeckillActivity.getId(); + + // 调用 + seckillActivityService.deleteSeckillActivity(id); + // 校验数据不存在了 + assertNull(seckillActivityMapper.selectById(id)); + } + + @Test + public void testDeleteSeckillActivity_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> seckillActivityService.deleteSeckillActivity(id), SECKILL_ACTIVITY_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetSeckillActivityPage() { + // mock 数据 + SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatus(null); + o.setTimeIds(null); + o.setCreateTime(null); + }); + seckillActivityMapper.insert(dbSeckillActivity); + // 测试 name 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null))); + // 测试 status 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null))); + // 测试 timeId 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeIds(null))); + // 测试 createTime 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null))); + // 准备参数 + SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + reqVO.setTimeId(null); + reqVO.setCreateTime((new LocalDateTime[]{})); + + // 调用 + PageResult pageResult = seckillActivityService.getSeckillActivityPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetSeckillActivityList() { + // mock 数据 + SeckillActivityDO dbSeckillActivity = randomPojo(SeckillActivityDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatus(null); + o.setTimeIds(null); + o.setCreateTime(null); + }); + seckillActivityMapper.insert(dbSeckillActivity); + // 测试 name 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null))); + // 测试 status 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null))); + // 测试 timeId 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setTimeIds(null))); + // 测试 createTime 不匹配 + seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null))); + // 准备参数 +// SeckillActivityExportReqVO reqVO = new SeckillActivityExportReqVO(); +// reqVO.setName(null); +// reqVO.setStatus(null); +// reqVO.setTimeId(null); +// reqVO.setCreateTime((new Date[]{})); +// +// // 调用 +// List list = seckillActivityService.getSeckillActivityList(reqVO); +// // 断言 +// assertEquals(1, list.size()); +// assertPojoEquals(dbSeckillActivity, list.get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckilltime/SeckillTimeServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckilltime/SeckillTimeServiceImplTest.java new file mode 100644 index 000000000..e61023c66 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckilltime/SeckillTimeServiceImplTest.java @@ -0,0 +1,189 @@ +package cn.iocoder.yudao.module.promotion.service.seckilltime; + +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeCreateReqVO; +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.time.SeckillTimeUpdateReqVO; +import cn.iocoder.yudao.module.promotion.service.seckill.seckilltime.SeckillTimeServiceImpl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckilltime.SeckillTimeDO; +import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckilltime.SeckillTimeMapper; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** +* {@link SeckillTimeServiceImpl} 的单元测试类 +* +* @author 芋道源码 +*/ +@Import(SeckillTimeServiceImpl.class) +public class SeckillTimeServiceImplTest extends BaseDbUnitTest { + + @Resource + private SeckillTimeServiceImpl seckillTimeService; + + @Resource + private SeckillTimeMapper seckillTimeMapper; + + @Resource + private ObjectMapper objectMapper; + + @Test + public void testJacksonSerializ(){ + + // 准备参数 + SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class); +// ObjectMapper objectMapper = new ObjectMapper(); + try { + String string = objectMapper.writeValueAsString(reqVO); + System.out.println(string); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + + } + + @Test + public void testCreateSeckillTime_success() { + // 准备参数 + SeckillTimeCreateReqVO reqVO = randomPojo(SeckillTimeCreateReqVO.class); + + // 调用 + Long seckillTimeId = seckillTimeService.createSeckillTime(reqVO); + // 断言 + assertNotNull(seckillTimeId); + // 校验记录的属性是否正确 + SeckillTimeDO seckillTime = seckillTimeMapper.selectById(seckillTimeId); + assertPojoEquals(reqVO, seckillTime); + } + + @Test + public void testUpdateSeckillTime_success() { + // mock 数据 + SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class); + seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据 + // 准备参数 + SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class, o -> { + o.setId(dbSeckillTime.getId()); // 设置更新的 ID + }); + + // 调用 + seckillTimeService.updateSeckillTime(reqVO); + // 校验是否更新正确 + SeckillTimeDO seckillTime = seckillTimeMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, seckillTime); + } + + @Test + public void testUpdateSeckillTime_notExists() { + // 准备参数 + SeckillTimeUpdateReqVO reqVO = randomPojo(SeckillTimeUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> seckillTimeService.updateSeckillTime(reqVO), SECKILL_TIME_NOT_EXISTS); + } + + @Test + public void testDeleteSeckillTime_success() { + // mock 数据 + SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class); + seckillTimeMapper.insert(dbSeckillTime);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbSeckillTime.getId(); + + // 调用 + seckillTimeService.deleteSeckillTime(id); + // 校验数据不存在了 + assertNull(seckillTimeMapper.selectById(id)); + } + + @Test + public void testDeleteSeckillTime_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> seckillTimeService.deleteSeckillTime(id), SECKILL_TIME_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetSeckillTimePage() { + // mock 数据 +// SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到 +// o.setName(null); +// o.setStartTime(null); +// o.setEndTime(null); +// o.setCreateTime(null); +// }); +// seckillTimeMapper.insert(dbSeckillTime); +// // 测试 name 不匹配 +// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null))); +// // 测试 startTime 不匹配 +// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null))); +// // 测试 endTime 不匹配 +// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null))); +// // 测试 createTime 不匹配 +// seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null))); +// // 准备参数 +// SeckillTimePageReqVO reqVO = new SeckillTimePageReqVO(); +// reqVO.setName(null); +//// reqVO.setStartTime((new LocalTime())); +//// reqVO.setEndTime((new LocalTime[]{})); +//// reqVO.setCreateTime((new Date[]{})); +// +// // 调用 +// PageResult pageResult = seckillTimeService.getSeckillTimePage(reqVO); +// // 断言 +// assertEquals(1, pageResult.getTotal()); +// assertEquals(1, pageResult.getList().size()); +// assertPojoEquals(dbSeckillTime, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetSeckillTimeList() { + // mock 数据 + SeckillTimeDO dbSeckillTime = randomPojo(SeckillTimeDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStartTime(null); + o.setEndTime(null); + o.setCreateTime(null); + }); + seckillTimeMapper.insert(dbSeckillTime); + // 测试 name 不匹配 + seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setName(null))); + // 测试 startTime 不匹配 + seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setStartTime(null))); + // 测试 endTime 不匹配 + seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setEndTime(null))); + // 测试 createTime 不匹配 + seckillTimeMapper.insert(cloneIgnoreId(dbSeckillTime, o -> o.setCreateTime(null))); + // 准备参数 +// SeckillTimeExportReqVO reqVO = new SeckillTimeExportReqVO(); +// reqVO.setName(null); +// reqVO.setStartTime((new LocalTime[]{})); +// reqVO.setEndTime((new LocalTime[]{})); +// reqVO.setCreateTime((new Date[]{})); +// +// // 调用 +// List list = seckillTimeService.getSeckillTimeList(reqVO); +// // 断言 +// assertEquals(1, list.size()); +// assertPojoEquals(dbSeckillTime, list.get(0)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index 8725ac58f..af387ab85 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -19,7 +19,31 @@ public interface ErrorCodeConstants { ErrorCode ORDER_CREATE_SPU_NOT_FOUND = new ErrorCode(1011000005, "商品 SPU 不可售卖"); ErrorCode ORDER_CREATE_ADDRESS_NOT_FOUND = new ErrorCode(1011000006, "收货地址不存在"); + ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在"); + ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在"); + ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试"); + ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "交易订单更新支付状态失败,订单不是【未支付】状态"); + ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "交易订单更新支付状态失败,支付单编号不匹配"); + ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态"); + ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配"); + ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态"); + ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态"); + + // ========== After Sale 模块 1-011-000-000 ========== + ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); + ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1011000101, "申请退款金额错误"); + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1011000102, "订单已关闭,无法申请售后"); + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1011000103, "订单未支付,无法申请售后"); + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1011000104, "订单未发货,无法申请【退货退款】售后"); + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1011000105, "订单项已申请售后,无法重复申请"); + ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1011000106, "审批失败,售后状态不处于审批中"); + ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试"); + ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】"); + ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】"); + ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000110, "退款失败,售后单状态不是【待退款】"); + ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE = new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】"); + // ========== Cart 模块 1-011-001-000 ========== - ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1001001000, "购物车项不存在"); + ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在"); } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java new file mode 100644 index 000000000..88ea5230c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleStatusEnum.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +import static cn.hutool.core.util.ArrayUtil.firstMatch; + +/** + * 售后状态的枚举 + * + * 状态流转 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum TradeAfterSaleStatusEnum implements IntArrayValuable { + + APPLY(10,"申请中", // 【申请售后】 + "会员申请退款"), + SELLER_AGREE(20, "卖家通过", // 卖家通过售后;【商品待退货】 + "商家同意退款"), + BUYER_DELIVERY(30,"待卖家收货", // 买家已退货,等待卖家收货;【商家待收货】 + "会员填写退货物流信息"), + WAIT_REFUND(40, "等待平台退款", // 卖家已收货,等待平台退款;等待退款【等待退款】 + "商家收货"), + COMPLETE(50, "完成", // 完成退款【退款成功】 + "商家确认退款"), + + BUYER_CANCEL(61, "买家取消售后", // 【买家取消】 + "会员取消退款"), + SELLER_DISAGREE(62,"卖家拒绝", // 卖家拒绝售后;商家拒绝【商家拒绝】 + "商家拒绝退款"), + SELLER_REFUSE(63,"卖家拒绝收货", // 卖家拒绝收货,终止售后;【商家拒收货】 + "商家拒绝收货"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray(); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + /** + * 操作内容 + * + * 目的:记录售后日志的内容 + */ + private final String content; + + @Override + public int[] array() { + return ARRAYS; + } + + public static TradeAfterSaleStatusEnum valueOf(Integer status) { + return firstMatch(value -> value.getStatus().equals(status), values()); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java new file mode 100644 index 000000000..d5323aac8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleTypeEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 交易售后 - 类型 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum TradeAfterSaleTypeEnum implements IntArrayValuable { + + IN_SALE(10, "售中退款"), // 交易完成前买家申请退款 + AFTER_SALE(20, "售后退款"); // 交易完成后买家申请退款 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java new file mode 100644 index 000000000..1bbb35327 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/TradeAfterSaleWayEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.trade.enums.aftersale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 交易售后 - 方式 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeAfterSaleWayEnum implements IntArrayValuable { + + REFUND(10, "仅退款"), + RETURN_AND_REFUND(20, "退货退款"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleWayEnum::getWay).toArray(); + + /** + * 方式 + */ + private final Integer way; + /** + * 方式名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderAfterSaleStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderAfterSaleStatusEnum.java new file mode 100644 index 000000000..40402b6f8 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderAfterSaleStatusEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 交易订单 - 售后状态 + * + * @author Sin + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderAfterSaleStatusEnum implements IntArrayValuable { + + NONE(0, "未退款"), + PART(1, "部分退款"), + ALL(2, "全部退款"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderAfterSaleStatusEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java index 670651d4e..1dabec194 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.trade.enums.order; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.Arrays; + /** * 交易订单 - 关闭类型 * @@ -10,12 +13,14 @@ import lombok.RequiredArgsConstructor; */ @RequiredArgsConstructor @Getter -public enum TradeOrderCancelTypeEnum { +public enum TradeOrderCancelTypeEnum implements IntArrayValuable { PAY_TIMEOUT(10, "超时未支付"), - REFUND_CLOSE(20, "退款关闭"), + AFTER_SALE_CLOSE(20, "退款关闭"), MEMBER_CANCEL(30, "买家取消"), - PAY_ON_DELIVERY(40, "已通过货到付款交易"),; + PAY_ON_DELIVERY(40, "已通过货到付款交易"),; // TODO 芋艿:这个类型,是不是可以去掉 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray(); /** * 关闭类型 @@ -26,4 +31,9 @@ public enum TradeOrderCancelTypeEnum { */ private final String name; + @Override + public int[] array() { + return ARRAYS; + } + } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderRefundStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderDeliveryStatusEnum.java similarity index 60% rename from yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderRefundStatusEnum.java rename to yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderDeliveryStatusEnum.java index 50fd88b12..27b061e37 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderRefundStatusEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderDeliveryStatusEnum.java @@ -4,17 +4,17 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; /** - * 交易订单 - 退款状态 + * 交易订单 - 发货状态 * - * @author Sin + * @author 芋道源码 */ @RequiredArgsConstructor @Getter -public enum TradeOrderRefundStatusEnum { +public enum TradeOrderDeliveryStatusEnum { - NONE(0, "未退款"), - PART(1, "部分退款"), - ALL(2, "全部退款"); + UNDELIVERED(0, "未发货"), + DELIVERED(1, "已发货"), + RECEIVED(2, "已收货"); /** * 状态值 diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemAfterSaleStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemAfterSaleStatusEnum.java new file mode 100644 index 000000000..c4fc8a373 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemAfterSaleStatusEnum.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.trade.enums.order; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * 交易订单项 - 售后状态 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum TradeOrderItemAfterSaleStatusEnum implements IntArrayValuable { + + NONE(0, "未售后"), + APPLY(1, "售后中"), + SUCCESS(2, "已退款"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderItemAfterSaleStatusEnum::getStatus).toArray(); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + // TODO 芋艿:EXPIRED 已失效不允许申请售后 + // TODO 芋艿:PART_AFTER_SALE 部分售后 + + @Override + public int[] array() { + return ARRAYS; + } + + /** + * 判断指定状态,是否正处于【未申请】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean isNone(Integer status) { + return ObjectUtil.equals(status, NONE.getStatus()); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemRefundStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemRefundStatusEnum.java deleted file mode 100644 index 4d81ea9eb..000000000 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderItemRefundStatusEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.trade.enums.order; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * 交易订单项 - 退款状态 - * - * @author Sin - */ -@RequiredArgsConstructor -@Getter -public enum TradeOrderItemRefundStatusEnum { - - NONE(0, "未申请退款"), - APPLY(1, "申请退款"), - WAIT(2, "等待退款"), - SUCCESS(3, "退款成功"); - - /** - * 状态值 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - -} diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java index fe0a85f3d..06fc3821e 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderStatusEnum.java @@ -1,8 +1,13 @@ package cn.iocoder.yudao.module.trade.enums.order; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.Arrays; + /** * 交易订单 - 状态 * @@ -10,13 +15,17 @@ import lombok.RequiredArgsConstructor; */ @RequiredArgsConstructor @Getter -public enum TradeOrderStatusEnum { +public enum TradeOrderStatusEnum implements IntArrayValuable { - WAITING_PAYMENT(0, "待付款"), - WAIT_SHIPMENT(1, "待发货"), - ALREADY_SHIPMENT(2, "待收货"), - COMPLETED(3, "已完成"), - CANCEL(4, "已关闭"); + UNPAID(0, "待支付"), + UNDELIVERED(10, "待发货"), + DELIVERED(20, "已发货"), + COMPLETED(30, "已完成"), + CANCELED(40, "已取消"); + + // TODO 芋艿: TAKE("待核验"):虚拟订单需要核验商品 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderStatusEnum::getStatus).toArray(); /** * 状态值 @@ -27,4 +36,83 @@ public enum TradeOrderStatusEnum { */ private final String name; + @Override + public int[] array() { + return ARRAYS; + } + + // ========== 问:为什么写了很多 isXXX 和 haveXXX 的判断逻辑呢? ========== + // ========== 答:方便找到某一类判断,哪些业务正在使用 ========== + + /** + * 判断指定状态,是否正处于【未付款】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean isUnpaid(Integer status) { + return ObjectUtil.equal(UNPAID.getStatus(), status); + } + + /** + * 判断指定状态,是否正处于【待发货】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean isUndelivered(Integer status) { + return ObjectUtil.equal(UNDELIVERED.getStatus(), status); + } + + /** + * 判断指定状态,是否正处于【已发货】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean isDelivered(Integer status) { + return ObjectUtil.equals(status, DELIVERED.getStatus()); + } + + /** + * 判断指定状态,是否正处于【已取消】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean isCanceled(Integer status) { + return ObjectUtil.equals(status, CANCELED.getStatus()); + } + + /** + * 判断指定状态,是否正处于【已完成】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean isCompleted(Integer status) { + return ObjectUtil.equals(status, COMPLETED.getStatus()); + } + + /** + * 判断指定状态,是否有过【已付款】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean havePaid(Integer status) { + return ObjectUtils.equalsAny(status, UNDELIVERED.getStatus(), + DELIVERED.getStatus(), COMPLETED.getStatus()); + } + + /** + * 判断指定状态,是否有过【已发货】状态 + * + * @param status 指定状态 + * @return 是否 + */ + public static boolean haveDelivered(Integer status) { + return ObjectUtils.equalsAny(status, DELIVERED.getStatus(), COMPLETED.getStatus()); + } + } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java index c10d0065a..c8001b490 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderTypeEnum.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.trade.enums.order; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.Arrays; + /** * 交易订单 - 类型 * @@ -10,13 +13,15 @@ import lombok.RequiredArgsConstructor; */ @RequiredArgsConstructor @Getter -public enum TradeOrderTypeEnum { +public enum TradeOrderTypeEnum implements IntArrayValuable { NORMAL(0, "普通订单"), SECKILL(1, "秒杀订单"), TEAM(2, "拼团订单"), BARGAIN(3, "砍价订单"); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderTypeEnum::getType).toArray(); + /** * 类型 */ @@ -26,4 +31,9 @@ public enum TradeOrderTypeEnum { */ private final String name; + @Override + public int[] array() { + return ARRAYS; + } + } diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/refund/TradeRefundTypeEnum.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/refund/TradeRefundTypeEnum.java deleted file mode 100644 index f74b39bba..000000000 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/refund/TradeRefundTypeEnum.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.trade.enums.refund; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * 交易退款 - 申请类型 - * - * @author Sin - */ -@RequiredArgsConstructor -@Getter -public enum TradeRefundTypeEnum { - - REFUND(10, "退款"), - RETURN_AND_REFUND(20, "退货退款"); - - /** - * 状态值 - */ - private final Integer type; - /** - * 状态名 - */ - private final String name; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index d92ec23cd..4eb0164d4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -50,6 +50,10 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.http b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.http new file mode 100644 index 000000000..d1a2acaf7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.http @@ -0,0 +1,4 @@ +### 获得交易售后分页 => 成功 +GET {{baseUrl}}/trade/after-sale/page?pageNo=1&pageSize=10 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java new file mode 100644 index 000000000..f2c7b1cc1 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO; +import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Api(tags = "管理后台 - 交易售后") +@RestController +@RequestMapping("/trade/after-sale") +@Validated +@Slf4j +public class TradeAfterSaleController { + + @Resource + private TradeAfterSaleService afterSaleService; + + @Resource + private MemberUserApi memberUserApi; + @Resource + private ProductPropertyValueApi productPropertyValueApi; + + @GetMapping("/page") + @ApiOperation("获得交易售后分页") + @PreAuthorize("@ss.hasPermission('trade:after-sale:query')") + public CommonResult> getAfterSalePage(@Valid TradeAfterSalePageReqVO pageVO) { + // 查询售后 + PageResult pageResult = afterSaleService.getAfterSalePage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + + // 查询商品属性 + List propertyValueDetails = productPropertyValueApi + .getPropertyValueDetailList(TradeAfterSaleConvert.INSTANCE.convertPropertyValueIds(pageResult.getList())); + // 查询会员 + Map memberUsers = memberUserApi.getUserMap( + convertSet(pageResult.getList(), TradeAfterSaleDO::getUserId)); + return success(TradeAfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers, propertyValueDetails)); + } + + @PutMapping("/agree") + @ApiOperation("同意售后") + @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:agree')") + public CommonResult agreeAfterSale(@RequestParam("id") Long id) { + afterSaleService.agreeAfterSale(getLoginUserId(), id); + return success(true); + } + + @PutMapping("/disagree") + @ApiOperation("拒绝售后") + @PreAuthorize("@ss.hasPermission('trade:after-sale:disagree')") + public CommonResult disagreeAfterSale(@RequestBody TradeAfterSaleDisagreeReqVO confirmReqVO) { + afterSaleService.disagreeAfterSale(getLoginUserId(), confirmReqVO); + return success(true); + } + + @PutMapping("/receive") + @ApiOperation("确认收货") + @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") + public CommonResult receiveAfterSale(@RequestParam("id") Long id) { + afterSaleService.receiveAfterSale(getLoginUserId(), id); + return success(true); + } + + @PutMapping("/refuse") + @ApiOperation("确认收货") + @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") + public CommonResult refuseAfterSale(TradeAfterSaleRefuseReqVO refuseReqVO) { + afterSaleService.refuseAfterSale(getLoginUserId(), refuseReqVO); + return success(true); + } + + @PostMapping("/refund") + @ApiOperation(value = "确认退款") + @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:after-sale:refund')") + public CommonResult refundAfterSale(@RequestParam("id") Long id) { + afterSaleService.refundAfterSale(getLoginUserId(), getClientIP(), id); + return success(true); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java new file mode 100644 index 000000000..4277fadd3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleBaseVO.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** +* 交易售后 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class TradeAfterSaleBaseVO { + + @ApiModelProperty(value = "售后流水号", required = true, example = "202211190847450020500077") + @NotNull(message = "售后流水号不能为空") + private String no; + + @ApiModelProperty(value = "售后状态", required = true, example = "10", notes = "参见 TradeAfterSaleStatusEnum 枚举") + @NotNull(message = "售后状态不能为空") + private Integer status; + + @ApiModelProperty(value = "售后类型", required = true, example = "20", notes = "参见 TradeAfterSaleTypeEnum 枚举") + @NotNull(message = "售后类型不能为空") + private Integer type; + + @ApiModelProperty(value = "售后方式", required = true, example = "10", notes = "参见 TradeAfterSaleWayEnum 枚举") + @NotNull(message = "售后方式不能为空") + private Integer way; + + @ApiModelProperty(value = "用户编号", required = true, example = "30337") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @ApiModelProperty(value = "申请原因", required = true, example = "不喜欢") + @NotNull(message = "申请原因不能为空") + private String applyReason; + + @ApiModelProperty(value = "补充描述", example = "你说的对") + private String applyDescription; + + @ApiModelProperty(value = "补充凭证图片", example = "https://www.iocoder.cn/1.png") + private List applyPicUrls; + + @ApiModelProperty(value = "订单编号", required = true, example = "18078") + @NotNull(message = "订单编号不能为空") + private Long orderId; + + @ApiModelProperty(value = "订单流水号", required = true, example = "2022111917190001") + @NotNull(message = "订单流水号不能为空") + private Long orderNo; + + @ApiModelProperty(value = "订单项编号", required = true, example = "572") + @NotNull(message = "订单项编号不能为空") + private Long orderItemId; + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "2888") + @NotNull(message = "商品 SPU 编号不能为空") + private Long spuId; + + @ApiModelProperty(value = "商品 SPU 名称", required = true, example = "李四") + @NotNull(message = "商品 SPU 名称不能为空") + private String spuName; + + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "15657") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @ApiModelProperty(value = "商品图片", example = "https://www.iocoder.cn/2.png") + private String picUrl; + + @ApiModelProperty(value = "购买数量", required = true, example = "20012") + @NotNull(message = "购买数量不能为空") + private Integer count; + + @ApiModelProperty(value = "审批时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime auditTime; + + @ApiModelProperty(value = "审批人", example = "30835") + private Long auditUserId; + + @ApiModelProperty(value = "审批备注", example = "不香") + private String auditReason; + + @ApiModelProperty(value = "退款金额,单位:分", required = true, example = "18077") + @NotNull(message = "退款金额,单位:分不能为空") + private Integer refundPrice; + + @ApiModelProperty(value = "支付退款编号", example = "10271") + private Long payRefundId; + + @ApiModelProperty(value = "退款时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime refundTime; + + @ApiModelProperty(value = "退货物流公司编号", example = "10") + private Long logisticsId; + + @ApiModelProperty(value = "退货物流单号", example = "610003952009") + private String logisticsNo; + + @ApiModelProperty(value = "退货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime deliveryTime; + + @ApiModelProperty(value = "收货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime receiveTime; + + @ApiModelProperty(value = "收货备注", example = "不喜欢") + private String receiveReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java new file mode 100644 index 000000000..67baca3b7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDisagreeReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@ApiModel("管理后台 - 交易售后拒绝 Request VO") +@Data +public class TradeAfterSaleDisagreeReqVO { + + @ApiModelProperty(value = "售后编号", required = true, example = "1024") + @NotNull(message = "售后编号不能为空") + private Long id; + + @ApiModelProperty(value = "审批备注", required = true, example = "你猜") + @NotEmpty(message = "审批备注不能为空") + private String auditReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java new file mode 100644 index 000000000..628b8bc56 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSalePageReqVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel("管理后台 - 交易售后分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TradeAfterSalePageReqVO extends PageParam { + + @ApiModelProperty(value = "售后流水号", example = "202211190847450020500077", notes = "模糊匹配") + private String no; + + @ApiModelProperty(value = "售后状态", example = "10", notes = "参见 TradeAfterSaleStatusEnum 枚举") + @InEnum(value = TradeAfterSaleStatusEnum.class, message = "售后状态必须是 {value}") + private Integer status; + + @ApiModelProperty(value = "售后类型", example = "20", notes = "参见 TradeAfterSaleTypeEnum 枚举") + @InEnum(value = TradeAfterSaleTypeEnum.class, message = "售后类型必须是 {value}") + private Integer type; + + @ApiModelProperty(value = "售后方式", example = "10", notes = "参见 TradeAfterSaleWayEnum 枚举") + @InEnum(value = TradeAfterSaleWayEnum.class, message = "售后方式必须是 {value}") + private Integer way; + + @ApiModelProperty(value = "订单编号", example = "18078", notes = "模糊匹配") + private String orderNo; + + @ApiModelProperty(value = "商品 SPU 名称", example = "李四", notes = "模糊匹配") + private String spuName; + + @ApiModelProperty(value = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java new file mode 100644 index 000000000..b74d73c7c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRefuseReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@ApiModel("管理后台 - 交易售后拒绝收货 Request VO") +@Data +public class TradeAfterSaleRefuseReqVO { + + @ApiModelProperty(value = "售后编号", required = true, example = "1024") + @NotNull(message = "售后编号不能为空") + private Long id; + + @ApiModelProperty(value = "收货备注", required = true, example = "你猜") + @NotNull(message = "收货备注不能为空") + private String refuseMemo; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java new file mode 100644 index 000000000..f57676bdc --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleRespPageItemVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo; + +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; +import java.util.List; + +@ApiModel("管理后台 - 交易售后分页的每一条记录 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TradeAfterSaleRespPageItemVO extends TradeAfterSaleBaseVO { + + @ApiModelProperty(value = "售后编号", required = true, example = "27630") + private Long id; + + @ApiModelProperty(value = "创建时间", required = true) + private LocalDateTime createTime; + + /** + * 商品属性数组 + */ + private List properties; + + /** + * 用户信息 + */ + private MemberUserRespVO user; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java new file mode 100644 index 000000000..990182499 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/TradeAfterSaleLogRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@ApiModel("管理后台 - 交易售后日志 Response VO") +@Data +public class TradeAfterSaleLogRespVO { + + @ApiModelProperty(value = "编号", required = true, example = "20669") + private Long id; + + @ApiModelProperty(value = "用户编号", required = true, example = "22634") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @ApiModelProperty(value = "用户类型", required = true, example = "2") + @NotNull(message = "用户类型不能为空") + private Integer userType; + + @ApiModelProperty(value = "售后编号", required = true, example = "3023") + @NotNull(message = "售后编号不能为空") + private Long afterSaleId; + + @ApiModelProperty(value = "订单编号", required = true, example = "25870") + @NotNull(message = "订单编号不能为空") + private Long orderId; + + @ApiModelProperty(value = "订单项编号", required = true, example = "23154") + @NotNull(message = "订单项编号不能为空") + private Long orderItemId; + + @ApiModelProperty(value = "售后状态(之前)", example = "2", notes = "参见 TradeAfterSaleStatusEnum 枚举") + private Integer beforeStatus; + + @ApiModelProperty(value = "售后状态(之后)", required = true, example = "1", notes = "参见 TradeAfterSaleStatusEnum 枚举") + @NotNull(message = "售后状态(之后)不能为空") + private Integer afterStatus; + + @ApiModelProperty(value = "操作明细", required = true, example = "维权完成,退款金额:¥37776.00") + @NotNull(message = "操作明细不能为空") + private String content; + + @ApiModelProperty(value = "创建时间", required = true) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/member/package-info.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/member/package-info.java new file mode 100644 index 000000000..f874e482d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/member/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位符,可忽略 + */ +package cn.iocoder.yudao.module.trade.controller.admin.base.member; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/member/user/MemberUserRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/member/user/MemberUserRespVO.java new file mode 100644 index 000000000..4f3545a91 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/member/user/MemberUserRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.trade.controller.admin.base.member.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("管理后台 - 会员用户 Response VO") +@Data +public class MemberUserRespVO { + + @ApiModelProperty(value = "用户 ID", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "用户昵称", required = true, example = "芋道源码") + private String nickname; + + @ApiModelProperty(value = "用户头像", example = "https://www.iocoder.cn/xxx.png") + private String avatar; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/package-info.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/package-info.java new file mode 100644 index 000000000..0baa83e49 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/package-info.java @@ -0,0 +1,4 @@ +/** + * 放置该模块通用的 VO 类 + */ +package cn.iocoder.yudao.module.trade.controller.admin.base; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/product/property/ProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/product/property/ProductPropertyValueDetailRespVO.java new file mode 100644 index 000000000..b9978770c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/base/product/property/ProductPropertyValueDetailRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.trade.controller.admin.base.product.property; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("管理后台 - 商品属性值的明细 Response VO") +@Data +public class ProductPropertyValueDetailRespVO { + + @ApiModelProperty(value = "属性的编号", required = true, example = "1") + private Long propertyId; + + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色") + private String propertyName; + + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024") + private Long valueId; + + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色") + private String valueName; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http new file mode 100644 index 000000000..0bf8812b2 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.http @@ -0,0 +1,9 @@ +### 获得交易订单分页 => 成功 +GET {{baseUrl}}/trade/order/page?pageNo=1&pageSize=10 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + +### 获得交易订单分页 => 成功 +GET {{baseUrl}}/trade/order/get-detail?id=21 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java new file mode 100644 index 000000000..58f3bf318 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageItemRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Api(tags = "管理后台 - 交易订单") +@RestController +@RequestMapping("/trade/order") +@Validated +@Slf4j +public class TradeOrderController { + + @Resource + private TradeOrderService tradeOrderService; + + @Resource + private ProductPropertyValueApi productPropertyValueApi; + @Resource + private MemberUserApi memberUserApi; + + @GetMapping("/page") + @ApiOperation("获得交易订单分页") + @PreAuthorize("@ss.hasPermission('trade:order:query')") + public CommonResult> getOrderPage(TradeOrderPageReqVO reqVO) { + // 查询订单 + PageResult pageResult = tradeOrderService.getOrderPage(reqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } + // 查询订单项 + List orderItems = tradeOrderService.getOrderItemListByOrderId( + convertSet(pageResult.getList(), TradeOrderDO::getId)); + // 查询商品属性 + List propertyValueDetails = productPropertyValueApi + .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); + // 最终组合 + return success(TradeOrderConvert.INSTANCE.convertPage(pageResult, orderItems, propertyValueDetails)); + } + + @GetMapping("/get-detail") + @ApiOperation("获得交易订单详情") + @ApiImplicitParam(name = "id", value = "订单编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('trade:order:query')") + public CommonResult getOrderDetail(@RequestParam("id") Long id) { + // 查询订单 + TradeOrderDO order = tradeOrderService.getOrder(id); + // 查询订单项 + List orderItems = tradeOrderService.getOrderItemListByOrderId(id); + // 查询商品属性 + List propertyValueDetails = productPropertyValueApi + .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); + // 查询会员 + MemberUserRespDTO user = memberUserApi.getUser(order.getUserId()); + // 最终组合 + return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, propertyValueDetails, user)); + } + + @PostMapping("/delivery") + @ApiOperation("发货订单") + @PreAuthorize("@ss.hasPermission('trade:order:delivery')") + public CommonResult deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) { + tradeOrderService.deliveryOrder(getLoginUserId(), deliveryReqVO); + return success(true); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java new file mode 100755 index 000000000..1669bc1ff --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Date; + +/** +* 交易订单 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class TradeOrderBaseVO { + + // ========== 订单基本信息 ========== + + @ApiModelProperty(value = "订单编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "订单流水号", required = true, example = "1146347329394184195") + private String no; + + @ApiModelProperty(value = "创建时间", required = true, notes = "下单时间") + private Date createTime; + + @ApiModelProperty(value = "订单类型", required = true, example = "1", notes = "参见 TradeOrderTypeEnum 枚举") + private Integer type; + + @ApiModelProperty(value = "订单来源", required = true, example = "1", notes = "参见 TerminalEnum 枚举") + private Integer terminal; + + @ApiModelProperty(value = "用户编号", required = true, example = "2048") + private Long userId; + + @ApiModelProperty(value = "用户 IP", required = true, example = "127.0.0.1") + private String userIp; + + @ApiModelProperty(value = "用户备注", required = true, example = "你猜") + private String userRemark; + + @ApiModelProperty(value = "订单状态", required = true, example = "1", notes = "参见 TradeOrderStatusEnum 枚举") + private Integer status; + + @ApiModelProperty(value = "购买的商品数量", required = true, example = "10") + private Integer productCount; + + @ApiModelProperty(value = "订单完成时间") + private LocalDateTime finishTime; + + @ApiModelProperty(value = "订单取消时间") + private LocalDateTime cancelTime; + + @ApiModelProperty(value = "取消类型", example = "10", notes = "参见 TradeOrderCancelTypeEnum 枚举") + private Integer cancelType; + + @ApiModelProperty(value = "商家备注", example = "你猜一下") + private String remark; + + // ========== 价格 + 支付基本信息 ========== + + @ApiModelProperty(value = "支付订单编号", required = true, example = "1024") + private Long payOrderId; + + @ApiModelProperty(value = "是否已支付", required = true, example = "true") + private Boolean payed; + + @ApiModelProperty(value = "付款时间") + private LocalDateTime payTime; + + @ApiModelProperty(value = "支付渠道", required = true, example = "wx_lite", notes = "参见 PayChannelEnum 枚举") + private String payChannelCode; + + @ApiModelProperty(value = "商品原价(总)", required = true, example = "1000", notes = "单位:分") + private Integer originalPrice; + + @ApiModelProperty(value = "订单原价(总)", required = true, example = "1000", notes = "单位:分") + private Integer orderPrice; + + @ApiModelProperty(value = "订单优惠(总)", required = true, example = "100", notes = "单位:分") + private Integer discountPrice; + + @ApiModelProperty(value = "运费金额", required = true, example = "100", notes = "单位:分") + private Integer deliveryPrice; + + @ApiModelProperty(value = "订单调价(总)", required = true, example = "100", notes = "单位:分") + private Integer adjustPrice; + + @ApiModelProperty(value = "应付金额(总)", required = true, example = "1000", notes = "单位:分") + private Integer payPrice; + + // ========== 收件 + 物流基本信息 ========== + + @ApiModelProperty(value = "配送模板编号", example = "1024") + private Long deliveryTemplateId; + + @ApiModelProperty(value = "发货物流公司编号", example = "1024") + private Long logisticsId; + + @ApiModelProperty(value = "发货物流单号", example = "1024") + private String logisticsNo; + + @ApiModelProperty(value = "发货状态", required = true, example = "1", notes = "参见 TradeOrderDeliveryStatusEnum 枚举") + private Integer deliveryStatus; + + @ApiModelProperty(value = "发货时间") + private LocalDateTime deliveryTime; + + @ApiModelProperty(value = "收货时间") + private LocalDateTime receiveTime; + + @ApiModelProperty(value = "收件人名称", required = true, example = "张三") + private String receiverName; + + @ApiModelProperty(value = "收件人手机", required = true, example = "13800138000") + private String receiverMobile; + + @ApiModelProperty(value = "收件人地区编号", required = true, example = "110000") + private Integer receiverAreaId; + + @ApiModelProperty(value = "收件人邮编", required = true, example = "100000") + private Integer receiverPostCode; + + @ApiModelProperty(value = "收件人详细地址", required = true, example = "中关村大街 1 号") + private String receiverDetailAddress; + + // ========== 售后基本信息 ========== + + @ApiModelProperty(value = "售后状态", example = "1", notes = "参见 TradeOrderAfterSaleStatusEnum 枚举") + private Integer afterSaleStatus; + + @ApiModelProperty(value = "退款金额", required = true, example = "100", notes = "单位:分") + private Integer refundPrice; + + // ========== 营销基本信息 ========== + + @ApiModelProperty(value = "优惠劵编号", example = "1024") + private Long couponId; + + @ApiModelProperty(value = "优惠劵减免金额", required = true, example = "100", notes = "单位:分") + private Integer couponPrice; + + @ApiModelProperty(value = "积分抵扣的金额", required = true, example = "100", notes = "单位:分") + private Integer pointPrice; +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java new file mode 100644 index 000000000..e75fcacf2 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@ApiModel("管理后台 - 订单发货 Request VO") +@Data +public class TradeOrderDeliveryReqVO { + + @ApiModelProperty(name = "订单编号", required = true, example = "1024") + @NotNull(message = "订单编号不能为空") + private Long id; + + @ApiModelProperty(name = "发货物流公司编号", required = true, example = "1") + @NotNull(message = "发货物流公司编号不能为空") + private Long logisticsId; + + @ApiModelProperty(name = "发货物流单号", required = true, example = "SF123456789") + @NotEmpty(message = "发货物流单号不能为空") + private String logisticsNo; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java new file mode 100644 index 000000000..a5fe26fda --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDetailRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order.vo; + +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("管理后台 - 交易订单的详情 Response VO") +@Data +public class TradeOrderDetailRespVO extends TradeOrderBaseVO { + + @ApiModelProperty(value = "收件人地区名字", required = true, example = "上海 上海市 普陀区") + private String receiverAreaName; + + /** + * 订单项列表 + */ + private List items; + + /** + * 用户信息 + */ + private MemberUserRespVO user; + + @ApiModel("管理后台 - 交易订单的详情的订单项目") + @Data + public static class Item extends TradeOrderItemBaseVO { + + /** + * 属性数组 + */ + private List properties; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderItemBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderItemBaseVO.java new file mode 100644 index 000000000..8e55b8ea7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderItemBaseVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 交易订单项 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class TradeOrderItemBaseVO { + + // ========== 订单项基本信息 ========== + + @ApiModelProperty(value = "编号", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "用户编号", required = true, example = "1") + private Long userId; + + @ApiModelProperty(value = "订单编号", required = true, example = "1") + private Long orderId; + + // ========== 商品基本信息 ========== + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + private Long spuId; + + @ApiModelProperty(value = "商品 SPU 名称", required = true, example = "芋道源码") + private String spuName; + + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1") + private Long skuId; + + @ApiModelProperty(value = "商品图片", required = true, example = "https://www.iocoder.cn/1.png") + private String picUrl; + + @ApiModelProperty(value = "购买数量", required = true, example = "1") + private Integer count; + + // ========== 价格 + 支付基本信息 ========== + + @ApiModelProperty(value = "商品原价(总)", required = true, example = "100", notes = "单位:分") + private Integer originalPrice; + + @ApiModelProperty(value = "商品原价(单)", required = true, example = "100", notes = "单位:分") + private Integer originalUnitPrice; + + @ApiModelProperty(value = "商品优惠(总)", required = true, example = "100", notes = "单位:分") + private Integer discountPrice; + + @ApiModelProperty(value = "商品实付金额(总)", required = true, example = "100", notes = "单位:分") + private Integer payPrice; + + @ApiModelProperty(value = "子订单分摊金额(总)", required = true, example = "100", notes = "单位:分") + private Integer orderPartPrice; + + @ApiModelProperty(value = "分摊后子订单实付金额(总)", required = true, example = "100", notes = "单位:分") + private Integer orderDividePrice; + + // ========== 营销基本信息 ========== + + // TODO 芋艿:在捉摸一下 + + // ========== 售后基本信息 ========== + + @ApiModelProperty(value = "售后状态", required = true, example = "1", notes = "参见 TradeOrderItemAfterSaleStatusEnum 枚举类") + private Integer afterSaleStatus; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageItemRespVO.java new file mode 100644 index 000000000..deb71d819 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageItemRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order.vo; + +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("管理后台 - 交易订单的分页项 Response VO") +@Data +public class TradeOrderPageItemRespVO extends TradeOrderBaseVO { + + @ApiModelProperty(value = "收件人地区名字", required = true, example = "上海 上海市 普陀区") + private String receiverAreaName; + + /** + * 订单项列表 + */ + private List items; + + @ApiModel("管理后台 - 交易订单的分页项的订单项目") + @Data + public static class Item extends TradeOrderItemBaseVO { + + /** + * 属性数组 + */ + private List properties; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java new file mode 100644 index 000000000..4295d8c3d --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderPageReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.trade.controller.admin.order.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@ApiModel("管理后台 - 交易订单的分页 Request VO") +@Data +public class TradeOrderPageReqVO extends PageParam { + + @ApiModelProperty(value = "订单号", example = "88888888", notes = "模糊匹配") + private String no; + + @ApiModelProperty(value = "用户编号", example = "1024") + private Long userId; + + @ApiModelProperty(value = "用户昵称", example = "小王", notes = "模糊匹配") + private String userNickname; + + @ApiModelProperty(value = "用户手机号", example = "小王", notes = "精准匹配") + @Mobile + private String userMobile; + + @ApiModelProperty(value = "收件人名称", example = "小红", notes = "模糊匹配") + private String receiverName; + + @ApiModelProperty(value = "收件人手机", example = "1560", notes = "模糊匹配") + @Mobile + private String receiverMobile; + + @ApiModelProperty(value = "订单类型", example = "1", notes = "参见 TradeOrderTypeEnum 枚举") + private Integer type; + + @ApiModelProperty(value = "订单状态", example = "1", notes = "参见 TradeOrderStatusEnum 枚举") + @InEnum(value = TradeOrderStatusEnum.class, message = "订单状态必须是 {value}") + private Integer status; + + @ApiModelProperty(value = "支付渠道", example = "wx_lite") + private String payChannelCode; + + @ApiModelProperty(value = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java new file mode 100644 index 000000000..5c1758f3b --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Api(tags = "用户 App - 交易售后") +@RestController +@RequestMapping("/trade/after-sale") +@Validated +@Slf4j +public class AppTradeAfterSaleController { + + @Resource + private TradeAfterSaleService afterSaleService; + + @PostMapping(value = "/create") + @ApiOperation(value = "申请售后") + public CommonResult createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) { + return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO)); + } + + @PostMapping(value = "/delivery") + @ApiOperation(value = "退回货物") + public CommonResult deliveryAfterSale(@RequestBody AppTradeAfterSaleDeliveryReqVO deliveryReqVO) { + afterSaleService.deliveryAfterSale(getLoginUserId(), deliveryReqVO); + return success(true); + } + + @DeleteMapping(value = "/cancel") + @ApiOperation(value = "取消售后") + @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") + public CommonResult cancelAfterSale(@RequestParam("id") Long id) { + afterSaleService.cancelAfterSale(getLoginUserId(), id); + return success(true); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java new file mode 100644 index 000000000..b5ea83904 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleCreateReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +@ApiModel("用户 App - 交易售后创建 Request VO") +@Data +public class AppTradeAfterSaleCreateReqVO { + + @ApiModelProperty(name = "订单项编号", required = true, example = "1024") + @NotNull(message = "订单项编号不能为空") + private Long orderItemId; + + @ApiModelProperty(name = "售后方式", required = true, example = "1", notes = "对应 TradeAfterSaleWayEnum 枚举") + @NotNull(message = "售后方式不能为空") + @InEnum(value = TradeAfterSaleWayEnum.class, message = "售后方式必须是 {value}") + private Integer way; + + @ApiModelProperty(name = "退款金额", required = true, example = "100", notes = "单位:分") + @NotNull(message = "退款金额不能为空") + @Min(value = 1, message = "退款金额必须大于 0") + private Integer refundPrice; + + @ApiModelProperty(name = "申请原因", required = true, example = "1", notes = "使用数据字典枚举,对应 trade_refund_apply_reason 类型") + @NotNull(message = "申请原因不能为空") + private String applyReason; + + @ApiModelProperty(name = "补充描述", example = "商品质量不好") + private String applyDescription; + + @ApiModelProperty(name = "补充凭证图片", example = "https://www.iocoder.cn/1.png, https://www.iocoder.cn/2.png") + private List applyPicUrls; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java new file mode 100644 index 000000000..c59d00034 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppTradeAfterSaleDeliveryReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@ApiModel("用户 App - 交易售后退回货物 Request VO") +@Data +public class AppTradeAfterSaleDeliveryReqVO { + + @ApiModelProperty(name = "售后编号", required = true, example = "1024") + @NotNull(message = "售后编号不能为空") + private Long id; + + @ApiModelProperty(name = "退货物流公司编号", required = true, example = "1") + @NotNull(message = "退货物流公司编号不能为空") + private Long logisticsId; + + @ApiModelProperty(name = "退货物流单号", required = true, example = "SF123456789") + @NotNull(message = "退货物流单号不能为空") + private String logisticsNo; + + @ApiModelProperty(name = "退货时间", required = true) + @NotEmpty(message = "退货时间不能为空") + private LocalDateTime deliveryTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/property/AppProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/property/AppProductPropertyValueDetailRespVO.java index e116f5888..bd5543b5f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/property/AppProductPropertyValueDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/property/AppProductPropertyValueDetailRespVO.java @@ -4,7 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -@ApiModel("用户 App - 规格 + 规格值 Response VO") +@ApiModel("用户 App - 商品属性值的明细 Response VO") @Data public class AppProductPropertyValueDetailRespVO { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java index ed666a9c8..e95b261d2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java @@ -27,7 +27,7 @@ public class AppProductSkuBaseRespVO { private Integer stock; /** - * 规格数组 + * 属性数组 */ private List properties; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http index 778e99029..8e7746359 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http @@ -8,24 +8,30 @@ GET {{shop-api-base-url}}/trade-order/confirm-create-order-info-from-cart Content-Type: application/x-www-form-urlencoded Authorization: Bearer {{user-access-token}} -### /trade-order/confirm-create-order-info-from-cart 基于商品,创建订单 -POST {{shop-api-base-url}}/trade-order/create +### /trade-order/create 基于商品,创建订单 +POST {{appApi}}/trade/order/create Content-Type: application/json -Authorization: Bearer {{user-access-token}} +Authorization: Bearer {{appToken}} +tenant-id: {{appTenentId}} { - "userAddressId": 19, + "addressId": 21, "remark": "我是备注", - "orderItems": [ + "fromCart": false, + "items": [ { - "skuId": 3, - "quantity": 1 + "skuId": 29, + "count": 1 } ] } -### /trade-order/page 获得订单交易分页 -GET {{shop-api-base-url}}/trade-order/page?status=1&pageNo=1&pageSize=10 -Content-Type: application/x-www-form-urlencoded +### 获得订单交易的分页 +GET {{appApi}}/trade/order/page?pageNo=1&pageSize=10 +Authorization: Bearer {{appToken}} +tenant-id: {{appTenentId}} -### +### 获得订单交易的详细 +GET {{appApi}}/trade/order/get-detail?id=21 +Authorization: Bearer {{appToken}} +tenant-id: {{appTenentId}} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 4233867e1..06ce965d2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -4,36 +4,46 @@ import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderGetCreateInfoRespVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.TradeOrderPageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.TradeOrderRespVO; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; +import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Api(tags = "用户 App - 交易订单") @RestController @RequestMapping("/trade/order") -@RequiredArgsConstructor // TODO @LeeYan9: 先统一使用 @Resource 注入哈; 项目只有三层, 依赖注入会存在, 所以使用 @Resource; 也因此, 最好全局保持一致 @Validated @Slf4j public class AppTradeOrderController { - private final TradeOrderService tradeOrderService; + @Resource + private TradeOrderService tradeOrderService; + + @Resource + private ProductPropertyValueApi productPropertyValueApi; @GetMapping("/get-create-info") @ApiOperation("基于商品,确认创建订单") @PreAuthenticated - public CommonResult getTradeOrderCreateInfo(AppTradeOrderCreateReqVO createReqVO) { + public CommonResult getOrderCreateInfo(AppTradeOrderCreateReqVO createReqVO) { // return success(tradeOrderService.getOrderConfirmCreateInfo(UserSecurityContextHolder.getUserId(), skuId, quantity, couponCardId)); return null; } @@ -41,29 +51,52 @@ public class AppTradeOrderController { @PostMapping("/create") @ApiOperation("创建订单") @PreAuthenticated - public CommonResult createTradeOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO, - HttpServletRequest servletRequest) { + public CommonResult createOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO, + HttpServletRequest servletRequest) { // 获取登录用户、用户 IP 地址 - Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + Long loginUserId = getLoginUserId(); String clientIp = ServletUtil.getClientIP(servletRequest); // 创建交易订单,预支付记录 - Long orderId = tradeOrderService.createTradeOrder(loginUserId, clientIp, createReqVO); - return CommonResult.success(orderId); + Long orderId = tradeOrderService.createOrder(loginUserId, clientIp, createReqVO); + return success(orderId); } - @GetMapping("/get") + @PostMapping("/update-paid") + @ApiOperation(value = "更新订单为已支付", notes = "由 pay-module 支付服务,进行回调,可见 PayNotifyJob") + public CommonResult updateOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) { + tradeOrderService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()), + notifyReqDTO.getPayOrderId()); + return success(true); + } + + @GetMapping("/get-detail") @ApiOperation("获得交易订单") - @ApiImplicitParam(name = "tradeOrderId", value = "交易订单编号", required = true, dataTypeClass = Long.class) - public CommonResult getTradeOrder(@RequestParam("tradeOrderId") Integer tradeOrderId) { -// return success(tradeOrderService.getTradeOrder(tradeOrderId)); - return null; + @ApiImplicitParam(name = "id", value = "交易订单编号", required = true, dataTypeClass = Long.class) + public CommonResult getOrder(@RequestParam("id") Long id) { + // 查询订单 + TradeOrderDO order = tradeOrderService.getOrder(getLoginUserId(), id); + // 查询订单项 + List orderItems = tradeOrderService.getOrderItemListByOrderId(order.getId()); + // 查询商品属性 + List propertyValueDetails = productPropertyValueApi + .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); + // 最终组合 + return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, propertyValueDetails)); } @GetMapping("/page") @ApiOperation("获得订单交易分页") - public CommonResult> pageTradeOrder(TradeOrderPageReqVO pageVO) { -// return success(tradeOrderService.pageTradeOrder(UserSecurityContextHolder.getUserId(), pageVO)); - return null; + public CommonResult> getOrderPage(AppTradeOrderPageReqVO reqVO) { + // 查询订单 + PageResult pageResult = tradeOrderService.getOrderPage(getLoginUserId(), reqVO); + // 查询订单项 + List orderItems = tradeOrderService.getOrderItemListByOrderId( + convertSet(pageResult.getList(), TradeOrderDO::getId)); + // 查询商品属性 + List propertyValueDetails = productPropertyValueApi + .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); + // 最终组合 + return success(TradeOrderConvert.INSTANCE.convertPage02(pageResult, orderItems, propertyValueDetails)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java index 5126de4a5..87c2919e2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; @@ -31,6 +32,7 @@ public class AppTradeOrderCreateReqVO { * 订单商品项列表 */ @NotEmpty(message = "必须选择购买的商品") + @Valid private List items; @ApiModel(value = "订单商品项") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java new file mode 100644 index 000000000..14614a57e --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java @@ -0,0 +1,150 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.vo; + +import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; + +@ApiModel("用户 App - 订单交易的明细 Response VO") +@Data +public class AppTradeOrderDetailRespVO { + + // ========== 订单基本信息 ========== + + @ApiModelProperty(value = "订单编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "订单流水号", required = true, example = "1146347329394184195") + private String no; + + @ApiModelProperty(value = "创建时间", required = true, notes = "下单时间") + private Date createTime; + + @ApiModelProperty(value = "用户备注", required = true, example = "你猜") + private String userRemark; + + @ApiModelProperty(value = "订单状态", required = true, example = "1", notes = "参见 TradeOrderStatusEnum 枚举") + private Integer status; + + @ApiModelProperty(value = "购买的商品数量", required = true, example = "10") + private Integer productCount; + + @ApiModelProperty(value = "订单完成时间") + private LocalDateTime finishTime; + + @ApiModelProperty(value = "订单取消时间") + private LocalDateTime cancelTime; + + // ========== 价格 + 支付基本信息 ========== + + @ApiModelProperty(value = "支付订单编号", required = true, example = "1024") + private Long payOrderId; + + @ApiModelProperty(value = "付款时间") + private LocalDateTime payTime; + + @ApiModelProperty(value = "商品原价(总)", required = true, example = "1000", notes = "单位:分") + private Integer originalPrice; + + @ApiModelProperty(value = "订单原价(总)", required = true, example = "1000", notes = "单位:分") + private Integer orderPrice; + + @ApiModelProperty(value = "订单优惠(总)", required = true, example = "100", notes = "单位:分") + private Integer discountPrice; + + @ApiModelProperty(value = "运费金额", required = true, example = "100", notes = "单位:分") + private Integer deliveryPrice; + + @ApiModelProperty(value = "订单调价(总)", required = true, example = "100", notes = "单位:分") + private Integer adjustPrice; + + @ApiModelProperty(value = "应付金额(总)", required = true, example = "1000", notes = "单位:分") + private Integer payPrice; + + // ========== 收件 + 物流基本信息 ========== + + @ApiModelProperty(value = "发货物流单号", example = "1024") + private String logisticsNo; + + @ApiModelProperty(value = "发货时间") + private LocalDateTime deliveryTime; + + @ApiModelProperty(value = "收货时间") + private LocalDateTime receiveTime; + + @ApiModelProperty(value = "收件人名称", required = true, example = "张三") + private String receiverName; + + @ApiModelProperty(value = "收件人手机", required = true, example = "13800138000") + private String receiverMobile; + + @ApiModelProperty(value = "收件人地区编号", required = true, example = "110000") + private Integer receiverAreaId; + + @ApiModelProperty(value = "收件人地区名字", required = true, example = "上海 上海市 普陀区") + private String receiverAreaName; + + @ApiModelProperty(value = "收件人邮编", required = true, example = "100000") + private Integer receiverPostCode; + + @ApiModelProperty(value = "收件人详细地址", required = true, example = "中关村大街 1 号") + private String receiverDetailAddress; + + // ========== 售后基本信息 ========== + + // ========== 营销基本信息 ========== + + @ApiModelProperty(value = "优惠劵编号", example = "1024") + private Long couponId; + + @ApiModelProperty(value = "优惠劵减免金额", required = true, example = "100", notes = "单位:分") + private Integer couponPrice; + + @ApiModelProperty(value = "积分抵扣的金额", required = true, example = "100", notes = "单位:分") + private Integer pointPrice; + + /** + * 订单项数组 + */ + private List items; + + @ApiModel("用户 App - 交易订单的分页项的订单项目") + @Data + public static class Item { + + @ApiModelProperty(value = "编号", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + private Long spuId; + + @ApiModelProperty(value = "商品 SPU 名称", required = true, example = "芋道源码") + private String spuName; + + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1") + private Long skuId; + + @ApiModelProperty(value = "商品图片", required = true, example = "https://www.iocoder.cn/1.png") + private String picUrl; + + @ApiModelProperty(value = "购买数量", required = true, example = "1") + private Integer count; + + @ApiModelProperty(value = "商品原价(总)", required = true, example = "100", notes = "单位:分") + private Integer originalPrice; + + @ApiModelProperty(value = "商品原价(单)", required = true, example = "100", notes = "单位:分") + private Integer originalUnitPrice; + + /** + * 属性数组 + */ + private List properties; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java index d0bf595f6..dba7fcb53 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderGetCreateInfoRespVO.java @@ -56,7 +56,7 @@ public class AppTradeOrderGetCreateInfoRespVO { */ private String picURL; // /** -// * 规格值数组 +// * 属性数组 // */ // private List attrs; // TODO 后面改下 /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java new file mode 100644 index 000000000..8815c0c39 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageItemRespVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.trade.controller.app.order.vo; + +import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("用户 App - 订单交易的分页项 Response VO") +@Data +public class AppTradeOrderPageItemRespVO { + + @ApiModelProperty(value = "订单编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "订单流水号", required = true, example = "1146347329394184195") + private String no; + + @ApiModelProperty(value = "订单状态", required = true, example = "1", notes = "参见 TradeOrderStatusEnum 枚举") + private Integer status; + + @ApiModelProperty(value = "购买的商品数量", required = true, example = "10") + private Integer productCount; + + /** + * 订单项数组 + */ + private List items; + + @ApiModel("用户 App - 交易订单的明细的订单项目") + @Data + public static class Item { + + @ApiModelProperty(value = "编号", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") + private Long spuId; + + @ApiModelProperty(value = "商品 SPU 名称", required = true, example = "芋道源码") + private String spuName; + + @ApiModelProperty(value = "商品 SKU 编号", required = true, example = "1") + private Long skuId; + + @ApiModelProperty(value = "商品图片", required = true, example = "https://www.iocoder.cn/1.png") + private String picUrl; + + @ApiModelProperty(value = "购买数量", required = true, example = "1") + private Integer count; + + @ApiModelProperty(value = "商品原价(总)", required = true, example = "100", notes = "单位:分") + private Integer originalPrice; + + @ApiModelProperty(value = "商品原价(单)", required = true, example = "100", notes = "单位:分") + private Integer originalUnitPrice; + + /** + * 属性数组 + */ + private List properties; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageReqVO.java similarity index 53% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageReqVO.java index 5c8b6c872..00d253305 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderPageReqVO.java @@ -1,17 +1,19 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import lombok.EqualsAndHashCode; +// TODO 芋艿:字段优化 @ApiModel("交易订单分页 Request VO") @Data -@EqualsAndHashCode(callSuper = true) -public class TradeOrderPageReqVO extends PageParam { +public class AppTradeOrderPageReqVO extends PageParam { @ApiModelProperty(value = "订单状态", example = "1", notes = "参见 TradeOrderStatusEnum 枚举") - private Integer orderStatus; + @InEnum(value = TradeOrderStatusEnum.class, message = "订单状态必须是 {value}") + private Integer status; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java deleted file mode 100644 index 354d8386a..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderItemRespVO.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.order.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -@ApiModel("交易订单项 Response VO") -@Data -public class TradeOrderItemRespVO { - - @ApiModelProperty(value = "id自增长", required = true) - private Integer id; - @ApiModelProperty(value = "订单编号", required = true) - private Integer orderId; - @ApiModelProperty(value = "订单项状态", required = true) - private Integer status; - @ApiModelProperty(value = "商品 SKU 编号", required = true) - private Integer skuId; - @ApiModelProperty(value = "商品 SPU 编号", required = true) - private Integer spuId; - @ApiModelProperty(value = "商品名字", required = true) - private String skuName; - @ApiModelProperty(value = "图片名字", required = true) - private String skuImage; - @ApiModelProperty(value = "商品数量", required = true) - private Integer quantity; - @ApiModelProperty(value = "原始单价,单位:分", required = true) - private Integer originPrice; - @ApiModelProperty(value = "购买单价,单位:分", required = true) - private Integer buyPrice; - @ApiModelProperty(value = "最终价格,单位:分", required = true) - private Integer presentPrice; - @ApiModelProperty(value = "购买总金额,单位:分", required = true) - private Integer buyTotal; - @ApiModelProperty(value = "优惠总金额,单位:分", required = true) - private Integer discountTotal; - @ApiModelProperty(value = "最终总金额,单位:分", required = true) - private Integer presentTotal; - @ApiModelProperty(value = "退款总金额,单位:分", required = true) - private Integer refundTotal; - @ApiModelProperty(value = "物流id") - private Integer logisticsId; - @ApiModelProperty(value = "售后状态", required = true) - private Integer afterSaleStatus; - @ApiModelProperty(value = "售后订单编号") - private Integer afterSaleOrderId; - @ApiModelProperty(value = "创建时间", required = true) - private LocalDateTime createTime; - - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java deleted file mode 100644 index 583edbabc..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/TradeOrderRespVO.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.order.vo; - -import lombok.*; -import io.swagger.annotations.*; - -import java.time.LocalDateTime; -import java.util.*; - -@ApiModel("订单交易 Response VO") -@Data -public class TradeOrderRespVO { - - @ApiModelProperty(value = "订单编号", required = true) - private Integer id; - @ApiModelProperty(value = "用户编号", required = true) - private Integer userId; - @ApiModelProperty(value = "订单单号", required = true) - private String orderNo; - @ApiModelProperty(value = "订单状态", required = true) - private Integer orderStatus; - @ApiModelProperty(value = "备注") - private String remark; - @ApiModelProperty(value = "订单结束时间") - private LocalDateTime endTime; - @ApiModelProperty(value = "订单金额(总金额),单位:分", required = true) - private Integer buyPrice; - @ApiModelProperty(value = "优惠总金额,单位:分", required = true) - private Integer discountPrice; - @ApiModelProperty(value = "物流金额,单位:分", required = true) - private Integer logisticsPrice; - @ApiModelProperty(value = "最终金额,单位:分", required = true) - private Integer presentPrice; - @ApiModelProperty(value = "支付金额,单位:分", required = true) - private Integer payPrice; - @ApiModelProperty(value = "退款金额,单位:分", required = true) - private Integer refundPrice; - @ApiModelProperty(value = "付款时间") - private LocalDateTime payTime; - @ApiModelProperty(value = "支付订单编号") - private Integer payTransactionId; - @ApiModelProperty(value = "支付渠道") - private Integer payChannel; - @ApiModelProperty(value = "配送类型", required = true) - private Integer deliveryType; - @ApiModelProperty(value = "发货时间") - private LocalDateTime deliveryTime; - @ApiModelProperty(value = "收货时间") - private LocalDateTime receiveTime; - @ApiModelProperty(value = "收件人名称", required = true) - private String receiverName; - @ApiModelProperty(value = "手机号", required = true) - private String receiverMobile; - @ApiModelProperty(value = "地区编码", required = true) - private Integer receiverAreaCode; - @ApiModelProperty(value = "收件详细地址", required = true) - private String receiverDetailAddress; - @ApiModelProperty(value = "售后状态", required = true) - private Integer afterSaleStatus; - @ApiModelProperty(value = "优惠劵编号") - private Integer couponCardId; - @ApiModelProperty(value = "创建时间", required = true) - private LocalDateTime createTime; - - /** - * 订单项数组 - * - * // TODO 芋艿,后续考虑怎么优化下,目前是内嵌了别的 dto - */ - private List orderItems; - - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/refund/TradeRefundController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/refund/TradeRefundController.java deleted file mode 100644 index aa419190e..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/refund/TradeRefundController.java +++ /dev/null @@ -1,4 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.refund; - -public class TradeRefundController { -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java new file mode 100644 index 000000000..fe1e3bd01 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.trade.convert.aftersale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.*; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +@Mapper +public interface TradeAfterSaleConvert { + + TradeAfterSaleConvert INSTANCE = Mappers.getMapper(TradeAfterSaleConvert.class); + + @Mappings({ + @Mapping(target = "id", ignore = true), + @Mapping(target = "createTime", ignore = true), + @Mapping(target = "updateTime", ignore = true), + @Mapping(target = "creator", ignore = true), + @Mapping(target = "updater", ignore = true), + }) + TradeAfterSaleDO convert(AppTradeAfterSaleCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItem); + + @Mappings({ + @Mapping(source = "afterSale.orderId", target = "merchantOrderId"), + @Mapping(source = "afterSale.applyReason", target = "reason"), + @Mapping(source = "afterSale.refundPrice", target = "amount") + }) + PayRefundCreateReqDTO convert(String userIp, TradeAfterSaleDO afterSale, + TradeOrderProperties orderProperties); + + MemberUserRespVO convert(MemberUserRespDTO bean); + + PageResult convertPage(PageResult page); + + default PageResult convertPage(PageResult pageResult, + Map memberUsers, List propertyValueDetails) { + PageResult pageVOResult = convertPage(pageResult); + // 处理会员 + 商品属性等关联信息 + Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); + for (int i = 0; i < pageResult.getList().size(); i++) { + TradeAfterSaleRespPageItemVO afterSaleVO = pageVOResult.getList().get(i); + TradeAfterSaleDO afterSaleDO = pageResult.getList().get(i); + // 会员 + afterSaleVO.setUser(convert(memberUsers.get(afterSaleDO.getUserId()))); + // 商品属性 + if (CollUtil.isNotEmpty(afterSaleDO.getProperties())) { + afterSaleVO.setProperties(new ArrayList<>(afterSaleDO.getProperties().size())); + // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中 + afterSaleDO.getProperties().forEach(property -> { + ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId()); + if (propertyValueDetail == null) { + return; + } + afterSaleVO.getProperties().add(convert(propertyValueDetail)); + }); + } + } + return pageVOResult; + } + + ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); + + default Set convertPropertyValueIds(List list) { + if (CollUtil.isEmpty(list)) { + return new HashSet<>(); + } + return list.stream().filter(item -> item.getProperties() != null) + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 + .map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 + .collect(Collectors.toSet()); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index d47dc76a1..b1f0b4b2a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -1,27 +1,40 @@ package cn.iocoder.yudao.module.trade.convert.order; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.pay.api.order.PayOrderInfoCreateReqDTO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageItemRespVO; +import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderDetailRespVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageItemRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemRefundStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; @Mapper @@ -56,7 +69,7 @@ public interface TradeOrderConvert { TradeOrderItemDO tradeOrderItemDO = convert(orderItem, skuMap.get(orderItem.getSkuId())); tradeOrderItemDO.setOrderId(tradeOrderDO.getId()); tradeOrderItemDO.setUserId(tradeOrderDO.getUserId()); - tradeOrderItemDO.setRefundStatus(TradeOrderItemRefundStatusEnum.NONE.getStatus()).setRefundTotal(0); // 退款信息 + tradeOrderItemDO.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); // 退款信息 // tradeOrderItemDO.setCommented(false); return tradeOrderItemDO; }); @@ -72,9 +85,9 @@ public interface TradeOrderConvert { ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean); List convertList(List list); - default PayOrderInfoCreateReqDTO convert(TradeOrderDO tradeOrderDO, List tradeOrderItemDOs, - List spus, TradeOrderProperties tradeOrderProperties) { - PayOrderInfoCreateReqDTO createReqDTO = new PayOrderInfoCreateReqDTO() + default PayOrderCreateReqDTO convert(TradeOrderDO tradeOrderDO, List tradeOrderItemDOs, + List spus, TradeOrderProperties tradeOrderProperties) { + PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO() .setAppId(tradeOrderProperties.getAppId()).setUserIp(tradeOrderDO.getUserIp()); // 商户相关字段 createReqDTO.setMerchantOrderId(String.valueOf(tradeOrderDO.getId())); @@ -88,4 +101,141 @@ public interface TradeOrderConvert { return createReqDTO; } + default Set convertPropertyValueIds(List list) { + if (CollUtil.isEmpty(list)) { + return new HashSet<>(); + } + return list.stream().filter(item -> item.getProperties() != null) + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 + .map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 + .collect(Collectors.toSet()); + } + + default PageResult convertPage(PageResult pageResult, List orderItems, + List propertyValueDetails) { + Map> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId); + Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); + // 转化 List + List orderVOs = CollectionUtils.convertList(pageResult.getList(), order -> { + List xOrderItems = orderItemMap.get(order.getId()); + TradeOrderPageItemRespVO orderVO = convert(order, xOrderItems); + if (CollUtil.isNotEmpty(xOrderItems)) { + // 处理商品属性 + for (int i = 0; i < xOrderItems.size(); i++) { + List properties = xOrderItems.get(i).getProperties(); + if (CollUtil.isEmpty(properties)) { + continue; + } + TradeOrderPageItemRespVO.Item item = orderVO.getItems().get(i); + item.setProperties(new ArrayList<>(properties.size())); + // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中 + properties.forEach(property -> { + ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId()); + if (propertyValueDetail == null) { + return; + } + item.getProperties().add(convert(propertyValueDetail)); + }); + } + } + // 处理收货地址 + orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId())); + return orderVO; + }); + return new PageResult<>(orderVOs, pageResult.getTotal()); + } + TradeOrderPageItemRespVO convert(TradeOrderDO order, List items); + ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); + + default TradeOrderDetailRespVO convert(TradeOrderDO order, List orderItems, + List propertyValueDetails, MemberUserRespDTO user) { + TradeOrderDetailRespVO orderVO = convert2(order, orderItems); + // 处理商品属性 + Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); + for (int i = 0; i < orderItems.size(); i++) { + List properties = orderItems.get(i).getProperties(); + if (CollUtil.isEmpty(properties)) { + continue; + } + TradeOrderDetailRespVO.Item item = orderVO.getItems().get(i); + item.setProperties(new ArrayList<>(properties.size())); + // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中 + properties.forEach(property -> { + ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId()); + if (propertyValueDetail == null) { + return; + } + item.getProperties().add(convert(propertyValueDetail)); + }); + } + // 处理收货地址 + orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId())); + // 处理用户信息 + orderVO.setUser(convert(user)); + return orderVO; + } + TradeOrderDetailRespVO convert2(TradeOrderDO order, List items); + MemberUserRespVO convert(MemberUserRespDTO bean); + + default PageResult convertPage02(PageResult pageResult, List orderItems, + List propertyValueDetails) { + Map> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId); + Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); + // 转化 List + List orderVOs = CollectionUtils.convertList(pageResult.getList(), order -> { + List xOrderItems = orderItemMap.get(order.getId()); + AppTradeOrderPageItemRespVO orderVO = convert02(order, xOrderItems); + if (CollUtil.isNotEmpty(xOrderItems)) { + // 处理商品属性 + for (int i = 0; i < xOrderItems.size(); i++) { + List properties = xOrderItems.get(i).getProperties(); + if (CollUtil.isEmpty(properties)) { + continue; + } + AppTradeOrderPageItemRespVO.Item item = orderVO.getItems().get(i); + item.setProperties(new ArrayList<>(properties.size())); + // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中 + properties.forEach(property -> { + ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId()); + if (propertyValueDetail == null) { + return; + } + item.getProperties().add(convert02(propertyValueDetail)); + }); + } + } + return orderVO; + }); + return new PageResult<>(orderVOs, pageResult.getTotal()); + } + AppTradeOrderPageItemRespVO convert02(TradeOrderDO order, List items); + AppProductPropertyValueDetailRespVO convert02(ProductPropertyValueDetailRespDTO bean); + + default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List orderItems, + List propertyValueDetails) { + AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); + // 处理商品属性 + Map propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId); + for (int i = 0; i < orderItems.size(); i++) { + List properties = orderItems.get(i).getProperties(); + if (CollUtil.isEmpty(properties)) { + continue; + } + AppTradeOrderDetailRespVO.Item item = orderVO.getItems().get(i); + item.setProperties(new ArrayList<>(properties.size())); + // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中 + properties.forEach(property -> { + ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId()); + if (propertyValueDetail == null) { + return; + } + item.getProperties().add(convert02(propertyValueDetail)); + }); + } + // 处理收货地址 + orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId())); + return orderVO; + } + AppTradeOrderDetailRespVO convert3(TradeOrderDO order, List items); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java new file mode 100644 index 000000000..1b703d9e7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleDO.java @@ -0,0 +1,201 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.aftersale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 交易售后,用于处理 {@link TradeOrderDO} 交易订单的退款退货流程 + * + * @author 芋道源码 + */ +@TableName(value = "trade_after_sale", autoResultMap = true) +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +public class TradeAfterSaleDO extends BaseDO { + + /** + * 售后编号,主键自增 + */ + private Long id; + /** + * 售后流水号 + * + * 例如说,1146347329394184195 + */ + private String no; + /** + * 退款状态 + * + * 枚举 {@link TradeAfterSaleStatusEnum} + */ + private Integer status; + /** + * 售后方式 + * + * 枚举 {@link TradeAfterSaleWayEnum} + */ + private Integer way; + /** + * 售后类型 + * + * 枚举 {@link TradeAfterSaleTypeEnum} + */ + private Integer type; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 编号 + */ + private Long userId; + /** + * 申请原因 + * + * type = 退款,对应 trade_after_sale_refund_reason 类型 + * type = 退货退款,对应 trade_after_sale_refund_and_return_reason 类型 + */ + private String applyReason; + /** + * 补充描述 + */ + private String applyDescription; + /** + * 补充凭证图片 + * + * 数组,以逗号分隔 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private List applyPicUrls; + + // ========== 交易订单相关 ========== + /** + * 交易订单编号 + * + * 关联 {@link TradeOrderDO#getId()} + */ + private Long orderId; + /** + * 订单流水号 + * + * 冗余 {@link TradeOrderDO#getNo()} + */ + private String orderNo; + /** + * 交易订单项编号 + * + * 关联 {@link TradeOrderItemDO#getId()} + */ + private Long orderItemId; + /** + * 商品 SPU 编号 + * + * 关联 ProductSpuDO 的 id 字段 + * 冗余 {@link TradeOrderItemDO#getSpuId()} + */ + private Long spuId; + /** + * 商品 SPU 名称 + * + * 关联 ProductSkuDO 的 name 字段 + * 冗余 {@link TradeOrderItemDO#getSpuName()} + */ + private String spuName; + /** + * 商品 SKU 编号 + * + * 关联 ProductSkuDO 的编号 + */ + private Long skuId; + /** + * 属性数组,JSON 格式 + * + * 冗余 {@link TradeOrderItemDO#getProperties()} + */ + @TableField(typeHandler = TradeOrderItemDO.PropertyTypeHandler.class) + private List properties; + /** + * 商品图片 + * + * 冗余 {@link TradeOrderItemDO#getPicUrl()} + */ + private String picUrl; + /** + * 退货商品数量 + */ + private Integer count; + + // ========== 审批相关 ========== + + /** + * 审批时间 + */ + private LocalDateTime auditTime; + /** + * 审批人 + * + * 关联 AdminUserDO 的 id 编号 + */ + private Long auditUserId; + /** + * 审批备注 + * + * 注意,只有审批不通过才会填写 + */ + private String auditReason; + + // ========== 退款相关 ========== + /** + * 退款金额,单位:分。 + */ + private Integer refundPrice; + /** + * 支付退款编号 + * + * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号 + */ + private Long payRefundId; + /** + * 退款时间 + */ + private LocalDateTime refundTime; + + // ========== 退货相关 ========== + /** + * 退货物流公司编号 + * + * 关联 LogisticsDO 的 id 编号 + */ + private Long logisticsId; + /** + * 退货物流单号 + */ + private String logisticsNo; + /** + * 退货时间 + */ + private LocalDateTime deliveryTime; + /** + * 收货时间 + */ + private LocalDateTime receiveTime; + /** + * 收货备注 + * + * 注意,只有拒绝收货才会填写 + */ + private String receiveReason; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java new file mode 100644 index 000000000..5aa627403 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/aftersale/TradeAfterSaleLogDO.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.trade.dal.dataobject.aftersale; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 交易售后日志 DO + * + * // TODO 可优化:参考淘宝或者有赞:1)增加 action 表示什么操作;2)content 记录每个操作的明细 + * + * @author 芋道源码 + */ +@TableName("trade_after_sale_log") +@KeySequence("trade_after_sale_log_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TradeAfterSaleLogDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 用户编号 + * + * 关联 1:AdminUserDO 的 id 字段 + * 关联 2:MemberUserDO 的 id 字段 + */ + private Long userId; + /** + * 用户类型 + * + * 枚举 {@link UserTypeEnum} + */ + private Integer userType; + /** + * 售后编号 + * + * 关联 {@link TradeAfterSaleDO#getId()} + */ + private Long afterSaleId; + /** + * 订单编号 + * + * 关联 {@link TradeOrderDO#getId()} + */ + private Long orderId; + /** + * 订单项编号 + * + * 关联 {@link TradeOrderItemDO#getId()} + */ + private Long orderItemId; + /** + * 售后状态(之前) + * + * 枚举 {@link TradeAfterSaleStatusEnum} + */ + private Integer beforeStatus; + /** + * 售后状态(之后) + * + * 枚举 {@link TradeAfterSaleStatusEnum} + */ + private Integer afterStatus; + /** + * 操作明细 + */ + private String content; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java index 4d68799b9..49d60ee37 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -4,7 +4,8 @@ import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO.OrderItem; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderDeliveryStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -44,9 +45,9 @@ public class TradeOrderDO extends BaseDO { * * 枚举 {@link TradeOrderTypeEnum} */ - private Integer type; // TODO order_promotion_type + private Integer type; /** - * 订单来源终端 + * 订单来源 * * 枚举 {@link TerminalEnum} */ @@ -71,7 +72,6 @@ public class TradeOrderDO extends BaseDO { * 枚举 {@link TradeOrderStatusEnum} */ private Integer status; - // TODO 芋艿:要不要存储 prod_name 购买的商品名门? /** * 购买的商品数量 */ @@ -96,6 +96,17 @@ public class TradeOrderDO extends BaseDO { private String remark; // ========== 价格 + 支付基本信息 ========== + + // 价格文档 - 淘宝:https://open.taobao.com/docV3.htm?docId=108471&docType=1 + // 价格文档 - 京东到家:https://openo2o.jddj.com/api/getApiDetail/182/4d1494c5e7ac4679bfdaaed950c5bc7f.htm + // 价格文档 - 有赞:https://doc.youzanyun.com/detail/API/0/906 + + /** + * 支付订单编号 + * + * 对接 pay-module-biz 支付服务的支付订单编号,即 PayOrderDO 的 id 编号 + */ + private Long payOrderId; /** * 是否已支付 * @@ -107,11 +118,12 @@ public class TradeOrderDO extends BaseDO { * 付款时间 */ private LocalDateTime payTime; - - // ========== 价格 + 支付基本信息 ========== - // 价格文档 - 淘宝:https://open.taobao.com/docV3.htm?docId=108471&docType=1 - // 价格文档 - 京东到家:https://openo2o.jddj.com/api/getApiDetail/182/4d1494c5e7ac4679bfdaaed950c5bc7f.htm - // 价格文档 - 有赞:https://doc.youzanyun.com/detail/API/0/906 + /** + * 支付渠道 + * + * 对应 PayChannelEnum 枚举 + */ + private String payChannelCode; /** * 商品原价(总),单位:分 @@ -157,18 +169,6 @@ public class TradeOrderDO extends BaseDO { * + {@link #adjustPrice} */ private Integer payPrice; - /** - * 支付订单编号 - * - * 对接 pay-module-biz 支付服务的支付订单编号,即 PayOrderDO 的 id 编号 - */ - private Long payOrderId; - /** - * 支付成功的支付渠道 - * - * 对应 PayChannelEnum 枚举 - */ - private Integer payChannel; // ========== 收件 + 物流基本信息 ========== /** @@ -178,20 +178,24 @@ public class TradeOrderDO extends BaseDO { */ private Long deliveryTemplateId; /** - * 物流公司单号 + * 发货物流公司编号 */ - private String expressNo; + private Long logisticsId; + /** + * 发货物流单号 + */ + private String logisticsNo; /** * 发货状态 * - * true - 已发货 - * false - 未发货 + * 枚举 {@link TradeOrderDeliveryStatusEnum} */ - private Boolean deliveryStatus; + private Integer deliveryStatus; /** * 发货时间 */ private LocalDateTime deliveryTime; + /** * 收货时间 */ @@ -207,7 +211,7 @@ public class TradeOrderDO extends BaseDO { /** * 收件人地区编号 */ - private Long receiverAreaId; + private Integer receiverAreaId; /** * 收件人邮编 */ @@ -217,13 +221,13 @@ public class TradeOrderDO extends BaseDO { */ private String receiverDetailAddress; - // ========== 退款基本信息 ========== + // ========== 售后基本信息 ========== /** - * 退款状态 + * 收货状态 * - * 枚举 {@link TradeOrderRefundStatusEnum} + * 枚举 {@link TradeOrderAfterSaleStatusEnum} */ - private Integer refundStatus; + private Integer afterSaleStatus; /** * 退款金额,单位:分 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java index 5dfcf4c6a..f8438030b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java @@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemRefundStatusEnum; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; @@ -10,6 +11,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.io.Serializable; import java.util.List; /** @@ -41,13 +43,19 @@ public class TradeOrderItemDO extends BaseDO { */ private Long orderId; - // ========== 商品基本信息 ========== + // ========== 商品基本信息; 冗余较多字段,减少关联查询 ========== /** * 商品 SPU 编号 * * 关联 ProductSkuDO 的 spuId 编号 */ private Long spuId; + /** + * 商品 SPU 名称 + * + * 冗余 ProductSkuDO 的 spuName 编号 + */ + private String spuName; /** * 商品 SKU 编号 * @@ -55,14 +63,12 @@ public class TradeOrderItemDO extends BaseDO { */ private Long skuId; /** - * 规格值数组,JSON 格式 + * 属性数组,JSON 格式 + * + * 冗余 ProductSkuDO 的 properties 字段 */ @TableField(typeHandler = PropertyTypeHandler.class) private List properties; - /** - * 商品名称 - */ - private String name; /** * 商品图片 */ @@ -132,32 +138,23 @@ public class TradeOrderItemDO extends BaseDO { // ========== 营销基本信息 ========== - // ========== 退款基本信息 ========== + // TODO 芋艿:在捉摸一下 + + // ========== 售后基本信息 ========== /** - * 退款状态 TODO + * 售后状态 * - * 枚举 {@link TradeOrderItemRefundStatusEnum} + * 枚举 {@link TradeOrderItemAfterSaleStatusEnum} + * + * @see TradeAfterSaleDO */ - private Integer refundStatus; // TODO 芋艿:可以考虑去查 - // 如上字段,举个例子: - // 假设购买三个,即 stock = 3 。 - // originPrice = 15 - // 使用限时折扣(单品优惠)8 折,buyPrice = 12 - // 开始算总的价格 - // buyTotal = buyPrice * stock = 12 * 3 = 36 - // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11 - // presentTotal = buyTotal - discountTotal = 24 - 11 = 13 - // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33 - /** - * 退款总金额,单位:分 TODO - */ - private Integer refundTotal; + private Integer afterSaleStatus; /** * 商品属性 */ @Data - public static class Property { + public static class Property implements Serializable { /** * 属性编号 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/refund/TradeRefundDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/refund/TradeRefundDO.java deleted file mode 100644 index d052d4dd3..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/refund/TradeRefundDO.java +++ /dev/null @@ -1,148 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.dataobject.refund; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; -import cn.iocoder.yudao.module.trade.enums.refund.TradeRefundTypeEnum; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 交易退款,用于处理 {@link TradeOrderDO} 交易订单的退货换流程 - */ -// TODO 芋艿:需要调整下每个字段的命名;未完全实现; -@TableName(value = "trade_refund") -@Data -@EqualsAndHashCode(callSuper = true) -@Accessors(chain = true) -public class TradeRefundDO extends BaseDO { - - /** - * 交易退款编号,主键自增 - */ - @Deprecated - private Long id; - /** - * 退款流水号 - * - * 例如说,1146347329394184195 - */ - private String sn; - /** - * 退款状态 - * - * 枚举 {@link TradeOrderRefundStatusEnum} - */ - private Integer status; - /** - * 用户编号 - * - * 关联 MemberUserDO 的 id 编号 - */ - private Long userId; - /** - * 用户手机 - */ - private String userMobile; - /** - * 申请类型 - * - * 枚举 {@link TradeRefundTypeEnum} - */ - private Integer type; - /** - * 用户售后说明 - */ - private String reasonMemo; // buyer_msg - /** - * 用户售后凭证图片的地址数组 - * - * 数组,以逗号分隔 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List reasonPicUrls; // photo_files - - // ========== 商家相关 ========== - - /** - * 商家处理时间 - */ - private LocalDateTime handleTime; // handel_time - /** - * 商家拒绝理由 - */ - private String rejectReasonMemo; // seller_msg - - // ========== 交易订单相关 ========== - /** - * 交易订单编号 - * - * 外键 {@link TradeOrderDO#getId()} - */ - private Long tradeOrderId; - /** - * 交易订单项编号 - * - * 关联 {@link TradeOrderItemDO#getId()} - * 如果全部退款,则该值设置为 0 即可 - */ - private Long tradeOrderItemId; - /** - * 商品 SKU 编号 - */ - @Deprecated - private Integer skuId; - /** - * 退货商品数量 - */ - private Integer stock; // goods_num - - // ========== 退款相关 ========== - /** - * 退款金额,单位:分。 - */ - private Integer refundPrice; // refund_amount - /** - * 支付退款编号 - * - * 对接 pay-module-biz 支付服务的退款订单编号,即 PayRefundDO 的 id 编号 - */ - private Long payRefundId; - // TODO 芋艿:看看是否有必要冗余,order_number、order_amount、flow_trade_no、out_refund_no、pay_type、return_money_sts、refund_time - - // ========== 退货相关 ========== - /** - * 退货物流公司编号 - * - * 关联 ExpressDO 的 id 编号 - */ - private Long returnExpressId; // express_name - /** - * 退货物流单号 - */ - private String returnExpressNo; // express_no - /** - * 退货时间 - */ - private LocalDateTime returnDate; // ship_time - - // ========== 收获相关 ========== - - /** - * 收获备注 - */ - private String receiveMemo; // receive_message - /** - * 收货时间 - */ - private LocalDateTime receiveDate; // receive_time - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java new file mode 100644 index 000000000..b92ce075f --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleLogMapper.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TradeAfterSaleLogMapper extends BaseMapperX { +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java new file mode 100644 index 000000000..175d7d2b0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/TradeAfterSaleMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TradeAfterSaleMapper extends BaseMapperX { + + default PageResult selectPage(TradeAfterSalePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(TradeAfterSaleDO::getNo, reqVO.getNo()) + .eqIfPresent(TradeAfterSaleDO::getStatus, reqVO.getStatus()) + .eqIfPresent(TradeAfterSaleDO::getType, reqVO.getType()) + .eqIfPresent(TradeAfterSaleDO::getWay, reqVO.getWay()) + .likeIfPresent(TradeAfterSaleDO::getOrderNo, reqVO.getOrderNo()) + .likeIfPresent(TradeAfterSaleDO::getSpuName, reqVO.getSpuName()) + .betweenIfPresent(TradeAfterSaleDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(TradeAfterSaleDO::getId)); + } + + default int updateByIdAndStatus(Long id, Integer status, TradeAfterSaleDO update) { + return update(update, new LambdaUpdateWrapper() + .eq(TradeAfterSaleDO::getId, id).eq(TradeAfterSaleDO::getStatus, status)); + } + + default TradeAfterSaleDO selectByPayRefundId(Long payRefundId) { + return selectOne(TradeAfterSaleDO::getPayRefundId, payRefundId); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java new file mode 100644 index 000000000..edb45fb62 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.trade.dal.mysql.order; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface TradeOrderItemMapper extends BaseMapperX { + + default int updateAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus) { + return update(new TradeOrderItemDO().setAfterSaleStatus(newAfterSaleStatus), + new LambdaUpdateWrapper<>(new TradeOrderItemDO().setId(id).setAfterSaleStatus(oldAfterSaleStatus))); + } + + default List selectListByOrderId(Long orderId) { + return selectList(TradeOrderItemDO::getOrderId, orderId); + } + + default List selectListByOrderId(Collection orderIds) { + return selectList(TradeOrderItemDO::getOrderId, orderIds); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java index a62746b1b..7be224744 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java @@ -1,9 +1,46 @@ package cn.iocoder.yudao.module.trade.dal.mysql.order; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.util.Set; + @Mapper public interface TradeOrderMapper extends BaseMapperX { + + default int updateByIdAndStatus(Long id, Integer status, TradeOrderDO update) { + return update(update, new LambdaUpdateWrapper() + .eq(TradeOrderDO::getId, id).eq(TradeOrderDO::getStatus, status)); + } + + default TradeOrderDO selectByIdAndUserId(Long id, Long userId) { + return selectOne(TradeOrderDO::getId, id, TradeOrderDO::getUserId, userId); + } + + default PageResult selectPage(TradeOrderPageReqVO reqVO, Set userIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(TradeOrderDO::getNo, reqVO.getNo()) + .eqIfPresent(TradeOrderDO::getUserId, reqVO.getUserId()) + .inIfPresent(TradeOrderDO::getUserId, userIds) + .likeIfPresent(TradeOrderDO::getReceiverName, reqVO.getReceiverName()) + .likeIfPresent(TradeOrderDO::getReceiverMobile, reqVO.getReceiverMobile()) + .eqIfPresent(TradeOrderDO::getType, reqVO.getType()) + .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus()) + .eqIfPresent(TradeOrderDO::getPayChannelCode, reqVO.getPayChannelCode()) + .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())); + } + + default PageResult selectPage(AppTradeOrderPageReqVO reqVO, Long userId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(TradeOrderDO::getUserId, userId) + .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus()) + .orderByDesc(TradeOrderDO::getId)); // TODO 芋艿:未来不同的 status,不同的排序 + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/orderitem/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/orderitem/TradeOrderItemMapper.java deleted file mode 100644 index 3a85e0cbb..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/orderitem/TradeOrderItemMapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.module.trade.dal.mysql.orderitem; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import org.apache.ibatis.annotations.Mapper; - -@Mapper -public interface TradeOrderItemMapper extends BaseMapperX { -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java new file mode 100644 index 000000000..d0d86c033 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; + +/** + * 交易售后 Service 接口 + * + * @author 芋道源码 + */ +public interface TradeAfterSaleService { + + /** + * 获得交易售后分页 + * + * @param pageReqVO 分页查询 + * @return 交易售后分页 + */ + PageResult getAfterSalePage(TradeAfterSalePageReqVO pageReqVO); + + /** + * 【会员】创建交易售后 + *

+ * 一般是用户发起售后请求 + * + * @param userId 会员用户编号 + * @param createReqVO 创建 Request 信息 + * @return 交易售后编号 + */ + Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO); + + /** + * 【管理员】同意交易售后 + * + * @param userId 管理员用户编号 + * @param id 交易售后编号 + */ + void agreeAfterSale(Long userId, Long id); + + /** + * 【管理员】拒绝交易售后 + * + * @param userId 管理员用户编号 + * @param auditReqVO 审批 Request 信息 + */ + void disagreeAfterSale(Long userId, TradeAfterSaleDisagreeReqVO auditReqVO); + + /** + * 【会员】退回货物 + * + * @param userId 会员用户编号 + * @param deliveryReqVO 退货 Request 信息 + */ + void deliveryAfterSale(Long userId, AppTradeAfterSaleDeliveryReqVO deliveryReqVO); + + /** + * 【管理员】确认收货 + * + * @param userId 管理员编号 + * @param id 交易售后编号 + */ + void receiveAfterSale(Long userId, Long id); + + /** + * 【管理员】拒绝收货 + * + * @param userId 管理员用户编号 + * @param refuseReqVO 拒绝收货 Request 信息 + */ + void refuseAfterSale(Long userId, TradeAfterSaleRefuseReqVO refuseReqVO); + + /** + * 【管理员】确认退款 + * + * @param userId 管理员用户编号 + * @param userIp 管理员用户 IP + * @param id 售后编号 + */ + void refundAfterSale(Long userId, String userIp, Long id); + + /** + * 【会员】取消售后 + * + * @param userId 会员用户编号 + * @param id 交易售后编号 + */ + void cancelAfterSale(Long userId, Long id); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java new file mode 100644 index 000000000..2da892d61 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java @@ -0,0 +1,392 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; +import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleLogMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleMapper; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; + +/** + * 交易售后 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { + + @Resource + private TradeOrderService tradeOrderService; + + @Resource + private TradeAfterSaleMapper tradeAfterSaleMapper; + @Resource + private TradeAfterSaleLogMapper tradeAfterSaleLogMapper; + + @Resource + private PayRefundApi payRefundApi; + + @Resource + private TradeOrderProperties tradeOrderProperties; + + @Override + public PageResult getAfterSalePage(TradeAfterSalePageReqVO pageReqVO) { + return tradeAfterSaleMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { + // 第一步,前置校验 + TradeOrderItemDO tradeOrderItem = validateOrderItemApplicable(userId, createReqVO); + + // 第二步,存储交易售后 + TradeAfterSaleDO afterSale = createAfterSale(createReqVO, tradeOrderItem); + return afterSale.getId(); + } + + /** + * 校验交易订单项是否可以申请售后 + * + * @param userId 用户编号 + * @param createReqVO 售后创建信息 + * @return 交易订单项 + */ + private TradeOrderItemDO validateOrderItemApplicable(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { + // 校验订单项存在 + TradeOrderItemDO orderItem = tradeOrderService.getOrderItem(userId, createReqVO.getOrderItemId()); + if (orderItem == null) { + throw exception(ORDER_ITEM_NOT_FOUND); + } + + // 已申请售后,不允许再发起售后申请 + if (!TradeOrderItemAfterSaleStatusEnum.isNone(orderItem.getAfterSaleStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED); + } + + // 申请的退款金额,不能超过商品的价格 + if (createReqVO.getRefundPrice() > orderItem.getOrderDividePrice()) { + throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR); + } + + // 校验订单存在 + TradeOrderDO order = tradeOrderService.getOrder(userId, orderItem.getOrderId()); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // TODO 芋艿:超过一定时间,不允许售后 + // 已取消,无法发起售后 + if (TradeOrderStatusEnum.isCanceled(order.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED); + } + // 未支付,无法发起售后 + if (!TradeOrderStatusEnum.havePaid(order.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID); + } + // 如果是【退货退款】的情况,需要额外校验是否发货 + if (createReqVO.getWay().equals(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()) + && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED); + } + return orderItem; + } + + private TradeAfterSaleDO createAfterSale(AppTradeAfterSaleCreateReqVO createReqVO, + TradeOrderItemDO orderItem) { + // 创建售后单 + TradeAfterSaleDO afterSale = TradeAfterSaleConvert.INSTANCE.convert(createReqVO, orderItem); + afterSale.setNo(RandomUtil.randomString(10)); // TODO 芋艿:优化 no 生成逻辑 + afterSale.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); + // 标记是售中还是售后 + TradeOrderDO order = tradeOrderService.getOrder(orderItem.getUserId(), orderItem.getOrderId()); + afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索 + afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus()) + ? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType()); + // TODO 退还积分 + tradeAfterSaleMapper.insert(afterSale); + + // 更新交易订单项的售后状态 + tradeOrderService.updateOrderItemAfterSaleStatus(orderItem.getId(), + TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), null); + + // 记录售后日志 + createAfterSaleLog(orderItem.getUserId(), UserTypeEnum.MEMBER.getValue(), + afterSale, null, afterSale.getStatus()); + + // TODO 发送售后消息 + return afterSale; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void agreeAfterSale(Long userId, Long id) { + // 校验售后单存在,并状态未审批 + TradeAfterSaleDO afterSale = validateAfterSaleAuditable(id); + + // 更新售后单的状态 + // 情况一:退款:标记为 WAIT_REFUND 状态。后续等退款发起成功后,在标记为 COMPLETE 状态 + // 情况二:退货退款:需要等用户退货后,才能发起退款 + Integer newStatus = afterSale.getType().equals(TradeAfterSaleWayEnum.REFUND.getWay()) ? + TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus() : TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(); + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.APPLY.getStatus(), new TradeAfterSaleDO() + .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.ADMIN.getValue(), + afterSale, afterSale.getStatus(), newStatus); + + // TODO 发送售后消息 + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void disagreeAfterSale(Long userId, TradeAfterSaleDisagreeReqVO auditReqVO) { + // 校验售后单存在,并状态未审批 + TradeAfterSaleDO afterSale = validateAfterSaleAuditable(auditReqVO.getId()); + + // 更新售后单的状态 + Integer newStatus = TradeAfterSaleStatusEnum.SELLER_DISAGREE.getStatus(); + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.APPLY.getStatus(), new TradeAfterSaleDO() + .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now()) + .setAuditReason(auditReqVO.getAuditReason())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.ADMIN.getValue(), + afterSale, afterSale.getStatus(), newStatus); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【未申请】 + tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), + TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); + } + + /** + * 校验售后单是否可审批(同意售后、拒绝售后) + * + * @param id 售后编号 + * @return 售后单 + */ + private TradeAfterSaleDO validateAfterSaleAuditable(Long id) { + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus())) { + throw exception(AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY); + } + return afterSale; + } + + private void updateAfterSaleStatus(Long id, Integer status, TradeAfterSaleDO updateObj) { + int updateCount = tradeAfterSaleMapper.updateByIdAndStatus(id, status, updateObj); + if (updateCount == 0) { + throw exception(AFTER_SALE_UPDATE_STATUS_FAIL); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deliveryAfterSale(Long userId, AppTradeAfterSaleDeliveryReqVO deliveryReqVO) { + // 校验售后单存在,并状态未退货 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(deliveryReqVO.getId()); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus())) { + throw exception(AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE); + } + + // 更新售后单的物流信息 + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus(), new TradeAfterSaleDO() + .setStatus(TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus()) + .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()) + .setDeliveryTime(deliveryReqVO.getDeliveryTime())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.MEMBER.getValue(), + afterSale, afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus()); + + // TODO 发送售后消息 + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void receiveAfterSale(Long userId, Long id) { + // 校验售后单存在,并状态为已退货 + TradeAfterSaleDO afterSale = validateAfterSaleReceivable(id); + + // 更新售后单的状态 + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new TradeAfterSaleDO() + .setStatus(TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus()).setReceiveTime(LocalDateTime.now())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.ADMIN.getValue(), + afterSale, afterSale.getStatus(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus()); + + // TODO 发送售后消息 + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void refuseAfterSale(Long userId, TradeAfterSaleRefuseReqVO refuseReqVO) { + // 校验售后单存在,并状态为已退货 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(refuseReqVO.getId()); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { + throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY); + } + + // 更新售后单的状态 + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new TradeAfterSaleDO() + .setStatus(TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus()).setReceiveTime(LocalDateTime.now()) + .setReceiveReason(refuseReqVO.getRefuseMemo())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.ADMIN.getValue(), + afterSale, afterSale.getStatus(), TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus()); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【未申请】 + tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), + TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); + } + + /** + * 校验售后单是否可收货,即处于买家已发货 + * + * @param id 售后编号 + * @return 售后单 + */ + private TradeAfterSaleDO validateAfterSaleReceivable(Long id) { + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) { + throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY); + } + return afterSale; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void refundAfterSale(Long userId, String userIp, Long id) { + // 校验售后单的状态,并状态待退款 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectByPayRefundId(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtil.notEqual(afterSale.getStatus(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus())) { + throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND); + } + + // 发起退款单。注意,需要在事务提交后,再进行发起,避免重复发起 + createPayRefund(userIp, afterSale); + + // 更新售后单的状态为【已完成】 + updateAfterSaleStatus(afterSale.getId(), TradeAfterSaleStatusEnum.WAIT_REFUND.getStatus(), new TradeAfterSaleDO() + .setStatus(TradeAfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(LocalDateTime.now())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.ADMIN.getValue(), + afterSale, afterSale.getStatus(), TradeAfterSaleStatusEnum.COMPLETE.getStatus()); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【已完成】 + tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), + TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), afterSale.getRefundPrice()); + } + + private void createPayRefund(String userIp, TradeAfterSaleDO afterSale) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + + @Override + public void afterCommit() { + // 创建退款单 + PayRefundCreateReqDTO createReqDTO = TradeAfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties); + Long payRefundId = payRefundApi.createPayRefund(createReqDTO); + // 更新售后单的退款单号 + tradeAfterSaleMapper.updateById(new TradeAfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId)); + } + }); + } + + @Override + public void cancelAfterSale(Long userId, Long id) { + // 校验售后单的状态,并状态待退款 + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectByPayRefundId(id); + if (afterSale == null) { + throw exception(AFTER_SALE_NOT_FOUND); + } + if (ObjectUtils.equalsAny(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus(), + TradeAfterSaleStatusEnum.SELLER_AGREE.getStatus())) { + throw exception(AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE); + } + + // 更新售后单的状态为【已取消】 + updateAfterSaleStatus(afterSale.getId(), afterSale.getStatus(), new TradeAfterSaleDO() + .setStatus(TradeAfterSaleStatusEnum.BUYER_CANCEL.getStatus())); + + // 记录售后日志 + createAfterSaleLog(userId, UserTypeEnum.MEMBER.getValue(), + afterSale, afterSale.getStatus(), TradeAfterSaleStatusEnum.BUYER_CANCEL.getStatus()); + + // TODO 发送售后消息 + + // 更新交易订单项的售后状态为【未申请】 + tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), + TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); + } + + private void createAfterSaleLog(Long userId, Integer userType, TradeAfterSaleDO afterSale, + Integer beforeStatus, Integer afterStatus) { + TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO().setUserId(userId).setUserType(userType) + .setAfterSaleId(afterSale.getId()).setOrderId(afterSale.getOrderId()) + .setOrderItemId(afterSale.getOrderItemId()).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus) + .setContent(TradeAfterSaleStatusEnum.valueOf(afterStatus).getContent()); + tradeAfterSaleLogMapper.insert(afterSaleLog); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java index f9e635fac..086f65edd 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java @@ -1,6 +1,17 @@ package cn.iocoder.yudao.module.trade.service.order; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; + +import java.util.Collection; +import java.util.List; + +import static java.util.Collections.singleton; /** * 交易订单 Service 接口 @@ -10,14 +21,122 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreate */ public interface TradeOrderService { + // =================== Order =================== + /** - * 创建交易订单 + * 【会员】创建交易订单 * - * @param loginUserId 登录用户 + * @param userId 登录用户 * @param userIp 用户 IP 地址 * @param createReqVO 创建交易订单请求模型 * @return 交易订单的编号 */ - Long createTradeOrder(Long loginUserId, String userIp, AppTradeOrderCreateReqVO createReqVO); + Long createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO); + + /** + * 更新交易订单已支付 + * + * @param id 交易订单编号 + * @param payOrderId 支付订单编号 + */ + void updateOrderPaid(Long id, Long payOrderId); + + /** + * 【管理员】发货交易订单 + * + * @param userId 管理员编号 + * @param deliveryReqVO 发货请求 + */ + void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO); + + /** + * 【会员】收货交易订单 + * + * @param userId 用户编号 + * @param id 订单编号 + */ + void receiveOrder(Long userId, Long id); + + /** + * 获得指定编号的交易订单 + * + * @param id 交易订单编号 + * @return 交易订单 + */ + TradeOrderDO getOrder(Long id); + + /** + * 获得指定用户,指定的交易订单 + * + * @param userId 用户编号 + * @param id 交易订单编号 + * @return 交易订单 + */ + TradeOrderDO getOrder(Long userId, Long id); + + /** + * 【管理员】获得交易订单分页 + * + * @param reqVO 分页请求 + * @return 交易订单 + */ + PageResult getOrderPage(TradeOrderPageReqVO reqVO); + + /** + * 【会员】获得交易订单分页 + * + * @param userId 用户编号 + * @param reqVO 分页请求 + * @return 交易订单 + */ + PageResult getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO); + + // =================== Order Item =================== + + /** + * 获得指定用户,指定的交易订单项 + * + * @param userId 用户编号 + * @param itemId 交易订单项编号 + * @return 交易订单项 + */ + TradeOrderItemDO getOrderItem(Long userId, Long itemId); + + /** + * 更新交易订单项的售后状态 + * + * @param id 交易订单项编号 + * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 + * @param newAfterSaleStatus 目标售后状态 + * @param refundPrice 退款金额;当订单项退款成功时,必须传递该值 + */ + void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, + Integer newAfterSaleStatus, Integer refundPrice); + + /** + * 根据交易订单项编号数组,查询交易订单项 + * + * @param ids 交易订单项编号数组 + * @return 交易订单项数组 + */ + List getOrderItemList(Collection ids); + + /** + * 根据交易订单编号,查询交易订单项 + * + * @param orderId 交易订单编号 + * @return 交易订单项数组 + */ + default List getOrderItemListByOrderId(Long orderId) { + return getOrderItemListByOrderId(singleton(orderId)); + } + + /** + * 根据交易订单编号数组,查询交易订单项 + * + * @param orderIds 交易订单编号数组 + * @return 交易订单项数组 + */ + List getOrderItemListByOrderId(Collection orderIds); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java index ac38f3cbf..86d84c415 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -1,14 +1,23 @@ package cn.iocoder.yudao.module.trade.service.order; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; -import cn.iocoder.yudao.module.pay.api.order.PayOrderInfoCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; @@ -19,31 +28,31 @@ import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; import cn.iocoder.yudao.module.promotion.api.price.PriceApi; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; -import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; +import java.time.LocalDateTime; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_SKU_NOT_SALE; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_SPU_NOT_FOUND; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** * 交易订单 Service 实现类 @@ -52,6 +61,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREAT * @since 2022-08-26 */ @Service +@Slf4j public class TradeOrderServiceImpl implements TradeOrderService { @Resource @@ -71,13 +81,17 @@ public class TradeOrderServiceImpl implements TradeOrderService { private AddressApi addressApi; @Resource private CouponApi couponApi; + @Resource + private MemberUserApi memberUserApi; @Resource private TradeOrderProperties tradeOrderProperties; + // =================== Order =================== + @Override @Transactional(rollbackFor = Exception.class) - public Long createTradeOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { + public Long createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { // 商品 SKU 检查:可售状态、库存 List skus = validateSkuSaleable(createReqVO.getItems()); // 商品 SPU 检查:可售状态 @@ -109,7 +123,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { List skus = productSkuApi.getSkuList(convertSet(items, Item::getSkuId)); // SKU 不存在 if (items.size() != skus.size()) { - throw exception(ErrorCodeConstants.ORDER_CREATE_SKU_NOT_FOUND); + throw exception(ORDER_CREATE_SKU_NOT_FOUND); } // 校验是否禁用 or 库存不足 Map skuMap = convertMap(skus, ProductSkuRespDTO::getId); @@ -167,14 +181,14 @@ public class TradeOrderServiceImpl implements TradeOrderService { PriceCalculateRespDTO.Order order, AddressRespDTO address) { TradeOrderDO tradeOrderDO = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, order, address); tradeOrderDO.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; - tradeOrderDO.setStatus(TradeOrderStatusEnum.WAITING_PAYMENT.getStatus()); + tradeOrderDO.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); tradeOrderDO.setType(TradeOrderTypeEnum.NORMAL.getType()); - tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); + tradeOrderDO.setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.NONE.getStatus()); tradeOrderDO.setProductCount(getSumValue(order.getItems(), PriceCalculateRespDTO.OrderItem::getCount, Integer::sum)); tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? tradeOrderDO.setAdjustPrice(0).setPayed(false); // 支付信息 - tradeOrderDO.setDeliveryStatus(false); // 物流信息 - tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); // 退款信息 + tradeOrderDO.setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); // 物流信息 + tradeOrderDO.setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.NONE.getStatus()).setRefundPrice(0); // 退款信息 tradeOrderMapper.insert(tradeOrderDO); return tradeOrderDO; } @@ -220,12 +234,297 @@ public class TradeOrderServiceImpl implements TradeOrderService { private void createPayOrder(TradeOrderDO tradeOrderDO, List tradeOrderItemDOs, List spus) { // 创建支付单,用于后续的支付 - PayOrderInfoCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( + PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( tradeOrderDO, tradeOrderItemDOs, spus, tradeOrderProperties); - Long payOrderId = payOrderApi.createPayOrder(payOrderCreateReqDTO); + Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO); // 更新到交易单上 tradeOrderMapper.updateById(new TradeOrderDO().setId(tradeOrderDO.getId()).setPayOrderId(payOrderId)); } + @Override + public void updateOrderPaid(Long id, Long payOrderId) { + // 校验并获得交易订单(可支付) + KeyValue orderResult = validateOrderPayable(id, payOrderId); + TradeOrderDO order = orderResult.getKey(); + PayOrderRespDTO payOrder = orderResult.getValue(); + + // 更新 TradeOrderDO 状态为已支付,等待发货 + int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), + new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayed(true) + .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode())); + if (updateCount == 0) { + throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); + } + + // TODO 芋艿:发送订单变化的消息 + + // TODO 芋艿:发送站内信 + + // TODO 芋艿:OrderLog + } + + /** + * 校验交易订单满足被支付的条件 + * + * 1. 交易订单未支付 + * 2. 支付单已支付 + * + * @param id 交易订单编号 + * @param payOrderId 支付订单编号 + * @return 交易订单 + */ + private KeyValue validateOrderPayable(Long id, Long payOrderId) { + // 校验订单是否存在 + TradeOrderDO order = tradeOrderMapper.selectById(id); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // 校验订单未支付 + if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayed()) { + log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", + id, JsonUtils.toJsonString(order)); + throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); + } + // 校验支付订单匹配 + if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 + log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(order)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); + } + + // 校验支付单是否存在 + PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); + if (payOrder == null) { + log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); + throw exception(PAY_ORDER_NOT_FOUND); + } + // 校验支付单已支付 + if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { + log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(payOrder)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); + } + // 校验支付金额一致 + if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPayPrice())) { + log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); + } + // 校验支付订单匹配(二次) + if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) { + log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(payOrder)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); + } + return new KeyValue<>(order, payOrder); + } + + // TODO 芋艿:如果无需发货,需要怎么存储? + @Override + public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { + // 校验并获得交易订单(可发货) + TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); + + // TODO 芋艿:logisticsId 校验存在 + + // 更新 TradeOrderDO 状态为已发货,等待收货 + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), + new TradeOrderDO().setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) + .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()) + .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now())); + if (updateCount == 0) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + + // TODO 芋艿:发送订单变化的消息 + + // TODO 芋艿:发送站内信 + + // TODO 芋艿:OrderLog + + // TODO 设计:like:是否要单独一个 delivery 发货单表??? + // TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞 + // TODO 设计:lili:是不是发货后,才支持售后? + } + + /** + * 校验交易订单满足被发货的条件 + * + * 1. 交易订单未发货 + * + * @param id 交易订单编号 + * @return 交易订单 + */ + private TradeOrderDO validateOrderDeliverable(Long id) { + // 校验订单是否存在 + TradeOrderDO order = tradeOrderMapper.selectById(id); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // 校验订单是否是待发货状态 + if (!TradeOrderStatusEnum.isUndelivered(order.getStatus()) + || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus())) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + return order; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void receiveOrder(Long userId, Long id) { + // 校验并获得交易订单(可收货) + TradeOrderDO order = validateOrderReceivable(userId, id); + + // 更新 TradeOrderDO 状态为已完成 + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), + new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()) + .setDeliveryStatus(TradeOrderDeliveryStatusEnum.RECEIVED.getStatus()).setReceiveTime(LocalDateTime.now())); + if (updateCount == 0) { + throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); + } + + // TODO 芋艿:OrderLog + + // TODO 芋艿:lili 发送订单变化的消息 + + // TODO 芋艿:lili 发送商品被购买完成的数据 + } + + @Override + public TradeOrderDO getOrder(Long id) { + return tradeOrderMapper.selectById(id); + } + + /** + * 校验交易订单满足可售货的条件 + * + * 1. 交易订单待收货 + * + * @param userId 用户编号 + * @param id 交易订单编号 + * @return 交易订单 + */ + private TradeOrderDO validateOrderReceivable(Long userId, Long id) { + // 校验订单是否存在 + TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // 校验订单是否是待收货状态 + if (!TradeOrderStatusEnum.isDelivered(order.getStatus()) + || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.DELIVERED.getStatus())) { + throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); + } + return order; + } + + @Override + public TradeOrderDO getOrder(Long userId, Long id) { + TradeOrderDO order = tradeOrderMapper.selectById(id); + if (order != null + && ObjectUtil.notEqual(order.getUserId(), userId)) { + return null; + } + return order; + } + + @Override + public PageResult getOrderPage(TradeOrderPageReqVO reqVO) { + // 获得 userId 相关的查询 + Set userIds = new HashSet<>(); + if (StrUtil.isNotEmpty(reqVO.getUserMobile())) { + MemberUserRespDTO user = memberUserApi.getUserByMobile(reqVO.getUserMobile()); + if (user == null) { // 没查询到用户,说明肯定也没他的订单 + return new PageResult<>(); + } + userIds.add(user.getId()); + } + if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { + List users = memberUserApi.getUserListByNickname(reqVO.getUserNickname()); + if (CollUtil.isEmpty(users)) { // 没查询到用户,说明肯定也没他的订单 + return new PageResult<>(); + } + userIds.addAll(convertSet(users, MemberUserRespDTO::getId)); + } + // 分页查询 + return tradeOrderMapper.selectPage(reqVO, userIds); + } + + @Override + public PageResult getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO) { + return tradeOrderMapper.selectPage(reqVO, userId); + } + + // =================== Order Item =================== + + @Override + public TradeOrderItemDO getOrderItem(Long userId, Long itemId) { + TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(itemId); + if (orderItem != null + && ObjectUtil.notEqual(orderItem.getUserId(), userId)) { + return null; + } + return orderItem; + } + + @Override + public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, Integer refundPrice) { + // 如果退款成功,则 refundPrice 非空 + if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) + && refundPrice == null) { + throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); + } + + // 更新订单项 + int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus); + if (updateCount <= 0) { + throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); + } + + // 如果有退款金额,则需要更新订单 + if (refundPrice == null) { + return; + } + // 计算总的退款金额 + TradeOrderDO order = tradeOrderMapper.selectById(tradeOrderItemMapper.selectById(id).getOrderId()); + Integer orderRefundPrice = order.getRefundPrice() + refundPrice; + if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) + .setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.ALL.getStatus()).setRefundPrice(orderRefundPrice) + .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); + + // TODO 芋艿:记录订单日志 + + // TODO 芋艿:站内信? + } else { // 如果部分售后,则更新退款金额 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) + .setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); + } + + // TODO 芋艿:未来如果有分佣,需要更新相关分佣订单为已失效 + } + + @Override + public List getOrderItemList(Collection ids) { + return tradeOrderItemMapper.selectBatchIds(ids); + } + + @Override + public List getOrderItemListByOrderId(Collection orderIds) { + return tradeOrderItemMapper.selectListByOrderId(orderIds); + } + + /** + * 判断指定订单的所有订单项,是不是都售后成功 + * + * @param id 订单编号 + * @return 是否都售后成功 + */ + private boolean isAllOrderItemAfterSaleSuccess(Long id) { + List orderItems = tradeOrderItemMapper.selectListByOrderId(id); + return orderItems.stream().allMatch(orderItem -> Objects.equals(orderItem.getAfterSaleStatus(), + TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java new file mode 100644 index 000000000..f628cef4a --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java @@ -0,0 +1,154 @@ +package cn.iocoder.yudao.module.trade.service.aftersale; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleLogMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.aftersale.TradeAfterSaleMapper; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; +import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static java.util.Arrays.asList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +/** + * {@link TradeAfterSaleService} 的单元测试 + * + * @author 芋道源码 + */ +@Import(TradeAfterSaleServiceImpl.class) +public class TradeAfterSaleServiceTest extends BaseDbUnitTest { + + @Resource + private TradeAfterSaleServiceImpl tradeAfterSaleService; + + @Resource + private TradeAfterSaleMapper tradeAfterSaleMapper; + @Resource + private TradeAfterSaleLogMapper tradeAfterSaleLogMapper; + + @MockBean + private TradeOrderService tradeOrderService; + @MockBean + private PayRefundApi payRefundApi; + + @MockBean + private TradeOrderProperties tradeOrderProperties; + + @Test + public void testCreateAfterSale() { + // 准备参数 + Long userId = 1024L; + AppTradeAfterSaleCreateReqVO createReqVO = new AppTradeAfterSaleCreateReqVO() + .setOrderItemId(1L).setRefundPrice(100).setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()) + .setApplyReason("退钱").setApplyDescription("快退") + .setApplyPicUrls(asList("https://www.baidu.com/1.png", "https://www.baidu.com/2.png")); + // mock 方法(交易订单项) + TradeOrderItemDO orderItem = randomPojo(TradeOrderItemDO.class, o -> { + o.setOrderId(111L).setUserId(userId).setOrderDividePrice(200); + o.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + }); + when(tradeOrderService.getOrderItem(eq(1024L), eq(1L))) + .thenReturn(orderItem); + // mock 方法(交易订单) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> o.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()) + .setNo("202211301234")); + when(tradeOrderService.getOrder(eq(1024L), eq(111L))).thenReturn(order); + + // 调用 + Long afterSaleId = tradeAfterSaleService.createAfterSale(userId, createReqVO); + // 断言(TradeAfterSaleDO) + TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(afterSaleId); + assertNotNull(afterSale.getNo()); + assertEquals(afterSale.getStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus()); + assertEquals(afterSale.getType(), TradeAfterSaleTypeEnum.IN_SALE.getType()); + assertPojoEquals(afterSale, createReqVO); + assertEquals(afterSale.getUserId(), 1024L); + assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); + assertEquals(afterSale.getOrderNo(), "202211301234"); + assertNull(afterSale.getPayRefundId()); + assertNull(afterSale.getRefundTime()); + assertNull(afterSale.getLogisticsId()); + assertNull(afterSale.getLogisticsNo()); + assertNull(afterSale.getDeliveryTime()); + assertNull(afterSale.getReceiveReason()); + // 断言(TradeAfterSaleLogDO) + TradeAfterSaleLogDO afterSaleLog = tradeAfterSaleLogMapper.selectList().get(0); + assertEquals(afterSaleLog.getUserId(), userId); + assertEquals(afterSaleLog.getUserType(), UserTypeEnum.MEMBER.getValue()); + assertEquals(afterSaleLog.getAfterSaleId(), afterSaleId); + assertPojoEquals(afterSale, orderItem, "id", "creator", "createTime", "updater", "updateTime"); + assertNull(afterSaleLog.getBeforeStatus()); + assertEquals(afterSaleLog.getAfterStatus(), TradeAfterSaleStatusEnum.APPLY.getStatus()); + assertEquals(afterSaleLog.getContent(), TradeAfterSaleStatusEnum.APPLY.getContent()); + } + + @Test + public void testGetAfterSalePage() { + // mock 数据 + TradeAfterSaleDO dbAfterSale = randomPojo(TradeAfterSaleDO.class, o -> { // 等会查询到 + o.setNo("202211190847450020500077"); + o.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); + o.setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()); + o.setType(TradeAfterSaleTypeEnum.IN_SALE.getType()); + o.setOrderNo("202211190847450020500011"); + o.setSpuName("芋艿"); + o.setCreateTime(buildTime(2022, 1, 15)); + }); + tradeAfterSaleMapper.insert(dbAfterSale); + // 测试 no 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setNo("202211190847450020500066"))); + // 测试 status 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setStatus(TradeAfterSaleStatusEnum.SELLER_REFUSE.getStatus()))); + // 测试 way 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setWay(TradeAfterSaleWayEnum.REFUND.getWay()))); + // 测试 type 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setType(TradeAfterSaleTypeEnum.AFTER_SALE.getType()))); + // 测试 orderNo 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setOrderNo("202211190847450020500022"))); + // 测试 spuName 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setSpuName("土豆"))); + // 测试 createTime 不匹配 + tradeAfterSaleMapper.insert(cloneIgnoreId(dbAfterSale, o -> o.setCreateTime(buildTime(2022, 1, 20)))); + // 准备参数 + TradeAfterSalePageReqVO reqVO = new TradeAfterSalePageReqVO(); + reqVO.setNo("20221119084745002050007"); + reqVO.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); + reqVO.setWay(TradeAfterSaleWayEnum.RETURN_AND_REFUND.getWay()); + reqVO.setType(TradeAfterSaleTypeEnum.IN_SALE.getType()); + reqVO.setOrderNo("20221119084745002050001"); + reqVO.setSpuName("芋"); + reqVO.setCreateTime(new LocalDateTime[]{buildTime(2022, 1, 1), buildTime(2022, 1, 16)}); + + // 调用 + PageResult pageResult = tradeAfterSaleService.getAfterSalePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbAfterSale, pageResult.getList().get(0)); + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java index 669680c3d..55bff8de6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java @@ -6,29 +6,27 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.member.api.address.AddressApi; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.price.PriceApi; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; -import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemRefundStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatcher; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -38,6 +36,8 @@ import java.util.Arrays; import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.*; @@ -53,7 +53,7 @@ import static org.mockito.Mockito.when; * @since 2022-09-07 */ @Import({TradeOrderServiceImpl.class, TradeOrderConfig.class}) -class TradeOrderServiceTest extends BaseDbUnitTest { +public class TradeOrderServiceTest extends BaseDbUnitTest { @Resource private TradeOrderServiceImpl tradeOrderService; @@ -111,7 +111,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { // mock 方法(用户收件地址的校验) AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿") .setMobile("15601691300").setAreaId(3306L).setPostCode("85757").setDetailAddress("土豆村"); - when(addressApi.getAddress(eq(userId), eq(10L))).thenReturn(addressRespDTO); + when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO); // mock 方法(价格计算) PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem() .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50) @@ -133,7 +133,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { return true; }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder)); // mock 方法(创建支付单) - when(payOrderApi.createPayOrder(argThat(createReqDTO -> { + when(payOrderApi.createOrder(argThat(createReqDTO -> { assertEquals(createReqDTO.getAppId(), 888L); assertEquals(createReqDTO.getUserIp(), userIp); assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空 @@ -145,7 +145,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { }))).thenReturn(1000L); // 调用方法 - Long tradeOrderId = tradeOrderService.createTradeOrder(userId, userIp, reqVO); + Long tradeOrderId = tradeOrderService.createOrder(userId, userIp, reqVO); // 断言 TradeOrderDO 订单 List tradeOrderDOs = tradeOrderMapper.selectList(); assertEquals(tradeOrderDOs.size(), 1); @@ -156,7 +156,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal()); assertEquals(tradeOrderDO.getUserId(), userId); assertEquals(tradeOrderDO.getUserIp(), userIp); - assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.WAITING_PAYMENT.getStatus()); + assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus()); assertEquals(tradeOrderDO.getProductCount(), 7); assertNull(tradeOrderDO.getFinishTime()); assertNull(tradeOrderDO.getCancelTime()); @@ -171,18 +171,18 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderDO.getAdjustPrice(), 0); assertEquals(tradeOrderDO.getPayPrice(), 80); assertEquals(tradeOrderDO.getPayOrderId(), 1000L); - assertNull(tradeOrderDO.getPayChannel()); + assertNull(tradeOrderDO.getPayChannelCode()); assertNull(tradeOrderDO.getDeliveryTemplateId()); - assertNull(tradeOrderDO.getExpressNo()); - assertFalse(tradeOrderDO.getDeliveryStatus()); + assertNull(tradeOrderDO.getLogisticsId()); + assertEquals(tradeOrderDO.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); assertNull(tradeOrderDO.getDeliveryTime()); assertNull(tradeOrderDO.getReceiveTime()); assertEquals(tradeOrderDO.getReceiverName(), "芋艿"); assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300"); - assertEquals(tradeOrderDO.getReceiverAreaId(), 3306L); + assertEquals(tradeOrderDO.getReceiverAreaId(), 3306); assertEquals(tradeOrderDO.getReceiverPostCode(), 85757); assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村"); - assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus()); + assertEquals(tradeOrderDO.getAfterSaleStatus(), TradeOrderAfterSaleStatusEnum.NONE.getStatus()); assertEquals(tradeOrderDO.getRefundPrice(), 0); assertEquals(tradeOrderDO.getCouponPrice(), 30); assertEquals(tradeOrderDO.getPointPrice(), 10); @@ -198,7 +198,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderItemDO01.getProperties().size(), 1); assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L); assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L); - assertEquals(tradeOrderItemDO01.getName(), sku01.getName()); + assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl()); assertEquals(tradeOrderItemDO01.getCount(), 3); assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150); @@ -207,8 +207,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderItemDO01.getPayPrice(), 130); assertEquals(tradeOrderItemDO01.getOrderPartPrice(), 7); assertEquals(tradeOrderItemDO01.getOrderDividePrice(), 35); - assertEquals(tradeOrderItemDO01.getRefundStatus(), TradeOrderItemRefundStatusEnum.NONE.getStatus()); - assertEquals(tradeOrderItemDO01.getRefundTotal(), 0); + assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); // 断言 TradeOrderItemDO 订单(第 2 个) TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1); assertNotNull(tradeOrderItemDO02.getId()); @@ -219,7 +218,7 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderItemDO02.getProperties().size(), 1); assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L); assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L); - assertEquals(tradeOrderItemDO02.getName(), sku02.getName()); + assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl()); assertEquals(tradeOrderItemDO02.getCount(), 4); assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80); @@ -228,21 +227,15 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderItemDO02.getPayPrice(), 40); assertEquals(tradeOrderItemDO02.getOrderPartPrice(), 15); assertEquals(tradeOrderItemDO02.getOrderDividePrice(), 25); - assertEquals(tradeOrderItemDO02.getRefundStatus(), TradeOrderItemRefundStatusEnum.NONE.getStatus()); - assertEquals(tradeOrderItemDO02.getRefundTotal(), 0); + assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); // 校验调用 - verify(productSkuApi).updateSkuStock(argThat(new ArgumentMatcher() { - - @Override - public boolean matches(ProductSkuUpdateStockReqDTO updateStockReqDTO) { - assertEquals(updateStockReqDTO.getItems().size(), 2); - assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L); - assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3); - assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L); - assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4); - return true; - } - + verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> { + assertEquals(updateStockReqDTO.getItems().size(), 2); + assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L); + assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3); + assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L); + assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4); + return true; })); verify(couponApi).useCoupon(argThat(reqDTO -> { assertEquals(reqDTO.getId(), reqVO.getCouponId()); @@ -250,11 +243,78 @@ class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(reqDTO.getOrderId(), tradeOrderId); return true; })); -// //mock 支付订单信息 -// when(payOrderApi.createPayOrder(any())).thenReturn(1L); + } -// //价格 -// assertEquals(calculateRespDTO.getOrder().getItems().get(0).getPresentPrice(), tradeOrderItemDO.getPresentPrice()); + @Test + public void testUpdateOrderPaid() { + // mock 数据(TradeOrder) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { + o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); + o.setPayOrderId(10L).setPayed(false).setPayPrice(100).setPayTime(null); + }); + tradeOrderMapper.insert(order); + // 准备参数 + Long id = 1L; + Long payOrderId = 10L; + // mock 方法(支付单) + when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class, + o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub") + .setMerchantOrderId("1")).setAmount(100)); + + // 调用 + tradeOrderService.updateOrderPaid(id, payOrderId); + // 断言 + TradeOrderDO dbOrder = tradeOrderMapper.selectById(id); + assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); + assertTrue(dbOrder.getPayed()); + assertNotNull(dbOrder.getPayTime()); + assertEquals(dbOrder.getPayChannelCode(), "wx_pub"); + } + + @Test + public void testDeliveryOrder() { + // mock 数据(TradeOrder) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { + o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()); + o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null) + .setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); + }); + tradeOrderMapper.insert(order); + // 准备参数 + TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L) + .setLogisticsId(10L).setLogisticsNo("100"); + // mock 方法(支付单) + + // 调用 + tradeOrderService.deliveryOrder(randomLongId(), deliveryReqVO); + // 断言 + TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); + assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus()); + assertEquals(dbOrder.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()); + assertPojoEquals(dbOrder, deliveryReqVO); + assertNotNull(dbOrder.getDeliveryTime()); + } + + @Test + public void testReceiveOrder() { + // mock 数据(TradeOrder) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { + o.setId(1L).setUserId(10L).setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()); + o.setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setReceiveTime(null); + }); + tradeOrderMapper.insert(order); + // 准备参数 + Long id = 1L; + Long userId = 10L; + // mock 方法(支付单) + + // 调用 + tradeOrderService.receiveOrder(userId, id); + // 断言 + TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); + assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); + assertEquals(dbOrder.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.RECEIVED.getStatus()); + assertNotNull(dbOrder.getReceiveTime()); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql index cd16db8c6..dfa4a5b42 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql @@ -1,2 +1,4 @@ DELETE FROM trade_order; -DELETE FROM trade_order_item; \ No newline at end of file +DELETE FROM trade_order_item; +DELETE FROM trade_after_sale; +DELETE FROM trade_after_sale_log; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql index fda7251dc..452362eb5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql @@ -20,11 +20,12 @@ CREATE TABLE IF NOT EXISTS "trade_order" ( "delivery_price" int NOT NULL, "adjust_price" int NOT NULL, "pay_price" int NOT NULL, - "pay_order_id" int, - "pay_channel" int, - "delivery_template_id" int, - "express_no" int, - "delivery_status" bit NOT NULL, + "pay_order_id" bigint, + "pay_channel_code" varchar, + "delivery_template_id" bigint, + "logistics_id" bigint, + "logistics_no" varchar, + "delivery_status" smallint NOT NULL, "delivery_time" datetime, "receive_time" datetime, "receiver_name" varchar NOT NULL, @@ -32,7 +33,7 @@ CREATE TABLE IF NOT EXISTS "trade_order" ( "receiver_area_id" int NOT NULL, "receiver_post_code" int, "receiver_detail_address" varchar NOT NULL, - "refund_status" int NOT NULL, + "after_sale_status" int NOT NULL, "refund_price" int NOT NULL, "coupon_id" bigint NOT NULL, "coupon_price" int NOT NULL, @@ -50,9 +51,9 @@ CREATE TABLE IF NOT EXISTS "trade_order_item" ( "user_id" bigint NOT NULL, "order_id" bigint NOT NULL, "spu_id" bigint NOT NULL, + "spu_name" varchar NOT NULL, "sku_id" bigint NOT NULL, "properties" varchar, - "name" varchar NOT NULL, "pic_url" varchar, "count" int NOT NULL, "original_price" int NOT NULL, @@ -61,8 +62,7 @@ CREATE TABLE IF NOT EXISTS "trade_order_item" ( "pay_price" int NOT NULL, "order_part_price" int NOT NULL, "order_divide_price" int NOT NULL, - "refund_status" int NOT NULL, - "refund_total" int NOT NULL, + "after_sale_status" int NOT NULL, "creator" varchar DEFAULT '', "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, "updater" varchar DEFAULT '', @@ -70,3 +70,59 @@ CREATE TABLE IF NOT EXISTS "trade_order_item" ( "deleted" bit NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT '交易订单明细表'; + +CREATE TABLE IF NOT EXISTS "trade_after_sale" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "no" varchar NOT NULL, + "status" int NOT NULL, + "type" int NOT NULL, + "way" int NOT NULL, + "user_id" bigint NOT NULL, + "apply_reason" varchar NOT NULL, + "apply_description" varchar, + "apply_pic_urls" varchar, + "order_id" bigint NOT NULL, + "order_no" varchar NOT NULL, + "order_item_id" bigint NOT NULL, + "spu_id" bigint NOT NULL, + "spu_name" varchar NOT NULL, + "sku_id" bigint NOT NULL, + "properties" varchar, + "pic_url" varchar, + "count" int NOT NULL, + "audit_time" varchar, + "audit_user_id" bigint, + "audit_reason" varchar, + "refund_price" int NOT NULL, + "pay_refund_id" bigint, + "refund_time" varchar, + "logistics_id" bigint, + "logistics_no" varchar, + "delivery_time" varchar, + "receive_time" varchar, + "receive_reason" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '交易售后表'; + +CREATE TABLE IF NOT EXISTS "trade_after_sale_log" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint NOT NULL, + "user_type" int NOT NULL, + "after_sale_id" bigint NOT NULL, + "order_id" bigint NOT NULL, + "order_item_id" bigint NOT NULL, + "before_status" int, + "after_status" int NOT NULL, + "content" varchar NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '交易售后日志'; diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java index 235ebb2c4..6cbb781bf 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApi.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.member.api.user; -import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import java.util.Collection; import java.util.List; @@ -21,7 +21,7 @@ public interface MemberUserApi { * @param id 用户编号 * @return 用户信息 */ - UserRespDTO getUser(Long id); + MemberUserRespDTO getUser(Long id); /** * 获得会员用户信息们 @@ -29,7 +29,7 @@ public interface MemberUserApi { * @param ids 用户编号的数组 * @return 用户信息们 */ - List getUsers(Collection ids); + List getUsers(Collection ids); /** * 获得会员用户 Map @@ -37,8 +37,8 @@ public interface MemberUserApi { * @param ids 用户编号的数组 * @return 会员用户 Map */ - default Map getUserMap(Collection ids) { - return convertMap(getUsers(ids), UserRespDTO::getId); + default Map getUserMap(Collection ids) { + return convertMap(getUsers(ids), MemberUserRespDTO::getId); } /** @@ -47,6 +47,14 @@ public interface MemberUserApi { * @param nickname 用户昵称,模糊匹配 * @return 用户信息的列表 */ - List getUserListByNickname(String nickname); + List getUserListByNickname(String nickname); + + /** + * 基于手机号,精准匹配用户 + * + * @param mobile 手机号 + * @return 用户信息 + */ + MemberUserRespDTO getUserByMobile(String mobile); } diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java similarity index 93% rename from yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java rename to yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java index e7a5aba9a..7b2bac0c9 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java @@ -9,7 +9,7 @@ import lombok.Data; * @author 芋道源码 */ @Data -public class UserRespDTO { +public class MemberUserRespDTO { /** * 用户ID diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java index 0c3e616a0..37aee217e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/user/MemberUserApiImpl.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.member.api.user; -import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.member.convert.user.UserConvert; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.service.user.MemberUserService; @@ -24,19 +24,24 @@ public class MemberUserApiImpl implements MemberUserApi { private MemberUserService userService; @Override - public UserRespDTO getUser(Long id) { + public MemberUserRespDTO getUser(Long id) { MemberUserDO user = userService.getUser(id); return UserConvert.INSTANCE.convert2(user); } @Override - public List getUsers(Collection ids) { + public List getUsers(Collection ids) { return UserConvert.INSTANCE.convertList2(userService.getUserList(ids)); } @Override - public List getUserListByNickname(String nickname) { + public List getUserListByNickname(String nickname) { return UserConvert.INSTANCE.convertList2(userService.getUserListByNickname(nickname)); } + @Override + public MemberUserRespDTO getUserByMobile(String mobile) { + return UserConvert.INSTANCE.convert2(userService.getUserByMobile(mobile)); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java index c2128c104..805ade807 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.member.convert.user; -import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserInfoRespVO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import org.mapstruct.Mapper; @@ -15,8 +15,8 @@ public interface UserConvert { AppUserInfoRespVO convert(MemberUserDO bean); - UserRespDTO convert2(MemberUserDO bean); + MemberUserRespDTO convert2(MemberUserDO bean); - List convertList2(List list); + List convertList2(List list); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index da3b4fd4a..b0a2edc79 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -31,7 +31,6 @@ public interface MemberUserService { */ List getUserListByNickname(String nickname); - /** * 基于手机号创建用户。 * 如果用户已经存在,则直接进行返回 diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayOrderNotifyReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayOrderNotifyReqDTO.java new file mode 100644 index 000000000..8920884ff --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayOrderNotifyReqDTO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.pay.api.notify.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 支付单的通知 Request DTO + * + * @author 芋道源码 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PayOrderNotifyReqDTO { + + /** + * 商户订单编号 + */ + @NotEmpty(message = "商户订单号不能为空") + private String merchantOrderId; + + /** + * 支付订单编号 + */ + @NotNull(message = "支付订单编号不能为空") + private Long payOrderId; + +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java new file mode 100644 index 000000000..879854264 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.pay.api.notify.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 退款单的通知 Request DTO + * + * @author 芋道源码 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PayRefundNotifyReqDTO { + + /** + * 商户退款单编号 + */ + @NotEmpty(message = "商户退款单编号不能为空") + private String merchantOrderId; + + /** + * 支付退款编号 + */ + @NotNull(message = "支付退款编号不能为空") + private Long payRefundId; + + /** + * 退款状态 + * + * (成功,失败) TODO 芋艿:枚举 + */ + @NotNull(message = "退款状态不能为空") + private Integer status; + +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/package-info.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/package-info.java new file mode 100644 index 000000000..60c4ca883 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位符,无特殊作用 + */ +package cn.iocoder.yudao.module.pay.api.notify; diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java index 36022b172..5c1905ebe 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApi.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.module.pay.api.order; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; + import javax.validation.Valid; /** @@ -16,6 +19,14 @@ public interface PayOrderApi { * @param reqDTO 创建请求 * @return 支付单编号 */ - Long createPayOrder(@Valid PayOrderInfoCreateReqDTO reqDTO); + Long createOrder(@Valid PayOrderCreateReqDTO reqDTO); + + /** + * 获得支付单 + * + * @param id 支付单编号 + * @return 支付单 + */ + PayOrderRespDTO getOrder(Long id); } diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderInfoCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderInfoCreateReqDTO.java deleted file mode 100644 index b5f64478d..000000000 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderInfoCreateReqDTO.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.pay.api.order; - -import lombok.Data; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.Min; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 支付单创建 Request DTO - * - * @author LeeYan9 - */ -@Data -public class PayOrderInfoCreateReqDTO implements Serializable { - - /** - * 应用编号 - */ - @NotNull(message = "应用编号不能为空") - private Long appId; - /** - * 用户 IP - */ - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - // ========== 商户相关字段 ========== - - /** - * 商户订单编号 - */ - @NotEmpty(message = "商户订单编号不能为空") - private String merchantOrderId; - /** - * 商品标题 - */ - @NotEmpty(message = "商品标题不能为空") - @Length(max = 32, message = "商品标题不能超过 32") - private String subject; - /** - * 商品描述 - */ -// @NotEmpty(message = "商品描述信息不能为空") // 允许空 - @Length(max = 128, message = "商品描述信息长度不能超过128") - private String body; - - // ========== 订单相关字段 ========== - - /** - * 支付金额,单位:分 - */ - @NotNull(message = "支付金额不能为空") - @Min(value = 1, message = "支付金额必须大于零") - private Integer amount; - - /** - * 支付过期时间 - */ - @NotNull(message = "支付过期时间不能为空") - private LocalDateTime expireTime; - -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java similarity index 93% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderCreateReqDTO.java rename to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java index 285158f0b..eb95ed657 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayOrderCreateReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.pay.service.order.dto; +package cn.iocoder.yudao.module.pay.api.order.dto; import lombok.Data; import org.hibernate.validator.constraints.Length; @@ -42,7 +42,7 @@ public class PayOrderCreateReqDTO implements Serializable { /** * 商品描述 */ - @NotEmpty(message = "商品描述信息不能为空") +// @NotEmpty(message = "商品描述信息不能为空") @Length(max = 128, message = "商品描述信息长度不能超过128") private String body; diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderRespDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderRespDTO.java new file mode 100644 index 000000000..1a053f68e --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderRespDTO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.pay.api.order.dto; + +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import lombok.Data; + +/** + * 支付单信息 Response DTO + * + * TODO 芋艿:还没定好字段 + * + * @author 芋道源码 + */ +@Data +public class PayOrderRespDTO { + + /** + * 订单编号,数据库自增 + */ + private Long id; + /** + * 渠道编码 + * + * 枚举 PayChannelEnum + */ + private String channelCode; + + // ========== 商户相关字段 ========== + /** + * 商户订单编号 + * 例如说,内部系统 A 的订单号。需要保证每个 PayMerchantDO 唯一 + */ + private String merchantOrderId; + + // ========== 订单相关字段 ========== + /** + * 支付金额,单位:分 + */ + private Integer amount; + /** + * 支付状态 + * + * 枚举 {@link PayOrderStatusEnum} + */ + private Integer status; + + // ========== 渠道相关字段 ========== + +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java new file mode 100644 index 000000000..395ba1220 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApi.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.pay.api.refund; + +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; + +import javax.validation.Valid; + +/** + * 退款单 API 接口 + * + * @author 芋道源码 + */ +public interface PayRefundApi { + + /** + * 创建退款单 + * + * @param reqDTO 创建请求 + * @return 退款单编号 + */ + Long createPayRefund(@Valid PayRefundCreateReqDTO reqDTO); + + /** + * 获得退款单 + * + * @param id 退款单编号 + * @return 退款单 + */ + PayRefundRespDTO getPayRefund(Long id); + +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java new file mode 100644 index 000000000..03c552640 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.pay.api.refund.dto; + +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * 退款单创建 Request DTO + * + * @author 芋道源码 + */ +@Data +public class PayRefundCreateReqDTO { + + /** + * 应用编号 + */ + @NotNull(message = "应用编号不能为空") + private Long appId; + /** + * 用户 IP + */ + @NotEmpty(message = "用户 IP 不能为空") + private String userIp; + + // ========== 商户相关字段 ========== + + /** + * 商户订单编号 + */ + @NotEmpty(message = "商户订单编号不能为空") + private String merchantOrderId; + + /** + * 退款描述 + */ + @NotEmpty(message = "退款描述不能为空") + @Length(max = 128, message = "退款描述长度不能超过128") + private String reason; + + // ========== 订单相关字段 ========== + + /** + * 退款金额,单位:分 + */ + @NotNull(message = "退款金额不能为空") + @Min(value = 1, message = "退款金额必须大于零") + private Integer amount; +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java new file mode 100644 index 000000000..c3bd38b5e --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.pay.api.refund.dto; + +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 退款单信息 Response DTO + * + * TODO 芋艿:还没定好字段 + * + * @author 芋道源码 + */ +@Data +public class PayRefundRespDTO { + + /** + * 退款单编号 + */ + private Long id; + + // ========== 退款相关字段 ========== + /** + * 退款状态 + * + * 枚举 {@link PayRefundStatusEnum} + */ + private Integer status; + + // ========== 渠道相关字段 ========== + /** + * 退款成功时间 + */ + private LocalDateTime successTime; + +} diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java index 203cb0703..9a68b9bc4 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java @@ -28,9 +28,9 @@ public interface ErrorCodeConstants { ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001007,"微信渠道v3版本apiclient_key.pem不可为空"); ErrorCode CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL = new ErrorCode(1007001008,"微信渠道v3版本中apiclient_cert.pem不可为空"); ErrorCode PAY_CHANNEL_NOTIFY_VERIFY_FAILED = new ErrorCode(1007001009, "渠道通知校验失败"); - /** - * ========== ORDER 模块 1-007-002-000 ========== - */ + + // ========== ORDER 模块 1-007-002-000 ========== + ErrorCode PAY_ORDER_NOT_FOUND = new ErrorCode(1007002000, "支付订单不存在"); ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1007002001, "支付订单不处于待支付"); ErrorCode PAY_ORDER_STATUS_IS_NOT_SUCCESS = new ErrorCode(1007002002, "支付订单不处于已支付"); @@ -57,8 +57,4 @@ public interface ErrorCodeConstants { ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除"); - - - - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java similarity index 71% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java rename to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java index ab542a97c..b4a5b2b98 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/order/PayOrderStatusEnum.java @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Objects; + /** * 支付订单的状态枚举 * @@ -26,4 +28,14 @@ public enum PayOrderStatusEnum implements IntArrayValuable { return new int[0]; } + /** + * 判断是否支付成功 + * + * @param status 状态 + * @return 是否支付成功 + */ + public static boolean isSuccess(Integer status) { + return Objects.equals(status, SUCCESS.getStatus()); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java similarity index 71% rename from yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java rename to yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java index 390804dd3..3fb8213f5 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/refund/PayRefundStatusEnum.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.enums.refund; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Objects; + @Getter @AllArgsConstructor public enum PayRefundStatusEnum { @@ -14,4 +16,9 @@ public enum PayRefundStatusEnum { private final Integer status; private final String name; + + public static boolean isSuccess(Integer status) { + return Objects.equals(status, SUCCESS.getStatus()); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/PayOrderApiImpl.java deleted file mode 100644 index d5dd64146..000000000 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/PayOrderApiImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.pay.api; - -import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; -import cn.iocoder.yudao.module.pay.api.order.PayOrderInfoCreateReqDTO; -import org.springframework.stereotype.Service; - -/** - * TODO 注释 - */ -@Service -public class PayOrderApiImpl implements PayOrderApi { - - @Override - public Long createPayOrder(PayOrderInfoCreateReqDTO reqDTO) { - return null; - } - -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java index 6f2556d35..d7299926b 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/order/PayOrderApiImpl.java @@ -1,19 +1,34 @@ -//package cn.iocoder.yudao.module.pay.api.order; -// -//import org.springframework.stereotype.Service; -//import org.springframework.transaction.annotation.Transactional; -// -///** -// * @author LeeYan9 -// * @since 2022-09-06 -// */ -//@Service -//public class PayOrderApiImpl implements PayOrderApi { -// -// @Override -// @Transactional(rollbackFor = Exception.class) -// public Long createPayOrder(PayOrderInfoCreateReqDTO reqDTO) { -// return null; -// } -// -//} +package cn.iocoder.yudao.module.pay.api.order; + +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * 支付单 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class PayOrderApiImpl implements PayOrderApi { + + @Resource + private PayOrderService payOrderService; + + @Override + public Long createOrder(PayOrderCreateReqDTO reqDTO) { + return payOrderService.createPayOrder(reqDTO); + } + + @Override + public PayOrderRespDTO getOrder(Long id) { + PayOrderDO order = payOrderService.getOrder(id); + return PayOrderConvert.INSTANCE.convert2(order); + } + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java new file mode 100644 index 000000000..454aa7b87 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.pay.api.refund; + +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * 退款单 API 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class PayRefundApiImpl implements PayRefundApi { + + @Override + public Long createPayRefund(PayRefundCreateReqDTO reqDTO) { + // TODO 芋艿:暂未实现 + return null; + } + + @Override + public PayRefundRespDTO getPayRefund(Long id) { + // TODO 芋艿:暂未实现 + return null; + } + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java new file mode 100644 index 000000000..fa9177538 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.module.pay.controller.admin.notify; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.pay.core.client.PayClient; +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.annotation.security.PermitAll; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND; + +@Api(tags = "管理后台 - 支付通知") +@RestController +@RequestMapping("/pay/notify") +@Validated +@Slf4j +public class PayNotifyController { + + @Resource + private PayOrderService orderService; + @Resource + private PayRefundService refundService; + + @Resource + private PayClientFactory payClientFactory; + + /** + * 统一的跳转页面,支付宝跳转参数说明 + * + * 支付宝 - 前台回跳参数说明 + * + * @param channelId 渠道编号 + * @return 返回跳转页面 + */ + @GetMapping(value = "/return/{channelId}") + @ApiOperation("渠道统一的支付成功返回地址") + @Deprecated // TODO yunai:如果是 way 的情况,应该是跳转回前端地址 + public String returnCallback(@PathVariable("channelId") Long channelId, + @RequestParam Map params) { + log.info("[returnCallback][app_id({}) 跳转]", params.get("app_id")); + return String.format("渠道[%s]支付成功", channelId); + } + + /** + * 统一的渠道支付回调,支付宝的退款回调 + * + * @param channelId 渠道编号 + * @param params form 参数 + * @param body request body + * @return 成功返回 "success" + */ + @PostMapping(value = "/callback/{channelId}") + @ApiOperation(value = "支付渠道的统一回调接口", notes = "包括支付回调,退款回调") + @PermitAll + @OperateLog(enable = false) // 回调地址,无需记录操作日志 + public String notifyCallback(@PathVariable("channelId") Long channelId, + @RequestParam Map params, + @RequestBody String body) throws Exception { + // 校验支付渠道是否存在 + PayClient payClient = payClientFactory.getPayClient(channelId); + if (payClient == null) { + log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId); + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); + } + // 校验通知数据是否合法 + PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(body).build(); + payClient.verifyNotifyData(notifyData); + + // 情况一:如果是退款,则发起退款通知 + if (payClient.isRefundNotify(notifyData)) { + refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(body).build()); + return "success"; + } + + // 情况二:如果非退款,则发起支付通知 + orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(body).build()); + return "success"; + } + + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http new file mode 100644 index 000000000..539d7965d --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.http @@ -0,0 +1,10 @@ +### /pay/create 提交支付订单 +POST {{appApi}}/pay/order/submit +Content-Type: application/json +Authorization: Bearer {{appToken}} +tenant-id: {{appTenentId}} + +{ + "id": 125, + "channelCode": "alipay_qr" +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java index e01f7f4f4..72f037a28 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java @@ -2,29 +2,25 @@ package cn.iocoder.yudao.module.pay.controller.app.order; import cn.hutool.core.bean.BeanUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.pay.core.client.PayClient; -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; -import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO; import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; -import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; -import java.util.Map; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; @Api(tags = "用户 APP - 支付订单") @RestController @@ -35,11 +31,6 @@ public class AppPayOrderController { @Resource private PayOrderService orderService; - @Resource - private PayRefundService refundService; - - @Resource - private PayClientFactory payClientFactory; @PostMapping("/submit") @ApiOperation("提交支付订单") @@ -59,64 +50,4 @@ public class AppPayOrderController { return success(AppPayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build()); } - // ========== 支付渠道的回调 ========== - // TODO @芋艿:是不是放到 notify 模块更合适 - //TODO 芋道源码 换成了统一的地址了 /notify/{channelId},测试通过可以删除 - @PostMapping("/notify/wx-pub/{channelId}") - @ApiOperation("通知微信公众号支付的结果") - public String notifyWxPayOrder(@PathVariable("channelId") Long channelId, - @RequestBody String xmlData) throws Exception { - orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().body(xmlData).build()); - return "success"; - } - - /** - * 统一的跳转页面, 支付宝跳转参数说明 - * https://opendocs.alipay.com/open/203/105285#%E5%89%8D%E5%8F%B0%E5%9B%9E%E8%B7%B3%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E - * @param channelId 渠道id - * @return 返回跳转页面 - */ - @GetMapping(value = "/return/{channelId}") - @ApiOperation("渠道统一的支付成功返回地址") - public String returnAliPayOrder(@PathVariable("channelId") Long channelId, @RequestParam Map params){ - //TODO 可以根据渠道和 app_id 返回不同的页面 - log.info("app_id is {}", params.get("app_id")); - return String.format("渠道[%s]支付成功", channelId); - } - - /** - * 统一的渠道支付回调,支付宝的退款回调 - * - * @param channelId 渠道编号 - * @param params form 参数 - * @param originData http request body - * @return 成功返回 "success" - */ - @PostMapping(value = "/notify/{channelId}") - @ApiOperation("渠道统一的支付成功,或退款成功 通知url") - public String notifyChannelPay(@PathVariable("channelId") Long channelId, - @RequestParam Map params, - @RequestBody String originData) throws Exception { - // 校验支付渠道是否存在 - PayClient payClient = payClientFactory.getPayClient(channelId); - if (payClient == null) { - log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId); - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); - } - - // 校验通知数据是否合法 - PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build(); - payClient.verifyNotifyData(notifyData); - - // 如果是退款,则发起退款通知 - if (payClient.isRefundNotify(notifyData)) { - refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); - return "success"; - } - - // 如果非退款,则发起支付通知 - orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build()); - return "success"; - } - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java index 49df1ea64..0c2b3fec5 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java @@ -1,16 +1,18 @@ package cn.iocoder.yudao.module.pay.convert.order; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderDetailsRespVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExcelVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageItemRespVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; -import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.math.BigDecimal; @@ -40,13 +42,14 @@ public interface PayOrderConvert { List convertList02(List list); /** - * 订单DO转自定义分页对象 + * 订单 DO 转自定义分页对象 * * @param bean 订单DO * @return 分页对象 */ PayOrderPageItemRespVO pageConvertItemPage(PayOrderDO bean); + // TODO 芋艿:优化下 convert 逻辑 default PayOrderExcelVO excelConvert(PayOrderDO bean) { if (bean == null) { return null; @@ -88,8 +91,11 @@ public interface PayOrderConvert { PayOrderDO convert(PayOrderCreateReqDTO bean); + @Mapping(target = "id", ignore = true) PayOrderExtensionDO convert(PayOrderSubmitReqDTO bean); PayOrderUnifiedReqDTO convert2(PayOrderSubmitReqDTO bean); + PayOrderRespDTO convert2(PayOrderDO bean); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java index 502c0515a..656cea01c 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -26,7 +26,7 @@ import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -public class PayChannelDO extends BaseDO { +public class PayChannelDO extends TenantBaseDO { /** * 渠道编号,数据库自增 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java index ad6f9ea7e..4f568ba5e 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java @@ -93,7 +93,7 @@ public class PayOrderDO extends BaseDO { /** * 支付金额,单位:分 */ - private Long amount; + private Integer amount; /** * 渠道手续费,单位:百分比 * diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java index 1ad5aa1c7..448cce30d 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java @@ -132,11 +132,11 @@ public class PayRefundDO extends BaseDO { /** * 支付金额,单位:分 */ - private Long payAmount; + private Integer payAmount; /** * 退款金额,单位:分 */ - private Long refundAmount; + private Integer refundAmount; /** * 退款原因 @@ -194,6 +194,4 @@ public class PayRefundDO extends BaseDO { private LocalDateTime notifyTime; - - } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java index fab0c8143..2907b75f3 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/job/notify/PayNotifyJob.java @@ -15,8 +15,8 @@ import javax.annotation.Resource; * @author 芋道源码 */ @Component +@TenantJob // 多租户 @Slf4j -@TenantJob public class PayNotifyJob implements JobHandler { @Resource diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/package-info.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/package-info.java index 1421e4e65..40ab66da0 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/package-info.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/package-info.java @@ -2,8 +2,8 @@ * pay 模块,我们放支付业务,提供业务的支付能力。 * 例如说:商户、应用、支付、退款等等 * - * 1. Controller URL:以 /member/ 开头,避免和其它 Module 冲突 - * 2. DataObject 表名:以 member_ 开头,方便在数据库中区分 + * 1. Controller URL:以 /pay/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 pay_ 开头,方便在数据库中区分 * * 注意,由于 Pay 模块和 Trade 模块,容易重名,所以类名都加载 Pay 的前缀~ */ diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java index 3907b0eca..166c50598 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelService.java @@ -22,7 +22,7 @@ public interface PayChannelService { /** * 初始化支付客户端 */ - void initPayClients(); + void initLocalCache(); /** * 创建支付渠道 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java index 08bd0f43e..e2fac7cad 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.pay.service.merchant; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; @@ -10,7 +9,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelExportReqVO; import cn.iocoder.yudao.module.pay.controller.admin.merchant.vo.channel.PayChannelPageReqVO; @@ -20,7 +19,6 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper; import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -66,53 +64,47 @@ public class PayChannelServiceImpl implements PayChannelService { @Resource private Validator validator; - @Resource - @Lazy // 注入自己,所以延迟加载 - private PayChannelService self; - + /** + * 初始化 {@link #payClientFactory} 缓存 + */ @Override @PostConstruct - @TenantIgnore // 忽略自动化租户,全局初始化本地缓存 - public void initPayClients() { - // 获取支付渠道,如果有更新 - List payChannels = loadPayChannelIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(payChannels)) { - return; - } - - // 创建或更新支付 Client - payChannels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), - payChannel.getCode(), payChannel.getConfig())); - - // 写入缓存 - maxUpdateTime = CollectionUtils.getMaxValue(payChannels, PayChannelDO::getUpdateTime); - log.info("[initPayClients][初始化 PayChannel 数量为 {}]", payChannels.size()); + public void initLocalCache() { + initLocalCacheIfUpdate(null); } @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) public void schedulePeriodicRefresh() { - self.initPayClients(); + initLocalCacheIfUpdate(this.maxUpdateTime); } /** - * 如果支付渠道发生变化,从数据库中获取最新的全量支付渠道。 - * 如果未发生变化,则返回空 + * 刷新本地缓存 * - * @param maxUpdateTime 当前支付渠道的最大更新时间 - * @return 支付渠道列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - private List loadPayChannelIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadPayChannelIfUpdate][首次加载全量支付渠道]"); - } else { // 判断数据库中是否有更新的支付渠道 - if (channelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 注意:忽略自动多租户,因为要全局初始化缓存 + TenantUtils.executeIgnore(() -> { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && channelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - log.info("[loadPayChannelIfUpdate][增量加载全量支付渠道]"); - } - // 第二步,如果有更新,则从数据库加载所有支付渠道 - return channelMapper.selectList(); + List channels = channelMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存支付渠道,数量为:{}]", channels.size()); + + // 第二步:构建缓存。创建或更新支付 Client + channels.forEach(payChannel -> payClientFactory.createOrUpdatePayClient(payChannel.getId(), + payChannel.getCode(), payChannel.getConfig())); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(channels, PayChannelDO::getUpdateTime); + }); } @Override diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java index bc941b06d..1f8131230 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java @@ -2,7 +2,13 @@ package cn.iocoder.yudao.module.pay.service.notify; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; @@ -13,11 +19,8 @@ import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; -import cn.iocoder.yudao.module.pay.service.notify.vo.PayNotifyOrderReqVO; -import cn.iocoder.yudao.module.pay.service.notify.vo.PayRefundOrderReqVO; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import lombok.extern.slf4j.Slf4j; @@ -30,7 +33,9 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -164,8 +169,9 @@ public class PayNotifyServiceImpl implements PayNotifyService { // 校验,当前任务是否已经被通知过 // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 PayNotifyTaskDO dbTask = payNotifyTaskCoreMapper.selectById(task.getId()); - if (DateUtils.afterNow(dbTask.getNextNotifyTime())) { - log.info("[executeNotify][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", JsonUtils.toJsonString(dbTask)); + if (LocalDateTimeUtils.afterNow(dbTask.getNextNotifyTime())) { + log.info("[executeNotifySync][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", + JsonUtils.toJsonString(dbTask)); return; } @@ -185,11 +191,12 @@ public class PayNotifyServiceImpl implements PayNotifyService { invokeException = e; } - // 处理 - Integer newStatus = this.processNotifyResult(task, invokeResult, invokeException); + // 处理结果 + Integer newStatus = processNotifyResult(task, invokeResult, invokeException); // 记录 PayNotifyLog 日志 - String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : JsonUtils.toJsonString(invokeResult); + String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : + JsonUtils.toJsonString(invokeResult); payNotifyLogCoreMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); } @@ -201,22 +208,28 @@ public class PayNotifyServiceImpl implements PayNotifyService { * @return HTTP 响应 */ private CommonResult executeNotifyInvoke(PayNotifyTaskDO task) { - // 拼接参数 + // 拼接 body 参数 Object request; if (Objects.equals(task.getType(), PayNotifyTypeEnum.ORDER.getType())) { - request = PayNotifyOrderReqVO.builder().merchantOrderId(task.getMerchantOrderId()) - .payOrderId(task.getDataId()).build(); + request = PayOrderNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId()) + .payOrderId(task.getDataId()).build(); } else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) { - request = PayRefundOrderReqVO.builder().merchantOrderId(task.getMerchantOrderId()) + request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId()) .payRefundId(task.getDataId()).build(); } else { throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task)); } - // 请求地址 - String response = HttpUtil.post(task.getNotifyUrl(), JsonUtils.toJsonString(request), - (int) NOTIFY_TIMEOUT_MILLIS); - // 解析结果 - return JsonUtils.parseObject(response, CommonResult.class); + // 拼接 header 参数 + Map headers = new HashMap<>(); + TenantUtils.addTenantHeader(headers); + + // 发起请求 + try (HttpResponse response = HttpUtil.createPost(task.getNotifyUrl()) + .body(JsonUtils.toJsonString(request)).addHeaders(headers) + .timeout((int) NOTIFY_TIMEOUT_MILLIS).execute()) { + // 解析结果 + return JsonUtils.parseObject(response.body(), CommonResult.class); + } } /** diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java deleted file mode 100644 index d4f6c1eae..000000000 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.pay.service.notify.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -@ApiModel(value = "支付单的通知 Request VO", description = "业务方接入支付回调时,使用该 VO 对象") -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class PayNotifyOrderReqVO { - - @ApiModelProperty(value = "商户订单编号", required = true, example = "10") - @NotEmpty(message = "商户订单号不能为空") - private String merchantOrderId; - - @ApiModelProperty(value = "支付订单编号", required = true, example = "20") - @NotNull(message = "支付订单编号不能为空") - private Long payOrderId; - -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java deleted file mode 100644 index 978283d1b..000000000 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.pay.service.notify.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -@ApiModel(value = "退款单的通知 Request VO", description = "业务方接入退款回调时,使用该 VO 对象") -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class PayRefundOrderReqVO { - - @ApiModelProperty(value = "商户退款单编号", required = true, example = "10") - @NotEmpty(message = "商户退款单编号不能为空") - private String merchantOrderId; - - @ApiModelProperty(value = "支付退款编号", required = true, example = "20") - @NotNull(message = "支付退款编号不能为空") - private Long payRefundId; - - @ApiModelProperty(value = "退款状态(成功,失败)", required = true, example = "10") - private Integer status; - -} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/package-info.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/package-info.java deleted file mode 100644 index fb006dd68..000000000 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 这里的 VO 包有点特殊,是提供给接入支付模块的业务,提供回调接口时,可以直接使用 VO - * - * 例如说,支付单的回调,使用 TODO 芋艿:想下怎么优化下 - */ -package cn.iocoder.yudao.module.pay.service.notify.vo; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java index 40ed287fc..6c7bd972a 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; -import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 67a3e7152..655c43ee2 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.pay.service.order; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.pay.config.PayProperties; import cn.iocoder.yudao.framework.pay.core.client.PayClient; @@ -11,6 +12,8 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderExportReqVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderPageReqVO; import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; @@ -28,8 +31,6 @@ import cn.iocoder.yudao.module.pay.service.merchant.PayAppService; import cn.iocoder.yudao.module.pay.service.merchant.PayChannelService; import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; import lombok.extern.slf4j.Slf4j; @@ -43,6 +44,8 @@ import java.util.Collection; import java.util.List; import java.util.Objects; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; + /** * 支付订单 Service 实现类 * @@ -103,7 +106,7 @@ public class PayOrderServiceImpl implements PayOrderService { if (order != null) { log.warn("[createPayOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(), order.getMerchantOrderId(), JsonUtils.toJsonString(order)); // 理论来说,不会出现这个情况 - return app.getId(); + return order.getId(); } // 创建支付交易单 @@ -133,16 +136,16 @@ public class PayOrderServiceImpl implements PayOrderService { PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[submitPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); + throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); } // 获得 PayOrderDO ,并校验其是否存在 PayOrderDO order = orderMapper.selectById(reqDTO.getId()); if (order == null || !Objects.equals(order.getAppId(), reqDTO.getAppId())) { // 是否存在 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); + throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); } if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); + throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); } // 插入 PayOrderExtensionDO @@ -177,7 +180,7 @@ public class PayOrderServiceImpl implements PayOrderService { * @return 支付成功返回的地址。 配置地址 + "/" + channel id */ private String genChannelReturnUrl(PayChannelDO channel) { - return payProperties.getPayReturnUrl() + "/" + channel.getId(); + return payProperties.getReturnUrl() + "/" + channel.getId(); } /** @@ -187,8 +190,7 @@ public class PayOrderServiceImpl implements PayOrderService { * @return 支付渠道的回调地址 配置地址 + "/" + channel id */ private String genChannelPayNotifyUrl(PayChannelDO channel) { - //去掉channel code, 似乎没啥用, 用统一的回调地址 - return payProperties.getPayNotifyUrl() + "/" + channel.getId(); + return payProperties.getCallbackUrl() + "/" + channel.getId(); } private String generateOrderExtensionNo() { @@ -210,64 +212,99 @@ public class PayOrderServiceImpl implements PayOrderService { } @Override - @Transactional - public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception { + @Transactional(rollbackFor = Exception.class) + public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) { // TODO 芋艿,记录回调日志 log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); // 校验支付渠道是否有效 PayChannelDO channel = channelService.validPayChannel(channelId); + TenantUtils.execute(channel.getTenantId(), () -> { + try { + notifyPayOrder(channel, notifyData); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + private void notifyPayOrder(PayChannelDO channel, PayNotifyDataDTO notifyData) throws Exception { // 校验支付客户端是否正确初始化 PayClient client = payClientFactory.getPayClient(channel.getId()); if (client == null) { log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); + throw exception(ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND); } - // 解析支付结果 + // 0. 解析支付结果 PayOrderNotifyRespDTO notifyRespDTO = client.parseOrderNotify(notifyData); - - // TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。 - // 1.1 查询 PayOrderExtensionDO - PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(notifyRespDTO.getOrderExtensionNo()); - if (orderExtension == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND); - } - if (!PayOrderStatusEnum.WAITING.getStatus().equals(orderExtension.getStatus())) { // 校验状态,必须是待支付 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); - } - // 1.2 更新 PayOrderExtensionDO - //TODO 支付宝交易超时 TRADE_FINISHED 需要更新交易关闭 - int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), - PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId()) - .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData.getBody()).build()); - if (updateCounts == 0) { // 校验状态,必须是待支付 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); - } - log.info("[notifyPayOrder][支付拓展单({}) 更新为已支付]", orderExtension.getId()); - - // 2.1 判断 PayOrderDO 是否处于待支付 - PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); - if (order == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); - } - if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); - } - // 2.2 更新 PayOrderDO - updateCounts = orderMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), - PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelId(channelId).channelCode(channel.getCode()) - .successTime(notifyRespDTO.getSuccessTime()).successExtensionId(orderExtension.getId()) - .channelOrderNo(notifyRespDTO.getChannelOrderNo()).channelUserId(notifyRespDTO.getChannelUserId()) - .notifyTime(LocalDateTime.now()).build()); - if (updateCounts == 0) { // 校验状态,必须是待支付 - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); - } - log.info("[notifyPayOrder][支付订单({}) 更新为已支付]", order.getId()); + // 1. 更新 PayOrderExtensionDO 支付成功 + PayOrderExtensionDO orderExtension = updatePayOrderExtensionSuccess(notifyRespDTO.getOrderExtensionNo(), notifyData.getBody()); + // 2. 更新 PayOrderDO 支付成功 + PayOrderDO order = updatePayOrderSuccess(channel, orderExtension, notifyRespDTO); // 3. 插入支付通知记录 notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() .type(PayNotifyTypeEnum.ORDER.getType()).dataId(order.getId()).build()); } + /** + * 更新 PayOrderExtensionDO 支付成功 + * + * @param no 支付订单号(支付模块) + * @param body 回调内容 + * @return PayOrderExtensionDO 对象 + */ + private PayOrderExtensionDO updatePayOrderExtensionSuccess(String no, String body) { + // 1.1 查询 PayOrderExtensionDO + PayOrderExtensionDO orderExtension = orderExtensionMapper.selectByNo(no); + if (orderExtension == null) { + throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_NOT_FOUND); + } + if (ObjectUtil.notEqual(orderExtension.getStatus(), PayOrderStatusEnum.WAITING.getStatus())) { // 校验状态,必须是待支付 + throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + } + // 1.2 更新 PayOrderExtensionDO + int updateCounts = orderExtensionMapper.updateByIdAndStatus(orderExtension.getId(), + PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId()) + .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(body).build()); + if (updateCounts == 0) { // 校验状态,必须是待支付 + throw exception(ErrorCodeConstants.PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); + } + log.info("[updatePayOrderSuccess][支付拓展单({}) 更新为已支付]", orderExtension.getId()); + return orderExtension; + } + + /** + * 更新 PayOrderDO 支付成功 + * + * @param channel 支付渠道 + * @param orderExtension 支付拓展单 + * @param notifyRespDTO 通知回调 + * @return PayOrderDO 对象 + */ + private PayOrderDO updatePayOrderSuccess(PayChannelDO channel, PayOrderExtensionDO orderExtension, + PayOrderNotifyRespDTO notifyRespDTO) { + // 2.1 判断 PayOrderDO 是否处于待支付 + PayOrderDO order = orderMapper.selectById(orderExtension.getOrderId()); + if (order == null) { + throw exception(ErrorCodeConstants.PAY_ORDER_NOT_FOUND); + } + if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付 + throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); + } + // 2.2 更新 PayOrderDO + int updateCounts = orderMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(), + PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()) + .channelId(channel.getId()).channelCode(channel.getCode()) + .successTime(notifyRespDTO.getSuccessTime()).successExtensionId(orderExtension.getId()) + .channelOrderNo(notifyRespDTO.getChannelOrderNo()).channelUserId(notifyRespDTO.getChannelUserId()) + .notifyTime(LocalDateTime.now()).build()); + if (updateCounts == 0) { // 校验状态,必须是待支付 + throw exception(ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING); + } + log.info("[updatePayOrderSuccess][支付订单({}) 更新为已支付]", order.getId()); + return order; + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java index 0eb24dbe2..31d19b91a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/dto/PayRefundReqDTO.java @@ -31,7 +31,7 @@ public class PayRefundReqDTO { */ @NotNull(message = "退款金额不能为空") @DecimalMin(value = "0", inclusive = false, message = "退款金额必须大于零") - private Long amount; + private Integer amount; /** * 退款原因 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/package-info.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/package-info.java deleted file mode 100644 index 2cad91eba..000000000 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.pay.service; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java index d51d00c20..c243a23c3 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java @@ -130,7 +130,7 @@ public class PayRefundServiceImpl implements PayRefundService { } else { // 成功,插入退款单 状态为生成.没有和渠道交互 // TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下; - payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo()) + payRefundDO = PayRefundDO.builder() .appId(order.getAppId()) .channelOrderNo(order.getChannelOrderNo()) .channelCode(order.getChannelCode()) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java index 2a63c3aea..95851a551 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayAppServiceTest.java @@ -22,7 +22,7 @@ import java.time.LocalDateTime; import java.util.Collections; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -123,7 +123,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { o.setPayNotifyUrl("https://www.hc.com"); o.setRefundNotifyUrl("https://www.xm.com"); o.setMerchantId(merchantId); - o.setCreateTime(buildLocalDateTime(2021,11,20)); + o.setCreateTime(buildTime(2021,11,20)); }); // mock 数据 @@ -134,7 +134,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { o.setShortName("灿灿子"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setRemark("灿哥的杂货铺"); - o.setCreateTime(buildLocalDateTime(2021,11,3)); + o.setCreateTime(buildTime(2021,11,3)); }); Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName())) @@ -154,7 +154,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { // 测试 merchantId 不匹配 appMapper.insert(cloneIgnoreId(dbApp, o -> o.setMerchantId(mismatchMerchantId))); // 测试 createTime 不匹配 - appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildLocalDateTime(2021,12,21)))); + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21)))); // 准备参数 PayAppPageReqVO reqVO = new PayAppPageReqVO(); reqVO.setName("灿灿姐的杂货铺"); @@ -163,7 +163,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { reqVO.setPayNotifyUrl("https://www.hc.com"); reqVO.setRefundNotifyUrl("https://www.xm.com"); reqVO.setMerchantName(dbMerchant.getName()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021,11,19),buildLocalDateTime(2021,11,21)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,19),buildTime(2021,11,21)})); // 调用 PageResult pageResult = appService.getAppPage(reqVO); @@ -186,7 +186,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { o.setPayNotifyUrl("https://www.hc.com"); o.setRefundNotifyUrl("https://www.xm.com"); o.setMerchantId(merchantId); - o.setCreateTime(buildLocalDateTime(2021,11,20)); + o.setCreateTime(buildTime(2021,11,20)); }); // mock 数据 @@ -197,7 +197,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { o.setShortName("灿灿子"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setRemark("灿哥的杂货铺"); - o.setCreateTime(buildLocalDateTime(2021,11,3)); + o.setCreateTime(buildTime(2021,11,3)); }); Mockito.when(payMerchantMapper.getMerchantListByName(dbMerchant.getName())) @@ -217,7 +217,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { // 测试 merchantId 不匹配 appMapper.insert(cloneIgnoreId(dbApp, o -> o.setMerchantId(mismatchMerchantId))); // 测试 createTime 不匹配 - appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildLocalDateTime(2021,12,21)))); + appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21)))); // 准备参数 PayAppExportReqVO reqVO = new PayAppExportReqVO(); reqVO.setName("灿灿姐的杂货铺"); @@ -226,7 +226,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { reqVO.setPayNotifyUrl("https://www.hc.com"); reqVO.setRefundNotifyUrl("https://www.xm.com"); reqVO.setMerchantName(dbMerchant.getName()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021,11,19),buildLocalDateTime(2021,11,21)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,19),buildTime(2021,11,21)})); // 调用 List list = appService.getAppList(reqVO); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java index 36e9ccfd2..44ea6c0b9 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceTest.java @@ -23,7 +23,7 @@ import javax.validation.Validator; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -49,7 +49,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @Test public void testCreateWechatVersion2Channel_success() { // 准备参数 - WXPayClientConfig v2Config = getV2Config(); PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { o.setCode(PayChannelEnum.WX_PUB.getCode()); @@ -215,7 +214,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { o.setMerchantId(1L); o.setAppId(1L); o.setConfig(payClientConfig); - o.setCreateTime(buildLocalDateTime(2021,11,20)); + o.setCreateTime(buildTime(2021,11,20)); }); channelMapper.insert(dbChannel); // 执行拷贝的时候会出现异常,所以在插入后要重置为null 后续在写入新的 @@ -253,7 +252,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 channelMapper.insert(cloneIgnoreId(dbChannel, o -> { o.setConfig(payClientConfig); - o.setCreateTime(buildLocalDateTime(2021, 10, 20)); + o.setCreateTime(buildTime(2021, 10, 20)); })); // 准备参数 PayChannelPageReqVO reqVO = new PayChannelPageReqVO(); @@ -264,7 +263,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { reqVO.setMerchantId(1L); reqVO.setAppId(1L); reqVO.setConfig(JSON.toJSONString(payClientConfig)); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021,11,19),buildLocalDateTime(2021,11,21)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,19),buildTime(2021,11,21)})); // 调用 PageResult pageResult = channelService.getChannelPage(reqVO); @@ -288,7 +287,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { o.setMerchantId(1L); o.setAppId(1L); o.setConfig(payClientConfig); - o.setCreateTime(buildLocalDateTime(2021,11,20)); + o.setCreateTime(buildTime(2021,11,20)); }); channelMapper.insert(dbChannel); // 执行拷贝的时候会出现异常,所以在插入后要重置为null 后续在写入新的 @@ -326,7 +325,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { // 测试 createTime 不匹配 channelMapper.insert(cloneIgnoreId(dbChannel, o -> { o.setConfig(payClientConfig); - o.setCreateTime(buildLocalDateTime(2021, 10, 20)); + o.setCreateTime(buildTime(2021, 10, 20)); })); // 准备参数 PayChannelExportReqVO reqVO = new PayChannelExportReqVO(); @@ -337,7 +336,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { reqVO.setMerchantId(1L); reqVO.setAppId(1L); reqVO.setConfig(JSON.toJSONString(payClientConfig)); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021,11,19),buildLocalDateTime(2021,11,21)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,19),buildTime(2021,11,21)})); // 调用 List list = channelService.getChannelList(reqVO); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java index 766ef36db..de3f6904f 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/merchant/PayMerchantServiceTest.java @@ -17,7 +17,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -116,7 +116,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { o.setShortName("灿灿子"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setRemark("灿哥的杂货铺"); - o.setCreateTime(buildLocalDateTime(2021,11,3)); + o.setCreateTime(buildTime(2021,11,3)); }); merchantMapper.insert(dbMerchant); // 测试 no 不匹配 @@ -130,7 +130,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { // 测试 remark 不匹配 merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setRemark("斌哥的杂货铺"))); // 测试 createTime 不匹配 - merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildLocalDateTime(2022,12,4)))); + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildTime(2022,12,4)))); // 准备参数 PayMerchantPageReqVO reqVO = new PayMerchantPageReqVO(); reqVO.setNo("M1008611"); @@ -138,7 +138,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { reqVO.setShortName("灿灿子"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setRemark("灿哥的杂货铺"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021,11,2),buildLocalDateTime(2021,11,4)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,2),buildTime(2021,11,4)})); // 调用 PageResult pageResult = merchantService.getMerchantPage(reqVO); @@ -157,7 +157,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { o.setShortName("灿灿子"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setRemark("灿哥的杂货铺"); - o.setCreateTime(buildLocalDateTime(2021,11,3)); + o.setCreateTime(buildTime(2021,11,3)); }); merchantMapper.insert(dbMerchant); // 测试 no 不匹配 @@ -171,7 +171,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { // 测试 remark 不匹配 merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setRemark("斌哥的杂货铺"))); // 测试 createTime 不匹配 - merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildLocalDateTime(2022,12,4)))); + merchantMapper.insert(cloneIgnoreId(dbMerchant, o -> o.setCreateTime(buildTime(2022,12,4)))); // 准备参数 PayMerchantExportReqVO reqVO = new PayMerchantExportReqVO(); reqVO.setNo("M1008611"); @@ -179,7 +179,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { reqVO.setShortName("灿灿子"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setRemark("灿哥的杂货铺"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021,11,2),buildLocalDateTime(2021,11,4)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,2),buildTime(2021,11,4)})); // 调用 List list = merchantService.getMerchantList(reqVO); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java index 8cb3efa7a..774ec3ade 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java @@ -76,7 +76,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { o.setBody("斌斌子送给灿灿子的炸弹猫"); o.setNotifyUrl("https://hc.com/lbh"); o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); - o.setAmount(10000L); + o.setAmount(10000); o.setChannelFeeRate(0.01); o.setChannelFeeAmount(1L); o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); @@ -148,7 +148,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest { o.setBody("斌斌子送给灿灿子的炸弹猫"); o.setNotifyUrl("https://hc.com/lbh"); o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); - o.setAmount(10000L); + o.setAmount(10000); o.setChannelFeeRate(0.01); o.setChannelFeeAmount(1L); o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java index 3815e1620..da42e7cf2 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java @@ -67,8 +67,8 @@ public class PayRefundServiceTest extends BaseDbUnitTest { o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); o.setType(PayRefundTypeEnum.SOME.getStatus()); - o.setPayAmount(100L); - o.setRefundAmount(500L); + o.setPayAmount(100); + o.setRefundAmount(500); o.setReason("就是想退款了,你有意见吗"); o.setUserIp("127.0.0.1"); o.setChannelOrderNo("CH0000001"); @@ -136,8 +136,8 @@ public class PayRefundServiceTest extends BaseDbUnitTest { o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus()); o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus()); o.setType(PayRefundTypeEnum.SOME.getStatus()); - o.setPayAmount(100L); - o.setRefundAmount(500L); + o.setPayAmount(100); + o.setRefundAmount(500); o.setReason("就是想退款了,你有意见吗"); o.setUserIp("127.0.0.1"); o.setChannelOrderNo("CH0000001"); diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql b/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql index 890fb7700..09cfa2887 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql @@ -43,6 +43,7 @@ CREATE TABLE IF NOT EXISTS "pay_channel" ( "updater" varchar(64) NULL DEFAULT '', "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, "deleted" bit(1) NOT NULL DEFAULT FALSE, + "tenant_id" bigint not null default '0', PRIMARY KEY ("id") ) COMMENT = '支付渠道'; diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 97bb86262..e5e416d0e 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -139,6 +139,6 @@ public interface ErrorCodeConstants { // ========== OAuth2 授权 1002022000 ========= ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在"); - ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022000, "code 已过期"); + ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022001, "code 已过期"); } diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index ecac34aa5..f1887ea90 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -54,6 +54,10 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-tenant + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java index 8fbb7c0ca..fbdd665e8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java @@ -30,6 +30,7 @@ public class CaptchaController extends com.anji.captcha.controller.CaptchaContro @ApiOperation("获得验证码") @PermitAll @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + @Override public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) { return super.get(data, request); } @@ -38,6 +39,7 @@ public class CaptchaController extends com.anji.captcha.controller.CaptchaContro @ApiOperation("校验验证码") @PermitAll @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + @Override public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) { return super.check(data, request); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.http b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.http new file mode 100644 index 000000000..f1b893d01 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.http @@ -0,0 +1,5 @@ +### 获得地区树 +GET {{baseUrl}}/system/area/tree +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java new file mode 100644 index 000000000..a7e4d3e03 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.system.controller.admin.ip; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; +import cn.iocoder.yudao.framework.ip.core.utils.IPUtils; +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; +import cn.iocoder.yudao.module.system.convert.ip.AreaConvert; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Api(tags = "管理后台 - 地区") +@RestController +@RequestMapping("/system/area") +@Validated +public class AreaController { + + @GetMapping("/tree") + @ApiOperation("获得地区树") + public CommonResult> getAreaTree() { + Area area = AreaUtils.getArea(Area.ID_CHINA); + Assert.notNull(area, "获取不到中国"); + return success(AreaConvert.INSTANCE.convertList(area.getChildren())); + } + + @GetMapping("/get-by-ip") + @ApiOperation("获得 IP 对应的地区名") + @ApiImplicitParam(name = "ip", value = "IP", required = true, dataTypeClass = String.class) + public CommonResult getAreaByIp(@RequestParam("ip") String ip) { + // 获得城市 + Area area = IPUtils.getArea(ip); + if (area == null) { + return success("未知"); + } + // 格式化返回 + return success(AreaUtils.format(area.getId())); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java new file mode 100644 index 000000000..a2416832d --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.system.controller.admin.ip.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("管理后台 - 地区节点 Response VO") +@Data +public class AreaNodeRespVO { + + @ApiModelProperty(value = "编号", required = true, example = "110000") + private Integer id; + + @ApiModelProperty(value = "名字", required = true, example = "北京") + private String name; + + /** + * 子节点 + */ + private List children; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java index ed32e00cf..8a0767652 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java @@ -1,17 +1,14 @@ package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.hutool.core.util.URLUtil; import cn.hutool.extra.servlet.ServletUtil; -import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @@ -28,17 +25,6 @@ public class SmsCallbackController { @Resource private SmsSendService smsSendService; - @PostMapping("/yunpian") - @PermitAll - @ApiOperation(value = "云片短信的回调", notes = "参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档") - @ApiImplicitParam(name = "sms_status", value = "发送状态", required = true, example = "[{具体内容}]", dataTypeClass = String.class) - @OperateLog(enable = false) - public String receiveYunpianSmsStatus(@RequestParam("sms_status") String smsStatus) throws Throwable { - String text = URLUtil.decode(smsStatus); // decode 解码参数,因为它被 encode - smsSendService.receiveSmsStatus(SmsChannelEnum.YUN_PIAN.getCode(), text); - return "SUCCESS"; // 约定返回 SUCCESS 为成功 - } - @PostMapping("/aliyun") @PermitAll @ApiOperation(value = "阿里云短信的回调", notes = "参见 https://help.aliyun.com/document_detail/120998.html 文档") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java new file mode 100644 index 000000000..0cedf8785 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.system.convert.ip; + +import cn.iocoder.yudao.framework.ip.core.Area; +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface AreaConvert { + + AreaConvert INSTANCE = Mappers.getMapper(AreaConvert.class); + + List convertList(List list); + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java index 1c9979e7c..bff0a63a7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dict/DictTypeDO.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import java.time.LocalDateTime; + /** * 字典类型表 * @@ -47,4 +49,9 @@ public class DictTypeDO extends BaseDO { */ private String remark; + /** + * 删除时间 + */ + private LocalDateTime deletedTime; + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java index 234c4acca..951ef87af 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java @@ -38,14 +38,15 @@ public interface DictDataMapper extends BaseMapperX { default PageResult selectPage(DictDataPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(DictDataDO::getLabel, reqVO.getLabel()) - .likeIfPresent(DictDataDO::getDictType, reqVO.getDictType()) + .eqIfPresent(DictDataDO::getDictType, reqVO.getDictType()) .eqIfPresent(DictDataDO::getStatus, reqVO.getStatus()) .orderByDesc(Arrays.asList(DictDataDO::getDictType, DictDataDO::getSort))); } default List selectList(DictDataExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX().likeIfPresent(DictDataDO::getLabel, reqVO.getLabel()) - .likeIfPresent(DictDataDO::getDictType, reqVO.getDictType()) + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(DictDataDO::getLabel, reqVO.getLabel()) + .eqIfPresent(DictDataDO::getDictType, reqVO.getDictType()) .eqIfPresent(DictDataDO::getStatus, reqVO.getStatus())); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java index 83cb9a503..261f18cc4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java @@ -5,10 +5,12 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; +import java.time.LocalDateTime; import java.util.List; @Mapper @@ -39,4 +41,8 @@ public interface DictTypeMapper extends BaseMapperX { return selectOne(DictTypeDO::getName, name); } + int deleteById(@Param("id") Long id, @Param("deletedTime") LocalDateTime deletedTime); + + @Update("UPDATE system_dict_type SET deleted = 1, deleted_time = #{deletedTime} WHERE id = #{id}") + void updateToDelete(@Param("id") Long id, @Param("deletedTime") LocalDateTime deletedTime); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/DemoJob.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/DemoJob.java new file mode 100644 index 000000000..fc205b53b --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/DemoJob.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.system.job; + +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +@Component +@TenantJob // 标记多租户 +public class DemoJob implements JobHandler { + + @Resource + private AdminUserMapper adminUserMapper; + + @Override + public String execute(String param) throws Exception { + System.out.println("当前租户:" + TenantContextHolder.getTenantId()); + List users = adminUserMapper.selectList(); + return "用户数量:" + users.size(); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java index cc5d83d1e..585eb57d7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/sms/SmsChannelRefreshConsumer.java @@ -23,7 +23,7 @@ public class SmsChannelRefreshConsumer extends AbstractChannelMessageListener deptList = loadDeptIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(deptList)) { - return; - } - - // 构建缓存 - ImmutableMap.Builder builder = ImmutableMap.builder(); - ImmutableMultimap.Builder parentBuilder = ImmutableMultimap.builder(); - deptList.forEach(sysRoleDO -> { - builder.put(sysRoleDO.getId(), sysRoleDO); - parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO); - }); - // 设置缓存 - deptCache = builder.build(); - parentDeptCache = parentBuilder.build(); - maxUpdateTime = CollectionUtils.getMaxValue(deptList, DeptDO::getUpdateTime); - log.info("[initLocalCache][初始化 Dept 数量为 {}]", deptList.size()); + initLocalCacheIfUpdate(null); } @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) public void schedulePeriodicRefresh() { - self.initLocalCache(); + initLocalCacheIfUpdate(this.maxUpdateTime); } /** - * 如果部门发生变化,从数据库中获取最新的全量部门。 - * 如果未发生变化,则返回空 + * 刷新本地缓存 * - * @param maxUpdateTime 当前部门的最大更新时间 - * @return 部门列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - protected List loadDeptIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadMenuIfUpdate][首次加载全量部门]"); - } else { // 判断数据库中是否有更新的部门 - if (deptMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 注意:忽略自动多租户,因为要全局初始化缓存 + TenantUtils.executeIgnore(() -> { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && deptMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - log.info("[loadMenuIfUpdate][增量加载全量部门]"); - } - // 第二步,如果有更新,则从数据库加载所有部门 - return deptMapper.selectList(); + List depts = deptMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存部门,数量为:{}]", depts.size()); + + // 第二步:构建缓存。创建或更新支付 Client + // 构建缓存 + ImmutableMap.Builder builder = ImmutableMap.builder(); + ImmutableMultimap.Builder parentBuilder = ImmutableMultimap.builder(); + depts.forEach(sysRoleDO -> { + builder.put(sysRoleDO.getId(), sysRoleDO); + parentBuilder.put(sysRoleDO.getParentId(), sysRoleDO); + }); + // 设置缓存 + deptCache = builder.build(); + parentDeptCache = parentBuilder.build(); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(depts, DeptDO::getUpdateTime); + }); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java index 8d1d8aef8..07fcf40f3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.dict; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; @@ -13,6 +14,7 @@ import com.google.common.annotations.VisibleForTesting; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -57,7 +59,8 @@ public class DictTypeServiceImpl implements DictTypeService { // 校验正确性 checkCreateOrUpdate(null, reqVO.getName(), reqVO.getType()); // 插入字典类型 - DictTypeDO dictType = DictTypeConvert.INSTANCE.convert(reqVO); + DictTypeDO dictType = DictTypeConvert.INSTANCE.convert(reqVO) + .setDeletedTime(LocalDateTimeUtils.EMPTY); // 唯一索引,避免 null 值 dictTypeMapper.insert(dictType); return dictType.getId(); } @@ -80,7 +83,7 @@ public class DictTypeServiceImpl implements DictTypeService { throw exception(DICT_TYPE_HAS_CHILDREN); } // 删除字典类型 - dictTypeMapper.deleteById(id); + dictTypeMapper.updateToDelete(id, LocalDateTime.now()); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java index f49683f3f..d9cadd1aa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java @@ -24,7 +24,9 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; @@ -74,42 +76,37 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { @Override @PostConstruct public void initLocalCache() { - // 获取客户端列表,如果有更新 - List tenantList = loadOAuth2ClientIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(tenantList)) { - return; - } - - // 写入缓存 - clientCache = convertMap(tenantList, OAuth2ClientDO::getClientId); - maxUpdateTime = getMaxValue(tenantList, OAuth2ClientDO::getUpdateTime); - log.info("[initLocalCache][初始化 OAuth2Client 数量为 {}]", tenantList.size()); + initLocalCacheIfUpdate(null); } @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) public void schedulePeriodicRefresh() { - initLocalCache(); + initLocalCacheIfUpdate(this.maxUpdateTime); } /** - * 如果客户端发生变化,从数据库中获取最新的全量客户端。 - * 如果未发生变化,则返回空 + * 刷新本地缓存 * - * @param maxUpdateTime 当前客户端的最大更新时间 - * @return 客户端列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - private List loadOAuth2ClientIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadOAuth2ClientIfUpdate][首次加载全量客户端]"); - } else { // 判断数据库中是否有更新的客户端 - if (oauth2ClientMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; - } - log.info("[loadOAuth2ClientIfUpdate][增量加载全量客户端]"); + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && oauth2ClientMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - // 第二步,如果有更新,则从数据库加载所有客户端 - return oauth2ClientMapper.selectList(); + List clients = oauth2ClientMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存 OAuth2 客户端,数量为:{}]", clients.size()); + + // 第二步:构建缓存。 + clientCache = convertMap(clients, OAuth2ClientDO::getClientId); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = getMaxValue(clients, OAuth2ClientDO::getUpdateTime); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java index 3d135177c..1f9fee802 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java @@ -86,13 +86,33 @@ public class MenuServiceImpl implements MenuService { @Override @PostConstruct public synchronized void initLocalCache() { - // 获取菜单列表,如果有更新 - List menuList = this.loadMenuIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(menuList)) { + initLocalCacheIfUpdate(null); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initLocalCacheIfUpdate(this.maxUpdateTime); + } + + /** + * 刷新本地缓存 + * + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 + */ + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && menuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); return; } + List menuList = menuMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存菜单,数量为:{}]", menuList.size()); - // 构建缓存 + // 第二步:构建缓存。 ImmutableMap.Builder menuCacheBuilder = ImmutableMap.builder(); ImmutableMultimap.Builder permMenuCacheBuilder = ImmutableMultimap.builder(); menuList.forEach(menuDO -> { @@ -103,34 +123,9 @@ public class MenuServiceImpl implements MenuService { }); menuCache = menuCacheBuilder.build(); permissionMenuCache = permMenuCacheBuilder.build(); - maxUpdateTime = CollectionUtils.getMaxValue(menuList, MenuDO::getUpdateTime); - log.info("[initLocalCache][缓存菜单,数量为:{}]", menuList.size()); - } - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - initLocalCache(); - } - - /** - * 如果菜单发生变化,从数据库中获取最新的全量菜单。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前菜单的最大更新时间 - * @return 菜单列表 - */ - private List loadMenuIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadMenuIfUpdate][首次加载全量菜单]"); - } else { // 判断数据库中是否有更新的菜单 - if (menuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; - } - log.info("[loadMenuIfUpdate][增量加载全量菜单]"); - } - // 第二步,如果有更新,则从数据库加载所有菜单 - return menuMapper.selectList(); + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(menuList, MenuDO::getUpdateTime); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java index 0270187fc..bc4d51b8e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; @@ -31,7 +32,6 @@ import com.google.common.collect.Sets; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -126,106 +126,84 @@ public class PermissionServiceImpl implements PermissionService { @Resource private PermissionProducer permissionProducer; - @Resource - @Lazy // 注入自己,所以延迟加载 - private PermissionService self; - @Override @PostConstruct - @TenantIgnore // 初始化缓存,无需租户过滤 public void initLocalCache() { - initUserRoleLocalCache(); - initRoleMenuLocalCache(); - } - - /** - * 初始化 {@link #roleMenuCache} 和 {@link #menuRoleCache} 缓存 - */ - @VisibleForTesting - void initRoleMenuLocalCache() { - // 获取角色与菜单的关联列表,如果有更新 - List roleMenuList = loadRoleMenuIfUpdate(roleMenuMaxUpdateTime); - if (CollUtil.isEmpty(roleMenuList)) { - return; - } - - // 初始化 roleMenuCache 和 menuRoleCache 缓存 - ImmutableMultimap.Builder roleMenuCacheBuilder = ImmutableMultimap.builder(); - ImmutableMultimap.Builder menuRoleCacheBuilder = ImmutableMultimap.builder(); - roleMenuList.forEach(roleMenuDO -> { - roleMenuCacheBuilder.put(roleMenuDO.getRoleId(), roleMenuDO.getMenuId()); - menuRoleCacheBuilder.put(roleMenuDO.getMenuId(), roleMenuDO.getRoleId()); - }); - roleMenuCache = roleMenuCacheBuilder.build(); - menuRoleCache = menuRoleCacheBuilder.build(); - roleMenuMaxUpdateTime = getMaxValue(roleMenuList, RoleMenuDO::getUpdateTime); - log.info("[initRoleMenuLocalCache][初始化角色与菜单的关联数量为 {}]", roleMenuList.size()); - } - - /** - * 初始化 {@link #userRoleCache} 缓存 - */ - @VisibleForTesting - void initUserRoleLocalCache() { - // 获取用户与角色的关联列表,如果有更新 - List userRoleList = loadUserRoleIfUpdate(userRoleMaxUpdateTime); - if (CollUtil.isEmpty(userRoleList)) { - return; - } - - // 初始化 userRoleCache 缓存 - ImmutableMultimap.Builder userRoleCacheBuilder = ImmutableMultimap.builder(); - userRoleList.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId())); - userRoleCache = CollectionUtils.convertMultiMap2(userRoleList, UserRoleDO::getUserId, UserRoleDO::getRoleId); - userRoleMaxUpdateTime = getMaxValue(userRoleList, UserRoleDO::getUpdateTime); - log.info("[initUserRoleLocalCache][初始化用户与角色的关联数量为 {}]", userRoleList.size()); + initLocalCacheIfUpdateForRoleMenu(null); + initLocalCacheIfUpdateForUserRole(null); } @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) public void schedulePeriodicRefresh() { - self.initLocalCache(); + initLocalCacheIfUpdateForRoleMenu(this.roleMenuMaxUpdateTime); + initLocalCacheIfUpdateForUserRole(this.userRoleMaxUpdateTime); } /** - * 如果角色与菜单的关联发生变化,从数据库中获取最新的全量角色与菜单的关联。 - * 如果未发生变化,则返回空 + * 刷新 RoleMenu 本地缓存 * - * @param maxUpdateTime 当前角色与菜单的关联的最大更新时间 - * @return 角色与菜单的关联列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - protected List loadRoleMenuIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadRoleMenuIfUpdate][首次加载全量角色与菜单的关联]"); - } else { // 判断数据库中是否有更新的角色与菜单的关联 - if (roleMenuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; + @VisibleForTesting + void initLocalCacheIfUpdateForRoleMenu(LocalDateTime maxUpdateTime) { + // 注意:忽略自动多租户,因为要全局初始化缓存 + TenantUtils.executeIgnore(() -> { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && roleMenuMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdateForRoleMenu][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - log.info("[loadRoleMenuIfUpdate][增量加载全量角色与菜单的关联]"); - } - // 第二步,如果有更新,则从数据库加载所有角色与菜单的关联 - return roleMenuMapper.selectList(); + List roleMenus = roleMenuMapper.selectList(); + log.info("[initLocalCacheIfUpdateForRoleMenu][缓存角色与菜单,数量为:{}]", roleMenus.size()); + + // 第二步:构建缓存。 + ImmutableMultimap.Builder roleMenuCacheBuilder = ImmutableMultimap.builder(); + ImmutableMultimap.Builder menuRoleCacheBuilder = ImmutableMultimap.builder(); + roleMenus.forEach(roleMenuDO -> { + roleMenuCacheBuilder.put(roleMenuDO.getRoleId(), roleMenuDO.getMenuId()); + menuRoleCacheBuilder.put(roleMenuDO.getMenuId(), roleMenuDO.getRoleId()); + }); + roleMenuCache = roleMenuCacheBuilder.build(); + menuRoleCache = menuRoleCacheBuilder.build(); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.roleMenuMaxUpdateTime = getMaxValue(roleMenus, RoleMenuDO::getUpdateTime); + }); } /** - * 如果用户与角色的关联发生变化,从数据库中获取最新的全量用户与角色的关联。 - * 如果未发生变化,则返回空 + * 刷新 UserRole 本地缓存 * - * @param maxUpdateTime 当前角色与菜单的关联的最大更新时间 - * @return 角色与菜单的关联列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - protected List loadUserRoleIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadUserRoleIfUpdate][首次加载全量用户与角色的关联]"); - } else { // 判断数据库中是否有更新的用户与角色的关联 - if (userRoleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; + @VisibleForTesting + void initLocalCacheIfUpdateForUserRole(LocalDateTime maxUpdateTime) { + // 注意:忽略自动多租户,因为要全局初始化缓存 + TenantUtils.executeIgnore(() -> { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && userRoleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdateForUserRole][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - log.info("[loadUserRoleIfUpdate][增量加载全量用户与角色的关联]"); - } - // 第二步,如果有更新,则从数据库加载所有用户与角色的关联 - return userRoleMapper.selectList(); + List userRoles = userRoleMapper.selectList(); + log.info("[initLocalCacheIfUpdateForUserRole][缓存用户与角色,数量为:{}]", userRoles.size()); + + // 第二步:构建缓存。 + ImmutableMultimap.Builder userRoleCacheBuilder = ImmutableMultimap.builder(); + userRoles.forEach(userRoleDO -> userRoleCacheBuilder.put(userRoleDO.getUserId(), userRoleDO.getRoleId())); + userRoleCache = CollectionUtils.convertMultiMap2(userRoles, UserRoleDO::getUserId, UserRoleDO::getRoleId); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.userRoleMaxUpdateTime = getMaxValue(userRoles, UserRoleDO::getUpdateTime); + }); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java index 1045fe0b5..f5569f855 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java @@ -6,8 +6,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; -import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; @@ -15,13 +14,13 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUp import cn.iocoder.yudao.module.system.convert.permission.RoleConvert; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; +import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; import cn.iocoder.yudao.module.system.mq.producer.permission.RoleProducer; import com.google.common.annotations.VisibleForTesting; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; import org.springframework.lang.Nullable; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -77,53 +76,46 @@ public class RoleServiceImpl implements RoleService { @Resource private RoleProducer roleProducer; - @Resource - @Lazy // 注入自己,所以延迟加载 - private RoleService self; - /** * 初始化 {@link #roleCache} 缓存 */ @Override @PostConstruct - @TenantIgnore // 忽略自动多租户,全局初始化缓存 public void initLocalCache() { - // 获取角色列表,如果有更新 - List roleList = loadRoleIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(roleList)) { - return; - } - - // 写入缓存 - roleCache = CollectionUtils.convertMap(roleList, RoleDO::getId); - maxUpdateTime = CollectionUtils.getMaxValue(roleList, RoleDO::getUpdateTime); - log.info("[initLocalCache][初始化 Role 数量为 {}]", roleList.size()); + initLocalCacheIfUpdate(null); } @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) public void schedulePeriodicRefresh() { - self.initLocalCache(); + initLocalCacheIfUpdate(this.maxUpdateTime); } /** - * 如果角色发生变化,从数据库中获取最新的全量角色。 - * 如果未发生变化,则返回空 + * 刷新本地缓存 * - * @param maxUpdateTime 当前角色的最大更新时间 - * @return 角色列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - private List loadRoleIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadRoleIfUpdate][首次加载全量角色]"); - } else { // 判断数据库中是否有更新的角色 - if (roleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 注意:忽略自动多租户,因为要全局初始化缓存 + TenantUtils.executeIgnore(() -> { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && roleMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - log.info("[loadRoleIfUpdate][增量加载全量角色]"); - } - // 第二步,如果有更新,则从数据库加载所有角色 - return roleMapper.selectList(); + List roleList = roleMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存角色,数量为:{}]", roleList.size()); + + // 第二步:构建缓存。 + roleCache = CollectionUtils.convertMap(roleList, RoleDO::getId); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(roleList, RoleDO::getUpdateTime); + }); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java index 3ec581a67..cc7975bfa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java @@ -84,21 +84,42 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { @Override @PostConstruct public void initLocalCache() { - // 获取敏感词列表,如果有更新 - List sensitiveWordList = loadSensitiveWordIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(sensitiveWordList)) { + initLocalCacheIfUpdate(null); + } + + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) + public void schedulePeriodicRefresh() { + initLocalCacheIfUpdate(this.maxUpdateTime); + } + + /** + * 刷新本地缓存 + * + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 + */ + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && sensitiveWordMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); return; } + List sensitiveWords = sensitiveWordMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存敏感词,数量为:{}]", sensitiveWords.size()); + // 第二步:构建缓存。 // 写入 sensitiveWordTagsCache 缓存 Set tags = new HashSet<>(); - sensitiveWordList.forEach(word -> tags.addAll(word.getTags())); + sensitiveWords.forEach(word -> tags.addAll(word.getTags())); sensitiveWordTagsCache = tags; // 写入 defaultSensitiveWordTrie、tagSensitiveWordTries 缓存 - initSensitiveWordTrie(sensitiveWordList); - // 写入 maxUpdateTime 最大更新时间 - maxUpdateTime = CollectionUtils.getMaxValue(sensitiveWordList, SensitiveWordDO::getUpdateTime); - log.info("[initLocalCache][初始化 敏感词 数量为 {}]", sensitiveWordList.size()); + initSensitiveWordTrie(sensitiveWords); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = CollectionUtils.getMaxValue(sensitiveWords, SensitiveWordDO::getUpdateTime); } private void initSensitiveWordTrie(List wordDOs) { @@ -122,33 +143,6 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { this.tagSensitiveWordTries = tagSensitiveWordTries; } - @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) - public void schedulePeriodicRefresh() { - initLocalCache(); - } - - /** - * 如果敏感词发生变化,从数据库中获取最新的全量敏感词。 - * 如果未发生变化,则返回空 - * - * @param maxUpdateTime 当前敏感词的最大更新时间 - * @return 敏感词列表 - */ - private List loadSensitiveWordIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - // 如果更新时间为空,说明 DB 一定有新数据 - if (maxUpdateTime == null) { - log.info("[loadSensitiveWordIfUpdate][首次加载全量敏感词]"); - } else { // 判断数据库中是否有更新的敏感词 - if (sensitiveWordMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; - } - log.info("[loadSensitiveWordIfUpdate][增量加载全量敏感词]"); - } - // 第二步,如果有更新,则从数据库加载所有敏感词 - return sensitiveWordMapper.selectList(); - } - @Override public Long createSensitiveWord(SensitiveWordCreateReqVO createReqVO) { // 校验唯一性 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java index 50e13a602..fb0b707d7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java @@ -21,7 +21,7 @@ public interface SmsChannelService { /** * 初始化短信客户端 */ - void initSmsClients(); + void initLocalCache(); /** * 创建短信渠道 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java index ed1a73122..50eeb4910 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java @@ -1,8 +1,6 @@ package cn.iocoder.yudao.module.system.service.sms; -import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; @@ -23,14 +21,14 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; /** - * 短信渠道Service实现类 + * 短信渠道 Service 实现类 * * @author zzf - * @date 2021/1/25 9:25 */ @Service @Slf4j @@ -61,46 +59,39 @@ public class SmsChannelServiceImpl implements SmsChannelService { @Override @PostConstruct - public void initSmsClients() { - // 获取短信渠道,如果有更新 - List smsChannels = this.loadSmsChannelIfUpdate(maxUpdateTime); - if (CollUtil.isEmpty(smsChannels)) { - return; - } - - // 创建或更新短信 Client - List propertiesList = SmsChannelConvert.INSTANCE.convertList02(smsChannels); - propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties)); - - // 写入缓存 - maxUpdateTime = CollectionUtils.getMaxValue(smsChannels, SmsChannelDO::getUpdateTime); - log.info("[initSmsClients][初始化 SmsChannel 数量为 {}]", smsChannels.size()); + public void initLocalCache() { + initLocalCacheIfUpdate(null); } @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) public void schedulePeriodicRefresh() { - initSmsClients(); + initLocalCacheIfUpdate(this.maxUpdateTime); } /** - * 如果短信渠道发生变化,从数据库中获取最新的全量短信渠道。 - * 如果未发生变化,则返回空 + * 刷新本地缓存 * - * @param maxUpdateTime 当前短信渠道的最大更新时间 - * @return 短信渠道列表 + * @param maxUpdateTime 最大更新时间 + * 1. 如果 maxUpdateTime 为 null,则“强制”刷新缓存 + * 2. 如果 maxUpdateTime 不为 null,判断自 maxUpdateTime 是否有数据发生变化,有的情况下才刷新缓存 */ - private List loadSmsChannelIfUpdate(LocalDateTime maxUpdateTime) { - // 第一步,判断是否要更新。 - if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据 - log.info("[loadSmsChannelIfUpdate][首次加载全量短信渠道]"); - } else { // 判断数据库中是否有更新的短信渠道 - if (smsChannelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { - return null; - } - log.info("[loadSmsChannelIfUpdate][增量加载全量短信渠道]"); + private void initLocalCacheIfUpdate(LocalDateTime maxUpdateTime) { + // 第一步:基于 maxUpdateTime 判断缓存是否刷新。 + // 如果没有增量的数据变化,则不进行本地缓存的刷新 + if (maxUpdateTime != null + && smsChannelMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) { + log.info("[initLocalCacheIfUpdate][数据未发生变化({}),本地缓存不刷新]", maxUpdateTime); + return; } - // 第二步,如果有更新,则从数据库加载所有短信渠道 - return smsChannelMapper.selectList(); + List channels = smsChannelMapper.selectList(); + log.info("[initLocalCacheIfUpdate][缓存短信渠道,数量为:{}]", channels.size()); + + // 第二步:构建缓存。创建或更新短信 Client + List propertiesList = SmsChannelConvert.INSTANCE.convertList02(channels); + propertiesList.forEach(properties -> smsClientFactory.createOrUpdateSmsClient(properties)); + + // 第三步:设置最新的 maxUpdateTime,用于下次的增量判断。 + this.maxUpdateTime = getMaxValue(channels, SmsChannelDO::getUpdateTime); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java index 6e425b919..85fee7ff4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java @@ -113,7 +113,7 @@ public class SmsSendServiceImpl implements SmsSendService { SmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId); // 短信模板不存在 if (channelDO == null) { - throw exception(SMS_SEND_TEMPLATE_NOT_EXISTS); + throw exception(SMS_CHANNEL_NOT_EXISTS); } return channelDO; } diff --git a/yudao-module-system/yudao-module-system-biz/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java b/yudao-module-system/yudao-module-system-biz/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java index b3ae5cde4..a8e57ccb5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test-integration/java/cn/iocoder/yudao/module/system/service/sms/SmsServiceIntegrationTest.java @@ -30,22 +30,6 @@ public class SmsServiceIntegrationTest extends BaseDbAndRedisIntegrationTest { @MockBean private AdminUserService userService; - @Test - public void testSendSingleSms_yunpianSuccess() { - // 参数准备 - String mobile = "15601691399"; - Long userId = 1L; - Integer userType = UserTypeEnum.ADMIN.getValue(); - String templateCode = "test_01"; - Map templateParams = MapUtil.builder() - .put("operation", "登录").put("code", "1234").build(); - // 调用 - smsService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); - - // 等待 MQ 消费 - ThreadUtil.sleep(1, TimeUnit.HOURS); - } - @Test public void testSendSingleSms_aliyunSuccess() { // 参数准备 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java index 307c6dca6..5c39b32e6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceTest.java @@ -24,7 +24,7 @@ import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; @@ -48,7 +48,7 @@ public class DictTypeServiceTest extends BaseDbUnitTest { o.setName("yunai"); o.setType("芋艿"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2021, 1, 15)); + o.setCreateTime(buildTime(2021, 1, 15)); }); dictTypeMapper.insert(dbDictType); // 测试 name 不匹配 @@ -58,13 +58,13 @@ public class DictTypeServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildLocalDateTime(2021, 1, 1)))); + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 DictTypePageReqVO reqVO = new DictTypePageReqVO(); reqVO.setName("nai"); reqVO.setType("艿"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 10),buildLocalDateTime(2021, 1, 20)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 10),buildTime(2021, 1, 20)})); // 调用 PageResult pageResult = dictTypeService.getDictTypePage(reqVO); @@ -81,7 +81,7 @@ public class DictTypeServiceTest extends BaseDbUnitTest { o.setName("yunai"); o.setType("芋艿"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2021, 1, 15)); + o.setCreateTime(buildTime(2021, 1, 15)); }); dictTypeMapper.insert(dbDictType); // 测试 name 不匹配 @@ -91,13 +91,13 @@ public class DictTypeServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildLocalDateTime(2021, 1, 1)))); + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1)))); // 准备参数 DictTypeExportReqVO reqVO = new DictTypeExportReqVO(); reqVO.setName("nai"); reqVO.setType("艿"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 1, 10),buildLocalDateTime(2021, 1, 20)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 1, 10),buildTime(2021, 1, 20)})); // 调用 List list = dictTypeService.getDictTypeList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java index ff46ad34a..163a2cda3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -96,7 +96,7 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { reqVO.setApplicationName("tu"); reqVO.setCode(1); reqVO.setMessage("ma"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 11, 1),buildLocalDateTime(2020, 11, 30)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 11, 1),buildTime(2020, 11, 30)})); // 调用 PageResult pageResult = errorCodeService.getErrorCodePage(reqVO); @@ -115,7 +115,7 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { o.setApplicationName("tudou"); o.setCode(1); o.setMessage("yuanma"); - o.setCreateTime(buildLocalDateTime(2020, 11, 11)); + o.setCreateTime(buildTime(2020, 11, 11)); }); errorCodeMapper.insert(dbErrorCode); // 测试 type 不匹配 @@ -127,7 +127,7 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { // 测试 message 不匹配 errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setMessage("nai"))); // 测试 createTime 不匹配 - errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setCreateTime(buildLocalDateTime(2020, 12, 12)))); + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setCreateTime(buildTime(2020, 12, 12)))); return dbErrorCode; } @@ -141,7 +141,7 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { reqVO.setApplicationName("tu"); reqVO.setCode(1); reqVO.setMessage("ma"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 11, 1),buildLocalDateTime(2020, 11, 30)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 11, 1),buildTime(2020, 11, 30)})); // 调用 List list = errorCodeService.getErrorCodeList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java index d867d4c12..101abe7d3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java @@ -21,7 +21,7 @@ import java.time.LocalDateTime; import java.util.List; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum.*; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -46,7 +46,7 @@ public class LoginLogServiceImplTest extends BaseDbUnitTest { logDO.setUserIp("192.168.199.16"); logDO.setUsername("wangkai"); - logDO.setCreateTime(buildLocalDateTime(2021, 3, 6)); + logDO.setCreateTime(buildTime(2021, 3, 6)); logDO.setResult(SUCCESS.getResult()); }); loginLogMapper.insert(loginLogDO); @@ -59,7 +59,7 @@ public class LoginLogServiceImplTest extends BaseDbUnitTest { // 不同username loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUsername("yunai"))); // 构造一个早期时间 2021-02-06 00:00:00 - loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildLocalDateTime(2021, 2, 6)))); + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6)))); // 构造调用参数 @@ -67,8 +67,8 @@ public class LoginLogServiceImplTest extends BaseDbUnitTest { reqVO.setUsername("wangkai"); reqVO.setUserIp("192.168.199"); reqVO.setStatus(true); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 5), - buildLocalDateTime(2021, 3, 7)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 3, 5), + buildTime(2021, 3, 7)})); // 调用service方法 PageResult pageResult = loginLogService.getLoginLogPage(reqVO); @@ -91,7 +91,7 @@ public class LoginLogServiceImplTest extends BaseDbUnitTest { logDO.setUserIp("192.168.111.16"); logDO.setUsername("wangxiaokai"); - logDO.setCreateTime(buildLocalDateTime(2021, 3, 6)); + logDO.setCreateTime(buildTime(2021, 3, 6)); logDO.setResult(SUCCESS.getResult()); }); loginLogMapper.insert(loginLogDO); @@ -104,15 +104,15 @@ public class LoginLogServiceImplTest extends BaseDbUnitTest { // 不同username loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUsername("yunai"))); // 构造一个早期时间 2021-02-06 00:00:00 - loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildLocalDateTime(2021, 2, 6)))); + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6)))); // 构造调用参数 LoginLogExportReqVO reqVO = new LoginLogExportReqVO(); reqVO.setUsername("wangxiaokai"); reqVO.setUserIp("192.168.111"); reqVO.setStatus(true); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 5), - buildLocalDateTime(2021, 3, 7)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 3, 5), + buildTime(2021, 3, 7)})); // 调用service方法 List loginLogList = loginLogService.getLoginLogList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java index 5dfa31d36..86be2a8bd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java @@ -29,7 +29,7 @@ import java.util.List; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -81,7 +81,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { o.setUserType(randomEle(UserTypeEnum.values()).getValue()); o.setModule("order"); o.setType(OperateTypeEnum.CREATE.getType()); - o.setStartTime(buildLocalDateTime(2021, 3, 6)); + o.setStartTime(buildTime(2021, 3, 6)); o.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()); o.setExts(MapUtil.builder("orderId", randomLongId()).build()); }); @@ -95,7 +95,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { // type 不同 operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType()))); // createTime 不同 - operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildLocalDateTime(2021, 2, 6)))); + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6)))); // resultCode 不同 operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(BAD_REQUEST.getCode()))); @@ -104,8 +104,8 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { reqVO.setUserNickname("wangkai"); reqVO.setModule("order"); reqVO.setType(OperateTypeEnum.CREATE.getType()); - reqVO.setStartTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 5), - buildLocalDateTime(2021, 3, 7)})); + reqVO.setStartTime((new LocalDateTime[]{buildTime(2021, 3, 5), + buildTime(2021, 3, 7)})); reqVO.setSuccess(true); // 调用service方法 @@ -133,7 +133,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { o.setUserType(randomEle(UserTypeEnum.values()).getValue()); o.setModule("order"); o.setType(OperateTypeEnum.CREATE.getType()); - o.setStartTime(buildLocalDateTime(2021, 3, 6)); + o.setStartTime(buildTime(2021, 3, 6)); o.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()); o.setExts(MapUtil.builder("orderId", randomLongId()).build()); }); @@ -147,7 +147,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { // type 不同 operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType()))); // createTime 不同 - operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildLocalDateTime(2021, 2, 6)))); + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6)))); // resultCode 不同 operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(BAD_REQUEST.getCode()))); @@ -156,7 +156,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { reqVO.setUserNickname("wangkai"); reqVO.setModule("order"); reqVO.setType(OperateTypeEnum.CREATE.getType()); - reqVO.setStartTime((new LocalDateTime[]{buildLocalDateTime(2021, 3, 5),buildLocalDateTime(2021, 3, 7)})); + reqVO.setStartTime((new LocalDateTime[]{buildTime(2021, 3, 5),buildTime(2021, 3, 7)})); reqVO.setSuccess(true); // 调用 service 方法 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java index 610828b6f..6352c4593 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceTest.java @@ -71,7 +71,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { private PermissionProducer permissionProducer; @Test - public void testInitRoleMenuLocalCache() { + public void testInitLocalCacheIfUpdateForRoleMenu() { // mock 数据 RoleMenuDO roleMenuDO01 = randomPojo(RoleMenuDO.class, o -> o.setRoleId(1L).setMenuId(10L)); roleMenuMapper.insert(roleMenuDO01); @@ -79,7 +79,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { roleMenuMapper.insert(roleMenuDO02); // 调用 - permissionService.initRoleMenuLocalCache(); + permissionService.initLocalCacheIfUpdateForRoleMenu(null); // 断言 roleMenuCache 缓存 assertEquals(1, permissionService.getRoleMenuCache().keySet().size()); assertEquals(asList(10L, 20L), permissionService.getRoleMenuCache().get(1L)); @@ -93,7 +93,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { } @Test - public void testInitUserRoleLocalCache() { + public void testInitLocalCacheIfUpdateForUserRole() { // mock 数据 UserRoleDO userRoleDO01 = randomPojo(UserRoleDO.class, o -> o.setUserId(1L).setRoleId(10L)); userRoleMapper.insert(userRoleDO01); @@ -101,7 +101,7 @@ public class PermissionServiceTest extends BaseDbUnitTest { userRoleMapper.insert(roleMenuDO02); // 调用 - permissionService.initUserRoleLocalCache(); + permissionService.initLocalCacheIfUpdateForUserRole(null); // 断言 roleMenuCache 缓存 assertEquals(1, permissionService.getUserRoleCache().size()); assertEquals(asSet(10L, 20L), permissionService.getUserRoleCache().get(1L)); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java index 7c19b2eb3..37d3ba44e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; @@ -21,9 +20,8 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.*; -import java.util.stream.Collectors; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -129,7 +127,7 @@ public class RoleServiceTest extends BaseDbUnitTest { Long roleId = roleDO.getId(); //调用 - Set deptIdSet = Arrays.asList(1L, 2L, 3L, 4L, 5L).stream().collect(Collectors.toSet()); + Set deptIdSet = new HashSet<>(Arrays.asList(1L, 2L, 3L, 4L, 5L)); roleService.updateRoleDataScope(roleId, DataScopeEnum.DEPT_CUSTOM.getScope(), deptIdSet); //断言 @@ -137,7 +135,7 @@ public class RoleServiceTest extends BaseDbUnitTest { assertEquals(DataScopeEnum.DEPT_CUSTOM.getScope(), newRoleDO.getDataScope()); Set newDeptIdSet = newRoleDO.getDataScopeDeptIds(); - assertTrue(deptIdSet.size() == newDeptIdSet.size()); + assertEquals(deptIdSet.size(), newDeptIdSet.size()); deptIdSet.stream().forEach(d -> assertTrue(newDeptIdSet.contains(d))); verify(roleProducer).sendRoleRefreshMessage(); @@ -166,7 +164,7 @@ public class RoleServiceTest extends BaseDbUnitTest { o.setName("土豆"); o.setCode("tudou"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 8)); + o.setCreateTime(buildTime(2022, 2, 8)); }); roleMapper.insert(dbRole); // 测试 name 不匹配 @@ -174,13 +172,13 @@ public class RoleServiceTest extends BaseDbUnitTest { // 测试 code 不匹配 roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCode("hong"))); // 测试 createTime 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 16)))); + roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCreateTime(buildTime(2022, 2, 16)))); // 准备参数 RoleExportReqVO reqVO = new RoleExportReqVO(); reqVO.setName("土豆"); reqVO.setCode("tu"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2022, 2, 1),buildLocalDateTime(2022, 2, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 2, 1),buildTime(2022, 2, 12)})); // 调用 List list = roleService.getRoleList(reqVO); @@ -196,7 +194,7 @@ public class RoleServiceTest extends BaseDbUnitTest { o.setName("土豆"); o.setCode("tudou"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 8)); + o.setCreateTime(buildTime(2022, 2, 8)); }); roleMapper.insert(dbRole); // 测试 name 不匹配 @@ -204,13 +202,13 @@ public class RoleServiceTest extends BaseDbUnitTest { // 测试 code 不匹配 roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCode("hong"))); // 测试 createTime 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 16)))); + roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCreateTime(buildTime(2022, 2, 16)))); // 准备参数 RolePageReqVO reqVO = new RolePageReqVO(); reqVO.setName("土豆"); reqVO.setCode("tu"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2022, 2, 1),buildLocalDateTime(2022, 2, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 2, 1),buildTime(2022, 2, 12)})); // 调用 PageResult pageResult = roleService.getRolePage(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java index f018975ba..447ea744c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.sensitiveword; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordExportReqVO; @@ -21,7 +20,7 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -145,7 +144,7 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { o.setName("笨蛋"); o.setTags(Arrays.asList("论坛", "蔬菜")); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 8)); + o.setCreateTime(buildTime(2022, 2, 8)); }); sensitiveWordMapper.insert(dbSensitiveWord); // 测试 name 不匹配 @@ -153,13 +152,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { // 测试 tags 不匹配 sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setTags(Arrays.asList("短信", "日用品")))); // 测试 createTime 不匹配 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 16)))); + sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setCreateTime(buildTime(2022, 2, 16)))); // 准备参数 SensitiveWordPageReqVO reqVO = new SensitiveWordPageReqVO(); reqVO.setName("笨"); reqVO.setTag("论坛"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2022, 2, 1),buildLocalDateTime(2022, 2, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 2, 1),buildTime(2022, 2, 12)})); // 调用 PageResult pageResult = sensitiveWordService.getSensitiveWordPage(reqVO); @@ -176,7 +175,7 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { o.setName("笨蛋"); o.setTags(Arrays.asList("论坛", "蔬菜")); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 8)); + o.setCreateTime(buildTime(2022, 2, 8)); }); sensitiveWordMapper.insert(dbSensitiveWord); // 测试 name 不匹配 @@ -184,13 +183,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { // 测试 tags 不匹配 sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setTags(Arrays.asList("短信", "日用品")))); // 测试 createTime 不匹配 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setCreateTime(DateUtils.buildLocalDateTime(2022, 2, 16)))); + sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setCreateTime(buildTime(2022, 2, 16)))); // 准备参数 SensitiveWordExportReqVO reqVO = new SensitiveWordExportReqVO(); reqVO.setName("笨"); reqVO.setTag("论坛"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2022, 2, 1),buildLocalDateTime(2022, 2, 12)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 2, 1),buildTime(2022, 2, 12)})); // 调用 List list = sensitiveWordService.getSensitiveWordList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java index 0feb7d592..5dea2808f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java @@ -24,7 +24,7 @@ import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_HAS_CHILDREN; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SMS_CHANNEL_NOT_EXISTS; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -57,7 +57,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { smsChannelMapper.insert(smsChannelDO02); // 调用 - smsChannelService.initSmsClients(); + smsChannelService.initLocalCache(); // 校验 maxUpdateTime 属性 LocalDateTime maxUpdateTime = (LocalDateTime) BeanUtil.getFieldValue(smsChannelService, "maxUpdateTime"); assertEquals(max(smsChannelDO01.getUpdateTime(), smsChannelDO02.getUpdateTime()), maxUpdateTime); @@ -159,7 +159,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到 o.setSignature("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2020, 12, 12)); + o.setCreateTime(buildTime(2020, 12, 12)); }); smsChannelMapper.insert(dbSmsChannel); // 测试 signature 不匹配 @@ -167,12 +167,12 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { // 测试 status 不匹配 smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildLocalDateTime(2020, 11, 11)))); + smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11)))); // 准备参数 SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO(); reqVO.setSignature("芋道"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 12, 1),buildLocalDateTime(2020, 12, 24)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 12, 1),buildTime(2020, 12, 24)})); // 调用 PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java index 8be82e9a8..3b314b791 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java @@ -26,7 +26,7 @@ import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomBoolean; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -49,9 +49,9 @@ public class SmsLogServiceTest extends BaseDbUnitTest { o.setTemplateId(10L); o.setMobile("15601691300"); o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - o.setSendTime(buildLocalDateTime(2020, 11, 11)); + o.setSendTime(buildTime(2020, 11, 11)); o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - o.setReceiveTime(buildLocalDateTime(2021, 11, 11)); + o.setReceiveTime(buildTime(2021, 11, 11)); }); smsLogMapper.insert(dbSmsLog); // 测试 channelId 不匹配 @@ -63,22 +63,22 @@ public class SmsLogServiceTest extends BaseDbUnitTest { // 测试 sendStatus 不匹配 smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); // 测试 sendTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildLocalDateTime(2020, 12, 12)))); + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); // 测试 receiveStatus 不匹配 smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); // 测试 receiveTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildLocalDateTime(2021, 12, 12)))); + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); // 准备参数 SmsLogPageReqVO reqVO = new SmsLogPageReqVO(); reqVO.setChannelId(1L); reqVO.setTemplateId(10L); reqVO.setMobile("156"); reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - reqVO.setSendTime((new LocalDateTime[]{buildLocalDateTime(2020, 11, 1), - buildLocalDateTime(2020, 11, 30)})); + reqVO.setSendTime((new LocalDateTime[]{buildTime(2020, 11, 1), + buildTime(2020, 11, 30)})); reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - reqVO.setReceiveTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 1), - buildLocalDateTime(2021, 11, 30)})); + reqVO.setReceiveTime((new LocalDateTime[]{buildTime(2021, 11, 1), + buildTime(2021, 11, 30)})); // 调用 PageResult pageResult = smsLogService.getSmsLogPage(reqVO); @@ -96,9 +96,9 @@ public class SmsLogServiceTest extends BaseDbUnitTest { o.setTemplateId(10L); o.setMobile("15601691300"); o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - o.setSendTime(buildLocalDateTime(2020, 11, 11)); + o.setSendTime(buildTime(2020, 11, 11)); o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - o.setReceiveTime(buildLocalDateTime(2021, 11, 11)); + o.setReceiveTime(buildTime(2021, 11, 11)); }); smsLogMapper.insert(dbSmsLog); // 测试 channelId 不匹配 @@ -110,22 +110,22 @@ public class SmsLogServiceTest extends BaseDbUnitTest { // 测试 sendStatus 不匹配 smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); // 测试 sendTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildLocalDateTime(2020, 12, 12)))); + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); // 测试 receiveStatus 不匹配 smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); // 测试 receiveTime 不匹配 - smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildLocalDateTime(2021, 12, 12)))); + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); // 准备参数 SmsLogExportReqVO reqVO = new SmsLogExportReqVO(); reqVO.setChannelId(1L); reqVO.setTemplateId(10L); reqVO.setMobile("156"); reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - reqVO.setSendTime((new LocalDateTime[]{buildLocalDateTime(2020, 11, 1), - buildLocalDateTime(2020, 11, 30)})); + reqVO.setSendTime((new LocalDateTime[]{buildTime(2020, 11, 1), + buildTime(2020, 11, 30)})); reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - reqVO.setReceiveTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 1), - buildLocalDateTime(2021, 11, 30)})); + reqVO.setReceiveTime((new LocalDateTime[]{buildTime(2021, 11, 1), + buildTime(2021, 11, 30)})); // 调用 List list = smsLogService.getSmsLogList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java index de0bf677c..81e03f29c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java @@ -34,7 +34,7 @@ import static cn.hutool.core.bean.BeanUtil.getFieldValue; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -205,7 +205,7 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { o.setContent("芋道源码"); o.setApiTemplateId("yunai"); o.setChannelId(1L); - o.setCreateTime(buildLocalDateTime(2021, 11, 11)); + o.setCreateTime(buildTime(2021, 11, 11)); }); smsTemplateMapper.insert(dbSmsTemplate); // 测试 type 不匹配 @@ -221,7 +221,7 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { // 测试 channelId 不匹配 smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L))); // 测试 createTime 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildLocalDateTime(2021, 12, 12)))); + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 SmsTemplatePageReqVO reqVO = new SmsTemplatePageReqVO(); reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); @@ -230,7 +230,7 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { reqVO.setContent("芋道"); reqVO.setApiTemplateId("yu"); reqVO.setChannelId(1L); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 1),buildLocalDateTime(2021, 12, 1)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 1),buildTime(2021, 12, 1)})); // 调用 PageResult pageResult = smsTemplateService.getSmsTemplatePage(reqVO); @@ -250,7 +250,7 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { o.setContent("芋道源码"); o.setApiTemplateId("yunai"); o.setChannelId(1L); - o.setCreateTime(buildLocalDateTime(2021, 11, 11)); + o.setCreateTime(buildTime(2021, 11, 11)); }); smsTemplateMapper.insert(dbSmsTemplate); // 测试 type 不匹配 @@ -266,7 +266,7 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { // 测试 channelId 不匹配 smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L))); // 测试 createTime 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildLocalDateTime(2021, 12, 12)))); + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 SmsTemplateExportReqVO reqVO = new SmsTemplateExportReqVO(); reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); @@ -275,7 +275,7 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { reqVO.setContent("芋道"); reqVO.setApiTemplateId("yu"); reqVO.setChannelId(1L); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2021, 11, 1),buildLocalDateTime(2021, 12, 1)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 1),buildTime(2021, 12, 1)})); // 调用 List list = smsTemplateService.getSmsTemplateList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java index 35a1bc6e6..8277cdea5 100755 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java @@ -17,7 +17,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -142,7 +142,7 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { o.setName("芋道源码"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setRemark("源码解析"); - o.setCreateTime(buildLocalDateTime(2022, 10, 10)); + o.setCreateTime(buildTime(2022, 10, 10)); }); tenantPackageMapper.insert(dbTenantPackage); // 测试 name 不匹配 @@ -152,13 +152,13 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { // 测试 remark 不匹配 tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setRemark("解析"))); // 测试 createTime 不匹配 - tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setCreateTime(buildLocalDateTime(2022, 11, 11)))); + tenantPackageMapper.insert(cloneIgnoreId(dbTenantPackage, o -> o.setCreateTime(buildTime(2022, 11, 11)))); // 准备参数 TenantPackagePageReqVO reqVO = new TenantPackagePageReqVO(); reqVO.setName("芋道"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); reqVO.setRemark("源码"); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2022, 10, 9),buildLocalDateTime(2022, 10, 11)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2022, 10, 9),buildTime(2022, 10, 11)})); // 调用 PageResult pageResult = tenantPackageService.getTenantPackagePage(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java index e63567ced..dfaebdbb7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java @@ -34,7 +34,7 @@ import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -110,7 +110,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { public void testValidTenant_expired() { // mock 数据 TenantDO tenant = randomPojo(TenantDO.class, o -> o.setId(1L).setStatus(CommonStatusEnum.ENABLE.getStatus()) - .setExpireTime(buildLocalDateTime(2020, 2, 2))); + .setExpireTime(buildTime(2020, 2, 2))); tenantMapper.insert(tenant); // 调用,并断言业务异常 @@ -291,7 +291,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { o.setContactName("芋艿"); o.setContactMobile("15601691300"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2020, 12, 12)); + o.setCreateTime(buildTime(2020, 12, 12)); }); tenantMapper.insert(dbTenant); // 测试 name 不匹配 @@ -303,14 +303,14 @@ public class TenantServiceImplTest extends BaseDbUnitTest { // 测试 status 不匹配 tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildLocalDateTime(2021, 12, 12)))); + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 TenantPageReqVO reqVO = new TenantPageReqVO(); reqVO.setName("芋道"); reqVO.setContactName("艿"); reqVO.setContactMobile("1560"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(new LocalDateTime[]{buildLocalDateTime(2020, 12, 1),buildLocalDateTime(2020, 12, 24)}); + reqVO.setCreateTime(new LocalDateTime[]{buildTime(2020, 12, 1),buildTime(2020, 12, 24)}); // 调用 PageResult pageResult = tenantService.getTenantPage(reqVO); @@ -328,7 +328,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { o.setContactName("芋艿"); o.setContactMobile("15601691300"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2020, 12, 12)); + o.setCreateTime(buildTime(2020, 12, 12)); }); tenantMapper.insert(dbTenant); // 测试 name 不匹配 @@ -340,14 +340,14 @@ public class TenantServiceImplTest extends BaseDbUnitTest { // 测试 status 不匹配 tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildLocalDateTime(2021, 12, 12)))); + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12)))); // 准备参数 TenantExportReqVO reqVO = new TenantExportReqVO(); reqVO.setName("芋道"); reqVO.setContactName("艿"); reqVO.setContactMobile("1560"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(new LocalDateTime[]{buildLocalDateTime(2020, 12, 1),buildLocalDateTime(2020, 12, 24)}); + reqVO.setCreateTime(new LocalDateTime[]{buildTime(2020, 12, 1),buildTime(2020, 12, 24)}); // 调用 List list = tenantService.getTenantList(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java index d44493139..2822789e3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java @@ -40,7 +40,7 @@ import java.util.function.Consumer; import static cn.hutool.core.util.RandomUtil.randomBytes; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildLocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; @@ -295,7 +295,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { reqVO.setUsername("tu"); reqVO.setMobile("1560"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 12, 1),buildLocalDateTime(2020, 12, 24)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 12, 1),buildTime(2020, 12, 24)})); reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 // mock 方法 List deptList = newArrayList(randomPojo(DeptDO.class, o -> o.setId(2L))); @@ -318,7 +318,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { reqVO.setUsername("tu"); reqVO.setMobile("1560"); reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime((new LocalDateTime[]{buildLocalDateTime(2020, 12, 1),buildLocalDateTime(2020, 12, 24)})); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2020, 12, 1),buildTime(2020, 12, 24)})); reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 // mock 方法 List deptList = newArrayList(randomPojo(DeptDO.class, o -> o.setId(2L))); @@ -340,7 +340,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { o.setUsername("tudou"); o.setMobile("15601691300"); o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildLocalDateTime(2020, 12, 12)); + o.setCreateTime(buildTime(2020, 12, 12)); o.setDeptId(2L); }); userMapper.insert(dbUser); @@ -351,7 +351,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { // 测试 status 不匹配 userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); // 测试 createTime 不匹配 - userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setCreateTime(buildLocalDateTime(2020, 11, 11)))); + userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11)))); // 测试 dept 不匹配 userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setDeptId(0L))); return dbUser; diff --git a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql index 56fc42704..7590e57a3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql @@ -111,6 +111,7 @@ CREATE TABLE IF NOT EXISTS "system_dict_type" ( "updater" varchar(64) DEFAULT '', "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, "deleted" bit NOT NULL DEFAULT FALSE, + "deleted_time" timestamp NOT NULL, PRIMARY KEY ("id") ) COMMENT '字典类型表'; diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 061e0d9bd..f2b1fdb74 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -38,24 +38,9 @@ cn.iocoder.boot - yudao-module-pay-biz - ${revision} - - - cn.iocoder.boot - yudao-module-promotion-biz - ${revision} - - - cn.iocoder.boot - yudao-module-product-biz - ${revision} - - - cn.iocoder.boot - yudao-module-trade-biz - ${revision} + yudao-spring-boot-starter-biz-error-code + @@ -68,11 +53,30 @@ + cn.iocoder.boot - yudao-spring-boot-starter-biz-error-code + yudao-module-pay-biz + ${revision} + + + + + + + + + + + + + + + + + org.springframework.boot @@ -100,7 +104,7 @@ org.springframework.boot spring-boot-maven-plugin - 2.6.7 + 2.7.6 true diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java index d744ec744..9e66b17a4 100644 --- a/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java @@ -1,11 +1,10 @@ package cn.iocoder.yudao.module.shop.controller.app; -import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.pay.service.notify.vo.PayNotifyOrderReqVO; -import cn.iocoder.yudao.module.pay.service.notify.vo.PayRefundOrderReqVO; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; +import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; -import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.util.PaySeqUtils; import cn.iocoder.yudao.module.shop.controller.app.vo.AppShopOrderCreateRespVO; import io.swagger.annotations.Api; @@ -20,7 +19,6 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.validation.Valid; import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; @@ -60,14 +58,14 @@ public class AppShopOrderController { @PostMapping("/pay-notify") @ApiOperation("支付回调") - public CommonResult payNotify(@RequestBody @Valid PayNotifyOrderReqVO reqVO) { + public CommonResult payNotify(@RequestBody @Valid PayOrderNotifyReqDTO reqVO) { log.info("[payNotify][回调成功]"); return success(true); } @PostMapping("/refund-notify") @ApiOperation("退款回调") - public CommonResult refundNotify(@RequestBody @Valid PayRefundOrderReqVO reqVO) { + public CommonResult refundNotify(@RequestBody @Valid PayRefundNotifyReqDTO reqVO) { log.info("[refundNotify][回调成功]"); return success(true); } diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 69896f780..f336560de 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -167,9 +167,8 @@ yudao: - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 pay: - pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify - pay-return-url: http://niubi.natapp1.cc/api/pay/order/return - refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify + callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback + return-url: http://yunai.natapp1.cc/admin-api/pay/notify/return demo: true # 开启演示模式 justauth: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index a0f09eff3..547efa69a 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -30,7 +30,7 @@ spring: multi-statement-allow: true dynamic: # 多数据源配置 druid: # Druid 【连接池】相关的全局配置 - initial-size: 1 # 初始连接数 + initial-size: 5 # 初始连接数 min-idle: 10 # 最小连接池数量 max-active: 20 # 最大连接池数量 max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 @@ -56,7 +56,7 @@ spring: # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W slave: # 模拟从库,可根据自己需要修改 name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 @@ -151,12 +151,14 @@ logging: # 配置自己写的 MyBatis Mapper 打印日志 cn.iocoder.yudao.module.bpm.dal.mysql: debug cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info cn.iocoder.yudao.module.pay.dal.mysql: debug cn.iocoder.yudao.module.system.dal.mysql: debug cn.iocoder.yudao.module.tool.dal.mysql: debug cn.iocoder.yudao.module.member.dal.mysql: debug cn.iocoder.yudao.module.trade.dal.mysql: debug cn.iocoder.yudao.module.promotion.dal.mysql: debug + debug: false --- #################### 微信公众号、小程序相关配置 #################### @@ -191,9 +193,8 @@ yudao: - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 pay: - pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify - pay-return-url: http://niubi.natapp1.cc/api/pay/order/return - refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify + callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback + return-url: http://yunai.natapp1.cc/admin-api/pay/notify/return access-log: # 访问日志的配置项 enable: false error-code: # 错误码相关配置项 diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 7918d443c..d6b0ea3e8 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -117,7 +117,7 @@ yudao: - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 - /admin-api/infra/file/*/get/** # 获取图片,和租户无关 - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号 - - /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号 + - /admin-api/pay/notify/callback/* # 支付回调通知,不携带租户编号 - /jmreport/* # 积木报表,无法携带租户编号 ignore-tables: - system_tenant diff --git a/yudao-ui-admin-vue3/.env b/yudao-ui-admin-vue3/.env index e5996ca53..e5dbc8ecf 100644 --- a/yudao-ui-admin-vue3/.env +++ b/yudao-ui-admin-vue3/.env @@ -12,3 +12,6 @@ VITE_APP_TENANT_ENABLE=true # 验证码的开关 VITE_APP_CAPTCHA_ENABLE=true + +# 路由在只有一个子集的时候是否显示父级 +VITE_ROUTE_ALWAYSSHOW_ENABLE=true diff --git a/yudao-ui-admin-vue3/.prettierignore b/yudao-ui-admin-vue3/.prettierignore index 15cf07183..21dcc7fbc 100644 --- a/yudao-ui-admin-vue3/.prettierignore +++ b/yudao-ui-admin-vue3/.prettierignore @@ -6,5 +6,4 @@ /vite.config.ts /src/types/env.d.ts /docs/**/* -/plop/**/* CHANGELOG diff --git a/yudao-ui-admin-vue3/README.md b/yudao-ui-admin-vue3/README.md index bf9692ae6..10fb35e02 100644 --- a/yudao-ui-admin-vue3/README.md +++ b/yudao-ui-admin-vue3/README.md @@ -1,43 +1,45 @@ -

🌈 yudao-ui-admin-vue3

-

- - - - - - - +# 🌈 yudao-ui-admin-vue3 # + +

+ vue + vite + typescript + Pinia2 + eslint + pnpm Prettier - Less - Taiwind + Sass + WindCSS

+ ## 介绍 -- 基于 vue3.2+ ,TypeScript ,Element Plus 2.2.0+ ,Vite3 ,Pinia ,Windicss 等开发的后台管理系统 +- 基于 vue3.2+ ,TypeScript ,Element Plus 2.2.0+ ,Vite4 ,Pinia ,Vxe-table , Windicss 等开发的后台管理系统 ## 注意事项 - 项目路径请不要使用中文命名!!!会造成解析乱码!!!请使用全英文路径!!! -- node >=14.19.0(建议使用 16 版本) ,pnpm >=7 +- node >=16 ,pnpm >=7.1 - 开发建议使用 [谷歌浏览器-开发者版](https://www.google.cn/intl/zh-CN/chrome/dev/) 不支持 IE\QQ 等浏览器 ### 点击查看[使用说明](./use.md) ### 前端依赖 -| 框架 | 说明 | 版本 | -| --- | --- |--------| -| [Vue](https://staging-cn.vuejs.org/) | vue 框架 | 3.2.44 | -| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.2.3 | -| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.20 | -| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.8.4 | -| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.23 | -| [vueuse](https://vueuse.org//) | 常用工具集 | 9.4.0 | -| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 | -| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.6 | -| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 | -| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.0.0 | -| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.22 | +| 框架 | 说明 | 版本 | +| --- | --- | --- | +| [Vue](https://staging-cn.vuejs.org/) | vue 框架 | 3.2.45 | +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.3 | +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.27 | +| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.9.4 | +| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.28 | +| [vueuse](https://vueuse.org/) | 常用工具集 | 9.8.2 | +| [vxe-table](https://vxetable.cn/) | vue 最强表单 | 4.3.7 | +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 | +| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.6 | +| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 | +| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.0.0 | +| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.23 | ### 推荐 VScode 开发,插件如下 @@ -82,7 +84,7 @@ pnpm install - 运行项目 ```bash -pnpm run dev +pnpm dev ``` - 打包 @@ -103,7 +105,13 @@ pnpm add 包名 pnpm remove 包名 ``` -- 其他命令请看 package.json +- 设置镜像源 + +```bash +pnpm config set registry https://registry.npm.taobao.org/ +``` + +- 其他命令请看 package.json scripts ## 浏览器支持 diff --git a/yudao-ui-admin-vue3/build/vite/index.ts b/yudao-ui-admin-vue3/build/vite/index.ts new file mode 100644 index 000000000..53da870f1 --- /dev/null +++ b/yudao-ui-admin-vue3/build/vite/index.ts @@ -0,0 +1,76 @@ +import { resolve } from 'path' +import Vue from '@vitejs/plugin-vue' +import VueJsx from '@vitejs/plugin-vue-jsx' +import WindiCSS from 'vite-plugin-windicss' +import progress from 'vite-plugin-progress' +import EslintPlugin from 'vite-plugin-eslint' +import PurgeIcons from 'vite-plugin-purge-icons' +import { ViteEjsPlugin } from 'vite-plugin-ejs' +import viteCompression from 'vite-plugin-compression' +import vueSetupExtend from 'vite-plugin-vue-setup-extend' +import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' +import { + createStyleImportPlugin, + ElementPlusResolve, + VxeTableResolve +} from 'vite-plugin-style-import' +export function createVitePlugins(VITE_APP_TITLE: string) { + const root = process.cwd() + // 路径查找 + function pathResolve(dir: string) { + return resolve(root, '.', dir) + } + return [ + Vue(), + VueJsx(), + WindiCSS(), + progress(), + PurgeIcons(), + vueSetupExtend(), + createStyleImportPlugin({ + resolves: [ElementPlusResolve(), VxeTableResolve()], + libs: [ + { + libraryName: 'element-plus', + esModule: true, + resolveStyle: (name) => { + return `element-plus/es/components/${name.substring(3)}/style/css` + } + }, + { + libraryName: 'vxe-table', + esModule: true, + resolveStyle: (name) => { + return `vxe-table/es/${name}/style.css` + } + } + ] + }), + EslintPlugin({ + cache: false, + include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件 + }), + VueI18nPlugin({ + runtimeOnly: true, + compositionOnly: true, + include: [resolve(__dirname, 'src/locales/**')] + }), + createSvgIconsPlugin({ + iconDirs: [pathResolve('src/assets/svgs')], + symbolId: 'icon-[dir]-[name]', + svgoOptions: true + }), + viteCompression({ + verbose: true, // 是否在控制台输出压缩结果 + disable: false, // 是否禁用 + threshold: 10240, // 体积大于 threshold 才会被压缩,单位 b + algorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw'] + ext: '.gz', // 生成的压缩包后缀 + deleteOriginFile: false //压缩后是否删除源文件 + }), + ViteEjsPlugin({ + title: VITE_APP_TITLE + }) + ] +} diff --git a/yudao-ui-admin-vue3/build/vite/optimize.ts b/yudao-ui-admin-vue3/build/vite/optimize.ts new file mode 100644 index 000000000..583daa93b --- /dev/null +++ b/yudao-ui-admin-vue3/build/vite/optimize.ts @@ -0,0 +1,40 @@ +const include = [ + 'qs', + 'url', + 'vue', + 'sass', + 'mitt', + 'axios', + 'pinia', + 'dayjs', + 'qrcode', + 'windicss', + 'vue-router', + 'vue-types', + 'vue-i18n', + 'xe-utils', + 'crypto-js', + 'lodash-es', + 'vxe-table', + 'nprogress', + 'animate.css', + 'vxe-table/es/style', + 'web-storage-cache', + 'element-plus', + 'element-plus/es/locale/lang/zh-cn', + 'element-plus/es/locale/lang/en', + '@iconify/iconify', + '@vueuse/core', + '@zxcvbn-ts/core', + 'echarts/core', + 'echarts/charts', + 'echarts/components', + 'echarts/renderers', + 'echarts-wordcloud', + '@wangeditor/editor', + '@wangeditor/editor-for-vue' +] + +const exclude = ['@iconify/json'] + +export { include, exclude } diff --git a/yudao-ui-admin-vue3/build/vite/styleImport.ts b/yudao-ui-admin-vue3/build/vite/styleImport.ts new file mode 100644 index 000000000..30dac059b --- /dev/null +++ b/yudao-ui-admin-vue3/build/vite/styleImport.ts @@ -0,0 +1,18 @@ +export const styleImportPlugin = { + libs: [ + { + libraryName: 'element-plus', + esModule: true, + resolveStyle: (name) => { + return `element-plus/es/components/${name.substring(3)}/style/css` + } + }, + { + libraryName: 'vxe-table', + esModule: true, + resolveStyle: (name) => { + return `vxe-table/es/${name}/style.css` + } + } + ] +} diff --git a/yudao-ui-admin-vue3/index.html b/yudao-ui-admin-vue3/index.html index f55255d15..cce65bdc7 100644 --- a/yudao-ui-admin-vue3/index.html +++ b/yudao-ui-admin-vue3/index.html @@ -7,11 +7,11 @@ <%= title %> diff --git a/yudao-ui-admin-vue3/package.json b/yudao-ui-admin-vue3/package.json index e90ef4070..4bc43875d 100644 --- a/yudao-ui-admin-vue3/package.json +++ b/yudao-ui-admin-vue3/package.json @@ -1,12 +1,12 @@ { - "name": "ruoyi-vue-pro-vue3", - "version": "1.6.4.1841", - "description": "基于vue3、vite3、element-plus、typesScript", + "name": "yudao-ui-admin-vue3", + "version": "1.6.5.1879", + "description": "基于vue3、vite4、element-plus、typesScript", "author": "xingyu", "private": false, "scripts": { "i": "pnpm install", - "dev": "vite --mode base --open", + "dev": "vite --mode base", "ts:check": "vue-tsc --noEmit", "build:pro": "vite build --mode pro", "build:dev": "vite build --mode dev", @@ -18,96 +18,97 @@ "clean": "npx rimraf node_modules", "clean:cache": "npx rimraf node_modules/.cache", "lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src", - "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,vue,html,md}\"", + "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"", "lint:style": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", "lint:lint-staged": "lint-staged -c ", - "lint:pretty": "pretty-quick --staged", - "p": "plop" + "lint:pretty": "pretty-quick --staged" }, "dependencies": { - "@iconify/iconify": "^3.0.0", - "@vueuse/core": "^9.5.0", - "@wangeditor/editor": "^5.1.22", + "@iconify/iconify": "^3.0.1", + "@vueuse/core": "^9.9.0", + "@wangeditor/editor": "^5.1.23", "@wangeditor/editor-for-vue": "^5.1.10", "@zxcvbn-ts/core": "^2.1.0", "animate.css": "^4.1.1", - "axios": "^0.27.2", + "axios": "^1.2.1", + "cropperjs": "^1.5.13", "crypto-js": "^4.1.1", - "dayjs": "^1.11.6", - "echarts": "^5.4.0", - "echarts-wordcloud": "^2.0.0", - "element-plus": "2.2.20", + "dayjs": "^1.11.7", + "echarts": "^5.4.1", + "echarts-wordcloud": "^2.1.0", + "element-plus": "2.2.27", "intro.js": "^6.0.0", "jsencrypt": "^3.3.1", - "js-cookie": "^3.0.1", "lodash-es": "^4.17.21", "mitt": "^3.0.0", "nprogress": "^0.2.0", - "pinia": "^2.0.23", + "pinia": "^2.0.28", "qrcode": "^1.5.1", "qs": "^6.11.0", "url": "^0.11.0", - "vue": "3.2.44", - "vue-cropper": "^1.0.3", + "vue": "3.2.45", "vue-i18n": "9.2.2", "vue-router": "^4.1.6", - "vue-types": "^4.2.1", - "vxe-table": "^4.3.5", + "vue-types": "^5.0.2", + "vxe-table": "^4.3.7", "web-storage-cache": "^1.1.1", "xe-utils": "^3.5.7" }, "devDependencies": { - "@commitlint/cli": "^17.2.0", - "@commitlint/config-conventional": "^17.2.0", - "@iconify/json": "^2.1.135", - "@intlify/vite-plugin-vue-i18n": "^6.0.3", + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@iconify/json": "^2.1.157", + "@intlify/unplugin-vue-i18n": "^0.8.1", "@purge-icons/generated": "^0.9.0", "@types/intro.js": "^5.1.0", "@types/lodash-es": "^4.17.6", - "@types/node": "^18.11.9", + "@types/node": "^18.11.17", "@types/nprogress": "^0.2.0", "@types/qrcode": "^1.5.0", "@types/qs": "^6.9.7", - "@typescript-eslint/eslint-plugin": "^5.42.1", - "@typescript-eslint/parser": "^5.42.1", - "@vitejs/plugin-vue": "^3.2.0", - "@vitejs/plugin-vue-jsx": "^2.1.1", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", + "@vitejs/plugin-legacy": "^3.0.1", + "@vitejs/plugin-vue": "^4.0.0", + "@vitejs/plugin-vue-jsx": "^3.0.0", "autoprefixer": "^10.4.13", - "eslint": "^8.27.0", + "consola": "^2.15.3", + "eslint": "^8.30.0", "eslint-config-prettier": "^8.5.0", "eslint-define-config": "^1.12.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-vue": "^9.7.0", - "less": "^4.1.3", - "lint-staged": "^13.0.3", - "plop": "^3.1.1", - "postcss": "^8.4.18", + "eslint-plugin-vue": "^9.8.0", + "lint-staged": "^13.1.0", + "postcss": "^8.4.20", "postcss-html": "^1.5.0", - "postcss-less": "^6.0.0", - "prettier": "^2.7.1", + "postcss-scss": "^4.0.6", + "prettier": "^2.8.1", "rimraf": "^3.0.2", - "rollup": "^3.2.5", - "stylelint": "^14.14.1", + "rollup": "^3.8.1", + "sass": "^1.57.1", + "stylelint": "^14.16.0", "stylelint-config-html": "^1.1.0", "stylelint-config-prettier": "^9.0.4", "stylelint-config-recommended": "^9.0.0", "stylelint-config-standard": "^29.0.0", "stylelint-order": "^5.0.0", - "typescript": "4.8.4", - "unplugin-vue-macros": "^0.16.2", - "vite": "3.2.3", + "terser": "^5.16.1", + "typescript": "4.9.4", + "vite": "4.0.3", "vite-plugin-compression": "^0.5.1", + "vite-plugin-ejs": "^1.6.4", "vite-plugin-eslint": "^1.8.1", - "vite-plugin-html": "^3.2.0", - "vite-plugin-purge-icons": "^0.9.1", + "vite-plugin-progress": "^0.0.6", + "vite-plugin-purge-icons": "^0.9.2", "vite-plugin-style-import": "2.0.0", "vite-plugin-svg-icons": "^2.0.1", - "vite-plugin-windicss": "^1.8.8", - "vue-tsc": "^1.0.9", + "vite-plugin-vue-setup-extend": "^0.4.0", + "vite-plugin-windicss": "^1.8.10", + "vue-tsc": "^1.0.17", "windicss": "^3.5.6" }, "engines": { - "node": "^14.19.0 || >=16.0.0" + "node": ">=16.0.0" }, "license": "MIT", "repository": { @@ -115,7 +116,7 @@ "url": "git+https://gitee.com/zhijiantianya/ruoyi-vue-pro" }, "bugs": { - "url": "https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues/I57XOQ" + "url": "https://gitee.com/zhijiantianya/ruoyi-vue-pro/issues" }, "homepage": "https://gitee.com/zhijiantianya/ruoyi-vue-pro" } diff --git a/yudao-ui-admin-vue3/plop/component/component.hbs b/yudao-ui-admin-vue3/plop/component/component.hbs deleted file mode 100644 index 21e56533d..000000000 --- a/yudao-ui-admin-vue3/plop/component/component.hbs +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/yudao-ui-admin-vue3/plop/component/index.hbs b/yudao-ui-admin-vue3/plop/component/index.hbs deleted file mode 100644 index aca6f0a8c..000000000 --- a/yudao-ui-admin-vue3/plop/component/index.hbs +++ /dev/null @@ -1,3 +0,0 @@ -import {{ upperFirstName }} from './src/{{ upperFirstName }}.vue' - -export { {{ upperFirstName }} } diff --git a/yudao-ui-admin-vue3/plop/component/prompt.js b/yudao-ui-admin-vue3/plop/component/prompt.js deleted file mode 100644 index 98a852f07..000000000 --- a/yudao-ui-admin-vue3/plop/component/prompt.js +++ /dev/null @@ -1,38 +0,0 @@ -const toUpperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1) - -module.exports = { - description: 'Create vue component', - prompts: [ - { - type: 'input', - name: 'name', - message: '请输入组件名称(Please enter the component name)' - } - ], - actions: (data) => { - const { name } = data - const upperFirstName = toUpperCase(name) - - const actions = [] - if (name) { - actions.push({ - type: 'add', - path: `./src/components/${upperFirstName}/src/${upperFirstName}.vue`, - templateFile: './plop/component/component.hbs', - data: { - name, - upperFirstName - } - }, { - type: 'add', - path: `./src/components/${upperFirstName}/index.ts`, - templateFile: './plop/component/index.hbs', - data: { - upperFirstName - } - }) - } - - return actions - } -} diff --git a/yudao-ui-admin-vue3/plop/view/prompt.js b/yudao-ui-admin-vue3/plop/view/prompt.js deleted file mode 100644 index dbf324fb6..000000000 --- a/yudao-ui-admin-vue3/plop/view/prompt.js +++ /dev/null @@ -1,37 +0,0 @@ -const toUpperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1) - -module.exports = { - description: 'Create vue view', - prompts: [ - { - type: 'input', - name: 'path', - message: '请输入路径(Please enter a path)', - default: 'views' - }, - { - type: 'input', - name: 'name', - message: '请输入模块名称(Please enter module name)' - } - ], - actions: (data) => { - const { name, path } = data - const upperFirstName = toUpperCase(name) - - const actions = [] - if (name) { - actions.push({ - type: 'add', - path: `./src/${path}/${upperFirstName}.vue`, - templateFile: './plop/view/view.hbs', - data: { - name, - upperFirstName - } - }) - } - - return actions - } -} diff --git a/yudao-ui-admin-vue3/plop/view/view.hbs b/yudao-ui-admin-vue3/plop/view/view.hbs deleted file mode 100644 index 9e359a85a..000000000 --- a/yudao-ui-admin-vue3/plop/view/view.hbs +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/yudao-ui-admin-vue3/plopfile.js b/yudao-ui-admin-vue3/plopfile.js deleted file mode 100644 index 72e6af29c..000000000 --- a/yudao-ui-admin-vue3/plopfile.js +++ /dev/null @@ -1,7 +0,0 @@ -const viewGenerator = require('./plop/view/prompt.js') -const componentGenerator = require('./plop/component/prompt.js') - -module.exports = function (plop) { - plop.setGenerator('view', viewGenerator) - plop.setGenerator('component', componentGenerator) -} diff --git a/yudao-ui-admin-vue3/pnpm-lock.yaml b/yudao-ui-admin-vue3/pnpm-lock.yaml index 3475dfc95..fd741a973 100644 --- a/yudao-ui-admin-vue3/pnpm-lock.yaml +++ b/yudao-ui-admin-vue3/pnpm-lock.yaml @@ -1,516 +1,209 @@ lockfileVersion: 5.4 specifiers: - '@commitlint/cli': ^17.2.0 - '@commitlint/config-conventional': ^17.2.0 - '@iconify/iconify': ^3.0.0 - '@iconify/json': ^2.1.135 - '@intlify/vite-plugin-vue-i18n': ^6.0.3 + '@commitlint/cli': ^17.3.0 + '@commitlint/config-conventional': ^17.3.0 + '@iconify/iconify': ^3.0.1 + '@iconify/json': ^2.1.156 + '@intlify/unplugin-vue-i18n': ^0.8.1 '@purge-icons/generated': ^0.9.0 '@types/intro.js': ^5.1.0 '@types/lodash-es': ^4.17.6 - '@types/node': ^18.11.9 + '@types/node': ^18.11.17 '@types/nprogress': ^0.2.0 '@types/qrcode': ^1.5.0 '@types/qs': ^6.9.7 - '@typescript-eslint/eslint-plugin': ^5.42.1 - '@typescript-eslint/parser': ^5.42.1 - '@vitejs/plugin-vue': ^3.2.0 - '@vitejs/plugin-vue-jsx': ^2.1.1 - '@vueuse/core': ^9.5.0 - '@wangeditor/editor': ^5.1.22 + '@typescript-eslint/eslint-plugin': ^5.47.0 + '@typescript-eslint/parser': ^5.47.0 + '@vitejs/plugin-legacy': ^3.0.1 + '@vitejs/plugin-vue': ^4.0.0 + '@vitejs/plugin-vue-jsx': ^3.0.0 + '@vueuse/core': ^9.8.2 + '@wangeditor/editor': ^5.1.23 '@wangeditor/editor-for-vue': ^5.1.10 '@zxcvbn-ts/core': ^2.1.0 animate.css: ^4.1.1 autoprefixer: ^10.4.13 - axios: ^0.27.2 + axios: ^1.2.1 + consola: ^2.15.3 + cropperjs: ^1.5.13 crypto-js: ^4.1.1 - dayjs: ^1.11.6 - echarts: ^5.4.0 - echarts-wordcloud: ^2.0.0 - element-plus: 2.2.20 - eslint: ^8.27.0 + dayjs: ^1.11.7 + echarts: ^5.4.1 + echarts-wordcloud: ^2.1.0 + element-plus: 2.2.27 + eslint: ^8.30.0 eslint-config-prettier: ^8.5.0 eslint-define-config: ^1.12.0 eslint-plugin-prettier: ^4.2.1 - eslint-plugin-vue: ^9.7.0 + eslint-plugin-vue: ^9.8.0 intro.js: ^6.0.0 - js-cookie: ^3.0.1 jsencrypt: ^3.3.1 - less: ^4.1.3 - lint-staged: ^13.0.3 + lint-staged: ^13.1.0 lodash-es: ^4.17.21 mitt: ^3.0.0 nprogress: ^0.2.0 - pinia: ^2.0.23 - plop: ^3.1.1 - postcss: ^8.4.18 + pinia: ^2.0.28 + postcss: ^8.4.20 postcss-html: ^1.5.0 - postcss-less: ^6.0.0 - prettier: ^2.7.1 + postcss-scss: ^4.0.6 + prettier: ^2.8.1 qrcode: ^1.5.1 qs: ^6.11.0 rimraf: ^3.0.2 - rollup: ^3.2.5 - stylelint: ^14.14.1 + rollup: ^3.8.1 + sass: ^1.57.1 + stylelint: ^14.16.0 stylelint-config-html: ^1.1.0 stylelint-config-prettier: ^9.0.4 stylelint-config-recommended: ^9.0.0 stylelint-config-standard: ^29.0.0 stylelint-order: ^5.0.0 - typescript: 4.8.4 - unplugin-vue-macros: ^0.16.2 + terser: ^5.16.1 + typescript: 4.9.4 url: ^0.11.0 - vite: 3.2.3 + vite: 4.0.3 vite-plugin-compression: ^0.5.1 + vite-plugin-ejs: ^1.6.4 vite-plugin-eslint: ^1.8.1 - vite-plugin-html: ^3.2.0 - vite-plugin-purge-icons: ^0.9.1 + vite-plugin-progress: ^0.0.6 + vite-plugin-purge-icons: ^0.9.2 vite-plugin-style-import: 2.0.0 vite-plugin-svg-icons: ^2.0.1 - vite-plugin-windicss: ^1.8.8 - vue: 3.2.44 - vue-cropper: ^1.0.3 + vite-plugin-vue-setup-extend: ^0.4.0 + vite-plugin-windicss: ^1.8.10 + vue: 3.2.45 vue-i18n: 9.2.2 vue-router: ^4.1.6 - vue-tsc: ^1.0.9 - vue-types: ^4.2.1 - vxe-table: ^4.3.5 + vue-tsc: ^1.0.16 + vue-types: ^5.0.2 + vxe-table: ^4.3.7 web-storage-cache: ^1.1.1 windicss: ^3.5.6 xe-utils: ^3.5.7 dependencies: - '@iconify/iconify': 3.0.0 - '@vueuse/core': 9.5.0_vue@3.2.44 - '@wangeditor/editor': 5.1.22 - '@wangeditor/editor-for-vue': 5.1.12_su3dw7bmszfjg67suaojchptby + '@iconify/iconify': 3.0.1 + '@vueuse/core': 9.8.2_vue@3.2.45 + '@wangeditor/editor': 5.1.23 + '@wangeditor/editor-for-vue': 5.1.12_3apfu3xbp6awzuex7ed3sbrv6y '@zxcvbn-ts/core': 2.1.0 animate.css: 4.1.1 - axios: 0.27.2 + axios: 1.2.1 + cropperjs: 1.5.13 crypto-js: 4.1.1 - dayjs: 1.11.6 - echarts: 5.4.0 - echarts-wordcloud: 2.0.0_echarts@5.4.0 - element-plus: 2.2.20_vue@3.2.44 + dayjs: 1.11.7 + echarts: registry.npmmirror.com/echarts/5.4.1 + echarts-wordcloud: 2.1.0_echarts@5.4.1 + element-plus: 2.2.27_vue@3.2.45 intro.js: 6.0.0 - js-cookie: 3.0.1 jsencrypt: 3.3.1 lodash-es: 4.17.21 mitt: 3.0.0 nprogress: 0.2.0 - pinia: 2.0.23_d45o5shxrtvj6wh4y524t7cqnm + pinia: registry.npmmirror.com/pinia/2.0.28_prq2uz4lho2pwp6irk4cfkrxwu qrcode: 1.5.1 qs: 6.11.0 url: 0.11.0 - vue: 3.2.44 - vue-cropper: 1.0.5 - vue-i18n: 9.2.2_vue@3.2.44 - vue-router: 4.1.6_vue@3.2.44 - vue-types: 4.2.1_vue@3.2.44 - vxe-table: 4.3.5_vue@3.2.44+xe-utils@3.5.7 + vue: 3.2.45 + vue-i18n: 9.2.2_vue@3.2.45 + vue-router: 4.1.6_vue@3.2.45 + vue-types: 5.0.2_vue@3.2.45 + vxe-table: registry.npmmirror.com/vxe-table/4.3.7_vue@3.2.45+xe-utils@3.5.7 web-storage-cache: 1.1.1 xe-utils: 3.5.7 devDependencies: - '@commitlint/cli': 17.2.0 - '@commitlint/config-conventional': 17.2.0 - '@iconify/json': 2.1.135 - '@intlify/vite-plugin-vue-i18n': 6.0.3_vite@3.2.3+vue-i18n@9.2.2 + '@commitlint/cli': 17.3.0 + '@commitlint/config-conventional': 17.3.0 + '@iconify/json': 2.1.156 + '@intlify/unplugin-vue-i18n': 0.8.1_vue-i18n@9.2.2 '@purge-icons/generated': 0.9.0 '@types/intro.js': 5.1.0 '@types/lodash-es': 4.17.6 - '@types/node': 18.11.9 + '@types/node': 18.11.17 '@types/nprogress': 0.2.0 '@types/qrcode': 1.5.0 '@types/qs': 6.9.7 - '@typescript-eslint/eslint-plugin': 5.42.1_2udltptbznfmezdozpdoa2aemq - '@typescript-eslint/parser': 5.42.1_rmayb2veg2btbq6mbmnyivgasy - '@vitejs/plugin-vue': 3.2.0_vite@3.2.3+vue@3.2.44 - '@vitejs/plugin-vue-jsx': 2.1.1_vite@3.2.3+vue@3.2.44 - autoprefixer: 10.4.13_postcss@8.4.18 - eslint: 8.27.0 - eslint-config-prettier: 8.5.0_eslint@8.27.0 + '@typescript-eslint/eslint-plugin': 5.47.0_ncmi6noazr3nzas7jxykisekym + '@typescript-eslint/parser': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa + '@vitejs/plugin-legacy': registry.npmmirror.com/@vitejs/plugin-legacy/3.0.1_terser@5.16.1+vite@4.0.3 + '@vitejs/plugin-vue': registry.npmmirror.com/@vitejs/plugin-vue/4.0.0_vite@4.0.3+vue@3.2.45 + '@vitejs/plugin-vue-jsx': registry.npmmirror.com/@vitejs/plugin-vue-jsx/3.0.0_vite@4.0.3+vue@3.2.45 + autoprefixer: 10.4.13_postcss@8.4.20 + consola: 2.15.3 + eslint: 8.30.0 + eslint-config-prettier: 8.5.0_eslint@8.30.0 eslint-define-config: 1.12.0 - eslint-plugin-prettier: 4.2.1_v7o5sx5x3wbs57ifz6wc4f76we - eslint-plugin-vue: 9.7.0_eslint@8.27.0 - less: 4.1.3 - lint-staged: 13.0.3 - plop: 3.1.1 - postcss: 8.4.18 + eslint-plugin-prettier: 4.2.1_kl4pe43v5b43npmso5hoplpbyi + eslint-plugin-vue: 9.8.0_eslint@8.30.0 + lint-staged: 13.1.0 + postcss: registry.npmmirror.com/postcss/8.4.20 postcss-html: 1.5.0 - postcss-less: 6.0.0_postcss@8.4.18 - prettier: 2.7.1 + postcss-scss: 4.0.6_postcss@8.4.20 + prettier: 2.8.1 rimraf: 3.0.2 - rollup: 3.2.5 - stylelint: 14.14.1 - stylelint-config-html: 1.1.0_a4i6jbpfaxelx4fvjhtlgvxx6i - stylelint-config-prettier: 9.0.4_stylelint@14.14.1 - stylelint-config-recommended: 9.0.0_stylelint@14.14.1 - stylelint-config-standard: 29.0.0_stylelint@14.14.1 - stylelint-order: 5.0.0_stylelint@14.14.1 - typescript: 4.8.4 - unplugin-vue-macros: 0.16.2_nch4vsbos5hmj7k4a4oy3znhuu - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - vite-plugin-compression: 0.5.1_vite@3.2.3 - vite-plugin-eslint: 1.8.1_eslint@8.27.0+vite@3.2.3 - vite-plugin-html: 3.2.0_vite@3.2.3 - vite-plugin-purge-icons: 0.9.1_vite@3.2.3 - vite-plugin-style-import: 2.0.0_vite@3.2.3 - vite-plugin-svg-icons: 2.0.1_vite@3.2.3 - vite-plugin-windicss: 1.8.8_vite@3.2.3 - vue-tsc: 1.0.9_typescript@4.8.4 + rollup: 3.8.1 + sass: 1.57.1 + stylelint: 14.16.0 + stylelint-config-html: 1.1.0_bto6pmslw3cibsiuq6smxboytq + stylelint-config-prettier: 9.0.4_stylelint@14.16.0 + stylelint-config-recommended: 9.0.0_stylelint@14.16.0 + stylelint-config-standard: 29.0.0_stylelint@14.16.0 + stylelint-order: 5.0.0_stylelint@14.16.0 + terser: 5.16.1 + typescript: 4.9.4 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce + vite-plugin-compression: 0.5.1_vite@4.0.3 + vite-plugin-ejs: 1.6.4 + vite-plugin-eslint: 1.8.1_eslint@8.30.0+vite@4.0.3 + vite-plugin-progress: 0.0.6_vite@4.0.3 + vite-plugin-purge-icons: registry.npmmirror.com/vite-plugin-purge-icons/0.9.2_vite@4.0.3 + vite-plugin-style-import: 2.0.0_vite@4.0.3 + vite-plugin-svg-icons: 2.0.1_vite@4.0.3 + vite-plugin-vue-setup-extend: 0.4.0_vite@4.0.3 + vite-plugin-windicss: registry.npmmirror.com/vite-plugin-windicss/1.8.10_vite@4.0.3 + vue-tsc: 1.0.16_typescript@4.9.4 windicss: 3.5.6 packages: - /@ampproject/remapping/2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.16 - dev: true - - /@antfu/utils/0.5.2: - resolution: {integrity: sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==} - dev: true - - /@antfu/utils/0.6.0: - resolution: {integrity: sha512-VauUKmo22NYo3y6fIjGjVU7LJyhaedYL9kyabdvIIIl7P+qbNPbQiaLwwk4UOU4McFfA2eg+aIWpEYhkHzsE9Q==} - dev: true - - /@babel/code-frame/7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: true - - /@babel/compat-data/7.19.3: - resolution: {integrity: sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core/7.19.6: - resolution: {integrity: sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.0 - '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.19.6 - '@babel/helper-module-transforms': 7.19.6 - '@babel/helpers': 7.20.0 - '@babel/parser': 7.20.0 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.0 - '@babel/types': 7.20.0 - convert-source-map: 1.8.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.1 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator/7.20.0: - resolution: {integrity: sha512-GUPcXxWibClgmYJuIwC2Bc2Lg+8b9VjaJ+HlNdACEVt+Wlr1eoU1OPZjZRm7Hzl0gaTsUZNQfeihvZJhG7oc3w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - dev: true - - /@babel/helper-annotate-as-pure/7.18.6: - resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-compilation-targets/7.19.3_@babel+core@7.19.6: - resolution: {integrity: sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.19.3 - '@babel/core': 7.19.6 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - semver: 6.3.0 - dev: true - - /@babel/helper-create-class-features-plugin/7.20.2_@babel+core@7.19.6: - resolution: {integrity: sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.19.6 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-member-expression-to-functions': 7.18.9 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.19.1 - '@babel/helper-split-export-declaration': 7.18.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-environment-visitor/7.18.9: - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-function-name/7.19.0: - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-hoist-variables/7.18.6: - resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-member-expression-to-functions/7.18.9: - resolution: {integrity: sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-module-imports/7.18.6: - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-module-transforms/7.19.6: - resolution: {integrity: sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.19.4 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.0 - '@babel/types': 7.20.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-optimise-call-expression/7.18.6: - resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-plugin-utils/7.20.2: - resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-replace-supers/7.19.1: - resolution: {integrity: sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-member-expression-to-functions': 7.18.9 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/traverse': 7.20.0 - '@babel/types': 7.20.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-simple-access/7.19.4: - resolution: {integrity: sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-split-export-declaration/7.18.6: - resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - dev: true - - /@babel/helper-string-parser/7.18.10: - resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-string-parser/7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier/7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option/7.18.6: - resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers/7.20.0: - resolution: {integrity: sha512-aGMjYraN0zosCEthoGLdqot1oRsmxVTQRHadsUPz5QM44Zej2PYRz7XiDE7GqnkZnNtLbOuxqoZw42vkU7+XEQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.0 - '@babel/types': 7.20.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight/7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser/7.19.3: - resolution: {integrity: sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==} + /@babel/parser/7.20.3: + resolution: {integrity: sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.19.3 - dev: true + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 - /@babel/parser/7.20.0: - resolution: {integrity: sha512-G9VgAhEaICnz8iiJeGJQyVl6J2nTjbW0xeisva0PK6XcKsga7BIaqm4ZF8Rg1Wbaqmy6znspNqhPaPkyukujzg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.20.0 - - /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.19.6: - resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.6 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.19.6: - resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.6 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-typescript/7.20.2_@babel+core@7.19.6: - resolution: {integrity: sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.19.6 - '@babel/helper-create-class-features-plugin': 7.20.2_@babel+core@7.19.6 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.19.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/runtime/7.19.0: - resolution: {integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==} + /@babel/runtime/7.20.1: + resolution: {integrity: sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==} engines: {node: '>=6.9.0'} dependencies: - regenerator-runtime: 0.13.9 + regenerator-runtime: registry.npmmirror.com/regenerator-runtime/0.13.11 dev: false - /@babel/template/7.18.10: - resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.20.0 - '@babel/types': 7.20.0 - dev: true - - /@babel/traverse/7.20.0: - resolution: {integrity: sha512-5+cAXQNARgjRUK0JWu2UBwja4JLSO/rBMPJzpsKb+oBF5xlUuCfljQepS4XypBQoiigL0VQjTZy6WiONtUdScQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.0 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.0 - '@babel/types': 7.20.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types/7.19.3: - resolution: {integrity: sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.18.10 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - dev: true - - /@babel/types/7.20.0: - resolution: {integrity: sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - - /@commitlint/cli/17.2.0: - resolution: {integrity: sha512-kd1zykcrjIKyDRftWW1E1TJqkgzeosEkv1BiYPCdzkb/g/3BrfgwZUHR1vg+HO3qKUb/0dN+jNXArhGGAHpmaQ==} + /@commitlint/cli/17.3.0: + resolution: {integrity: sha512-/H0md7TsKflKzVPz226VfXzVafJFO1f9+r2KcFvmBu08V0T56lZU1s8WL7/xlxqLMqBTVaBf7Ixtc4bskdEEZg==} engines: {node: '>=v14'} hasBin: true dependencies: '@commitlint/format': 17.0.0 - '@commitlint/lint': 17.2.0 - '@commitlint/load': 17.2.0 + '@commitlint/lint': 17.3.0 + '@commitlint/load': 17.3.0 '@commitlint/read': 17.2.0 '@commitlint/types': 17.0.0 execa: 5.1.1 - lodash: 4.17.21 + lodash.isfunction: 3.0.9 resolve-from: 5.0.0 resolve-global: 1.0.0 - yargs: 17.6.0 + yargs: 17.6.2 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' dev: true - /@commitlint/config-conventional/17.2.0: - resolution: {integrity: sha512-g5hQqRa80f++SYS233dbDSg16YdyounMTAhVcmqtInNeY/GF3aA4st9SVtJxpeGrGmueMrU4L+BBb+6Vs5wrcg==} + /@commitlint/config-conventional/17.3.0: + resolution: {integrity: sha512-hgI+fN5xF8nhS9uG/V06xyT0nlcyvHHMkq0kwRSr96vl5BFlRGaL2C0/YY4kQagfU087tmj01bJkG9Ek98Wllw==} engines: {node: '>=v14'} dependencies: conventional-changelog-conventionalcommits: 5.0.0 @@ -521,15 +214,19 @@ packages: engines: {node: '>=v14'} dependencies: '@commitlint/types': 17.0.0 - ajv: 8.11.0 + ajv: 8.11.2 dev: true - /@commitlint/ensure/17.0.0: - resolution: {integrity: sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==} + /@commitlint/ensure/17.3.0: + resolution: {integrity: sha512-kWbrQHDoW5veIUQx30gXoLOCjWvwC6OOEofhPCLl5ytRPBDAQObMbxTha1Bt2aSyNE/IrJ0s0xkdZ1Gi3wJwQg==} engines: {node: '>=v14'} dependencies: '@commitlint/types': 17.0.0 - lodash: 4.17.21 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 dev: true /@commitlint/execute-rule/17.0.0: @@ -550,35 +247,37 @@ packages: engines: {node: '>=v14'} dependencies: '@commitlint/types': 17.0.0 - semver: 7.3.7 + semver: registry.npmmirror.com/semver/7.3.7 dev: true - /@commitlint/lint/17.2.0: - resolution: {integrity: sha512-N2oLn4Dj672wKH5qJ4LGO+73UkYXGHO+NTVUusGw83SjEv7GjpqPGKU6KALW2kFQ/GsDefSvOjpSi3CzWHQBDg==} + /@commitlint/lint/17.3.0: + resolution: {integrity: sha512-VilOTPg0i9A7CCWM49E9bl5jytfTvfTxf9iwbWAWNjxJ/A5mhPKbm3sHuAdwJ87tDk1k4j8vomYfH23iaY+1Rw==} engines: {node: '>=v14'} dependencies: '@commitlint/is-ignored': 17.2.0 '@commitlint/parse': 17.2.0 - '@commitlint/rules': 17.2.0 + '@commitlint/rules': 17.3.0 '@commitlint/types': 17.0.0 dev: true - /@commitlint/load/17.2.0: - resolution: {integrity: sha512-HDD57qSqNrk399R4TIjw31AWBG8dBjNj1MrDKZKmC/wvimtnIFlqzcu1+sxfXIOHj/+M6tcMWDtvknGUd7SU+g==} + /@commitlint/load/17.3.0: + resolution: {integrity: sha512-u/pV6rCAJrCUN+HylBHLzZ4qj1Ew3+eN9GBPhNi9otGxtOfA8b+8nJSxaNbcC23Ins/kcpjGf9zPSVW7628Umw==} engines: {node: '>=v14'} dependencies: '@commitlint/config-validator': 17.1.0 '@commitlint/execute-rule': 17.0.0 - '@commitlint/resolve-extends': 17.1.0 + '@commitlint/resolve-extends': 17.3.0 '@commitlint/types': 17.0.0 - '@types/node': 14.18.31 + '@types/node': 14.18.33 chalk: 4.1.2 - cosmiconfig: 7.0.1 - cosmiconfig-typescript-loader: 4.1.1_gpl3msxjb2n3qdkii2jvdrcxxe - lodash: 4.17.21 + cosmiconfig: 7.1.0 + cosmiconfig-typescript-loader: 4.2.0_wb7bklcl6jlvxijczjyxggip4a + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 resolve-from: 5.0.0 - ts-node: 10.9.1_fk6arlf3j7tudlucddpzvj2plq - typescript: 4.8.4 + ts-node: 10.9.1_rju6pyblifsagdmqm3y74zsi6q + typescript: 4.9.4 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' @@ -606,26 +305,26 @@ packages: '@commitlint/types': 17.0.0 fs-extra: 10.1.0 git-raw-commits: 2.0.11 - minimist: 1.2.6 + minimist: 1.2.7 dev: true - /@commitlint/resolve-extends/17.1.0: - resolution: {integrity: sha512-jqKm00LJ59T0O8O4bH4oMa4XyJVEOK4GzH8Qye9XKji+Q1FxhZznxMV/bDLyYkzbTodBt9sL0WLql8wMtRTbqQ==} + /@commitlint/resolve-extends/17.3.0: + resolution: {integrity: sha512-Lf3JufJlc5yVEtJWC8o4IAZaB8FQAUaVlhlAHRACd0TTFizV2Lk2VH70et23KgvbQNf7kQzHs/2B4QZalBv6Cg==} engines: {node: '>=v14'} dependencies: '@commitlint/config-validator': 17.1.0 '@commitlint/types': 17.0.0 import-fresh: 3.3.0 - lodash: 4.17.21 + lodash.mergewith: 4.6.2 resolve-from: 5.0.0 resolve-global: 1.0.0 dev: true - /@commitlint/rules/17.2.0: - resolution: {integrity: sha512-1YynwD4Eh7HXZNpqG8mtUlL2pSX2jBy61EejYJv4ooZPcg50Ak7LPOyD3a9UZnsE76AXWFBz+yo9Hv4MIpAa0Q==} + /@commitlint/rules/17.3.0: + resolution: {integrity: sha512-s2UhDjC5yP2utx3WWqsnZRzjgzAX8BMwr1nltC0u0p8T/nzpkx4TojEfhlsOUj1t7efxzZRjUAV0NxNwdJyk+g==} engines: {node: '>=v14'} dependencies: - '@commitlint/ensure': 17.0.0 + '@commitlint/ensure': 17.3.0 '@commitlint/message': 17.2.0 '@commitlint/to-lines': 17.0.0 '@commitlint/types': 17.0.0 @@ -655,18 +354,18 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} dependencies: - '@jridgewell/trace-mapping': 0.3.9 + '@jridgewell/trace-mapping': registry.npmmirror.com/@jridgewell/trace-mapping/0.3.9 dev: true - /@csstools/selector-specificity/2.0.2_dvkg4kkb622mvceygg47xxdz3a: + /@csstools/selector-specificity/2.0.2_2xshye3abirqjlplmebvmaxyna: resolution: {integrity: sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==} engines: {node: ^12 || ^14 || >=16} peerDependencies: postcss: ^8.2 postcss-selector-parser: ^6.0.10 dependencies: - postcss: 8.4.18 - postcss-selector-parser: 6.0.10 + postcss: registry.npmmirror.com/postcss/8.4.20 + postcss-selector-parser: 6.0.11 dev: true /@ctrl/tinycolor/3.4.1: @@ -674,16 +373,16 @@ packages: engines: {node: '>=10'} dev: false - /@element-plus/icons-vue/2.0.9_vue@3.2.44: - resolution: {integrity: sha512-okdrwiVeKBmW41Hkl0eMrXDjzJwhQMuKiBOu17rOszqM+LS/yBYpNQNV5Jvoh06Wc+89fMmb/uhzf8NZuDuUaQ==} + /@element-plus/icons-vue/2.0.10_vue@3.2.45: + resolution: {integrity: sha512-ygEZ1mwPjcPo/OulhzLE7mtDrQBWI8vZzEWSNB2W/RNCRjoQGwbaK4N8lV4rid7Ts4qvySU3njMN7YCiSlSaTQ==} peerDependencies: vue: ^3.2.0 dependencies: - vue: 3.2.44 + vue: 3.2.45 dev: false - /@esbuild/android-arm/0.15.10: - resolution: {integrity: sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==} + /@esbuild/android-arm/0.16.5: + resolution: {integrity: sha512-eNkNuLSKpbZTH0BZklJ9B9Sml7fTIamhrQNBwftsEHCUuSLBVunzV3LfghryVGpE5lSkOwOfeX6gR6+3yLaEfQ==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -691,8 +390,89 @@ packages: dev: true optional: true - /@esbuild/linux-loong64/0.15.10: - resolution: {integrity: sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==} + /@esbuild/android-arm64/0.16.5: + resolution: {integrity: sha512-BCWkmAqFoW6xXzz6Up16bU0vdZqe23UxkrabbrmXXUuH27Tts3LVcHFCi/dGLYa6ZqC/txhtJm2kAJdoyOfHxg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.16.5: + resolution: {integrity: sha512-E0R7d0dy9+QlpMps8gJXXhtfn+fQFaTXbq8kV2u/HfHyyhxr4nIIuXZCcYxxA9LSKnsFBBbSQIGDUVY9FGgx0w==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.16.5: + resolution: {integrity: sha512-4HlbUMy50cRaHGVriBjShs46WRPshtnVOqkxEGhEuDuJhgZ3regpWzaQxXOcDXFvVwue8RiqDAAcOi/QlVLE6Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.16.5: + resolution: {integrity: sha512-ZDCAxAPwbtKJ5YxRZusQKDFuywH+7YNKbilss0DCRPtXMxrKRZETcuSfcgIWGYBBc+ypdOazousx3yZss2Az0A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.16.5: + resolution: {integrity: sha512-w0dJ8om4KiagLCHURgwxXVWzi5xa0W7F5woMxzWO+LDCebrlyZUhCIbSXUKa4qD3XbdG7K4Y8N4mLDRMkZzMuw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.16.5: + resolution: {integrity: sha512-qCdC0T7XUxngX8otO4nmPUE/cHZfvF8jk+GMr9qkAGP0nIMACD7t/AWoY2N5rsn5/dOJ1VKM/aMF4wCFBP5AqQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.16.5: + resolution: {integrity: sha512-6crdpqwFjl+DObBgwaJMtB+VWrZd87Jy05gQTERysc1ujnUJNCJzemUcRDT5hM34dzTYThlXfFW32qQy9QpPGQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.16.5: + resolution: {integrity: sha512-h84QZmBhBdEclyxf9Wm/UESY6ITI7/gYLNvj/3emhDd0ILAqwHdWnMDmKqqubrMcpb1O4sWOYRm7EZ+Av8eGiQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.16.5: + resolution: {integrity: sha512-P1WNzGqy6ipvbt8iNoYY66+qUANCiM80D8bGJIU8jqSZ613eG0lUWBePi4xQazcNgIi9tSiCa9Ba3f4krXtQDw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.16.5: + resolution: {integrity: sha512-r8wKqs+rl4gIT/xDB6CHMaYcvvyZ7tWf5LulH9NsDvgQEy3gIXQPR4Oy9tYrjM75uKkvBv1uw15Iz4EWsvve9Q==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -700,15 +480,114 @@ packages: dev: true optional: true - /@eslint/eslintrc/1.3.3: - resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==} + /@esbuild/linux-mips64el/0.16.5: + resolution: {integrity: sha512-0WMhOlwfeeAp6KMx3E6LZKDN6INk4Me8dwIw1XMSFvmE6r31vRnwXkrQlAk5FI44KZ/rIi+yynRZqEd7UJAV2g==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.16.5: + resolution: {integrity: sha512-29x+DtRGcYH0Sh3QSnoF+D2SYkHLxwx5AugoGLIlVtcVqDb4fEb654d67k9VcAR2RiTAYUZ764KXzWB+ItQfgw==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.16.5: + resolution: {integrity: sha512-ZX4SSKOJUcuqFNDydfN4yCo9je9f1T72Pj+RLsAGRiuiREVCwRkXIBp810C01+MdPqYExp322kY78ISEq5XGLQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.16.5: + resolution: {integrity: sha512-pYY86RiLD1s5RN8q0aMhWD44NiHmAZxv2bSzaNlL63/ibWETld+m6F+MPh9+ZNOqGJw53E/0qHukYI5Lm+1k7A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.16.5: + resolution: {integrity: sha512-vsOwzKN+4NenUTyuoWLmg5dAuO8JKuLD9MXSeENA385XucuOZbblmOMwwgPlHsgVRtSjz38riqPJU2ALI/CWYQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.16.5: + resolution: {integrity: sha512-ZhfELxpZLXg7OidX9MrjgQNhjhYx3GXm59EAQVZds8GTyOOPj+Hg7ttKenlXoV8PZVkoCm0dgoWXzhasZJGfWw==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.16.5: + resolution: {integrity: sha512-2HY2L0afN8IUgvxCAWY04bB6mhHSnC7YNGM2hmEkyAgP+n8jpZgGjiRokuk3AQ0g0IpX8h0KnS+xaznGEr5CGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.16.5: + resolution: {integrity: sha512-Q7+HbDnW52LLW8YIU5h0sYZ23TvaaC0vuwiIbJUa91Qr77NKNJCe8stfunN1TRZo+6OwGpM3MrdUcUVUfr5wuA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.16.5: + resolution: {integrity: sha512-KcegNS7IgLm/cAcjIW3kZyLiZi/p8I+A2a6OonDA77em9xHewdA2yTA+9pO4gr77MkXATcnDAFBrWw5oLHIZkQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.16.5: + resolution: {integrity: sha512-ReUCJSzLNGH6WcvwjMzpEy2SX5GTZBeRTvCdklN4DT2YrgRIe82lYVikVHwA7fdiL3xHKvmdiicMqxE8QYmxrA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.16.5: + resolution: {integrity: sha512-q00Jasz6/wCOD2XxRj4GEwj27u1zfpiBniL1ip3/YGGcYtvOoGKCNSS47sufO/8ixEgrSYDlkglSd6CxcS7m0g==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint/eslintrc/1.4.0: + resolution: {integrity: sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 9.4.0 - globals: 13.17.0 - ignore: 5.2.0 + espree: 9.4.1 + globals: 13.19.0 + ignore: 5.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -717,18 +596,18 @@ packages: - supports-color dev: true - /@floating-ui/core/1.0.1: - resolution: {integrity: sha512-bO37brCPfteXQfFY0DyNDGB3+IMe4j150KFQcgJ5aBP295p9nBGeHEs/p0czrRbtlHq4Px/yoPXO/+dOCcF4uA==} + /@floating-ui/core/1.0.2: + resolution: {integrity: sha512-Skfy0YS3NJ5nV9us0uuPN0HDk1Q4edljaOhRBJGDWs9EBa7ZVMYBHRFlhLvvmwEoaIM9BlH6QJFn9/uZg0bACg==} dev: false - /@floating-ui/dom/1.0.2: - resolution: {integrity: sha512-5X9WSvZ8/fjy3gDu8yx9HAA4KG1lazUN2P4/VnaXLxTO9Dz53HI1oYoh1OlhqFNlHgGDiwFX5WhFCc2ljbW3yA==} + /@floating-ui/dom/1.0.6: + resolution: {integrity: sha512-kt/tg1oip9OAH1xjCTcx1OpcUpu9rjDw3GKJ/rEhUqhO7QyJWfrHU0DpLTNsH67+JyFL5Kv9X1utsXwKFVtyEQ==} dependencies: - '@floating-ui/core': 1.0.1 + '@floating-ui/core': 1.0.2 dev: false - /@humanwhocodes/config-array/0.11.6: - resolution: {integrity: sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==} + /@humanwhocodes/config-array/0.11.8: + resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 @@ -747,21 +626,13 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@iconify/iconify/2.1.2: - resolution: {integrity: sha512-QcUzFeEWkE/mW+BVtEGmcWATClcCOIJFiYUD/PiCWuTcdEA297o8D4oN6Ra44WrNOHu1wqNW4J0ioaDIiqaFOQ==} - dependencies: - cross-fetch: 3.1.5 - transitivePeerDependencies: - - encoding - dev: true - - /@iconify/iconify/3.0.0: - resolution: {integrity: sha512-wgCSv4GwVLzwGqfUkYEDT9XOfetGZV67D5CmMYp74IdaPMnyOWb/3XxUPvGmuTt8Yw9xekMqzvdQp/p+a/abNw==} + /@iconify/iconify/3.0.1: + resolution: {integrity: sha512-OPqVBTh8YsfrYZRVFv3OkmFNLqacM0dy/Oiw1h2wO+RZW5LieNGHlG2f9pzaeVRFWbEB8LHTeo8mcwgUTUbibQ==} dependencies: '@iconify/types': 2.0.0 - /@iconify/json/2.1.135: - resolution: {integrity: sha512-TPcWuayPACVtr2PxMbayUU+UEpoeL9VKvc3iJ+nImmxCZvDqeO7ralHqBSZi52sf9O5lvpe6xQSQijSIr6omAw==} + /@iconify/json/2.1.156: + resolution: {integrity: sha512-QaLf/XSPRe6i35Z9WIRBxlWOLykDXNnEGYFf+9E+GWLmRqVQ2VNyTsEo6CNZqP5eGQRDPJyNhd+2vH+gbehGDg==} dependencies: '@iconify/types': 2.0.0 pathe: 0.3.9 @@ -770,8 +641,8 @@ packages: /@iconify/types/2.0.0: resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - /@intlify/bundle-utils/3.2.1_vue-i18n@9.2.2: - resolution: {integrity: sha512-rf4cLBOnbqmpXVcCdcYHilZpMt1m82syh3WLBJlZvGxN2KkH9HeHVH4+bnibF/SDXCHNh6lM6wTpS/qw+PkcMg==} + /@intlify/bundle-utils/3.4.0_vue-i18n@9.2.2: + resolution: {integrity: sha512-2UQkqiSAOSPEHMGWlybqWm4G2K0X+FyYho5AwXz6QklSX1EY5EDmOSxZmwscn2qmKBnp6OYsme5kUrnN9xrWzQ==} engines: {node: '>= 12'} peerDependencies: petite-vue-i18n: '*' @@ -782,11 +653,11 @@ packages: vue-i18n: optional: true dependencies: - '@intlify/message-compiler': 9.3.0-beta.6 - '@intlify/shared': 9.3.0-beta.6 + '@intlify/message-compiler': 9.3.0-beta.11 + '@intlify/shared': 9.3.0-beta.11 jsonc-eslint-parser: 1.4.1 source-map: 0.6.1 - vue-i18n: 9.2.2_vue@3.2.44 + vue-i18n: 9.2.2_vue@3.2.45 yaml-eslint-parser: 0.3.2 dev: true @@ -812,11 +683,11 @@ packages: '@intlify/shared': 9.2.2 source-map: 0.6.1 - /@intlify/message-compiler/9.3.0-beta.6: - resolution: {integrity: sha512-3PJqRJoqvFHExA9DCkf7fZYKbvYne1tYQ0fptJAhUOZsELarh8wr4aPLKWCkQSRuutdrtZ/n5CcPgJgUmVthDw==} + /@intlify/message-compiler/9.3.0-beta.11: + resolution: {integrity: sha512-gGGfBGzM7JBXp1Q9gbDAy5jELz9ho3ILqnpxp2yp64+gkqohrqc2YXIvCdwZoc6AtKIh/Zmv4sWVqxkvMsBWtQ==} engines: {node: '>= 14'} dependencies: - '@intlify/shared': 9.3.0-beta.6 + '@intlify/shared': 9.3.0-beta.11 source-map: 0.6.1 dev: true @@ -824,34 +695,39 @@ packages: resolution: {integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==} engines: {node: '>= 14'} - /@intlify/shared/9.3.0-beta.6: - resolution: {integrity: sha512-ITA1R4tvJYwZXT5x6QCSwxcwQ4dU52zrzVm/EUbgsp8oWzYS1xexBrxyNM80PSQudYvL2rvcZJKQ7yBh7b0LkQ==} + /@intlify/shared/9.3.0-beta.11: + resolution: {integrity: sha512-CtbotesxTRiC3bRyXyv1NG39fkqJ790f8z8xFaeIXSZpOdiyxoh5BIyypCzSFQZDGLwz0Q9gyWbW1XpxQJm68Q==} engines: {node: '>= 14'} dev: true - /@intlify/vite-plugin-vue-i18n/6.0.3_vite@3.2.3+vue-i18n@9.2.2: - resolution: {integrity: sha512-6SgNzPAOCR90wvt368lKzi7f/5ZEWJn22UCGvhFsP3XvKqlF3cVzojahgQ6o+LTdCkExeM6wPgd+haFf28E9VQ==} - engines: {node: '>= 14.6'} + /@intlify/unplugin-vue-i18n/0.8.1_vue-i18n@9.2.2: + resolution: {integrity: sha512-BhigujPmP6JL1FSxmpogCaL+REozncHCVkJuUnefz4GWBu3X+pRe5O7PeJn8/g+Iml2ieQJz4ISPMmEbuGQjqQ==} + engines: {node: '>= 14.16'} peerDependencies: petite-vue-i18n: '*' - vite: ^2.9.0 || ^3.0.0 vue-i18n: '*' + vue-i18n-bridge: '*' peerDependenciesMeta: petite-vue-i18n: optional: true - vite: - optional: true vue-i18n: optional: true + vue-i18n-bridge: + optional: true dependencies: - '@intlify/bundle-utils': 3.2.1_vue-i18n@9.2.2 - '@intlify/shared': 9.3.0-beta.6 + '@intlify/bundle-utils': 3.4.0_vue-i18n@9.2.2 + '@intlify/shared': 9.3.0-beta.11 '@rollup/pluginutils': 4.2.1 + '@vue/compiler-sfc': 3.2.45 debug: 4.3.4 fast-glob: 3.2.12 + js-yaml: 4.1.0 + json5: 2.2.1 + pathe: 1.0.0 + picocolors: 1.0.0 source-map: 0.6.1 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - vue-i18n: 9.2.2_vue@3.2.44 + unplugin: 1.0.1 + vue-i18n: 9.2.2_vue@3.2.45 transitivePeerDependencies: - supports-color dev: true @@ -863,56 +739,27 @@ packages: '@intlify/core-base': 9.2.2 '@intlify/shared': 9.2.2 - /@jridgewell/gen-mapping/0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - /@jridgewell/gen-mapping/0.3.2: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} engines: {node: '>=6.0.0'} dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.16 - dev: true - - /@jridgewell/resolve-uri/3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array/1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} + '@jridgewell/set-array': registry.npmmirror.com/@jridgewell/set-array/1.1.2 + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 + '@jridgewell/trace-mapping': registry.npmmirror.com/@jridgewell/trace-mapping/0.3.17 dev: true /@jridgewell/source-map/0.3.2: resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} dependencies: '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.16 + '@jridgewell/trace-mapping': 0.3.17 dev: true - /@jridgewell/sourcemap-codec/1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true - - /@jridgewell/trace-mapping/0.3.16: - resolution: {integrity: sha512-LCQ+NeThyJ4k1W2d+vIKdxuSt9R3pQSZ4P92m7EakaYuXcVWbHuT5bjNcqLd4Rdgi6xYWYDvBJZJLZSLanjDcA==} + /@jridgewell/trace-mapping/0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jridgewell/trace-mapping/0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/resolve-uri': registry.npmmirror.com/@jridgewell/resolve-uri/3.1.0 + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 dev: true /@nodelib/fs.scandir/2.1.5: @@ -936,23 +783,10 @@ packages: fastq: 1.13.0 dev: true - /@purge-icons/core/0.9.1: - resolution: {integrity: sha512-sx8/a30MbbqQVEqhuMPE1wJpdVRRbEmwEPZpFzVkcDixzX4p+R2A0WVxqkb0xfHUBAVQwrSE2SeAyniIQLqbLw==} - dependencies: - '@iconify/iconify': 2.1.2 - axios: 0.26.1_debug@4.3.4 - debug: 4.3.4 - fast-glob: 3.2.12 - fs-extra: 10.1.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - /@purge-icons/generated/0.9.0: resolution: {integrity: sha512-s2t+1oVtGDV6KtqfCXtUOhxfeYvOdDF90IVm+nMs/6bUP0HeGZLslguuL/AibpwtfL4FA/oCsIu/RhwapgAdJw==} dependencies: - '@iconify/iconify': 3.0.0 + '@iconify/iconify': 3.0.1 dev: true /@rollup/pluginutils/4.2.1: @@ -992,8 +826,8 @@ packages: resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} dev: true - /@types/eslint/8.4.6: - resolution: {integrity: sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==} + /@types/eslint/8.4.10: + resolution: {integrity: sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==} dependencies: '@types/estree': 1.0.0 '@types/json-schema': 7.0.11 @@ -1007,16 +841,6 @@ packages: resolution: {integrity: sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q==} dev: false - /@types/fined/1.1.3: - resolution: {integrity: sha512-CWYnSRnun3CGbt6taXeVo2lCbuaj4mchVJ4UF/BdU5TSuIn3AmS13pGMwCsBUoehGbhZrBrpNJZSZI5EVilXww==} - dev: true - - /@types/inquirer/8.2.4: - resolution: {integrity: sha512-Pxxx3i3AyK7vKAj3LRM/vF7ETcHKiLJ/u5CnNgbz/eYj/vB3xGAYtRxI5IKtq0hpe5iFHD22BKV3n6WHUu0k4Q==} - dependencies: - '@types/through': 0.0.30 - dev: true - /@types/intro.js/5.1.0: resolution: {integrity: sha512-XHkD6t7f3bn8B2//kOlznRzmk15KvsRkFpY6i8em/eDphblQ8QHbCiW+6OPjX7CxI0aVNVJK6Yamb2h2KMmFdA==} dev: true @@ -1025,31 +849,28 @@ packages: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true - /@types/liftoff/4.0.0: - resolution: {integrity: sha512-Ny/PJkO6nxWAQnaet8q/oWz15lrfwvdvBpuY4treB0CSsBO1CG0fVuNLngR3m3bepQLd+E4c3Y3DlC2okpUvPw==} - dependencies: - '@types/fined': 1.1.3 - '@types/node': 18.11.9 - dev: true - /@types/lodash-es/4.17.6: resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} dependencies: - '@types/lodash': 4.14.186 + '@types/lodash': 4.14.189 - /@types/lodash/4.14.186: - resolution: {integrity: sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw==} + /@types/lodash/4.14.189: + resolution: {integrity: sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==} /@types/minimist/1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/node/14.18.31: - resolution: {integrity: sha512-vQAnaReSQkEDa8uwAyQby8bYGKu84R/deEc6mg5T8fX6gzCn8QW6rziSgsti1fNvsrswKUKPnVTi7uoB+u62Mw==} + /@types/node/10.17.60: + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} dev: true - /@types/node/18.11.9: - resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} + /@types/node/14.18.33: + resolution: {integrity: sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==} + dev: true + + /@types/node/18.11.17: + resolution: {integrity: sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==} dev: true /@types/normalize-package-data/2.4.1: @@ -1067,34 +888,29 @@ packages: /@types/qrcode/1.5.0: resolution: {integrity: sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.11.17 dev: true /@types/qs/6.9.7: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} dev: true - /@types/semver/7.3.12: - resolution: {integrity: sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==} + /@types/semver/7.3.13: + resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} dev: true /@types/svgo/2.6.4: resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} dependencies: - '@types/node': 18.11.9 - dev: true - - /@types/through/0.0.30: - resolution: {integrity: sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==} - dependencies: - '@types/node': 18.11.9 + '@types/node': 18.11.17 dev: true /@types/web-bluetooth/0.0.16: resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + dev: false - /@typescript-eslint/eslint-plugin/5.42.1_2udltptbznfmezdozpdoa2aemq: - resolution: {integrity: sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==} + /@typescript-eslint/eslint-plugin/5.47.0_ncmi6noazr3nzas7jxykisekym: + resolution: {integrity: sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -1104,24 +920,24 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.42.1_rmayb2veg2btbq6mbmnyivgasy - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/type-utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy - '@typescript-eslint/utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy + '@typescript-eslint/parser': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa + '@typescript-eslint/scope-manager': 5.47.0 + '@typescript-eslint/type-utils': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa + '@typescript-eslint/utils': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa debug: 4.3.4 - eslint: 8.27.0 - ignore: 5.2.0 + eslint: 8.30.0 + ignore: 5.2.1 natural-compare-lite: 1.4.0 regexpp: 3.2.0 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.8.4 - typescript: 4.8.4 + tsutils: 3.21.0_typescript@4.9.4 + typescript: 4.9.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/5.42.1_rmayb2veg2btbq6mbmnyivgasy: - resolution: {integrity: sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==} + /@typescript-eslint/parser/5.47.0_lzzuuodtsqwxnvqeq4g4likcqa: + resolution: {integrity: sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1130,26 +946,26 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4 + '@typescript-eslint/scope-manager': 5.47.0 + '@typescript-eslint/types': 5.47.0 + '@typescript-eslint/typescript-estree': 5.47.0_typescript@4.9.4 debug: 4.3.4 - eslint: 8.27.0 - typescript: 4.8.4 + eslint: 8.30.0 + typescript: 4.9.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/5.42.1: - resolution: {integrity: sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==} + /@typescript-eslint/scope-manager/5.47.0: + resolution: {integrity: sha512-dvJab4bFf7JVvjPuh3sfBUWsiD73aiftKBpWSfi3sUkysDQ4W8x+ZcFpNp7Kgv0weldhpmMOZBjx1wKN8uWvAw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/visitor-keys': 5.42.1 + '@typescript-eslint/types': 5.47.0 + '@typescript-eslint/visitor-keys': 5.47.0 dev: true - /@typescript-eslint/type-utils/5.42.1_rmayb2veg2btbq6mbmnyivgasy: - resolution: {integrity: sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==} + /@typescript-eslint/type-utils/5.47.0_lzzuuodtsqwxnvqeq4g4likcqa: + resolution: {integrity: sha512-1J+DFFrYoDUXQE1b7QjrNGARZE6uVhBqIvdaXTe5IN+NmEyD68qXR1qX1g2u4voA+nCaelQyG8w30SAOihhEYg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -1158,23 +974,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4 - '@typescript-eslint/utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy + '@typescript-eslint/typescript-estree': 5.47.0_typescript@4.9.4 + '@typescript-eslint/utils': 5.47.0_lzzuuodtsqwxnvqeq4g4likcqa debug: 4.3.4 - eslint: 8.27.0 - tsutils: 3.21.0_typescript@4.8.4 - typescript: 4.8.4 + eslint: 8.30.0 + tsutils: 3.21.0_typescript@4.9.4 + typescript: 4.9.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types/5.42.1: - resolution: {integrity: sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==} + /@typescript-eslint/types/5.47.0: + resolution: {integrity: sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree/5.42.1_typescript@4.8.4: - resolution: {integrity: sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==} + /@typescript-eslint/typescript-estree/5.47.0_typescript@4.9.4: + resolution: {integrity: sha512-LxfKCG4bsRGq60Sqqu+34QT5qT2TEAHvSCCJ321uBWywgE2dS0LKcu5u+3sMGo+Vy9UmLOhdTw5JHzePV/1y4Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -1182,43 +998,43 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/visitor-keys': 5.42.1 + '@typescript-eslint/types': 5.47.0 + '@typescript-eslint/visitor-keys': 5.47.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.8.4 - typescript: 4.8.4 + tsutils: 3.21.0_typescript@4.9.4 + typescript: 4.9.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils/5.42.1_rmayb2veg2btbq6mbmnyivgasy: - resolution: {integrity: sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==} + /@typescript-eslint/utils/5.47.0_lzzuuodtsqwxnvqeq4g4likcqa: + resolution: {integrity: sha512-U9xcc0N7xINrCdGVPwABjbAKqx4GK67xuMV87toI+HUqgXj26m6RBp9UshEXcTrgCkdGYFzgKLt8kxu49RilDw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.11 - '@types/semver': 7.3.12 - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4 - eslint: 8.27.0 + '@types/semver': 7.3.13 + '@typescript-eslint/scope-manager': 5.47.0 + '@typescript-eslint/types': 5.47.0 + '@typescript-eslint/typescript-estree': 5.47.0_typescript@4.9.4 + eslint: 8.30.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint-utils: 3.0.0_eslint@8.30.0 semver: 7.3.8 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys/5.42.1: - resolution: {integrity: sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==} + /@typescript-eslint/visitor-keys/5.47.0: + resolution: {integrity: sha512-ByPi5iMa6QqDXe/GmT/hR6MZtVPi0SqMQPDx15FczCBXJo/7M8T88xReOALAfpBLm+zxpPfmhuEvPb577JRAEg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.42.1 + '@typescript-eslint/types': 5.47.0 eslint-visitor-keys: 3.3.0 dev: true @@ -1238,8 +1054,8 @@ packages: lodash.throttle: 4.1.1 mime-match: 1.0.2 namespace-emitter: 2.0.1 - nanoid: 3.3.4 - preact: 10.11.1 + nanoid: registry.npmmirror.com/nanoid/3.3.4 + preact: 10.11.3 dev: false /@uppy/store-default/2.1.1: @@ -1260,454 +1076,153 @@ packages: '@uppy/companion-client': 2.2.2 '@uppy/core': 2.3.4 '@uppy/utils': 4.1.3 - nanoid: 3.3.4 + nanoid: registry.npmmirror.com/nanoid/3.3.4 dev: false - /@vitejs/plugin-vue-jsx/2.1.1_vite@3.2.3+vue@3.2.44: - resolution: {integrity: sha512-JgDhxstQlwnHBvZ1BSnU5mbmyQ14/t5JhREc6YH5kWyu2QdAAOsLF6xgHoIWarj8tddaiwFrNzLbWJPudpXKYA==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^3.0.0 - vue: ^3.0.0 + /@volar/language-core/1.0.16: + resolution: {integrity: sha512-IGnOxWTs4DZ81TDcmxBAkCBxs97hUblwcjpBsTx/pOGGaSSDQRJPn0wL8NYTybEObU0i7lhEpKZ+0vJfdIy1Kg==} dependencies: - '@babel/core': 7.19.6 - '@babel/plugin-transform-typescript': 7.20.2_@babel+core@7.19.6 - '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.19.6 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - vue: 3.2.44 - transitivePeerDependencies: - - supports-color - dev: true - - /@vitejs/plugin-vue/3.2.0_vite@3.2.3+vue@3.2.44: - resolution: {integrity: sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^3.0.0 - vue: ^3.2.25 - dependencies: - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - vue: 3.2.44 - dev: true - - /@volar/language-core/1.0.9: - resolution: {integrity: sha512-5Fty3slLet6svXiJw2YxhYeo6c7wFdtILrql5bZymYLM+HbiZtJbryW1YnUEKAP7MO9Mbeh+TNH4Z0HFxHgIqw==} - dependencies: - '@volar/source-map': 1.0.9 - '@vue/reactivity': 3.2.41 + '@volar/source-map': 1.0.16 + '@vue/reactivity': 3.2.45 muggle-string: 0.1.0 dev: true - /@volar/source-map/1.0.9: - resolution: {integrity: sha512-fazB/vy5ZEJ3yKx4fabJyGNI3CBkdLkfEIRVu6+1P3VixK0Mn+eqyUIkLBrzGYaeFM3GybhCLCvsVdNz0Fu/CQ==} + /@volar/source-map/1.0.16: + resolution: {integrity: sha512-PKjzmQcg8QOGC/1V9tmGh2jcy6bKLhkW5bGidElSr83iDbCzLvldt2/La/QlDxaRCHYLT0MeyuGJBZIChB1dYQ==} dependencies: muggle-string: 0.1.0 dev: true - /@volar/typescript/1.0.9: - resolution: {integrity: sha512-dVziu+ShQUWuMukM6bvK2v2O446/gG6l1XkTh2vfkccw1IzjfbiP1TWQoNo1ipTfZOtu5YJGYAx+o5HNrGXWfQ==} + /@volar/typescript/1.0.16: + resolution: {integrity: sha512-Yov+n4oO3iYnuMt9QJAFpJabfTRCzc7KvjlAwBaSuZy+Gc/f9611MgtqAh5/SIGmltFN8dXn1Ijno8ro8I4lyw==} dependencies: - '@volar/language-core': 1.0.9 + '@volar/language-core': 1.0.16 dev: true - /@volar/vue-language-core/1.0.9: - resolution: {integrity: sha512-tofNoR8ShPFenHT1YVMuvoXtXWwoQE+fiXVqSmW0dSKZqEDjWQ3YeXSd0a6aqyKaIbvR7kWWGp34WbpQlwf9Ww==} + /@volar/vue-language-core/1.0.16: + resolution: {integrity: sha512-sQ/aW1Vuiyy4OQuh2lthyYicruM3qh9VSk/aDh8/bFvM8GoohHZqVpMN3LYldEJ9eT/rN6u4xmYP54vc/EjX4Q==} dependencies: - '@volar/language-core': 1.0.9 - '@volar/source-map': 1.0.9 - '@vue/compiler-dom': 3.2.41 - '@vue/compiler-sfc': 3.2.41 - '@vue/reactivity': 3.2.41 - '@vue/shared': 3.2.41 - minimatch: 5.1.0 - vue-template-compiler: 2.7.10 + '@volar/language-core': 1.0.16 + '@volar/source-map': 1.0.16 + '@vue/compiler-dom': 3.2.45 + '@vue/compiler-sfc': 3.2.45 + '@vue/reactivity': 3.2.45 + '@vue/shared': 3.2.45 + minimatch: 5.1.2 + vue-template-compiler: 2.7.14 dev: true - /@volar/vue-typescript/1.0.9: - resolution: {integrity: sha512-ZLe4y9YNbviACa7uAMCilzxA76gbbSlKfjspXBzk6fCobd8QCIig+VyDYcjANIlm2HhgSCX8jYTzhCKlegh4mw==} + /@volar/vue-typescript/1.0.16: + resolution: {integrity: sha512-M018Ulg/o2FVktAdlr5b/z4K69bYzekxNUA1o39y5Ur6CObc/o+5eDCCS7gIYijWnx9iNKkSQpWWWblJFv7kHQ==} dependencies: - '@volar/typescript': 1.0.9 - '@volar/vue-language-core': 1.0.9 + '@volar/typescript': 1.0.16 + '@volar/vue-language-core': 1.0.16 dev: true - /@vue-macros/api/0.1.2: - resolution: {integrity: sha512-NuhWgOmxwmdHtGVhucLaRSJPymmr8Phabw2PuV8mLp7pRmjibp+99+RWF6IwXCNqVnEDYt3MwcEzTvPSzRcqjA==} - engines: {node: '>=14.19.0'} + /@vue/compiler-core/3.2.45: + resolution: {integrity: sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==} dependencies: - '@babel/types': 7.20.0 - '@vue-macros/common': 0.13.3 - dev: true - - /@vue-macros/better-define/0.1.0: - resolution: {integrity: sha512-ujuB6G/1+/2Y789CGZegyyRzGoW8bTWzGUXgpNPiIF9H+o3r+1/Ksd1wYC9J08jZrtaXh9q4a6m6b0otbABQ8g==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/api': 0.1.2 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - dev: true - - /@vue-macros/common/0.13.3: - resolution: {integrity: sha512-pV9UFwGZs7ddbAmJI5PZvNA2ZlNESQD81jOJM1wmwLnta66K8m0RQuJK2X/tdy7Avpm/p62M8opwbWyfXsBk4w==} - engines: {node: '>=14.19.0'} - dependencies: - '@babel/types': 7.20.0 - '@vue/compiler-sfc': 3.2.42 - magic-string: 0.26.7 - dev: true - - /@vue-macros/define-model/0.13.8_@vueuse+core@9.5.0: - resolution: {integrity: sha512-B/cV6n8wRRxwY4GLNo2q/YUzwYDR3Kbt2cI7Bxb51VRCxZexRqOazn5ZB8I9LdBwBLEenOX/3gRrHW3FApkRww==} - engines: {node: '>=14.19.0'} - peerDependencies: - '@vueuse/core': ^9.0.0 - peerDependenciesMeta: - '@vueuse/core': - optional: true - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - '@vueuse/core': 9.5.0_vue@3.2.44 - ast-walker-scope: 0.3.0 - unplugin: 0.10.2 - dev: true - - /@vue-macros/define-props/0.0.2_vue@3.2.44: - resolution: {integrity: sha512-OfqC+xlN+0/koBPr4HbCJUsRbPhyOqJR2TJdeb0efTewyEljxskqh3ZCGzE4RusX+yzqTrzePlxWTcb1akNr8Q==} - engines: {node: '>=14.19.0'} - peerDependencies: - vue: ^3.2.25 - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - vue: 3.2.44 - dev: true - - /@vue-macros/define-render/0.13.8_vue@3.2.44: - resolution: {integrity: sha512-a1FIGgTuvLN5gfbh7/dtYLSaXPBYLu33l2sc0auc55uNXqB6qXGzxu/12bEskONhYcx1BBwsqjWiSFbSJ3yLbg==} - engines: {node: '>=14.19.0'} - peerDependencies: - vue: ^2.7.0 || ^3.0.0 - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - vue: 3.2.44 - dev: true - - /@vue-macros/define-slots/0.0.5_vue@3.2.44: - resolution: {integrity: sha512-+CS2MTH1fBeHbiZzThn6aXmrcbPRiuG29yWI6ugMarpIxwvVWXrPcvrWSE2BK/FSwcCR9Xfz7rETIo+BSjdo6A==} - engines: {node: '>=14.19.0'} - peerDependencies: - vue: ^2.7.0 || ^3.0.0 - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - vue: 3.2.44 - dev: true - - /@vue-macros/hoist-static/0.12.7: - resolution: {integrity: sha512-YRQ1zcy/sH13dgURk4PtazrLzMMnRDwg2N5xyeozaUWNczJmC65OWA5W9wK60WcxHu4pHRR/p7x+jive/bui9w==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - dev: true - - /@vue-macros/named-template/0.0.5_vkxhlib7tgibcivdhj2bfsgnbi: - resolution: {integrity: sha512-bZRUljNyvOOqeE9dyqXvKPQCLUCcPt1EkThmXqSbxagV29ohyviF8+CCs/8OdmNygLTBIChjP8DexQ3nUIFzUg==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vitejs/plugin-vue': 3.2.0_vite@3.2.3+vue@3.2.44 - '@vue-macros/common': 0.13.3 - '@vue/compiler-dom': 3.2.41 - unplugin: 0.10.2 - unplugin-combine: 0.2.8_rollup@3.2.5+vite@3.2.3 - transitivePeerDependencies: - - esbuild - - rollup - - vite - - vue - - webpack - dev: true - - /@vue-macros/setup-component/0.12.7_rollup@3.2.5+vite@3.2.3: - resolution: {integrity: sha512-L0WkJgw0QDwZh4tOjjKIDR0DMIybiOunsaxVqkJjicTb2YaiRUSLq4Wadl8Ttrsd0IEfI51CSlg7Sx0/dKLrlQ==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - unplugin-combine: 0.2.8_rollup@3.2.5+vite@3.2.3 - transitivePeerDependencies: - - esbuild - - rollup - - vite - - webpack - dev: true - - /@vue-macros/setup-sfc/0.12.7: - resolution: {integrity: sha512-2RyeAEanl2MLeIoyfBKWSpJgXHjAazubF02hO7nbDCf2FgKqWB0Vu8NwyMZaQPNCWJuE4azLEodg8XBMJxyUKg==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - dev: true - - /@vue-macros/short-emits/0.12.8: - resolution: {integrity: sha512-av/dqgPtU4EomWHHJPbGeuoYavCX2QTE0cd7Ka0dSuXuGgMhTN7feOv+sqsN8003yfOaPSBt6R+N/fy+T99GMA==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - unplugin: 0.10.2 - dev: true - - /@vue/babel-helper-vue-transform-on/1.0.2: - resolution: {integrity: sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==} - dev: true - - /@vue/babel-plugin-jsx/1.1.1_@babel+core@7.19.6: - resolution: {integrity: sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==} - dependencies: - '@babel/helper-module-imports': 7.18.6 - '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.19.6 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.0 - '@babel/types': 7.20.0 - '@vue/babel-helper-vue-transform-on': 1.0.2 - camelcase: 6.3.0 - html-tags: 3.2.0 - svg-tags: 1.0.0 - transitivePeerDependencies: - - '@babel/core' - - supports-color - dev: true - - /@vue/compiler-core/3.2.41: - resolution: {integrity: sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==} - dependencies: - '@babel/parser': 7.19.3 - '@vue/shared': 3.2.41 - estree-walker: 2.0.2 - source-map: 0.6.1 - dev: true - - /@vue/compiler-core/3.2.42: - resolution: {integrity: sha512-qKpDdoGaKq53T1+U4R7pk62QeDe8Kc6RN1xSd7tGi4DK3mGrqT32gyOL542wpt73Ftza0AvWmVCchmKtTpwxDg==} - dependencies: - '@babel/parser': 7.20.0 - '@vue/shared': 3.2.42 - estree-walker: 2.0.2 - source-map: 0.6.1 - dev: true - - /@vue/compiler-core/3.2.44: - resolution: {integrity: sha512-TwzeVSnaklb8wIvMtwtkPkt9wnU+XD70xJ7N9+eIHtjKAG7OoZttm+14ZL6vWOL+2RcMtSZ+cYH+gvkUqsrmSQ==} - dependencies: - '@babel/parser': 7.20.0 - '@vue/shared': 3.2.44 - estree-walker: 2.0.2 + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 + estree-walker: registry.npmmirror.com/estree-walker/2.0.2 source-map: 0.6.1 - /@vue/compiler-dom/3.2.41: - resolution: {integrity: sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==} + /@vue/compiler-dom/3.2.45: + resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==} dependencies: - '@vue/compiler-core': 3.2.41 - '@vue/shared': 3.2.41 - dev: true + '@vue/compiler-core': 3.2.45 + '@vue/shared': 3.2.45 - /@vue/compiler-dom/3.2.42: - resolution: {integrity: sha512-QVrAVX9zzvLltyQy1uxxgOmsKLStFalw0f/8HEdWIR95YjJsNo3S3SwBJDR2cnjwcVGftXBLksf1ikMyAl8bUw==} + /@vue/compiler-sfc/3.2.45: + resolution: {integrity: sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==} dependencies: - '@vue/compiler-core': 3.2.42 - '@vue/shared': 3.2.42 - dev: true - - /@vue/compiler-dom/3.2.44: - resolution: {integrity: sha512-wPDR+gOn2Qi7SudPJ+gE62vuO/aKXIiIFALvHpztXmDdbAHGy3CDfmBgOGchTgTlSeDJHe9olEMkgOdmyXTjUg==} - dependencies: - '@vue/compiler-core': 3.2.44 - '@vue/shared': 3.2.44 - - /@vue/compiler-sfc/3.2.41: - resolution: {integrity: sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==} - dependencies: - '@babel/parser': 7.19.3 - '@vue/compiler-core': 3.2.41 - '@vue/compiler-dom': 3.2.41 - '@vue/compiler-ssr': 3.2.41 - '@vue/reactivity-transform': 3.2.41 - '@vue/shared': 3.2.41 + '@babel/parser': 7.20.3 + '@vue/compiler-core': 3.2.45 + '@vue/compiler-dom': 3.2.45 + '@vue/compiler-ssr': 3.2.45 + '@vue/reactivity-transform': 3.2.45 + '@vue/shared': 3.2.45 estree-walker: 2.0.2 - magic-string: 0.25.9 - postcss: 8.4.18 - source-map: 0.6.1 - dev: true - - /@vue/compiler-sfc/3.2.42: - resolution: {integrity: sha512-lWiyxMfQ3SXGhFszSpKuPT5JcSM1ypAbLJOpHpCqvbSaJE+FAZYMbFzAC/y4MC3jSbNQ0moWncOS1gO4aXMbNQ==} - dependencies: - '@babel/parser': 7.20.0 - '@vue/compiler-core': 3.2.42 - '@vue/compiler-dom': 3.2.42 - '@vue/compiler-ssr': 3.2.42 - '@vue/reactivity-transform': 3.2.42 - '@vue/shared': 3.2.42 - estree-walker: 2.0.2 - magic-string: 0.25.9 - postcss: 8.4.18 - source-map: 0.6.1 - dev: true - - /@vue/compiler-sfc/3.2.44: - resolution: {integrity: sha512-8cFZcUWlrtnfM/GlRwYJdlfgbEOy0OZ/osLDU3h/wJu24HuYAc7QIML1USaKqiZzkjOaTd4y8mvYvcWXq3o5dA==} - dependencies: - '@babel/parser': 7.20.0 - '@vue/compiler-core': 3.2.44 - '@vue/compiler-dom': 3.2.44 - '@vue/compiler-ssr': 3.2.44 - '@vue/reactivity-transform': 3.2.44 - '@vue/shared': 3.2.44 - estree-walker: 2.0.2 - magic-string: 0.25.9 - postcss: 8.4.18 + magic-string: registry.npmmirror.com/magic-string/0.25.9 + postcss: registry.npmmirror.com/postcss/8.4.20 source-map: 0.6.1 - /@vue/compiler-ssr/3.2.41: - resolution: {integrity: sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==} + /@vue/compiler-ssr/3.2.45: + resolution: {integrity: sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==} dependencies: - '@vue/compiler-dom': 3.2.41 - '@vue/shared': 3.2.41 - dev: true - - /@vue/compiler-ssr/3.2.42: - resolution: {integrity: sha512-2Q0IclcvsX1A8N8/M7Ub32gitdnKdsjRHdj6R3Z/HGW34CXGsb4tHzjthOuT5fiyPG+CzyyAn4HiqCN8oI4iqg==} - dependencies: - '@vue/compiler-dom': 3.2.42 - '@vue/shared': 3.2.42 - dev: true - - /@vue/compiler-ssr/3.2.44: - resolution: {integrity: sha512-tAkUFLgvxds3l5KPyAH77OIYrEeLngNYQfWA9GocHiy2nlyajjqAH/Jq93Bq29Y20GeJzblmRp9DVYCVkJ5Rsw==} - dependencies: - '@vue/compiler-dom': 3.2.44 - '@vue/shared': 3.2.44 - - /@vue/devtools-api/6.4.3: - resolution: {integrity: sha512-9WCRwdROJvWcHAdyrR7SZMM/qUvllDZnpndHXokThkUsjnJ2xe4/pvsH9FZrxFe22L+JmDKczL79HjLJ7DK9rg==} - - /@vue/devtools-api/6.4.4: - resolution: {integrity: sha512-Ku31WzpOV/8cruFaXaEZKF81WkNnvCSlBY4eOGtz5WMSdJvX1v1WWlSMGZeqUwPtQ27ZZz7B62erEMq8JDjcXw==} - dev: false + '@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom/3.2.45 + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 /@vue/devtools-api/6.4.5: resolution: {integrity: sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==} - dev: false - /@vue/reactivity-transform/3.2.41: - resolution: {integrity: sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==} + /@vue/reactivity-transform/3.2.45: + resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==} dependencies: - '@babel/parser': 7.19.3 - '@vue/compiler-core': 3.2.41 - '@vue/shared': 3.2.41 - estree-walker: 2.0.2 - magic-string: 0.25.9 + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core/3.2.45 + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 + estree-walker: registry.npmmirror.com/estree-walker/2.0.2 + magic-string: registry.npmmirror.com/magic-string/0.25.9 + + /@vue/reactivity/3.2.45: + resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==} + dependencies: + '@vue/shared': 3.2.45 dev: true - /@vue/reactivity-transform/3.2.42: - resolution: {integrity: sha512-u5Qp09PCGa0yJqfbHbJXDfm9BrNx5xYtHIl5CuWbnUtBAxr8vKRjMZmFpa4CmSufixWcbwvKvSD9weamEVbfeA==} + /@vue/runtime-core/3.2.45: + resolution: {integrity: sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==} dependencies: - '@babel/parser': 7.20.0 - '@vue/compiler-core': 3.2.42 - '@vue/shared': 3.2.42 - estree-walker: 2.0.2 - magic-string: 0.25.9 - dev: true + '@vue/reactivity': registry.npmmirror.com/@vue/reactivity/3.2.45 + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 - /@vue/reactivity-transform/3.2.44: - resolution: {integrity: sha512-WGbEiXaS2qAOTS9Z3kKk2Nk4bi8OUl73Sih+h0XV9RTUATnaJSEQedveHUDQnHyXiZwyBMKosrxJg8aThHO/rw==} + /@vue/runtime-dom/3.2.45: + resolution: {integrity: sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==} dependencies: - '@babel/parser': 7.20.0 - '@vue/compiler-core': 3.2.44 - '@vue/shared': 3.2.44 - estree-walker: 2.0.2 - magic-string: 0.25.9 - - /@vue/reactivity/3.2.41: - resolution: {integrity: sha512-9JvCnlj8uc5xRiQGZ28MKGjuCoPhhTwcoAdv3o31+cfGgonwdPNuvqAXLhlzu4zwqavFEG5tvaoINQEfxz+l6g==} - dependencies: - '@vue/shared': 3.2.41 - dev: true - - /@vue/reactivity/3.2.44: - resolution: {integrity: sha512-Fe0s52fTsPl+RSdvoqUZ3HRKlaVsKhIh1mea5EWOedFvZCjnymzlj3YC1wZMxi89qXRFSdEASVA/BWUGypk0Ig==} - dependencies: - '@vue/shared': 3.2.44 - - /@vue/runtime-core/3.2.44: - resolution: {integrity: sha512-uwEV1cttL33k2dC+CNGYhKEYqGejT9KmgQ+4n/LmYUfZ1Gorl8F32DlIX+1pANyGHL1tBAisqHDxKyQBp2oBNA==} - dependencies: - '@vue/reactivity': 3.2.44 - '@vue/shared': 3.2.44 - - /@vue/runtime-dom/3.2.44: - resolution: {integrity: sha512-LDzNwXpU/nSpxrLk5jS0bfStgt88msgsgFzj6vHrl7es3QktIrCGybQS5CB/p/TO0q98iAiYtEVmi+Lej7Vgjg==} - dependencies: - '@vue/runtime-core': 3.2.44 - '@vue/shared': 3.2.44 + '@vue/runtime-core': 3.2.45 + '@vue/shared': 3.2.45 csstype: 2.6.21 - /@vue/server-renderer/3.2.44_vue@3.2.44: - resolution: {integrity: sha512-3+ArN07UgOAdbGKIp3uVqeC3bnR3J324QNjPR6vxHbLrTlkibFv8QNled/ux3fVq0KDCkVVKGOKB2V4sCIYOgg==} + /@vue/server-renderer/3.2.45_vue@3.2.45: + resolution: {integrity: sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==} peerDependencies: - vue: 3.2.44 + vue: 3.2.45 dependencies: - '@vue/compiler-ssr': 3.2.44 - '@vue/shared': 3.2.44 - vue: 3.2.44 + '@vue/compiler-ssr': 3.2.45 + '@vue/shared': 3.2.45 + vue: 3.2.45 - /@vue/shared/3.2.41: - resolution: {integrity: sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==} - dev: true + /@vue/shared/3.2.45: + resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==} - /@vue/shared/3.2.42: - resolution: {integrity: sha512-cheJw3tpW34LWVUL3fySuwCmF1/gFBHWZ3WjmMcBIHMcnKrS/SRapvkbYWzyw5FiM8OcpYHO5e7hWYOFCsyHmA==} - dev: true - - /@vue/shared/3.2.44: - resolution: {integrity: sha512-mGZ44bnn0zpZ36nXtxbrBPno43yr96wjQE1dBEKS1Sieugt27HS4OGZVBRIgsdGzosB7vqZAvu0ttu1FDVdolA==} - - /@vueuse/core/9.5.0_vue@3.2.44: - resolution: {integrity: sha512-6GsWBsJHEb3sYw15mbLrcbslAVY45pkzjJYTKYKCXv88z7srAF0VEW0q+oXKsl58tCbqooplInahXFg8Yo1m4w==} + /@vueuse/core/9.8.2_vue@3.2.45: + resolution: {integrity: sha512-aWiCmcYIpPt7xjuqYiceODEMHchDYthrJ4AqI+FXPZrR23PZOqdiktbUVyQl2kGlR3H4i9UJ/uimQrwhz9UouQ==} dependencies: '@types/web-bluetooth': 0.0.16 - '@vueuse/metadata': 9.5.0 - '@vueuse/shared': 9.5.0_vue@3.2.44 - vue-demi: 0.13.11_vue@3.2.44 + '@vueuse/metadata': 9.8.2 + '@vueuse/shared': 9.8.2_vue@3.2.45 + vue-demi: 0.13.11_vue@3.2.45 transitivePeerDependencies: - '@vue/composition-api' - vue + dev: false - /@vueuse/metadata/9.5.0: - resolution: {integrity: sha512-4M1AyPZmIv41pym+K5+4wup3bKuYebbH8w8BROY1hmT7rIwcyS4tEL+UsGz0Hiu1FCOxcoBrwtAizc0YmBJjyQ==} + /@vueuse/metadata/9.8.2: + resolution: {integrity: sha512-N4E/BKS+9VsUeD4WLVRU1J2kCOLh+iikBcMtipFcTyL204132vDYHs27zLAVabJYGnhC0dIVGdhg9pbOZiY2TQ==} + dev: false - /@vueuse/shared/9.5.0_vue@3.2.44: - resolution: {integrity: sha512-HnnCWU1Vg9CVWRCcI8ohDKDRB2Sc4bTgT1XAIaoLSfVHHn+TKbrox6pd3klCSw4UDxkhDfOk8cAdcK+Z5KleCA==} + /@vueuse/shared/9.8.2_vue@3.2.45: + resolution: {integrity: sha512-ACjrPQzowd5dnabNJt9EoGVobco9/ENiA5qP53vjiuxndlJYuc/UegwhXC7KdQbPX4F45a50+45K3g1wNqOzmA==} dependencies: - vue-demi: 0.13.11_vue@3.2.44 + vue-demi: 0.13.11_vue@3.2.45 transitivePeerDependencies: - '@vue/composition-api' - vue + dev: false - /@wangeditor/basic-modules/1.1.6_o6rq7lyzv5eg7j3353bh3hudbm: - resolution: {integrity: sha512-wckcFm/kEAHpTn7dTmN0+7POFoygqt9bZdNHJUkdKObXtAerml8RdjrkHRcwJFCkSELbrNK63fvkwS0+FsabfA==} + /@wangeditor/basic-modules/1.1.7_j7icpicfeimtkldwmemjnpdjs4: + resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==} peerDependencies: '@wangeditor/core': 1.x dom7: ^3.0.0 @@ -1716,7 +1231,7 @@ packages: slate: ^0.72.0 snabbdom: ^3.1.0 dependencies: - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e dom7: 3.0.0 is-url: 1.2.4 lodash.throttle: 4.1.1 @@ -1725,7 +1240,7 @@ packages: snabbdom: 3.5.1 dev: false - /@wangeditor/code-highlight/1.0.3_l7btiqc6jwjbtk5j6zx52mrhj4: + /@wangeditor/code-highlight/1.0.3_tztyh2vh7kwzpeloifaekkk3my: resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==} peerDependencies: '@wangeditor/core': 1.x @@ -1733,15 +1248,15 @@ packages: slate: ^0.72.0 snabbdom: ^3.1.0 dependencies: - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e dom7: 3.0.0 prismjs: 1.29.0 slate: 0.72.8 snabbdom: 3.5.1 dev: false - /@wangeditor/core/1.1.18_qokc4m5r26t2nkvzejrgzroa7e: - resolution: {integrity: sha512-GZsW/8tm2Hc2hZKX8BZP9PO7vTZll9YXsOt+jKck3D2bj9nk4T0FZymuE5fq9ZHdo+MwLiXBHXS/D1SIGlVnGQ==} + /@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e: + resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==} peerDependencies: '@uppy/core': ^2.1.1 '@uppy/xhr-upload': ^2.0.3 @@ -1780,28 +1295,28 @@ packages: snabbdom: 3.5.1 dev: false - /@wangeditor/editor-for-vue/5.1.12_su3dw7bmszfjg67suaojchptby: + /@wangeditor/editor-for-vue/5.1.12_3apfu3xbp6awzuex7ed3sbrv6y: resolution: {integrity: sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==} peerDependencies: '@wangeditor/editor': '>=5.1.0' vue: ^3.0.5 dependencies: - '@wangeditor/editor': 5.1.22 - vue: 3.2.44 + '@wangeditor/editor': 5.1.23 + vue: 3.2.45 dev: false - /@wangeditor/editor/5.1.22: - resolution: {integrity: sha512-Bg+NakUvg6+UvkRT/xD9a0zMhPy/4kwhiv8Hp93csa4dg2u/dlZORRTjJCWaWmVK82PrtBG3VAcuw3rPdQCfag==} + /@wangeditor/editor/5.1.23: + resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==} dependencies: '@uppy/core': 2.3.4 '@uppy/xhr-upload': 2.1.3_@uppy+core@2.3.4 - '@wangeditor/basic-modules': 1.1.6_o6rq7lyzv5eg7j3353bh3hudbm - '@wangeditor/code-highlight': 1.0.3_l7btiqc6jwjbtk5j6zx52mrhj4 - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e - '@wangeditor/list-module': 1.0.5_l7btiqc6jwjbtk5j6zx52mrhj4 - '@wangeditor/table-module': 1.1.4_lwgnfhttvljctbijfdv636yew4 - '@wangeditor/upload-image-module': 1.0.2_pknk2k7txbsal4ptocd5fojeuq - '@wangeditor/video-module': 1.1.4_i7nsf6mii7znnnswtj7jlro46u + '@wangeditor/basic-modules': 1.1.7_j7icpicfeimtkldwmemjnpdjs4 + '@wangeditor/code-highlight': 1.0.3_tztyh2vh7kwzpeloifaekkk3my + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/list-module': 1.0.5_tztyh2vh7kwzpeloifaekkk3my + '@wangeditor/table-module': 1.1.4_2dde2uzwslfxq2cqrl35sl4erm + '@wangeditor/upload-image-module': 1.0.2_dwqga4onuah5imhngzkgmw6t5a + '@wangeditor/video-module': 1.1.4_i6gxywmu7tvxmjxypclnjlcil4 dom7: 3.0.0 is-hotkey: 0.2.0 lodash.camelcase: 4.3.0 @@ -1816,7 +1331,7 @@ packages: snabbdom: 3.5.1 dev: false - /@wangeditor/list-module/1.0.5_l7btiqc6jwjbtk5j6zx52mrhj4: + /@wangeditor/list-module/1.0.5_tztyh2vh7kwzpeloifaekkk3my: resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==} peerDependencies: '@wangeditor/core': 1.x @@ -1824,13 +1339,13 @@ packages: slate: ^0.72.0 snabbdom: ^3.1.0 dependencies: - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e dom7: 3.0.0 slate: 0.72.8 snabbdom: 3.5.1 dev: false - /@wangeditor/table-module/1.1.4_lwgnfhttvljctbijfdv636yew4: + /@wangeditor/table-module/1.1.4_2dde2uzwslfxq2cqrl35sl4erm: resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==} peerDependencies: '@wangeditor/core': 1.x @@ -1841,7 +1356,7 @@ packages: slate: ^0.72.0 snabbdom: ^3.1.0 dependencies: - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e dom7: 3.0.0 lodash.isequal: 4.5.0 lodash.throttle: 4.1.1 @@ -1850,7 +1365,7 @@ packages: snabbdom: 3.5.1 dev: false - /@wangeditor/upload-image-module/1.0.2_pknk2k7txbsal4ptocd5fojeuq: + /@wangeditor/upload-image-module/1.0.2_dwqga4onuah5imhngzkgmw6t5a: resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==} peerDependencies: '@uppy/core': ^2.0.3 @@ -1864,15 +1379,15 @@ packages: dependencies: '@uppy/core': 2.3.4 '@uppy/xhr-upload': 2.1.3_@uppy+core@2.3.4 - '@wangeditor/basic-modules': 1.1.6_o6rq7lyzv5eg7j3353bh3hudbm - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/basic-modules': 1.1.7_j7icpicfeimtkldwmemjnpdjs4 + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e dom7: 3.0.0 lodash.foreach: 4.5.0 slate: 0.72.8 snabbdom: 3.5.1 dev: false - /@wangeditor/video-module/1.1.4_i7nsf6mii7znnnswtj7jlro46u: + /@wangeditor/video-module/1.1.4_i6gxywmu7tvxmjxypclnjlcil4: resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==} peerDependencies: '@uppy/core': ^2.1.4 @@ -1885,37 +1400,13 @@ packages: dependencies: '@uppy/core': 2.3.4 '@uppy/xhr-upload': 2.1.3_@uppy+core@2.3.4 - '@wangeditor/core': 1.1.18_qokc4m5r26t2nkvzejrgzroa7e + '@wangeditor/core': 1.1.19_qokc4m5r26t2nkvzejrgzroa7e dom7: 3.0.0 nanoid: 3.3.4 slate: 0.72.8 snabbdom: 3.5.1 dev: false - /@windicss/config/1.8.8: - resolution: {integrity: sha512-kNas/zMkwsDFMcJPmHoPDJlQi1MHvYwx8BSxo9JKcbCW7Gaj8Rg2CnEImX5YdT+ZcFQqQ+kUn0Vi/ScsAxhGEw==} - dependencies: - debug: 4.3.4 - jiti: 1.16.0 - windicss: 3.5.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@windicss/plugin-utils/1.8.8: - resolution: {integrity: sha512-a+npbTKmdrAvnMqzVJvyPa29xyNcPaSkt6qQpgWY9m0WyVlYd9BM8V0+cbqt279fTlvlaZpUs9dqmilB1PUH6g==} - dependencies: - '@antfu/utils': 0.5.2 - '@windicss/config': 1.8.8 - debug: 4.3.4 - fast-glob: 3.2.12 - magic-string: 0.26.7 - micromatch: 4.0.5 - windicss: 3.5.6 - transitivePeerDependencies: - - supports-color - dev: true - /@zxcvbn-ts/core/2.1.0: resolution: {integrity: sha512-doxol9xrO7LgyVJhguXe7vO0xthnIYmsOKoDwrLg0Ho2kkpQaVtM+AOQw+BkEiKIqNg1V48eUf4/cTzMElXdiA==} dev: false @@ -1936,12 +1427,12 @@ packages: acorn: 7.4.1 dev: true - /acorn-jsx/5.3.2_acorn@8.8.0: + /acorn-jsx/5.3.2_acorn@8.8.1: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.8.0 + acorn: 8.8.1 dev: true /acorn-walk/8.2.0: @@ -1955,8 +1446,8 @@ packages: hasBin: true dev: true - /acorn/8.8.0: - resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} + /acorn/8.8.1: + resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} engines: {node: '>=0.4.0'} hasBin: true dev: true @@ -1978,8 +1469,8 @@ packages: uri-js: 4.4.1 dev: true - /ajv/8.11.0: - resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + /ajv/8.11.2: + resolution: {integrity: sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==} dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -2012,31 +1503,20 @@ packages: engines: {node: '>=12'} dev: true - /ansi-styles/2.2.1: - resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} - engines: {node: '>=0.10.0'} - dev: true - - /ansi-styles/3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - /ansi-styles/4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 + dev: true - /ansi-styles/6.1.1: - resolution: {integrity: sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==} + /ansi-styles/6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} dev: true - /anymatch/3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + /anymatch/3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} dependencies: normalize-path: 3.0.0 @@ -2066,20 +1546,10 @@ packages: engines: {node: '>=0.10.0'} dev: true - /array-each/1.0.1: - resolution: {integrity: sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==} - engines: {node: '>=0.10.0'} - dev: true - /array-ify/1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} dev: true - /array-slice/1.1.0: - resolution: {integrity: sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==} - engines: {node: '>=0.10.0'} - dev: true - /array-union/2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -2100,14 +1570,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /ast-walker-scope/0.3.0: - resolution: {integrity: sha512-bsOBv3jB+1kGaxwPHhkLiagS+75KfzEqtkNWvATgMGtXM6kJZG3PlG4fYQFMiHeLpoAkwc6G61w07+hEXx39aA==} - engines: {node: '>=14.19.0'} - dependencies: - '@babel/parser': 7.20.0 - '@babel/types': 7.20.0 - dev: true - /astral-regex/2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -2131,7 +1593,7 @@ packages: hasBin: true dev: true - /autoprefixer/10.4.13_postcss@8.4.18: + /autoprefixer/10.4.13_postcss@8.4.20: resolution: {integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==} engines: {node: ^10 || ^12 || >=14} hasBin: true @@ -2139,27 +1601,20 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.21.4 - caniuse-lite: 1.0.30001427 + caniuse-lite: 1.0.30001431 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 - postcss: 8.4.18 + postcss: registry.npmmirror.com/postcss/8.4.20 postcss-value-parser: 4.2.0 dev: true - /axios/0.26.1_debug@4.3.4: - resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} - dependencies: - follow-redirects: 1.15.2 - transitivePeerDependencies: - - debug - dev: true - - /axios/0.27.2: - resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + /axios/1.2.1: + resolution: {integrity: sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==} dependencies: follow-redirects: 1.15.2 form-data: 4.0.0 + proxy-from-env: 1.1.0 transitivePeerDependencies: - debug dev: false @@ -2185,10 +1640,6 @@ packages: pascalcase: 0.1.1 dev: true - /base64-js/1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - /big.js/5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} dev: true @@ -2198,22 +1649,6 @@ packages: engines: {node: '>=8'} dev: true - /bl/4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.0 - dev: true - - /bl/5.0.0: - resolution: {integrity: sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==} - dependencies: - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 3.6.0 - dev: true - /bluebird/3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} dev: true @@ -2235,29 +1670,11 @@ packages: balanced-match: 1.0.2 dev: true - /braces/2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - dependencies: - arr-flatten: 1.1.0 - array-unique: 0.3.2 - extend-shallow: 2.0.1 - fill-range: 4.0.0 - isobject: 3.0.1 - repeat-element: 1.1.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - /braces/3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: - fill-range: 7.0.1 + fill-range: registry.npmmirror.com/fill-range/7.0.1 dev: true /browserslist/4.21.4: @@ -2265,8 +1682,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001427 - electron-to-chromium: 1.4.276 + caniuse-lite: 1.0.30001431 + electron-to-chromium: 1.4.284 node-releases: 2.0.6 update-browserslist-db: 1.0.10_browserslist@4.21.4 dev: true @@ -2275,20 +1692,6 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /buffer/5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - - /buffer/6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - /cache-base/1.0.1: resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} engines: {node: '>=0.10.0'} @@ -2307,7 +1710,7 @@ packages: /call-bind/1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: - function-bind: 1.1.1 + function-bind: registry.npmmirror.com/function-bind/1.1.1 get-intrinsic: 1.1.3 dev: false @@ -2320,36 +1723,27 @@ packages: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} dependencies: pascal-case: 3.1.2 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /camelcase-keys/6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} dependencies: - camelcase: 5.3.1 + camelcase: registry.npmmirror.com/camelcase/5.3.1 map-obj: 4.3.0 quick-lru: 4.0.1 dev: true - /camelcase/5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - /camelcase/6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-lite/1.0.30001427: - resolution: {integrity: sha512-lfXQ73oB9c8DP5Suxaszm+Ta2sr/4tf8+381GkIm1MLj/YdLf+rEDyDSRCzeltuyTVGm+/s18gdZ0q+Wmp8VsQ==} + /caniuse-lite/1.0.30001431: + resolution: {integrity: sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==} dev: true /capital-case/1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} dependencies: no-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 upper-case-first: 2.0.2 dev: true @@ -2357,20 +1751,20 @@ packages: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} dependencies: - ansi-styles: 2.2.1 + ansi-styles: registry.npmmirror.com/ansi-styles/2.2.1 escape-string-regexp: 1.0.5 has-ansi: 2.0.0 strip-ansi: 3.0.1 - supports-color: 2.0.0 + supports-color: registry.npmmirror.com/supports-color/2.0.0 dev: true /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} dependencies: - ansi-styles: 3.2.1 + ansi-styles: registry.npmmirror.com/ansi-styles/3.2.1 escape-string-regexp: 1.0.5 - supports-color: 5.5.0 + supports-color: registry.npmmirror.com/supports-color/5.5.0 dev: true /chalk/4.1.2: @@ -2381,11 +1775,6 @@ packages: supports-color: 7.2.0 dev: true - /chalk/5.1.0: - resolution: {integrity: sha512-56zD4khRTBoIyzUYAFgDDaPhUMN/fC/rySe6aZGqbj/VWiU2eI3l6ZLOtYGFZAV5v02mwPjtpzlrOveJiz5eZQ==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - /change-case/4.1.2: resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} dependencies: @@ -2400,18 +1789,14 @@ packages: path-case: 3.0.4 sentence-case: 3.0.4 snake-case: 3.0.4 - tslib: 2.4.0 - dev: true - - /chardet/0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + tslib: 2.4.1 dev: true /chokidar/3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} dependencies: - anymatch: 3.1.2 + anymatch: 3.1.3 braces: 3.0.2 glob-parent: 5.1.2 is-binary-path: 2.1.0 @@ -2432,13 +1817,6 @@ packages: static-extend: 0.1.2 dev: true - /clean-css/5.3.1: - resolution: {integrity: sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==} - engines: {node: '>= 10.0'} - dependencies: - source-map: 0.6.1 - dev: true - /clean-stack/2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -2451,18 +1829,6 @@ packages: restore-cursor: 3.1.0 dev: true - /cli-cursor/4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - restore-cursor: 4.0.0 - dev: true - - /cli-spinners/2.7.0: - resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} - engines: {node: '>=6'} - dev: true - /cli-truncate/2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} @@ -2479,11 +1845,6 @@ packages: string-width: 5.1.2 dev: true - /cli-width/3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} - dev: true - /cliui/6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: @@ -2501,11 +1862,6 @@ packages: wrap-ansi: 7.0.0 dev: true - /clone/1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - /clone/2.1.2: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} @@ -2519,25 +1875,13 @@ packages: object-visit: 1.0.1 dev: true - /color-convert/1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - /color-convert/2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} dependencies: - color-name: 1.1.4 - - /color-name/1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name: registry.npmmirror.com/color-name/1.1.4 dev: true - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - /colord/2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} dev: true @@ -2562,11 +1906,6 @@ packages: engines: {node: '>= 10'} dev: true - /commander/8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - /commander/9.4.1: resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} engines: {node: ^12.20.0 || >=14} @@ -2591,11 +1930,6 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true - /connect-history-api-fallback/1.6.0: - resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} - engines: {node: '>=0.8'} - dev: true - /consola/2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} dev: true @@ -2608,7 +1942,7 @@ packages: resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} dependencies: no-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 upper-case: 2.0.2 dev: true @@ -2642,18 +1976,6 @@ packages: through2: 4.0.2 dev: true - /convert-source-map/1.8.0: - resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /copy-anything/2.0.6: - resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} - dependencies: - is-what: 3.14.1 - dev: true - /copy-descriptor/0.1.1: resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} engines: {node: '>=0.10.0'} @@ -2667,8 +1989,8 @@ packages: vary: 1.1.2 dev: true - /cosmiconfig-typescript-loader/4.1.1_gpl3msxjb2n3qdkii2jvdrcxxe: - resolution: {integrity: sha512-9DHpa379Gp0o0Zefii35fcmuuin6q92FnLDffzdZ0l9tVd3nEobG3O+MZ06+kuBvFTSVScvNb/oHA13Nd4iipg==} + /cosmiconfig-typescript-loader/4.2.0_wb7bklcl6jlvxijczjyxggip4a: + resolution: {integrity: sha512-NkANeMnaHrlaSSlpKGyvn2R4rqUDeE/9E5YHx+b4nwo0R8dZyAqcih8/gxpCZvqWP9Vf6xuLpMSzSgdVEIM78g==} engines: {node: '>=12', npm: '>=6'} peerDependencies: '@types/node': '*' @@ -2676,14 +1998,14 @@ packages: ts-node: '>=10' typescript: '>=3' dependencies: - '@types/node': 14.18.31 - cosmiconfig: 7.0.1 - ts-node: 10.9.1_fk6arlf3j7tudlucddpzvj2plq - typescript: 4.8.4 + '@types/node': 14.18.33 + cosmiconfig: 7.1.0 + ts-node: 10.9.1_rju6pyblifsagdmqm3y74zsi6q + typescript: 4.9.4 dev: true - /cosmiconfig/7.0.1: - resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} + /cosmiconfig/7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} dependencies: '@types/parse-json': 4.0.0 @@ -2697,13 +2019,9 @@ packages: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true - /cross-fetch/3.1.5: - resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==} - dependencies: - node-fetch: 2.6.7 - transitivePeerDependencies: - - encoding - dev: true + /cropperjs/1.5.13: + resolution: {integrity: sha512-by7jKAo73y5/Do0K6sxdTKHgndY0NMjG2bEdgeJxycbcmHuCiMXqw8sxy5C5Y5WTOTcDGmbT7Sr5CgKOXR06OA==} + dev: false /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -2774,8 +2092,8 @@ packages: engines: {node: '>=8'} dev: true - /dayjs/1.11.6: - resolution: {integrity: sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ==} + /dayjs/1.11.7: + resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} dev: false /de-indent/1.0.2: @@ -2793,18 +2111,6 @@ packages: ms: 2.0.0 dev: true - /debug/3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - optional: true - /debug/4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -2817,8 +2123,8 @@ packages: ms: 2.1.2 dev: true - /decamelize-keys/1.1.0: - resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} + /decamelize-keys/1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} dependencies: decamelize: 1.2.0 @@ -2838,12 +2144,6 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true - /defaults/1.0.3: - resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} - dependencies: - clone: 1.0.4 - dev: true - /define-property/0.2.5: resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} engines: {node: '>=0.10.0'} @@ -2866,30 +2166,11 @@ packages: isobject: 3.0.1 dev: true - /del/6.1.1: - resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} - engines: {node: '>=10'} - dependencies: - globby: 11.1.0 - graceful-fs: 4.2.10 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 4.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - dev: true - /delayed-stream/1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} dev: false - /detect-file/1.0.0: - resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} - engines: {node: '>=0.10.0'} - dev: true - /diff/4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -2997,7 +2278,7 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /dot-prop/5.3.0: @@ -3007,33 +2288,16 @@ packages: is-obj: 2.0.0 dev: true - /dotenv-expand/8.0.3: - resolution: {integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==} - engines: {node: '>=12'} - dev: true - - /dotenv/16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - /eastasianwidth/0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /echarts-wordcloud/2.0.0_echarts@5.4.0: - resolution: {integrity: sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g==} + /echarts-wordcloud/2.1.0_echarts@5.4.1: + resolution: {integrity: sha512-Kt1JmbcROgb+3IMI48KZECK2AP5lG6bSsOEs+AsuwaWJxQom31RTNd6NFYI01E/YaI1PFZeueaupjlmzSQasjQ==} peerDependencies: echarts: ^5.0.1 dependencies: - echarts: 5.4.0 - dev: false - - /echarts/5.4.0: - resolution: {integrity: sha512-uPsO9VRUIKAdFOoH3B0aNg7NRVdN7aM39/OjovjO9MwmWsAkfGyeXJhK+dbRi51iDrQWliXV60/XwLA7kg3z0w==} - dependencies: - tslib: 2.3.0 - zrender: 5.4.0 + echarts: registry.npmmirror.com/echarts/5.4.1 dev: false /ejs/3.1.8: @@ -3044,31 +2308,31 @@ packages: jake: 10.8.5 dev: true - /electron-to-chromium/1.4.276: - resolution: {integrity: sha512-EpuHPqu8YhonqLBXHoU6hDJCD98FCe6KDoet3/gY1qsQ6usjJoHqBH2YIVs8FXaAtHwVL8Uqa/fsYao/vq9VWQ==} + /electron-to-chromium/1.4.284: + resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} dev: true - /element-plus/2.2.20_vue@3.2.44: - resolution: {integrity: sha512-ludShd3f5kNRY4FLzeoNitLcwZ4qs2M/zwKeyeE7rUzZJAQ0BZtcT3SvZoEoBLmgxw9jHoonl4WIwon4UzhyRA==} + /element-plus/2.2.27_vue@3.2.45: + resolution: {integrity: sha512-P04HDOZBYDdvlYuleuCZRULzAc5xJVOBfLDK9xWxVo0vyo8ntdaXS5sTU+/76vrNzuO3FhLn9kvrsbiJEVa1jg==} peerDependencies: vue: ^3.2.0 dependencies: '@ctrl/tinycolor': 3.4.1 - '@element-plus/icons-vue': 2.0.9_vue@3.2.44 - '@floating-ui/dom': 1.0.2 + '@element-plus/icons-vue': 2.0.10_vue@3.2.45 + '@floating-ui/dom': 1.0.6 '@popperjs/core': /@sxzz/popperjs-es/2.11.7 - '@types/lodash': 4.14.186 + '@types/lodash': 4.14.189 '@types/lodash-es': 4.17.6 - '@vueuse/core': 9.5.0_vue@3.2.44 + '@vueuse/core': 9.8.2_vue@3.2.45 async-validator: 4.2.5 - dayjs: 1.11.6 + dayjs: 1.11.7 escape-html: 1.0.3 lodash: 4.17.21 lodash-es: 4.17.21 - lodash-unified: 1.0.2_3ib2ivapxullxkx3xftsimdk7u + lodash-unified: 1.0.3_3ib2ivapxullxkx3xftsimdk7u memoize-one: 6.0.0 normalize-wheel-es: 1.2.0 - vue: 3.2.44 + vue: 3.2.45 transitivePeerDependencies: - '@vue/composition-api' dev: false @@ -3102,15 +2366,6 @@ packages: engines: {node: '>=0.12'} dev: true - /errno/0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} - hasBin: true - requiresBuild: true - dependencies: - prr: 1.0.1 - dev: true - optional: true - /error-ex/1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -3146,214 +2401,34 @@ packages: ext: 1.7.0 dev: false - /esbuild-android-64/0.15.10: - resolution: {integrity: sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /esbuild-android-arm64/0.15.10: - resolution: {integrity: sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /esbuild-darwin-64/0.15.10: - resolution: {integrity: sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /esbuild-darwin-arm64/0.15.10: - resolution: {integrity: sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /esbuild-freebsd-64/0.15.10: - resolution: {integrity: sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-freebsd-arm64/0.15.10: - resolution: {integrity: sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-32/0.15.10: - resolution: {integrity: sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-64/0.15.10: - resolution: {integrity: sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-arm/0.15.10: - resolution: {integrity: sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-arm64/0.15.10: - resolution: {integrity: sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-mips64le/0.15.10: - resolution: {integrity: sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-ppc64le/0.15.10: - resolution: {integrity: sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-riscv64/0.15.10: - resolution: {integrity: sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-s390x/0.15.10: - resolution: {integrity: sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-netbsd-64/0.15.10: - resolution: {integrity: sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-openbsd-64/0.15.10: - resolution: {integrity: sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-sunos-64/0.15.10: - resolution: {integrity: sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-32/0.15.10: - resolution: {integrity: sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-64/0.15.10: - resolution: {integrity: sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-arm64/0.15.10: - resolution: {integrity: sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild/0.15.10: - resolution: {integrity: sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==} + /esbuild/0.16.5: + resolution: {integrity: sha512-te0zG5CDzAxhnBKeddXUtK8xDnYL6jv100ekldhtUk0ALXPXcDAtuH0fAR7rbKwUdz3bOey6HVq2N+aWCKZ1cw==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.15.10 - '@esbuild/linux-loong64': 0.15.10 - esbuild-android-64: 0.15.10 - esbuild-android-arm64: 0.15.10 - esbuild-darwin-64: 0.15.10 - esbuild-darwin-arm64: 0.15.10 - esbuild-freebsd-64: 0.15.10 - esbuild-freebsd-arm64: 0.15.10 - esbuild-linux-32: 0.15.10 - esbuild-linux-64: 0.15.10 - esbuild-linux-arm: 0.15.10 - esbuild-linux-arm64: 0.15.10 - esbuild-linux-mips64le: 0.15.10 - esbuild-linux-ppc64le: 0.15.10 - esbuild-linux-riscv64: 0.15.10 - esbuild-linux-s390x: 0.15.10 - esbuild-netbsd-64: 0.15.10 - esbuild-openbsd-64: 0.15.10 - esbuild-sunos-64: 0.15.10 - esbuild-windows-32: 0.15.10 - esbuild-windows-64: 0.15.10 - esbuild-windows-arm64: 0.15.10 + '@esbuild/android-arm': 0.16.5 + '@esbuild/android-arm64': 0.16.5 + '@esbuild/android-x64': 0.16.5 + '@esbuild/darwin-arm64': 0.16.5 + '@esbuild/darwin-x64': 0.16.5 + '@esbuild/freebsd-arm64': 0.16.5 + '@esbuild/freebsd-x64': 0.16.5 + '@esbuild/linux-arm': 0.16.5 + '@esbuild/linux-arm64': 0.16.5 + '@esbuild/linux-ia32': 0.16.5 + '@esbuild/linux-loong64': 0.16.5 + '@esbuild/linux-mips64el': 0.16.5 + '@esbuild/linux-ppc64': 0.16.5 + '@esbuild/linux-riscv64': 0.16.5 + '@esbuild/linux-s390x': 0.16.5 + '@esbuild/linux-x64': 0.16.5 + '@esbuild/netbsd-x64': 0.16.5 + '@esbuild/openbsd-x64': 0.16.5 + '@esbuild/sunos-x64': 0.16.5 + '@esbuild/win32-arm64': 0.16.5 + '@esbuild/win32-ia32': 0.16.5 + '@esbuild/win32-x64': 0.16.5 dev: true /escalade/3.1.1: @@ -3375,13 +2450,13 @@ packages: engines: {node: '>=10'} dev: true - /eslint-config-prettier/8.5.0_eslint@8.27.0: + /eslint-config-prettier/8.5.0_eslint@8.30.0: resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.27.0 + eslint: 8.30.0 dev: true /eslint-define-config/1.12.0: @@ -3389,7 +2464,7 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13', pnpm: '>= 7.0.0'} dev: true - /eslint-plugin-prettier/4.2.1_v7o5sx5x3wbs57ifz6wc4f76we: + /eslint-plugin-prettier/4.2.1_kl4pe43v5b43npmso5hoplpbyi: resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -3400,25 +2475,25 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.27.0 - eslint-config-prettier: 8.5.0_eslint@8.27.0 - prettier: 2.7.1 + eslint: 8.30.0 + eslint-config-prettier: 8.5.0_eslint@8.30.0 + prettier: 2.8.1 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-vue/9.7.0_eslint@8.27.0: - resolution: {integrity: sha512-DrOO3WZCZEwcLsnd3ohFwqCoipGRSTKTBTnLwdhqAbYZtzWl0o7D+D8ZhlmiZvABKTEl8AFsqH1GHGdybyoQmw==} + /eslint-plugin-vue/9.8.0_eslint@8.30.0: + resolution: {integrity: sha512-E/AXwcTzunyzM83C2QqDHxepMzvI2y6x+mmeYHbVDQlKFqmKYvRrhaVixEeeG27uI44p9oKDFiyCRw4XxgtfHA==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.27.0 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint: 8.30.0 + eslint-utils: 3.0.0_eslint@8.30.0 natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.0.10 semver: 7.3.8 - vue-eslint-parser: 9.1.0_eslint@8.27.0 + vue-eslint-parser: 9.1.0_eslint@8.30.0 xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color @@ -3447,13 +2522,13 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.27.0: + /eslint-utils/3.0.0_eslint@8.30.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.27.0 + eslint: 8.30.0 eslint-visitor-keys: 2.1.0 dev: true @@ -3472,13 +2547,13 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.27.0: - resolution: {integrity: sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==} + /eslint/8.30.0: + resolution: {integrity: sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint/eslintrc': 1.3.3 - '@humanwhocodes/config-array': 0.11.6 + '@eslint/eslintrc': 1.4.0 + '@humanwhocodes/config-array': 0.11.8 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 @@ -3488,18 +2563,18 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.27.0 + eslint-utils: 3.0.0_eslint@8.30.0 eslint-visitor-keys: 3.3.0 - espree: 9.4.0 + espree: 9.4.1 esquery: 1.4.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.17.0 + globals: 13.19.0 grapheme-splitter: 1.0.4 - ignore: 5.2.0 + ignore: 5.2.1 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 @@ -3529,12 +2604,12 @@ packages: eslint-visitor-keys: 1.3.0 dev: true - /espree/9.4.0: - resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==} + /espree/9.4.1: + resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.8.0 - acorn-jsx: 5.3.2_acorn@8.8.0 + acorn: 8.8.1 + acorn-jsx: 5.3.2_acorn@8.8.1 eslint-visitor-keys: 3.3.0 dev: true @@ -3627,13 +2702,6 @@ packages: - supports-color dev: true - /expand-tilde/2.0.2: - resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} - engines: {node: '>=0.10.0'} - dependencies: - homedir-polyfill: 1.0.3 - dev: true - /ext/1.7.0: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} dependencies: @@ -3655,19 +2723,6 @@ packages: is-extendable: 1.0.1 dev: true - /extend/3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: true - - /external-editor/3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - /extglob/2.0.4: resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} engines: {node: '>=0.10.0'} @@ -3722,13 +2777,6 @@ packages: reusify: 1.0.4 dev: true - /figures/3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3742,23 +2790,6 @@ packages: minimatch: 5.1.0 dev: true - /fill-range/4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - /find-up/4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -3774,32 +2805,6 @@ packages: path-exists: 4.0.0 dev: true - /findup-sync/5.0.0: - resolution: {integrity: sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==} - engines: {node: '>= 10.13.0'} - dependencies: - detect-file: 1.0.0 - is-glob: 4.0.3 - micromatch: 4.0.5 - resolve-dir: 1.0.1 - dev: true - - /fined/2.0.0: - resolution: {integrity: sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==} - engines: {node: '>= 10.13.0'} - dependencies: - expand-tilde: 2.0.2 - is-plain-object: 5.0.0 - object.defaults: 1.1.0 - object.pick: 1.3.0 - parse-filepath: 1.0.2 - dev: true - - /flagged-respawn/2.0.0: - resolution: {integrity: sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==} - engines: {node: '>= 10.13.0'} - dev: true - /flat-cache/3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3820,19 +2825,13 @@ packages: peerDependenciesMeta: debug: optional: true + dev: false /for-in/1.0.2: resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} engines: {node: '>=0.10.0'} dev: true - /for-own/1.0.0: - resolution: {integrity: sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==} - engines: {node: '>=0.10.0'} - dependencies: - for-in: 1.0.2 - dev: true - /form-data/4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -3876,10 +2875,6 @@ packages: /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - - /gensync/1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} dev: true /get-caller-file/2.0.5: @@ -3889,8 +2884,8 @@ packages: /get-intrinsic/1.1.3: resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} dependencies: - function-bind: 1.1.1 - has: 1.0.3 + function-bind: registry.npmmirror.com/function-bind/1.1.1 + has: registry.npmmirror.com/has/1.0.3 has-symbols: 1.0.3 dev: false @@ -3948,15 +2943,6 @@ packages: ini: 1.3.8 dev: true - /global-modules/1.0.0: - resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} - engines: {node: '>=0.10.0'} - dependencies: - global-prefix: 1.0.2 - is-windows: 1.0.2 - resolve-dir: 1.0.1 - dev: true - /global-modules/2.0.0: resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} engines: {node: '>=6'} @@ -3964,17 +2950,6 @@ packages: global-prefix: 3.0.0 dev: true - /global-prefix/1.0.2: - resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 2.0.2 - homedir-polyfill: 1.0.3 - ini: 1.3.8 - is-windows: 1.0.2 - which: 1.3.1 - dev: true - /global-prefix/3.0.0: resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} engines: {node: '>=6'} @@ -3989,8 +2964,8 @@ packages: engines: {node: '>=4'} dev: true - /globals/13.17.0: - resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==} + /globals/13.19.0: + resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 @@ -4003,22 +2978,11 @@ packages: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.2.12 - ignore: 5.2.0 + ignore: 5.2.1 merge2: 1.4.1 slash: 3.0.0 dev: true - /globby/13.1.2: - resolution: {integrity: sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.2.12 - ignore: 5.2.0 - merge2: 1.4.1 - slash: 4.0.0 - dev: true - /globjoin/0.1.4: resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} dev: true @@ -4031,19 +2995,6 @@ packages: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} dev: true - /handlebars/4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.6 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.3 - dev: true - /hard-rejection/2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} @@ -4056,16 +3007,6 @@ packages: ansi-regex: 2.1.1 dev: true - /has-flag/1.0.0: - resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} - engines: {node: '>=0.10.0'} - dev: true - - /has-flag/3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - /has-flag/4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -4103,7 +3044,7 @@ packages: resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} engines: {node: '>=0.10.0'} dependencies: - is-number: 3.0.0 + is-number: registry.npmmirror.com/is-number/3.0.0 kind-of: 4.0.0 dev: true @@ -4112,6 +3053,7 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 + dev: true /he/1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -4122,14 +3064,7 @@ packages: resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} dependencies: capital-case: 1.0.4 - tslib: 2.4.0 - dev: true - - /homedir-polyfill/1.0.3: - resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} - engines: {node: '>=0.10.0'} - dependencies: - parse-passwd: 1.0.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /hosted-git-info/2.8.9: @@ -4140,21 +3075,7 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} dependencies: - lru-cache: 6.0.0 - dev: true - - /html-minifier-terser/6.1.0: - resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} - engines: {node: '>=12'} - hasBin: true - dependencies: - camel-case: 4.1.2 - clean-css: 5.3.1 - commander: 8.3.0 - he: 1.2.0 - param-case: 3.0.4 - relateurl: 0.2.7 - terser: 5.15.1 + lru-cache: registry.npmmirror.com/lru-cache/6.0.0 dev: true /html-tags/3.2.0: @@ -4199,30 +3120,11 @@ packages: /i18next/20.6.1: resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} dependencies: - '@babel/runtime': 7.19.0 + '@babel/runtime': 7.20.1 dev: false - /iconv-lite/0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /iconv-lite/0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - optional: true - - /ieee754/1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - - /ignore/5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + /ignore/5.2.1: + resolution: {integrity: sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==} engines: {node: '>= 4'} dev: true @@ -4232,10 +3134,14 @@ packages: hasBin: true dev: true - /immer/9.0.15: - resolution: {integrity: sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==} + /immer/9.0.16: + resolution: {integrity: sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==} dev: false + /immutable/4.1.0: + resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} + dev: true + /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -4274,44 +3180,10 @@ packages: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true - /inquirer/8.2.4: - resolution: {integrity: sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==} - engines: {node: '>=12.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.5.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 7.0.0 - dev: true - - /interpret/2.2.0: - resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} - engines: {node: '>= 0.10'} - dev: true - /intro.js/6.0.0: resolution: {integrity: sha512-ZUiR6BoLSvPSlLG0boewnWVgji1fE1gBvP/pyw5pgCKXEDQz1mMeUxarggClPNs71UTq364LwSk9zxz17A9gaQ==} dev: false - /is-absolute/1.0.0: - resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} - engines: {node: '>=0.10.0'} - dependencies: - is-relative: 1.0.0 - is-windows: 1.0.2 - dev: true - /is-accessor-descriptor/0.1.6: resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} engines: {node: '>=0.10.0'} @@ -4341,8 +3213,8 @@ packages: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} dev: true - /is-core-module/2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} dependencies: has: 1.0.3 dev: true @@ -4416,38 +3288,11 @@ packages: resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==} dev: false - /is-interactive/1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - - /is-interactive/2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - dev: true - - /is-number/3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - /is-obj/2.0.0: resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} engines: {node: '>=8'} dev: true - /is-path-cwd/2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - dev: true - /is-path-inside/3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} @@ -4469,13 +3314,6 @@ packages: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} - /is-relative/1.0.0: - resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} - engines: {node: '>=0.10.0'} - dependencies: - is-unc-path: 1.0.0 - dev: true - /is-stream/2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -4493,31 +3331,10 @@ packages: text-extensions: 1.9.0 dev: true - /is-unc-path/1.0.0: - resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} - engines: {node: '>=0.10.0'} - dependencies: - unc-path-regex: 0.1.2 - dev: true - - /is-unicode-supported/0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - - /is-unicode-supported/1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - dev: true - /is-url/1.2.4: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} dev: false - /is-what/3.14.1: - resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} - dev: true - /is-windows/1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -4527,11 +3344,6 @@ packages: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: true - /isbinaryfile/4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - dev: true - /isexe/2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true @@ -4559,28 +3371,14 @@ packages: minimatch: 3.1.2 dev: true - /jiti/1.16.0: - resolution: {integrity: sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==} - hasBin: true - dev: true - /js-base64/2.6.4: resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} dev: true - /js-cookie/3.0.1: - resolution: {integrity: sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==} - engines: {node: '>=12'} - dev: false - /js-sdsl/4.1.5: resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==} dev: true - /js-tokens/4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - /js-tokens/8.0.0: resolution: {integrity: sha512-PC7MzqInq9OqKyTXfIvQNcjMkODJYC8A17kAaQgeW79yfhqTWSOfjHYQ2mDDcwJ96Iibtwkfh0C7R/OvqPlgVA==} dev: true @@ -4596,12 +3394,6 @@ packages: resolution: {integrity: sha512-dVvV54GdFuJgmEKn+oBiaifDMen4p6o6j/lJh0OVMcouME8sST0bJ7bldIgKBQk4za0zyGn0/pm4vOznR25mLw==} dev: false - /jsesc/2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - /json-parse-even-better-errors/2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true @@ -4622,7 +3414,7 @@ packages: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: - minimist: 1.2.6 + minimist: 1.2.7 dev: true /json5/2.2.1: @@ -4645,7 +3437,7 @@ packages: /jsonfile/6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: - universalify: 2.0.0 + universalify: registry.npmmirror.com/universalify/2.0.0 optionalDependencies: graceful-fs: 4.2.10 dev: true @@ -4683,30 +3475,6 @@ packages: resolution: {integrity: sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==} dev: true - /kolorist/1.6.0: - resolution: {integrity: sha512-dLkz37Ab97HWMx9KTes3Tbi3D1ln9fCAy2zr2YVExJasDRPGRaKcoE4fycWNtnCAJfjFqe0cnY+f8KT2JePEXQ==} - dev: true - - /less/4.1.3: - resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} - engines: {node: '>=6'} - hasBin: true - dependencies: - copy-anything: 2.0.6 - parse-node-version: 1.0.1 - tslib: 2.4.0 - optionalDependencies: - errno: 0.1.8 - graceful-fs: 4.2.10 - image-size: 0.5.5 - make-dir: 2.1.0 - mime: 1.6.0 - needle: 3.1.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - /levn/0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -4715,22 +3483,8 @@ packages: type-check: 0.4.0 dev: true - /liftoff/4.0.0: - resolution: {integrity: sha512-rMGwYF8q7g2XhG2ulBmmJgWv25qBsqRbDn5gH0+wnuyeFt7QBJlHJmtg5qEdn4pN6WVAUMgXnIxytMFRX9c1aA==} - engines: {node: '>=10.13.0'} - dependencies: - extend: 3.0.2 - findup-sync: 5.0.0 - fined: 2.0.0 - flagged-respawn: 2.0.0 - is-plain-object: 5.0.0 - object.map: 1.0.1 - rechoir: 0.8.0 - resolve: 1.22.1 - dev: true - - /lilconfig/2.0.5: - resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} + /lilconfig/2.0.6: + resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} engines: {node: '>=10'} dev: true @@ -4738,8 +3492,8 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true - /lint-staged/13.0.3: - resolution: {integrity: sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==} + /lint-staged/13.1.0: + resolution: {integrity: sha512-pn/sR8IrcF/T0vpWLilih8jmVouMlxqXxKuAojmbiGX5n/gDnz+abdPptlj0vYnbfE0SQNl3CY/HwtM0+yfOVQ==} engines: {node: ^14.13.1 || >=16.0.0} hasBin: true dependencies: @@ -4748,8 +3502,8 @@ packages: commander: 9.4.1 debug: 4.3.4 execa: 6.1.0 - lilconfig: 2.0.5 - listr2: 4.0.5 + lilconfig: 2.0.6 + listr2: 5.0.5 micromatch: 4.0.5 normalize-path: 3.0.0 object-inspect: 1.12.2 @@ -4761,9 +3515,9 @@ packages: - supports-color dev: true - /listr2/4.0.5: - resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} - engines: {node: '>=12'} + /listr2/5.0.5: + resolution: {integrity: sha512-DpBel6fczu7oQKTXMekeprc0o3XDgGMkD7JNYyX+X0xbwK+xgrx9dcyKoXKqpLSUvAWfmoePS7kavniOcq3r4w==} + engines: {node: ^14.13.1 || >=16.0.0} peerDependencies: enquirer: '>= 2.3.0 < 3' peerDependenciesMeta: @@ -4780,8 +3534,8 @@ packages: wrap-ansi: 7.0.0 dev: true - /loader-utils/1.4.0: - resolution: {integrity: sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==} + /loader-utils/1.4.2: + resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} engines: {node: '>=4.0.0'} dependencies: big.js: 5.2.2 @@ -4789,11 +3543,6 @@ packages: json5: 1.0.1 dev: true - /local-pkg/0.4.2: - resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} - engines: {node: '>=14'} - dev: true - /locate-path/5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -4811,8 +3560,8 @@ packages: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} dev: false - /lodash-unified/1.0.2_3ib2ivapxullxkx3xftsimdk7u: - resolution: {integrity: sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==} + /lodash-unified/1.0.3_3ib2ivapxullxkx3xftsimdk7u: + resolution: {integrity: sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==} peerDependencies: '@types/lodash-es': '*' lodash: '*' @@ -4825,7 +3574,6 @@ packages: /lodash.camelcase/4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: false /lodash.clonedeep/4.5.0: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} @@ -4839,18 +3587,38 @@ packages: resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} dev: false - /lodash.get/4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: true - /lodash.isequal/4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} dev: false + /lodash.isfunction/3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + dev: true + + /lodash.isplainobject/4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.kebabcase/4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + dev: true + /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash.mergewith/4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: true + + /lodash.snakecase/4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + dev: true + + /lodash.startcase/4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + /lodash.throttle/4.1.1: resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} dev: false @@ -4863,25 +3631,17 @@ packages: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} dev: true + /lodash.uniq/4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash.upperfirst/4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + /lodash/4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - /log-symbols/4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - - /log-symbols/5.1.0: - resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} - engines: {node: '>=12'} - dependencies: - chalk: 5.1.0 - is-unicode-supported: 1.3.0 - dev: true - /log-update/4.0.0: resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} engines: {node: '>=10'} @@ -4895,7 +3655,7 @@ packages: /lower-case/2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /lru-cache/6.0.0: @@ -4909,35 +3669,12 @@ packages: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} dependencies: sourcemap-codec: 1.4.8 - - /magic-string/0.26.7: - resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} - engines: {node: '>=12'} - dependencies: - sourcemap-codec: 1.4.8 dev: true - /make-dir/2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - pify: 4.0.1 - semver: 5.7.1 - dev: true - optional: true - /make-error/1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true - /make-iterator/1.0.1: - resolution: {integrity: sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 6.0.3 - dev: true - /map-cache/0.2.2: resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} engines: {node: '>=0.10.0'} @@ -4978,7 +3715,7 @@ packages: dependencies: '@types/minimist': 1.2.2 camelcase-keys: 6.2.2 - decamelize-keys: 1.1.0 + decamelize-keys: 1.1.1 hard-rejection: 2.1.0 minimist-options: 4.1.0 normalize-package-data: 3.0.3 @@ -4996,7 +3733,7 @@ packages: '@types/minimist': 1.2.2 camelcase-keys: 6.2.2 decamelize: 1.2.0 - decamelize-keys: 1.1.0 + decamelize-keys: 1.1.1 hard-rejection: 2.1.0 minimist-options: 4.1.0 normalize-package-data: 3.0.3 @@ -5029,7 +3766,7 @@ packages: dependencies: arr-diff: 4.0.0 array-unique: 0.3.2 - braces: 2.3.2 + braces: registry.npmmirror.com/braces/2.3.2 define-property: 1.0.0 extend-shallow: 2.0.1 extglob: 2.0.4 @@ -5070,14 +3807,6 @@ packages: mime-db: 1.52.0 dev: false - /mime/1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - requiresBuild: true - dev: true - optional: true - /mimic-fn/2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -5106,6 +3835,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch/5.1.2: + resolution: {integrity: sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimist-options/4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -5115,8 +3851,8 @@ packages: kind-of: 6.0.3 dev: true - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} dev: true /mitt/3.0.0: @@ -5131,12 +3867,6 @@ packages: is-extendable: 1.0.1 dev: true - /mkdirp/1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - /ms/2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: true @@ -5145,19 +3875,10 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true - /ms/2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - optional: true - /muggle-string/0.1.0: resolution: {integrity: sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg==} dev: true - /mute-stream/0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - dev: true - /namespace-emitter/2.0.1: resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==} dev: false @@ -5194,24 +3915,6 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /needle/3.1.0: - resolution: {integrity: sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==} - engines: {node: '>= 4.4.x'} - hasBin: true - requiresBuild: true - dependencies: - debug: 3.2.7 - iconv-lite: 0.6.3 - sax: 1.2.4 - transitivePeerDependencies: - - supports-color - dev: true - optional: true - - /neo-async/2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - /next-tick/1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: false @@ -5220,45 +3923,7 @@ packages: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 - tslib: 2.4.0 - dev: true - - /node-fetch/2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-html-parser/5.4.2: - resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} - dependencies: - css-select: 4.3.0 - he: 1.2.0 - dev: true - - /node-plop/0.31.0: - resolution: {integrity: sha512-aKLPxiBoFTNUovvtK8j/Whc4PZREkYx6htw2HJPiU8wYquXmN8pkd9B3xlFo6AJ4ZlzFsQSf/NXR5xET8EqRYw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - '@types/inquirer': 8.2.4 - change-case: 4.1.2 - del: 6.1.1 - globby: 13.1.2 - handlebars: 4.7.7 - inquirer: 8.2.4 - isbinaryfile: 4.0.10 - lodash.get: 4.4.2 - lower-case: 2.0.2 - mkdirp: 1.0.4 - resolve: 1.22.1 - title-case: 3.0.3 - upper-case: 2.0.2 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /node-releases/2.0.6: @@ -5279,8 +3944,8 @@ packages: engines: {node: '>=10'} dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.10.0 - semver: 7.3.8 + is-core-module: registry.npmmirror.com/is-core-module/2.11.0 + semver: registry.npmmirror.com/semver/7.3.8 validate-npm-package-license: 3.0.4 dev: true @@ -5346,24 +4011,6 @@ packages: isobject: 3.0.1 dev: true - /object.defaults/1.1.0: - resolution: {integrity: sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==} - engines: {node: '>=0.10.0'} - dependencies: - array-each: 1.0.1 - array-slice: 1.1.0 - for-own: 1.0.0 - isobject: 3.0.1 - dev: true - - /object.map/1.0.1: - resolution: {integrity: sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==} - engines: {node: '>=0.10.0'} - dependencies: - for-own: 1.0.0 - make-iterator: 1.0.1 - dev: true - /object.pick/1.3.0: resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} engines: {node: '>=0.10.0'} @@ -5403,41 +4050,6 @@ packages: word-wrap: 1.2.3 dev: true - /ora/5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.7.0 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /ora/6.1.2: - resolution: {integrity: sha512-EJQ3NiP5Xo94wJXIzAyOtSb0QEIAUu7m8t6UZ9krbz0vAJqr92JpcK/lEXg91q6B9pEGqrykkd2EQplnifDSBw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - bl: 5.0.0 - chalk: 5.1.0 - cli-cursor: 4.0.0 - cli-spinners: 2.7.0 - is-interactive: 2.0.0 - is-unicode-supported: 1.3.0 - log-symbols: 5.1.0 - strip-ansi: 7.0.1 - wcwidth: 1.0.1 - dev: true - - /os-tmpdir/1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - /p-limit/2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -5479,7 +4091,7 @@ packages: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} dependencies: dot-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /parent-module/1.0.1: @@ -5489,40 +4101,21 @@ packages: callsites: 3.1.0 dev: true - /parse-filepath/1.0.2: - resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} - engines: {node: '>=0.8'} - dependencies: - is-absolute: 1.0.0 - map-cache: 0.2.2 - path-root: 0.1.1 - dev: true - /parse-json/5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': registry.npmmirror.com/@babel/code-frame/7.18.6 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 dev: true - /parse-node-version/1.0.1: - resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} - engines: {node: '>= 0.10'} - dev: true - - /parse-passwd/1.0.0: - resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} - engines: {node: '>=0.10.0'} - dev: true - /pascal-case/3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} dependencies: no-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /pascalcase/0.1.1: @@ -5534,7 +4127,7 @@ packages: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} dependencies: dot-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /path-exists/4.0.0: @@ -5560,18 +4153,6 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true - /path-root-regex/0.1.2: - resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} - engines: {node: '>=0.10.0'} - dev: true - - /path-root/0.1.1: - resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} - engines: {node: '>=0.10.0'} - dependencies: - path-root-regex: 0.1.2 - dev: true - /path-type/4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -5585,8 +4166,13 @@ packages: resolution: {integrity: sha512-6Y6s0vT112P3jD8dGfuS6r+lpa0qqNrLyHPOwvXMnyNTQaYiwgau2DP3aNDsR13xqtGj7rrPo+jFUATpU6/s+g==} dev: true + /pathe/1.0.0: + resolution: {integrity: sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==} + dev: true + /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -5599,45 +4185,6 @@ packages: hasBin: true dev: true - /pify/4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - optional: true - - /pinia/2.0.23_d45o5shxrtvj6wh4y524t7cqnm: - resolution: {integrity: sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==} - peerDependencies: - '@vue/composition-api': ^1.4.0 - typescript: '>=4.4.4' - vue: ^2.6.14 || ^3.2.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - typescript: - optional: true - dependencies: - '@vue/devtools-api': 6.4.4 - typescript: 4.8.4 - vue: 3.2.44 - vue-demi: 0.13.11_vue@3.2.44 - dev: false - - /plop/3.1.1: - resolution: {integrity: sha512-NuctKmuNUACXBQn25bBr5oj/75nHxdKGwjA/+b7cVoj1sp+gTVqcc8eAr4QcNJgMPsZWRJBN2kMkgmsqbqV9gg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dependencies: - '@types/liftoff': 4.0.0 - chalk: 5.1.0 - interpret: 2.2.0 - liftoff: 4.0.0 - minimist: 1.2.6 - node-plop: 0.31.0 - ora: 6.1.2 - v8flags: 4.0.0 - dev: true - /pngjs/5.0.0: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} @@ -5654,17 +4201,8 @@ packages: dependencies: htmlparser2: 8.0.1 js-tokens: 8.0.0 - postcss: 8.4.18 - postcss-safe-parser: 6.0.0_postcss@8.4.18 - dev: true - - /postcss-less/6.0.0_postcss@8.4.18: - resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==} - engines: {node: '>=12'} - peerDependencies: - postcss: ^8.3.5 - dependencies: - postcss: 8.4.18 + postcss: registry.npmmirror.com/postcss/8.4.20 + postcss-safe-parser: 6.0.0_postcss@8.4.20 dev: true /postcss-media-query-parser/0.2.3: @@ -5676,20 +4214,29 @@ packages: peerDependencies: postcss: '>4 <9' dependencies: - postcss: 5.2.18 + postcss: registry.npmmirror.com/postcss/5.2.18 dev: true /postcss-resolve-nested-selector/0.1.1: resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} dev: true - /postcss-safe-parser/6.0.0_postcss@8.4.18: + /postcss-safe-parser/6.0.0_postcss@8.4.20: resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.3.3 dependencies: - postcss: 8.4.18 + postcss: registry.npmmirror.com/postcss/8.4.20 + dev: true + + /postcss-scss/4.0.6_postcss@8.4.20: + resolution: {integrity: sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.19 + dependencies: + postcss: registry.npmmirror.com/postcss/8.4.20 dev: true /postcss-selector-parser/6.0.10: @@ -5700,35 +4247,34 @@ packages: util-deprecate: 1.0.2 dev: true - /postcss-sorting/7.0.1_postcss@8.4.18: + /postcss-selector-parser/6.0.11: + resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-sorting/7.0.1_postcss@8.4.20: resolution: {integrity: sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==} peerDependencies: postcss: ^8.3.9 dependencies: - postcss: 8.4.18 + postcss: registry.npmmirror.com/postcss/8.4.20 dev: true /postcss-value-parser/4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} dev: true - /postcss/5.2.18: - resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} - engines: {node: '>=0.12'} - dependencies: - chalk: 1.1.3 - js-base64: 2.6.4 - source-map: 0.5.7 - supports-color: 3.2.3 - dev: true - - /postcss/8.4.18: - resolution: {integrity: sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==} + /postcss/8.4.20: + resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.4 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: true /posthtml-parser/0.2.1: resolution: {integrity: sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==} @@ -5765,8 +4311,8 @@ packages: posthtml-render: 1.4.0 dev: true - /preact/10.11.1: - resolution: {integrity: sha512-1Wz5PCRm6Fg+6BTXWJHhX4wRK9MZbZBHuwBqfZlOdVm2NqPe8/rjYpufvYCwJSGb9layyzB2jTTXfpCTynLqFQ==} + /preact/10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} dev: false /prelude-ls/1.2.1: @@ -5781,8 +4327,8 @@ packages: fast-diff: 1.2.0 dev: true - /prettier/2.7.1: - resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} + /prettier/2.8.1: + resolution: {integrity: sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==} engines: {node: '>=10.13.0'} hasBin: true dev: true @@ -5792,10 +4338,14 @@ packages: engines: {node: '>=6'} dev: false - /prr/1.0.1: - resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + /progress/2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} dev: true - optional: true + + /proxy-from-env/1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false /punycode/1.3.2: resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} @@ -5852,6 +4402,12 @@ packages: engines: {node: '>=8'} dev: true + /rd/2.0.1: + resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==} + dependencies: + '@types/node': 10.17.60 + dev: true + /read-pkg-up/7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -5887,13 +4443,6 @@ packages: picomatch: 2.3.1 dev: true - /rechoir/0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - dependencies: - resolve: 1.22.1 - dev: true - /redent/3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -5902,10 +4451,6 @@ packages: strip-indent: 3.0.0 dev: true - /regenerator-runtime/0.13.9: - resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} - dev: false - /regex-not/1.0.2: resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} engines: {node: '>=0.10.0'} @@ -5919,11 +4464,6 @@ packages: engines: {node: '>=8'} dev: true - /relateurl/0.2.7: - resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} - engines: {node: '>= 0.10'} - dev: true - /repeat-element/1.1.4: resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} engines: {node: '>=0.10.0'} @@ -5947,14 +4487,6 @@ packages: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} dev: false - /resolve-dir/1.0.1: - resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 2.0.2 - global-modules: 1.0.0 - dev: true - /resolve-from/4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -5981,7 +4513,7 @@ packages: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true dependencies: - is-core-module: 2.10.0 + is-core-module: 2.11.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -5994,14 +4526,6 @@ packages: signal-exit: 3.0.7 dev: true - /restore-cursor/4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - /ret/0.1.15: resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} engines: {node: '>=0.12'} @@ -6023,17 +4547,6 @@ packages: glob: 7.2.3 dev: true - /rollup-plugin-purge-icons/0.9.1: - resolution: {integrity: sha512-hRDKBsPUz47UMdBufki2feTmBF2ClEJlYqL7N6vpVAHSLd7V2BJUaNKOF7YYbLMofVVF+9hm44YSkYO6k9hUgg==} - engines: {node: '>= 12'} - dependencies: - '@purge-icons/core': 0.9.1 - '@purge-icons/generated': 0.9.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - /rollup/2.79.1: resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} engines: {node: '>=10.0.0'} @@ -6042,19 +4555,14 @@ packages: fsevents: 2.3.2 dev: true - /rollup/3.2.5: - resolution: {integrity: sha512-/Ha7HhVVofduy+RKWOQJrxe4Qb3xyZo+chcpYiD8SoQa4AG7llhupUtyfKSSrdBM2mWJjhM8wZwmbY23NmlIYw==} + /rollup/3.8.1: + resolution: {integrity: sha512-4yh9eMW7byOroYcN8DlF9P/2jCpu6txVIHjEqquQVSx7DI0RgyCCN3tjrcy4ra6yVtV336aLBB3v2AarYAxePQ==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: fsevents: 2.3.2 dev: true - /run-async/2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - dev: true - /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -6064,11 +4572,7 @@ packages: /rxjs/7.5.7: resolution: {integrity: sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==} dependencies: - tslib: 2.4.0 - dev: true - - /safe-buffer/5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /safe-buffer/5.2.1: @@ -6081,15 +4585,16 @@ packages: ret: 0.1.15 dev: true - /safer-buffer/2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + /sass/1.57.1: + resolution: {integrity: sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.1.0 + source-map-js: 1.0.2 dev: true - /sax/1.2.4: - resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} - dev: true - optional: true - /scroll-into-view-if-needed/2.2.29: resolution: {integrity: sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==} dependencies: @@ -6106,14 +4611,6 @@ packages: hasBin: true dev: true - /semver/7.3.7: - resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - /semver/7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} @@ -6126,7 +4623,7 @@ packages: resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} dependencies: no-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 upper-case-first: 2.0.2 dev: true @@ -6173,11 +4670,6 @@ packages: engines: {node: '>=8'} dev: true - /slash/4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - dev: true - /slate-history/0.66.0_slate@0.72.8: resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==} peerDependencies: @@ -6190,7 +4682,7 @@ packages: /slate/0.72.8: resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==} dependencies: - immer: 9.0.15 + immer: 9.0.16 is-plain-object: 5.0.0 tiny-warning: 1.0.3 dev: false @@ -6199,7 +4691,7 @@ packages: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} dependencies: - ansi-styles: 4.3.0 + ansi-styles: registry.npmmirror.com/ansi-styles/4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 dev: true @@ -6208,7 +4700,7 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} dependencies: - ansi-styles: 4.3.0 + ansi-styles: registry.npmmirror.com/ansi-styles/4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 dev: true @@ -6217,7 +4709,7 @@ packages: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} dependencies: - ansi-styles: 6.1.1 + ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 dev: true @@ -6230,7 +4722,7 @@ packages: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} dependencies: dot-case: 3.0.4 - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /snapdragon-node/2.1.1: @@ -6268,6 +4760,7 @@ packages: /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + dev: true /source-map-resolve/0.5.3: resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} @@ -6303,6 +4796,7 @@ packages: /sourcemap-codec/1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead /spdx-correct/3.1.1: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} @@ -6435,7 +4929,7 @@ packages: resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} dev: true - /stylelint-config-html/1.1.0_a4i6jbpfaxelx4fvjhtlgvxx6i: + /stylelint-config-html/1.1.0_bto6pmslw3cibsiuq6smxboytq: resolution: {integrity: sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==} engines: {node: ^12 || >=14} peerDependencies: @@ -6443,55 +4937,55 @@ packages: stylelint: '>=14.0.0' dependencies: postcss-html: 1.5.0 - stylelint: 14.14.1 + stylelint: 14.16.0 dev: true - /stylelint-config-prettier/9.0.4_stylelint@14.14.1: + /stylelint-config-prettier/9.0.4_stylelint@14.16.0: resolution: {integrity: sha512-38nIGTGpFOiK5LjJ8Ma1yUgpKENxoKSOhbDNSemY7Ep0VsJoXIW9Iq/2hSt699oB9tReynfWicTAoIHiq8Rvbg==} engines: {node: '>= 12'} hasBin: true peerDependencies: stylelint: '>=11.0.0' dependencies: - stylelint: 14.14.1 + stylelint: 14.16.0 dev: true - /stylelint-config-recommended/9.0.0_stylelint@14.14.1: + /stylelint-config-recommended/9.0.0_stylelint@14.16.0: resolution: {integrity: sha512-9YQSrJq4NvvRuTbzDsWX3rrFOzOlYBmZP+o513BJN/yfEmGSr0AxdvrWs0P/ilSpVV/wisamAHu5XSk8Rcf4CQ==} peerDependencies: stylelint: ^14.10.0 dependencies: - stylelint: 14.14.1 + stylelint: 14.16.0 dev: true - /stylelint-config-standard/29.0.0_stylelint@14.14.1: + /stylelint-config-standard/29.0.0_stylelint@14.16.0: resolution: {integrity: sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==} peerDependencies: stylelint: ^14.14.0 dependencies: - stylelint: 14.14.1 - stylelint-config-recommended: 9.0.0_stylelint@14.14.1 + stylelint: 14.16.0 + stylelint-config-recommended: 9.0.0_stylelint@14.16.0 dev: true - /stylelint-order/5.0.0_stylelint@14.14.1: + /stylelint-order/5.0.0_stylelint@14.16.0: resolution: {integrity: sha512-OWQ7pmicXufDw5BlRqzdz3fkGKJPgLyDwD1rFY3AIEfIH/LQY38Vu/85v8/up0I+VPiuGRwbc2Hg3zLAsJaiyw==} peerDependencies: stylelint: ^14.0.0 dependencies: - postcss: 8.4.18 - postcss-sorting: 7.0.1_postcss@8.4.18 - stylelint: 14.14.1 + postcss: registry.npmmirror.com/postcss/8.4.20 + postcss-sorting: 7.0.1_postcss@8.4.20 + stylelint: 14.16.0 dev: true - /stylelint/14.14.1: - resolution: {integrity: sha512-Jnftu+lSD8cSpcV/+Z2nfgfgFpTIS1FcujezXPngtoIQ6wtwutL22MsNE0dJuMiM1h1790g2qIjAyUZCMrX4sw==} + /stylelint/14.16.0: + resolution: {integrity: sha512-X6uTi9DcxjzLV8ZUAjit1vsRtSwcls0nl07c9rqOPzvpA8IvTX/xWEkBRowS0ffevRrqkHa/ThDEu86u73FQDg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true dependencies: - '@csstools/selector-specificity': 2.0.2_dvkg4kkb622mvceygg47xxdz3a + '@csstools/selector-specificity': 2.0.2_2xshye3abirqjlplmebvmaxyna balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 7.0.1 + cosmiconfig: 7.1.0 css-functions-list: 3.1.0 debug: 4.3.4 fast-glob: 3.2.12 @@ -6501,7 +4995,7 @@ packages: globby: 11.1.0 globjoin: 0.1.4 html-tags: 3.2.0 - ignore: 5.2.0 + ignore: 5.2.1 import-lazy: 4.0.0 imurmurhash: 0.1.4 is-plain-object: 5.0.0 @@ -6511,11 +5005,11 @@ packages: micromatch: 4.0.5 normalize-path: 3.0.0 picocolors: 1.0.0 - postcss: 8.4.18 + postcss: registry.npmmirror.com/postcss/8.4.20 postcss-media-query-parser: 0.2.3 postcss-resolve-nested-selector: 0.1.1 - postcss-safe-parser: 6.0.0_postcss@8.4.18 - postcss-selector-parser: 6.0.10 + postcss-safe-parser: 6.0.0_postcss@8.4.20 + postcss-selector-parser: 6.0.11 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 string-width: 4.2.3 @@ -6530,25 +5024,6 @@ packages: - supports-color dev: true - /supports-color/2.0.0: - resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} - engines: {node: '>=0.8.0'} - dev: true - - /supports-color/3.2.3: - resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} - engines: {node: '>=0.8.0'} - dependencies: - has-flag: 1.0.0 - dev: true - - /supports-color/5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - /supports-color/7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -6576,15 +5051,15 @@ packages: clone: 2.1.2 he: 1.2.0 image-size: 0.5.5 - loader-utils: 1.4.0 + loader-utils: 1.4.2 merge-options: 1.0.1 micromatch: 3.1.0 - postcss: 5.2.18 + postcss: registry.npmmirror.com/postcss/5.2.18 postcss-prefix-selector: 1.16.0_postcss@5.2.18 posthtml-rename-id: 1.0.12 posthtml-svg-mode: 1.0.3 query-string: 4.3.4 - traverse: 0.6.6 + traverse: 0.6.7 transitivePeerDependencies: - supports-color dev: true @@ -6603,7 +5078,7 @@ packages: css-select: 4.3.0 css-tree: 1.1.3 csso: 4.2.0 - picocolors: 1.0.0 + picocolors: registry.npmmirror.com/picocolors/1.0.0 stable: 0.1.8 dev: true @@ -6611,20 +5086,20 @@ packages: resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} engines: {node: '>=10.0.0'} dependencies: - ajv: 8.11.0 + ajv: 8.11.2 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 dev: true - /terser/5.15.1: - resolution: {integrity: sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==} + /terser/5.16.1: + resolution: {integrity: sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==} engines: {node: '>=10'} hasBin: true dependencies: '@jridgewell/source-map': 0.3.2 - acorn: 8.8.0 + acorn: 8.8.1 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -6652,23 +5127,6 @@ packages: resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} dev: false - /title-case/3.0.3: - resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} - dependencies: - tslib: 2.4.0 - dev: true - - /tmp/0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /to-fast-properties/2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - /to-object-path/0.3.0: resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} engines: {node: '>=0.10.0'} @@ -6676,21 +5134,6 @@ packages: kind-of: 3.2.2 dev: true - /to-regex-range/2.1.1: - resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - dev: true - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - /to-regex/3.0.2: resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} engines: {node: '>=0.10.0'} @@ -6701,12 +5144,8 @@ packages: safe-regex: 1.1.0 dev: true - /tr46/0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true - - /traverse/0.6.6: - resolution: {integrity: sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==} + /traverse/0.6.7: + resolution: {integrity: sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==} dev: true /trim-newlines/3.0.1: @@ -6714,7 +5153,7 @@ packages: engines: {node: '>=8'} dev: true - /ts-node/10.9.1_fk6arlf3j7tudlucddpzvj2plq: + /ts-node/10.9.1_rju6pyblifsagdmqm3y74zsi6q: resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -6733,14 +5172,14 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 14.18.31 - acorn: 8.8.0 + '@types/node': 14.18.33 + acorn: 8.8.1 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 4.8.4 + typescript: 4.9.4 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: true @@ -6749,22 +5188,18 @@ packages: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true - /tslib/2.3.0: - resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} - dev: false - - /tslib/2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} dev: true - /tsutils/3.21.0_typescript@4.8.4: + /tsutils/3.21.0_typescript@4.9.4: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 4.8.4 + typescript: 4.9.4 dev: true /type-check/0.4.0: @@ -6807,24 +5242,11 @@ packages: resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} dev: false - /typescript/4.8.4: - resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} + /typescript/4.9.4: + resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} engines: {node: '>=4.2.0'} hasBin: true - /uglify-js/3.17.3: - resolution: {integrity: sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /unc-path-regex/0.1.2: - resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} - engines: {node: '>=0.10.0'} - dev: true - /union-value/1.0.1: resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} engines: {node: '>=0.10.0'} @@ -6840,76 +5262,13 @@ packages: engines: {node: '>= 10.0.0'} dev: true - /unplugin-combine/0.2.8_rollup@3.2.5+vite@3.2.3: - resolution: {integrity: sha512-Z38AC/TEjXbVyZ5HjVqo+lADj0/dcfwWC0Z4y0LNhybJzJQwmcMxm+ZsqHY3faauj4YigmlRMdptR5JEW9RuLg==} - engines: {node: '>=14.19.0'} - peerDependencies: - esbuild: '>=0.13' - rollup: ^2.50.0 - vite: ^2.3.0 || ^3.0.0 - webpack: 4 || 5 - peerDependenciesMeta: - esbuild: - optional: true - rollup: - optional: true - vite: - optional: true - webpack: - optional: true + /unplugin/1.0.1: + resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} dependencies: - '@antfu/utils': 0.6.0 - rollup: 3.2.5 - unplugin: 0.10.2 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - dev: true - - /unplugin-vue-define-options/0.12.7: - resolution: {integrity: sha512-relFORVPLDs4dd3ogEti5YyAqQ62XEieRgLu/OrDIRZdSZQ942pydf9ilfLFiFwCUt+EES/2Xl4EERtgP1T/og==} - engines: {node: '>=14.19.0'} - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/common': 0.13.3 - ast-walker-scope: 0.3.0 - unplugin: 0.10.2 - dev: true - - /unplugin-vue-macros/0.16.2_nch4vsbos5hmj7k4a4oy3znhuu: - resolution: {integrity: sha512-uNfjIXVUYBujbjJUcjXreE6zipZlPAIEMsx6bc/5qygwTfdvkJeHCAvvxrl0c8hdcT5/18OV2VDdwI60vCh56g==} - engines: {node: '>=14.19.0'} - peerDependencies: - vue: ^2.7.0 || ^3.2.25 - dependencies: - '@rollup/pluginutils': 4.2.1 - '@vue-macros/better-define': 0.1.0 - '@vue-macros/define-model': 0.13.8_@vueuse+core@9.5.0 - '@vue-macros/define-props': 0.0.2_vue@3.2.44 - '@vue-macros/define-render': 0.13.8_vue@3.2.44 - '@vue-macros/define-slots': 0.0.5_vue@3.2.44 - '@vue-macros/hoist-static': 0.12.7 - '@vue-macros/named-template': 0.0.5_vkxhlib7tgibcivdhj2bfsgnbi - '@vue-macros/setup-component': 0.12.7_rollup@3.2.5+vite@3.2.3 - '@vue-macros/setup-sfc': 0.12.7 - '@vue-macros/short-emits': 0.12.8 - local-pkg: 0.4.2 - unplugin-combine: 0.2.8_rollup@3.2.5+vite@3.2.3 - unplugin-vue-define-options: 0.12.7 - vue: 3.2.44 - transitivePeerDependencies: - - '@vueuse/core' - - esbuild - - rollup - - vite - - webpack - dev: true - - /unplugin/0.10.2: - resolution: {integrity: sha512-6rk7GUa4ICYjae5PrAllvcDeuT8pA9+j5J5EkxbMFaV+SalHhxZ7X2dohMzu6C3XzsMT+6jwR/+pwPNR3uK9MA==} - dependencies: - acorn: 8.8.0 + acorn: 8.8.1 chokidar: 3.5.3 webpack-sources: 3.2.3 - webpack-virtual-modules: 0.4.5 + webpack-virtual-modules: 0.5.0 dev: true /unset-value/1.0.0: @@ -6928,19 +5287,19 @@ packages: dependencies: browserslist: 4.21.4 escalade: 3.1.1 - picocolors: 1.0.0 + picocolors: registry.npmmirror.com/picocolors/1.0.0 dev: true /upper-case-first/2.0.2: resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} dependencies: - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /upper-case/2.0.2: resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} dependencies: - tslib: 2.4.0 + tslib: registry.npmmirror.com/tslib/2.4.1 dev: true /uri-js/4.4.1: @@ -6978,11 +5337,6 @@ packages: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true - /v8flags/4.0.0: - resolution: {integrity: sha512-83N0OkTbn6gOjJ2awNuzuK4czeGxwEwBoTqlhBZhnp8o0IJ72mXRQKphj/azwRf3acbDJZYZhbOPEJHd884ELg==} - engines: {node: '>= 10.13.0'} - dev: true - /validate-npm-package-license/3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: @@ -6995,7 +5349,7 @@ packages: engines: {node: '>= 0.8'} dev: true - /vite-plugin-compression/0.5.1_vite@3.2.3: + /vite-plugin-compression/0.5.1_vite@4.0.3: resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} peerDependencies: vite: '>=2.0.0' @@ -7003,60 +5357,43 @@ packages: chalk: 4.1.2 debug: 4.3.4 fs-extra: 10.1.0 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce transitivePeerDependencies: - supports-color dev: true - /vite-plugin-eslint/1.8.1_eslint@8.27.0+vite@3.2.3: + /vite-plugin-ejs/1.6.4: + resolution: {integrity: sha512-23p1RS4PiA0veXY5/gHZ60pl3pPvd8NEqdBsDgxNK8nM1rjFFDcVb0paNmuipzCgNP/Y0f/Id22M7Il4kvZ2jA==} + dependencies: + ejs: 3.1.8 + dev: true + + /vite-plugin-eslint/1.8.1_eslint@8.30.0+vite@4.0.3: resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==} peerDependencies: eslint: '>=7' vite: '>=2' dependencies: '@rollup/pluginutils': 4.2.1 - '@types/eslint': 8.4.6 - eslint: 8.27.0 + '@types/eslint': 8.4.10 + eslint: 8.30.0 rollup: 2.79.1 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce dev: true - /vite-plugin-html/3.2.0_vite@3.2.3: - resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==} + /vite-plugin-progress/0.0.6_vite@4.0.3: + resolution: {integrity: sha512-pIK2TVEY4XFGrz10CQDdEufBBCDaV0geRHfXV3abGTBr+OF9O0Zmd3ZDrHJXDv4Rl3qAQP4BTCuPYQ3XqstmqA==} + engines: {node: '>=14', pnpm: '>=7.0.0'} peerDependencies: - vite: '>=2.0.0' + vite: '>2.0.0-0' dependencies: - '@rollup/pluginutils': 4.2.1 - colorette: 2.0.19 - connect-history-api-fallback: 1.6.0 - consola: 2.15.3 - dotenv: 16.0.3 - dotenv-expand: 8.0.3 - ejs: 3.1.8 - fast-glob: 3.2.12 - fs-extra: 10.1.0 - html-minifier-terser: 6.1.0 - node-html-parser: 5.4.2 - pathe: 0.2.0 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi + picocolors: 1.0.0 + progress: 2.0.3 + rd: 2.0.1 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce dev: true - /vite-plugin-purge-icons/0.9.1_vite@3.2.3: - resolution: {integrity: sha512-oS0Y9Iq6vGnTDVRzB8xJNhA/gGlyR0lfCICU6+9FRKdrO5PnT34fRjvd8YWEsegCrk91+w3GVZc0HJDj/dPp5Q==} - engines: {node: '>= 12'} - peerDependencies: - vite: ^2.0.0-beta.3 || ^3.0.0 - dependencies: - '@purge-icons/core': 0.9.1 - '@purge-icons/generated': 0.9.0 - rollup-plugin-purge-icons: 0.9.1 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /vite-plugin-style-import/2.0.0_vite@3.2.3: + /vite-plugin-style-import/2.0.0_vite@4.0.3: resolution: {integrity: sha512-qtoHQae5dSUQPo/rYz/8p190VU5y19rtBaeV7ryLa/AYAU/e9CG89NrN/3+k7MR8mJy/GPIu91iJ3zk9foUOSA==} peerDependencies: vite: '>=2.0.0' @@ -7068,10 +5405,10 @@ packages: fs-extra: 10.1.0 magic-string: 0.25.9 pathe: 0.2.0 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce dev: true - /vite-plugin-svg-icons/2.0.1_vite@3.2.3: + /vite-plugin-svg-icons/2.0.1_vite@4.0.3: resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==} peerDependencies: vite: '>=2.0.0' @@ -7084,27 +5421,23 @@ packages: pathe: 0.2.0 svg-baker: 1.7.0 svgo: 2.8.0 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce transitivePeerDependencies: - supports-color dev: true - /vite-plugin-windicss/1.8.8_vite@3.2.3: - resolution: {integrity: sha512-iyu+ZX0NmhNEUaLPv7xtC+EFRBpWMmw0nhd9a9upayfuNG/thwslKiQKmRB7U/dG0k/2oWLvPDvN/B9i7oRgSA==} + /vite-plugin-vue-setup-extend/0.4.0_vite@4.0.3: + resolution: {integrity: sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==} peerDependencies: - vite: ^2.0.1 || ^3.0.0 + vite: '>=2.0.0' dependencies: - '@windicss/plugin-utils': 1.8.8 - debug: 4.3.4 - kolorist: 1.6.0 - vite: 3.2.3_mp5lu76ee5qtwstsyca37sdhqi - windicss: 3.5.6 - transitivePeerDependencies: - - supports-color + '@vue/compiler-sfc': 3.2.45 + magic-string: 0.25.9 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce dev: true - /vite/3.2.3_mp5lu76ee5qtwstsyca37sdhqi: - resolution: {integrity: sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==} + /vite/4.0.3_amyfslv6hdwxqbf7f4ldebbtce: + resolution: {integrity: sha512-HvuNv1RdE7deIfQb8mPk51UKjqptO/4RXZ5yXSAvurd5xOckwS/gg8h9Tky3uSbnjYTgUm0hVCet1cyhKd73ZA==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -7128,21 +5461,18 @@ packages: terser: optional: true dependencies: - '@types/node': 18.11.9 - esbuild: 0.15.10 - less: 4.1.3 - postcss: 8.4.18 + '@types/node': 18.11.17 + esbuild: 0.16.5 + postcss: 8.4.20 resolve: 1.22.1 - rollup: 2.79.1 + rollup: 3.8.1 + sass: 1.57.1 + terser: 5.16.1 optionalDependencies: fsevents: 2.3.2 dev: true - /vue-cropper/1.0.5: - resolution: {integrity: sha512-D4XXdqWmMWRLOIV9LIh7/mkH6OBOMQDFbRjwntkxmAtxOtwpC9U5ZZ6lSXw5F5cbd4g8znDjk6MuCwIL+fZSrA==} - dev: false - - /vue-demi/0.13.11_vue@3.2.44: + /vue-demi/0.13.11_vue@3.2.45: resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} engines: {node: '>=12'} hasBin: true @@ -7154,19 +5484,20 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.2.44 + vue: 3.2.45 + dev: false - /vue-eslint-parser/9.1.0_eslint@8.27.0: + /vue-eslint-parser/9.1.0_eslint@8.30.0: resolution: {integrity: sha512-NGn/iQy8/Wb7RrRa4aRkokyCZfOUWk19OP5HP6JEozQFX5AoS/t+Z0ZN7FY4LlmWc4FNI922V7cvX28zctN8dQ==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: debug: 4.3.4 - eslint: 8.27.0 + eslint: 8.30.0 eslint-scope: 7.1.1 eslint-visitor-keys: 3.3.0 - espree: 9.4.0 + espree: 9.4.1 esquery: 1.4.0 lodash: 4.17.21 semver: 7.3.8 @@ -7174,7 +5505,7 @@ packages: - supports-color dev: true - /vue-i18n/9.2.2_vue@3.2.44: + /vue-i18n/9.2.2_vue@3.2.45: resolution: {integrity: sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==} engines: {node: '>= 14'} peerDependencies: @@ -7183,93 +5514,69 @@ packages: '@intlify/core-base': 9.2.2 '@intlify/shared': 9.2.2 '@intlify/vue-devtools': 9.2.2 - '@vue/devtools-api': 6.4.3 - vue: 3.2.44 + '@vue/devtools-api': 6.4.5 + vue: 3.2.45 - /vue-router/4.1.6_vue@3.2.44: + /vue-router/4.1.6_vue@3.2.45: resolution: {integrity: sha512-DYWYwsG6xNPmLq/FmZn8Ip+qrhFEzA14EI12MsMgVxvHFDYvlr4NXpVF5hrRH1wVcDP8fGi5F4rxuJSl8/r+EQ==} peerDependencies: vue: ^3.2.0 dependencies: '@vue/devtools-api': 6.4.5 - vue: 3.2.44 + vue: 3.2.45 dev: false - /vue-template-compiler/2.7.10: - resolution: {integrity: sha512-QO+8R9YRq1Gudm8ZMdo/lImZLJVUIAM8c07Vp84ojdDAf8HmPJc7XB556PcXV218k2AkKznsRz6xB5uOjAC4EQ==} + /vue-template-compiler/2.7.14: + resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} dependencies: de-indent: 1.0.2 he: 1.2.0 dev: true - /vue-tsc/1.0.9_typescript@4.8.4: - resolution: {integrity: sha512-vRmHD1K6DmBymNhoHjQy/aYKTRQNLGOu2/ESasChG9Vy113K6CdP0NlhR0bzgFJfv2eFB9Ez/9L5kIciUajBxQ==} + /vue-tsc/1.0.16_typescript@4.9.4: + resolution: {integrity: sha512-yZaiJBbcKR1rSLhiF9KryAFH7R63po+N/invr2EAHGXxMzZksE5j1zyQKvrYiqK47ZHLAlCR+re/PHqWp/UzTg==} hasBin: true peerDependencies: typescript: '*' dependencies: - '@volar/vue-language-core': 1.0.9 - '@volar/vue-typescript': 1.0.9 - typescript: 4.8.4 + '@volar/vue-language-core': 1.0.16 + '@volar/vue-typescript': 1.0.16 + typescript: 4.9.4 dev: true - /vue-types/4.2.1_vue@3.2.44: - resolution: {integrity: sha512-DNQZmJuOvovLUIp0BENRkdnZHbI0V4e2mNvjAZOAXKD56YGvRchtUYOXA/XqTxdv7Ng5SJLZqRKRpAhm5NLaPQ==} - engines: {node: '>=12.16.0'} + /vue-types/5.0.2_vue@3.2.45: + resolution: {integrity: sha512-+/5hnQ65XOYqPs+tEUF8GGTJX95UFVH0wPQo71IJJYh5TKMfik2tGKTLkZ42JqAczANA9hGu5FrZmPgxn20nnA==} + engines: {node: '>=14.0.0'} peerDependencies: vue: ^2.0.0 || ^3.0.0 + peerDependenciesMeta: + vue: + optional: true dependencies: is-plain-object: 5.0.0 - vue: 3.2.44 + vue: 3.2.45 dev: false - /vue/3.2.44: - resolution: {integrity: sha512-nyNtFDh+0TpRgYCUVfPD1mJ9PpIsCPXaOF4DeGNIT5vQ4X23ykflGq3Sy2P+tEt1/pQZxZnAysuRKwyhNj+Cjw==} + /vue/3.2.45: + resolution: {integrity: sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==} dependencies: - '@vue/compiler-dom': 3.2.44 - '@vue/compiler-sfc': 3.2.44 - '@vue/runtime-dom': 3.2.44 - '@vue/server-renderer': 3.2.44_vue@3.2.44 - '@vue/shared': 3.2.44 - - /vxe-table/4.3.5_vue@3.2.44+xe-utils@3.5.7: - resolution: {integrity: sha512-JEvGAs7SBN1rWn5f2tkoRiXd/rAT7RfnDTTlFsHsTtASiUTKNTISI2WBsVeLkkNRTs0SXh6FgrYsIPO2soSBXA==} - peerDependencies: - vue: ^3.2.28 - xe-utils: ^3.5.0 - dependencies: - vue: 3.2.44 - xe-utils: 3.5.7 - dev: false - - /wcwidth/1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.3 - dev: true + '@vue/compiler-dom': 3.2.45 + '@vue/compiler-sfc': 3.2.45 + '@vue/runtime-dom': 3.2.45 + '@vue/server-renderer': 3.2.45_vue@3.2.45 + '@vue/shared': 3.2.45 /web-storage-cache/1.1.1: resolution: {integrity: sha512-D0MieGooOs8RpsrK+vnejXnvh4OOv/+lTFB35JRkJJQt+uOjPE08XpaE0QBLMTRu47B1KGT/Nq3Gbag3Orinzw==} dev: false - /webidl-conversions/3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true - /webpack-sources/3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} dev: true - /webpack-virtual-modules/0.4.5: - resolution: {integrity: sha512-8bWq0Iluiv9lVf9YaqWQ9+liNgXSHICm+rg544yRgGYaR8yXZTVBaHZkINZSB2yZSWo4b0F6MIxqJezVfOEAlg==} - dev: true - - /whatwg-url/5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 + /webpack-virtual-modules/0.5.0: + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} dev: true /which-module/2.0.0: @@ -7306,15 +5613,11 @@ packages: engines: {node: '>=0.10.0'} dev: true - /wordwrap/1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - /wrap-ansi/6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} dependencies: - ansi-styles: 4.3.0 + ansi-styles: registry.npmmirror.com/ansi-styles/4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 @@ -7383,7 +5686,7 @@ packages: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} dependencies: - camelcase: 5.3.1 + camelcase: registry.npmmirror.com/camelcase/5.3.1 decamelize: 1.2.0 dev: false @@ -7414,8 +5717,8 @@ packages: yargs-parser: 18.1.3 dev: false - /yargs/17.6.0: - resolution: {integrity: sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==} + /yargs/17.6.2: + resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} engines: {node: '>=12'} dependencies: cliui: 8.0.1 @@ -7437,8 +5740,1398 @@ packages: engines: {node: '>=10'} dev: true - /zrender/5.4.0: - resolution: {integrity: sha512-rOS09Z2HSVGFs2dn/TuYk5BlCaZcVe8UDLLjj1ySYF828LATKKdxuakSZMvrDz54yiKPDYVfjdKqcX8Jky3BIA==} + registry.npmmirror.com/@ampproject/remapping/2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.0.tgz} + name: '@ampproject/remapping' + version: 2.2.0 + engines: {node: '>=6.0.0'} dependencies: - tslib: 2.3.0 + '@jridgewell/gen-mapping': registry.npmmirror.com/@jridgewell/gen-mapping/0.1.1 + '@jridgewell/trace-mapping': registry.npmmirror.com/@jridgewell/trace-mapping/0.3.17 + dev: true + + registry.npmmirror.com/@antfu/utils/0.7.2: + resolution: {integrity: sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.2.tgz} + name: '@antfu/utils' + version: 0.7.2 + dev: true + + registry.npmmirror.com/@babel/code-frame/7.18.6: + resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.18.6.tgz} + name: '@babel/code-frame' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': registry.npmmirror.com/@babel/highlight/7.18.6 + dev: true + + registry.npmmirror.com/@babel/compat-data/7.20.1: + resolution: {integrity: sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.20.1.tgz} + name: '@babel/compat-data' + version: 7.20.1 + engines: {node: '>=6.9.0'} + dev: true + + registry.npmmirror.com/@babel/core/7.20.5: + resolution: {integrity: sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/core/-/core-7.20.5.tgz} + name: '@babel/core' + version: 7.20.5 + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': registry.npmmirror.com/@ampproject/remapping/2.2.0 + '@babel/code-frame': registry.npmmirror.com/@babel/code-frame/7.18.6 + '@babel/generator': registry.npmmirror.com/@babel/generator/7.20.5 + '@babel/helper-compilation-targets': registry.npmmirror.com/@babel/helper-compilation-targets/7.20.0_@babel+core@7.20.5 + '@babel/helper-module-transforms': registry.npmmirror.com/@babel/helper-module-transforms/7.20.2 + '@babel/helpers': registry.npmmirror.com/@babel/helpers/7.20.6 + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@babel/template': registry.npmmirror.com/@babel/template/7.18.10 + '@babel/traverse': registry.npmmirror.com/@babel/traverse/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + convert-source-map: registry.npmmirror.com/convert-source-map/1.9.0 + debug: 4.3.4 + gensync: registry.npmmirror.com/gensync/1.0.0-beta.2 + json5: registry.npmmirror.com/json5/2.2.1 + semver: registry.npmmirror.com/semver/6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/generator/7.20.5: + resolution: {integrity: sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/generator/-/generator-7.20.5.tgz} + name: '@babel/generator' + version: 7.20.5 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + '@jridgewell/gen-mapping': registry.npmmirror.com/@jridgewell/gen-mapping/0.3.2 + jsesc: registry.npmmirror.com/jsesc/2.5.2 + dev: true + + registry.npmmirror.com/@babel/helper-annotate-as-pure/7.18.6: + resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz} + name: '@babel/helper-annotate-as-pure' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-compilation-targets/7.20.0_@babel+core@7.20.5: + resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz} + id: registry.npmmirror.com/@babel/helper-compilation-targets/7.20.0 + name: '@babel/helper-compilation-targets' + version: 7.20.0 + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': registry.npmmirror.com/@babel/compat-data/7.20.1 + '@babel/core': registry.npmmirror.com/@babel/core/7.20.5 + '@babel/helper-validator-option': registry.npmmirror.com/@babel/helper-validator-option/7.18.6 + browserslist: registry.npmmirror.com/browserslist/4.21.4 + semver: registry.npmmirror.com/semver/6.3.0 + dev: true + + registry.npmmirror.com/@babel/helper-create-class-features-plugin/7.20.2_@babel+core@7.20.5: + resolution: {integrity: sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz} + id: registry.npmmirror.com/@babel/helper-create-class-features-plugin/7.20.2 + name: '@babel/helper-create-class-features-plugin' + version: 7.20.2 + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': registry.npmmirror.com/@babel/core/7.20.5 + '@babel/helper-annotate-as-pure': registry.npmmirror.com/@babel/helper-annotate-as-pure/7.18.6 + '@babel/helper-environment-visitor': registry.npmmirror.com/@babel/helper-environment-visitor/7.18.9 + '@babel/helper-function-name': registry.npmmirror.com/@babel/helper-function-name/7.19.0 + '@babel/helper-member-expression-to-functions': registry.npmmirror.com/@babel/helper-member-expression-to-functions/7.18.9 + '@babel/helper-optimise-call-expression': registry.npmmirror.com/@babel/helper-optimise-call-expression/7.18.6 + '@babel/helper-replace-supers': registry.npmmirror.com/@babel/helper-replace-supers/7.19.1 + '@babel/helper-split-export-declaration': registry.npmmirror.com/@babel/helper-split-export-declaration/7.18.6 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/helper-environment-visitor/7.18.9: + resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz} + name: '@babel/helper-environment-visitor' + version: 7.18.9 + engines: {node: '>=6.9.0'} + dev: true + + registry.npmmirror.com/@babel/helper-function-name/7.19.0: + resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz} + name: '@babel/helper-function-name' + version: 7.19.0 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': registry.npmmirror.com/@babel/template/7.18.10 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-hoist-variables/7.18.6: + resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz} + name: '@babel/helper-hoist-variables' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-member-expression-to-functions/7.18.9: + resolution: {integrity: sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz} + name: '@babel/helper-member-expression-to-functions' + version: 7.18.9 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-module-imports/7.18.6: + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz} + name: '@babel/helper-module-imports' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-module-transforms/7.20.2: + resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz} + name: '@babel/helper-module-transforms' + version: 7.20.2 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': registry.npmmirror.com/@babel/helper-environment-visitor/7.18.9 + '@babel/helper-module-imports': registry.npmmirror.com/@babel/helper-module-imports/7.18.6 + '@babel/helper-simple-access': registry.npmmirror.com/@babel/helper-simple-access/7.20.2 + '@babel/helper-split-export-declaration': registry.npmmirror.com/@babel/helper-split-export-declaration/7.18.6 + '@babel/helper-validator-identifier': registry.npmmirror.com/@babel/helper-validator-identifier/7.19.1 + '@babel/template': registry.npmmirror.com/@babel/template/7.18.10 + '@babel/traverse': registry.npmmirror.com/@babel/traverse/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/helper-optimise-call-expression/7.18.6: + resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz} + name: '@babel/helper-optimise-call-expression' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-plugin-utils/7.20.2: + resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz} + name: '@babel/helper-plugin-utils' + version: 7.20.2 + engines: {node: '>=6.9.0'} + dev: true + + registry.npmmirror.com/@babel/helper-replace-supers/7.19.1: + resolution: {integrity: sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz} + name: '@babel/helper-replace-supers' + version: 7.19.1 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': registry.npmmirror.com/@babel/helper-environment-visitor/7.18.9 + '@babel/helper-member-expression-to-functions': registry.npmmirror.com/@babel/helper-member-expression-to-functions/7.18.9 + '@babel/helper-optimise-call-expression': registry.npmmirror.com/@babel/helper-optimise-call-expression/7.18.6 + '@babel/traverse': registry.npmmirror.com/@babel/traverse/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/helper-simple-access/7.20.2: + resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz} + name: '@babel/helper-simple-access' + version: 7.20.2 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-split-export-declaration/7.18.6: + resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz} + name: '@babel/helper-split-export-declaration' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/helper-string-parser/7.19.4: + resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz} + name: '@babel/helper-string-parser' + version: 7.19.4 + engines: {node: '>=6.9.0'} + + registry.npmmirror.com/@babel/helper-validator-identifier/7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz} + name: '@babel/helper-validator-identifier' + version: 7.19.1 + engines: {node: '>=6.9.0'} + + registry.npmmirror.com/@babel/helper-validator-option/7.18.6: + resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz} + name: '@babel/helper-validator-option' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dev: true + + registry.npmmirror.com/@babel/helpers/7.20.6: + resolution: {integrity: sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/helpers/-/helpers-7.20.6.tgz} + name: '@babel/helpers' + version: 7.20.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': registry.npmmirror.com/@babel/template/7.18.10 + '@babel/traverse': registry.npmmirror.com/@babel/traverse/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/highlight/7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/highlight/-/highlight-7.18.6.tgz} + name: '@babel/highlight' + version: 7.18.6 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': registry.npmmirror.com/@babel/helper-validator-identifier/7.19.1 + chalk: 2.4.2 + js-tokens: registry.npmmirror.com/js-tokens/4.0.0 + dev: true + + registry.npmmirror.com/@babel/parser/7.20.5: + resolution: {integrity: sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/parser/-/parser-7.20.5.tgz} + name: '@babel/parser' + version: 7.20.5 + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + + registry.npmmirror.com/@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.20.5: + resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz} + id: registry.npmmirror.com/@babel/plugin-syntax-jsx/7.18.6 + name: '@babel/plugin-syntax-jsx' + version: 7.18.6 + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': registry.npmmirror.com/@babel/core/7.20.5 + '@babel/helper-plugin-utils': registry.npmmirror.com/@babel/helper-plugin-utils/7.20.2 + dev: true + + registry.npmmirror.com/@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.20.5: + resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz} + id: registry.npmmirror.com/@babel/plugin-syntax-typescript/7.20.0 + name: '@babel/plugin-syntax-typescript' + version: 7.20.0 + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': registry.npmmirror.com/@babel/core/7.20.5 + '@babel/helper-plugin-utils': registry.npmmirror.com/@babel/helper-plugin-utils/7.20.2 + dev: true + + registry.npmmirror.com/@babel/plugin-transform-typescript/7.20.2_@babel+core@7.20.5: + resolution: {integrity: sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.2.tgz} + id: registry.npmmirror.com/@babel/plugin-transform-typescript/7.20.2 + name: '@babel/plugin-transform-typescript' + version: 7.20.2 + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': registry.npmmirror.com/@babel/core/7.20.5 + '@babel/helper-create-class-features-plugin': registry.npmmirror.com/@babel/helper-create-class-features-plugin/7.20.2_@babel+core@7.20.5 + '@babel/helper-plugin-utils': registry.npmmirror.com/@babel/helper-plugin-utils/7.20.2 + '@babel/plugin-syntax-typescript': registry.npmmirror.com/@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.20.5 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/standalone/7.20.6: + resolution: {integrity: sha512-u5at/CbBLETf7kx2LOY4XdhseD79Y099WZKAOMXeT8qvd9OSR515my2UNBBLY4qIht/Qi9KySeQHQwQwxJN4Sw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/standalone/-/standalone-7.20.6.tgz} + name: '@babel/standalone' + version: 7.20.6 + engines: {node: '>=6.9.0'} + dev: true + + registry.npmmirror.com/@babel/template/7.18.10: + resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/template/-/template-7.18.10.tgz} + name: '@babel/template' + version: 7.18.10 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': registry.npmmirror.com/@babel/code-frame/7.18.6 + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + dev: true + + registry.npmmirror.com/@babel/traverse/7.20.1: + resolution: {integrity: sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/traverse/-/traverse-7.20.1.tgz} + name: '@babel/traverse' + version: 7.20.1 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': registry.npmmirror.com/@babel/code-frame/7.18.6 + '@babel/generator': registry.npmmirror.com/@babel/generator/7.20.5 + '@babel/helper-environment-visitor': registry.npmmirror.com/@babel/helper-environment-visitor/7.18.9 + '@babel/helper-function-name': registry.npmmirror.com/@babel/helper-function-name/7.19.0 + '@babel/helper-hoist-variables': registry.npmmirror.com/@babel/helper-hoist-variables/7.18.6 + '@babel/helper-split-export-declaration': registry.npmmirror.com/@babel/helper-split-export-declaration/7.18.6 + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/traverse/7.20.5: + resolution: {integrity: sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/traverse/-/traverse-7.20.5.tgz} + name: '@babel/traverse' + version: 7.20.5 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': registry.npmmirror.com/@babel/code-frame/7.18.6 + '@babel/generator': registry.npmmirror.com/@babel/generator/7.20.5 + '@babel/helper-environment-visitor': registry.npmmirror.com/@babel/helper-environment-visitor/7.18.9 + '@babel/helper-function-name': registry.npmmirror.com/@babel/helper-function-name/7.19.0 + '@babel/helper-hoist-variables': registry.npmmirror.com/@babel/helper-hoist-variables/7.18.6 + '@babel/helper-split-export-declaration': registry.npmmirror.com/@babel/helper-split-export-declaration/7.18.6 + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.5 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@babel/types/7.20.2: + resolution: {integrity: sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/types/-/types-7.20.2.tgz} + name: '@babel/types' + version: 7.20.2 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': registry.npmmirror.com/@babel/helper-string-parser/7.19.4 + '@babel/helper-validator-identifier': registry.npmmirror.com/@babel/helper-validator-identifier/7.19.1 + to-fast-properties: registry.npmmirror.com/to-fast-properties/2.0.0 + dev: true + + registry.npmmirror.com/@babel/types/7.20.5: + resolution: {integrity: sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/types/-/types-7.20.5.tgz} + name: '@babel/types' + version: 7.20.5 + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': registry.npmmirror.com/@babel/helper-string-parser/7.19.4 + '@babel/helper-validator-identifier': registry.npmmirror.com/@babel/helper-validator-identifier/7.19.1 + to-fast-properties: registry.npmmirror.com/to-fast-properties/2.0.0 + + registry.npmmirror.com/@iconify/iconify/2.1.2: + resolution: {integrity: sha512-QcUzFeEWkE/mW+BVtEGmcWATClcCOIJFiYUD/PiCWuTcdEA297o8D4oN6Ra44WrNOHu1wqNW4J0ioaDIiqaFOQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@iconify/iconify/-/iconify-2.1.2.tgz} + name: '@iconify/iconify' + version: 2.1.2 + dependencies: + cross-fetch: registry.npmmirror.com/cross-fetch/3.1.5 + transitivePeerDependencies: + - encoding + dev: true + + registry.npmmirror.com/@iconify/iconify/3.0.1: + resolution: {integrity: sha512-OPqVBTh8YsfrYZRVFv3OkmFNLqacM0dy/Oiw1h2wO+RZW5LieNGHlG2f9pzaeVRFWbEB8LHTeo8mcwgUTUbibQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@iconify/iconify/-/iconify-3.0.1.tgz} + name: '@iconify/iconify' + version: 3.0.1 + dependencies: + '@iconify/types': 2.0.0 + dev: true + + registry.npmmirror.com/@jridgewell/gen-mapping/0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz} + name: '@jridgewell/gen-mapping' + version: 0.1.1 + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': registry.npmmirror.com/@jridgewell/set-array/1.1.2 + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 + dev: true + + registry.npmmirror.com/@jridgewell/gen-mapping/0.3.2: + resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz} + name: '@jridgewell/gen-mapping' + version: 0.3.2 + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': registry.npmmirror.com/@jridgewell/set-array/1.1.2 + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 + '@jridgewell/trace-mapping': registry.npmmirror.com/@jridgewell/trace-mapping/0.3.17 + dev: true + + registry.npmmirror.com/@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz} + name: '@jridgewell/resolve-uri' + version: 3.1.0 + engines: {node: '>=6.0.0'} + dev: true + + registry.npmmirror.com/@jridgewell/set-array/1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz} + name: '@jridgewell/set-array' + version: 1.1.2 + engines: {node: '>=6.0.0'} + dev: true + + registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz} + name: '@jridgewell/sourcemap-codec' + version: 1.4.14 + dev: true + + registry.npmmirror.com/@jridgewell/trace-mapping/0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz} + name: '@jridgewell/trace-mapping' + version: 0.3.17 + dependencies: + '@jridgewell/resolve-uri': registry.npmmirror.com/@jridgewell/resolve-uri/3.1.0 + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 + dev: true + + registry.npmmirror.com/@jridgewell/trace-mapping/0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz} + name: '@jridgewell/trace-mapping' + version: 0.3.9 + dependencies: + '@jridgewell/resolve-uri': registry.npmmirror.com/@jridgewell/resolve-uri/3.1.0 + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 + dev: true + + registry.npmmirror.com/@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz} + name: '@nodelib/fs.stat' + version: 2.0.5 + engines: {node: '>= 8'} + dev: true + + registry.npmmirror.com/@purge-icons/core/0.9.1: + resolution: {integrity: sha512-sx8/a30MbbqQVEqhuMPE1wJpdVRRbEmwEPZpFzVkcDixzX4p+R2A0WVxqkb0xfHUBAVQwrSE2SeAyniIQLqbLw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@purge-icons/core/-/core-0.9.1.tgz} + name: '@purge-icons/core' + version: 0.9.1 + dependencies: + '@iconify/iconify': registry.npmmirror.com/@iconify/iconify/2.1.2 + axios: registry.npmmirror.com/axios/0.26.1_debug@4.3.4 + debug: 4.3.4 + fast-glob: registry.npmmirror.com/fast-glob/3.2.12 + fs-extra: registry.npmmirror.com/fs-extra/10.1.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + registry.npmmirror.com/@purge-icons/generated/0.9.0: + resolution: {integrity: sha512-s2t+1oVtGDV6KtqfCXtUOhxfeYvOdDF90IVm+nMs/6bUP0HeGZLslguuL/AibpwtfL4FA/oCsIu/RhwapgAdJw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@purge-icons/generated/-/generated-0.9.0.tgz} + name: '@purge-icons/generated' + version: 0.9.0 + dependencies: + '@iconify/iconify': registry.npmmirror.com/@iconify/iconify/3.0.1 + dev: true + + registry.npmmirror.com/@vitejs/plugin-legacy/3.0.1_terser@5.16.1+vite@4.0.3: + resolution: {integrity: sha512-XCtEjxoR3rmy000ujYRBp5kggWqzHz9+F20/yIMUWOzbvu0+KW1e14Fvb8h7SpNn+bfjGW1RiAs1Vrgb7Js+iQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-3.0.1.tgz} + id: registry.npmmirror.com/@vitejs/plugin-legacy/3.0.1 + name: '@vitejs/plugin-legacy' + version: 3.0.1 + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + terser: ^5.4.0 + vite: ^4.0.0 + dependencies: + '@babel/standalone': registry.npmmirror.com/@babel/standalone/7.20.6 + core-js: registry.npmmirror.com/core-js/3.26.1 + magic-string: registry.npmmirror.com/magic-string/0.27.0 + regenerator-runtime: registry.npmmirror.com/regenerator-runtime/0.13.11 + systemjs: registry.npmmirror.com/systemjs/6.13.0 + terser: 5.16.1 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce + dev: true + + registry.npmmirror.com/@vitejs/plugin-vue-jsx/3.0.0_vite@4.0.3+vue@3.2.45: + resolution: {integrity: sha512-vurkuzgac5SYuxd2HUZqAFAWGTF10diKBwJNbCvnWijNZfXd+7jMtqjPFbGt7idOJUn584fP1Ar9j/GN2jQ3Ew==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-3.0.0.tgz} + id: registry.npmmirror.com/@vitejs/plugin-vue-jsx/3.0.0 + name: '@vitejs/plugin-vue-jsx' + version: 3.0.0 + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 + vue: ^3.0.0 + dependencies: + '@babel/core': registry.npmmirror.com/@babel/core/7.20.5 + '@babel/plugin-transform-typescript': registry.npmmirror.com/@babel/plugin-transform-typescript/7.20.2_@babel+core@7.20.5 + '@vue/babel-plugin-jsx': registry.npmmirror.com/@vue/babel-plugin-jsx/1.1.1_@babel+core@7.20.5 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce + vue: 3.2.45 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@vitejs/plugin-vue/4.0.0_vite@4.0.3+vue@3.2.45: + resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz} + id: registry.npmmirror.com/@vitejs/plugin-vue/4.0.0 + name: '@vitejs/plugin-vue' + version: 4.0.0 + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 + vue: ^3.2.25 + dependencies: + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce + vue: 3.2.45 + dev: true + + registry.npmmirror.com/@vue/babel-helper-vue-transform-on/1.0.2: + resolution: {integrity: sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz} + name: '@vue/babel-helper-vue-transform-on' + version: 1.0.2 + dev: true + + registry.npmmirror.com/@vue/babel-plugin-jsx/1.1.1_@babel+core@7.20.5: + resolution: {integrity: sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz} + id: registry.npmmirror.com/@vue/babel-plugin-jsx/1.1.1 + name: '@vue/babel-plugin-jsx' + version: 1.1.1 + dependencies: + '@babel/helper-module-imports': registry.npmmirror.com/@babel/helper-module-imports/7.18.6 + '@babel/plugin-syntax-jsx': registry.npmmirror.com/@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.20.5 + '@babel/template': registry.npmmirror.com/@babel/template/7.18.10 + '@babel/traverse': registry.npmmirror.com/@babel/traverse/7.20.1 + '@babel/types': registry.npmmirror.com/@babel/types/7.20.2 + '@vue/babel-helper-vue-transform-on': registry.npmmirror.com/@vue/babel-helper-vue-transform-on/1.0.2 + camelcase: registry.npmmirror.com/camelcase/6.3.0 + html-tags: registry.npmmirror.com/html-tags/3.2.0 + svg-tags: registry.npmmirror.com/svg-tags/1.0.0 + transitivePeerDependencies: + - '@babel/core' + - supports-color + dev: true + + registry.npmmirror.com/@vue/compiler-core/3.2.45: + resolution: {integrity: sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.45.tgz} + name: '@vue/compiler-core' + version: 3.2.45 + dependencies: + '@babel/parser': registry.npmmirror.com/@babel/parser/7.20.5 + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 + estree-walker: registry.npmmirror.com/estree-walker/2.0.2 + source-map: 0.6.1 + + registry.npmmirror.com/@vue/compiler-dom/3.2.45: + resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.45.tgz} + name: '@vue/compiler-dom' + version: 3.2.45 + dependencies: + '@vue/compiler-core': registry.npmmirror.com/@vue/compiler-core/3.2.45 + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 + + registry.npmmirror.com/@vue/devtools-api/6.4.5: + resolution: {integrity: sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.4.5.tgz} + name: '@vue/devtools-api' + version: 6.4.5 + dev: false + + registry.npmmirror.com/@vue/reactivity/3.2.45: + resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.45.tgz} + name: '@vue/reactivity' + version: 3.2.45 + dependencies: + '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.45 + + registry.npmmirror.com/@vue/shared/3.2.45: + resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vue/shared/-/shared-3.2.45.tgz} + name: '@vue/shared' + version: 3.2.45 + + registry.npmmirror.com/@windicss/config/1.8.10: + resolution: {integrity: sha512-O9SsC110b1Ik3YYa4Ck/0TWuCo7YFfA9KDrwD5sAeqscT5COIGK1HszdCT3oh0MJFej2wNrvpfyW9h6yQaW6PA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@windicss/config/-/config-1.8.10.tgz} + name: '@windicss/config' + version: 1.8.10 + dependencies: + debug: 4.3.4 + jiti: registry.npmmirror.com/jiti/1.16.0 + windicss: registry.npmmirror.com/windicss/3.5.6 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@windicss/plugin-utils/1.8.10: + resolution: {integrity: sha512-Phqk5OW1w+Mv+ry6t7BzAeDq3aMhbI94gR49j9vQCufFfDGCHndhhjtMK0sBv+NPJUsIAIh6qayb1iwBCXUGrw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@windicss/plugin-utils/-/plugin-utils-1.8.10.tgz} + name: '@windicss/plugin-utils' + version: 1.8.10 + dependencies: + '@antfu/utils': registry.npmmirror.com/@antfu/utils/0.7.2 + '@windicss/config': registry.npmmirror.com/@windicss/config/1.8.10 + debug: 4.3.4 + fast-glob: registry.npmmirror.com/fast-glob/3.2.12 + magic-string: registry.npmmirror.com/magic-string/0.27.0 + micromatch: registry.npmmirror.com/micromatch/4.0.5 + windicss: registry.npmmirror.com/windicss/3.5.6 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/ansi-styles/2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz} + name: ansi-styles + version: 2.2.1 + engines: {node: '>=0.10.0'} + dev: true + + registry.npmmirror.com/ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz} + name: ansi-styles + version: 3.2.1 + engines: {node: '>=4'} + dependencies: + color-convert: registry.npmmirror.com/color-convert/1.9.3 + dev: true + + registry.npmmirror.com/ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz} + name: ansi-styles + version: 4.3.0 + engines: {node: '>=8'} + dependencies: + color-convert: registry.npmmirror.com/color-convert/2.0.1 + + registry.npmmirror.com/axios/0.26.1_debug@4.3.4: + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz} + id: registry.npmmirror.com/axios/0.26.1 + name: axios + version: 0.26.1 + dependencies: + follow-redirects: registry.npmmirror.com/follow-redirects/1.15.2_debug@4.3.4 + transitivePeerDependencies: + - debug + dev: true + + registry.npmmirror.com/braces/2.3.2: + resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/braces/-/braces-2.3.2.tgz} + name: braces + version: 2.3.2 + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + array-unique: 0.3.2 + extend-shallow: 2.0.1 + fill-range: registry.npmmirror.com/fill-range/4.0.0 + isobject: 3.0.1 + repeat-element: 1.1.4 + snapdragon: 0.8.2 + snapdragon-node: 2.1.1 + split-string: 3.1.0 + to-regex: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz} + name: braces + version: 3.0.2 + engines: {node: '>=8'} + dependencies: + fill-range: registry.npmmirror.com/fill-range/7.0.1 + dev: true + + registry.npmmirror.com/browserslist/4.21.4: + resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/browserslist/-/browserslist-4.21.4.tgz} + name: browserslist + version: 4.21.4 + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: registry.npmmirror.com/caniuse-lite/1.0.30001431 + electron-to-chromium: registry.npmmirror.com/electron-to-chromium/1.4.284 + node-releases: registry.npmmirror.com/node-releases/2.0.6 + update-browserslist-db: registry.npmmirror.com/update-browserslist-db/1.0.10_browserslist@4.21.4 + dev: true + + registry.npmmirror.com/camelcase/5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz} + name: camelcase + version: 5.3.1 + engines: {node: '>=6'} + + registry.npmmirror.com/camelcase/6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz} + name: camelcase + version: 6.3.0 + engines: {node: '>=10'} + dev: true + + registry.npmmirror.com/caniuse-lite/1.0.30001431: + resolution: {integrity: sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz} + name: caniuse-lite + version: 1.0.30001431 + dev: true + + registry.npmmirror.com/color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz} + name: color-convert + version: 1.9.3 + dependencies: + color-name: registry.npmmirror.com/color-name/1.1.3 + dev: true + + registry.npmmirror.com/color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz} + name: color-convert + version: 2.0.1 + engines: {node: '>=7.0.0'} + dependencies: + color-name: registry.npmmirror.com/color-name/1.1.4 + + registry.npmmirror.com/color-name/1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz} + name: color-name + version: 1.1.3 + dev: true + + registry.npmmirror.com/color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz} + name: color-name + version: 1.1.4 + + registry.npmmirror.com/convert-source-map/1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz} + name: convert-source-map + version: 1.9.0 + dev: true + + registry.npmmirror.com/core-js/3.26.1: + resolution: {integrity: sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/core-js/-/core-js-3.26.1.tgz} + name: core-js + version: 3.26.1 + requiresBuild: true + dev: true + + registry.npmmirror.com/cross-fetch/3.1.5: + resolution: {integrity: sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.5.tgz} + name: cross-fetch + version: 3.1.5 + dependencies: + node-fetch: registry.npmmirror.com/node-fetch/2.6.7 + transitivePeerDependencies: + - encoding + dev: true + + registry.npmmirror.com/debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz} + name: debug + version: 4.3.4 + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: registry.npmmirror.com/ms/2.1.2 + dev: true + + registry.npmmirror.com/echarts/5.4.1: + resolution: {integrity: sha512-9ltS3M2JB0w2EhcYjCdmtrJ+6haZcW6acBolMGIuf01Hql1yrIV01L1aRj7jsaaIULJslEP9Z3vKlEmnJaWJVQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/echarts/-/echarts-5.4.1.tgz} + name: echarts + version: 5.4.1 + dependencies: + tslib: registry.npmmirror.com/tslib/2.3.0 + zrender: registry.npmmirror.com/zrender/5.4.1 + dev: false + + registry.npmmirror.com/electron-to-chromium/1.4.284: + resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz} + name: electron-to-chromium + version: 1.4.284 + dev: true + + registry.npmmirror.com/escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz} + name: escalade + version: 3.1.1 + engines: {node: '>=6'} + dev: true + + registry.npmmirror.com/estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz} + name: estree-walker + version: 2.0.2 + + registry.npmmirror.com/fast-glob/3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz} + name: fast-glob + version: 3.2.12 + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': registry.npmmirror.com/@nodelib/fs.stat/2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: registry.npmmirror.com/merge2/1.4.1 + micromatch: registry.npmmirror.com/micromatch/4.0.5 + dev: true + + registry.npmmirror.com/fill-range/4.0.0: + resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fill-range/-/fill-range-4.0.0.tgz} + name: fill-range + version: 4.0.0 + engines: {node: '>=0.10.0'} + dependencies: + extend-shallow: 2.0.1 + is-number: registry.npmmirror.com/is-number/3.0.0 + repeat-string: 1.6.1 + to-regex-range: registry.npmmirror.com/to-regex-range/2.1.1 + dev: true + + registry.npmmirror.com/fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz} + name: fill-range + version: 7.0.1 + engines: {node: '>=8'} + dependencies: + to-regex-range: registry.npmmirror.com/to-regex-range/5.0.1 + dev: true + + registry.npmmirror.com/follow-redirects/1.15.2_debug@4.3.4: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz} + id: registry.npmmirror.com/follow-redirects/1.15.2 + name: follow-redirects + version: 1.15.2 + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dependencies: + debug: 4.3.4 + dev: true + + registry.npmmirror.com/fs-extra/10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz} + name: fs-extra + version: 10.1.0 + engines: {node: '>=12'} + dependencies: + graceful-fs: registry.npmmirror.com/graceful-fs/4.2.10 + jsonfile: registry.npmmirror.com/jsonfile/6.1.0 + universalify: registry.npmmirror.com/universalify/2.0.0 + dev: true + + registry.npmmirror.com/function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz} + name: function-bind + version: 1.1.1 + + registry.npmmirror.com/gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz} + name: gensync + version: 1.0.0-beta.2 + engines: {node: '>=6.9.0'} + dev: true + + registry.npmmirror.com/graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz} + name: graceful-fs + version: 4.2.10 + dev: true + + registry.npmmirror.com/has-flag/1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/has-flag/-/has-flag-1.0.0.tgz} + name: has-flag + version: 1.0.0 + engines: {node: '>=0.10.0'} + dev: true + + registry.npmmirror.com/has-flag/3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz} + name: has-flag + version: 3.0.0 + engines: {node: '>=4'} + dev: true + + registry.npmmirror.com/has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/has/-/has-1.0.3.tgz} + name: has + version: 1.0.3 + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: registry.npmmirror.com/function-bind/1.1.1 + + registry.npmmirror.com/html-tags/3.2.0: + resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/html-tags/-/html-tags-3.2.0.tgz} + name: html-tags + version: 3.2.0 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-core-module/-/is-core-module-2.11.0.tgz} + name: is-core-module + version: 2.11.0 + dependencies: + has: registry.npmmirror.com/has/1.0.3 + dev: true + + registry.npmmirror.com/is-number/3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-number/-/is-number-3.0.0.tgz} + name: is-number + version: 3.0.0 + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + registry.npmmirror.com/is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz} + name: is-number + version: 7.0.0 + engines: {node: '>=0.12.0'} + dev: true + + registry.npmmirror.com/jiti/1.16.0: + resolution: {integrity: sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/jiti/-/jiti-1.16.0.tgz} + name: jiti + version: 1.16.0 + hasBin: true + dev: true + + registry.npmmirror.com/js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz} + name: js-tokens + version: 4.0.0 + dev: true + + registry.npmmirror.com/jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz} + name: jsesc + version: 2.5.2 + engines: {node: '>=4'} + hasBin: true + dev: true + + registry.npmmirror.com/json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/json5/-/json5-2.2.1.tgz} + name: json5 + version: 2.2.1 + engines: {node: '>=6'} + hasBin: true + dev: true + + registry.npmmirror.com/jsonfile/6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz} + name: jsonfile + version: 6.1.0 + dependencies: + universalify: registry.npmmirror.com/universalify/2.0.0 + optionalDependencies: + graceful-fs: 4.2.10 + dev: true + + registry.npmmirror.com/kolorist/1.6.0: + resolution: {integrity: sha512-dLkz37Ab97HWMx9KTes3Tbi3D1ln9fCAy2zr2YVExJasDRPGRaKcoE4fycWNtnCAJfjFqe0cnY+f8KT2JePEXQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/kolorist/-/kolorist-1.6.0.tgz} + name: kolorist + version: 1.6.0 + dev: true + + registry.npmmirror.com/lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz} + name: lru-cache + version: 6.0.0 + engines: {node: '>=10'} + dependencies: + yallist: registry.npmmirror.com/yallist/4.0.0 + dev: true + + registry.npmmirror.com/magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz} + name: magic-string + version: 0.25.9 + dependencies: + sourcemap-codec: 1.4.8 + + registry.npmmirror.com/magic-string/0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/magic-string/-/magic-string-0.27.0.tgz} + name: magic-string + version: 0.27.0 + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': registry.npmmirror.com/@jridgewell/sourcemap-codec/1.4.14 + dev: true + + registry.npmmirror.com/merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz} + name: merge2 + version: 1.4.1 + engines: {node: '>= 8'} + dev: true + + registry.npmmirror.com/micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz} + name: micromatch + version: 4.0.5 + engines: {node: '>=8.6'} + dependencies: + braces: registry.npmmirror.com/braces/3.0.2 + picomatch: registry.npmmirror.com/picomatch/2.3.1 + dev: true + + registry.npmmirror.com/ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz} + name: ms + version: 2.1.2 + dev: true + + registry.npmmirror.com/nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz} + name: nanoid + version: 3.3.4 + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + registry.npmmirror.com/node-fetch/2.6.7: + resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz} + name: node-fetch + version: 2.6.7 + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: registry.npmmirror.com/whatwg-url/5.0.0 + dev: true + + registry.npmmirror.com/node-releases/2.0.6: + resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/node-releases/-/node-releases-2.0.6.tgz} + name: node-releases + version: 2.0.6 + dev: true + + registry.npmmirror.com/picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz} + name: picocolors + version: 1.0.0 + + registry.npmmirror.com/picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz} + name: picomatch + version: 2.3.1 + engines: {node: '>=8.6'} + dev: true + + registry.npmmirror.com/pinia/2.0.28_prq2uz4lho2pwp6irk4cfkrxwu: + resolution: {integrity: sha512-YClq9DkqCblq9rlyUual7ezMu/iICWdBtfJrDt4oWU9Zxpijyz7xB2xTwx57DaBQ96UGvvTMORzALr+iO5PVMw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pinia/-/pinia-2.0.28.tgz} + id: registry.npmmirror.com/pinia/2.0.28 + name: pinia + version: 2.0.28 + peerDependencies: + '@vue/composition-api': ^1.4.0 + typescript: '>=4.4.4' + vue: ^2.6.14 || ^3.2.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + typescript: + optional: true + dependencies: + '@vue/devtools-api': registry.npmmirror.com/@vue/devtools-api/6.4.5 + typescript: 4.9.4 + vue: 3.2.45 + vue-demi: registry.npmmirror.com/vue-demi/0.13.11_vue@3.2.45 + dev: false + + registry.npmmirror.com/postcss/5.2.18: + resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/postcss/-/postcss-5.2.18.tgz} + name: postcss + version: 5.2.18 + engines: {node: '>=0.12'} + dependencies: + chalk: 1.1.3 + js-base64: 2.6.4 + source-map: 0.5.7 + supports-color: registry.npmmirror.com/supports-color/3.2.3 + dev: true + + registry.npmmirror.com/postcss/8.4.20: + resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/postcss/-/postcss-8.4.20.tgz} + name: postcss + version: 8.4.20 + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: registry.npmmirror.com/nanoid/3.3.4 + picocolors: registry.npmmirror.com/picocolors/1.0.0 + source-map-js: registry.npmmirror.com/source-map-js/1.0.2 + + registry.npmmirror.com/regenerator-runtime/0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz} + name: regenerator-runtime + version: 0.13.11 + + registry.npmmirror.com/rollup-plugin-purge-icons/0.9.1: + resolution: {integrity: sha512-hRDKBsPUz47UMdBufki2feTmBF2ClEJlYqL7N6vpVAHSLd7V2BJUaNKOF7YYbLMofVVF+9hm44YSkYO6k9hUgg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rollup-plugin-purge-icons/-/rollup-plugin-purge-icons-0.9.1.tgz} + name: rollup-plugin-purge-icons + version: 0.9.1 + engines: {node: '>= 12'} + dependencies: + '@purge-icons/core': registry.npmmirror.com/@purge-icons/core/0.9.1 + '@purge-icons/generated': registry.npmmirror.com/@purge-icons/generated/0.9.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + registry.npmmirror.com/semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz} + name: semver + version: 6.3.0 + hasBin: true + dev: true + + registry.npmmirror.com/semver/7.3.7: + resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz} + name: semver + version: 7.3.7 + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: registry.npmmirror.com/lru-cache/6.0.0 + dev: true + + registry.npmmirror.com/semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/semver/-/semver-7.3.8.tgz} + name: semver + version: 7.3.8 + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: registry.npmmirror.com/lru-cache/6.0.0 + dev: true + + registry.npmmirror.com/source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz} + name: source-map-js + version: 1.0.2 + engines: {node: '>=0.10.0'} + + registry.npmmirror.com/supports-color/2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/supports-color/-/supports-color-2.0.0.tgz} + name: supports-color + version: 2.0.0 + engines: {node: '>=0.8.0'} + dev: true + + registry.npmmirror.com/supports-color/3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/supports-color/-/supports-color-3.2.3.tgz} + name: supports-color + version: 3.2.3 + engines: {node: '>=0.8.0'} + dependencies: + has-flag: registry.npmmirror.com/has-flag/1.0.0 + dev: true + + registry.npmmirror.com/supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz} + name: supports-color + version: 5.5.0 + engines: {node: '>=4'} + dependencies: + has-flag: registry.npmmirror.com/has-flag/3.0.0 + dev: true + + registry.npmmirror.com/svg-tags/1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz} + name: svg-tags + version: 1.0.0 + dev: true + + registry.npmmirror.com/systemjs/6.13.0: + resolution: {integrity: sha512-P3cgh2bpaPvAO2NE3uRp/n6hmk4xPX4DQf+UzTlCAycssKdqhp6hjw+ENWe+aUS7TogKRFtptMosTSFeC6R55g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/systemjs/-/systemjs-6.13.0.tgz} + name: systemjs + version: 6.13.0 + dev: true + + registry.npmmirror.com/to-fast-properties/2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz} + name: to-fast-properties + version: 2.0.0 + engines: {node: '>=4'} + + registry.npmmirror.com/to-regex-range/2.1.1: + resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/to-regex-range/-/to-regex-range-2.1.1.tgz} + name: to-regex-range + version: 2.1.1 + engines: {node: '>=0.10.0'} + dependencies: + is-number: registry.npmmirror.com/is-number/3.0.0 + repeat-string: 1.6.1 + dev: true + + registry.npmmirror.com/to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz} + name: to-regex-range + version: 5.0.1 + engines: {node: '>=8.0'} + dependencies: + is-number: registry.npmmirror.com/is-number/7.0.0 + dev: true + + registry.npmmirror.com/tr46/0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz} + name: tr46 + version: 0.0.3 + dev: true + + registry.npmmirror.com/tslib/2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz} + name: tslib + version: 2.3.0 + dev: false + + registry.npmmirror.com/tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tslib/-/tslib-2.4.1.tgz} + name: tslib + version: 2.4.1 + dev: true + + registry.npmmirror.com/universalify/2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/universalify/-/universalify-2.0.0.tgz} + name: universalify + version: 2.0.0 + engines: {node: '>= 10.0.0'} + dev: true + + registry.npmmirror.com/update-browserslist-db/1.0.10_browserslist@4.21.4: + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz} + id: registry.npmmirror.com/update-browserslist-db/1.0.10 + name: update-browserslist-db + version: 1.0.10 + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: registry.npmmirror.com/browserslist/4.21.4 + escalade: registry.npmmirror.com/escalade/3.1.1 + picocolors: 1.0.0 + dev: true + + registry.npmmirror.com/vite-plugin-purge-icons/0.9.2_vite@4.0.3: + resolution: {integrity: sha512-vxJEMyNyckqLr/4HPsW9P6BMLUvOVMvjjFz3jLl4Wke1KWE8ITJUxIUwodxaOmEp9L2lxVk5an3TYeycZCfqFw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vite-plugin-purge-icons/-/vite-plugin-purge-icons-0.9.2.tgz} + id: registry.npmmirror.com/vite-plugin-purge-icons/0.9.2 + name: vite-plugin-purge-icons + version: 0.9.2 + engines: {node: '>= 12'} + peerDependencies: + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 + dependencies: + '@purge-icons/core': registry.npmmirror.com/@purge-icons/core/0.9.1 + '@purge-icons/generated': registry.npmmirror.com/@purge-icons/generated/0.9.0 + rollup-plugin-purge-icons: registry.npmmirror.com/rollup-plugin-purge-icons/0.9.1 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + registry.npmmirror.com/vite-plugin-windicss/1.8.10_vite@4.0.3: + resolution: {integrity: sha512-scywsuzo46lcTBohspmF0WiwhWEte6p+OUVrX4yr7VMRvLHMHVfLtJReyD5pppjijG7YOwVsZn7XBWWZtF658Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vite-plugin-windicss/-/vite-plugin-windicss-1.8.10.tgz} + id: registry.npmmirror.com/vite-plugin-windicss/1.8.10 + name: vite-plugin-windicss + version: 1.8.10 + peerDependencies: + vite: ^2.0.1 || ^3.0.0 || ^4.0.0 + dependencies: + '@windicss/plugin-utils': registry.npmmirror.com/@windicss/plugin-utils/1.8.10 + debug: registry.npmmirror.com/debug/4.3.4 + kolorist: registry.npmmirror.com/kolorist/1.6.0 + vite: 4.0.3_amyfslv6hdwxqbf7f4ldebbtce + windicss: registry.npmmirror.com/windicss/3.5.6 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/vue-demi/0.13.11_vue@3.2.45: + resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz} + id: registry.npmmirror.com/vue-demi/0.13.11 + name: vue-demi + version: 0.13.11 + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.2.45 + dev: false + + registry.npmmirror.com/vxe-table/4.3.7_vue@3.2.45+xe-utils@3.5.7: + resolution: {integrity: sha512-v+d7eEQ5uqtVTQCts4xkW0S15LZcIuEukYHGXI53SdoUj2gLFggPYAxQr1y659CM/ESRWPz9LNVHpd97KkjGHw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vxe-table/-/vxe-table-4.3.7.tgz} + id: registry.npmmirror.com/vxe-table/4.3.7 + name: vxe-table + version: 4.3.7 + peerDependencies: + vue: ^3.2.28 + xe-utils: ^3.5.0 + dependencies: + vue: 3.2.45 + xe-utils: 3.5.7 + dev: false + + registry.npmmirror.com/webidl-conversions/3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz} + name: webidl-conversions + version: 3.0.1 + dev: true + + registry.npmmirror.com/whatwg-url/5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz} + name: whatwg-url + version: 5.0.0 + dependencies: + tr46: registry.npmmirror.com/tr46/0.0.3 + webidl-conversions: registry.npmmirror.com/webidl-conversions/3.0.1 + dev: true + + registry.npmmirror.com/windicss/3.5.6: + resolution: {integrity: sha512-P1mzPEjgFMZLX0ZqfFht4fhV/FX8DTG7ERG1fBLiWvd34pTLVReS5CVsewKn9PApSgXnVfPWwvq+qUsRwpnwFA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/windicss/-/windicss-3.5.6.tgz} + name: windicss + version: 3.5.6 + engines: {node: '>= 12'} + hasBin: true + dev: true + + registry.npmmirror.com/yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz} + name: yallist + version: 4.0.0 + dev: true + + registry.npmmirror.com/zrender/5.4.1: + resolution: {integrity: sha512-M4Z05BHWtajY2241EmMPHglDQAJ1UyHQcYsxDNzD9XLSkPDqMq4bB28v9Pb4mvHnVQ0GxyTklZ/69xCFP6RXBA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/zrender/-/zrender-5.4.1.tgz} + name: zrender + version: 5.4.1 + dependencies: + tslib: registry.npmmirror.com/tslib/2.3.0 dev: false diff --git a/yudao-ui-admin-vue3/prettier.config.js b/yudao-ui-admin-vue3/prettier.config.js index b46239fe4..b014bbf1b 100644 --- a/yudao-ui-admin-vue3/prettier.config.js +++ b/yudao-ui-admin-vue3/prettier.config.js @@ -1,14 +1,17 @@ module.exports = { - printWidth: 100, - tabWidth: 2, - useTabs: false, - semi: false, + printWidth: 100, // 每行代码长度(默认80) + tabWidth: 2, // 每个tab相当于多少个空格(默认2)ab进行缩进(默认false) + useTabs: false, // 是否使用tab + semi: false, // 声明结尾使用分号(默认true) vueIndentScriptAndStyle: false, - singleQuote: true, + singleQuote: true, // 使用单引号(默认false) quoteProps: 'as-needed', - bracketSpacing: true, - trailingComma: 'none', + bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true) + trailingComma: 'none', // 多行使用拖尾逗号(默认none) jsxSingleQuote: false, + // 箭头函数参数括号 默认avoid 可选 avoid| always + // avoid 能省略括号的时候就省略 例如x => x + // always 总是有括号 arrowParens: 'always', insertPragma: false, requirePragma: false, diff --git a/yudao-ui-admin-vue3/src/App.vue b/yudao-ui-admin-vue3/src/App.vue index 20b5730bf..476c0c5de 100644 --- a/yudao-ui-admin-vue3/src/App.vue +++ b/yudao-ui-admin-vue3/src/App.vue @@ -1,64 +1,51 @@ - - - diff --git a/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/index.ts b/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/index.ts index e058abd21..b46199e4b 100644 --- a/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/index.ts @@ -1,11 +1,50 @@ import request from '@/config/axios' +export interface ApiAccessLogVO { + id: number + traceId: string + userId: number + userType: number + applicationName: string + requestMethod: string + requestParams: string + requestUrl: string + userIp: string + userAgent: string + beginTime: Date + endTIme: Date + duration: number + resultCode: number + resultMsg: string + createTime: Date +} + +export interface ApiAccessLogPageReqVO extends PageParam { + userId?: number + userType?: number + applicationName?: string + requestUrl?: string + beginTime?: Date[] + duration?: number + resultCode?: number +} + +export interface ApiAccessLogExportReqVO { + userId?: number + userType?: number + applicationName?: string + requestUrl?: string + beginTime?: Date[] + duration?: number + resultCode?: number +} + // 查询列表API 访问日志 -export const getApiAccessLogPageApi = (params) => { +export const getApiAccessLogPageApi = (params: ApiAccessLogPageReqVO) => { return request.get({ url: '/infra/api-access-log/page', params }) } // 导出API 访问日志 -export const exportApiAccessLogApi = (params) => { +export const exportApiAccessLogApi = (params: ApiAccessLogExportReqVO) => { return request.download({ url: '/infra/api-access-log/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/types.ts b/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/types.ts deleted file mode 100644 index 5e2a42c98..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/apiAccessLog/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type ApiAccessLogVO = { - id: number - traceId: string - userId: string - userType: string - applicationName: string - requestMethod: string - requestParams: string - requestUrl: string - beginTime: string - endTIme: string - duration: string - resultCode: number -} diff --git a/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/index.ts b/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/index.ts index e38a1de88..06515c36b 100644 --- a/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/index.ts @@ -1,7 +1,52 @@ import request from '@/config/axios' +export interface ApiErrorLogVO { + id: number + traceId: string + userId: number + userType: number + applicationName: string + requestMethod: string + requestParams: string + requestUrl: string + userIp: string + userAgent: string + exceptionTime: Date + exceptionName: string + exceptionMessage: string + exceptionRootCauseMessage: string + exceptionStackTrace: string + exceptionClassName: string + exceptionFileName: string + exceptionMethodName: string + exceptionLineNumber: number + processUserId: number + processStatus: number + processTime: Date + resultCode: number + createTime: Date +} + +export interface ApiErrorLogPageReqVO extends PageParam { + userId?: number + userType?: number + applicationName?: string + requestUrl?: string + exceptionTime?: Date[] + processStatus: number +} + +export interface ApiErrorLogExportReqVO { + userId?: number + userType?: number + applicationName?: string + requestUrl?: string + exceptionTime?: Date[] + processStatus: number +} + // 查询列表API 访问日志 -export const getApiErrorLogPageApi = (params) => { +export const getApiErrorLogPageApi = (params: ApiErrorLogPageReqVO) => { return request.get({ url: '/infra/api-error-log/page', params }) } @@ -13,7 +58,7 @@ export const updateApiErrorLogPageApi = (id: number, processStatus: number) => { } // 导出API 访问日志 -export const exportApiErrorLogApi = (params) => { +export const exportApiErrorLogApi = (params: ApiErrorLogExportReqVO) => { return request.download({ url: '/infra/api-error-log/export-excel', params diff --git a/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/types.ts b/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/types.ts deleted file mode 100644 index dfc871032..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/apiErrorLog/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type ApiErrorLogVO = { - id: number - userId: string - userIp: string - userAgent: string - userType: string - applicationName: string - requestMethod: string - requestParams: string - requestUrl: string - exceptionTime: string - exceptionName: string - exceptionStackTrace: string - processUserId: string - processStatus: number - resultCode: number -} diff --git a/yudao-ui-admin-vue3/src/api/infra/codegen/types.ts b/yudao-ui-admin-vue3/src/api/infra/codegen/types.ts index 57d9e3871..be6a66ede 100644 --- a/yudao-ui-admin-vue3/src/api/infra/codegen/types.ts +++ b/yudao-ui-admin-vue3/src/api/infra/codegen/types.ts @@ -12,8 +12,8 @@ export type CodegenTableVO = { className: string classComment: string author: string - createTime: string - updateTime: string + createTime: Date + updateTime: Date templateType: number parentMenuId: number } diff --git a/yudao-ui-admin-vue3/src/api/infra/config/index.ts b/yudao-ui-admin-vue3/src/api/infra/config/index.ts index 38a8eeb6d..5a9bee1bc 100644 --- a/yudao-ui-admin-vue3/src/api/infra/config/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/config/index.ts @@ -1,8 +1,33 @@ import request from '@/config/axios' -import type { ConfigVO } from './types' + +export interface ConfigVO { + id: number + category: string + name: string + key: string + value: string + type: number + visible: boolean + remark: string + createTime: Date +} + +export interface ConfigPageReqVO extends PageParam { + name?: string + key?: string + type?: number + createTime?: Date[] +} + +export interface ConfigExportReqVO { + name?: string + key?: string + type?: number + createTime?: Date[] +} // 查询参数列表 -export const getConfigPageApi = (params) => { +export const getConfigPageApi = (params: ConfigPageReqVO) => { return request.get({ url: '/infra/config/page', params }) } @@ -32,6 +57,6 @@ export const deleteConfigApi = (id: number) => { } // 导出参数 -export const exportConfigApi = (params) => { +export const exportConfigApi = (params: ConfigExportReqVO) => { return request.download({ url: '/infra/config/export', params }) } diff --git a/yudao-ui-admin-vue3/src/api/infra/config/types.ts b/yudao-ui-admin-vue3/src/api/infra/config/types.ts deleted file mode 100644 index 613a5e65c..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/config/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type ConfigVO = { - id: number - group: string - name: string - key: string - value: string - type: string - visible: boolean - remark: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/index.ts b/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/index.ts index a0a321794..c0f9f6249 100644 --- a/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/index.ts @@ -1,5 +1,13 @@ import request from '@/config/axios' -import type { DataSourceConfigVO } from './types' + +export interface DataSourceConfigVO { + id: number + name: string + url: string + username: string + password: string + createTime: Date +} // 查询数据源配置列表 export const getDataSourceConfigListApi = () => { diff --git a/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/types.ts b/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/types.ts deleted file mode 100644 index cba6eb7be..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/dataSourceConfig/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type DataSourceConfigVO = { - id: number - name: string - url: string - username: string - password: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/infra/fileConfig/index.ts b/yudao-ui-admin-vue3/src/api/infra/fileConfig/index.ts index 2ba10879e..2151141cd 100644 --- a/yudao-ui-admin-vue3/src/api/infra/fileConfig/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/fileConfig/index.ts @@ -1,8 +1,37 @@ import request from '@/config/axios' -import type { FileConfigVO } from './types' + +export interface FileClientConfig { + basePath: string + host?: string + port?: number + username?: string + password?: string + mode?: string + endpoint?: string + bucket?: string + accessKey?: string + accessSecret?: string + domain: string +} +export interface FileConfigVO { + id: number + name: string + storage: number + master: boolean + visible: boolean + config: FileClientConfig + remark: string + createTime: Date +} + +export interface FileConfigPageReqVO extends PageParam { + name?: string + storage?: number + createTime?: Date[] +} // 查询文件配置列表 -export const getFileConfigPageApi = (params) => { +export const getFileConfigPageApi = (params: FileConfigPageReqVO) => { return request.get({ url: '/infra/file-config/page', params }) } @@ -13,7 +42,7 @@ export const getFileConfigApi = (id: number) => { // 更新文件配置为主配置 export const updateFileConfigMasterApi = (id: number) => { - return request.get({ url: '/infra/file-config/update-master?id=' + id }) + return request.put({ url: '/infra/file-config/update-master?id=' + id }) } // 新增文件配置 diff --git a/yudao-ui-admin-vue3/src/api/infra/fileConfig/types.ts b/yudao-ui-admin-vue3/src/api/infra/fileConfig/types.ts deleted file mode 100644 index ce21b49e0..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/fileConfig/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -export type ConfigType = { - basePath: string - host: string - port: string - username: string - password: string - mode: string - endpoint: string - bucket: string - accessKey: string - accessSecret: string - domain: string -} -export type FileConfigVO = { - id: number - name: string - storage: string - primary: number - visible: boolean - config: ConfigType - remark: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/infra/fileList/index.ts b/yudao-ui-admin-vue3/src/api/infra/fileList/index.ts index 5c9c324fa..48b3c9917 100644 --- a/yudao-ui-admin-vue3/src/api/infra/fileList/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/fileList/index.ts @@ -1,7 +1,24 @@ import request from '@/config/axios' +export interface FileVO { + id: number + configId: number + path: string + name: string + url: string + size: string + type: string + createTime: Date +} + +export interface FilePageReqVO extends PageParam { + path?: string + type?: string + createTime?: Date[] +} + // 查询文件列表 -export const getFilePageApi = (params) => { +export const getFilePageApi = (params: FilePageReqVO) => { return request.get({ url: '/infra/file/page', params }) } diff --git a/yudao-ui-admin-vue3/src/api/infra/fileList/types.ts b/yudao-ui-admin-vue3/src/api/infra/fileList/types.ts deleted file mode 100644 index 0d32314c4..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/fileList/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type FileVO = { - id: number - path: string - url: string - size: string - type: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/infra/job/index.ts b/yudao-ui-admin-vue3/src/api/infra/job/index.ts index 15c73d60c..63f15da0d 100644 --- a/yudao-ui-admin-vue3/src/api/infra/job/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/job/index.ts @@ -1,8 +1,32 @@ import request from '@/config/axios' -import type { JobVO } from './types' + +export interface JobVO { + id: number + name: string + status: number + handlerName: string + handlerParam: string + cronExpression: string + retryCount: number + retryInterval: number + monitorTimeout: number + createTime: Date +} + +export interface JobPageReqVO extends PageParam { + name?: string + status?: number + handlerName?: string +} + +export interface JobExportReqVO { + name?: string + status?: number + handlerName?: string +} // 任务列表 -export const getJobPageApi = (params) => { +export const getJobPageApi = (params: JobPageReqVO) => { return request.get({ url: '/infra/job/page', params }) } @@ -27,7 +51,7 @@ export const deleteJobApi = (id: number) => { } // 导出定时任务调度 -export const exportJobApi = (params) => { +export const exportJobApi = (params: JobExportReqVO) => { return request.download({ url: '/infra/job/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/infra/job/types.ts b/yudao-ui-admin-vue3/src/api/infra/job/types.ts deleted file mode 100644 index 5a3b74fd7..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/job/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type JobVO = { - id: number - name: string - status: number - handlerName: string - handlerParam: string - cronExpression: string - retryCount: number - retryInterval: number - monitorTimeout: number -} diff --git a/yudao-ui-admin-vue3/src/api/infra/jobLog/index.ts b/yudao-ui-admin-vue3/src/api/infra/jobLog/index.ts index 349a23fb5..84b74fbde 100644 --- a/yudao-ui-admin-vue3/src/api/infra/jobLog/index.ts +++ b/yudao-ui-admin-vue3/src/api/infra/jobLog/index.ts @@ -1,7 +1,37 @@ import request from '@/config/axios' +export interface JobLogVO { + id: number + jobId: number + handlerName: string + handlerParam: string + cronExpression: string + executeIndex: string + beginTime: string + endTime: string + duration: string + status: number + createTime: string +} + +export interface JobLogPageReqVO extends PageParam { + jobId?: number + handlerName?: string + beginTime?: string + endTime?: string + status?: number +} + +export interface JobLogExportReqVO { + jobId?: number + handlerName?: string + beginTime?: string + endTime?: string + status?: number +} + // 任务日志列表 -export const getJobLogPageApi = (params) => { +export const getJobLogPageApi = (params: JobLogPageReqVO) => { return request.get({ url: '/infra/job-log/page', params }) } @@ -11,7 +41,7 @@ export const getJobLogApi = (id: number) => { } // 导出定时任务日志 -export const exportJobLogApi = (params) => { +export const exportJobLogApi = (params: JobLogExportReqVO) => { return request.download({ url: '/infra/job-log/export-excel', params diff --git a/yudao-ui-admin-vue3/src/api/infra/jobLog/types.ts b/yudao-ui-admin-vue3/src/api/infra/jobLog/types.ts deleted file mode 100644 index 0e6e90313..000000000 --- a/yudao-ui-admin-vue3/src/api/infra/jobLog/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type JobLogVO = { - id: number - jobId: number - handlerName: string - handlerParam: string - cronExpression: string - executeIndex: string - beginTime: Date - endTime: Date - duration: string - status: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/login/index.ts b/yudao-ui-admin-vue3/src/api/login/index.ts index 3f9c9a93f..6ff93e428 100644 --- a/yudao-ui-admin-vue3/src/api/login/index.ts +++ b/yudao-ui-admin-vue3/src/api/login/index.ts @@ -57,8 +57,17 @@ export const smsLoginApi = (data: SmsLoginVO) => { } // 社交授权的跳转 -export const socialAuthRedirectApi = (type: string, redirectUri: string) => { +export const socialAuthRedirectApi = (type: number, redirectUri: string) => { return request.get({ url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri }) } +// 获取验证图片 以及token +export const getCodeApi = (data) => { + return request.postOriginal({ url: 'system/captcha/get', data }) +} + +// 滑动或者点选验证 +export const reqCheckApi = (data) => { + return request.postOriginal({ url: 'system/captcha/check', data }) +} diff --git a/yudao-ui-admin-vue3/src/api/pay/app/index.ts b/yudao-ui-admin-vue3/src/api/pay/app/index.ts index 501fb2024..348185c8e 100644 --- a/yudao-ui-admin-vue3/src/api/pay/app/index.ts +++ b/yudao-ui-admin-vue3/src/api/pay/app/index.ts @@ -1,8 +1,44 @@ import request from '@/config/axios' -import type { AppVO } from './types' + +export interface AppVO { + id: number + name: string + status: number + remark: string + payNotifyUrl: string + refundNotifyUrl: string + merchantId: number + merchantName: string + createTime: Date +} + +export interface AppPageReqVO extends PageParam { + name?: string + status?: number + remark?: string + payNotifyUrl?: string + refundNotifyUrl?: string + merchantName?: string + createTime?: Date[] +} + +export interface AppExportReqVO { + name?: string + status?: number + remark?: string + payNotifyUrl?: string + refundNotifyUrl?: string + merchantName?: string + createTime?: Date[] +} + +export interface AppUpdateStatusReqVO { + id: number + status: number +} // 查询列表支付应用 -export const getAppPageApi = (params) => { +export const getAppPageApi = (params: AppPageReqVO) => { return request.get({ url: '/pay/app/page', params }) } @@ -22,11 +58,7 @@ export const updateAppApi = (data: AppVO) => { } // 支付应用信息状态修改 -export const changeAppStatusApi = (id: number, status: number) => { - const data = { - id, - status - } +export const changeAppStatusApi = (data: AppUpdateStatusReqVO) => { return request.put({ url: '/pay/app/update-status', data: data }) } @@ -36,7 +68,7 @@ export const deleteAppApi = (id: number) => { } // 导出支付应用 -export const exportAppApi = (params) => { +export const exportAppApi = (params: AppExportReqVO) => { return request.download({ url: '/pay/app/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/pay/app/types.ts b/yudao-ui-admin-vue3/src/api/pay/app/types.ts deleted file mode 100644 index ed5779db9..000000000 --- a/yudao-ui-admin-vue3/src/api/pay/app/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type AppVO = { - id: number - name: string - status: number - remark: string - payNotifyUrl: string - refundNotifyUrl: string - merchantName: string - merchantId: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/pay/channel/index.ts b/yudao-ui-admin-vue3/src/api/pay/channel/index.ts index 3fbd54def..a6da9eb88 100644 --- a/yudao-ui-admin-vue3/src/api/pay/channel/index.ts +++ b/yudao-ui-admin-vue3/src/api/pay/channel/index.ts @@ -1,8 +1,41 @@ import request from '@/config/axios' -import type { ChannelVO } from './types' + +export interface ChannelVO { + id: number + code: string + config: string + status: number + remark: string + feeRate: number + merchantId: number + appId: number + createTime: Date +} + +export interface ChannelPageReqVO extends PageParam { + code?: string + status?: number + remark?: string + feeRate?: number + merchantId?: number + appId?: number + config?: string + createTime?: Date[] +} + +export interface ChannelExportReqVO { + code?: string + status?: number + remark?: string + feeRate?: number + merchantId?: number + appId?: number + config?: string + createTime?: Date[] +} // 查询列表支付渠道 -export const getChannelPageApi = (params) => { +export const getChannelPageApi = (params: ChannelPageReqVO) => { return request.get({ url: '/pay/channel/page', params }) } @@ -32,6 +65,6 @@ export const deleteChannelApi = (id: number) => { } // 导出支付渠道 -export const exportChannelApi = (params) => { +export const exportChannelApi = (params: ChannelExportReqVO) => { return request.download({ url: '/pay/channel/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/pay/channel/types.ts b/yudao-ui-admin-vue3/src/api/pay/channel/types.ts deleted file mode 100644 index 980a7c377..000000000 --- a/yudao-ui-admin-vue3/src/api/pay/channel/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type ChannelVO = { - id: number - code: string - config: string - status: number - remark: string - feeRate: number - merchantId: number - appId: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/pay/merchant/index.ts b/yudao-ui-admin-vue3/src/api/pay/merchant/index.ts index 749591c5c..b4b6ba511 100644 --- a/yudao-ui-admin-vue3/src/api/pay/merchant/index.ts +++ b/yudao-ui-admin-vue3/src/api/pay/merchant/index.ts @@ -1,8 +1,35 @@ import request from '@/config/axios' -import type { MerchantVO } from './types' + +export interface MerchantVO { + id: number + no: string + name: string + shortName: string + status: number + remark: string + createTime: Date +} + +export interface MerchantPageReqVO extends PageParam { + no?: string + name?: string + shortName?: string + status?: number + remark?: string + createTime?: Date[] +} + +export interface MerchantExportReqVO { + no?: string + name?: string + shortName?: string + status?: number + remark?: string + createTime?: Date[] +} // 查询列表支付商户 -export const getMerchantPageApi = (params) => { +export const getMerchantPageApi = (params: MerchantPageReqVO) => { return request.get({ url: '/pay/merchant/page', params }) } @@ -37,7 +64,7 @@ export const deleteMerchantApi = (id: number) => { } // 导出支付商户 -export const exportMerchantApi = (params) => { +export const exportMerchantApi = (params: MerchantExportReqVO) => { return request.download({ url: '/pay/merchant/export-excel', params }) } // 支付商户状态修改 diff --git a/yudao-ui-admin-vue3/src/api/pay/merchant/types.ts b/yudao-ui-admin-vue3/src/api/pay/merchant/types.ts deleted file mode 100644 index 0a78a2a58..000000000 --- a/yudao-ui-admin-vue3/src/api/pay/merchant/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type MerchantVO = { - id: number - no: string - name: string - shortName: string - status: number - remark: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/pay/order/index.ts b/yudao-ui-admin-vue3/src/api/pay/order/index.ts index 9f4f18bc1..53e35aa94 100644 --- a/yudao-ui-admin-vue3/src/api/pay/order/index.ts +++ b/yudao-ui-admin-vue3/src/api/pay/order/index.ts @@ -1,8 +1,85 @@ import request from '@/config/axios' -import type { OrderVO } from './types' + +export interface OrderVO { + id: number + merchantId: number + appId: number + channelId: number + channelCode: string + merchantOrderId: string + subject: string + body: string + notifyUrl: string + notifyStatus: number + amount: number + channelFeeRate: number + channelFeeAmount: number + status: number + userIp: string + expireTime: Date + successTime: Date + notifyTime: Date + successExtensionId: number + refundStatus: number + refundTimes: number + refundAmount: number + channelUserId: string + channelOrderNo: string + createTime: Date +} + +export interface OrderPageReqVO extends PageParam { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + merchantOrderId?: string + subject?: string + body?: string + notifyUrl?: string + notifyStatus?: number + amount?: number + channelFeeRate?: number + channelFeeAmount?: number + status?: number + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + successExtensionId?: number + refundStatus?: number + refundTimes?: number + channelUserId?: string + channelOrderNo?: string + createTime?: Date[] +} + +export interface OrderExportReqVO { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + merchantOrderId?: string + subject?: string + body?: string + notifyUrl?: string + notifyStatus?: number + amount?: number + channelFeeRate?: number + channelFeeAmount?: number + status?: number + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + successExtensionId?: number + refundStatus?: number + refundTimes?: number + channelUserId?: string + channelOrderNo?: string + createTime?: Date[] +} // 查询列表支付订单 -export const getOrderPageApi = async (params) => { +export const getOrderPageApi = async (params: OrderPageReqVO) => { return await request.get({ url: '/pay/order/page', params }) } @@ -27,6 +104,6 @@ export const deleteOrderApi = async (id: number) => { } // 导出支付订单 -export const exportOrderApi = async (params) => { +export const exportOrderApi = async (params: OrderExportReqVO) => { return await request.download({ url: '/pay/order/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/pay/order/types.ts b/yudao-ui-admin-vue3/src/api/pay/order/types.ts deleted file mode 100644 index 6a8729073..000000000 --- a/yudao-ui-admin-vue3/src/api/pay/order/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type OrderVO = { - id: number - merchantId: number - appId: number - channelId: number - channelCode: string - merchantOrderId: string - subject: string - body: string - notifyUrl: string - notifyStatus: number - amount: number - channelFeeRate: number - channelFeeAmount: number - status: number - userIp: string - expireTime: string - successTime: string - notifyTime: string - successExtensionId: number - refundStatus: number - refundTimes: number - refundAmount: number - channelUserId: string - channelOrderNo: string -} diff --git a/yudao-ui-admin-vue3/src/api/pay/refund/index.ts b/yudao-ui-admin-vue3/src/api/pay/refund/index.ts index 45d9bc9ad..cd68a1448 100644 --- a/yudao-ui-admin-vue3/src/api/pay/refund/index.ts +++ b/yudao-ui-admin-vue3/src/api/pay/refund/index.ts @@ -1,8 +1,92 @@ import request from '@/config/axios' -import type { RefundVO } from './types' + +export interface RefundVO { + id: number + merchantId: number + appId: number + channelId: number + channelCode: string + orderId: string + tradeNo: string + merchantOrderId: string + merchantRefundNo: string + notifyUrl: string + notifyStatus: number + status: number + type: number + payAmount: number + refundAmount: number + reason: string + userIp: string + channelOrderNo: string + channelRefundNo: string + channelErrorCode: string + channelErrorMsg: string + channelExtras: string + expireTime: Date + successTime: Date + notifyTime: Date + createTime: Date +} + +export interface RefundPageReqVO extends PageParam { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + orderId?: string + tradeNo?: string + merchantOrderId?: string + merchantRefundNo?: string + notifyUrl?: string + notifyStatus?: number + status?: number + type?: number + payAmount?: number + refundAmount?: number + reason?: string + userIp?: string + channelOrderNo?: string + channelRefundNo?: string + channelErrorCode?: string + channelErrorMsg?: string + channelExtras?: string + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + createTime?: Date[] +} + +export interface PayRefundExportReqVO { + merchantId?: number + appId?: number + channelId?: number + channelCode?: string + orderId?: string + tradeNo?: string + merchantOrderId?: string + merchantRefundNo?: string + notifyUrl?: string + notifyStatus?: number + status?: number + type?: number + payAmount?: number + refundAmount?: number + reason?: string + userIp?: string + channelOrderNo?: string + channelRefundNo?: string + channelErrorCode?: string + channelErrorMsg?: string + channelExtras?: string + expireTime?: Date[] + successTime?: Date[] + notifyTime?: Date[] + createTime?: Date[] +} // 查询列表退款订单 -export const getRefundPageApi = (params) => { +export const getRefundPageApi = (params: RefundPageReqVO) => { return request.get({ url: '/pay/refund/page', params }) } @@ -27,6 +111,6 @@ export const deleteRefundApi = (id: number) => { } // 导出退款订单 -export const exportRefundApi = (params) => { +export const exportRefundApi = (params: PayRefundExportReqVO) => { return request.download({ url: '/pay/refund/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/pay/refund/types.ts b/yudao-ui-admin-vue3/src/api/pay/refund/types.ts deleted file mode 100644 index 878a23218..000000000 --- a/yudao-ui-admin-vue3/src/api/pay/refund/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -export type RefundVO = { - id: number - merchantId: number - appId: number - channelId: number - channelCode: string - merchantOrderId: string - subject: string - body: string - notifyUrl: string - notifyStatus: number - amount: number - channelFeeRate: number - channelFeeAmount: number - status: number - userIp: string - expireTime: string - successTime: string - notifyTime: string - successExtensionId: number - refundStatus: number - refundTimes: number - refundAmount: number - channelUserId: string - channelOrderNo: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/dept/index.ts b/yudao-ui-admin-vue3/src/api/system/dept/index.ts index 5e602d067..d66de3f1c 100644 --- a/yudao-ui-admin-vue3/src/api/system/dept/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/dept/index.ts @@ -1,32 +1,48 @@ import request from '@/config/axios' -import type { DeptVO, DeptListReqVO } from './types' + +export interface DeptVO { + id?: number + name: string + parentId: number + status: number + sort: number + leaderUserId: number + phone: string + email: string + createTime: Date +} + +export interface DeptPageReqVO { + name?: string + status?: number +} // 查询部门(精简)列表 -export const listSimpleDeptApi = () => { - return request.get({ url: '/system/dept/list-all-simple' }) +export const listSimpleDeptApi = async () => { + return await request.get({ url: '/system/dept/list-all-simple' }) } // 查询部门列表 -export const getDeptPageApi = (params: DeptListReqVO) => { - return request.get({ url: '/system/dept/list', params }) +export const getDeptPageApi = async (params: DeptPageReqVO) => { + return await request.get({ url: '/system/dept/list', params }) } // 查询部门详情 -export const getDeptApi = (id: number) => { - return request.get({ url: '/system/dept/get?id=' + id }) +export const getDeptApi = async (id: number) => { + return await request.get({ url: '/system/dept/get?id=' + id }) } // 新增部门 -export const createDeptApi = (data: DeptVO) => { - return request.post({ url: '/system/dept/create', data: data }) +export const createDeptApi = async (data: DeptVO) => { + return await request.post({ url: '/system/dept/create', data: data }) } // 修改部门 -export const updateDeptApi = (params: DeptVO) => { - return request.put({ url: '/system/dept/update', data: params }) +export const updateDeptApi = async (params: DeptVO) => { + return await request.put({ url: '/system/dept/update', data: params }) } // 删除部门 -export const deleteDeptApi = (id: number) => { - return request.delete({ url: '/system/dept/delete?id=' + id }) +export const deleteDeptApi = async (id: number) => { + return await request.delete({ url: '/system/dept/delete?id=' + id }) } diff --git a/yudao-ui-admin-vue3/src/api/system/dept/types.ts b/yudao-ui-admin-vue3/src/api/system/dept/types.ts deleted file mode 100644 index 470fcd3d8..000000000 --- a/yudao-ui-admin-vue3/src/api/system/dept/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type DeptVO = { - id: number - name: string - parentId: number - status: number - sort: number - leaderUserId: number - phone: string - email: string -} - -export type DeptListReqVO = { - name: string - status: number -} diff --git a/yudao-ui-admin-vue3/src/api/system/dict/types.ts b/yudao-ui-admin-vue3/src/api/system/dict/types.ts index 3b5893833..b630dccba 100644 --- a/yudao-ui-admin-vue3/src/api/system/dict/types.ts +++ b/yudao-ui-admin-vue3/src/api/system/dict/types.ts @@ -4,21 +4,21 @@ export type DictTypeVO = { type: string status: number remark: string - createTime: string + createTime: Date } export type DictTypePageReqVO = { name: string type: string status: number - createTime: [] + createTime: Date[] } export type DictTypeExportReqVO = { name: string type: string status: number - createTime: [] + createTime: Date[] } export type DictDataVO = { @@ -31,7 +31,7 @@ export type DictDataVO = { colorType: string cssClass: string remark: string - createTime: string + createTime: Date } export type DictDataPageReqVO = { label: string diff --git a/yudao-ui-admin-vue3/src/api/system/errorCode/index.ts b/yudao-ui-admin-vue3/src/api/system/errorCode/index.ts index da3a8e64d..0e000794e 100644 --- a/yudao-ui-admin-vue3/src/api/system/errorCode/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/errorCode/index.ts @@ -1,8 +1,25 @@ import request from '@/config/axios' -import type { ErrorCodeVO } from './types' + +export interface ErrorCodeVO { + id: number + type: number + applicationName: string + code: number + message: string + memo: string + createTime: Date +} + +export interface ErrorCodePageReqVO extends PageParam { + type?: number + applicationName?: string + code?: number + message?: string + createTime?: Date[] +} // 查询错误码列表 -export const getErrorCodePageApi = (params) => { +export const getErrorCodePageApi = (params: ErrorCodePageReqVO) => { return request.get({ url: '/system/error-code/page', params }) } @@ -26,6 +43,6 @@ export const deleteErrorCodeApi = (id: number) => { return request.delete({ url: '/system/error-code/delete?id=' + id }) } // 导出错误码 -export const excelErrorCodeApi = (params) => { +export const excelErrorCodeApi = (params: ErrorCodePageReqVO) => { return request.download({ url: '/system/error-code/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/errorCode/types.ts b/yudao-ui-admin-vue3/src/api/system/errorCode/types.ts deleted file mode 100644 index de8423979..000000000 --- a/yudao-ui-admin-vue3/src/api/system/errorCode/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type ErrorCodeVO = { - id: number - type: number - applicationName: string - code: number - message: string - memo: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/loginLog/index.ts b/yudao-ui-admin-vue3/src/api/system/loginLog/index.ts index 32c2d9796..cadaeaf30 100644 --- a/yudao-ui-admin-vue3/src/api/system/loginLog/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/loginLog/index.ts @@ -1,10 +1,30 @@ import request from '@/config/axios' +export interface LoginLogVO { + id: number + logType: number + traceId: number + userId: number + userType: number + username: string + status: number + userIp: string + userAgent: string + createTime: Date +} + +export interface LoginLogReqVO extends PageParam { + userIp?: string + username?: string + status?: boolean + createTime?: Date[] +} + // 查询登录日志列表 -export const getLoginLogPageApi = (params) => { +export const getLoginLogPageApi = (params: LoginLogReqVO) => { return request.get({ url: '/system/login-log/page', params }) } // 导出登录日志 -export const exportLoginLogApi = (params) => { +export const exportLoginLogApi = (params: LoginLogReqVO) => { return request.download({ url: '/system/login-log/export', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/loginLog/types.ts b/yudao-ui-admin-vue3/src/api/system/loginLog/types.ts deleted file mode 100644 index 7454ccf3a..000000000 --- a/yudao-ui-admin-vue3/src/api/system/loginLog/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type LoginLogVO = { - id: number - logType: number - traceId: number - userType: number - username: string - status: number - userIp: string - userAgent: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/menu/index.ts b/yudao-ui-admin-vue3/src/api/system/menu/index.ts index 92ec2301e..8f4029fe8 100644 --- a/yudao-ui-admin-vue3/src/api/system/menu/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/menu/index.ts @@ -1,5 +1,25 @@ import request from '@/config/axios' -import type { MenuVO } from './types' + +export interface MenuVO { + id: number + name: string + permission: string + type: number + sort: number + parentId: number + path: string + icon: string + component: string + status: number + visible: boolean + keepAlive: boolean + createTime: Date +} + +export interface MenuPageReqVO { + name?: string + status?: number +} // 查询菜单(精简)列表 export const listSimpleMenusApi = () => { @@ -7,7 +27,7 @@ export const listSimpleMenusApi = () => { } // 查询菜单列表 -export const getMenuListApi = (params) => { +export const getMenuListApi = (params: MenuPageReqVO) => { return request.get({ url: '/system/menu/list', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/menu/types.ts b/yudao-ui-admin-vue3/src/api/system/menu/types.ts deleted file mode 100644 index 1506e87aa..000000000 --- a/yudao-ui-admin-vue3/src/api/system/menu/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type MenuVO = { - id: number - name: string - permission: string - type: number - sort: number - parentId: number - path: string - icon: string - component: string - status: number - visible: boolean - keepAlive: boolean - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/notice/index.ts b/yudao-ui-admin-vue3/src/api/system/notice/index.ts index 7ccafad4a..f0f5d7e9c 100644 --- a/yudao-ui-admin-vue3/src/api/system/notice/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/notice/index.ts @@ -1,8 +1,23 @@ import request from '@/config/axios' -import type { NoticeVO } from './types' + +export interface NoticeVO { + id: number + title: string + type: number + content: string + status: number + remark: string + creator: string + createTime: Date +} + +export interface NoticePageReqVO extends PageParam { + title?: string + status?: number +} // 查询公告列表 -export const getNoticePageApi = (params) => { +export const getNoticePageApi = (params: NoticePageReqVO) => { return request.get({ url: '/system/notice/page', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/notice/types.ts b/yudao-ui-admin-vue3/src/api/system/notice/types.ts deleted file mode 100644 index 0e0bb43ec..000000000 --- a/yudao-ui-admin-vue3/src/api/system/notice/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -export type NoticeVO = { - id: number - title: string - type: number - content: string - status: number - remark: string - creator: string - createTime: string - updater: string - updateTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/oauth2/client.ts b/yudao-ui-admin-vue3/src/api/system/oauth2/client.ts index 11b696f5c..4c06386df 100644 --- a/yudao-ui-admin-vue3/src/api/system/oauth2/client.ts +++ b/yudao-ui-admin-vue3/src/api/system/oauth2/client.ts @@ -1,8 +1,32 @@ import request from '@/config/axios' -import { OAuth2ClientVo } from './client.types' +export interface OAuth2ClientVO { + id: number + clientId: string + secret: string + name: string + logo: string + description: string + status: number + accessTokenValiditySeconds: number + refreshTokenValiditySeconds: number + redirectUris: string[] + autoApprove: boolean + authorizedGrantTypes: string[] + scopes: string[] + authorities: string[] + resourceIds: string[] + additionalInformation: string + isAdditionalInformationJson: boolean + createTime: Date +} + +export interface OAuth2ClientPageReqVO extends PageParam { + name?: string + status?: number +} // 查询 OAuth2列表 -export const getOAuth2ClientPageApi = (params) => { +export const getOAuth2ClientPageApi = (params: OAuth2ClientPageReqVO) => { return request.get({ url: '/system/oauth2-client/page', params }) } @@ -12,12 +36,12 @@ export const getOAuth2ClientApi = (id: number) => { } // 新增 OAuth2 -export const createOAuth2ClientApi = (data: OAuth2ClientVo) => { +export const createOAuth2ClientApi = (data: OAuth2ClientVO) => { return request.post({ url: '/system/oauth2-client/create', data }) } // 修改 OAuth2 -export const updateOAuth2ClientApi = (data: OAuth2ClientVo) => { +export const updateOAuth2ClientApi = (data: OAuth2ClientVO) => { return request.put({ url: '/system/oauth2-client/update', data }) } diff --git a/yudao-ui-admin-vue3/src/api/system/oauth2/client.types.ts b/yudao-ui-admin-vue3/src/api/system/oauth2/client.types.ts deleted file mode 100644 index 895e04762..000000000 --- a/yudao-ui-admin-vue3/src/api/system/oauth2/client.types.ts +++ /dev/null @@ -1,20 +0,0 @@ -export type OAuth2ClientVo = { - id: number - clientId: string - secret: string - name: string - logo: string - description: string - status: number - accessTokenValiditySeconds: number - refreshTokenValiditySeconds: number - redirectUris: string[] - autoApprove: boolean - authorizedGrantTypes: string[] - scopes: string[] - authorities: string[] - resourceIds: string[] - additionalInformation: string - isAdditionalInformationJson: boolean - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/oauth2/token.ts b/yudao-ui-admin-vue3/src/api/system/oauth2/token.ts index d14ed2799..dc7c44f57 100644 --- a/yudao-ui-admin-vue3/src/api/system/oauth2/token.ts +++ b/yudao-ui-admin-vue3/src/api/system/oauth2/token.ts @@ -1,7 +1,24 @@ import request from '@/config/axios' +export interface OAuth2TokenVO { + id: number + accessToken: string + refreshToken: string + userId: number + userType: number + clientId: string + createTime: Date + expiresTime: Date +} + +export interface OAuth2TokenPageReqVO extends PageParam { + userId?: number + userType?: number + clientId?: string +} + // 查询 token列表 -export const getAccessTokenPageApi = (params) => { +export const getAccessTokenPageApi = (params: OAuth2TokenPageReqVO) => { return request.get({ url: '/system/oauth2-token/page', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/oauth2/token.types.ts b/yudao-ui-admin-vue3/src/api/system/oauth2/token.types.ts deleted file mode 100644 index f12e9943d..000000000 --- a/yudao-ui-admin-vue3/src/api/system/oauth2/token.types.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type OAuth2TokenVo = { - id: number - accessToken: string - refreshToken: string - userId: number - userType: number - clientId: string - createTime: string - expiresTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/operatelog/index.ts b/yudao-ui-admin-vue3/src/api/system/operatelog/index.ts index bf990bb36..5fd31dbac 100644 --- a/yudao-ui-admin-vue3/src/api/system/operatelog/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/operatelog/index.ts @@ -1,10 +1,41 @@ import request from '@/config/axios' +export type OperateLogVO = { + id: number + userNickname: string + traceId: string + userId: number + module: string + name: string + type: number + content: string + exts: Map + requestMethod: string + requestUrl: string + userIp: string + userAgent: string + javaMethod: string + javaMethodArgs: string + startTime: Date + duration: number + resultCode: number + resultMsg: string + resultData: string +} + +export interface OperateLogPageReqVO extends PageParam { + module?: string + userNickname?: string + type?: number + success?: boolean + startTime?: Date[] +} + // 查询操作日志列表 -export const getOperateLogPageApi = (params) => { +export const getOperateLogPageApi = (params: OperateLogPageReqVO) => { return request.get({ url: '/system/operate-log/page', params }) } // 导出操作日志 -export const exportOperateLogApi = (params) => { +export const exportOperateLogApi = (params: OperateLogPageReqVO) => { return request.download({ url: '/system/operate-log/export', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/operatelog/types.ts b/yudao-ui-admin-vue3/src/api/system/operatelog/types.ts deleted file mode 100644 index 896d15df4..000000000 --- a/yudao-ui-admin-vue3/src/api/system/operatelog/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export type OperateLogVO = { - id: number - userNickname: string - traceId: string - userId: number - module: string - name: string - type: number - content: string - exts: object - requestMethod: string - requestUrl: string - userIp: string - userAgent: string - javaMethod: string - javaMethodArgs: string - startTime: string - duration: number - resultCode: number - resultMsg: string - resultData: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/permission/index.ts b/yudao-ui-admin-vue3/src/api/system/permission/index.ts index e7e87e7aa..aa355dfcd 100644 --- a/yudao-ui-admin-vue3/src/api/system/permission/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/permission/index.ts @@ -1,9 +1,20 @@ import request from '@/config/axios' -import type { - PermissionAssignRoleDataScopeReqVO, - PermissionAssignRoleMenuReqVO, - PermissionAssignUserRoleReqVO -} from './types' + +export interface PermissionAssignUserRoleReqVO { + userId: number + roleIds: number[] +} + +export interface PermissionAssignRoleMenuReqVO { + roleId: number + menuIds: number[] +} + +export interface PermissionAssignRoleDataScopeReqVO { + roleId: number + dataScope: number + dataScopeDeptIds: number[] +} // 查询角色拥有的菜单权限 export const listRoleMenusApi = async (roleId: number) => { diff --git a/yudao-ui-admin-vue3/src/api/system/permission/types.ts b/yudao-ui-admin-vue3/src/api/system/permission/types.ts deleted file mode 100644 index 1050c39e2..000000000 --- a/yudao-ui-admin-vue3/src/api/system/permission/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type PermissionAssignUserRoleReqVO = { - userId: number - roleIds: number[] -} - -export type PermissionAssignRoleMenuReqVO = { - roleId: number - menuIds: number[] -} - -export type PermissionAssignRoleDataScopeReqVO = { - roleId: number - dataScope: number - dataScopeDeptIds: number[] -} diff --git a/yudao-ui-admin-vue3/src/api/system/post/index.ts b/yudao-ui-admin-vue3/src/api/system/post/index.ts index 3401359da..9e2540f01 100644 --- a/yudao-ui-admin-vue3/src/api/system/post/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/post/index.ts @@ -1,5 +1,26 @@ import request from '@/config/axios' -import type { PostVO, PostPageReqVO, PostExportReqVO } from './types' + +export interface PostVO { + id?: number + name: string + code: string + sort: number + status: number + remark: string + createTime?: Date +} + +export interface PostPageReqVO extends PageParam { + code?: string + name?: string + status?: number +} + +export interface PostExportReqVO { + code?: string + name?: string + status?: number +} // 查询岗位列表 export const getPostPageApi = async (params: PostPageReqVO) => { @@ -10,6 +31,7 @@ export const getPostPageApi = async (params: PostPageReqVO) => { export const listSimplePostsApi = async () => { return await request.get({ url: '/system/post/list-all-simple' }) } + // 查询岗位详情 export const getPostApi = async (id: number) => { return await request.get({ url: '/system/post/get?id=' + id }) @@ -31,7 +53,6 @@ export const deletePostApi = async (id: number) => { } // 导出岗位 -// TODO @星语:导出这块,咱怎么弄哈 export const exportPostApi = async (params: PostExportReqVO) => { return await request.download({ url: '/system/post/export', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/post/types.ts b/yudao-ui-admin-vue3/src/api/system/post/types.ts deleted file mode 100644 index fc239e30e..000000000 --- a/yudao-ui-admin-vue3/src/api/system/post/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -export type PostVO = { - id?: number - name: string - code: string - sort: number - status: number - remark: string - createTime?: string -} - -// TODO @星语:要不要搞个 Page 基类呀?和后端对应 -export type PostPageReqVO = { - code: string - name: string - status?: number - pageSize?: number - pageNo?: number -} - -export type PostExportReqVO = { - code: string - name: string - status?: number -} diff --git a/yudao-ui-admin-vue3/src/api/system/role/index.ts b/yudao-ui-admin-vue3/src/api/system/role/index.ts index efbb75d48..0d4775559 100644 --- a/yudao-ui-admin-vue3/src/api/system/role/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/role/index.ts @@ -1,8 +1,29 @@ import request from '@/config/axios' -import type { RoleVO } from './types' + +export interface RoleVO { + id: number + name: string + code: string + sort: number + status: number + type: number + createTime: Date +} + +export interface RolePageReqVO extends PageParam { + name?: string + code?: string + status?: number + createTime?: Date[] +} + +export interface UpdateStatusReqVO { + id: number + status: number +} // 查询角色列表 -export const getRolePageApi = async (params) => { +export const getRolePageApi = async (params: RolePageReqVO) => { return await request.get({ url: '/system/role/page', params }) } @@ -27,7 +48,7 @@ export const updateRoleApi = async (data: RoleVO) => { } // 修改角色状态 -export const updateRoleStatusApi = async (data: RoleVO) => { +export const updateRoleStatusApi = async (data: UpdateStatusReqVO) => { return await request.put({ url: '/system/role/update-status', data }) } diff --git a/yudao-ui-admin-vue3/src/api/system/role/types.ts b/yudao-ui-admin-vue3/src/api/system/role/types.ts deleted file mode 100644 index f5e17ea99..000000000 --- a/yudao-ui-admin-vue3/src/api/system/role/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type RoleVO = { - id: number - name: string - code: string - sort: number - status: number - type: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/sensitiveWord/index.ts b/yudao-ui-admin-vue3/src/api/system/sensitiveWord/index.ts index 4ad3f8df1..ffda89c03 100644 --- a/yudao-ui-admin-vue3/src/api/system/sensitiveWord/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/sensitiveWord/index.ts @@ -1,8 +1,30 @@ import request from '@/config/axios' -import type { SensitiveWordVO } from './types' + +export interface SensitiveWordVO { + id: number + name: string + status: number + description: string + tags: string[] + createTime: Date +} + +export interface SensitiveWordPageReqVO extends PageParam { + name?: string + tag?: string + status?: number + createTime?: Date[] +} + +export interface SensitiveWordExportReqVO { + name?: string + tag?: string + status?: number + createTime?: Date[] +} // 查询敏感词列表 -export const getSensitiveWordPageApi = (params) => { +export const getSensitiveWordPageApi = (params: SensitiveWordPageReqVO) => { return request.get({ url: '/system/sensitive-word/page', params }) } @@ -27,7 +49,7 @@ export const deleteSensitiveWordApi = (id: number) => { } // 导出敏感词 -export const exportSensitiveWordApi = (params) => { +export const exportSensitiveWordApi = (params: SensitiveWordExportReqVO) => { return request.download({ url: '/system/sensitive-word/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/sensitiveWord/types.ts b/yudao-ui-admin-vue3/src/api/system/sensitiveWord/types.ts deleted file mode 100644 index 68219fe43..000000000 --- a/yudao-ui-admin-vue3/src/api/system/sensitiveWord/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type SensitiveWordVO = { - id: number - name: string - status: number - description: string - tags: string - type: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/index.ts b/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/index.ts index 213cd2296..176d075fe 100644 --- a/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/index.ts @@ -1,8 +1,26 @@ import request from '@/config/axios' -import type { SmsChannelVO } from './types' + +export interface SmsChannelVO { + id: number + code: string + status: number + signature: string + remark: string + apiKey: string + apiSecret: string + callbackUrl: string + createTime: Date +} + +export interface SmsChannelPageReqVO extends PageParam { + signature?: string + code?: string + status?: number + createTime?: Date[] +} // 查询短信渠道列表 -export const getSmsChannelPageApi = (params) => { +export const getSmsChannelPageApi = (params: SmsChannelPageReqVO) => { return request.get({ url: '/system/sms-channel/page', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/types.ts b/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/types.ts deleted file mode 100644 index c4e9da24a..000000000 --- a/yudao-ui-admin-vue3/src/api/system/sms/smsChannel/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type SmsChannelVO = { - id: number - status: number - signature: string - remark: string - apiKey: string - apiSecret: string - callbackUrl: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/sms/smsLog/index.ts b/yudao-ui-admin-vue3/src/api/system/sms/smsLog/index.ts index b7c518720..52594b908 100644 --- a/yudao-ui-admin-vue3/src/api/system/sms/smsLog/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/sms/smsLog/index.ts @@ -1,11 +1,57 @@ import request from '@/config/axios' +export interface SmsLogVO { + id: number + channelId: number + channelCode: string + templateId: number + templateCode: string + templateType: number + templateContent: string + templateParams: Map + mobile: string + userId: number + userType: number + sendStatus: number + sendTime: Date + sendCode: number + sendMsg: string + apiSendCode: string + apiSendMsg: string + apiRequestId: string + apiSerialNo: string + receiveStatus: number + receiveTime: Date + apiReceiveCode: string + apiReceiveMsg: string + createTime: Date +} + +export interface SmsLogPageReqVO extends PageParam { + channelId?: number + templateId?: number + mobile?: string + sendStatus?: number + sendTime?: Date[] + receiveStatus?: number + receiveTime?: Date[] +} +export interface SmsLogExportReqVO { + channelId?: number + templateId?: number + mobile?: string + sendStatus?: number + sendTime?: Date[] + receiveStatus?: number + receiveTime?: Date[] +} + // 查询短信日志列表 -export const getSmsLogPageApi = (params) => { +export const getSmsLogPageApi = (params: SmsLogPageReqVO) => { return request.get({ url: '/system/sms-log/page', params }) } // 导出短信日志 -export const exportSmsLogApi = (params) => { +export const exportSmsLogApi = (params: SmsLogExportReqVO) => { return request.download({ url: '/system/sms-log/export', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/sms/smsLog/types.ts b/yudao-ui-admin-vue3/src/api/system/sms/smsLog/types.ts deleted file mode 100644 index 2a1781f5b..000000000 --- a/yudao-ui-admin-vue3/src/api/system/sms/smsLog/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type SmsLogVO = { - id: number - idchannelId: number - templateId: number - mobile: string - sendStatus: number - receiveStatus: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/index.ts b/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/index.ts index b096f00a7..0433fe3a4 100644 --- a/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/index.ts @@ -1,8 +1,48 @@ import request from '@/config/axios' -import type { SmsTemplateVO } from './types' + +export interface SmsTemplateVO { + id: number + type: number + status: number + code: string + name: string + content: string + remark: string + apiTemplateId: string + channelId: number + channelCode: string + params: string[] + createTime: Date +} + +export interface SendSmsReqVO { + mobile: string + templateCode: string + templateParams: Map +} + +export interface SmsTemplatePageReqVO { + type?: number + status?: number + code?: string + content?: string + apiTemplateId?: string + channelId?: number + createTime?: Date[] +} + +export interface SmsTemplateExportReqVO { + type?: number + status?: number + code?: string + content?: string + apiTemplateId?: string + channelId?: number + createTime?: Date[] +} // 查询短信模板列表 -export const getSmsTemplatePageApi = (params) => { +export const getSmsTemplatePageApi = (params: SmsTemplatePageReqVO) => { return request.get({ url: '/system/sms-template/page', params }) } @@ -27,12 +67,12 @@ export const deleteSmsTemplateApi = (id: number) => { } // 发送短信 -export const sendSmsApi = (data) => { +export const sendSmsApi = (data: SendSmsReqVO) => { return request.post({ url: '/system/sms-template/send-sms', data }) } // 导出短信模板 -export const exportPostApi = (params) => { +export const exportPostApi = (params: SmsTemplateExportReqVO) => { return request.download({ url: '/system/sms-template/export-excel', params diff --git a/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/types.ts b/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/types.ts deleted file mode 100644 index 70c8421b5..000000000 --- a/yudao-ui-admin-vue3/src/api/system/sms/smsTemplate/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -export type SmsTemplateVO = { - id: number - type: number - status: number - code: string - name: string - content: string - remark: string - apiTemplateId: string - channelId: number - channelCode: string - createTime: string -} - -export type SmsSendVO = { - mobile: string - templateCode: string - templateParams: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/tenant/index.ts b/yudao-ui-admin-vue3/src/api/system/tenant/index.ts index 0eb134d8c..d79fb7b23 100644 --- a/yudao-ui-admin-vue3/src/api/system/tenant/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/tenant/index.ts @@ -1,8 +1,38 @@ import request from '@/config/axios' -import type { TenantVO } from './types' + +export interface TenantVO { + id: number + name: string + contactName: string + contactMobile: string + status: number + domain: string + packageId: number + username: string + password: string + expireTime: Date + accountCount: number + createTime: Date +} + +export interface TenantPageReqVO extends PageParam { + name?: string + contactName?: string + contactMobile?: string + status?: number + createTime?: Date[] +} + +export interface TenantExportReqVO { + name?: string + contactName?: string + contactMobile?: string + status?: number + createTime?: Date[] +} // 查询租户列表 -export const getTenantPageApi = (params) => { +export const getTenantPageApi = (params: TenantPageReqVO) => { return request.get({ url: '/system/tenant/page', params }) } @@ -27,6 +57,6 @@ export const deleteTenantApi = (id: number) => { } // 导出租户 -export const exportTenantApi = (params) => { +export const exportTenantApi = (params: TenantExportReqVO) => { return request.download({ url: '/system/tenant/export-excel', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/tenant/types.ts b/yudao-ui-admin-vue3/src/api/system/tenant/types.ts deleted file mode 100644 index dc19b8e2c..000000000 --- a/yudao-ui-admin-vue3/src/api/system/tenant/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -export type TenantVO = { - id: number - name: string - packageId: number - contactName: string - contactMobile: string - username: string - password: string - accountCount: number - expireTime: string - domain: string - status: number - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/api/system/tenantPackage/index.ts b/yudao-ui-admin-vue3/src/api/system/tenantPackage/index.ts index 420cf24a3..e431a9ee6 100644 --- a/yudao-ui-admin-vue3/src/api/system/tenantPackage/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/tenantPackage/index.ts @@ -1,8 +1,26 @@ import request from '@/config/axios' -import type { TenantPackageVO } from './types' + +export interface TenantPackageVO { + id: number + name: string + status: number + remark: string + creator: string + updater: string + updateTime: string + menuIds: number[] + createTime: Date +} + +export interface TenantPackagePageReqVO extends PageParam { + name?: string + status?: number + remark?: string + createTime?: Date[] +} // 查询租户套餐列表 -export const getTenantPackageTypePageApi = (params) => { +export const getTenantPackageTypePageApi = (params: TenantPackagePageReqVO) => { return request.get({ url: '/system/tenant-package/page', params }) } @@ -25,7 +43,7 @@ export const updateTenantPackageTypeApi = (data: TenantPackageVO) => { export const deleteTenantPackageTypeApi = (id: number) => { return request.delete({ url: '/system/tenant-package/delete?id=' + id }) } -// // 获取租户套餐精简信息列表 +// 获取租户套餐精简信息列表 export const getTenantPackageList = () => { return request.get({ url: '/system/tenant-package/get-simple-list' }) } diff --git a/yudao-ui-admin-vue3/src/api/system/tenantPackage/types.ts b/yudao-ui-admin-vue3/src/api/system/tenantPackage/types.ts deleted file mode 100644 index b67dad77e..000000000 --- a/yudao-ui-admin-vue3/src/api/system/tenantPackage/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type TenantPackageVO = { - id: number - name: string - status: number - remark: string - creator: string - createTime: string - updater: string - updateTime: string - menuIds: string[] -} diff --git a/yudao-ui-admin-vue3/src/api/system/user/index.ts b/yudao-ui-admin-vue3/src/api/system/user/index.ts index 3c989d881..e505921d3 100644 --- a/yudao-ui-admin-vue3/src/api/system/user/index.ts +++ b/yudao-ui-admin-vue3/src/api/system/user/index.ts @@ -1,8 +1,39 @@ import request from '@/config/axios' -import type { UserVO } from './types' + +export interface UserVO { + id: number + username: string + nickname: string + deptId: number + postIds: string[] + email: string + mobile: string + sex: number + avatar: string + loginIp: string + status: number + remark: string + loginDate: Date + createTime: Date +} + +export interface UserPageReqVO extends PageParam { + deptId?: number + username?: string + mobile?: string + status?: number + createTime?: Date[] +} + +export interface UserExportReqVO { + code?: string + name?: string + status?: number + createTime?: Date[] +} // 查询用户管理列表 -export const getUserPageApi = (params) => { +export const getUserPageApi = (params: UserPageReqVO) => { return request.get({ url: '/system/user/page', params }) } @@ -27,7 +58,7 @@ export const deleteUserApi = (id: number) => { } // 导出用户 -export const exportUserApi = (params) => { +export const exportUserApi = (params: UserExportReqVO) => { return request.download({ url: '/system/user/export', params }) } diff --git a/yudao-ui-admin-vue3/src/api/system/user/profile.ts b/yudao-ui-admin-vue3/src/api/system/user/profile.ts new file mode 100644 index 000000000..e78424cc4 --- /dev/null +++ b/yudao-ui-admin-vue3/src/api/system/user/profile.ts @@ -0,0 +1,77 @@ +import request from '@/config/axios' + +export interface ProfileDept { + id: number + name: string +} +export interface ProfileRole { + id: number + name: string +} +export interface ProfilePost { + id: number + name: string +} +export interface SocialUser { + id: number + type: number + openid: string + token: string + rawTokenInfo: string + nickname: string + avatar: string + rawUserInfo: string + code: string + state: string +} +export interface ProfileVO { + id: number + username: string + nickname: string + dept: ProfileDept + roles: ProfileRole[] + posts: ProfilePost[] + socialUsers: SocialUser[] + email: string + mobile: string + sex: number + avatar: string + status: number + remark: string + loginIp: string + loginDate: Date + createTime: Date +} + +export interface UserProfileUpdateReqVO { + nickname: string + email: string + mobile: string + sex: number +} + +// 查询用户个人信息 +export const getUserProfileApi = () => { + return request.get({ url: '/system/user/profile/get' }) +} + +// 修改用户个人信息 +export const updateUserProfileApi = (data: UserProfileUpdateReqVO) => { + return request.put({ url: '/system/user/profile/update', data }) +} + +// 用户密码重置 +export const updateUserPwdApi = (oldPassword: string, newPassword: string) => { + return request.put({ + url: '/system/user/profile/update-password', + data: { + oldPassword: oldPassword, + newPassword: newPassword + } + }) +} + +// 用户头像上传 +export const uploadAvatarApi = (data) => { + return request.upload({ url: '/system/user/profile/update-avatar', data: data }) +} diff --git a/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts b/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts deleted file mode 100644 index 2863452b4..000000000 --- a/yudao-ui-admin-vue3/src/api/system/user/profile/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import request from '@/config/axios' - -// 查询用户个人信息 -export const getUserProfileApi = () => { - return request.get({ url: '/system/user/profile/get' }) -} - -// 修改用户个人信息 -export const updateUserProfileApi = (params) => { - return request.put({ url: '/system/user/profile/update', params }) -} - -// 用户密码重置 -export const updateUserPwdApi = (oldPassword: string, newPassword: string) => { - return request.put({ - url: '/system/user/profile/update-password', - data: { - oldPassword: oldPassword, - newPassword: newPassword - } - }) -} - -// 用户头像上传 -export const uploadAvatarApi = (data) => { - return request.upload({ url: '/system/user/profile/update-avatar', data: data }) -} diff --git a/yudao-ui-admin-vue3/src/api/system/user/profile/types.ts b/yudao-ui-admin-vue3/src/api/system/user/profile/types.ts deleted file mode 100644 index f4d748301..000000000 --- a/yudao-ui-admin-vue3/src/api/system/user/profile/types.ts +++ /dev/null @@ -1,42 +0,0 @@ -export type ProfileDept = { - id: number - name: string -} -export type ProfileRole = { - id: number - name: string -} -export type ProfilePost = { - id: number - name: string -} -export type SocialUser = { - id: number - type: number - openid: string - token: string - rawTokenInfo: string - nickname: string - avatar: string - rawUserInfo: string - code: string - state: string -} -export type ProfileVO = { - id: number - username: string - nickname: string - dept: ProfileDept - roles: ProfileRole[] - posts: ProfilePost[] - socialUsers: SocialUser[] - email: string - mobile: string - sex: number - avatar: string - status: number - remark: string - loginIp: string - loginDate: Date - createTime: Date -} diff --git a/yudao-ui-admin-vue3/src/api/system/user/socialUser.ts b/yudao-ui-admin-vue3/src/api/system/user/socialUser.ts new file mode 100644 index 000000000..79f4d4027 --- /dev/null +++ b/yudao-ui-admin-vue3/src/api/system/user/socialUser.ts @@ -0,0 +1,31 @@ +import request from '@/config/axios' + +// 社交绑定,使用 code 授权码 +export const socialBind = (type, code, state) => { + return request.post({ + url: '/system/social-user/bind', + data: { + type, + code, + state + } + }) +} + +// 取消社交绑定 +export const socialUnbind = (type, openid) => { + return request.delete({ + url: '/system/social-user/unbind', + data: { + type, + openid + } + }) +} + +// 社交授权的跳转 +export const socialAuthRedirect = (type, redirectUri) => { + return request.get({ + url: '/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri + }) +} diff --git a/yudao-ui-admin-vue3/src/api/system/user/types.ts b/yudao-ui-admin-vue3/src/api/system/user/types.ts deleted file mode 100644 index 2102bbe99..000000000 --- a/yudao-ui-admin-vue3/src/api/system/user/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -export type UserVO = { - id: number - username: string - nickname: string - deptId: number - postIds: string[] - email: string - mobile: string - sex: number - avatar: string - loginIp: string - status: number - remark: string - loginDate: string - createTime: string -} diff --git a/yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue b/yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue index da6f8c710..0a55f1523 100644 --- a/yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue +++ b/yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue @@ -14,7 +14,7 @@ const { variables } = useDesign() const appStore = useAppStore() const props = defineProps({ - size: propTypes.oneOf(['default', 'small', 'large']).def('default') + size: propTypes.oneOf(['default', 'small', 'large']).def('default') }) provide('configGlobal', props) diff --git a/yudao-ui-admin-vue3/src/components/ContentDetailWrap/src/ContentDetailWrap.vue b/yudao-ui-admin-vue3/src/components/ContentDetailWrap/src/ContentDetailWrap.vue index 9bab3970a..887357b1a 100644 --- a/yudao-ui-admin-vue3/src/components/ContentDetailWrap/src/ContentDetailWrap.vue +++ b/yudao-ui-admin-vue3/src/components/ContentDetailWrap/src/ContentDetailWrap.vue @@ -2,7 +2,7 @@ import { ElCard } from 'element-plus' import { propTypes } from '@/utils/propTypes' import { useDesign } from '@/hooks/web/useDesign' -import { ref, onMounted, defineEmits } from 'vue' +import { ref, onMounted } from 'vue' import { Sticky } from '@/components/Sticky' import { useI18n } from '@/hooks/web/useI18n' const { t } = useI18n() @@ -24,12 +24,12 @@ onMounted(() => { - diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts deleted file mode 100644 index 78c7c335c..000000000 --- a/yudao-ui-admin-vue3/src/components/Verifition/src/api/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 此处可直接引用自己项目封装好的 axios 配合后端联调 - */ - -import request from './../utils/axios' //组件内部封装的axios -// import request from "@/api/axios.js" //调用项目封装的axios - -//获取验证图片 以及token -export function reqGet(data) { - return request({ - // url: '/captcha/get', - url: '/admin-api/system/captcha/get', // 使用项目自定义的 /admin-api/ 前缀 - method: 'post', - data - }) -} - -//滑动或者点选验证 -export function reqCheck(data) { - return request({ - // url: '/captcha/check', - url: '/admin-api/system/captcha/check', // 使用项目自定义的 /admin-api/ 前缀 - method: 'post', - data - }) -} diff --git a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts b/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts deleted file mode 100644 index ca68097e7..000000000 --- a/yudao-ui-admin-vue3/src/components/Verifition/src/utils/axios.ts +++ /dev/null @@ -1,26 +0,0 @@ -import axios from 'axios' - -axios.defaults.baseURL = import.meta.env.VITE_BASE_URL - -const service = axios.create({ - timeout: 40000, - headers: { - 'X-Requested-With': 'XMLHttpRequest', - 'Content-Type': 'application/json; charset=UTF-8' - } -}) -service.interceptors.request.use( - (config) => { - return config - }, - (error) => { - Promise.reject(error) - } -) - -// response interceptor -service.interceptors.response.use((response) => { - const res = response.data - return res -}) -export default service diff --git a/yudao-ui-admin-vue3/src/components/XButton/src/XButton.vue b/yudao-ui-admin-vue3/src/components/XButton/src/XButton.vue index 6539e73cd..13c35bef3 100644 --- a/yudao-ui-admin-vue3/src/components/XButton/src/XButton.vue +++ b/yudao-ui-admin-vue3/src/components/XButton/src/XButton.vue @@ -35,7 +35,7 @@ const getBindValue = computed(() => { - - diff --git a/yudao-ui-admin-vue3/src/components/Screenfull/index.ts b/yudao-ui-admin-vue3/src/layout/components/Screenfull/index.ts similarity index 100% rename from yudao-ui-admin-vue3/src/components/Screenfull/index.ts rename to yudao-ui-admin-vue3/src/layout/components/Screenfull/index.ts diff --git a/yudao-ui-admin-vue3/src/components/Screenfull/src/Screenfull.vue b/yudao-ui-admin-vue3/src/layout/components/Screenfull/src/Screenfull.vue similarity index 100% rename from yudao-ui-admin-vue3/src/components/Screenfull/src/Screenfull.vue rename to yudao-ui-admin-vue3/src/layout/components/Screenfull/src/Screenfull.vue diff --git a/yudao-ui-admin-vue3/src/components/Setting/index.ts b/yudao-ui-admin-vue3/src/layout/components/Setting/index.ts similarity index 100% rename from yudao-ui-admin-vue3/src/components/Setting/index.ts rename to yudao-ui-admin-vue3/src/layout/components/Setting/index.ts diff --git a/yudao-ui-admin-vue3/src/components/Setting/src/Setting.vue b/yudao-ui-admin-vue3/src/layout/components/Setting/src/Setting.vue similarity index 95% rename from yudao-ui-admin-vue3/src/components/Setting/src/Setting.vue rename to yudao-ui-admin-vue3/src/layout/components/Setting/src/Setting.vue index 558c81c9a..14bb7393d 100644 --- a/yudao-ui-admin-vue3/src/components/Setting/src/Setting.vue +++ b/yudao-ui-admin-vue3/src/layout/components/Setting/src/Setting.vue @@ -1,29 +1,25 @@ @@ -292,10 +290,10 @@ const clear = () => { - diff --git a/yudao-ui-admin-vue3/src/components/Setting/src/components/ColorRadioPicker.vue b/yudao-ui-admin-vue3/src/layout/components/Setting/src/components/ColorRadioPicker.vue similarity index 93% rename from yudao-ui-admin-vue3/src/components/Setting/src/components/ColorRadioPicker.vue rename to yudao-ui-admin-vue3/src/layout/components/Setting/src/components/ColorRadioPicker.vue index bc40e1067..9787ea7f8 100644 --- a/yudao-ui-admin-vue3/src/components/Setting/src/components/ColorRadioPicker.vue +++ b/yudao-ui-admin-vue3/src/layout/components/Setting/src/components/ColorRadioPicker.vue @@ -54,10 +54,10 @@ watch( - diff --git a/yudao-ui-admin-vue3/src/components/UserInfo/index.ts b/yudao-ui-admin-vue3/src/layout/components/UserInfo/index.ts similarity index 100% rename from yudao-ui-admin-vue3/src/components/UserInfo/index.ts rename to yudao-ui-admin-vue3/src/layout/components/UserInfo/index.ts diff --git a/yudao-ui-admin-vue3/src/components/UserInfo/src/UserInfo.vue b/yudao-ui-admin-vue3/src/layout/components/UserInfo/src/UserInfo.vue similarity index 95% rename from yudao-ui-admin-vue3/src/components/UserInfo/src/UserInfo.vue rename to yudao-ui-admin-vue3/src/layout/components/UserInfo/src/UserInfo.vue index 33dd11ddd..cdce9ddf5 100644 --- a/yudao-ui-admin-vue3/src/components/UserInfo/src/UserInfo.vue +++ b/yudao-ui-admin-vue3/src/layout/components/UserInfo/src/UserInfo.vue @@ -1,7 +1,7 @@ - - diff --git a/yudao-ui-admin-vue3/src/views/Error/404.vue b/yudao-ui-admin-vue3/src/views/Error/404.vue index fffedd89f..b8f121f26 100644 --- a/yudao-ui-admin-vue3/src/views/Error/404.vue +++ b/yudao-ui-admin-vue3/src/views/Error/404.vue @@ -1,3 +1,6 @@ + - - diff --git a/yudao-ui-admin-vue3/src/views/Error/500.vue b/yudao-ui-admin-vue3/src/views/Error/500.vue index 2898cfe7b..d9f3ede46 100644 --- a/yudao-ui-admin-vue3/src/views/Error/500.vue +++ b/yudao-ui-admin-vue3/src/views/Error/500.vue @@ -1,3 +1,6 @@ + - - diff --git a/yudao-ui-admin-vue3/src/views/Home/Index.vue b/yudao-ui-admin-vue3/src/views/Home/Index.vue index db371fb03..07ab61be3 100644 --- a/yudao-ui-admin-vue3/src/views/Home/Index.vue +++ b/yudao-ui-admin-vue3/src/views/Home/Index.vue @@ -1,23 +1,187 @@ - - - diff --git a/yudao-ui-admin-vue3/src/views/Home/Index2.vue b/yudao-ui-admin-vue3/src/views/Home/Index2.vue index fb5db7dcd..de91eb54c 100644 --- a/yudao-ui-admin-vue3/src/views/Home/Index2.vue +++ b/yudao-ui-admin-vue3/src/views/Home/Index2.vue @@ -1,133 +1,3 @@ - - - diff --git a/yudao-ui-admin-vue3/src/views/Profile/components/UserSocial.vue b/yudao-ui-admin-vue3/src/views/Profile/components/UserSocial.vue index 3cbc28b7b..ee94dcfee 100644 --- a/yudao-ui-admin-vue3/src/views/Profile/components/UserSocial.vue +++ b/yudao-ui-admin-vue3/src/views/Profile/components/UserSocial.vue @@ -1,54 +1,70 @@ -