From 04b4e090bd5fe98933caf5008e885329cee59915 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 27 Nov 2023 18:35:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=9C=80=E6=96=B0=20master?= =?UTF-8?q?=20=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 30 +- .../framework/weixin/WxMpServiceTest.java | 34 --- .../yudao-spring-boot-starter-mq/pom.xml | 2 +- .../mq/core/bus/AbstractBusProducer.java | 40 --- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../bpm/service/oa/BpmOALeaveServiceImpl.java | 2 +- .../bpm/service/task/BpmTaskService.java | 66 ++++- .../bpm/service/task/BpmTaskServiceImpl.java | 1 - .../admin/test/TestDemoController.java | 97 ------- .../admin/test/vo/TestDemoBaseVO.java | 33 --- .../service/codegen/CodegenServiceImpl.java | 45 ++- .../service/codegen/inner/CodegenBuilder.java | 2 +- .../service/codegen/inner/CodegenEngine.java | 259 +++++++++++++++--- .../logger/ApiAccessLogServiceImpl.java | 20 ++ .../logger/ApiErrorLogServiceImpl.java | 19 ++ .../infra/service/test/TestDemoService.java | 75 ----- .../service/test/TestDemoServiceImpl.java | 91 ------ .../config/SecurityConfiguration.java | 15 +- .../config/SecurityConfiguration.java | 15 +- .../config/SecurityConfiguration.java | 13 +- .../config/SecurityConfiguration.java | 15 +- .../order/TradeOrderUpdateServiceImpl.java | 2 +- .../module/pay/api/order/PayOrderApi.java | 17 +- .../module/pay/api/refund/PayRefundApi.java | 5 +- .../module/pay/api/order/PayOrderApiImpl.java | 17 +- .../pay/api/refund/PayRefundApiImpl.java | 11 +- .../system/api/social/SocialUserApi.java | 20 +- .../api/social/dto/SocialUserBindReqDTO.java | 2 +- .../social/dto/SocialUserUnbindReqDTO.java | 4 +- .../controller/admin/auth/AuthController.java | 18 +- .../controller/admin/dept/PostController.java | 37 ++- .../admin/dept/vo/post/PostSaveReqVO.java | 21 +- .../admin/dept/vo/post/PostUpdateReqVO.java | 17 -- .../admin/tenant/vo/tenant/TenantBaseVO.java | 2 +- .../service/auth/AdminAuthServiceImpl.java | 7 +- .../system/service/sms/SmsLogServiceImpl.java | 10 +- .../service/sms/SmsSendServiceImpl.java | 20 +- .../service/social/SocialClientService.java | 3 +- .../social/SocialClientServiceImpl.java | 2 +- .../service/social/SocialUserService.java | 63 ++--- .../service/social/SocialUserServiceImpl.java | 132 +++++---- 41 files changed, 629 insertions(+), 657 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/bus/AbstractBusProducer.java delete mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java delete mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java delete mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java delete mode 100755 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index ae7766c57..2fbf6eec2 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.8.2-snapshot + 1.8.3-snapshot 1.5.0 3.1.4 @@ -24,6 +24,8 @@ 2.5 2.2.0 4.3.0 + + 2.2.3 1.2.19 3.5.3.2 @@ -133,11 +135,6 @@ yudao-spring-boot-starter-biz-pay ${revision} - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-weixin - ${revision} - cn.iocoder.cloud yudao-spring-boot-starter-biz-tenant @@ -148,11 +145,6 @@ yudao-spring-boot-starter-biz-data-permission ${revision} - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-social - ${revision} - cn.iocoder.cloud yudao-spring-boot-starter-biz-error-code @@ -201,6 +193,12 @@ ${revision} + + cn.iocoder.cloud + yudao-spring-boot-starter-websocket + ${revision} + + com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter @@ -298,6 +296,12 @@ ${revision} + + org.apache.rocketmq + rocketmq-spring-boot-starter + ${rocketmq-spring.version} + + cn.iocoder.cloud @@ -616,12 +620,12 @@ com.github.binarywang - weixin-java-mp + wx-java-mp-spring-boot-starter ${weixin-java.version} com.github.binarywang - wx-java-mp-spring-boot-starter + wx-java-miniapp-spring-boot-starter ${weixin-java.version} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java b/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java deleted file mode 100644 index 3ac1d5b63..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.framework.weixin; - -import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.mp.api.WxMpService; -import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; - -import jakarta.annotation.Resource; - -@SpringBootTest(classes = WxMpServiceTest.Application.class) -public class WxMpServiceTest { - - @Resource - private WxMpService wxMpService; - - @Test - public void testGetAccessToken() throws WxErrorException { - String accessToken = wxMpService.getAccessToken(); - System.out.println(accessToken); - } - - @Test - public void testGet() throws WxErrorException { - String jsapiTicket = wxMpService.getJsapiTicket(); - System.out.println(jsapiTicket); - } - - @SpringBootApplication - public static class Application { - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-mq/pom.xml b/yudao-framework/yudao-spring-boot-starter-mq/pom.xml index 504d2711c..8d669eddb 100644 --- a/yudao-framework/yudao-spring-boot-starter-mq/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mq/pom.xml @@ -40,4 +40,4 @@ - + \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/bus/AbstractBusProducer.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/bus/AbstractBusProducer.java deleted file mode 100644 index c690fc131..000000000 --- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/core/bus/AbstractBusProducer.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.framework.mq.core.bus; - -import jakarta.annotation.Resource; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cloud.bus.ServiceMatcher; -import org.springframework.cloud.bus.event.RemoteApplicationEvent; -import org.springframework.context.ApplicationEventPublisher; - -/** - * 基于 Spring Cloud Bus 实现的 Producer 抽象类 - * - * @author 芋道源码 - */ -public abstract class AbstractBusProducer { - - @Resource - protected ApplicationEventPublisher applicationEventPublisher; - - @Resource - protected ServiceMatcher serviceMatcher; - - @Value("${spring.application.name}") - protected String applicationName; - - protected void publishEvent(RemoteApplicationEvent event) { - applicationEventPublisher.publishEvent(event); - } - - /** - * @return 只广播给自己服务的实例 - */ - protected String selfDestinationService() { - return applicationName + ":**"; - } - - protected String getBusId() { - return serviceMatcher.getBusId(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4b98f6110..213850b94 100644 --- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,3 +1,3 @@ cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQProducerAutoConfiguration cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration -cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration +cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration \ No newline at end of file diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java index 294d3660f..7b6525e64 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOALeaveServiceImpl.java @@ -56,7 +56,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService { processInstanceVariables.put("day", day); String processInstanceId = processInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) - .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))).getCheckedData(); + .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))); // 将工作流的编号,更新到 OA 请假单中 leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId)); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index 400f81ed9..9ed5900e6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.service.task; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; +import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; import jakarta.validation.Valid; import org.flowable.task.api.Task; @@ -22,7 +23,6 @@ public interface BpmTaskService { * * @param userId 用户编号 * @param pageReqVO 分页请求 - * * @return 流程任务分页 */ PageResult getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO); @@ -32,7 +32,6 @@ public interface BpmTaskService { * * @param userId 用户编号 * @param pageReqVO 分页请求 - * * @return 流程任务分页 */ PageResult getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO); @@ -41,19 +40,17 @@ public interface BpmTaskService { * 获得流程任务 Map * * @param processInstanceIds 流程实例的编号数组 - * * @return 流程任务 Map */ default Map> getTaskMapByProcessInstanceIds(List processInstanceIds) { return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds), - Task::getProcessInstanceId); + Task::getProcessInstanceId); } /** * 获得流程任务列表 * * @param processInstanceIds 流程实例的编号数组 - * * @return 流程任务列表 */ List getTasksByProcessInstanceIds(List processInstanceIds); @@ -62,11 +59,19 @@ public interface BpmTaskService { * 获得指令流程实例的流程任务列表,包括所有状态的 * * @param processInstanceId 流程实例的编号 - * * @return 流程任务列表 */ List getTaskListByProcessInstanceId(String processInstanceId); + + /** + * 通过任务 ID 集合,获取任务扩展表信息集合 + * + * @param taskIdList 任务 ID 集合 + * @return 任务列表 + */ + List getTaskListByTaskIdList(List taskIdList); + /** * 通过任务 * @@ -127,4 +132,53 @@ public interface BpmTaskService { */ void updateTaskExtAssign(Task task); + /** + * 获取当前任务的可回退的流程集合 + * + * @param taskId 当前的任务 ID + * @return 可以回退的节点列表 + */ + List getReturnTaskList(String taskId); + + /** + * 将任务回退到指定的 targetDefinitionKey 位置 + * + * @param userId 用户编号 + * @param reqVO 回退的任务key和当前所在的任务ID + */ + void returnTask(Long userId, BpmTaskReturnReqVO reqVO); + + + /** + * 将指定任务委派给其他人处理,等接收人处理后再回到原审批人手中审批 + * + * @param userId 用户编号 + * @param reqVO 被委派人和被委派的任务编号理由参数 + */ + void delegateTask(Long userId, BpmTaskDelegateReqVO reqVO); + + /** + * 任务加签 + * + * @param userId 被加签的用户和任务 ID,加签类型 + * @param reqVO 当前用户 ID + */ + void createSignTask(Long userId, BpmTaskAddSignReqVO reqVO); + + /** + * 任务减签名 + * + * @param userId 当前用户ID + * @param reqVO 被减签的任务 ID,理由 + */ + void deleteSignTask(Long userId, BpmTaskSubSignReqVO reqVO); + + /** + * 获取指定任务的子任务和审批人信息 + * + * @param parentId 指定任务ID + * @return 子任务列表 + */ + List getChildrenTaskList(String parentId); + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index cc937be42..33ef4b07f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -58,7 +58,6 @@ import java.util.stream.Stream; 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.bpm.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_TARGET_NODE_NOT_EXISTS; /** * 流程任务实例 Service 实现类 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java deleted file mode 100755 index 828059ca4..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.*; -import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import cn.iocoder.yudao.module.infra.service.test.TestDemoService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Tag(name = "管理后台 - 字典类型") -@RestController -@RequestMapping("/infra/test-demo") -@Validated -public class TestDemoController { - - @Resource - private TestDemoService testDemoService; - - @PostMapping("/create") - @Operation(summary = "创建字典类型") - @PreAuthorize("@ss.hasPermission('infra:test-demo:create')") - public CommonResult createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) { - return success(testDemoService.createTestDemo(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新字典类型") - @PreAuthorize("@ss.hasPermission('infra:test-demo:update')") - public CommonResult updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) { - testDemoService.updateTestDemo(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除字典类型") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:test-demo:delete')") - public CommonResult deleteTestDemo(@RequestParam("id") Long id) { - testDemoService.deleteTestDemo(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得字典类型") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('infra:test-demo:query')") - public CommonResult getTestDemo(@RequestParam("id") Long id) { - TestDemoDO testDemo = testDemoService.getTestDemo(id); - return success(TestDemoConvert.INSTANCE.convert(testDemo)); - } - - @GetMapping("/list") - @Operation(summary = "获得字典类型列表") - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") - @PreAuthorize("@ss.hasPermission('infra:test-demo:query')") - public CommonResult> getTestDemoList(@RequestParam("ids") Collection ids) { - List list = testDemoService.getTestDemoList(ids); - return success(TestDemoConvert.INSTANCE.convertList(list)); - } - - @GetMapping("/page") - @Operation(summary = "获得字典类型分页") - @PreAuthorize("@ss.hasPermission('infra:test-demo:query')") public CommonResult> getTestDemoPage(@Valid TestDemoPageReqVO pageVO) { - PageResult pageResult = testDemoService.getTestDemoPage(pageVO); - return success(TestDemoConvert.INSTANCE.convertPage(pageResult)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出字典类型 Excel") - @PreAuthorize("@ss.hasPermission('infra:test-demo:export')") @OperateLog(type = EXPORT) - public void exportTestDemoExcel(@Valid TestDemoExportReqVO exportReqVO, - HttpServletResponse response) throws IOException { - List list = testDemoService.getTestDemoList(exportReqVO); - // 导出 Excel - List datas = TestDemoConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "字典类型.xls", "数据", TestDemoExcelVO.class, datas); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java deleted file mode 100755 index d58c5afbc..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -/** -* 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class TestDemoBaseVO { - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "名字不能为空") - private String name; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "状态不能为空") - private Integer status; - - @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "类型不能为空") - private Integer type; - - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "分类不能为空") - private Integer category; - - @Schema(description = "备注") - private String remark; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java index 7c8291f63..c3656fa36 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; @@ -25,10 +26,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.BiPredicate; import java.util.stream.Collectors; @@ -129,6 +127,16 @@ public class CodegenServiceImpl implements CodegenService { if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } + // 校验主表字段存在 + if (Objects.equals(updateReqVO.getTable().getTemplateType(), CodegenTemplateTypeEnum.SUB.getType())) { + if (codegenTableMapper.selectById(updateReqVO.getTable().getMasterTableId()) == null) { + throw exception(CODEGEN_MASTER_TABLE_NOT_EXISTS, updateReqVO.getTable().getMasterTableId()); + } + if (CollUtil.findOne(updateReqVO.getColumns(), // 关联主表的字段不存在 + column -> column.getId().equals(updateReqVO.getTable().getSubJoinColumnId())) == null) { + throw exception(CODEGEN_SUB_COLUMN_NOT_EXISTS, updateReqVO.getTable().getSubJoinColumnId()); + } + } // 更新 table 表定义 CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable()); @@ -208,6 +216,11 @@ public class CodegenServiceImpl implements CodegenService { codegenColumnMapper.deleteListByTableId(tableId); } + @Override + public List getCodegenTableList(Long dataSourceConfigId) { + return codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId); + } + @Override public PageResult getCodegenTablePage(CodegenTablePageReqVO pageReqVO) { return codegenTableMapper.selectPage(pageReqVO); @@ -235,14 +248,34 @@ public class CodegenServiceImpl implements CodegenService { throw exception(CODEGEN_COLUMN_NOT_EXISTS); } + // 如果是主子表,则加载对应的子表信息 + List subTables = null; + List> subColumnsList = null; + if (CodegenTemplateTypeEnum.isMaster(table.getTemplateType())) { + // 校验子表存在 + subTables = codegenTableMapper.selectListByTemplateTypeAndMasterTableId( + CodegenTemplateTypeEnum.SUB.getType(), tableId); + if (CollUtil.isEmpty(subTables)) { + throw exception(CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE); + } + // 校验子表的关联字段存在 + subColumnsList = new ArrayList<>(); + for (CodegenTableDO subTable : subTables) { + List subColumns = codegenColumnMapper.selectListByTableId(subTable.getId()); + if (CollUtil.findOne(subColumns, column -> column.getId().equals(subTable.getSubJoinColumnId())) == null) { + throw exception(CODEGEN_SUB_COLUMN_NOT_EXISTS, subTable.getId()); + } + subColumnsList.add(subColumns); + } + } + // 执行生成 - return codegenEngine.execute(table, columns); + return codegenEngine.execute(table, columns, subTables, subColumnsList); } @Override public List getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { List tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); - // 移除已经生成的表 // 移除在 Codegen 中,已经存在的 Set existsTables = CollectionUtils.convertSet( codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName); 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 b529c4981..13402c7d6 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 @@ -64,7 +64,7 @@ public class CodegenBuilder { */ public static final String TENANT_ID_FIELD = "tenantId"; /** - * {@link cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO} 的字段 + * {@link BaseDO} 的字段 */ public static final Set BASE_DO_FIELDS = new HashSet<>(); /** 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 d8d89793c..61a6d2e0c 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 @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.template.TemplateConfig; import cn.hutool.extra.template.TemplateEngine; @@ -12,7 +14,9 @@ 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.DateUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -25,7 +29,9 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Maps; import com.google.common.collect.Table; @@ -33,10 +39,7 @@ import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.hutool.core.map.MapUtil.getStr; import static cn.hutool.core.text.CharSequenceUtil.*; @@ -60,20 +63,19 @@ public class CodegenEngine { */ private static final Map SERVER_TEMPLATES = MapUtil.builder(new LinkedHashMap<>()) // 有序 // Java module-biz Main - .put(javaTemplatePath("controller/vo/baseVO"), javaModuleImplVOFilePath("BaseVO")) - .put(javaTemplatePath("controller/vo/createReqVO"), javaModuleImplVOFilePath("CreateReqVO")) .put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO")) + .put(javaTemplatePath("controller/vo/listReqVO"), javaModuleImplVOFilePath("ListReqVO")) .put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO")) - .put(javaTemplatePath("controller/vo/updateReqVO"), javaModuleImplVOFilePath("UpdateReqVO")) - .put(javaTemplatePath("controller/vo/exportReqVO"), javaModuleImplVOFilePath("ExportReqVO")) - .put(javaTemplatePath("controller/vo/excelVO"), javaModuleImplVOFilePath("ExcelVO")) + .put(javaTemplatePath("controller/vo/saveReqVO"), javaModuleImplVOFilePath("SaveReqVO")) .put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath()) - .put(javaTemplatePath("convert/convert"), - javaModuleImplMainFilePath("convert/${table.businessName}/${table.className}Convert")) .put(javaTemplatePath("dal/do"), javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO")) + .put(javaTemplatePath("dal/do_sub"), // 特殊:主子表专属逻辑 + javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${subTable.className}DO")) .put(javaTemplatePath("dal/mapper"), javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${table.className}Mapper")) + .put(javaTemplatePath("dal/mapper_sub"), // 特殊:主子表专属逻辑 + javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${subTable.className}Mapper")) .put(javaTemplatePath("dal/mapper.xml"), mapperXmlFilePath()) .put(javaTemplatePath("service/serviceImpl"), javaModuleImplMainFilePath("service/${table.businessName}/${table.className}ServiceImpl")) @@ -99,34 +101,44 @@ public class CodegenEngine { private static final Table FRONT_TEMPLATES = ImmutableTable.builder() // Vue2 标准模版 .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/index.vue"), - vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vueFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("api/api.js"), vueFilePath("api/${table.moduleName}/${classNameVar}.js")) // Vue3 标准模版 .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_erp.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_inner.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_erp.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // Vue3 Schema 模版 .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // Vue3 vben 模版 .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Modal.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .build(); @Resource @@ -149,7 +161,8 @@ public class CodegenEngine { } @PostConstruct - private void initGlobalBindingMap() { + @VisibleForTesting + void initGlobalBindingMap() { // 全局配置 globalBindingMap.put("basePackage", codegenProperties.getBasePackage()); globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage() @@ -174,9 +187,122 @@ public class CodegenEngine { globalBindingMap.put("DictConvertClassName", DictConvert.class.getName()); globalBindingMap.put("OperateLogClassName", OperateLog.class.getName()); globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName()); + globalBindingMap.put("BeanUtils", BeanUtils.class.getName()); } - public Map execute(CodegenTableDO table, List columns) { + /** + * 生成代码 + * + * @param table 表定义 + * @param columns table 的字段定义数组 + * @param subTables 子表数组,当且仅当主子表时使用 + * @param subColumnsList subTables 的字段定义数组 + * @return 生成的代码,key 是路径,value 是对应代码 + */ + public Map execute(CodegenTableDO table, List columns, + List subTables, List> subColumnsList) { + // 1.1 初始化 bindMap 上下文 + Map bindingMap = initBindingMap(table, columns, subTables, subColumnsList); + // 1.2 获得模版 + Map templates = getTemplates(table.getFrontType()); + + // 2. 执行生成 + Map result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 + templates.forEach((vmPath, filePath) -> { + // 2.1 特殊:主子表专属逻辑 + if (isSubTemplate(vmPath)) { + generateSubCode(table, subTables, result, vmPath, filePath, bindingMap); + return; + // 2.2 特殊:树表专属逻辑 + } else if (isPageReqVOTemplate(vmPath)) { + // 减少多余的类生成,例如说 PageVO.java 类 + if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { + return; + } + } else if (isListReqVOTemplate(vmPath)) { + // 减少多余的类生成,例如说 ListVO.java 类 + if (!CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { + return; + } + } + // 2.3 默认生成 + generateCode(result, vmPath, filePath, bindingMap); + }); + return result; + } + + private void generateCode(Map result, String vmPath, + String filePath, Map bindingMap) { + filePath = formatFilePath(filePath, bindingMap); + String content = templateEngine.getTemplate(vmPath).render(bindingMap); + // 格式化代码 + content = prettyCode(content); + result.put(filePath, content); + } + + private void generateSubCode(CodegenTableDO table, List subTables, + Map result, String vmPath, + String filePath, Map bindingMap) { + // 没有子表,所以不生成 + if (CollUtil.isEmpty(subTables)) { + return; + } + // 主子表的模式匹配。目的:过滤掉个性化的模版 + if (vmPath.contains("_normal") + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_NORMAL.getType())) { + return; + } + if (vmPath.contains("_erp") + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_ERP.getType())) { + return; + } + if (vmPath.contains("_inner") + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_INNER.getType())) { + return; + } + + // 逐个生成 + for (int i = 0; i < subTables.size(); i++) { + bindingMap.put("subIndex", i); + generateCode(result, vmPath, filePath, bindingMap); + } + bindingMap.remove("subIndex"); + } + + /** + * 格式化生成后的代码 + * + * 因为尽量让 vm 模版简单,所以统一的处理都在这个方法。 + * 如果不处理,Vue 的 Pretty 格式校验可能会报错 + * + * @param content 格式化前的代码 + * @return 格式化后的代码 + */ + private String prettyCode(String content) { + // Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错 + content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }"); + // Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到 + if (StrUtil.count(content, "dateFormatter") == 1) { + content = StrUtils.removeLineContains(content, "dateFormatter"); + } + // Vue 界面:去除多的 dict 相关,只有一个的情况下,说明没使用到 + if (StrUtil.count(content, "getIntDictOptions") == 1) { + content = content.replace("getIntDictOptions, ", ""); + } + if (StrUtil.count(content, "getStrDictOptions") == 1) { + content = content.replace("getStrDictOptions, ", ""); + } + if (StrUtil.count(content, "getBoolDictOptions") == 1) { + content = content.replace("getBoolDictOptions, ", ""); + } + if (StrUtil.count(content, "DICT_TYPE.") == 0) { + content = StrUtils.removeLineContains(content, "DICT_TYPE"); + } + return content; + } + + private Map initBindingMap(CodegenTableDO table, List columns, + List subTables, List> subColumnsList) { // 创建 bindingMap Map bindingMap = new HashMap<>(globalBindingMap); bindingMap.put("table", table); @@ -196,17 +322,54 @@ public class CodegenEngine { // permission 前缀 bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase); - // 执行生成 - Map templates = getTemplates(table.getFrontType()); - Map result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 - templates.forEach((vmPath, filePath) -> { - filePath = formatFilePath(filePath, bindingMap); - String content = templateEngine.getTemplate(vmPath).render(bindingMap); - // 去除字段后面多余的 , 逗号 - content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }"); - result.put(filePath, content); - }); - return result; + // 特殊:树表专属逻辑 + if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { + CodegenColumnDO treeParentColumn = CollUtil.findOne(columns, + column -> Objects.equals(column.getId(), table.getTreeParentColumnId())); + bindingMap.put("treeParentColumn", treeParentColumn); + bindingMap.put("treeParentColumn_javaField_underlineCase", toUnderlineCase(treeParentColumn.getJavaField())); + CodegenColumnDO treeNameColumn = CollUtil.findOne(columns, + column -> Objects.equals(column.getId(), table.getTreeNameColumnId())); + bindingMap.put("treeNameColumn", treeNameColumn); + bindingMap.put("treeNameColumn_javaField_underlineCase", toUnderlineCase(treeNameColumn.getJavaField())); + } + + // 特殊:主子表专属逻辑 + if (CollUtil.isNotEmpty(subTables)) { + // 创建 bindingMap + bindingMap.put("subTables", subTables); + bindingMap.put("subColumnsList", subColumnsList); + List subPrimaryColumns = new ArrayList<>(); + List subJoinColumns = new ArrayList<>(); + List subJoinColumnStrikeCases = new ArrayList<>(); + List subSimpleClassNames = new ArrayList<>(); + List subClassNameVars = new ArrayList<>(); + List simpleClassNameUnderlineCases = new ArrayList<>(); + List subSimpleClassNameStrikeCases = new ArrayList<>(); + for (int i = 0; i < subTables.size(); i++) { + CodegenTableDO subTable = subTables.get(i); + List subColumns = subColumnsList.get(i); + subPrimaryColumns.add(CollectionUtils.findFirst(subColumns, CodegenColumnDO::getPrimaryKey)); // + CodegenColumnDO subColumn = CollectionUtils.findFirst(subColumns, // 关联的字段 + column -> Objects.equals(column.getId(), subTable.getSubJoinColumnId())); + subJoinColumns.add(subColumn); + subJoinColumnStrikeCases.add(toSymbolCase(subColumn.getJavaField(), '-')); // 将 DictType 转换成 dict-type + // className 相关 + String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName())); + subSimpleClassNames.add(subSimpleClassName); + simpleClassNameUnderlineCases.add(toUnderlineCase(subSimpleClassName)); // 将 DictType 转换成 dict_type + subClassNameVars.add(lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType,用于变量 + subSimpleClassNameStrikeCases.add(toSymbolCase(subSimpleClassName, '-')); // 将 DictType 转换成 dict-type + } + bindingMap.put("subPrimaryColumns", subPrimaryColumns); + bindingMap.put("subJoinColumns", subJoinColumns); + bindingMap.put("subJoinColumn_strikeCases", subJoinColumnStrikeCases); + bindingMap.put("subSimpleClassNames", subSimpleClassNames); + bindingMap.put("simpleClassNameUnderlineCases", simpleClassNameUnderlineCases); + bindingMap.put("subClassNameVars", subClassNameVars); + bindingMap.put("subSimpleClassName_strikeCases", subSimpleClassNameStrikeCases); + } + return bindingMap; } private Map getTemplates(Integer frontType) { @@ -216,6 +379,7 @@ public class CodegenEngine { return templates; } + @SuppressWarnings("unchecked") private String formatFilePath(String filePath, Map bindingMap) { filePath = StrUtil.replace(filePath, "${basePackage}", getStr(bindingMap, "basePackage").replaceAll("\\.", "/")); @@ -232,6 +396,16 @@ public class CodegenEngine { filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName()); filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName()); filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName()); + // 特殊:主子表专属逻辑 + Integer subIndex = (Integer) bindingMap.get("subIndex"); + if (subIndex != null) { + CodegenTableDO subTable = ((List) bindingMap.get("subTables")).get(subIndex); + filePath = StrUtil.replace(filePath, "${subTable.moduleName}", subTable.getModuleName()); + filePath = StrUtil.replace(filePath, "${subTable.businessName}", subTable.getBusinessName()); + filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName()); + filePath = StrUtil.replace(filePath, "${subSimpleClassName}", + ((List) bindingMap.get("subSimpleClassNames")).get(subIndex)); + } return filePath; } @@ -298,4 +472,17 @@ public class CodegenEngine { private static String vue3VbenTemplatePath(String path) { return "codegen/vue3_vben/" + path + ".vm"; } + + private static boolean isSubTemplate(String path) { + return path.contains("_sub"); + } + + private static boolean isPageReqVOTemplate(String path) { + return path.contains("pageReqVO"); + } + + private static boolean isListReqVOTemplate(String path) { + return path.contains("listReqVO"); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java index 21207c389..f435446f2 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java @@ -8,9 +8,11 @@ import cn.iocoder.yudao.module.infra.convert.logger.ApiAccessLogConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiAccessLogMapper; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.List; /** @@ -18,6 +20,7 @@ import java.util.List; * * @author 芋道源码 */ +@Slf4j @Service @Validated public class ApiAccessLogServiceImpl implements ApiAccessLogService { @@ -41,4 +44,21 @@ public class ApiAccessLogServiceImpl implements ApiAccessLogService { return apiAccessLogMapper.selectList(exportReqVO); } + @Override + @SuppressWarnings("DuplicatedCode") + public Integer cleanAccessLog(Integer exceedDay, Integer deleteLimit) { + int count = 0; + LocalDateTime expireDate = LocalDateTime.now().minusDays(exceedDay); + // 循环删除,直到没有满足条件的数据 + for (int i = 0; i < Short.MAX_VALUE; i++) { + int deleteCount = apiAccessLogMapper.deleteByCreateTimeLt(expireDate, deleteLimit); + count += deleteCount; + // 达到删除预期条数,说明到底了 + if (deleteCount < deleteLimit) { + break; + } + } + return count; + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java index ef4acdd49..00dcd6628 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper; import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -24,6 +25,7 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_L * * @author 芋道源码 */ +@Slf4j @Service @Validated public class ApiErrorLogServiceImpl implements ApiErrorLogService { @@ -62,4 +64,21 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService { .processUserId(processUserId).processTime(LocalDateTime.now()).build()); } + @Override + @SuppressWarnings("DuplicatedCode") + public Integer cleanErrorLog(Integer exceedDay, Integer deleteLimit) { + int count = 0; + LocalDateTime expireDate = LocalDateTime.now().minusDays(exceedDay); + // 循环删除,直到没有满足条件的数据 + for (int i = 0; i < Short.MAX_VALUE; i++) { + int deleteCount = apiErrorLogMapper.deleteByCreateTimeLt(expireDate, deleteLimit); + count += deleteCount; + // 达到删除预期条数,说明到底了 + if (deleteCount < deleteLimit) { + break; + } + } + return count; + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java deleted file mode 100755 index 813a181b1..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.module.infra.service.test; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import jakarta.validation.Valid; - -import java.util.Collection; -import java.util.List; - -/** - * 字典类型 Service 接口 - * - * @author 芋道源码 - */ -public interface TestDemoService { - - /** - * 创建字典类型 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createTestDemo(@Valid TestDemoCreateReqVO createReqVO); - - /** - * 更新字典类型 - * - * @param updateReqVO 更新信息 - */ - void updateTestDemo(@Valid TestDemoUpdateReqVO updateReqVO); - - /** - * 删除字典类型 - * - * @param id 编号 - */ - void deleteTestDemo(Long id); - - /** - * 获得字典类型 - * - * @param id 编号 - * @return 字典类型 - */ - TestDemoDO getTestDemo(Long id); - - /** - * 获得字典类型列表 - * - * @param ids 编号 - * @return 字典类型列表 - */ - List getTestDemoList(Collection ids); - - /** - * 获得字典类型分页 - * - * @param pageReqVO 分页查询 - * @return 字典类型分页 - */ - PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO); - - /** - * 获得字典类型列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 字典类型列表 - */ - List getTestDemoList(TestDemoExportReqVO exportReqVO); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java deleted file mode 100755 index 65e9f13a9..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.iocoder.yudao.module.infra.service.test; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO; -import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import cn.iocoder.yudao.module.infra.dal.mysql.test.TestDemoMapper; -import jakarta.annotation.Resource; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -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.infra.enums.ErrorCodeConstants.TEST_DEMO_NOT_EXISTS; - -/** - * 字典类型 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class TestDemoServiceImpl implements TestDemoService { - - @Resource - private TestDemoMapper testDemoMapper; - - @Override - public Long createTestDemo(TestDemoCreateReqVO createReqVO) { - // 插入 - TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO); - testDemoMapper.insert(testDemo); - // 返回 - return testDemo.getId(); - } - - @Override - @CacheEvict(value = "test", key = "#updateReqVO.id") - public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) { - // 校验存在 - validateTestDemoExists(updateReqVO.getId()); - // 更新 - TestDemoDO updateObj = TestDemoConvert.INSTANCE.convert(updateReqVO); - testDemoMapper.updateById(updateObj); - } - - @Override - @CacheEvict(value = "test", key = "#id") - public void deleteTestDemo(Long id) { - // 校验存在 - validateTestDemoExists(id); - // 删除 - testDemoMapper.deleteById(id); - } - - private void validateTestDemoExists(Long id) { - if (testDemoMapper.selectById(id) == null) { - throw exception(TEST_DEMO_NOT_EXISTS); - } - } - - @Override - @Cacheable(cacheNames = "test", key = "#id") - public TestDemoDO getTestDemo(Long id) { - return testDemoMapper.selectById(id); - } - - @Override - public List getTestDemoList(Collection ids) { - return testDemoMapper.selectBatchIds(ids); - } - - @Override - public PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO) { -// testDemoMapper.selectList2(); - return testDemoMapper.selectPage(pageReqVO); - } - - @Override - public List getTestDemoList(TestDemoExportReqVO exportReqVO) { - return testDemoMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/security/config/SecurityConfiguration.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/security/config/SecurityConfiguration.java index dbfb9f445..37e55d2b3 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/security/config/SecurityConfiguration.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/framework/security/config/SecurityConfiguration.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.product.enums.ApiConstants; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** @@ -18,17 +19,17 @@ public class SecurityConfiguration { return new AuthorizeRequestsCustomizer() { @Override - public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { // Swagger 接口文档 - registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 - .antMatchers("/swagger-ui.html").permitAll(); // Swagger UI + registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据 + .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI // Spring Boot Actuator 的安全配置 - registry.antMatchers("/actuator").anonymous() - .antMatchers("/actuator/**").anonymous(); + registry.requestMatchers("/actuator").anonymous() + .requestMatchers("/actuator/**").anonymous(); // Druid 监控 - registry.antMatchers("/druid/**").anonymous(); + registry.requestMatchers("/druid/**").anonymous(); // RPC 服务的安全配置 - registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); + registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll(); } }; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/framework/security/config/SecurityConfiguration.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/framework/security/config/SecurityConfiguration.java index 3dbee4f06..a36474e5e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/framework/security/config/SecurityConfiguration.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/framework/security/config/SecurityConfiguration.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.enums.ApiConstants; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** @@ -18,17 +19,17 @@ public class SecurityConfiguration { return new AuthorizeRequestsCustomizer() { @Override - public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { // Swagger 接口文档 - registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 - .antMatchers("/swagger-ui.html").permitAll(); // Swagger UI + registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据 + .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI // Spring Boot Actuator 的安全配置 - registry.antMatchers("/actuator").anonymous() - .antMatchers("/actuator/**").anonymous(); + registry.requestMatchers("/actuator").anonymous() + .requestMatchers("/actuator/**").anonymous(); // Druid 监控 - registry.antMatchers("/druid/**").anonymous(); + registry.requestMatchers("/druid/**").anonymous(); // RPC 服务的安全配置 - registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); + registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll(); } }; diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/framework/security/config/SecurityConfiguration.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/framework/security/config/SecurityConfiguration.java index 5fa5376b5..9559d14ef 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/framework/security/config/SecurityConfiguration.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/framework/security/config/SecurityConfiguration.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** @@ -17,15 +18,15 @@ public class SecurityConfiguration { return new AuthorizeRequestsCustomizer() { @Override - public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { // Swagger 接口文档 - registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 - .antMatchers("/swagger-ui.html").permitAll(); // Swagger UI + registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据 + .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI // Spring Boot Actuator 的安全配置 - registry.antMatchers("/actuator").anonymous() - .antMatchers("/actuator/**").anonymous(); + registry.requestMatchers("/actuator").anonymous() + .requestMatchers("/actuator/**").anonymous(); // Druid 监控 - registry.antMatchers("/druid/**").anonymous(); + registry.requestMatchers("/druid/**").anonymous(); } }; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/security/config/SecurityConfiguration.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/security/config/SecurityConfiguration.java index 64c0e3db9..1bb0c4197 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/security/config/SecurityConfiguration.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/security/config/SecurityConfiguration.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.member.enums.ApiConstants; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** @@ -18,17 +19,17 @@ public class SecurityConfiguration { return new AuthorizeRequestsCustomizer() { @Override - public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { // Swagger 接口文档 - registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 - .antMatchers("/swagger-ui.html").permitAll(); // Swagger UI + registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据 + .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI // Spring Boot Actuator 的安全配置 - registry.antMatchers("/actuator").anonymous() - .antMatchers("/actuator/**").anonymous(); + registry.requestMatchers("/actuator").anonymous() + .requestMatchers("/actuator/**").anonymous(); // Druid 监控 - registry.antMatchers("/druid/**").anonymous(); + registry.requestMatchers("/druid/**").anonymous(); // RPC 服务的安全配置 - registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); + registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll(); } }; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 4595f185c..69a26fb65 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -643,7 +643,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { tradeOrderItemMapper.updateBatch(updateItems); // 4. 更新支付订单 - payOrderApi.updatePayOrderPrice(order.getPayOrderId(), newPayPrice); + payOrderApi.updatePayOrderPrice(order.getPayOrderId(), newPayPrice).getCheckedData(); // 5. 记录订单日志 TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus(), 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 78ed1786d..274384db8 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,15 +1,19 @@ package cn.iocoder.yudao.module.pay.api.order; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.ApiConstants; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; @FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = @Tag(name = "RPC 服务 - 支付单") @@ -19,11 +23,20 @@ public interface PayOrderApi { @PostMapping(PREFIX + "/create") @Operation(summary = "创建支付单") - Long createOrder(@Valid @RequestBody PayOrderCreateReqDTO reqDTO); + CommonResult createOrder(@Valid @RequestBody PayOrderCreateReqDTO reqDTO); @PostMapping(PREFIX + "/get") @Operation(summary = "获得支付单") @Parameter(name = "id", description = "支付单编号", example = "1", required = true) - PayOrderRespDTO getOrder(Long id); + CommonResult getOrder(Long id); + + @PutMapping(PREFIX + "/update-price") + @Operation(summary = "更新支付订单价格") + @Parameters({ + @Parameter(name = "id", description = "支付单编号", example = "1", required = true), + @Parameter(name = "payPrice", description = "支付单价格", example = "100", required = true) + }) + CommonResult updatePayOrderPrice(@RequestParam("id") Long id, + @RequestParam("payPrice") Integer payPrice); } 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 index 11085af39..2d958b819 100644 --- 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 @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.pay.api.refund; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; import cn.iocoder.yudao.module.pay.enums.ApiConstants; @@ -19,11 +20,11 @@ public interface PayRefundApi { @PostMapping(PREFIX + "/create") @Operation(summary = "创建退款单") - Long createRefund(@Valid @RequestBody PayRefundCreateReqDTO reqDTO); + CommonResult createRefund(@Valid @RequestBody PayRefundCreateReqDTO reqDTO); @PostMapping(PREFIX + "/get") @Operation(summary = "获得退款单") @Parameter(name = "id", description = "退款单编号", example = "1", required = true) - PayRefundRespDTO getRefund(Long id); + CommonResult getRefund(Long id); } 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 8490c482b..d41a03837 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,5 +1,6 @@ package cn.iocoder.yudao.module.pay.api.order; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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; @@ -10,6 +11,8 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + @Service @RestController // 提供 RESTful API 接口,给 Feign 调用 @Validated @@ -19,14 +22,20 @@ public class PayOrderApiImpl implements PayOrderApi { private PayOrderService payOrderService; @Override - public Long createOrder(PayOrderCreateReqDTO reqDTO) { - return payOrderService.createOrder(reqDTO); + public CommonResult createOrder(PayOrderCreateReqDTO reqDTO) { + return success(payOrderService.createOrder(reqDTO)); } @Override - public PayOrderRespDTO getOrder(Long id) { + public CommonResult getOrder(Long id) { PayOrderDO order = payOrderService.getOrder(id); - return PayOrderConvert.INSTANCE.convert2(order); + return success(PayOrderConvert.INSTANCE.convert2(order)); + } + + @Override + public CommonResult updatePayOrderPrice(Long id, Integer payPrice) { + payOrderService.updatePayOrderPrice(id, payPrice); + return success(true); } } 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 index de04d95e8..a2505cb44 100644 --- 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 @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.pay.api.refund; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert; @@ -9,6 +10,8 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + @Service @RestController // 提供 RESTful API 接口,给 Feign 调用 @Validated @@ -18,13 +21,13 @@ public class PayRefundApiImpl implements PayRefundApi { private PayRefundService payRefundService; @Override - public Long createRefund(PayRefundCreateReqDTO reqDTO) { - return payRefundService.createPayRefund(reqDTO); + public CommonResult createRefund(PayRefundCreateReqDTO reqDTO) { + return success(payRefundService.createPayRefund(reqDTO)); } @Override - public PayRefundRespDTO getRefund(Long id) { - return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id)); + public CommonResult getRefund(Long id) { + return success(PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id))); } } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java index b241a1db1..e7d540315 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.social; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; import cn.iocoder.yudao.module.system.enums.ApiConstants; import io.swagger.v3.oas.annotations.Operation; @@ -18,18 +19,9 @@ public interface SocialUserApi { String PREFIX = ApiConstants.PREFIX + "/social-user"; - @GetMapping("PREFIX + /get-authorize-url") - @Operation(summary = "获得社交平台的授权 URL") - @Parameters({ - @Parameter(name = "type", description = "社交平台的类型", example = "1", required = true), - @Parameter(name = "redirectUri", description = "重定向 URL", example = "https://www.iocoder.cn",required = true) - }) - CommonResult getAuthorizeUrl(@RequestParam("type") Integer type, - @RequestParam("redirectUri") String redirectUri); - @PostMapping("PREFIX + /bind") @Operation(summary = "绑定社交用户") - CommonResult bindSocialUser(@Valid @RequestBody SocialUserBindReqDTO reqDTO); + CommonResult bindSocialUser(@Valid @RequestBody SocialUserBindReqDTO reqDTO); @DeleteMapping("PREFIX + /unbind") @Operation(summary = "取消绑定社交用户") @@ -43,9 +35,9 @@ public interface SocialUserApi { @Parameter(name = "code", description = "授权码", required = true, example = "tudou"), @Parameter(name = "state", description = "state", required = true, example = "coke") }) - CommonResult getBindUserId(@RequestParam("userType") Integer userType, - @RequestParam("type") Integer type, - @RequestParam("code") String code, - @RequestParam("state") String state); + CommonResult getSocialUser(@RequestParam("userType") Integer userType, + @RequestParam("type") Integer type, + @RequestParam("code") String code, + @RequestParam("state") String state); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java index f41bf0fef..edd113d3b 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java @@ -36,7 +36,7 @@ public class SocialUserBindReqDTO { */ @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") - private Integer type; + private Integer socialType; /** * 授权码 */ diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java index 066536f4a..e95495d27 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java @@ -32,12 +32,12 @@ public class SocialUserUnbindReqDTO { */ @InEnum(SocialTypeEnum.class) @NotNull(message = "社交平台的类型不能为空") - private Integer type; + private Integer socialType; /** * 社交平台的 unionId */ @NotEmpty(message = "社交平台的 unionId 不能为空") - private String unionId; + private String openid; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index 606e7bff8..b2528ae16 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.system.controller.admin.auth; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; @@ -15,7 +18,7 @@ import cn.iocoder.yudao.module.system.service.auth.AdminAuthService; import cn.iocoder.yudao.module.system.service.permission.MenuService; import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.permission.RoleService; -import cn.iocoder.yudao.module.system.service.social.SocialUserService; +import cn.iocoder.yudao.module.system.service.social.SocialClientService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -29,13 +32,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.Collections; import java.util.List; import java.util.Set; 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; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.obtainAuthorization; @Tag(name = "管理后台 - 认证") @RestController @@ -55,7 +58,7 @@ public class AuthController { @Resource private PermissionService permissionService; @Resource - private SocialUserService socialUserService; + private SocialClientService socialClientService; @Resource private SecurityProperties securityProperties; @@ -73,7 +76,8 @@ public class AuthController { @Operation(summary = "登出系统") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 public CommonResult logout(HttpServletRequest request) { - String token = obtainAuthorization(request, securityProperties.getTokenHeader()); + String token = SecurityFrameworkUtils.obtainAuthorization(request, + securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); if (StrUtil.isNotBlank(token)) { authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); } @@ -100,6 +104,9 @@ public class AuthController { // 1.2 获得角色列表 Set roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); + if (CollUtil.isEmpty(roleIds)) { + return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList())); + } List roles = roleService.getRoleList(roleIds); roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 @@ -142,7 +149,8 @@ public class AuthController { }) public CommonResult socialLogin(@RequestParam("type") Integer type, @RequestParam("redirectUri") String redirectUri) { - return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri)); + return success(socialClientService.getAuthorizeUrl( + type, UserTypeEnum.ADMIN.getValue(), redirectUri)); } @PostMapping("/social-login") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java index 8293a939b..36eca0dc8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java @@ -2,11 +2,15 @@ package cn.iocoder.yudao.module.system.controller.admin.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.*; -import cn.iocoder.yudao.module.system.convert.dept.PostConvert; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.service.dept.PostService; import io.swagger.v3.oas.annotations.Operation; @@ -39,16 +43,16 @@ public class PostController { @PostMapping("/create") @Operation(summary = "创建岗位") @PreAuthorize("@ss.hasPermission('system:post:create')") - public CommonResult createPost(@Valid @RequestBody PostCreateReqVO reqVO) { - Long postId = postService.createPost(reqVO); + public CommonResult createPost(@Valid @RequestBody PostSaveReqVO createReqVO) { + Long postId = postService.createPost(createReqVO); return success(postId); } @PutMapping("/update") @Operation(summary = "修改岗位") @PreAuthorize("@ss.hasPermission('system:post:update')") - public CommonResult updatePost(@Valid @RequestBody PostUpdateReqVO reqVO) { - postService.updatePost(reqVO); + public CommonResult updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) { + postService.updatePost(updateReqVO); return success(true); } @@ -65,35 +69,38 @@ public class PostController { @Parameter(name = "id", description = "岗位编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:post:query')") public CommonResult getPost(@RequestParam("id") Long id) { - return success(PostConvert.INSTANCE.convert(postService.getPost(id))); + PostDO post = postService.getPost(id); + return success(BeanUtils.toBean(post, PostRespVO.class)); } @GetMapping("/list-all-simple") - @Operation(summary = "获取岗位精简信息列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") + @Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") public CommonResult> getSimplePostList() { // 获得岗位列表,只要开启状态的 List list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); // 排序后,返回给前端 list.sort(Comparator.comparing(PostDO::getSort)); - return success(PostConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, PostSimpleRespVO.class)); } @GetMapping("/page") @Operation(summary = "获得岗位分页列表") @PreAuthorize("@ss.hasPermission('system:post:query')") - public CommonResult> getPostPage(@Validated PostPageReqVO reqVO) { - return success(PostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO))); + public CommonResult> getPostPage(@Validated PostPageReqVO pageReqVO) { + PageResult pageResult = postService.getPostPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, PostRespVO.class)); } @GetMapping("/export") @Operation(summary = "岗位管理") @PreAuthorize("@ss.hasPermission('system:post:export')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Validated PostExportReqVO reqVO) throws IOException { - List posts = postService.getPostList(reqVO); - List data = PostConvert.INSTANCE.convertList03(posts); + public void export(HttpServletResponse response, @Validated PostPageReqVO reqVO) throws IOException { + reqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = postService.getPostPage(reqVO).getList(); // 输出 - ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostExcelVO.class, data); + ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostRespVO.class, + BeanUtils.toBean(list, PostRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java index 427a1b57e..14f0679b8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java @@ -1,21 +1,23 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; -/** - * 岗位 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 岗位创建/修改 Request VO") @Data -public class PostBaseVO { +public class PostSaveReqVO { - @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") + @Schema(description = "岗位编号", example = "1024") + private Long id; + + @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆") @NotBlank(message = "岗位名称不能为空") - @Size(max = 50, message = "岗位名称长度不能超过50个字符") + @Size(max = 50, message = "岗位名称长度不能超过 50 个字符") private String name; @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") @@ -27,10 +29,11 @@ public class PostBaseVO { @NotNull(message = "显示顺序不能为空") private Integer sort; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(CommonStatusEnum.class) private Integer status; @Schema(description = "备注", example = "快乐的备注") private String remark; -} +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java deleted file mode 100644 index dbebfdbc0..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - 岗位更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class PostUpdateReqVO extends PostBaseVO { - - @Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "岗位编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java index 84c1b0482..ab5ed1f30 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java @@ -29,7 +29,7 @@ public class TenantBaseVO { private Integer status; @Schema(description = "绑定域名", example = "https://www.iocoder.cn") - private String domain; + private String website; @Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "租户套餐编号不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index e27d4d077..cd2827da6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; @@ -155,14 +156,14 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 - Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), + SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); - if (userId == null) { + if (socialUser == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } // 获得用户 - AdminUserDO user = userService.getUser(userId); + AdminUserDO user = userService.getUser(socialUser.getUserId()); if (user == null) { throw exception(USER_NOT_EXISTS); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java index 79f80f015..7449d3db7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; @@ -55,13 +54,12 @@ public class SmsLogServiceImpl implements SmsLogService { } @Override - public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, + public void updateSmsSendResult(Long id, Boolean success, String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) { - SmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? - SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; - smsLogMapper.updateById(SmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()) - .sendTime(LocalDateTime.now()).sendCode(sendCode).sendMsg(sendMsg) + SmsSendStatusEnum sendStatus = success ? SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; + smsLogMapper.updateById(SmsLogDO.builder().id(id) + .sendStatus(sendStatus.getStatus()).sendTime(LocalDateTime.now()) .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); } 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 c402eec6a..f686a097a 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 @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; @@ -8,7 +9,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -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.module.system.dal.dataobject.sms.SmsChannelDO; @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.service.member.MemberService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.google.common.annotations.VisibleForTesting; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.List; @@ -35,6 +36,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; * @author 芋道源码 */ @Service +@Slf4j public class SmsSendServiceImpl implements SmsSendService { @Resource @@ -158,11 +160,17 @@ public class SmsSendServiceImpl implements SmsSendService { SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId()); Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); // 发送短信 - SmsCommonResult sendResult = smsClient.sendSms(message.getLogId(), message.getMobile(), - message.getApiTemplateId(), message.getTemplateParams()); - smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), - sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(), - sendResult.getData() != null ? sendResult.getData().getSerialNo() : null); + try { + SmsSendRespDTO sendResponse = smsClient.sendSms(message.getLogId(), message.getMobile(), + message.getApiTemplateId(), message.getTemplateParams()); + smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(), + sendResponse.getApiCode(), sendResponse.getApiMsg(), + sendResponse.getApiRequestId(), sendResponse.getSerialNo()); + } catch (Throwable ex) { + log.error("[doSendSms][发送短信异常,日志编号({})]", message.getLogId(), ex); + smsLogService.updateSmsSendResult(message.getLogId(), false, + "EXCEPTION", ExceptionUtil.getRootCauseMessage(ex), null, null); + } } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java index 659c904e0..aab8d6c93 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java @@ -8,9 +8,8 @@ import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialCl import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import com.xingyuv.jushauth.model.AuthUser; -import me.chanjar.weixin.common.bean.WxJsapiSignature; - import jakarta.validation.Valid; +import me.chanjar.weixin.common.bean.WxJsapiSignature; /** * 社交应用 Service 接口 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 71000c1d8..179d97460 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -31,6 +31,7 @@ import com.xingyuv.jushauth.model.AuthUser; import com.xingyuv.jushauth.request.AuthRequest; import com.xingyuv.jushauth.utils.AuthStateUtils; import com.xingyuv.justauth.AuthRequestFactory; +import jakarta.annotation.Resource; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.bean.WxJsapiSignature; @@ -42,7 +43,6 @@ import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; -import jakarta.annotation.Resource; import java.time.Duration; import java.util.Objects; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java index 93f1f0184..a2fa43fcc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -1,11 +1,13 @@ package cn.iocoder.yudao.module.system.service.social; import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; import java.util.List; @@ -16,31 +18,10 @@ import java.util.List; */ public interface SocialUserService { - /** - * 获得社交平台的授权 URL - * - * @param type 社交平台的类型 {@link SocialTypeEnum} - * @param redirectUri 重定向 URL - * @return 社交平台的授权 URL - */ - String getAuthorizeUrl(Integer type, String redirectUri); - - /** - * 授权获得对应的社交用户 - * 如果授权失败,则会抛出 {@link ServiceException} 异常 - * - * @param type 社交平台的类型 {@link SocialTypeEnum} - * @param code 授权码 - * @param state state - * @return 授权用户 - */ - @NotNull - SocialUserDO authSocialUser(Integer type, String code, String state); - /** * 获得指定用户的社交用户列表 * - * @param userId 用户编号 + * @param userId 用户编号 * @param userType 用户类型 * @return 社交用户列表 */ @@ -50,29 +31,49 @@ public interface SocialUserService { * 绑定社交用户 * * @param reqDTO 绑定信息 + * @return 社交用户 openid */ - void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); + String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); /** * 取消绑定社交用户 * * @param userId 用户编号 * @param userType 全局用户类型 - * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param socialType 社交平台的类型 {@link SocialTypeEnum} * @param openid 社交平台的 openid */ - void unbindSocialUser(Long userId, Integer userType, Integer type, String openid); + void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid); /** - * 获得社交用户的绑定用户编号 - * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! + * 获得社交用户 + * * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 * * @param userType 用户类型 - * @param type 社交平台的类型 + * @param socialType 社交平台的类型 * @param code 授权码 * @param state state - * @return 绑定用户编号 + * @return 社交用户 */ - Long getBindUserId(Integer userType, Integer type, String code, String state); + SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state); + + // ==================== 社交用户 CRUD ==================== + + /** + * 获得社交用户 + * + * @param id 编号 + * @return 社交用户 + */ + SocialUserDO getSocialUser(Long id); + + /** + * 获得社交用户分页 + * + * @param pageReqVO 分页查询 + * @return 社交用户分页 + */ + PageResult getSocialUserPage(SocialUserPageReqVO pageReqVO); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 493710aae..60f098f04 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -2,20 +2,19 @@ package cn.iocoder.yudao.module.system.service.social; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.util.http.HttpUtils; -import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; -import com.xingyuv.jushauth.model.AuthCallback; -import com.xingyuv.jushauth.model.AuthResponse; import com.xingyuv.jushauth.model.AuthUser; -import com.xingyuv.jushauth.request.AuthRequest; -import com.xingyuv.jushauth.utils.AuthStateUtils; import jakarta.annotation.Resource; +import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,7 +26,8 @@ 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.convertSet; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND; /** * 社交用户 Service 实现类 @@ -39,51 +39,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; @Slf4j public class SocialUserServiceImpl implements SocialUserService { - @Resource// 由于自定义了 YudaoAuthRequestFactory 无法覆盖默认的 AuthRequestFactory,所以只能注入它 - private YudaoAuthRequestFactory yudaoAuthRequestFactory; - @Resource private SocialUserBindMapper socialUserBindMapper; @Resource private SocialUserMapper socialUserMapper; - @Override - public String getAuthorizeUrl(Integer type, String redirectUri) { - // 获得对应的 AuthRequest 实现 - AuthRequest authRequest = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource()); - // 生成跳转地址 - String authorizeUri = authRequest.authorize(AuthStateUtils.createState()); - return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri); - } - - @Override - public SocialUserDO authSocialUser(Integer type, String code, String state) { - // 优先从 DB 中获取,因为 code 有且可以使用一次。 - // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次 - SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(type, code, state); - if (socialUser != null) { - return socialUser; - } - - // 请求获取 - AuthUser authUser = getAuthUser(type, code, state); - Assert.notNull(authUser, "三方用户不能为空"); - - // 保存到 DB 中 - socialUser = socialUserMapper.selectByTypeAndOpenid(type, authUser.getUuid()); - if (socialUser == null) { - socialUser = new SocialUserDO(); - } - socialUser.setType(type).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询 - .setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken()))) - .setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo())); - if (socialUser.getId() == null) { - socialUserMapper.insert(socialUser); - } else { - socialUserMapper.updateById(socialUser); - } - return socialUser; - } + @Resource + private SocialClientService socialClientService; @Override public List getSocialUserList(Long userId, Integer userType) { @@ -98,9 +60,10 @@ public class SocialUserServiceImpl implements SocialUserService { @Override @Transactional - public void bindSocialUser(SocialUserBindReqDTO reqDTO) { + public String bindSocialUser(SocialUserBindReqDTO reqDTO) { // 获得社交用户 - SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState()); + SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(), + reqDTO.getCode(), reqDTO.getState()); Assert.notNull(socialUser, "社交用户不能为空"); // 社交用户可能之前绑定过别的用户,需要进行解绑 @@ -115,12 +78,13 @@ public class SocialUserServiceImpl implements SocialUserService { .userId(reqDTO.getUserId()).userType(reqDTO.getUserType()) .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build(); socialUserBindMapper.insert(socialUserBind); + return socialUser.getOpenid(); } @Override - public void unbindSocialUser(Long userId, Integer userType, Integer type, String openid) { + public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) { // 获得 openid 对应的 SocialUserDO 社交用户 - SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(type, openid); + SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid); if (socialUser == null) { throw exception(SOCIAL_USER_NOT_FOUND); } @@ -130,9 +94,9 @@ public class SocialUserServiceImpl implements SocialUserService { } @Override - public Long getBindUserId(Integer userType, Integer type, String code, String state) { + public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) { // 获得社交用户 - SocialUserDO socialUser = authSocialUser(type, code, state); + SocialUserDO socialUser = authSocialUser(socialType, userType, code, state); Assert.notNull(socialUser, "社交用户不能为空"); // 如果未绑定的社交用户,则无法自动登录,进行报错 @@ -141,27 +105,59 @@ public class SocialUserServiceImpl implements SocialUserService { if (socialUserBind == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } - return socialUserBind.getUserId(); + return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId()); } + // TODO 芋艿:调整下单测 /** - * 请求社交平台,获得授权的用户 + * 授权获得对应的社交用户 + * 如果授权失败,则会抛出 {@link ServiceException} 异常 * - * @param type 社交平台的类型 - * @param code 授权码 - * @param state 授权 state - * @return 授权的用户 + * @param socialType 社交平台的类型 {@link SocialTypeEnum} + * @param userType 用户类型 + * @param code 授权码 + * @param state state + * @return 授权用户 */ - private AuthUser getAuthUser(Integer type, String code, String state) { - AuthRequest authRequest = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource()); - AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build(); - AuthResponse authResponse = authRequest.login(authCallback); - log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", type, - toJsonString(authCallback), toJsonString(authResponse)); - if (!authResponse.ok()) { - throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg()); + @NotNull + public SocialUserDO authSocialUser(Integer socialType, Integer userType, String code, String state) { + // 优先从 DB 中获取,因为 code 有且可以使用一次。 + // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次 + SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(socialType, code, state); + if (socialUser != null) { + return socialUser; } - return (AuthUser) authResponse.getData(); + + // 请求获取 + AuthUser authUser = socialClientService.getAuthUser(socialType, userType, code, state); + Assert.notNull(authUser, "三方用户不能为空"); + + // 保存到 DB 中 + socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, authUser.getUuid()); + if (socialUser == null) { + socialUser = new SocialUserDO(); + } + socialUser.setType(socialType).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询 + .setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken()))) + .setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo())); + if (socialUser.getId() == null) { + socialUserMapper.insert(socialUser); + } else { + socialUserMapper.updateById(socialUser); + } + return socialUser; + } + + // ==================== 社交用户 CRUD ==================== + + @Override + public SocialUserDO getSocialUser(Long id) { + return socialUserMapper.selectById(id); + } + + @Override + public PageResult getSocialUserPage(SocialUserPageReqVO pageReqVO) { + return socialUserMapper.selectPage(pageReqVO); } }