同步最新 master 代码

pull/70/head
YunaiV 2023-11-27 18:35:03 +08:00
parent 61cb7d94ac
commit 04b4e090bd
41 changed files with 629 additions and 657 deletions

View File

@ -14,7 +14,7 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url> <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties> <properties>
<revision>1.8.2-snapshot</revision> <revision>1.8.3-snapshot</revision>
<flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version> <flatten-maven-plugin.version>1.5.0</flatten-maven-plugin.version>
<!-- 统一依赖管理 --> <!-- 统一依赖管理 -->
<spring.boot.version>3.1.4</spring.boot.version> <spring.boot.version>3.1.4</spring.boot.version>
@ -24,6 +24,8 @@
<servlet.versoin>2.5</servlet.versoin> <servlet.versoin>2.5</servlet.versoin>
<springdoc.version>2.2.0</springdoc.version> <springdoc.version>2.2.0</springdoc.version>
<knife4j.version>4.3.0</knife4j.version> <knife4j.version>4.3.0</knife4j.version>
<!-- 消息队列 -->
<rocketmq-spring.version>2.2.3</rocketmq-spring.version>
<!-- DB 相关 --> <!-- DB 相关 -->
<druid.version>1.2.19</druid.version> <druid.version>1.2.19</druid.version>
<mybatis-plus.version>3.5.3.2</mybatis-plus.version> <mybatis-plus.version>3.5.3.2</mybatis-plus.version>
@ -133,11 +135,6 @@
<artifactId>yudao-spring-boot-starter-biz-pay</artifactId> <artifactId>yudao-spring-boot-starter-biz-pay</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
<version>${revision}</version>
</dependency>
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
@ -148,11 +145,6 @@
<artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId> <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-social</artifactId>
<version>${revision}</version>
</dependency>
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-error-code</artifactId> <artifactId>yudao-spring-boot-starter-biz-error-code</artifactId>
@ -201,6 +193,12 @@
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-websocket</artifactId>
<version>${revision}</version>
</dependency>
<dependency> <dependency>
<groupId>com.github.xiaoymin</groupId> <groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
@ -298,6 +296,12 @@
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>${rocketmq-spring.version}</version>
</dependency>
<!-- 服务保障相关 --> <!-- 服务保障相关 -->
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
@ -616,12 +620,12 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId> <artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>${weixin-java.version}</version> <version>${weixin-java.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <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> <version>${weixin-java.version}</version>
</dependency> </dependency>

View File

@ -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 {
}
}

View File

@ -40,4 +40,4 @@
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -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();
}
}

View File

@ -1,3 +1,3 @@
cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQProducerAutoConfiguration cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQProducerAutoConfiguration
cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration
cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration

View File

@ -56,7 +56,7 @@ public class BpmOALeaveServiceImpl implements BpmOALeaveService {
processInstanceVariables.put("day", day); processInstanceVariables.put("day", day);
String processInstanceId = processInstanceApi.createProcessInstance(userId, String processInstanceId = processInstanceApi.createProcessInstance(userId,
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY) new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId()))).getCheckedData(); .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(leave.getId())));
// 将工作流的编号,更新到 OA 请假单中 // 将工作流的编号,更新到 OA 请假单中
leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId)); leaveMapper.updateById(new BpmOALeaveDO().setId(leave.getId()).setProcessInstanceId(processInstanceId));

View File

@ -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.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 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.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.flowable.task.api.Task; import org.flowable.task.api.Task;
@ -22,7 +23,6 @@ public interface BpmTaskService {
* *
* @param userId * @param userId
* @param pageReqVO * @param pageReqVO
*
* @return * @return
*/ */
PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO); PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageReqVO);
@ -32,7 +32,6 @@ public interface BpmTaskService {
* *
* @param userId * @param userId
* @param pageReqVO * @param pageReqVO
*
* @return * @return
*/ */
PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO); PageResult<BpmTaskDonePageItemRespVO> getDoneTaskPage(Long userId, BpmTaskDonePageReqVO pageReqVO);
@ -41,19 +40,17 @@ public interface BpmTaskService {
* Map * Map
* *
* @param processInstanceIds * @param processInstanceIds
*
* @return Map * @return Map
*/ */
default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) { default Map<String, List<Task>> getTaskMapByProcessInstanceIds(List<String> processInstanceIds) {
return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds), return CollectionUtils.convertMultiMap(getTasksByProcessInstanceIds(processInstanceIds),
Task::getProcessInstanceId); Task::getProcessInstanceId);
} }
/** /**
* *
* *
* @param processInstanceIds * @param processInstanceIds
*
* @return * @return
*/ */
List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds); List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
@ -62,11 +59,19 @@ public interface BpmTaskService {
* *
* *
* @param processInstanceId * @param processInstanceId
*
* @return * @return
*/ */
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId); 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); void updateTaskExtAssign(Task task);
/**
* 退
*
* @param taskId ID
* @return 退
*/
List<BpmTaskSimpleRespVO> getReturnTaskList(String taskId);
/**
* 退 targetDefinitionKey
*
* @param userId
* @param reqVO 退keyID
*/
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);
} }

View File

@ -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.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 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.*;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.TASK_TARGET_NODE_NOT_EXISTS;
/** /**
* Service * Service

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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.CodegenColumnMapper;
import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; 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.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.framework.codegen.config.CodegenProperties;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder;
import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; 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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -129,6 +127,16 @@ public class CodegenServiceImpl implements CodegenService {
if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) {
throw exception(CODEGEN_TABLE_NOT_EXISTS); 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 表定义 // 更新 table 表定义
CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable()); CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable());
@ -208,6 +216,11 @@ public class CodegenServiceImpl implements CodegenService {
codegenColumnMapper.deleteListByTableId(tableId); codegenColumnMapper.deleteListByTableId(tableId);
} }
@Override
public List<CodegenTableDO> getCodegenTableList(Long dataSourceConfigId) {
return codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId);
}
@Override @Override
public PageResult<CodegenTableDO> getCodegenTablePage(CodegenTablePageReqVO pageReqVO) { public PageResult<CodegenTableDO> getCodegenTablePage(CodegenTablePageReqVO pageReqVO) {
return codegenTableMapper.selectPage(pageReqVO); return codegenTableMapper.selectPage(pageReqVO);
@ -235,14 +248,34 @@ public class CodegenServiceImpl implements CodegenService {
throw exception(CODEGEN_COLUMN_NOT_EXISTS); 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 @Override
public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { public List<DatabaseTableRespVO> getDatabaseTableList(Long dataSourceConfigId, String name, String comment) {
List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); List<TableInfo> tables = databaseTableService.getTableList(dataSourceConfigId, name, comment);
// 移除已经生成的表
// 移除在 Codegen 中,已经存在的 // 移除在 Codegen 中,已经存在的
Set<String> existsTables = CollectionUtils.convertSet( Set<String> existsTables = CollectionUtils.convertSet(
codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName); codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName);

View File

@ -64,7 +64,7 @@ public class CodegenBuilder {
*/ */
public static final String TENANT_ID_FIELD = "tenantId"; 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<>(); public static final Set<String> BASE_DO_FIELDS = new HashSet<>();
/** /**

View File

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.infra.service.codegen.inner; 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.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.TemplateConfig; import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine; 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.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.date.DateUtils; 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.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.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.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 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.dal.dataobject.codegen.CodegenTableDO;
import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; 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.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.framework.codegen.config.CodegenProperties;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableTable; import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Table; import com.google.common.collect.Table;
@ -33,10 +39,7 @@ import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static cn.hutool.core.map.MapUtil.getStr; import static cn.hutool.core.map.MapUtil.getStr;
import static cn.hutool.core.text.CharSequenceUtil.*; 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<>()) // 有序 private static final Map<String, String> SERVER_TEMPLATES = MapUtil.<String, String>builder(new LinkedHashMap<>()) // 有序
// Java module-biz Main // 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/pageReqVO"), javaModuleImplVOFilePath("PageReqVO"))
.put(javaTemplatePath("controller/vo/listReqVO"), javaModuleImplVOFilePath("ListReqVO"))
.put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO")) .put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO"))
.put(javaTemplatePath("controller/vo/updateReqVO"), javaModuleImplVOFilePath("UpdateReqVO")) .put(javaTemplatePath("controller/vo/saveReqVO"), javaModuleImplVOFilePath("SaveReqVO"))
.put(javaTemplatePath("controller/vo/exportReqVO"), javaModuleImplVOFilePath("ExportReqVO"))
.put(javaTemplatePath("controller/vo/excelVO"), javaModuleImplVOFilePath("ExcelVO"))
.put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath()) .put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath())
.put(javaTemplatePath("convert/convert"),
javaModuleImplMainFilePath("convert/${table.businessName}/${table.className}Convert"))
.put(javaTemplatePath("dal/do"), .put(javaTemplatePath("dal/do"),
javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}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"), .put(javaTemplatePath("dal/mapper"),
javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${table.className}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("dal/mapper.xml"), mapperXmlFilePath())
.put(javaTemplatePath("service/serviceImpl"), .put(javaTemplatePath("service/serviceImpl"),
javaModuleImplMainFilePath("service/${table.businessName}/${table.className}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() private static final Table<Integer, String, String> FRONT_TEMPLATES = ImmutableTable.<Integer, String, String>builder()
// Vue2 标准模版 // Vue2 标准模版
.put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/index.vue"), .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"), .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("api/api.js"),
vueFilePath("api/${table.moduleName}/${classNameVar}.js")) vueFilePath("api/${table.moduleName}/${classNameVar}.js"))
// Vue3 标准模版 // Vue3 标准模版
.put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/index.vue"), .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"), .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"), .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 模版 // Vue3 Schema 模版
.put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"), .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"), .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"), .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"), .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 模版 // Vue3 vben 模版
.put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/data.ts"), .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"), .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"), .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"), .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(); .build();
@Resource @Resource
@ -149,7 +161,8 @@ public class CodegenEngine {
} }
@PostConstruct @PostConstruct
private void initGlobalBindingMap() { @VisibleForTesting
void initGlobalBindingMap() {
// 全局配置 // 全局配置
globalBindingMap.put("basePackage", codegenProperties.getBasePackage()); globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage() globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage()
@ -174,9 +187,122 @@ public class CodegenEngine {
globalBindingMap.put("DictConvertClassName", DictConvert.class.getName()); globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
globalBindingMap.put("OperateLogClassName", OperateLog.class.getName()); globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.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 // 创建 bindingMap
Map<String, Object> bindingMap = new HashMap<>(globalBindingMap); Map<String, Object> bindingMap = new HashMap<>(globalBindingMap);
bindingMap.put("table", table); bindingMap.put("table", table);
@ -196,17 +322,54 @@ public class CodegenEngine {
// permission 前缀 // permission 前缀
bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase); bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase);
// 执行生成 // 特殊:树表专属逻辑
Map<String, String> templates = getTemplates(table.getFrontType()); if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) {
Map<String, String> result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 CodegenColumnDO treeParentColumn = CollUtil.findOne(columns,
templates.forEach((vmPath, filePath) -> { column -> Objects.equals(column.getId(), table.getTreeParentColumnId()));
filePath = formatFilePath(filePath, bindingMap); bindingMap.put("treeParentColumn", treeParentColumn);
String content = templateEngine.getTemplate(vmPath).render(bindingMap); bindingMap.put("treeParentColumn_javaField_underlineCase", toUnderlineCase(treeParentColumn.getJavaField()));
// 去除字段后面多余的 , 逗号 CodegenColumnDO treeNameColumn = CollUtil.findOne(columns,
content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }"); column -> Objects.equals(column.getId(), table.getTreeNameColumnId()));
result.put(filePath, content); bindingMap.put("treeNameColumn", treeNameColumn);
}); bindingMap.put("treeNameColumn_javaField_underlineCase", toUnderlineCase(treeNameColumn.getJavaField()));
return result; }
// 特殊:主子表专属逻辑
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) { private Map<String, String> getTemplates(Integer frontType) {
@ -216,6 +379,7 @@ public class CodegenEngine {
return templates; return templates;
} }
@SuppressWarnings("unchecked")
private String formatFilePath(String filePath, Map<String, Object> bindingMap) { private String formatFilePath(String filePath, Map<String, Object> bindingMap) {
filePath = StrUtil.replace(filePath, "${basePackage}", filePath = StrUtil.replace(filePath, "${basePackage}",
getStr(bindingMap, "basePackage").replaceAll("\\.", "/")); getStr(bindingMap, "basePackage").replaceAll("\\.", "/"));
@ -232,6 +396,16 @@ public class CodegenEngine {
filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName()); filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName());
filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName()); filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName());
filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName()); 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; return filePath;
} }
@ -298,4 +472,17 @@ public class CodegenEngine {
private static String vue3VbenTemplatePath(String path) { private static String vue3VbenTemplatePath(String path) {
return "codegen/vue3_vben/" + path + ".vm"; 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");
}
} }

View File

@ -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.dataobject.logger.ApiAccessLogDO;
import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiAccessLogMapper; import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiAccessLogMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@ -18,6 +20,7 @@ import java.util.List;
* *
* @author * @author
*/ */
@Slf4j
@Service @Service
@Validated @Validated
public class ApiAccessLogServiceImpl implements ApiAccessLogService { public class ApiAccessLogServiceImpl implements ApiAccessLogService {
@ -41,4 +44,21 @@ public class ApiAccessLogServiceImpl implements ApiAccessLogService {
return apiAccessLogMapper.selectList(exportReqVO); 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;
}
} }

View File

@ -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.dal.mysql.logger.ApiErrorLogMapper;
import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum; import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -24,6 +25,7 @@ import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_L
* *
* @author * @author
*/ */
@Slf4j
@Service @Service
@Validated @Validated
public class ApiErrorLogServiceImpl implements ApiErrorLogService { public class ApiErrorLogServiceImpl implements ApiErrorLogService {
@ -62,4 +64,21 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService {
.processUserId(processUserId).processTime(LocalDateTime.now()).build()); .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;
}
} }

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.product.enums.ApiConstants;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
/** /**
@ -18,17 +19,17 @@ public class SecurityConfiguration {
return new AuthorizeRequestsCustomizer() { return new AuthorizeRequestsCustomizer() {
@Override @Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
// Swagger 接口文档 // Swagger 接口文档
registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据
.antMatchers("/swagger-ui.html").permitAll(); // Swagger UI .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI
// Spring Boot Actuator 的安全配置 // Spring Boot Actuator 的安全配置
registry.antMatchers("/actuator").anonymous() registry.requestMatchers("/actuator").anonymous()
.antMatchers("/actuator/**").anonymous(); .requestMatchers("/actuator/**").anonymous();
// Druid 监控 // Druid 监控
registry.antMatchers("/druid/**").anonymous(); registry.requestMatchers("/druid/**").anonymous();
// RPC 服务的安全配置 // RPC 服务的安全配置
registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
} }
}; };

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.enums.ApiConstants;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
/** /**
@ -18,17 +19,17 @@ public class SecurityConfiguration {
return new AuthorizeRequestsCustomizer() { return new AuthorizeRequestsCustomizer() {
@Override @Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
// Swagger 接口文档 // Swagger 接口文档
registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据
.antMatchers("/swagger-ui.html").permitAll(); // Swagger UI .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI
// Spring Boot Actuator 的安全配置 // Spring Boot Actuator 的安全配置
registry.antMatchers("/actuator").anonymous() registry.requestMatchers("/actuator").anonymous()
.antMatchers("/actuator/**").anonymous(); .requestMatchers("/actuator/**").anonymous();
// Druid 监控 // Druid 监控
registry.antMatchers("/druid/**").anonymous(); registry.requestMatchers("/druid/**").anonymous();
// RPC 服务的安全配置 // RPC 服务的安全配置
registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
} }
}; };

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
/** /**
@ -17,15 +18,15 @@ public class SecurityConfiguration {
return new AuthorizeRequestsCustomizer() { return new AuthorizeRequestsCustomizer() {
@Override @Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
// Swagger 接口文档 // Swagger 接口文档
registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据
.antMatchers("/swagger-ui.html").permitAll(); // Swagger UI .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI
// Spring Boot Actuator 的安全配置 // Spring Boot Actuator 的安全配置
registry.antMatchers("/actuator").anonymous() registry.requestMatchers("/actuator").anonymous()
.antMatchers("/actuator/**").anonymous(); .requestMatchers("/actuator/**").anonymous();
// Druid 监控 // Druid 监控
registry.antMatchers("/druid/**").anonymous(); registry.requestMatchers("/druid/**").anonymous();
} }
}; };

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.member.enums.ApiConstants;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
/** /**
@ -18,17 +19,17 @@ public class SecurityConfiguration {
return new AuthorizeRequestsCustomizer() { return new AuthorizeRequestsCustomizer() {
@Override @Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { public void customize(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry registry) {
// Swagger 接口文档 // Swagger 接口文档
registry.antMatchers("/v3/api-docs/**").permitAll() // 元数据 registry.requestMatchers("/v3/api-docs/**").permitAll() // 元数据
.antMatchers("/swagger-ui.html").permitAll(); // Swagger UI .requestMatchers("/swagger-ui.html").permitAll(); // Swagger UI
// Spring Boot Actuator 的安全配置 // Spring Boot Actuator 的安全配置
registry.antMatchers("/actuator").anonymous() registry.requestMatchers("/actuator").anonymous()
.antMatchers("/actuator/**").anonymous(); .requestMatchers("/actuator/**").anonymous();
// Druid 监控 // Druid 监控
registry.antMatchers("/druid/**").anonymous(); registry.requestMatchers("/druid/**").anonymous();
// RPC 服务的安全配置 // RPC 服务的安全配置
registry.antMatchers(ApiConstants.PREFIX + "/**").permitAll(); registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll();
} }
}; };

View File

@ -643,7 +643,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
tradeOrderItemMapper.updateBatch(updateItems); tradeOrderItemMapper.updateBatch(updateItems);
// 4. 更新支付订单 // 4. 更新支付订单
payOrderApi.updatePayOrderPrice(order.getPayOrderId(), newPayPrice); payOrderApi.updatePayOrderPrice(order.getPayOrderId(), newPayPrice).getCheckedData();
// 5. 记录订单日志 // 5. 记录订单日志
TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus(), TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus(),

View File

@ -1,15 +1,19 @@
package cn.iocoder.yudao.module.pay.api.order; 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.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.enums.ApiConstants; import cn.iocoder.yudao.module.pay.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping; 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.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory = @FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 支付单") @Tag(name = "RPC 服务 - 支付单")
@ -19,11 +23,20 @@ public interface PayOrderApi {
@PostMapping(PREFIX + "/create") @PostMapping(PREFIX + "/create")
@Operation(summary = "创建支付单") @Operation(summary = "创建支付单")
Long createOrder(@Valid @RequestBody PayOrderCreateReqDTO reqDTO); CommonResult<Long> createOrder(@Valid @RequestBody PayOrderCreateReqDTO reqDTO);
@PostMapping(PREFIX + "/get") @PostMapping(PREFIX + "/get")
@Operation(summary = "获得支付单") @Operation(summary = "获得支付单")
@Parameter(name = "id", description = "支付单编号", example = "1", required = true) @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);
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.pay.api.refund; 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.PayRefundCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
import cn.iocoder.yudao.module.pay.enums.ApiConstants; import cn.iocoder.yudao.module.pay.enums.ApiConstants;
@ -19,11 +20,11 @@ public interface PayRefundApi {
@PostMapping(PREFIX + "/create") @PostMapping(PREFIX + "/create")
@Operation(summary = "创建退款单") @Operation(summary = "创建退款单")
Long createRefund(@Valid @RequestBody PayRefundCreateReqDTO reqDTO); CommonResult<Long> createRefund(@Valid @RequestBody PayRefundCreateReqDTO reqDTO);
@PostMapping(PREFIX + "/get") @PostMapping(PREFIX + "/get")
@Operation(summary = "获得退款单") @Operation(summary = "获得退款单")
@Parameter(name = "id", description = "退款单编号", example = "1", required = true) @Parameter(name = "id", description = "退款单编号", example = "1", required = true)
PayRefundRespDTO getRefund(Long id); CommonResult<PayRefundRespDTO> getRefund(Long id);
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.pay.api.order; 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.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
@ -10,6 +11,8 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Service @Service
@RestController // 提供 RESTful API 接口,给 Feign 调用 @RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated @Validated
@ -19,14 +22,20 @@ public class PayOrderApiImpl implements PayOrderApi {
private PayOrderService payOrderService; private PayOrderService payOrderService;
@Override @Override
public Long createOrder(PayOrderCreateReqDTO reqDTO) { public CommonResult<Long> createOrder(PayOrderCreateReqDTO reqDTO) {
return payOrderService.createOrder(reqDTO); return success(payOrderService.createOrder(reqDTO));
} }
@Override @Override
public PayOrderRespDTO getOrder(Long id) { public CommonResult<PayOrderRespDTO> getOrder(Long id) {
PayOrderDO order = payOrderService.getOrder(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);
} }
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.pay.api.refund; 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.PayRefundCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
import cn.iocoder.yudao.module.pay.convert.refund.PayRefundConvert; 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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Service @Service
@RestController // 提供 RESTful API 接口,给 Feign 调用 @RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated @Validated
@ -18,13 +21,13 @@ public class PayRefundApiImpl implements PayRefundApi {
private PayRefundService payRefundService; private PayRefundService payRefundService;
@Override @Override
public Long createRefund(PayRefundCreateReqDTO reqDTO) { public CommonResult<Long> createRefund(PayRefundCreateReqDTO reqDTO) {
return payRefundService.createPayRefund(reqDTO); return success(payRefundService.createPayRefund(reqDTO));
} }
@Override @Override
public PayRefundRespDTO getRefund(Long id) { public CommonResult<PayRefundRespDTO> getRefund(Long id) {
return PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id)); return success(PayRefundConvert.INSTANCE.convert02(payRefundService.getRefund(id)));
} }
} }

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.api.social;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.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.api.social.dto.SocialUserUnbindReqDTO;
import cn.iocoder.yudao.module.system.enums.ApiConstants; import cn.iocoder.yudao.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -18,18 +19,9 @@ public interface SocialUserApi {
String PREFIX = ApiConstants.PREFIX + "/social-user"; 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") @PostMapping("PREFIX + /bind")
@Operation(summary = "绑定社交用户") @Operation(summary = "绑定社交用户")
CommonResult<Boolean> bindSocialUser(@Valid @RequestBody SocialUserBindReqDTO reqDTO); CommonResult<String> bindSocialUser(@Valid @RequestBody SocialUserBindReqDTO reqDTO);
@DeleteMapping("PREFIX + /unbind") @DeleteMapping("PREFIX + /unbind")
@Operation(summary = "取消绑定社交用户") @Operation(summary = "取消绑定社交用户")
@ -43,9 +35,9 @@ public interface SocialUserApi {
@Parameter(name = "code", description = "授权码", required = true, example = "tudou"), @Parameter(name = "code", description = "授权码", required = true, example = "tudou"),
@Parameter(name = "state", description = "state", required = true, example = "coke") @Parameter(name = "state", description = "state", required = true, example = "coke")
}) })
CommonResult<Long> getBindUserId(@RequestParam("userType") Integer userType, CommonResult<SocialUserRespDTO> getSocialUser(@RequestParam("userType") Integer userType,
@RequestParam("type") Integer type, @RequestParam("type") Integer type,
@RequestParam("code") String code, @RequestParam("code") String code,
@RequestParam("state") String state); @RequestParam("state") String state);
} }

View File

@ -36,7 +36,7 @@ public class SocialUserBindReqDTO {
*/ */
@InEnum(SocialTypeEnum.class) @InEnum(SocialTypeEnum.class)
@NotNull(message = "社交平台的类型不能为空") @NotNull(message = "社交平台的类型不能为空")
private Integer type; private Integer socialType;
/** /**
* *
*/ */

View File

@ -32,12 +32,12 @@ public class SocialUserUnbindReqDTO {
*/ */
@InEnum(SocialTypeEnum.class) @InEnum(SocialTypeEnum.class)
@NotNull(message = "社交平台的类型不能为空") @NotNull(message = "社交平台的类型不能为空")
private Integer type; private Integer socialType;
/** /**
* unionId * unionId
*/ */
@NotEmpty(message = "社交平台的 unionId 不能为空") @NotEmpty(message = "社交平台的 unionId 不能为空")
private String unionId; private String openid;
} }

View File

@ -1,10 +1,13 @@
package cn.iocoder.yudao.module.system.controller.admin.auth; package cn.iocoder.yudao.module.system.controller.admin.auth;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 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.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.security.config.SecurityProperties; 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.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; 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.MenuService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService; 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.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 cn.iocoder.yudao.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; 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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.obtainAuthorization;
@Tag(name = "管理后台 - 认证") @Tag(name = "管理后台 - 认证")
@RestController @RestController
@ -55,7 +58,7 @@ public class AuthController {
@Resource @Resource
private PermissionService permissionService; private PermissionService permissionService;
@Resource @Resource
private SocialUserService socialUserService; private SocialClientService socialClientService;
@Resource @Resource
private SecurityProperties securityProperties; private SecurityProperties securityProperties;
@ -73,7 +76,8 @@ public class AuthController {
@Operation(summary = "登出系统") @Operation(summary = "登出系统")
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
public CommonResult<Boolean> logout(HttpServletRequest request) { 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)) { if (StrUtil.isNotBlank(token)) {
authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType());
} }
@ -100,6 +104,9 @@ public class AuthController {
// 1.2 获得角色列表 // 1.2 获得角色列表
Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(getLoginUserId()); 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); List<RoleDO> roles = roleService.getRoleList(roleIds);
roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色 roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
@ -142,7 +149,8 @@ public class AuthController {
}) })
public CommonResult<String> socialLogin(@RequestParam("type") Integer type, public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
@RequestParam("redirectUri") String redirectUri) { @RequestParam("redirectUri") String redirectUri) {
return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri)); return success(socialClientService.getAuthorizeUrl(
type, UserTypeEnum.ADMIN.getValue(), redirectUri));
} }
@PostMapping("/social-login") @PostMapping("/social-login")

View File

@ -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.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.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.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 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.controller.admin.dept.vo.post.PostPageReqVO;
import cn.iocoder.yudao.module.system.convert.dept.PostConvert; 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.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.service.dept.PostService; import cn.iocoder.yudao.module.system.service.dept.PostService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -39,16 +43,16 @@ public class PostController {
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建岗位") @Operation(summary = "创建岗位")
@PreAuthorize("@ss.hasPermission('system:post:create')") @PreAuthorize("@ss.hasPermission('system:post:create')")
public CommonResult<Long> createPost(@Valid @RequestBody PostCreateReqVO reqVO) { public CommonResult<Long> createPost(@Valid @RequestBody PostSaveReqVO createReqVO) {
Long postId = postService.createPost(reqVO); Long postId = postService.createPost(createReqVO);
return success(postId); return success(postId);
} }
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "修改岗位") @Operation(summary = "修改岗位")
@PreAuthorize("@ss.hasPermission('system:post:update')") @PreAuthorize("@ss.hasPermission('system:post:update')")
public CommonResult<Boolean> updatePost(@Valid @RequestBody PostUpdateReqVO reqVO) { public CommonResult<Boolean> updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) {
postService.updatePost(reqVO); postService.updatePost(updateReqVO);
return success(true); return success(true);
} }
@ -65,35 +69,38 @@ public class PostController {
@Parameter(name = "id", description = "岗位编号", required = true, example = "1024") @Parameter(name = "id", description = "岗位编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:post:query')") @PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PostRespVO> getPost(@RequestParam("id") Long id) { 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") @GetMapping("/list-all-simple")
@Operation(summary = "获取岗位精简信息列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") @Operation(summary = "获取岗位列表", description = "只包含被开启的岗位,主要用于前端的下拉选项")
public CommonResult<List<PostSimpleRespVO>> getSimplePostList() { public CommonResult<List<PostSimpleRespVO>> getSimplePostList() {
// 获得岗位列表,只要开启状态的 // 获得岗位列表,只要开启状态的
List<PostDO> list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); List<PostDO> list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus()));
// 排序后,返回给前端 // 排序后,返回给前端
list.sort(Comparator.comparing(PostDO::getSort)); list.sort(Comparator.comparing(PostDO::getSort));
return success(PostConvert.INSTANCE.convertList02(list)); return success(BeanUtils.toBean(list, PostSimpleRespVO.class));
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得岗位分页列表") @Operation(summary = "获得岗位分页列表")
@PreAuthorize("@ss.hasPermission('system:post:query')") @PreAuthorize("@ss.hasPermission('system:post:query')")
public CommonResult<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO reqVO) { public CommonResult<PageResult<PostRespVO>> getPostPage(@Validated PostPageReqVO pageReqVO) {
return success(PostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO))); PageResult<PostDO> pageResult = postService.getPostPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, PostRespVO.class));
} }
@GetMapping("/export") @GetMapping("/export")
@Operation(summary = "岗位管理") @Operation(summary = "岗位管理")
@PreAuthorize("@ss.hasPermission('system:post:export')") @PreAuthorize("@ss.hasPermission('system:post:export')")
@OperateLog(type = EXPORT) @OperateLog(type = EXPORT)
public void export(HttpServletResponse response, @Validated PostExportReqVO reqVO) throws IOException { public void export(HttpServletResponse response, @Validated PostPageReqVO reqVO) throws IOException {
List<PostDO> posts = postService.getPostList(reqVO); reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<PostExcelVO> data = PostConvert.INSTANCE.convertList03(posts); 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));
} }
} }

View File

@ -1,21 +1,23 @@
package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; 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 io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
/** @Schema(description = "管理后台 - 岗位创建/修改 Request VO")
* Base VO VO 使
* VO Swagger
*/
@Data @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 = "岗位名称不能为空") @NotBlank(message = "岗位名称不能为空")
@Size(max = 50, message = "岗位名称长度不能超过50个字符") @Size(max = 50, message = "岗位名称长度不能超过 50 个字符")
private String name; private String name;
@Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@ -27,10 +29,11 @@ public class PostBaseVO {
@NotNull(message = "显示顺序不能为空") @NotNull(message = "显示顺序不能为空")
private Integer sort; 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; private Integer status;
@Schema(description = "备注", example = "快乐的备注") @Schema(description = "备注", example = "快乐的备注")
private String remark; private String remark;
} }

View File

@ -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;
}

View File

@ -29,7 +29,7 @@ public class TenantBaseVO {
private Integer status; private Integer status;
@Schema(description = "绑定域名", example = "https://www.iocoder.cn") @Schema(description = "绑定域名", example = "https://www.iocoder.cn")
private String domain; private String website;
@Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "租户套餐编号不能为空") @NotNull(message = "租户套餐编号不能为空")

View File

@ -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.logger.dto.LoginLogCreateReqDTO;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 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.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.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
@ -155,14 +156,14 @@ public class AdminAuthServiceImpl implements AdminAuthService {
@Override @Override
public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) { public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) {
// 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
Long userId = socialUserService.getBindUserId(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(),
reqVO.getCode(), reqVO.getState()); reqVO.getCode(), reqVO.getState());
if (userId == null) { if (socialUser == null) {
throw exception(AUTH_THIRD_LOGIN_NOT_BIND); throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
} }
// 获得用户 // 获得用户
AdminUserDO user = userService.getUser(userId); AdminUserDO user = userService.getUser(socialUser.getUserId());
if (user == null) { if (user == null) {
throw exception(USER_NOT_EXISTS); throw exception(USER_NOT_EXISTS);
} }

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.system.service.sms; 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.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.SmsLogExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO;
@ -55,13 +54,12 @@ public class SmsLogServiceImpl implements SmsLogService {
} }
@Override @Override
public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, public void updateSmsSendResult(Long id, Boolean success,
String apiSendCode, String apiSendMsg, String apiSendCode, String apiSendMsg,
String apiRequestId, String apiSerialNo) { String apiRequestId, String apiSerialNo) {
SmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? SmsSendStatusEnum sendStatus = success ? SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE;
SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; smsLogMapper.updateById(SmsLogDO.builder().id(id)
smsLogMapper.updateById(SmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()) .sendStatus(sendStatus.getStatus()).sendTime(LocalDateTime.now())
.sendTime(LocalDateTime.now()).sendCode(sendCode).sendMsg(sendMsg)
.apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg)
.apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build());
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.service.sms; package cn.iocoder.yudao.module.system.service.sms;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue; 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.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; 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.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.SmsReceiveRespDTO;
import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; 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 cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@ -35,6 +36,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
* @author * @author
*/ */
@Service @Service
@Slf4j
public class SmsSendServiceImpl implements SmsSendService { public class SmsSendServiceImpl implements SmsSendService {
@Resource @Resource
@ -158,11 +160,17 @@ public class SmsSendServiceImpl implements SmsSendService {
SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId()); SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId());
Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId());
// 发送短信 // 发送短信
SmsCommonResult<SmsSendRespDTO> sendResult = smsClient.sendSms(message.getLogId(), message.getMobile(), try {
message.getApiTemplateId(), message.getTemplateParams()); SmsSendRespDTO sendResponse = smsClient.sendSms(message.getLogId(), message.getMobile(),
smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), message.getApiTemplateId(), message.getTemplateParams());
sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(), smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(),
sendResult.getData() != null ? sendResult.getData().getSerialNo() : null); 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 @Override

View File

@ -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.dal.dataobject.social.SocialClientDO;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import com.xingyuv.jushauth.model.AuthUser; import com.xingyuv.jushauth.model.AuthUser;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
/** /**
* Service * Service

View File

@ -31,6 +31,7 @@ import com.xingyuv.jushauth.model.AuthUser;
import com.xingyuv.jushauth.request.AuthRequest; import com.xingyuv.jushauth.request.AuthRequest;
import com.xingyuv.jushauth.utils.AuthStateUtils; import com.xingyuv.jushauth.utils.AuthStateUtils;
import com.xingyuv.justauth.AuthRequestFactory; import com.xingyuv.justauth.AuthRequestFactory;
import jakarta.annotation.Resource;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxJsapiSignature; 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.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.time.Duration; import java.time.Duration;
import java.util.Objects; import java.util.Objects;

View File

@ -1,11 +1,13 @@
package cn.iocoder.yudao.module.system.service.social; package cn.iocoder.yudao.module.system.service.social;
import cn.iocoder.yudao.framework.common.exception.ServiceException; 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.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.dal.dataobject.social.SocialUserDO;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List; import java.util.List;
@ -16,31 +18,10 @@ import java.util.List;
*/ */
public interface SocialUserService { 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 * @param userType
* @return * @return
*/ */
@ -50,29 +31,49 @@ public interface SocialUserService {
* *
* *
* @param reqDTO * @param reqDTO
* @return openid
*/ */
void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO);
/** /**
* *
* *
* @param userId * @param userId
* @param userType * @param userType
* @param type {@link SocialTypeEnum} * @param socialType {@link SocialTypeEnum}
* @param openid openid * @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} * {@link ServiceException}
* *
* @param userType * @param userType
* @param type * @param socialType
* @param code * @param code
* @param state state * @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);
} }

View File

@ -2,20 +2,19 @@ package cn.iocoder.yudao.module.system.service.social;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; 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.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.SocialUserBindDO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 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.SocialUserBindMapper;
import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 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.model.AuthUser;
import com.xingyuv.jushauth.request.AuthRequest;
import com.xingyuv.jushauth.utils.AuthStateUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; 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.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 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.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 * Service
@ -39,51 +39,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@Slf4j @Slf4j
public class SocialUserServiceImpl implements SocialUserService { public class SocialUserServiceImpl implements SocialUserService {
@Resource// 由于自定义了 YudaoAuthRequestFactory 无法覆盖默认的 AuthRequestFactory所以只能注入它
private YudaoAuthRequestFactory yudaoAuthRequestFactory;
@Resource @Resource
private SocialUserBindMapper socialUserBindMapper; private SocialUserBindMapper socialUserBindMapper;
@Resource @Resource
private SocialUserMapper socialUserMapper; private SocialUserMapper socialUserMapper;
@Override @Resource
public String getAuthorizeUrl(Integer type, String redirectUri) { private SocialClientService socialClientService;
// 获得对应的 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;
}
@Override @Override
public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) { public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {
@ -98,9 +60,10 @@ public class SocialUserServiceImpl implements SocialUserService {
@Override @Override
@Transactional @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, "社交用户不能为空"); Assert.notNull(socialUser, "社交用户不能为空");
// 社交用户可能之前绑定过别的用户,需要进行解绑 // 社交用户可能之前绑定过别的用户,需要进行解绑
@ -115,12 +78,13 @@ public class SocialUserServiceImpl implements SocialUserService {
.userId(reqDTO.getUserId()).userType(reqDTO.getUserType()) .userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
.socialUserId(socialUser.getId()).socialType(socialUser.getType()).build(); .socialUserId(socialUser.getId()).socialType(socialUser.getType()).build();
socialUserBindMapper.insert(socialUserBind); socialUserBindMapper.insert(socialUserBind);
return socialUser.getOpenid();
} }
@Override @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 社交用户 // 获得 openid 对应的 SocialUserDO 社交用户
SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(type, openid); SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
if (socialUser == null) { if (socialUser == null) {
throw exception(SOCIAL_USER_NOT_FOUND); throw exception(SOCIAL_USER_NOT_FOUND);
} }
@ -130,9 +94,9 @@ public class SocialUserServiceImpl implements SocialUserService {
} }
@Override @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, "社交用户不能为空"); Assert.notNull(socialUser, "社交用户不能为空");
// 如果未绑定的社交用户,则无法自动登录,进行报错 // 如果未绑定的社交用户,则无法自动登录,进行报错
@ -141,27 +105,59 @@ public class SocialUserServiceImpl implements SocialUserService {
if (socialUserBind == null) { if (socialUserBind == null) {
throw exception(AUTH_THIRD_LOGIN_NOT_BIND); throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
} }
return socialUserBind.getUserId(); return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId());
} }
// TODO 芋艿:调整下单测
/** /**
* *
* {@link ServiceException}
* *
* @param type * @param socialType {@link SocialTypeEnum}
* @param code * @param userType
* @param state state * @param code
* @return * @param state state
* @return
*/ */
private AuthUser getAuthUser(Integer type, String code, String state) { @NotNull
AuthRequest authRequest = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource()); public SocialUserDO authSocialUser(Integer socialType, Integer userType, String code, String state) {
AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build(); // 优先从 DB 中获取,因为 code 有且可以使用一次。
AuthResponse<?> authResponse = authRequest.login(authCallback); // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", type, SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(socialType, code, state);
toJsonString(authCallback), toJsonString(authResponse)); if (socialUser != null) {
if (!authResponse.ok()) { return socialUser;
throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg());
} }
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);
} }
} }