Commit 2df46a7c2da5868b0321face7c18ae14c3b5b9a0

Authored by YunaiV
2 parents dd2d8a2b 65843d55

Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into pay_extension

 Conflicts:
	更新日志.md
Showing 35 changed files with 542 additions and 125 deletions
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 20 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
21 21
22 <properties> 22 <properties>
23 - <revision>1.1.0-snapshot</revision> 23 + <revision>1.2.0-snapshot</revision>
24 <!-- Maven 相关 --> 24 <!-- Maven 相关 -->
25 <java.version>1.8</java.version> 25 <java.version>1.8</java.version>
26 <maven.compiler.source>${java.version}</maven.compiler.source> 26 <maven.compiler.source>${java.version}</maven.compiler.source>
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java
1 package cn.iocoder.yudao.adminserver.modules.infra.controller.file; 1 package cn.iocoder.yudao.adminserver.modules.infra.controller.file;
2 2
3 import cn.hutool.core.io.IoUtil; 3 import cn.hutool.core.io.IoUtil;
  4 +import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService;
  5 +import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
  6 +import cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo.InfFileRespVO;
4 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; 7 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
  8 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 9 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;  
8 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFileRespVO;  
9 import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert; 11 import cn.iocoder.yudao.adminserver.modules.infra.convert.file.InfFileConvert;
10 -import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService;  
11 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 12 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
12 import io.swagger.annotations.Api; 13 import io.swagger.annotations.Api;
13 import io.swagger.annotations.ApiImplicitParam; 14 import io.swagger.annotations.ApiImplicitParam;
@@ -36,6 +37,8 @@ public class InfFileController { @@ -36,6 +37,8 @@ public class InfFileController {
36 37
37 @Resource 38 @Resource
38 private InfFileService fileService; 39 private InfFileService fileService;
  40 + @Resource
  41 + private InfFileCoreService fileCoreService;
39 42
40 @PostMapping("/upload") 43 @PostMapping("/upload")
41 @ApiOperation("上传文件") 44 @ApiOperation("上传文件")
@@ -45,7 +48,7 @@ public class InfFileController { @@ -45,7 +48,7 @@ public class InfFileController {
45 }) 48 })
46 public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file, 49 public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
47 @RequestParam("path") String path) throws IOException { 50 @RequestParam("path") String path) throws IOException {
48 - return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream()))); 51 + return success(fileCoreService.createFile(path, IoUtil.readBytes(file.getInputStream())));
49 } 52 }
50 53
51 @DeleteMapping("/delete") 54 @DeleteMapping("/delete")
@@ -53,7 +56,7 @@ public class InfFileController { @@ -53,7 +56,7 @@ public class InfFileController {
53 @ApiImplicitParam(name = "id", value = "编号", required = true) 56 @ApiImplicitParam(name = "id", value = "编号", required = true)
54 @PreAuthorize("@ss.hasPermission('infra:file:delete')") 57 @PreAuthorize("@ss.hasPermission('infra:file:delete')")
55 public CommonResult<Boolean> deleteFile(@RequestParam("id") String id) { 58 public CommonResult<Boolean> deleteFile(@RequestParam("id") String id) {
56 - fileService.deleteFile(id); 59 + fileCoreService.deleteFile(id);
57 return success(true); 60 return success(true);
58 } 61 }
59 62
@@ -61,7 +64,7 @@ public class InfFileController { @@ -61,7 +64,7 @@ public class InfFileController {
61 @ApiOperation("下载文件") 64 @ApiOperation("下载文件")
62 @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class) 65 @ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
63 public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException { 66 public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
64 - InfFileDO file = fileService.getFile(path); 67 + InfFileDO file = fileCoreService.getFile(path);
65 if (file == null) { 68 if (file == null) {
66 log.warn("[getFile][path({}) 文件不存在]", path); 69 log.warn("[getFile][path({}) 文件不存在]", path);
67 response.setStatus(HttpStatus.NOT_FOUND.value()); 70 response.setStatus(HttpStatus.NOT_FOUND.value());
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/convert/file/InfFileConvert.java
1 package cn.iocoder.yudao.adminserver.modules.infra.convert.file; 1 package cn.iocoder.yudao.adminserver.modules.infra.convert.file;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo.InfFileRespVO;
3 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; 4 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFileRespVO;  
6 import org.mapstruct.Mapper; 6 import org.mapstruct.Mapper;
7 import org.mapstruct.factory.Mappers; 7 import org.mapstruct.factory.Mappers;
8 8
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/dal/mysql/file/InfFileMapper.java
1 package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file; 1 package cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
3 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; 4 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
7 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;  
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 9
  10 +/**
  11 + * admin 文件操作 Mapper
  12 + *
  13 + * @author 芋道源码
  14 + */
10 @Mapper 15 @Mapper
11 public interface InfFileMapper extends BaseMapperX<InfFileDO> { 16 public interface InfFileMapper extends BaseMapperX<InfFileDO> {
12 -  
13 - default Integer selectCountById(String id) {  
14 - return selectCount("id", id);  
15 - }  
16 -  
17 default PageResult<InfFileDO> selectPage(InfFilePageReqVO reqVO) { 17 default PageResult<InfFileDO> selectPage(InfFilePageReqVO reqVO) {
18 return selectPage(reqVO, new QueryWrapperX<InfFileDO>() 18 return selectPage(reqVO, new QueryWrapperX<InfFileDO>()
19 .likeIfPresent("id", reqVO.getId()) 19 .likeIfPresent("id", reqVO.getId())
@@ -21,5 +21,4 @@ public interface InfFileMapper extends BaseMapperX&lt;InfFileDO&gt; { @@ -21,5 +21,4 @@ public interface InfFileMapper extends BaseMapperX&lt;InfFileDO&gt; {
21 .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime()) 21 .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
22 .orderByDesc("create_time")); 22 .orderByDesc("create_time"));
23 } 23 }
24 -  
25 } 24 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/enums/InfErrorCodeConstants.java
@@ -27,7 +27,4 @@ public interface InfErrorCodeConstants { @@ -27,7 +27,4 @@ public interface InfErrorCodeConstants {
27 ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在"); 27 ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在");
28 ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理"); 28 ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理");
29 29
30 - // ========== 文件 1001003000 ==========  
31 - ErrorCode FILE_NOT_EXISTS = new ErrorCode(1001003000, "文件不存在");  
32 -  
33 } 30 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileService.java
1 package cn.iocoder.yudao.adminserver.modules.infra.service.file; 1 package cn.iocoder.yudao.adminserver.modules.infra.service.file;
2 2
  3 +import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
3 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; 4 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;  
6 6
7 /** 7 /**
8 * 文件 Service 接口 8 * 文件 Service 接口
@@ -12,30 +12,6 @@ import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePage @@ -12,30 +12,6 @@ import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePage
12 public interface InfFileService { 12 public interface InfFileService {
13 13
14 /** 14 /**
15 - * 保存文件,并返回文件的访问路径  
16 - *  
17 - * @param path 文件路径  
18 - * @param content 文件内容  
19 - * @return 文件路径  
20 - */  
21 - String createFile(String path, byte[] content);  
22 -  
23 - /**  
24 - * 删除文件  
25 - *  
26 - * @param id 编号  
27 - */  
28 - void deleteFile(String id);  
29 -  
30 - /**  
31 - * 获得文件  
32 - *  
33 - * @param path 文件路径  
34 - * @return 文件  
35 - */  
36 - InfFileDO getFile(String path);  
37 -  
38 - /**  
39 * 获得文件分页 15 * 获得文件分页
40 * 16 *
41 * @param pageReqVO 分页查询 17 * @param pageReqVO 分页查询
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/impl/InfFileServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.infra.service.file.impl; 1 package cn.iocoder.yudao.adminserver.modules.infra.service.file.impl;
2 2
3 -import cn.hutool.core.io.FileTypeUtil;  
4 -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;  
5 -import cn.iocoder.yudao.framework.common.pojo.PageResult;  
6 -import cn.iocoder.yudao.adminserver.modules.infra.framework.file.config.FileProperties;  
7 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;  
8 import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file.InfFileMapper; 3 import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file.InfFileMapper;
9 import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService; 4 import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService;
  5 +import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
  6 +import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
  7 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
11 10
12 import javax.annotation.Resource; 11 import javax.annotation.Resource;
13 -import java.io.ByteArrayInputStream;  
14 -  
15 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
16 -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.FILE_NOT_EXISTS;  
17 -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;  
18 12
19 /** 13 /**
20 * 文件 Service 实现类 14 * 文件 Service 实现类
@@ -27,43 +21,6 @@ public class InfFileServiceImpl implements InfFileService { @@ -27,43 +21,6 @@ public class InfFileServiceImpl implements InfFileService {
27 @Resource 21 @Resource
28 private InfFileMapper fileMapper; 22 private InfFileMapper fileMapper;
29 23
30 - @Resource  
31 - private FileProperties fileProperties;  
32 -  
33 - @Override  
34 - public String createFile(String path, byte[] content) {  
35 - if (fileMapper.selectCountById(path) > 0) {  
36 - throw exception(FILE_PATH_EXISTS);  
37 - }  
38 - // 保存到数据库  
39 - InfFileDO file = new InfFileDO();  
40 - file.setId(path);  
41 - file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content)));  
42 - file.setContent(content);  
43 - fileMapper.insert(file);  
44 - // 拼接路径返回  
45 - return fileProperties.getBasePath() + path;  
46 - }  
47 -  
48 - @Override  
49 - public void deleteFile(String id) {  
50 - // 校验存在  
51 - this.validateFileExists(id);  
52 - // 更新  
53 - fileMapper.deleteById(id);  
54 - }  
55 -  
56 - private void validateFileExists(String id) {  
57 - if (fileMapper.selectById(id) == null) {  
58 - throw exception(FILE_NOT_EXISTS);  
59 - }  
60 - }  
61 -  
62 - @Override  
63 - public InfFileDO getFile(String path) {  
64 - return fileMapper.selectById(path);  
65 - }  
66 -  
67 @Override 24 @Override
68 public PageResult<InfFileDO> getFilePage(InfFilePageReqVO pageReqVO) { 25 public PageResult<InfFileDO> getFilePage(InfFilePageReqVO pageReqVO) {
69 return fileMapper.selectPage(pageReqVO); 26 return fileMapper.selectPage(pageReqVO);
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.io.IoUtil; 4 import cn.hutool.core.io.IoUtil;
5 import cn.hutool.core.util.IdUtil; 5 import cn.hutool.core.util.IdUtil;
6 import cn.hutool.core.util.StrUtil; 6 import cn.hutool.core.util.StrUtil;
7 -import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService;  
8 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; 7 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO;
9 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; 8 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO;
10 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; 9 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*;
@@ -16,6 +15,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; @@ -16,6 +15,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
16 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; 15 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
17 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 16 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
18 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 17 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  18 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
19 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 19 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
20 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 20 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
21 import cn.iocoder.yudao.framework.common.exception.ServiceException; 21 import cn.iocoder.yudao.framework.common.exception.ServiceException;
@@ -59,7 +59,7 @@ public class SysUserServiceImpl implements SysUserService { @@ -59,7 +59,7 @@ public class SysUserServiceImpl implements SysUserService {
59 @Resource 59 @Resource
60 private PasswordEncoder passwordEncoder; 60 private PasswordEncoder passwordEncoder;
61 @Resource 61 @Resource
62 - private InfFileService fileService; 62 + private InfFileCoreService fileService;
63 63
64 @Override 64 @Override
65 public Long createUser(SysUserCreateReqVO reqVO) { 65 public Long createUser(SysUserCreateReqVO reqVO) {
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/file/InfFileServiceTest.java
@@ -2,12 +2,12 @@ package cn.iocoder.yudao.adminserver.modules.infra.service.file; @@ -2,12 +2,12 @@ package cn.iocoder.yudao.adminserver.modules.infra.service.file;
2 2
3 import cn.hutool.core.io.resource.ResourceUtil; 3 import cn.hutool.core.io.resource.ResourceUtil;
4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest; 4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
  5 +import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;
5 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; 6 import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
  7 +import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper;
  8 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.impl.InfFileCoreServiceImpl;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.adminserver.modules.infra.framework.file.config.FileProperties;  
8 -import cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo.InfFilePageReqVO;  
9 -import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.file.InfFileMapper;  
10 -import cn.iocoder.yudao.adminserver.modules.infra.service.file.impl.InfFileServiceImpl; 10 +import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties;
11 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 11 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
12 import org.junit.jupiter.api.Test; 12 import org.junit.jupiter.api.Test;
13 import org.springframework.boot.test.mock.mockito.MockBean; 13 import org.springframework.boot.test.mock.mockito.MockBean;
@@ -15,8 +15,8 @@ import org.springframework.context.annotation.Import; @@ -15,8 +15,8 @@ import org.springframework.context.annotation.Import;
15 15
16 import javax.annotation.Resource; 16 import javax.annotation.Resource;
17 17
  18 +import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.FILE_NOT_EXISTS;
18 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 19 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
19 -import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.FILE_NOT_EXISTS;  
20 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS; 20 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
21 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 21 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
22 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 22 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
@@ -24,17 +24,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString @@ -24,17 +24,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
24 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; 24 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
25 import static org.junit.jupiter.api.Assertions.*; 25 import static org.junit.jupiter.api.Assertions.*;
26 26
27 -@Import({InfFileServiceImpl.class, FileProperties.class}) 27 +@Import({InfFileCoreServiceImpl.class, FileProperties.class})
28 public class InfFileServiceTest extends BaseDbUnitTest { 28 public class InfFileServiceTest extends BaseDbUnitTest {
29 29
30 @Resource 30 @Resource
31 - private InfFileServiceImpl fileService; 31 + private InfFileService fileService;
32 32
33 @MockBean 33 @MockBean
34 private FileProperties fileProperties; 34 private FileProperties fileProperties;
35 35
36 @Resource 36 @Resource
37 - private InfFileMapper fileMapper; 37 + private InfFileCoreMapper fileMapper;
38 38
39 @Test 39 @Test
40 public void testCreateFile_success() { 40 public void testCreateFile_success() {
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImplTest.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.adminserver.modules.system.service.user; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.adminserver.modules.system.service.user;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.RandomUtil; 4 import cn.hutool.core.util.RandomUtil;
5 import cn.iocoder.yudao.adminserver.BaseDbUnitTest; 5 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
6 -import cn.iocoder.yudao.adminserver.modules.infra.service.file.InfFileService;  
7 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO;
8 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; 7 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO;
9 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; 8 import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*;
@@ -14,6 +13,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; @@ -14,6 +13,7 @@ import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
14 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
15 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
16 import cn.iocoder.yudao.adminserver.modules.system.service.user.impl.SysUserServiceImpl; 15 import cn.iocoder.yudao.adminserver.modules.system.service.user.impl.SysUserServiceImpl;
  16 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
17 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 17 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
18 import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum; 18 import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum;
19 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 19 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -69,7 +69,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest { @@ -69,7 +69,7 @@ public class SysUserServiceImplTest extends BaseDbUnitTest {
69 @MockBean 69 @MockBean
70 private PasswordEncoder passwordEncoder; 70 private PasswordEncoder passwordEncoder;
71 @MockBean 71 @MockBean
72 - private InfFileService fileService; 72 + private InfFileCoreService fileService;
73 73
74 @Test 74 @Test
75 public void testCreatUser_success() { 75 public void testCreatUser_success() {
yudao-core-service/pom.xml
@@ -5,14 +5,14 @@ @@ -5,14 +5,14 @@
5 <parent> 5 <parent>
6 <artifactId>yudao</artifactId> 6 <artifactId>yudao</artifactId>
7 <groupId>cn.iocoder.boot</groupId> 7 <groupId>cn.iocoder.boot</groupId>
8 - <version>1.1.0-snapshot</version> 8 + <version>1.2.0-snapshot</version>
9 </parent> 9 </parent>
10 <modelVersion>4.0.0</modelVersion> 10 <modelVersion>4.0.0</modelVersion>
11 11
12 <artifactId>yudao-core-service</artifactId> 12 <artifactId>yudao-core-service</artifactId>
13 <packaging>jar</packaging> 13 <packaging>jar</packaging>
14 14
15 - <name>yudao-admin-server</name> 15 + <name>yudao-core-service</name>
16 <description> 16 <description>
17 公共服务,通过 jar 包的方式,被 yudao-admin-server、yudao-user-service 使用。例如说: 17 公共服务,通过 jar 包的方式,被 yudao-admin-server、yudao-user-service 使用。例如说:
18 1. 日志相关:访问日志、登录日志、异常日志等等 18 1. 日志相关:访问日志、登录日志、异常日志等等
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/vo/InfFileRespVO.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/controller/file/vo/InfFileRespVO.java
1 -package cn.iocoder.yudao.adminserver.modules.infra.controller.file.vo; 1 +package cn.iocoder.yudao.coreservice.modules.infra.controller.file.vo;
2 2
3 import io.swagger.annotations.ApiModel; 3 import io.swagger.annotations.ApiModel;
4 import io.swagger.annotations.ApiModelProperty; 4 import io.swagger.annotations.ApiModelProperty;
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/mysql/file/InfFileCoreMapper.java
@@ -6,5 +6,7 @@ import org.apache.ibatis.annotations.Mapper; @@ -6,5 +6,7 @@ import org.apache.ibatis.annotations.Mapper;
6 6
7 @Mapper 7 @Mapper
8 public interface InfFileCoreMapper extends BaseMapperX<InfFileDO> { 8 public interface InfFileCoreMapper extends BaseMapperX<InfFileDO> {
9 - 9 + default Integer selectCountById(String id) {
  10 + return selectCount("id", id);
  11 + }
10 } 12 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/framework/file/config/FileConfiguration.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileConfiguration.java
1 -package cn.iocoder.yudao.adminserver.modules.infra.framework.file.config; 1 +package cn.iocoder.yudao.coreservice.modules.infra.framework.file.config;
2 2
3 import org.springframework.boot.context.properties.EnableConfigurationProperties; 3 import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 import org.springframework.context.annotation.Configuration; 4 import org.springframework.context.annotation.Configuration;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/framework/file/config/FileProperties.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/config/FileProperties.java
1 -package cn.iocoder.yudao.adminserver.modules.infra.framework.file.config; 1 +package cn.iocoder.yudao.coreservice.modules.infra.framework.file.config;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import org.springframework.boot.context.properties.ConfigurationProperties; 4 import org.springframework.boot.context.properties.ConfigurationProperties;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/framework/file/package-info.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/framework/file/package-info.java
@@ -13,4 +13,4 @@ @@ -13,4 +13,4 @@
13 * 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。 13 * 综合考虑,暂时使用方案 3 的方式,比较适合这样一个 all in one 的项目。
14 * 随着文件的量级大了之后,还是推荐采用云服务。 14 * 随着文件的量级大了之后,还是推荐采用云服务。
15 */ 15 */
16 -package cn.iocoder.yudao.adminserver.modules.infra.framework.file; 16 +package cn.iocoder.yudao.coreservice.modules.infra.framework.file;
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreService.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.infra.service.file;
  2 +
  3 +import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
  4 +
  5 +/**
  6 + * core service 文件接口
  7 + *
  8 + * @author 宋天
  9 + */
  10 +public interface InfFileCoreService {
  11 +
  12 +
  13 + /**
  14 + * 保存文件,并返回文件的访问路径
  15 + *
  16 + * @param path 文件路径
  17 + * @param content 文件内容
  18 + * @return 文件路径
  19 + */
  20 + String createFile(String path, byte[] content);
  21 +
  22 + /**
  23 + * 删除文件
  24 + *
  25 + * @param id 编号
  26 + */
  27 + void deleteFile(String id);
  28 +
  29 + /**
  30 + * 获得文件
  31 + *
  32 + * @param path 文件路径
  33 + * @return 文件
  34 + */
  35 + InfFileDO getFile(String path);
  36 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/impl/InfFileCoreServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.infra.service.file.impl;
  2 +
  3 +import cn.hutool.core.io.FileTypeUtil;
  4 +import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
  5 +import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.file.InfFileCoreMapper;
  6 +import cn.iocoder.yudao.coreservice.modules.infra.framework.file.config.FileProperties;
  7 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +import javax.annotation.Resource;
  11 +import java.io.ByteArrayInputStream;
  12 +
  13 +import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.*;
  14 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  15 +
  16 +/**
  17 + * core service 文件实现类
  18 + *
  19 + * @author 宋天
  20 + */
  21 +@Service
  22 +public class InfFileCoreServiceImpl implements InfFileCoreService {
  23 +
  24 + @Resource
  25 + private InfFileCoreMapper fileMapper;
  26 +
  27 + @Resource
  28 + private FileProperties fileProperties;
  29 +
  30 + @Override
  31 + public String createFile(String path, byte[] content) {
  32 + if (fileMapper.selectCountById(path) > 0) {
  33 + throw exception(FILE_PATH_EXISTS);
  34 + }
  35 + // 保存到数据库
  36 + InfFileDO file = new InfFileDO();
  37 + file.setId(path);
  38 + file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content)));
  39 + file.setContent(content);
  40 + fileMapper.insert(file);
  41 + // 拼接路径返回
  42 + return fileProperties.getBasePath() + path;
  43 + }
  44 +
  45 + @Override
  46 + public void deleteFile(String id) {
  47 + // 校验存在
  48 + this.validateFileExists(id);
  49 + // 更新
  50 + fileMapper.deleteById(id);
  51 + }
  52 +
  53 + private void validateFileExists(String id) {
  54 + if (fileMapper.selectById(id) == null) {
  55 + throw exception(FILE_NOT_EXISTS);
  56 + }
  57 + }
  58 +
  59 + @Override
  60 + public InfFileDO getFile(String path) {
  61 + return fileMapper.selectById(path);
  62 + }
  63 +
  64 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/SysErrorCodeConstants.java
@@ -14,4 +14,7 @@ public interface SysErrorCodeConstants { @@ -14,4 +14,7 @@ public interface SysErrorCodeConstants {
14 ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1006000001, "模板参数({})缺失"); 14 ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1006000001, "模板参数({})缺失");
15 ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1006000000, "短信模板不存在"); 15 ErrorCode SMS_SEND_TEMPLATE_NOT_EXISTS = new ErrorCode(1006000000, "短信模板不存在");
16 16
  17 + // ========= 文件相关 1006001000=================
  18 + ErrorCode FILE_PATH_EXISTS = new ErrorCode(1006001000, "文件路径已存在");
  19 + ErrorCode FILE_NOT_EXISTS = new ErrorCode(1006001002, "文件不存在");
17 } 20 }
yudao-dependencies/pom.xml
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.1.0-snapshot</revision> 17 + <revision>1.2.0-snapshot</revision>
18 <!-- 统一依赖管理 --> 18 <!-- 统一依赖管理 -->
19 <spring.boot.version>2.4.5</spring.boot.version> 19 <spring.boot.version>2.4.5</spring.boot.version>
20 <!-- Web 相关 --> 20 <!-- Web 相关 -->
yudao-user-server/pom.xml
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <artifactId>yudao-user-server</artifactId> 12 <artifactId>yudao-user-server</artifactId>
13 <packaging>jar</packaging> 13 <packaging>jar</packaging>
14 14
15 - <name>yudao-admin-server</name> 15 + <name>yudao-user-server</name>
16 <description>用户前台 Server,提供其 API 接口</description> 16 <description>用户前台 Server,提供其 API 接口</description>
17 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 17 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
18 18
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.http
1 ### 请求 /system/user/profile/get 接口 => 没有权限 1 ### 请求 /system/user/profile/get 接口 => 没有权限
2 GET {{userServerUrl}}/system/user/profile/get 2 GET {{userServerUrl}}/system/user/profile/get
3 Authorization: Bearer test245 3 Authorization: Bearer test245
  4 +
  5 +### 请求 /system/user/profile/revise-nickname 接口 成功
  6 +PUT {{userServerUrl}}/system/user/profile/update-nickname?nickName=yunai222
  7 +Authorization: Bearer test245
  8 +
  9 +### 请求 /system/user/profile/get-user-info 接口 成功
  10 +GET {{userServerUrl}}/system/user/profile/get-user-info?id=245
  11 +Authorization: Bearer test245
4 \ No newline at end of file 12 \ No newline at end of file
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.java
1 package cn.iocoder.yudao.userserver.modules.member.controller.user; 1 package cn.iocoder.yudao.userserver.modules.member.controller.user;
2 2
  3 +import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
  4 +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; 6 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  7 +import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
5 import io.swagger.annotations.Api; 8 import io.swagger.annotations.Api;
6 import io.swagger.annotations.ApiOperation; 9 import io.swagger.annotations.ApiOperation;
7 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
8 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
9 -import org.springframework.web.bind.annotation.GetMapping;  
10 -import org.springframework.web.bind.annotation.RequestMapping;  
11 -import org.springframework.web.bind.annotation.RestController; 12 +import org.springframework.web.bind.annotation.*;
  13 +import org.springframework.web.multipart.MultipartFile;
  14 +
  15 +import javax.annotation.Resource;
  16 +
  17 +import java.io.IOException;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  21 +import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.FILE_IS_EMPTY;
12 22
13 @Api(tags = "用户个人中心") 23 @Api(tags = "用户个人中心")
14 @RestController 24 @RestController
@@ -17,11 +27,34 @@ import org.springframework.web.bind.annotation.RestController; @@ -17,11 +27,34 @@ import org.springframework.web.bind.annotation.RestController;
17 @Slf4j 27 @Slf4j
18 public class SysUserProfileController { 28 public class SysUserProfileController {
19 29
20 - @GetMapping("/get")  
21 - @ApiOperation("获得登录用户信息") 30 + @Resource
  31 + private MbrUserService userService;
  32 +
  33 + @PutMapping("/update-nickname")
  34 + @ApiOperation("修改用户昵称")
22 @PreAuthenticated 35 @PreAuthenticated
23 - public CommonResult<Boolean> profile() {  
24 - return null; 36 + public CommonResult<Boolean> updateNickname(@RequestParam("nickName") String nickName) {
  37 + userService.updateNickname(getLoginUserId(), nickName);
  38 + return success(true);
  39 + }
  40 +
  41 + @PutMapping("/update-avatar")
  42 + @ApiOperation("修改用户头像")
  43 + @PreAuthenticated
  44 + public CommonResult<String> updateAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
  45 + if (file.isEmpty()) {
  46 + throw ServiceExceptionUtil.exception(FILE_IS_EMPTY);
  47 + }
  48 + String avatar = userService.updateAvatar(getLoginUserId(), file.getInputStream());
  49 + return success(avatar);
  50 + }
  51 +
  52 + @GetMapping("/get-user-info")
  53 + @ApiOperation("获取用户头像与昵称")
  54 + @PreAuthenticated
  55 + public CommonResult<MbrUserInfoRespVO> getUserInfo() {
  56 + return success(userService.getUserInfo(getLoginUserId()));
25 } 57 }
26 58
27 } 59 }
  60 +
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserInfoRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.member.controller.user.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.AllArgsConstructor;
  6 +import lombok.Data;
  7 +import lombok.NoArgsConstructor;
  8 +
  9 +@ApiModel("用户个人信息 Response VO")
  10 +@Data
  11 +@NoArgsConstructor
  12 +@AllArgsConstructor
  13 +public class MbrUserInfoRespVO {
  14 +
  15 + @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
  16 + private String nickName;
  17 +
  18 + @ApiModelProperty(value = "用户头像", required = true, example = "/infra/file/get/35a12e57-4297-4faa-bf7d-7ed2f211c952")
  19 + private String avatar;
  20 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/enums/MbrErrorCodeConstants.java
@@ -9,4 +9,9 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -9,4 +9,9 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
9 */ 9 */
10 public interface MbrErrorCodeConstants { 10 public interface MbrErrorCodeConstants {
11 11
  12 + // ==========用户相关 1004001000============
  13 + ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
  14 +
  15 + // ==========文件相关 1004002000 ===========
  16 + ErrorCode FILE_IS_EMPTY = new ErrorCode(1004002000, "文件为空");
12 } 17 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java
1 package cn.iocoder.yudao.userserver.modules.member.service.user; 1 package cn.iocoder.yudao.userserver.modules.member.service.user;
2 2
3 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; 3 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
  4 +import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
4 import cn.iocoder.yudao.framework.common.validation.Mobile; 5 import cn.iocoder.yudao.framework.common.validation.Mobile;
5 6
  7 +import java.io.InputStream;
  8 +
6 /** 9 /**
7 * 前台用户 Service 接口 10 * 前台用户 Service 接口
8 * 11 *
@@ -44,4 +47,26 @@ public interface MbrUserService { @@ -44,4 +47,26 @@ public interface MbrUserService {
44 */ 47 */
45 MbrUserDO getUser(Long id); 48 MbrUserDO getUser(Long id);
46 49
  50 + /**
  51 + * 修改用户昵称
  52 + * @param userId 用户id
  53 + * @param nickName 用户新昵称
  54 + */
  55 + void updateNickname(Long userId, String nickName);
  56 +
  57 + /**
  58 + * 修改用户头像
  59 + * @param userId 用户id
  60 + * @param inputStream 头像文件
  61 + * @return 头像url
  62 + */
  63 + String updateAvatar(Long userId, InputStream inputStream);
  64 +
  65 + /**
  66 + * 根据用户id,获取用户头像与昵称
  67 + * @param userId 用户id
  68 + * @return 用户响应实体类
  69 + */
  70 + MbrUserInfoRespVO getUserInfo(Long userId);
  71 +
47 } 72 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java
1 package cn.iocoder.yudao.userserver.modules.member.service.user.impl; 1 package cn.iocoder.yudao.userserver.modules.member.service.user.impl;
2 2
  3 +import cn.hutool.core.io.IoUtil;
3 import cn.hutool.core.util.IdUtil; 4 import cn.hutool.core.util.IdUtil;
  5 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
4 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; 6 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
  7 +import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 8 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper; 9 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
7 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService; 10 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
  11 +import com.google.common.annotations.VisibleForTesting;
8 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
9 import org.springframework.security.crypto.password.PasswordEncoder; 13 import org.springframework.security.crypto.password.PasswordEncoder;
10 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
11 15
12 import javax.annotation.Resource; 16 import javax.annotation.Resource;
13 import javax.validation.Valid; 17 import javax.validation.Valid;
  18 +import java.io.InputStream;
14 import java.util.Date; 19 import java.util.Date;
15 20
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  22 +import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.USER_NOT_EXISTS;
  23 +
16 /** 24 /**
17 * User Service 实现类 25 * User Service 实现类
18 * 26 *
@@ -27,6 +35,9 @@ public class MbrUserServiceImpl implements MbrUserService { @@ -27,6 +35,9 @@ public class MbrUserServiceImpl implements MbrUserService {
27 private MbrUserMapper userMapper; 35 private MbrUserMapper userMapper;
28 36
29 @Resource 37 @Resource
  38 + private InfFileCoreService fileCoreService;
  39 +
  40 + @Resource
30 private PasswordEncoder passwordEncoder; 41 private PasswordEncoder passwordEncoder;
31 42
32 @Override 43 @Override
@@ -68,4 +79,53 @@ public class MbrUserServiceImpl implements MbrUserService { @@ -68,4 +79,53 @@ public class MbrUserServiceImpl implements MbrUserService {
68 return userMapper.selectById(id); 79 return userMapper.selectById(id);
69 } 80 }
70 81
  82 + @Override
  83 + public void updateNickname(Long userId, String nickName) {
  84 + MbrUserDO user = this.checkUserExists(userId);
  85 + // 仅当新昵称不等于旧昵称时进行修改
  86 + if (nickName.equals(user.getNickname())){
  87 + return;
  88 + }
  89 + MbrUserDO userDO = new MbrUserDO();
  90 + userDO.setId(user.getId());
  91 + userDO.setNickname(nickName);
  92 + userMapper.updateById(userDO);
  93 + }
  94 +
  95 + @Override
  96 + public String updateAvatar(Long userId, InputStream avatarFile) {
  97 + this.checkUserExists(userId);
  98 + // 创建文件
  99 + String avatar = fileCoreService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile));
  100 + // 更新头像路径
  101 + MbrUserDO userDO = MbrUserDO.builder()
  102 + .id(userId)
  103 + .avatar(avatar)
  104 + .build();
  105 + userMapper.updateById(userDO);
  106 + return avatar;
  107 + }
  108 +
  109 + @Override
  110 + public MbrUserInfoRespVO getUserInfo(Long userId) {
  111 + MbrUserDO user = this.checkUserExists(userId);
  112 + // 拼接返回结果
  113 + MbrUserInfoRespVO userResp = new MbrUserInfoRespVO();
  114 + userResp.setNickName(user.getNickname());
  115 + userResp.setAvatar(user.getAvatar());
  116 + return userResp;
  117 + }
  118 +
  119 + @VisibleForTesting
  120 + public MbrUserDO checkUserExists(Long id) {
  121 + if (id == null) {
  122 + return null;
  123 + }
  124 + MbrUserDO user = userMapper.selectById(id);
  125 + if (user == null) {
  126 + throw exception(USER_NOT_EXISTS);
  127 + }else{
  128 + return user;
  129 + }
  130 + }
71 } 131 }
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbUnitTest.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver;
  2 +
  3 +import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
  4 +import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
  5 +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
  6 +import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
  7 +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  8 +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
  9 +import org.springframework.boot.test.context.SpringBootTest;
  10 +import org.springframework.context.annotation.Import;
  11 +import org.springframework.test.context.ActiveProfiles;
  12 +import org.springframework.test.context.jdbc.Sql;
  13 +
  14 +/**
  15 + * 依赖内存 DB 的单元测试
  16 + *
  17 + * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class)
  22 +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
  23 +@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
  24 +public class BaseDbUnitTest {
  25 +
  26 + @Import({
  27 + // DB 配置类
  28 + YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
  29 + DataSourceAutoConfiguration.class, // Spring DB 自动配置类
  30 + DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
  31 + DruidDataSourceAutoConfigure.class, // Druid 自动配置类
  32 + // MyBatis 配置类
  33 + YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
  34 + MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
  35 + })
  36 + public static class Application {
  37 + }
  38 +
  39 +}
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.member.service;
  2 +
  3 +import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
  4 +import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  7 +import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
  8 +import cn.iocoder.yudao.userserver.BaseDbUnitTest;
  9 +import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
  10 +import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
  11 +import cn.iocoder.yudao.userserver.modules.member.service.user.impl.MbrUserServiceImpl;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.springframework.boot.test.mock.mockito.MockBean;
  14 +import org.springframework.context.annotation.Import;
  15 +import org.springframework.http.MediaType;
  16 +import org.springframework.mock.web.MockMultipartFile;
  17 +import org.springframework.security.crypto.password.PasswordEncoder;
  18 +import org.springframework.util.Assert;
  19 +
  20 +import javax.annotation.Resource;
  21 +import java.io.*;
  22 +import java.util.function.Consumer;
  23 +
  24 +import static cn.hutool.core.util.RandomUtil.randomBytes;
  25 +import static org.junit.jupiter.api.Assertions.assertEquals;
  26 +import static cn.hutool.core.util.RandomUtil.randomEle;
  27 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  28 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
  29 +import static org.mockito.Mockito.*;
  30 +/**
  31 + * {@link MbrUserServiceImpl} 的单元测试类
  32 + *
  33 + * @author 宋天
  34 + */
  35 +@Import(MbrUserServiceImpl.class)
  36 +public class MbrUserServiceImplTest extends BaseDbUnitTest {
  37 +
  38 + @Resource
  39 + private MbrUserServiceImpl mbrUserService;
  40 +
  41 + @Resource
  42 + private MbrUserMapper userMapper;
  43 +
  44 + @MockBean
  45 + private InfFileCoreService fileCoreService;
  46 +
  47 + @MockBean
  48 + private PasswordEncoder passwordEncoder;
  49 +
  50 + @Test
  51 + public void testUpdateNickName_success(){
  52 + // mock 数据
  53 + MbrUserDO userDO = randomMbrUserDO();
  54 + userMapper.insert(userDO);
  55 +
  56 + // 随机昵称
  57 + String newNickName = randomString();
  58 +
  59 + // 调用接口修改昵称
  60 + mbrUserService.updateNickname(userDO.getId(),newNickName);
  61 + // 查询新修改后的昵称
  62 + String nickname = mbrUserService.getUser(userDO.getId()).getNickname();
  63 + // 断言
  64 + assertEquals(newNickName,nickname);
  65 + }
  66 +
  67 + @Test
  68 + public void testGetUserInfo_success(){
  69 + // mock 数据
  70 + MbrUserDO userDO = randomMbrUserDO();
  71 + userMapper.insert(userDO);
  72 +
  73 + // 查询用户昵称与头像
  74 + MbrUserInfoRespVO userInfo = mbrUserService.getUserInfo(userDO.getId());
  75 + System.out.println(userInfo);
  76 + }
  77 +
  78 + @Test
  79 + public void testUpdateAvatar_success(){
  80 + // mock 数据
  81 + MbrUserDO dbUser = randomMbrUserDO();
  82 + userMapper.insert(dbUser);
  83 +
  84 + // 准备参数
  85 + Long userId = dbUser.getId();
  86 + byte[] avatarFileBytes = randomBytes(10);
  87 + ByteArrayInputStream avatarFile = new ByteArrayInputStream(avatarFileBytes);
  88 + // mock 方法
  89 + String avatar = randomString();
  90 + when(fileCoreService.createFile(anyString(), eq(avatarFileBytes))).thenReturn(avatar);
  91 + // 调用
  92 + String str = mbrUserService.updateAvatar(userId, avatarFile);
  93 + // 断言
  94 + assertEquals(avatar, str);
  95 + }
  96 +
  97 + // ========== 随机对象 ==========
  98 +
  99 + @SafeVarargs
  100 + private static MbrUserDO randomMbrUserDO(Consumer<MbrUserDO>... consumers) {
  101 + Consumer<MbrUserDO> consumer = (o) -> {
  102 + o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
  103 + };
  104 + return randomPojo(MbrUserDO.class, ArrayUtils.append(consumer, consumers));
  105 + }
  106 +
  107 +}
yudao-user-server/src/test/resources/application-unit-test.yaml 0 → 100644
  1 +spring:
  2 + main:
  3 + lazy-initialization: true # 开启懒加载,加快速度
  4 + banner-mode: off # 单元测试,禁用 Banner
  5 +
  6 +--- #################### 数据库相关配置 ####################
  7 +
  8 +spring:
  9 + # 数据源配置项
  10 + datasource:
  11 + name: ruoyi-vue-pro
  12 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  13 + driver-class-name: org.h2.Driver
  14 + username: sa
  15 + password:
  16 + schema: classpath:sql/create_tables.sql # MySQL 转 H2 的语句,使用 https://www.jooq.org/translate/ 工具
  17 + druid:
  18 + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
  19 + initial-size: 1 # 单元测试,配置为 1,提升启动速度
  20 +
  21 + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  22 + redis:
  23 + host: 127.0.0.1 # 地址
  24 + port: 16379 # 端口(单元测试,使用 16379 端口)
  25 + database: 0 # 数据库索引
  26 +
  27 +mybatis:
  28 + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
  29 +
  30 +--- #################### 定时任务相关配置 ####################
  31 +
  32 +--- #################### 配置中心相关配置 ####################
  33 +
  34 +--- #################### 服务保障相关配置 ####################
  35 +
  36 +# Lock4j 配置项(单元测试,禁用 Lock4j)
  37 +
  38 +# Resilience4j 配置项
  39 +
  40 +--- #################### 监控相关配置 ####################
  41 +
  42 +--- #################### 芋道相关配置 ####################
  43 +
  44 +# 芋道配置项,设置当前项目所有自定义的配置
yudao-user-server/src/test/resources/file/erweima.jpg 0 → 100644

18 KB

yudao-user-server/src/test/resources/logback-spring.xml 0 → 100644
  1 +<configuration>
  2 + <!-- 引用 Spring Boot 的 logback 基础配置 -->
  3 + <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  4 +</configuration>
yudao-user-server/src/test/resources/sql/clean.sql 0 → 100644
  1 +-- mbr 开头的 DB
  2 +DELETE FROM "mbr_user";
0 \ No newline at end of file 3 \ No newline at end of file
yudao-user-server/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +-- mbr 开头的 DB
  2 +CREATE TABLE IF NOT EXISTS "mbr_user" (
  3 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '编号',
  4 + "nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称',
  5 + "avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头像',
  6 + "status" tinyint NOT NULL COMMENT '状态',
  7 + "mobile" varchar(11) NOT NULL COMMENT '手机号',
  8 + "password" varchar(100) NOT NULL DEFAULT '' COMMENT '密码',
  9 + "register_ip" varchar(32) NOT NULL COMMENT '注册 IP',
  10 + "login_ip" varchar(50) NULL DEFAULT '' COMMENT '最后登录IP',
  11 + "login_date" datetime NULL DEFAULT NULL COMMENT '最后登录时间',
  12 + "creator" varchar(64) NULL DEFAULT '' COMMENT '创建者',
  13 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  14 + "updater" varchar(64) NULL DEFAULT '' COMMENT '更新者',
  15 + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  16 + "deleted" bit(1) NOT NULL DEFAULT '0' COMMENT '是否删除',
  17 + PRIMARY KEY ("id")
  18 +) COMMENT '会员表';
  19 +
  20 +-- inf 开头的 DB
  21 +CREATE TABLE IF NOT EXISTS "inf_file" (
  22 + "id" varchar(188) NOT NULL,
  23 + "type" varchar(63) DEFAULT NULL,
  24 + "content" blob NOT NULL,
  25 + "creator" varchar(64) DEFAULT '',
  26 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  27 + "updater" varchar(64) DEFAULT '',
  28 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  29 + "deleted" bit NOT NULL DEFAULT FALSE,
  30 + PRIMARY KEY ("id")
  31 +) COMMENT '文件表';
  32 +
更新日志.md
@@ -3,24 +3,25 @@ @@ -3,24 +3,25 @@
3 * 邮件 3 * 邮件
4 * 钉钉、飞书等通知 4 * 钉钉、飞书等通知
5 5
6 -## [v1.2.0] 待定 6 +## [v1.3.0] 待定
7 7
8 * 工作流 8 * 工作流
9 9
10 -## [v1.1.2] 待定 10 +## [v1.2.0] 进行中
11 11
12 -* 用户前台的社交登陆 12 +* 新增用户前台的昵称、头像的修改
13 13
14 -## [v1.1.1] 待定 14 +TODO
15 15
16 * 支付 16 * 支付
  17 +* 用户前台的社交登陆
17 18
18 -## [v1.1.0] 进行中 19 +## [v1.1.0] 2021.10.25
19 20
20 * 新增管理后台的企业微信、钉钉等社交登录 21 * 新增管理后台的企业微信、钉钉等社交登录
21 * 新增用户前台(例如说,用户使用的小程序)的后端项目 `yudao-user-server` 22 * 新增用户前台(例如说,用户使用的小程序)的后端项目 `yudao-user-server`
22 * 新增公共服务 `yudao-core-service` 项目,通过 Jar 包的方式,提供 `yudao-user-server` 和 `yudao-admin-server` 的共享逻辑的复用 23 * 新增公共服务 `yudao-core-service` 项目,通过 Jar 包的方式,提供 `yudao-user-server` 和 `yudao-admin-server` 的共享逻辑的复用
23 -* 新增用户前台的手机登录、验证码登录 24 +* 新增用户前台的手机登录、验证码登录
24 * 修复管理后台的用户头像上传 404 的问题,原因是请求路径不对 25 * 修复管理后台的用户头像上传 404 的问题,原因是请求路径不对
25 * 修复用户导入失败的问题,原因是 Lombok 链式与 cglib 读取属性有冲突 26 * 修复用户导入失败的问题,原因是 Lombok 链式与 cglib 读取属性有冲突
26 * 修复阿里云短信发送失败的问题,原因是 Opentracing 依赖的版本太低,调整成 0.31.0 27 * 修复阿里云短信发送失败的问题,原因是 Opentracing 依赖的版本太低,调整成 0.31.0
@@ -37,7 +38,7 @@ @@ -37,7 +38,7 @@
37 ### 代码的重构 38 ### 代码的重构
38 39
39 * 调整整体代码结构,将多个 Maven Module 合并为单个,使用 Java package 进行拆分隔离,如 [图](https://static.iocoder.cn/ruoyi-vue-pro-modules.jpg) 所示。原因是:随着业务逻辑的逐步复杂,多个 Maven Module 的依赖关系的管理,会是一个很大的问题。 40 * 调整整体代码结构,将多个 Maven Module 合并为单个,使用 Java package 进行拆分隔离,如 [图](https://static.iocoder.cn/ruoyi-vue-pro-modules.jpg) 所示。原因是:随着业务逻辑的逐步复杂,多个 Maven Module 的依赖关系的管理,会是一个很大的问题。
40 -* 拆分 [framework](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework) 为多个 Maven Module,按照 [Web](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-web)、[Security](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-security)、[MyBatis](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-mybatis)、[Redis](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-redis) 等不同组件,进行封装与拓展。 41 +* 拆分 [framework](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework) 为多个 Maven Module,按照 [Web](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-web)、[Security](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-security)、[MyBatis](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-mybatis)、[Redis](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-redis) 等不同组件,进行封装与拓展。
41 * 基于 [JUnit5](https://junit.org/junit5/) 与 [Mockito](https://github.com/mockito/mockito),实现单元测试,保证功能的正确性,与代码的可维护性。一直自动化,一直爽! 42 * 基于 [JUnit5](https://junit.org/junit5/) 与 [Mockito](https://github.com/mockito/mockito),实现单元测试,保证功能的正确性,与代码的可维护性。一直自动化,一直爽!
42 * 增加 SpringBoot 多环境的配置文件,提供完善的 [deploy.sh](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/bin/deploy.sh) 部署脚本,以及 [Jenkins 部署教程](https://juejin.cn/post/6942098287533129765)。 43 * 增加 SpringBoot 多环境的配置文件,提供完善的 [deploy.sh](https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/bin/deploy.sh) 部署脚本,以及 [Jenkins 部署教程](https://juejin.cn/post/6942098287533129765)。
43 * 优化 [Spring Security](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-security) 实现权限的代码,提升可读性和维护性。 44 * 优化 [Spring Security](https://gitee.com/zhijiantianya/ruoyi-vue-pro/tree/master/yudao-framework/yudao-spring-boot-starter-security) 实现权限的代码,提升可读性和维护性。