同步最新 master 代码
parent
61cb7d94ac
commit
04b4e090bd
|
|
@ -14,7 +14,7 @@
|
|||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.8.2-snapshot</revision>
|
||||
<revision>1.8.3-snapshot</revision>
|
||||
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.boot.version>3.1.4</spring.boot.version>
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
<servlet.versoin>2.5</servlet.versoin>
|
||||
<springdoc.version>2.2.0</springdoc.version>
|
||||
<knife4j.version>4.3.0</knife4j.version>
|
||||
<!-- 消息队列 -->
|
||||
<rocketmq-spring.version>2.2.3</rocketmq-spring.version>
|
||||
<!-- DB 相关 -->
|
||||
<druid.version>1.2.19</druid.version>
|
||||
<mybatis-plus.version>3.5.3.2</mybatis-plus.version>
|
||||
|
|
@ -133,11 +135,6 @@
|
|||
<artifactId>yudao-spring-boot-starter-biz-pay</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
|
|
@ -148,11 +145,6 @@
|
|||
<artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-social</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-error-code</artifactId>
|
||||
|
|
@ -201,6 +193,12 @@
|
|||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-websocket</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
|
|
@ -298,6 +296,12 @@
|
|||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-spring-boot-starter</artifactId>
|
||||
<version>${rocketmq-spring.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 服务保障相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
|
|
@ -616,12 +620,12 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
|
||||
<version>${weixin-java.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java-mp-spring-boot-starter</artifactId>
|
||||
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||
<version>${weixin-java.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -40,4 +40,4 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
|
||||
|
|
@ -32,7 +32,6 @@ public interface BpmTaskService {
|
|||
*
|
||||
* @param userId 用户编号
|
||||
* @param pageReqVO 分页请求
|
||||
*
|
||||
* @return 流程任务分页
|
||||
*/
|
||||
PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
|
||||
|
|
@ -41,19 +40,17 @@ public interface BpmTaskService {
|
|||
* 获得流程任务 Map
|
||||
*
|
||||
* @param processInstanceIds 流程实例的编号数组
|
||||
*
|
||||
* @return 流程任务 Map
|
||||
*/
|
||||
default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
|
||||
return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
|
||||
Task::getProcessInstanceId);
|
||||
Task::getProcessInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得流程任务列表
|
||||
*
|
||||
* @param processInstanceIds 流程实例的编号数组
|
||||
*
|
||||
* @return 流程任务列表
|
||||
*/
|
||||
List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
|
||||
|
|
@ -62,11 +59,19 @@ public interface BpmTaskService {
|
|||
* 获得指令流程实例的流程任务列表,包括所有状态的
|
||||
*
|
||||
* @param processInstanceId 流程实例的编号
|
||||
*
|
||||
* @return 流程任务列表
|
||||
*/
|
||||
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
|
||||
|
||||
|
||||
/**
|
||||
* 通过任务 ID 集合,获取任务扩展表信息集合
|
||||
*
|
||||
* @param taskIdList 任务 ID 集合
|
||||
* @return 任务列表
|
||||
*/
|
||||
List<BpmTaskExtDO> getTaskListByTaskIdList(List<String> taskIdList);
|
||||
|
||||
/**
|
||||
* 通过任务
|
||||
*
|
||||
|
|
@ -127,4 +132,53 @@ public interface BpmTaskService {
|
|||
*/
|
||||
void updateTaskExtAssign(Task task);
|
||||
|
||||
/**
|
||||
* 获取当前任务的可回退的流程集合
|
||||
*
|
||||
* @param taskId 当前的任务 ID
|
||||
* @return 可以回退的节点列表
|
||||
*/
|
||||
List<BpmTaskSimpleRespVO> 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<BpmTaskSubSignRespVO> getChildrenTaskList(String parentId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 实现类
|
||||
|
|
|
|||
|
|
@ -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<Long> createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) {
|
||||
return success(testDemoService.createTestDemo(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新字典类型")
|
||||
@PreAuthorize("@ss.hasPermission('infra:test-demo:update')")
|
||||
public CommonResult<Boolean> 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<Boolean> 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<TestDemoRespVO> 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<List<TestDemoRespVO>> getTestDemoList(@RequestParam("ids") Collection<Long> ids) {
|
||||
List<TestDemoDO> list = testDemoService.getTestDemoList(ids);
|
||||
return success(TestDemoConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得字典类型分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:test-demo:query')") public CommonResult<PageResult<TestDemoRespVO>> getTestDemoPage(@Valid TestDemoPageReqVO pageVO) {
|
||||
PageResult<TestDemoDO> 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<TestDemoDO> list = testDemoService.getTestDemoList(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<TestDemoExcelVO> datas = TestDemoConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "字典类型.xls", "数据", TestDemoExcelVO.class, datas);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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<CodegenTableDO> getCodegenTableList(Long dataSourceConfigId) {
|
||||
return codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CodegenTableDO> getCodegenTablePage(CodegenTablePageReqVO pageReqVO) {
|
||||
return codegenTableMapper.selectPage(pageReqVO);
|
||||
|
|
@ -235,14 +248,34 @@ public class CodegenServiceImpl implements CodegenService {
|
|||
throw exception(CODEGEN_COLUMN_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 如果是主子表,则加载对应的子表信息
|
||||
List<CodegenTableDO> subTables = null;
|
||||
List<List<CodegenColumnDO>> 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<CodegenColumnDO> 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<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) {
|
||||
List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment);
|
||||
// 移除已经生成的表
|
||||
// 移除在 Codegen 中,已经存在的
|
||||
Set<String> existsTables = CollectionUtils.convertSet(
|
||||
codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName);
|
||||
|
|
|
|||
|
|
@ -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<String> BASE_DO_FIELDS = new HashSet<>();
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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<String, String> SERVER_TEMPLATES = MapUtil.<String, String>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<Integer, String, String> FRONT_TEMPLATES = ImmutableTable.<Integer, String, String>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<String, String> execute(CodegenTableDO table, List<CodegenColumnDO> columns) {
|
||||
/**
|
||||
* 生成代码
|
||||
*
|
||||
* @param table 表定义
|
||||
* @param columns table 的字段定义数组
|
||||
* @param subTables 子表数组,当且仅当主子表时使用
|
||||
* @param subColumnsList subTables 的字段定义数组
|
||||
* @return 生成的代码,key 是路径,value 是对应代码
|
||||
*/
|
||||
public Map<String, String> execute(CodegenTableDO table, List<CodegenColumnDO> columns,
|
||||
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
|
||||
// 1.1 初始化 bindMap 上下文
|
||||
Map<String, Object> bindingMap = initBindingMap(table, columns, subTables, subColumnsList);
|
||||
// 1.2 获得模版
|
||||
Map<String, String> templates = getTemplates(table.getFrontType());
|
||||
|
||||
// 2. 执行生成
|
||||
Map<String, String> 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<String, String> result, String vmPath,
|
||||
String filePath, Map<String, Object> 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<CodegenTableDO> subTables,
|
||||
Map<String, String> result, String vmPath,
|
||||
String filePath, Map<String, Object> 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<String, Object> initBindingMap(CodegenTableDO table, List<CodegenColumnDO> columns,
|
||||
List<CodegenTableDO> subTables, List<List<CodegenColumnDO>> subColumnsList) {
|
||||
// 创建 bindingMap
|
||||
Map<String, Object> bindingMap = new HashMap<>(globalBindingMap);
|
||||
bindingMap.put("table", table);
|
||||
|
|
@ -196,17 +322,54 @@ public class CodegenEngine {
|
|||
// permission 前缀
|
||||
bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase);
|
||||
|
||||
// 执行生成
|
||||
Map<String, String> templates = getTemplates(table.getFrontType());
|
||||
Map<String, String> 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<CodegenColumnDO> subPrimaryColumns = new ArrayList<>();
|
||||
List<CodegenColumnDO> subJoinColumns = new ArrayList<>();
|
||||
List<String> subJoinColumnStrikeCases = new ArrayList<>();
|
||||
List<String> subSimpleClassNames = new ArrayList<>();
|
||||
List<String> subClassNameVars = new ArrayList<>();
|
||||
List<String> simpleClassNameUnderlineCases = new ArrayList<>();
|
||||
List<String> subSimpleClassNameStrikeCases = new ArrayList<>();
|
||||
for (int i = 0; i < subTables.size(); i++) {
|
||||
CodegenTableDO subTable = subTables.get(i);
|
||||
List<CodegenColumnDO> 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<String, String> getTemplates(Integer frontType) {
|
||||
|
|
@ -216,6 +379,7 @@ public class CodegenEngine {
|
|||
return templates;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private String formatFilePath(String filePath, Map<String, Object> 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<CodegenTableDO>) 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<String>) 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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TestDemoDO> getTestDemoList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得字典类型分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 字典类型分页
|
||||
*/
|
||||
PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得字典类型列表, 用于 Excel 导出
|
||||
*
|
||||
* @param exportReqVO 查询条件
|
||||
* @return 字典类型列表
|
||||
*/
|
||||
List<TestDemoDO> getTestDemoList(TestDemoExportReqVO exportReqVO);
|
||||
|
||||
}
|
||||
|
|
@ -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<TestDemoDO> getTestDemoList(Collection<Long> ids) {
|
||||
return testDemoMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) {
|
||||
// testDemoMapper.selectList2();
|
||||
return testDemoMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TestDemoDO> getTestDemoList(TestDemoExportReqVO exportReqVO) {
|
||||
return testDemoMapper.selectList(exportReqVO);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.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();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.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();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.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();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||
public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.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();
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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<Long> createOrder(@Valid @RequestBody PayOrderCreateReqDTO reqDTO);
|
||||
|
||||
@PostMapping(PREFIX + "/get")
|
||||
@Operation(summary = "获得支付单")
|
||||
@Parameter(name = "id", description = "支付单编号", example = "1", required = true)
|
||||
PayOrderRespDTO getOrder(Long id);
|
||||
CommonResult<PayOrderRespDTO> 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<Boolean> updatePayOrderPrice(@RequestParam("id") Long id,
|
||||
@RequestParam("payPrice") Integer payPrice);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Long> createRefund(@Valid @RequestBody PayRefundCreateReqDTO reqDTO);
|
||||
|
||||
@PostMapping(PREFIX + "/get")
|
||||
@Operation(summary = "获得退款单")
|
||||
@Parameter(name = "id", description = "退款单编号", example = "1", required = true)
|
||||
PayRefundRespDTO getRefund(Long id);
|
||||
CommonResult<PayRefundRespDTO> getRefund(Long id);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Long> createOrder(PayOrderCreateReqDTO reqDTO) {
|
||||
return success(payOrderService.createOrder(reqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOrderRespDTO getOrder(Long id) {
|
||||
public CommonResult<PayOrderRespDTO> getOrder(Long id) {
|
||||
PayOrderDO order = payOrderService.getOrder(id);
|
||||
return PayOrderConvert.INSTANCE.convert2(order);
|
||||
return success(PayOrderConvert.INSTANCE.convert2(order));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> updatePayOrderPrice(Long id, Integer payPrice) {
|
||||
payOrderService.updatePayOrderPrice(id, payPrice);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Long> createRefund(PayRefundCreateReqDTO reqDTO) {
|
||||
return success(payRefundService.createPayRefund(reqDTO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayRefundRespDTO getRefund(Long id) {
|
||||
return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id));
|
||||
public CommonResult<PayRefundRespDTO> getRefund(Long id) {
|
||||
return success(PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> getAuthorizeUrl(@RequestParam("type") Integer type,
|
||||
@RequestParam("redirectUri") String redirectUri);
|
||||
|
||||
@PostMapping("PREFIX + /bind")
|
||||
@Operation(summary = "绑定社交用户")
|
||||
CommonResult<Boolean> bindSocialUser(@Valid @RequestBody SocialUserBindReqDTO reqDTO);
|
||||
CommonResult<String> 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<Long> getBindUserId(@RequestParam("userType") Integer userType,
|
||||
@RequestParam("type") Integer type,
|
||||
@RequestParam("code") String code,
|
||||
@RequestParam("state") String state);
|
||||
CommonResult<SocialUserRespDTO> getSocialUser(@RequestParam("userType") Integer userType,
|
||||
@RequestParam("type") Integer type,
|
||||
@RequestParam("code") String code,
|
||||
@RequestParam("state") String state);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class SocialUserBindReqDTO {
|
|||
*/
|
||||
@InEnum(SocialTypeEnum.class)
|
||||
@NotNull(message = "社交平台的类型不能为空")
|
||||
private Integer type;
|
||||
private Integer socialType;
|
||||
/**
|
||||
* 授权码
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Boolean> 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<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId());
|
||||
if (CollUtil.isEmpty(roleIds)) {
|
||||
return success(AuthConvert.INSTANCE.convert(user, Collections.emptyList(), Collections.emptyList()));
|
||||
}
|
||||
List<RoleDO> roles = roleService.getRoleList(roleIds);
|
||||
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
|
||||
|
||||
|
|
@ -142,7 +149,8 @@ public class AuthController {
|
|||
})
|
||||
public CommonResult<String> 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")
|
||||
|
|
|
|||
|
|
@ -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<Long> createPost(@Valid @RequestBody PostCreateReqVO reqVO) {
|
||||
Long postId = postService.createPost(reqVO);
|
||||
public CommonResult<Long> 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<Boolean> updatePost(@Valid @RequestBody PostUpdateReqVO reqVO) {
|
||||
postService.updatePost(reqVO);
|
||||
public CommonResult<Boolean> 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<PostRespVO> 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<List<PostSimpleRespVO>> getSimplePostList() {
|
||||
// 获得岗位列表,只要开启状态的
|
||||
List<PostDO> 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<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO reqVO) {
|
||||
return success(PostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO)));
|
||||
public CommonResult<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO pageReqVO) {
|
||||
PageResult<PostDO> 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<PostDO> posts = postService.getPostList(reqVO);
|
||||
List<PostExcelVO> data = PostConvert.INSTANCE.convertList03(posts);
|
||||
public void export(HttpServletResponse response, @Validated PostPageReqVO reqVO) throws IOException {
|
||||
reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<PostDO> list = postService.getPostPage(reqVO).getList();
|
||||
// 输出
|
||||
ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostExcelVO.class, data);
|
||||
ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostRespVO.class,
|
||||
BeanUtils.toBean(list, PostRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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 = "租户套餐编号不能为空")
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SmsSendRespDTO> 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
|
||||
|
|
|
|||
|
|
@ -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 接口
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SocialUserDO> 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<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO) {
|
||||
return socialUserMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue