From 98917630154af5664b5d1cc506144fa82d75358c Mon Sep 17 00:00:00 2001 From: timfruit Date: Fri, 12 Mar 2021 00:01:37 +0800 Subject: [PATCH 01/14] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/doc/InfDbDocController.java | 81 ++++++++++++++----- 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java index 0735c4d54..47f748433 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java @@ -1,6 +1,7 @@ package cn.iocoder.dashboard.modules.infra.controller.doc; -import cn.hutool.extra.servlet.ServletUtil; +import cn.hutool.core.lang.UUID; +import cn.iocoder.dashboard.util.servlet.ServletUtils; import cn.smallbun.screw.core.Configuration; import cn.smallbun.screw.core.engine.EngineConfig; import cn.smallbun.screw.core.engine.EngineFileType; @@ -11,17 +12,15 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import io.swagger.annotations.Api; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; -import org.springframework.http.MediaType; +import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; -import javax.sql.DataSource; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; +import java.io.*; import java.util.Collections; @Api(tags = "数据库文档") @@ -34,36 +33,82 @@ public class InfDbDocController { private static final String FILE_OUTPUT_DIR = System.getProperty("java.io.tmpdir") + File.separator + "db-doc"; - private static final EngineFileType FILE_OUTPUT_TYPE = EngineFileType.HTML; // 可以设置 Word 或者 Markdown 格式 private static final String DOC_FILE_NAME = "数据库文档"; private static final String DOC_VERSION = "1.0.0"; private static final String DOC_DESCRIPTION = "文档描述"; - @Resource - private DataSource dataSource; @GetMapping("/export-html") - public synchronized void exportHtml(HttpServletResponse response) throws FileNotFoundException { + public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile, + HttpServletResponse response) throws IOException { + EngineFileType fileOutputType=EngineFileType.HTML; + doExportFile(fileOutputType,deleteFile,response); + } + + + + @GetMapping("/export-word") + public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile, + HttpServletResponse response) throws IOException { + EngineFileType fileOutputType=EngineFileType.WORD; + doExportFile(fileOutputType,deleteFile,response); + } + + + @GetMapping("/export-markdown") + public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile, + HttpServletResponse response) throws IOException { + EngineFileType fileOutputType=EngineFileType.MD; + doExportFile(fileOutputType,deleteFile,response); + } + + private void doExportFile(EngineFileType fileOutputType, Boolean deleteFile, + HttpServletResponse response) throws IOException { + String docFileName=DOC_FILE_NAME+"_"+ UUID.fastUUID().toString(true); + String filePath= doExportFile(fileOutputType,docFileName); + String downloadFileName=DOC_FILE_NAME+fileOutputType.getFileSuffix(); //下载后的文件名 + // 读取,返回 + try (InputStream is=new FileInputStream(filePath)){//处理后关闭文件流才能删除 + ServletUtils.writeAttachment(response,downloadFileName, StreamUtils.copyToByteArray(is)); + } + handleDeleteFile(deleteFile,filePath); + } + + + /** + * 输出文件,返回文件路径 + * @param fileOutputType + * @param fileName + * @return + */ + private String doExportFile(EngineFileType fileOutputType, String fileName){ try (HikariDataSource dataSource = buildDataSource()) { // 创建 screw 的配置 Configuration config = Configuration.builder() .version(DOC_VERSION) // 版本 .description(DOC_DESCRIPTION) // 描述 .dataSource(dataSource) // 数据源 - .engineConfig(buildEngineConfig()) // 引擎配置 + .engineConfig(buildEngineConfig(fileOutputType,fileName)) // 引擎配置 .produceConfig(buildProcessConfig()) // 处理配置 .build(); // 执行 screw,生成数据库文档 new DocumentationExecute(config).execute(); - // 读取,返回 - ServletUtil.write(response, - new FileInputStream(FILE_OUTPUT_DIR + File.separator + DOC_FILE_NAME + FILE_OUTPUT_TYPE.getFileSuffix()), - MediaType.TEXT_HTML_VALUE); + + String filePath=FILE_OUTPUT_DIR + File.separator + fileName + fileOutputType.getFileSuffix(); + return filePath; } } + private void handleDeleteFile(Boolean deleteFile,String filePath){ + if(!deleteFile){ + return; + } + File file=new File(filePath); + file.delete(); + } + /** * 创建数据源 */ @@ -83,13 +128,13 @@ public class InfDbDocController { /** * 创建 screw 的引擎配置 */ - private static EngineConfig buildEngineConfig() { + private static EngineConfig buildEngineConfig(EngineFileType fileOutputType,String docFileName) { return EngineConfig.builder() .fileOutputDir(FILE_OUTPUT_DIR) // 生成文件路径 .openOutputDir(false) // 打开目录 - .fileType(FILE_OUTPUT_TYPE) // 文件类型 + .fileType(fileOutputType) // 文件类型 .produceType(EngineTemplateType.freemarker) // 文件类型 - .fileName(DOC_FILE_NAME) // 自定义文件名称 + .fileName(docFileName) // 自定义文件名称 .build(); } From 0181baa72ba2d983a873c392514944989575659b Mon Sep 17 00:00:00 2001 From: niudehua <657563945@qq.com> Date: Fri, 12 Mar 2021 00:31:23 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=AE=BE=E7=BD=AE=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/SysUserProfileController.java | 179 +++++++++--------- .../user/vo/user/SysUserProfileRespVO.java | 42 ++++ .../vo/user/SysUserProfileUpdateReqVO.java | 25 +++ .../system/convert/auth/SysAuthConvert.java | 24 ++- .../system/convert/user/SysUserConvert.java | 17 +- .../system/enums/SysErrorCodeConstants.java | 2 + .../system/service/user/SysUserService.java | 32 +++- .../service/user/SysUserServiceImpl.java | 84 +++++++- src/main/resources/application-dev.yaml | 2 +- src/main/resources/application-local.yaml | 2 +- 10 files changed, 300 insertions(+), 109 deletions(-) create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index bd84ba60c..40a99910f 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -1,92 +1,99 @@ package cn.iocoder.dashboard.modules.system.controller.user; +import cn.iocoder.dashboard.common.pojo.CommonResult; +import cn.iocoder.dashboard.framework.security.core.LoginUser; +import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO; +import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; +import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; +import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; +import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; +import cn.iocoder.dashboard.modules.system.service.user.SysUserService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author niudehua + */ +@Api(tags = "用户个人中心") +@RestController +@RequestMapping("/system/user/profile") public class SysUserProfileController { -// /** -// * 个人信息 -// */ -// @GetMapping -// public AjaxResult profile() -// { -// LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); -// SysUser user = loginUser.getUser(); -// AjaxResult ajax = AjaxResult.success(user); -// ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername())); -// ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername())); -// return ajax; -// } -// -// /** -// * 修改用户 -// */ -// @Log(title = "个人信息", businessType = BusinessType.UPDATE) -// @PutMapping -// public AjaxResult updateProfile(@RequestBody SysUser user) -// { -// if (userService.updateUserProfile(user) > 0) -// { -// LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); -// // 更新缓存用户信息 -// loginUser.getUser().setNickName(user.getNickName()); -// loginUser.getUser().setPhonenumber(user.getPhonenumber()); -// loginUser.getUser().setEmail(user.getEmail()); -// loginUser.getUser().setSex(user.getSex()); -// tokenService.setLoginUser(loginUser); -// return AjaxResult.success(); -// } -// return AjaxResult.error("修改个人信息异常,请联系管理员"); -// } -// -// /** -// * 重置密码 -// */ -// @Log(title = "个人信息", businessType = BusinessType.UPDATE) -// @PutMapping("/updatePwd") -// public AjaxResult updatePwd(String oldPassword, String newPassword) -// { -// LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); -// String userName = loginUser.getUsername(); -// String password = loginUser.getPassword(); -// if (!SecurityUtils.matchesPassword(oldPassword, password)) -// { -// return AjaxResult.error("修改密码失败,旧密码错误"); -// } -// if (SecurityUtils.matchesPassword(newPassword, password)) -// { -// return AjaxResult.error("新密码不能与旧密码相同"); -// } -// if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) -// { -// // 更新缓存用户密码 -// loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword)); -// tokenService.setLoginUser(loginUser); -// return AjaxResult.success(); -// } -// return AjaxResult.error("修改密码异常,请联系管理员"); -// } -// -// /** -// * 头像上传 -// */ -// @Log(title = "用户头像", businessType = BusinessType.UPDATE) -// @PostMapping("/avatar") -// public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException -// { -// if (!file.isEmpty()) -// { -// LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest()); -// String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file); -// if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) -// { -// AjaxResult ajax = AjaxResult.success(); -// ajax.put("imgUrl", avatar); -// // 更新缓存用户头像 -// loginUser.getUser().setAvatar(avatar); -// tokenService.setLoginUser(loginUser); -// return ajax; -// } -// } -// return AjaxResult.error("上传图片异常,请联系管理员"); -// } + @Resource + private SysUserService userService; + @Resource + private SysPermissionService permissionService; + @Resource + private SysRoleService roleService; + /** + * 个人信息 + * + * @return 个人信息详情 + */ + @ApiOperation("获得登录用户信息") + @GetMapping("/get") + public CommonResult profile() { + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + // 获取用户信息 + assert loginUser != null; + Long userId = loginUser.getId(); + SysUserDO user = userService.getUser(userId); + SysUserProfileRespVO userProfileRespVO = SysUserConvert.INSTANCE.convert03(user); + List userRoles = roleService.listRolesFromCache(permissionService.listUserRoleIs(userId)); + userProfileRespVO.setRoles(userRoles.stream().map(SysUserConvert.INSTANCE::convert).collect(Collectors.toSet())); + return CommonResult.success(userProfileRespVO); + } + + /** + * 修改个人信息 + * + * @param reqVO 个人信息更新 reqVO + * @param request HttpServletRequest + * @return 修改结果 + */ + @ApiOperation("修改用户个人信息") + @PostMapping("/update") + public CommonResult updateProfile(@RequestBody SysUserProfileUpdateReqVO reqVO, HttpServletRequest request) { + if (userService.updateUserProfile(reqVO) > 0) { + SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request); + return CommonResult.success(true); + } + return CommonResult.success(false); + } + + /** + * 上传用户个人头像 + * + * @param file 头像文件 + * @return 上传结果 + */ + @ApiOperation("上传用户个人头像") + @PostMapping("/uploadAvatar") + public CommonResult uploadAvatar(@RequestParam("avatarFile") MultipartFile file) { + if (!file.isEmpty()) { + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + assert loginUser != null; + if (userService.updateAvatar(loginUser.getId(), file) > 0) { + return CommonResult.success(true); + } + } + return CommonResult.success(false); + } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java new file mode 100644 index 000000000..a081dea65 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.dashboard.modules.system.controller.user.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.util.Set; + + +@ApiModel("用户个人中心信息 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SysUserProfileRespVO extends SysUserRespVO { + + @ApiModelProperty(value = "旧密码", required = true, example = "123456") + private String oldPassword; + + @ApiModelProperty(value = "新密码", required = true, example = "123456") + private String newPassword; + /** + * 所属角色 + */ + @ApiModelProperty(value = "所属角色", required = true, example = "123456") + private Set roles; + + @ApiModel("角色") + @Data + public static class Role { + + @ApiModelProperty(value = "角色编号", required = true, example = "1") + private Long id; + + @ApiModelProperty(value = "角色名称", required = true, example = "普通角色") + private String name; + + } +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java new file mode 100644 index 000000000..d3185b242 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.dashboard.modules.system.controller.user.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotNull; + +@ApiModel("用户更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class SysUserProfileUpdateReqVO extends SysUserBaseVO { + + @ApiModelProperty(value = "用户编号", required = true, example = "1024") + @NotNull(message = "用户编号不能为空") + private Long id; + + @ApiModelProperty(value = "旧密码", required = true, example = "123456") + private String oldPassword; + + @ApiModelProperty(value = "新密码", required = true, example = "654321") + private String newPassword; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java index 1c34fe407..e474ce7b1 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/auth/SysAuthConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.convert.auth; import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; import cn.iocoder.dashboard.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysMenuDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; @@ -13,26 +14,33 @@ import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; @Mapper public interface SysAuthConvert { SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class); - @Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同,但是含义不同,忽略 + @Mapping(source = "updateTime", target = "updateTime", ignore = true) + // 字段相同,但是含义不同,忽略 LoginUser convert(SysUserDO bean); default SysAuthPermissionInfoRespVO convert(SysUserDO user, List roleList, List menuList) { return SysAuthPermissionInfoRespVO.builder() - .user(SysAuthPermissionInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build()) - .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode)) - .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission)) - .build(); + .user(SysAuthPermissionInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode)) + .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission)) + .build(); } SysAuthMenuRespVO convertTreeNode(SysMenuDO menu); + LoginUser convert(SysUserProfileUpdateReqVO reqVO); + /** * 将菜单列表,构建成菜单树 * @@ -47,12 +55,12 @@ public interface SysAuthConvert { Map treeNodeMap = new LinkedHashMap<>(); menuList.forEach(menu -> treeNodeMap.put(menu.getId(), SysAuthConvert.INSTANCE.convertTreeNode(menu))); // 处理父子关系 - treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach((childNode) -> { + treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(MenuIdEnum.ROOT.getId())).forEach(childNode -> { // 获得父节点 SysAuthMenuRespVO parentNode = treeNodeMap.get(childNode.getParentId()); if (parentNode == null) { LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", - childNode.getId(), childNode.getParentId()); + childNode.getId(), childNode.getParentId()); return; } // 将自己添加到父节点中 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java index b8ff73671..af72c9c2b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java @@ -1,7 +1,14 @@ package cn.iocoder.dashboard.modules.system.convert.user; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExcelVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageItemRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; +import cn.iocoder.dashboard.modules.system.dal.dataobject.permission.SysRoleDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -23,4 +30,12 @@ public interface SysUserConvert { SysUserDO convert(SysUserImportExcelVO bean); + SysUserProfileRespVO convert03(SysUserDO bean); + + SysUserProfileRespVO.Role convert(SysRoleDO bean); + + SysUserDO convert(SysUserProfileUpdateReqVO bean); + + + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java index 21d3e8910..3f4214325 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java @@ -40,6 +40,7 @@ public interface SysErrorCodeConstants { ErrorCode USER_EMAIL_EXISTS = new ErrorCode(1002004002, "邮箱已经存在"); ErrorCode USER_NOT_EXISTS = new ErrorCode(1002004003, "用户不存在"); ErrorCode USER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1002004004, "导入用户数据不能为空!"); + ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1002004005, "用户密码校验失败"); // ========== 部门模块 1002005000 ========== ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1002004001, "已经存在该名字的部门"); @@ -74,5 +75,6 @@ public interface SysErrorCodeConstants { // ========== 文件 1002009000 ========== ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在"); + ErrorCode FILE_UPLOAD_FAILED = new ErrorCode(1002009002, "文件上传失败"); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java index 3de54f34b..e8097590f 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java @@ -2,9 +2,16 @@ package cn.iocoder.dashboard.modules.system.service.user; import cn.hutool.core.collection.CollUtil; import cn.iocoder.dashboard.common.pojo.PageResult; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.util.collection.CollectionUtils; +import org.springframework.web.multipart.MultipartFile; import java.util.Collection; import java.util.HashMap; @@ -102,6 +109,14 @@ public interface SysUserService { */ void updateUser(SysUserUpdateReqVO reqVO); + /** + * 修改用户个人信息 + * + * @param reqVO 用户个人信息 + * @return 修改结果 + */ + int updateUserProfile(SysUserProfileUpdateReqVO reqVO); + /** * 删除用户 * @@ -112,7 +127,7 @@ public interface SysUserService { /** * 修改密码 * - * @param id 用户编号 + * @param id 用户编号 * @param password 密码 */ void updateUserPassword(Long id, String password); @@ -120,7 +135,7 @@ public interface SysUserService { /** * 修改密码 * - * @param id 用户编号 + * @param id 用户编号 * @param status 状态 */ void updateUserStatus(Long id, Integer status); @@ -128,12 +143,21 @@ public interface SysUserService { /** * 批量导入用户 * - * @param importUsers 导入用户列表 + * @param importUsers 导入用户列表 * @param isUpdateSupport 是否支持更新 * @return 导入结果 */ SysUserImportRespVO importUsers(List importUsers, boolean isUpdateSupport); + /** + * 更新用户头像 + * + * @param id 用户 id + * @param avatarFile 头像文件 + * @return 更新结果 + */ + int updateAvatar(Long id, MultipartFile avatarFile); + // // /** // * 修改用户基本信息 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index d97d2c00f..c1fc828a0 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -1,17 +1,25 @@ package cn.iocoder.dashboard.modules.system.service.user; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.common.exception.ServiceException; import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; import cn.iocoder.dashboard.common.pojo.PageResult; -import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportRespVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO; +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; -import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper; +import cn.iocoder.dashboard.modules.system.service.common.SysFileService; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; @@ -20,9 +28,17 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.util.*; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; @@ -49,6 +65,9 @@ public class SysUserServiceImpl implements SysUserService { @Resource private PasswordEncoder passwordEncoder; + @Resource + private SysFileService fileService; + // /** // * 根据条件分页查询用户列表 // * @@ -108,7 +127,7 @@ public class SysUserServiceImpl implements SysUserService { return Collections.emptySet(); } Set deptIds = CollectionUtils.convertSet(deptService.listDeptsByParentIdFromCache( - deptId, true), SysDeptDO::getId); + deptId, true), SysDeptDO::getId); deptIds.add(deptId); // 包括自身 return deptIds; } @@ -117,7 +136,7 @@ public class SysUserServiceImpl implements SysUserService { public Long createUser(SysUserCreateReqVO reqVO) { // 校验正确性 this.checkCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), - reqVO.getDeptId(), reqVO.getPostIds()); + reqVO.getDeptId(), reqVO.getPostIds()); // 插入用户 SysUserDO user = SysUserConvert.INSTANCE.convert(reqVO); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 @@ -130,12 +149,29 @@ public class SysUserServiceImpl implements SysUserService { public void updateUser(SysUserUpdateReqVO reqVO) { // 校验正确性 this.checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), - reqVO.getDeptId(), reqVO.getPostIds()); + reqVO.getDeptId(), reqVO.getPostIds()); // 更新用户 SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); userMapper.updateById(updateObj); } + @Override + public int updateUserProfile(SysUserProfileUpdateReqVO reqVO) { + // 校验正确性 + this.checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), + reqVO.getDeptId(), reqVO.getPostIds()); + + SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); + // 校验旧密码 + if (checkOldPassword(reqVO.getId(), reqVO.getOldPassword(), reqVO.getNewPassword())) { + return userMapper.updateById(updateObj); + } + + String encode = passwordEncoder.encode(reqVO.getNewPassword()); + updateObj.setPassword(encode); + return userMapper.updateById(updateObj); + } + @Override public void deleteUser(Long id) { // 校验用户存在 @@ -278,6 +314,21 @@ public class SysUserServiceImpl implements SysUserService { }); } + private boolean checkOldPassword(Long id, String oldPassword, String newPassword) { + if (id == null || StrUtil.isBlank(oldPassword) || StrUtil.isBlank(newPassword)) { + return true; + } + SysUserDO user = userMapper.selectById(id); + if (user == null) { + throw ServiceExceptionUtil.exception(USER_NOT_EXISTS); + } + + if (!passwordEncoder.matches(oldPassword, user.getPassword())) { + throw ServiceExceptionUtil.exception(USER_PASSWORD_FAILED); + } + return false; + } + @Override @Transactional // 添加事务,异常则回滚所有导入 public SysUserImportRespVO importUsers(List importUsers, boolean isUpdateSupport) { @@ -285,12 +336,12 @@ public class SysUserServiceImpl implements SysUserService { throw ServiceExceptionUtil.exception(USER_IMPORT_LIST_IS_EMPTY); } SysUserImportRespVO respVO = SysUserImportRespVO.builder().createUsernames(new ArrayList<>()) - .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build(); + .updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build(); importUsers.forEach(importUser -> { // 校验,判断是否有不符合的原因 try { checkCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(), - importUser.getDeptId(), null); + importUser.getDeptId(), null); } catch (ServiceException ex) { respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage()); return; @@ -316,4 +367,21 @@ public class SysUserServiceImpl implements SysUserService { return respVO; } + @Override + public int updateAvatar(Long id, MultipartFile avatarFile) { + this.checkUserExists(id); + // 存储文件 + String avatar = null; + try { + avatar = fileService.createFile(avatarFile.getOriginalFilename(), IoUtil.readBytes(avatarFile.getInputStream())); + } catch (IOException e) { + throw ServiceExceptionUtil.exception(FILE_UPLOAD_FAILED); + } + // 更新路径 + SysUserDO sysUserDO = new SysUserDO(); + sysUserDO.setId(id); + sysUserDO.setAvatar(avatar); + return userMapper.updateById(sysUserDO); + } + } diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index dbf2ad53b..c9c40e739 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -152,7 +152,7 @@ yudao: width: 160 height: 60 file: - base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/ + base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/system/file/get/ codegen: base-package: ${yudao.info.base-package} db-schemas: ${spring.datasource.name} diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index 537156cf7..500eb7b51 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -152,7 +152,7 @@ yudao: width: 160 height: 60 file: - base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/ + base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/system/file/get/ codegen: base-package: ${yudao.info.base-package} db-schemas: ${spring.datasource.name} From 7089ef7651edb115bedbc504c584a7aedcac98a5 Mon Sep 17 00:00:00 2001 From: timfruit Date: Sat, 13 Mar 2021 13:21:33 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E8=89=BF=E8=89=BF?= =?UTF-8?q?=E7=9A=84=E8=AF=B4=E6=98=8E=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/doc/InfDbDocController.java | 78 +++++++++++-------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java index 47f748433..c39392c33 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java @@ -1,6 +1,10 @@ package cn.iocoder.dashboard.modules.infra.controller.doc; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.UUID; +import cn.hutool.core.util.IdUtil; +import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.dashboard.util.servlet.ServletUtils; import cn.smallbun.screw.core.Configuration; import cn.smallbun.screw.core.engine.EngineConfig; @@ -11,7 +15,11 @@ import cn.smallbun.screw.core.process.ProcessConfig; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.http.MediaType; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -39,74 +47,78 @@ public class InfDbDocController { @GetMapping("/export-html") + @ApiOperation("导出html格式的数据文档") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class), + }) public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile, - HttpServletResponse response) throws IOException { - EngineFileType fileOutputType=EngineFileType.HTML; - doExportFile(fileOutputType,deleteFile,response); + HttpServletResponse response) throws IOException { + doExportFile(EngineFileType.HTML, deleteFile, response); } - - @GetMapping("/export-word") + @ApiOperation("导出word格式的数据文档") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class), + }) public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile, - HttpServletResponse response) throws IOException { - EngineFileType fileOutputType=EngineFileType.WORD; - doExportFile(fileOutputType,deleteFile,response); + HttpServletResponse response) throws IOException { + doExportFile(EngineFileType.WORD, deleteFile, response); } - @GetMapping("/export-markdown") + @ApiOperation("导出markdown格式的数据文档") + @ApiImplicitParams({ + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class), + }) public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile, - HttpServletResponse response) throws IOException { - EngineFileType fileOutputType=EngineFileType.MD; - doExportFile(fileOutputType,deleteFile,response); + HttpServletResponse response) throws IOException { + doExportFile(EngineFileType.MD, deleteFile, response); } private void doExportFile(EngineFileType fileOutputType, Boolean deleteFile, HttpServletResponse response) throws IOException { - String docFileName=DOC_FILE_NAME+"_"+ UUID.fastUUID().toString(true); - String filePath= doExportFile(fileOutputType,docFileName); - String downloadFileName=DOC_FILE_NAME+fileOutputType.getFileSuffix(); //下载后的文件名 + String docFileName = DOC_FILE_NAME + "_" + IdUtil.fastSimpleUUID(); + String filePath = doExportFile(fileOutputType, docFileName); + String downloadFileName = DOC_FILE_NAME + fileOutputType.getFileSuffix(); //下载后的文件名 // 读取,返回 - try (InputStream is=new FileInputStream(filePath)){//处理后关闭文件流才能删除 - ServletUtils.writeAttachment(response,downloadFileName, StreamUtils.copyToByteArray(is)); - } - handleDeleteFile(deleteFile,filePath); + //IoUtil.readBytes 直接读取FileInputStream 不会关闭流,有bug,所以用BufferedInputStream包装一下, 关闭流后才能删除文件 + byte[] content = IoUtil.readBytes(new BufferedInputStream(new FileInputStream(filePath))); + //这里不用hutool工具类,它的中文文件名编码有问题,导致在浏览器下载时有问题 + ServletUtils.writeAttachment(response, downloadFileName, content); + handleDeleteFile(deleteFile, filePath); } - /** * 输出文件,返回文件路径 - * @param fileOutputType - * @param fileName - * @return + * + * @param fileOutputType 文件类型 + * @param fileName 文件名, 无需 ".docx" 等文件后缀 + * @return 生成的文件所在路径 */ - private String doExportFile(EngineFileType fileOutputType, String fileName){ + private String doExportFile(EngineFileType fileOutputType, String fileName) { try (HikariDataSource dataSource = buildDataSource()) { // 创建 screw 的配置 Configuration config = Configuration.builder() .version(DOC_VERSION) // 版本 .description(DOC_DESCRIPTION) // 描述 .dataSource(dataSource) // 数据源 - .engineConfig(buildEngineConfig(fileOutputType,fileName)) // 引擎配置 + .engineConfig(buildEngineConfig(fileOutputType, fileName)) // 引擎配置 .produceConfig(buildProcessConfig()) // 处理配置 .build(); // 执行 screw,生成数据库文档 new DocumentationExecute(config).execute(); - - String filePath=FILE_OUTPUT_DIR + File.separator + fileName + fileOutputType.getFileSuffix(); - return filePath; + return FILE_OUTPUT_DIR + File.separator + fileName + fileOutputType.getFileSuffix(); } } - private void handleDeleteFile(Boolean deleteFile,String filePath){ - if(!deleteFile){ + private void handleDeleteFile(Boolean deleteFile, String filePath) { + if (!deleteFile) { return; } - File file=new File(filePath); - file.delete(); + FileUtil.del(filePath); } /** @@ -128,7 +140,7 @@ public class InfDbDocController { /** * 创建 screw 的引擎配置 */ - private static EngineConfig buildEngineConfig(EngineFileType fileOutputType,String docFileName) { + private static EngineConfig buildEngineConfig(EngineFileType fileOutputType, String docFileName) { return EngineConfig.builder() .fileOutputDir(FILE_OUTPUT_DIR) // 生成文件路径 .openOutputDir(false) // 打开目录 From 9c71274994bc74b2f908480414e2ecd040a39431 Mon Sep 17 00:00:00 2001 From: NiuXing Date: Sat, 13 Mar 2021 19:13:01 +0800 Subject: [PATCH 04/14] =?UTF-8?q?I3B7FG=E4=BB=BB=E5=8A=A1=E6=8F=90?= =?UTF-8?q?=E4=BA=A4;=E8=A7=A3=E5=86=B3=E9=A1=B5=E9=9D=A2=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=8C=89=E9=92=AE=E7=B9=81=E5=A4=9A=E6=97=B6=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=BD=93=E9=AA=8C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/views/system/user/index.vue | 1466 +++++++++++----------- 1 file changed, 751 insertions(+), 715 deletions(-) diff --git a/ruoyi-ui/src/views/system/user/index.vue b/ruoyi-ui/src/views/system/user/index.vue index af2856b34..021716b78 100644 --- a/ruoyi-ui/src/views/system/user/index.vue +++ b/ruoyi-ui/src/views/system/user/index.vue @@ -1,715 +1,751 @@ - - - + + + + From 8af60fdaa6b6c7dd4d9e73c18aedd6ee17a2f9e0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 13 Mar 2021 19:34:26 +0800 Subject: [PATCH 05/14] =?UTF-8?q?1.=20=E9=AA=8C=E8=AF=81=E7=A0=81=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=202.=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20h2=20=E8=84=9A=E6=9C=AC=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/SysCaptchaController.java | 2 +- .../dashboard/BaseDbAndRedisUnitTest.java | 4 +- .../iocoder/dashboard/BaseRedisUnitTest.java | 32 +++++++++ .../dashboard/BaseSpringBootUnitTest.java | 32 --------- .../config/RedisTestConfiguration.java | 6 +- .../core/scheduler/SchedulerManagerTest.java | 4 +- .../service/common/SysCaptchaServiceTest.java | 66 +++++++++++++++++++ ...ToolInformationSchemaColumnMapperTest.java | 4 +- .../ToolInformationSchemaTableMapperTest.java | 4 +- .../codegen/impl/ToolCodegenEngineTest.java | 5 +- .../impl/ToolCodegenSQLParserTest.java | 4 +- .../impl/ToolCodegenServiceImplTest.java | 5 +- src/test/resources/sql/create_tables.sql | 8 +-- 13 files changed, 119 insertions(+), 57 deletions(-) create mode 100644 src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java delete mode 100644 src/test/java/cn/iocoder/dashboard/BaseSpringBootUnitTest.java create mode 100644 src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java index 13e84dc4e..487389331 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java @@ -21,8 +21,8 @@ public class SysCaptchaController { @Resource private SysCaptchaService captchaService; - @ApiOperation("生成图片验证码") @GetMapping("/get-image") + @ApiOperation("生成图片验证码") public CommonResult getCaptchaImage() { return success(captchaService.getCaptchaImage()); } diff --git a/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java b/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java index 59bacb052..43d28da9f 100644 --- a/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java +++ b/src/test/java/cn/iocoder/dashboard/BaseDbAndRedisUnitTest.java @@ -15,9 +15,9 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.jdbc.Sql; /** - * 依赖内存 DB 的单元测试 + * 依赖内存 DB + Redis 的单元测试 * - * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法 + * 相比 {@link BaseDbUnitTest} 来说,额外增加了内存 Redis * * @author 芋道源码 */ diff --git a/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java b/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java new file mode 100644 index 000000000..a806e4670 --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/BaseRedisUnitTest.java @@ -0,0 +1,32 @@ +package cn.iocoder.dashboard; + +import cn.iocoder.dashboard.config.RedisTestConfiguration; +import cn.iocoder.dashboard.framework.redis.config.RedisConfig; +import org.redisson.spring.starter.RedissonAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +/** + * 依赖内存 Redis 的单元测试 + * + * 相比 {@link BaseDbUnitTest} 来说,从内存 DB 改成了内存 Redis + * + * @author 芋道源码 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisUnitTest.Application.class) +@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 +public class BaseRedisUnitTest { + + @Import({ + // Redis 配置类 + RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer + RedisAutoConfiguration.class, // Spring Redis 自动配置类 + RedisConfig.class, // 自己的 Redis 配置类 + RedissonAutoConfiguration.class, // Redisson 自动高配置类 + }) + public static class Application { + } + +} diff --git a/src/test/java/cn/iocoder/dashboard/BaseSpringBootUnitTest.java b/src/test/java/cn/iocoder/dashboard/BaseSpringBootUnitTest.java deleted file mode 100644 index fe615dcaf..000000000 --- a/src/test/java/cn/iocoder/dashboard/BaseSpringBootUnitTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.dashboard; - -import org.junit.jupiter.api.AfterEach; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; - -import javax.annotation.Resource; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) -@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 -@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB -@Deprecated -public class BaseSpringBootUnitTest { - - @Resource - private StringRedisTemplate stringRedisTemplate; - - /** - * 每个单元测试结束后,清理 Redis - */ - @AfterEach - public void cleanRedis() { - stringRedisTemplate.execute((RedisCallback) connection -> { - connection.flushDb(); - return null; - }); - } - -} diff --git a/src/test/java/cn/iocoder/dashboard/config/RedisTestConfiguration.java b/src/test/java/cn/iocoder/dashboard/config/RedisTestConfiguration.java index c93d766a4..29539dbad 100644 --- a/src/test/java/cn/iocoder/dashboard/config/RedisTestConfiguration.java +++ b/src/test/java/cn/iocoder/dashboard/config/RedisTestConfiguration.java @@ -1,19 +1,17 @@ package cn.iocoder.dashboard.config; import com.github.fppt.jedismock.RedisServer; -import org.redisson.spring.starter.RedissonAutoConfiguration; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; import java.io.IOException; @Configuration(proxyBeanMethods = false) +@Lazy(false) // 禁止延迟加载 @EnableConfigurationProperties(RedisProperties.class) -@AutoConfigureBefore({RedisAutoConfiguration.class, RedissonAutoConfiguration.class}) // 在 Redis 自动配置前,进行初始化 public class RedisTestConfiguration { /** diff --git a/src/test/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManagerTest.java b/src/test/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManagerTest.java index a9b050153..a4dd5cbe0 100644 --- a/src/test/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManagerTest.java +++ b/src/test/java/cn/iocoder/dashboard/framework/quartz/core/scheduler/SchedulerManagerTest.java @@ -1,14 +1,14 @@ package cn.iocoder.dashboard.framework.quartz.core.scheduler; import cn.hutool.core.util.StrUtil; -import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.dashboard.modules.system.job.auth.SysUserSessionTimeoutJob; import org.junit.jupiter.api.Test; import org.quartz.SchedulerException; import javax.annotation.Resource; -class SchedulerManagerTest extends BaseSpringBootUnitTest { +class SchedulerManagerTest extends BaseDbUnitTest { @Resource private SchedulerManager schedulerManager; diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java new file mode 100644 index 000000000..ed127442d --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/common/SysCaptchaServiceTest.java @@ -0,0 +1,66 @@ +package cn.iocoder.dashboard.modules.system.service.common; + +import cn.iocoder.dashboard.BaseRedisUnitTest; +import cn.iocoder.dashboard.framework.captcha.config.CaptchaProperties; +import cn.iocoder.dashboard.modules.system.controller.common.vo.SysCaptchaImageRespVO; +import cn.iocoder.dashboard.modules.system.dal.redis.common.SysCaptchaRedisDAO; +import cn.iocoder.dashboard.modules.system.service.common.impl.SysCaptchaServiceImpl; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.dashboard.util.RandomUtils.randomString; +import static org.junit.jupiter.api.Assertions.*; + +@Import({SysCaptchaServiceImpl.class, CaptchaProperties.class, SysCaptchaRedisDAO.class}) +public class SysCaptchaServiceTest extends BaseRedisUnitTest { + + @Resource + private SysCaptchaServiceImpl captchaService; + + @Resource + private SysCaptchaRedisDAO captchaRedisDAO; + @Resource + private CaptchaProperties captchaProperties; + + @Test + public void testGetCaptchaImage() { + // 调用 + SysCaptchaImageRespVO respVO = captchaService.getCaptchaImage(); + // 断言 + assertNotNull(respVO.getUuid()); + assertNotNull(respVO.getImg()); + String captchaCode = captchaRedisDAO.get(respVO.getUuid()); + assertNotNull(captchaCode); + } + + @Test + public void testGetCaptchaCode() { + // 准备参数 + String uuid = randomString(); + String code = randomString(); + // mock 数据 + captchaRedisDAO.set(uuid, code, captchaProperties.getTimeout()); + + // 调用 + String resultCode = captchaService.getCaptchaCode(uuid); + // 断言 + assertEquals(code, resultCode); + } + + @Test + public void testDeleteCaptchaCode() { + // 准备参数 + String uuid = randomString(); + String code = randomString(); + // mock 数据 + captchaRedisDAO.set(uuid, code, captchaProperties.getTimeout()); + + // 调用 + captchaService.deleteCaptchaCode(uuid); + // 断言 + assertNull(captchaRedisDAO.get(uuid)); + } + +} diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java index 1b7e1f283..dfb64a8ea 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaColumnMapperTest.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.tool.dal.mysql.codegen; -import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolSchemaColumnDO; import org.junit.jupiter.api.Test; @@ -9,7 +9,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertTrue; -public class ToolInformationSchemaColumnMapperTest extends BaseSpringBootUnitTest { +public class ToolInformationSchemaColumnMapperTest extends BaseDbUnitTest { @Resource private ToolSchemaColumnMapper toolInformationSchemaColumnMapper; diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java index ff488972c..67e8f7066 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java @@ -1,6 +1,6 @@ package cn.iocoder.dashboard.modules.tool.dal.mysql.codegen; -import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; import org.junit.jupiter.api.Test; @@ -9,7 +9,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertTrue; -class ToolInformationSchemaTableMapperTest extends BaseSpringBootUnitTest { +class ToolInformationSchemaTableMapperTest extends BaseDbUnitTest { @Resource private ToolSchemaTableMapper toolInformationSchemaTableMapper; diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java index e415b4f84..94ade49f4 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenEngineTest.java @@ -1,18 +1,17 @@ package cn.iocoder.dashboard.modules.tool.service.codegen.impl; -import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.BaseDbUnitTest; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenColumnDO; import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolCodegenTableDO; import cn.iocoder.dashboard.modules.tool.dal.mysql.codegen.ToolCodegenColumnMapper; import cn.iocoder.dashboard.modules.tool.dal.mysql.codegen.ToolCodegenTableMapper; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import java.util.List; import java.util.Map; -public class ToolCodegenEngineTest extends BaseSpringBootUnitTest { +public class ToolCodegenEngineTest extends BaseDbUnitTest { @Resource private ToolCodegenTableMapper codegenTableMapper; diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenSQLParserTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenSQLParserTest.java index 1c331dfdf..f47fce0c3 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenSQLParserTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenSQLParserTest.java @@ -1,9 +1,9 @@ package cn.iocoder.dashboard.modules.tool.service.codegen.impl; -import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.BaseDbUnitTest; import org.junit.jupiter.api.Test; -public class ToolCodegenSQLParserTest extends BaseSpringBootUnitTest { +public class ToolCodegenSQLParserTest extends BaseDbUnitTest { @Test public void testParse() { diff --git a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java index 603ae9a47..1198a52c7 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImplTest.java @@ -1,12 +1,11 @@ package cn.iocoder.dashboard.modules.tool.service.codegen.impl; -import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.BaseDbUnitTest; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; -class ToolCodegenServiceImplTest extends BaseSpringBootUnitTest { +class ToolCodegenServiceImplTest extends BaseDbUnitTest { @Resource private ToolCodegenServiceImpl toolCodegenService; diff --git a/src/test/resources/sql/create_tables.sql b/src/test/resources/sql/create_tables.sql index 36c573dd9..4a9d218b9 100644 --- a/src/test/resources/sql/create_tables.sql +++ b/src/test/resources/sql/create_tables.sql @@ -113,7 +113,7 @@ CREATE TABLE IF NOT EXISTS "sys_menu" ( PRIMARY KEY ("id") ) COMMENT '菜单权限表'; -CREATE TABLE "sys_dict_type" ( +CREATE TABLE IF NOT EXISTS "sys_dict_type" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "name" varchar(100) NOT NULL DEFAULT '', "type" varchar(100) NOT NULL DEFAULT '', @@ -127,7 +127,7 @@ CREATE TABLE "sys_dict_type" ( PRIMARY KEY ("id") ) COMMENT '字典类型表'; -CREATE TABLE `sys_user_session` ( +CREATE TABLE IF NOT EXISTS `sys_user_session` ( `id` varchar(32) NOT NULL, `user_id` bigint DEFAULT NULL, `username` varchar(50) NOT NULL DEFAULT '', @@ -191,7 +191,7 @@ CREATE TABLE IF NOT EXISTS `sys_login_log` ( ) COMMENT ='系统访问记录'; -CREATE TABLE `sys_operate_log` ( +CREATE TABLE IF NOT EXISTS `sys_operate_log` ( `id` bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY, `trace_id` varchar(64) NOT NULL DEFAULT '', `user_id` bigint(20) NOT NULL, @@ -219,7 +219,7 @@ CREATE TABLE `sys_operate_log` ( PRIMARY KEY (`id`) ) COMMENT ='操作日志记录'; -create table "sys_user" ( +create table IF NOT EXISTS "sys_user" ( "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, "username" varchar(30) not null, "password" varchar(100) not null default '', From cd854d0ee13323eeaa23951315adabc31cee2edd Mon Sep 17 00:00:00 2001 From: niudehua <657563945@qq.com> Date: Sat, 13 Mar 2021 21:07:04 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=AE=BE=E7=BD=AE=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/user/SysUserController.java | 4 +- .../user/SysUserProfileController.java | 42 ++++++++------ .../user/vo/user/SysUserProfileRespVO.java | 5 -- .../vo/user/SysUserProfileUpdateReqVO.java | 27 +++++++-- .../system/service/user/SysUserService.java | 6 +- .../service/user/SysUserServiceImpl.java | 56 ++++++++++--------- src/main/resources/application-dev.yaml | 2 +- src/main/resources/application-local.yaml | 2 +- 8 files changed, 86 insertions(+), 58 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java index 273be98f0..4374ff4d9 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java @@ -40,8 +40,8 @@ public class SysUserController { @Resource private SysDeptService deptService; - @ApiOperation("获得用户分页列表") @GetMapping("/page") + @ApiOperation("获得用户分页列表") @PreAuthorize("@ss.hasPermission('system:user:list')") public CommonResult> pageUsers(@Validated SysUserPageReqVO reqVO) { // 获得用户分页列表 @@ -66,9 +66,9 @@ public class SysUserController { /** * 根据用户编号获取详细信息 */ + @GetMapping("/get") @ApiOperation("获得用户详情") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) - @GetMapping("/get") // @PreAuthorize("@ss.hasPermi('system:user:query')") public CommonResult getInfo(@RequestParam("id") Long id) { return success(SysUserConvert.INSTANCE.convert(userService.getUser(id))); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index 40a99910f..710617e1f 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -1,5 +1,6 @@ package cn.iocoder.dashboard.modules.system.controller.user; +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; import cn.iocoder.dashboard.common.pojo.CommonResult; import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; @@ -12,8 +13,10 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; +import cn.iocoder.dashboard.util.collection.CollectionUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -24,15 +27,19 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import java.io.IOException; import java.util.List; -import java.util.stream.Collectors; + +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_UPLOAD_FAILED; /** * @author niudehua */ -@Api(tags = "用户个人中心") @RestController @RequestMapping("/system/user/profile") +@Api(tags = "用户个人中心") +@Slf4j public class SysUserProfileController { @Resource @@ -47,18 +54,17 @@ public class SysUserProfileController { * * @return 个人信息详情 */ - @ApiOperation("获得登录用户信息") @GetMapping("/get") + @ApiOperation("获得登录用户信息") public CommonResult profile() { LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); // 获取用户信息 - assert loginUser != null; Long userId = loginUser.getId(); SysUserDO user = userService.getUser(userId); SysUserProfileRespVO userProfileRespVO = SysUserConvert.INSTANCE.convert03(user); List userRoles = roleService.listRolesFromCache(permissionService.listUserRoleIs(userId)); - userProfileRespVO.setRoles(userRoles.stream().map(SysUserConvert.INSTANCE::convert).collect(Collectors.toSet())); - return CommonResult.success(userProfileRespVO); + userProfileRespVO.setRoles(CollectionUtils.convertSet(userRoles, SysUserConvert.INSTANCE::convert)); + return success(userProfileRespVO); } /** @@ -68,14 +74,12 @@ public class SysUserProfileController { * @param request HttpServletRequest * @return 修改结果 */ - @ApiOperation("修改用户个人信息") @PostMapping("/update") + @ApiOperation("修改用户个人信息") public CommonResult updateProfile(@RequestBody SysUserProfileUpdateReqVO reqVO, HttpServletRequest request) { - if (userService.updateUserProfile(reqVO) > 0) { - SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request); - return CommonResult.success(true); - } - return CommonResult.success(false); + userService.updateUserProfile(reqVO); + SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request); + return success(true); } /** @@ -84,16 +88,20 @@ public class SysUserProfileController { * @param file 头像文件 * @return 上传结果 */ - @ApiOperation("上传用户个人头像") @PostMapping("/uploadAvatar") + @ApiOperation("上传用户个人头像") public CommonResult uploadAvatar(@RequestParam("avatarFile") MultipartFile file) { if (!file.isEmpty()) { LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); - assert loginUser != null; - if (userService.updateAvatar(loginUser.getId(), file) > 0) { - return CommonResult.success(true); + try { + if (userService.updateAvatar(loginUser.getId(), file.getInputStream()) > 0) { + return success(true); + } + } catch (IOException e) { + log.error("文件上传失败", e); + throw ServiceExceptionUtil.exception(FILE_UPLOAD_FAILED); } } - return CommonResult.success(false); + return success(false); } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java index a081dea65..39737f00b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java @@ -17,11 +17,6 @@ import java.util.Set; @EqualsAndHashCode(callSuper = true) public class SysUserProfileRespVO extends SysUserRespVO { - @ApiModelProperty(value = "旧密码", required = true, example = "123456") - private String oldPassword; - - @ApiModelProperty(value = "新密码", required = true, example = "123456") - private String newPassword; /** * 所属角色 */ diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java index d3185b242..cea2ca77c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java @@ -3,19 +3,38 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import lombok.EqualsAndHashCode; +import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; -@ApiModel("用户更新 Request VO") +@ApiModel("用户个人信息更新 Request VO") @Data -@EqualsAndHashCode(callSuper = true) -public class SysUserProfileUpdateReqVO extends SysUserBaseVO { +public class SysUserProfileUpdateReqVO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") @NotNull(message = "用户编号不能为空") private Long id; + @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿") + @Size(max = 30, message = "用户昵称长度不能超过30个字符") + private String nickname; + + @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn") + @Email(message = "邮箱格式不正确") + @Size(max = 50, message = "邮箱长度不能超过50个字符") + private String email; + + @ApiModelProperty(value = "手机号码", example = "15601691300") + @Size(max = 11, message = "手机号码长度不能超过11个字符") + private String mobile; + + @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类") + private Integer sex; + + @ApiModelProperty(value = "用户头像", example = "http://www.iocoder.cn/xxx.png") + private String avatar; + @ApiModelProperty(value = "旧密码", required = true, example = "123456") private String oldPassword; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java index e8097590f..def5624e9 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java @@ -11,8 +11,8 @@ import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfil import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.util.collection.CollectionUtils; -import org.springframework.web.multipart.MultipartFile; +import java.io.InputStream; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -115,7 +115,7 @@ public interface SysUserService { * @param reqVO 用户个人信息 * @return 修改结果 */ - int updateUserProfile(SysUserProfileUpdateReqVO reqVO); + void updateUserProfile(SysUserProfileUpdateReqVO reqVO); /** * 删除用户 @@ -156,7 +156,7 @@ public interface SysUserService { * @param avatarFile 头像文件 * @return 更新结果 */ - int updateAvatar(Long id, MultipartFile avatarFile); + int updateAvatar(Long id, InputStream avatarFile); // // /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index c1fc828a0..735121216 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -2,11 +2,13 @@ package cn.iocoder.dashboard.modules.system.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.lang.UUID; import cn.hutool.core.util.StrUtil; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.common.exception.ServiceException; import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.infra.service.file.InfFileService; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO; @@ -19,7 +21,6 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper; -import cn.iocoder.dashboard.modules.system.service.common.SysFileService; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; @@ -28,10 +29,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -66,7 +66,7 @@ public class SysUserServiceImpl implements SysUserService { private PasswordEncoder passwordEncoder; @Resource - private SysFileService fileService; + private InfFileService fileService; // /** // * 根据条件分页查询用户列表 @@ -156,20 +156,22 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public int updateUserProfile(SysUserProfileUpdateReqVO reqVO) { + public void updateUserProfile(SysUserProfileUpdateReqVO reqVO) { // 校验正确性 - this.checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), - reqVO.getDeptId(), reqVO.getPostIds()); - - SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); - // 校验旧密码 - if (checkOldPassword(reqVO.getId(), reqVO.getOldPassword(), reqVO.getNewPassword())) { - return userMapper.updateById(updateObj); + this.checkUserExists(reqVO.getId()); + this.checkEmailUnique(reqVO.getId(), reqVO.getEmail()); + this.checkMobileUnique(reqVO.getId(), reqVO.getMobile()); + // 校验填写密码 + String encode = null; + if (this.checkOldPassword(reqVO.getId(), reqVO.getOldPassword(), reqVO.getNewPassword())) { + // 更新密码 + encode = passwordEncoder.encode(reqVO.getNewPassword()); } - - String encode = passwordEncoder.encode(reqVO.getNewPassword()); - updateObj.setPassword(encode); - return userMapper.updateById(updateObj); + SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); + if (StrUtil.isNotBlank(encode)) { + updateObj.setPassword(encode); + } + userMapper.updateById(updateObj); } @Override @@ -314,9 +316,17 @@ public class SysUserServiceImpl implements SysUserService { }); } + /** + * 校验旧密码、新密码 + * + * @param id 用户 id + * @param oldPassword 旧密码 + * @param newPassword 新密码 + * @return + */ private boolean checkOldPassword(Long id, String oldPassword, String newPassword) { if (id == null || StrUtil.isBlank(oldPassword) || StrUtil.isBlank(newPassword)) { - return true; + return false; } SysUserDO user = userMapper.selectById(id); if (user == null) { @@ -326,7 +336,7 @@ public class SysUserServiceImpl implements SysUserService { if (!passwordEncoder.matches(oldPassword, user.getPassword())) { throw ServiceExceptionUtil.exception(USER_PASSWORD_FAILED); } - return false; + return true; } @Override @@ -368,15 +378,11 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public int updateAvatar(Long id, MultipartFile avatarFile) { + public int updateAvatar(Long id, InputStream avatarFile) { this.checkUserExists(id); // 存储文件 - String avatar = null; - try { - avatar = fileService.createFile(avatarFile.getOriginalFilename(), IoUtil.readBytes(avatarFile.getInputStream())); - } catch (IOException e) { - throw ServiceExceptionUtil.exception(FILE_UPLOAD_FAILED); - } + String avatar; + avatar = fileService.createFile(UUID.fastUUID().toString(), IoUtil.readBytes(avatarFile)); // 更新路径 SysUserDO sysUserDO = new SysUserDO(); sysUserDO.setId(id); diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index c9c40e739..b0a96fb04 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -145,7 +145,7 @@ yudao: swagger: title: 管理后台 description: 提供管理员管理的所有功能 - version: ${yudao.info.base-package} + version: ${yudao.info.version} base-package: ${yudao.info.base-package}.modules captcha: timeout: 5m diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index 500eb7b51..fdb260758 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -145,7 +145,7 @@ yudao: swagger: title: 管理后台 description: 提供管理员管理的所有功能 - version: ${yudao.info.base-package} + version: ${yudao.info.version} base-package: ${yudao.info.base-package}.modules captcha: timeout: 5m From 2dd87e0414e05054e0cd350f8fc217e1308e11dc Mon Sep 17 00:00:00 2001 From: niudehua <657563945@qq.com> Date: Sat, 13 Mar 2021 22:16:40 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20=E4=BA=8B=E5=8A=A1?= =?UTF-8?q?=20rollback=20=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/job/impl/InfJobServiceImpl.java | 8 +++---- .../user/SysUserProfileController.java | 2 +- .../permission/impl/SysMenuServiceImpl.java | 2 +- .../impl/SysPermissionServiceImpl.java | 2 +- .../permission/impl/SysRoleServiceImpl.java | 2 +- .../service/user/SysUserServiceImpl.java | 22 ++++--------------- .../codegen/impl/ToolCodegenServiceImpl.java | 10 ++++----- 7 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java index d82207de1..156c423c6 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java @@ -41,7 +41,7 @@ public class InfJobServiceImpl implements InfJobService { private SchedulerManager schedulerManager; @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public Long createJob(InfJobCreateReqVO createReqVO) throws SchedulerException { validateCronExpression(createReqVO.getCronExpression()); // 校验唯一性 @@ -66,7 +66,7 @@ public class InfJobServiceImpl implements InfJobService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateJob(InfJobUpdateReqVO updateReqVO) throws SchedulerException { validateCronExpression(updateReqVO.getCronExpression()); // 校验存在 @@ -86,7 +86,7 @@ public class InfJobServiceImpl implements InfJobService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateJobStatus(Long id, Integer status) throws SchedulerException { // 校验 status if (!containsAny(status, InfJobStatusEnum.NORMAL.getStatus(), InfJobStatusEnum.STOP.getStatus())) { @@ -120,7 +120,7 @@ public class InfJobServiceImpl implements InfJobService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteJob(Long id) throws SchedulerException { // 校验存在 InfJobDO job = this.validateJobExists(id); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index 710617e1f..1b2503c77 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -88,7 +88,7 @@ public class SysUserProfileController { * @param file 头像文件 * @return 上传结果 */ - @PostMapping("/uploadAvatar") + @PostMapping("/upload-avatar") @ApiOperation("上传用户个人头像") public CommonResult uploadAvatar(@RequestParam("avatarFile") MultipartFile file) { if (!file.isEmpty()) { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java index 070677d8e..b4773c248 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java @@ -206,7 +206,7 @@ public class SysMenuServiceImpl implements SysMenuService { * * @param menuId 菜单编号 */ - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteMenu(Long menuId) { // 校验更新的菜单是否存在 if (menuMapper.selectById(menuId) == null) { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 9f48af9f5..ceb1d6d83 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java @@ -176,7 +176,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void assignRoleMenu(Long roleId, Set menuIds) { // 获得角色拥有菜单编号 Set dbMenuIds = CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId), diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java index d760b734b..93f67ea71 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java @@ -174,7 +174,7 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteRole(Long id) { // 校验是否可以更新 this.checkUpdateRole(id); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index 735121216..5411d27e8 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; -import cn.hutool.core.lang.UUID; +import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.common.exception.ServiceException; @@ -68,19 +68,6 @@ public class SysUserServiceImpl implements SysUserService { @Resource private InfFileService fileService; -// /** -// * 根据条件分页查询用户列表 -// * -// * @param user 用户信息 -// * @return 用户信息集合信息 -// */ -// @Override -// @DataScope(deptAlias = "d", userAlias = "u") -// public List selectUserList(SysUser user) -// { -// return userMapper.selectUserList(user); -// } - @Override public SysUserDO getUserByUserName(String username) { return userMapper.selectByUsername(username); @@ -322,7 +309,7 @@ public class SysUserServiceImpl implements SysUserService { * @param id 用户 id * @param oldPassword 旧密码 * @param newPassword 新密码 - * @return + * @return 校验结果 */ private boolean checkOldPassword(Long id, String oldPassword, String newPassword) { if (id == null || StrUtil.isBlank(oldPassword) || StrUtil.isBlank(newPassword)) { @@ -340,7 +327,7 @@ public class SysUserServiceImpl implements SysUserService { } @Override - @Transactional // 添加事务,异常则回滚所有导入 + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 public SysUserImportRespVO importUsers(List importUsers, boolean isUpdateSupport) { if (CollUtil.isEmpty(importUsers)) { throw ServiceExceptionUtil.exception(USER_IMPORT_LIST_IS_EMPTY); @@ -381,8 +368,7 @@ public class SysUserServiceImpl implements SysUserService { public int updateAvatar(Long id, InputStream avatarFile) { this.checkUserExists(id); // 存储文件 - String avatar; - avatar = fileService.createFile(UUID.fastUUID().toString(), IoUtil.readBytes(avatarFile)); + String avatar = fileService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile)); // 更新路径 SysUserDO sysUserDO = new SysUserDO(); sysUserDO.setId(id); diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java index 6b2b5f9f7..5b746f6fd 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java @@ -109,7 +109,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public List createCodegenListFromDB(List tableNames) { List ids = new ArrayList<>(tableNames.size()); // 遍历添加。虽然效率会低一点,但是没必要做成完全批量,因为不会这么大量 @@ -118,7 +118,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateCodegen(ToolCodegenUpdateReqVO updateReqVO) { // 校验是否已经存在 if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { @@ -134,7 +134,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void syncCodegenFromDB(Long tableId) { // 校验是否已经存在 ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); @@ -149,7 +149,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void syncCodegenFromSQL(Long tableId, String sql) { // 校验是否已经存在 ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); @@ -201,7 +201,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteCodegen(Long tableId) { // 校验是否已经存在 if (codegenTableMapper.selectById(tableId) == null) { From 8297d94b51dc5dc8efe4567647de14238f0f6371 Mon Sep 17 00:00:00 2001 From: niudehua <657563945@qq.com> Date: Sat, 13 Mar 2021 22:24:02 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=AE=BE=E7=BD=AE=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/SysUserProfileController.java | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index 1b2503c77..27a170560 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -1,6 +1,5 @@ package cn.iocoder.dashboard.modules.system.controller.user; -import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; import cn.iocoder.dashboard.common.pojo.CommonResult; import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; @@ -31,7 +30,6 @@ import java.io.IOException; import java.util.List; import static cn.iocoder.dashboard.common.pojo.CommonResult.success; -import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_UPLOAD_FAILED; /** * @author niudehua @@ -49,11 +47,6 @@ public class SysUserProfileController { @Resource private SysRoleService roleService; - /** - * 个人信息 - * - * @return 个人信息详情 - */ @GetMapping("/get") @ApiOperation("获得登录用户信息") public CommonResult profile() { @@ -67,13 +60,6 @@ public class SysUserProfileController { return success(userProfileRespVO); } - /** - * 修改个人信息 - * - * @param reqVO 个人信息更新 reqVO - * @param request HttpServletRequest - * @return 修改结果 - */ @PostMapping("/update") @ApiOperation("修改用户个人信息") public CommonResult updateProfile(@RequestBody SysUserProfileUpdateReqVO reqVO, HttpServletRequest request) { @@ -82,12 +68,6 @@ public class SysUserProfileController { return success(true); } - /** - * 上传用户个人头像 - * - * @param file 头像文件 - * @return 上传结果 - */ @PostMapping("/upload-avatar") @ApiOperation("上传用户个人头像") public CommonResult uploadAvatar(@RequestParam("avatarFile") MultipartFile file) { @@ -99,7 +79,7 @@ public class SysUserProfileController { } } catch (IOException e) { log.error("文件上传失败", e); - throw ServiceExceptionUtil.exception(FILE_UPLOAD_FAILED); + throw new RuntimeException(e); } } return success(false); From 74669817d8e203ce4219e3d98532a61bbd3f5d20 Mon Sep 17 00:00:00 2001 From: niudehua <657563945@qq.com> Date: Sat, 13 Mar 2021 22:25:06 +0800 Subject: [PATCH 09/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E4=B8=AA=E4=BA=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=AE=BE=E7=BD=AE=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/system/controller/user/SysUserProfileController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index 27a170560..3b420a463 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -78,7 +78,6 @@ public class SysUserProfileController { return success(true); } } catch (IOException e) { - log.error("文件上传失败", e); throw new RuntimeException(e); } } From 562f4cb953bccd1b4be474441e5e36011941b945 Mon Sep 17 00:00:00 2001 From: timfruit Date: Sat, 13 Mar 2021 22:40:16 +0800 Subject: [PATCH 10/14] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E8=89=BF=E8=89=BF?= =?UTF-8?q?=E7=9A=84=E6=8F=90=E7=A4=BA=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/doc/InfDbDocController.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java index c39392c33..f5b293538 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/doc/InfDbDocController.java @@ -48,9 +48,7 @@ public class InfDbDocController { @GetMapping("/export-html") @ApiOperation("导出html格式的数据文档") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class), - }) + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class) public void exportHtml(@RequestParam(defaultValue = "true") Boolean deleteFile, HttpServletResponse response) throws IOException { doExportFile(EngineFileType.HTML, deleteFile, response); @@ -58,9 +56,7 @@ public class InfDbDocController { @GetMapping("/export-word") @ApiOperation("导出word格式的数据文档") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class), - }) + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class) public void exportWord(@RequestParam(defaultValue = "true") Boolean deleteFile, HttpServletResponse response) throws IOException { doExportFile(EngineFileType.WORD, deleteFile, response); @@ -68,9 +64,7 @@ public class InfDbDocController { @GetMapping("/export-markdown") @ApiOperation("导出markdown格式的数据文档") - @ApiImplicitParams({ - @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class), - }) + @ApiImplicitParam(name = "deleteFile", value = "是否删除在服务器本地生成的数据库文档", example = "true", dataTypeClass = Boolean.class) public void exportMarkdown(@RequestParam(defaultValue = "true") Boolean deleteFile, HttpServletResponse response) throws IOException { doExportFile(EngineFileType.MD, deleteFile, response); @@ -81,12 +75,13 @@ public class InfDbDocController { String docFileName = DOC_FILE_NAME + "_" + IdUtil.fastSimpleUUID(); String filePath = doExportFile(fileOutputType, docFileName); String downloadFileName = DOC_FILE_NAME + fileOutputType.getFileSuffix(); //下载后的文件名 - // 读取,返回 - //IoUtil.readBytes 直接读取FileInputStream 不会关闭流,有bug,所以用BufferedInputStream包装一下, 关闭流后才能删除文件 - byte[] content = IoUtil.readBytes(new BufferedInputStream(new FileInputStream(filePath))); - //这里不用hutool工具类,它的中文文件名编码有问题,导致在浏览器下载时有问题 - ServletUtils.writeAttachment(response, downloadFileName, content); - handleDeleteFile(deleteFile, filePath); + try { + // 读取,返回 + //这里不用hutool工具类,它的中文文件名编码有问题,导致在浏览器下载时有问题 + ServletUtils.writeAttachment(response, downloadFileName, FileUtil.readBytes(filePath)); + }finally { + handleDeleteFile(deleteFile, filePath); + } } /** From 61c24c0aa7fd1b4640b8f1feeaa1d81d0214fc3a Mon Sep 17 00:00:00 2001 From: niudehua <657563945@qq.com> Date: Sat, 13 Mar 2021 21:07:04 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20=E4=BA=8B=E5=8A=A1?= =?UTF-8?q?=20rollback=20=E5=B1=9E=E6=80=A7=20=E5=A2=9E=E5=8A=A0=20?= =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF=E8=AE=BE=E7=BD=AE=20?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加 个人信息设置 功能 --- .../service/job/impl/InfJobServiceImpl.java | 8 +-- .../controller/user/SysUserController.java | 4 +- .../user/SysUserProfileController.java | 65 ++++++----------- .../user/vo/user/SysUserProfileRespVO.java | 5 -- .../vo/user/SysUserProfileUpdateReqVO.java | 27 +++++-- .../system/enums/SysErrorCodeConstants.java | 1 + .../permission/impl/SysMenuServiceImpl.java | 2 +- .../impl/SysPermissionServiceImpl.java | 2 +- .../permission/impl/SysRoleServiceImpl.java | 2 +- .../system/service/user/SysUserService.java | 7 +- .../service/user/SysUserServiceImpl.java | 72 +++++++++---------- .../codegen/impl/ToolCodegenServiceImpl.java | 10 +-- src/main/resources/application-dev.yaml | 2 +- src/main/resources/application-local.yaml | 2 +- 14 files changed, 98 insertions(+), 111 deletions(-) diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java index d82207de1..156c423c6 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobServiceImpl.java @@ -41,7 +41,7 @@ public class InfJobServiceImpl implements InfJobService { private SchedulerManager schedulerManager; @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public Long createJob(InfJobCreateReqVO createReqVO) throws SchedulerException { validateCronExpression(createReqVO.getCronExpression()); // 校验唯一性 @@ -66,7 +66,7 @@ public class InfJobServiceImpl implements InfJobService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateJob(InfJobUpdateReqVO updateReqVO) throws SchedulerException { validateCronExpression(updateReqVO.getCronExpression()); // 校验存在 @@ -86,7 +86,7 @@ public class InfJobServiceImpl implements InfJobService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateJobStatus(Long id, Integer status) throws SchedulerException { // 校验 status if (!containsAny(status, InfJobStatusEnum.NORMAL.getStatus(), InfJobStatusEnum.STOP.getStatus())) { @@ -120,7 +120,7 @@ public class InfJobServiceImpl implements InfJobService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteJob(Long id) throws SchedulerException { // 校验存在 InfJobDO job = this.validateJobExists(id); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java index 273be98f0..4374ff4d9 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java @@ -40,8 +40,8 @@ public class SysUserController { @Resource private SysDeptService deptService; - @ApiOperation("获得用户分页列表") @GetMapping("/page") + @ApiOperation("获得用户分页列表") @PreAuthorize("@ss.hasPermission('system:user:list')") public CommonResult> pageUsers(@Validated SysUserPageReqVO reqVO) { // 获得用户分页列表 @@ -66,9 +66,9 @@ public class SysUserController { /** * 根据用户编号获取详细信息 */ + @GetMapping("/get") @ApiOperation("获得用户详情") @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) - @GetMapping("/get") // @PreAuthorize("@ss.hasPermi('system:user:query')") public CommonResult getInfo(@RequestParam("id") Long id) { return success(SysUserConvert.INSTANCE.convert(userService.getUser(id))); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java index 40a99910f..a43b0a4e7 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserProfileController.java @@ -1,7 +1,7 @@ package cn.iocoder.dashboard.modules.system.controller.user; +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; import cn.iocoder.dashboard.common.pojo.CommonResult; -import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileRespVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfileUpdateReqVO; @@ -12,8 +12,10 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; +import cn.iocoder.dashboard.util.collection.CollectionUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -24,15 +26,19 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import java.io.IOException; import java.util.List; -import java.util.stream.Collectors; + +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_IS_EMPTY; /** * @author niudehua */ -@Api(tags = "用户个人中心") @RestController @RequestMapping("/system/user/profile") +@Api(tags = "用户个人中心") +@Slf4j public class SysUserProfileController { @Resource @@ -42,58 +48,33 @@ public class SysUserProfileController { @Resource private SysRoleService roleService; - /** - * 个人信息 - * - * @return 个人信息详情 - */ - @ApiOperation("获得登录用户信息") @GetMapping("/get") + @ApiOperation("获得登录用户信息") public CommonResult profile() { - LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); // 获取用户信息 - assert loginUser != null; - Long userId = loginUser.getId(); + Long userId = SecurityFrameworkUtils.getLoginUserId(); SysUserDO user = userService.getUser(userId); SysUserProfileRespVO userProfileRespVO = SysUserConvert.INSTANCE.convert03(user); List userRoles = roleService.listRolesFromCache(permissionService.listUserRoleIs(userId)); - userProfileRespVO.setRoles(userRoles.stream().map(SysUserConvert.INSTANCE::convert).collect(Collectors.toSet())); - return CommonResult.success(userProfileRespVO); + userProfileRespVO.setRoles(CollectionUtils.convertSet(userRoles, SysUserConvert.INSTANCE::convert)); + return success(userProfileRespVO); } - /** - * 修改个人信息 - * - * @param reqVO 个人信息更新 reqVO - * @param request HttpServletRequest - * @return 修改结果 - */ - @ApiOperation("修改用户个人信息") @PostMapping("/update") + @ApiOperation("修改用户个人信息") public CommonResult updateProfile(@RequestBody SysUserProfileUpdateReqVO reqVO, HttpServletRequest request) { - if (userService.updateUserProfile(reqVO) > 0) { - SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request); - return CommonResult.success(true); - } - return CommonResult.success(false); + userService.updateUserProfile(reqVO); + SecurityFrameworkUtils.setLoginUser(SysAuthConvert.INSTANCE.convert(reqVO), request); + return success(true); } - /** - * 上传用户个人头像 - * - * @param file 头像文件 - * @return 上传结果 - */ + @PostMapping("/upload-avatar") @ApiOperation("上传用户个人头像") - @PostMapping("/uploadAvatar") - public CommonResult uploadAvatar(@RequestParam("avatarFile") MultipartFile file) { - if (!file.isEmpty()) { - LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); - assert loginUser != null; - if (userService.updateAvatar(loginUser.getId(), file) > 0) { - return CommonResult.success(true); - } + public CommonResult uploadAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException { + if (file.isEmpty()) { + throw ServiceExceptionUtil.exception(FILE_IS_EMPTY); } - return CommonResult.success(false); + userService.updateAvatar(SecurityFrameworkUtils.getLoginUserId(), file.getInputStream()); + return success(true); } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java index a081dea65..39737f00b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileRespVO.java @@ -17,11 +17,6 @@ import java.util.Set; @EqualsAndHashCode(callSuper = true) public class SysUserProfileRespVO extends SysUserRespVO { - @ApiModelProperty(value = "旧密码", required = true, example = "123456") - private String oldPassword; - - @ApiModelProperty(value = "新密码", required = true, example = "123456") - private String newPassword; /** * 所属角色 */ diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java index d3185b242..cea2ca77c 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserProfileUpdateReqVO.java @@ -3,19 +3,38 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.user; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import lombok.EqualsAndHashCode; +import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; -@ApiModel("用户更新 Request VO") +@ApiModel("用户个人信息更新 Request VO") @Data -@EqualsAndHashCode(callSuper = true) -public class SysUserProfileUpdateReqVO extends SysUserBaseVO { +public class SysUserProfileUpdateReqVO { @ApiModelProperty(value = "用户编号", required = true, example = "1024") @NotNull(message = "用户编号不能为空") private Long id; + @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿") + @Size(max = 30, message = "用户昵称长度不能超过30个字符") + private String nickname; + + @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn") + @Email(message = "邮箱格式不正确") + @Size(max = 50, message = "邮箱长度不能超过50个字符") + private String email; + + @ApiModelProperty(value = "手机号码", example = "15601691300") + @Size(max = 11, message = "手机号码长度不能超过11个字符") + private String mobile; + + @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类") + private Integer sex; + + @ApiModelProperty(value = "用户头像", example = "http://www.iocoder.cn/xxx.png") + private String avatar; + @ApiModelProperty(value = "旧密码", required = true, example = "123456") private String oldPassword; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java index 3f4214325..0197b6c05 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java @@ -76,5 +76,6 @@ public interface SysErrorCodeConstants { // ========== 文件 1002009000 ========== ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在"); ErrorCode FILE_UPLOAD_FAILED = new ErrorCode(1002009002, "文件上传失败"); + ErrorCode FILE_IS_EMPTY= new ErrorCode(1002009003, "文件为空"); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java index 070677d8e..b4773c248 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysMenuServiceImpl.java @@ -206,7 +206,7 @@ public class SysMenuServiceImpl implements SysMenuService { * * @param menuId 菜单编号 */ - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteMenu(Long menuId) { // 校验更新的菜单是否存在 if (menuMapper.selectById(menuId) == null) { diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 9f48af9f5..ceb1d6d83 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java @@ -176,7 +176,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void assignRoleMenu(Long roleId, Set menuIds) { // 获得角色拥有菜单编号 Set dbMenuIds = CollectionUtils.convertSet(roleMenuMapper.selectListByRoleId(roleId), diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java index d760b734b..93f67ea71 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysRoleServiceImpl.java @@ -174,7 +174,7 @@ public class SysRoleServiceImpl implements SysRoleService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteRole(Long id) { // 校验是否可以更新 this.checkUpdateRole(id); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java index e8097590f..c0ac9e611 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java @@ -11,8 +11,8 @@ import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserProfil import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.util.collection.CollectionUtils; -import org.springframework.web.multipart.MultipartFile; +import java.io.InputStream; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -115,7 +115,7 @@ public interface SysUserService { * @param reqVO 用户个人信息 * @return 修改结果 */ - int updateUserProfile(SysUserProfileUpdateReqVO reqVO); + void updateUserProfile(SysUserProfileUpdateReqVO reqVO); /** * 删除用户 @@ -154,9 +154,8 @@ public interface SysUserService { * * @param id 用户 id * @param avatarFile 头像文件 - * @return 更新结果 */ - int updateAvatar(Long id, MultipartFile avatarFile); + void updateAvatar(Long id, InputStream avatarFile); // // /** diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index c1fc828a0..acffcb7d1 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -2,11 +2,13 @@ package cn.iocoder.dashboard.modules.system.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.common.exception.ServiceException; import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.modules.infra.service.file.InfFileService; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserImportExcelVO; @@ -19,7 +21,6 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.dept.SysPostDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper; -import cn.iocoder.dashboard.modules.system.service.common.SysFileService; import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; import cn.iocoder.dashboard.modules.system.service.dept.SysPostService; import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; @@ -28,10 +29,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -66,20 +66,7 @@ public class SysUserServiceImpl implements SysUserService { private PasswordEncoder passwordEncoder; @Resource - private SysFileService fileService; - -// /** -// * 根据条件分页查询用户列表 -// * -// * @param user 用户信息 -// * @return 用户信息集合信息 -// */ -// @Override -// @DataScope(deptAlias = "d", userAlias = "u") -// public List selectUserList(SysUser user) -// { -// return userMapper.selectUserList(user); -// } + private InfFileService fileService; @Override public SysUserDO getUserByUserName(String username) { @@ -156,20 +143,22 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public int updateUserProfile(SysUserProfileUpdateReqVO reqVO) { + public void updateUserProfile(SysUserProfileUpdateReqVO reqVO) { // 校验正确性 - this.checkCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), - reqVO.getDeptId(), reqVO.getPostIds()); - - SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); - // 校验旧密码 - if (checkOldPassword(reqVO.getId(), reqVO.getOldPassword(), reqVO.getNewPassword())) { - return userMapper.updateById(updateObj); + this.checkUserExists(reqVO.getId()); + this.checkEmailUnique(reqVO.getId(), reqVO.getEmail()); + this.checkMobileUnique(reqVO.getId(), reqVO.getMobile()); + // 校验填写密码 + String encode = null; + if (this.checkOldPassword(reqVO.getId(), reqVO.getOldPassword(), reqVO.getNewPassword())) { + // 更新密码 + encode = passwordEncoder.encode(reqVO.getNewPassword()); } - - String encode = passwordEncoder.encode(reqVO.getNewPassword()); - updateObj.setPassword(encode); - return userMapper.updateById(updateObj); + SysUserDO updateObj = SysUserConvert.INSTANCE.convert(reqVO); + if (StrUtil.isNotBlank(encode)) { + updateObj.setPassword(encode); + } + userMapper.updateById(updateObj); } @Override @@ -314,9 +303,17 @@ public class SysUserServiceImpl implements SysUserService { }); } + /** + * 校验旧密码、新密码 + * + * @param id 用户 id + * @param oldPassword 旧密码 + * @param newPassword 新密码 + * @return 校验结果 + */ private boolean checkOldPassword(Long id, String oldPassword, String newPassword) { if (id == null || StrUtil.isBlank(oldPassword) || StrUtil.isBlank(newPassword)) { - return true; + return false; } SysUserDO user = userMapper.selectById(id); if (user == null) { @@ -326,11 +323,11 @@ public class SysUserServiceImpl implements SysUserService { if (!passwordEncoder.matches(oldPassword, user.getPassword())) { throw ServiceExceptionUtil.exception(USER_PASSWORD_FAILED); } - return false; + return true; } @Override - @Transactional // 添加事务,异常则回滚所有导入 + @Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入 public SysUserImportRespVO importUsers(List importUsers, boolean isUpdateSupport) { if (CollUtil.isEmpty(importUsers)) { throw ServiceExceptionUtil.exception(USER_IMPORT_LIST_IS_EMPTY); @@ -368,20 +365,15 @@ public class SysUserServiceImpl implements SysUserService { } @Override - public int updateAvatar(Long id, MultipartFile avatarFile) { + public void updateAvatar(Long id, InputStream avatarFile) { this.checkUserExists(id); // 存储文件 - String avatar = null; - try { - avatar = fileService.createFile(avatarFile.getOriginalFilename(), IoUtil.readBytes(avatarFile.getInputStream())); - } catch (IOException e) { - throw ServiceExceptionUtil.exception(FILE_UPLOAD_FAILED); - } + String avatar = fileService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile)); // 更新路径 SysUserDO sysUserDO = new SysUserDO(); sysUserDO.setId(id); sysUserDO.setAvatar(avatar); - return userMapper.updateById(sysUserDO); + userMapper.updateById(sysUserDO); } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java index 6b2b5f9f7..5b746f6fd 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java @@ -109,7 +109,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public List createCodegenListFromDB(List tableNames) { List ids = new ArrayList<>(tableNames.size()); // 遍历添加。虽然效率会低一点,但是没必要做成完全批量,因为不会这么大量 @@ -118,7 +118,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateCodegen(ToolCodegenUpdateReqVO updateReqVO) { // 校验是否已经存在 if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { @@ -134,7 +134,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void syncCodegenFromDB(Long tableId) { // 校验是否已经存在 ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); @@ -149,7 +149,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void syncCodegenFromSQL(Long tableId, String sql) { // 校验是否已经存在 ToolCodegenTableDO table = codegenTableMapper.selectById(tableId); @@ -201,7 +201,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void deleteCodegen(Long tableId) { // 校验是否已经存在 if (codegenTableMapper.selectById(tableId) == null) { diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index c9c40e739..b0a96fb04 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -145,7 +145,7 @@ yudao: swagger: title: 管理后台 description: 提供管理员管理的所有功能 - version: ${yudao.info.base-package} + version: ${yudao.info.version} base-package: ${yudao.info.base-package}.modules captcha: timeout: 5m diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index 500eb7b51..fdb260758 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -145,7 +145,7 @@ yudao: swagger: title: 管理后台 description: 提供管理员管理的所有功能 - version: ${yudao.info.base-package} + version: ${yudao.info.version} base-package: ${yudao.info.base-package}.modules captcha: timeout: 5m From 32620fb3a7d5dd29943227f44bb55c5906225bbe Mon Sep 17 00:00:00 2001 From: wangkai Date: Sat, 13 Mar 2021 23:20:29 +0800 Subject: [PATCH 12/14] =?UTF-8?q?infra=20logger=20=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=20(issues=20I3A9GW)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ApiAccessLogFrameworkService.java | 4 +- .../service/ApiErrorLogFrameworkService.java | 4 +- .../InfApiErrorLogExportReqVO.java | 2 +- .../apierrorlog/InfApiErrorLogPageReqVO.java | 2 +- .../dataobject/logger/InfApiAccessLogDO.java | 2 +- .../dataobject/logger/InfApiErrorLogDO.java | 4 +- .../impl/InfApiAccessLogServiceImpl.java | 8 +- .../impl/InfApiErrorLogServiceImpl.java | 9 +- .../InfApiAccessLogServiceImplTest.java | 177 +++++++++++++++ .../logger/InfApiErrorLogServiceImplTest.java | 207 ++++++++++++++++++ src/test/resources/sql/create_tables.sql | 57 +++++ 11 files changed, 463 insertions(+), 13 deletions(-) create mode 100644 src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java create mode 100644 src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java b/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java index eda202ac3..ecafe5559 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiAccessLogFrameworkService.java @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.logger.apilog.core.service; import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; import javax.validation.Valid; +import java.util.concurrent.Future; /** * API 访问日志 Framework Service 接口 @@ -15,7 +16,8 @@ public interface ApiAccessLogFrameworkService { * 创建 API 访问日志 * * @param createDTO 创建信息 + * @return 是否创建成功 */ - void createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO); + Future createApiAccessLogAsync(@Valid ApiAccessLogCreateDTO createDTO); } diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java b/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java index 032ef40e1..763db3a12 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/apilog/core/service/ApiErrorLogFrameworkService.java @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.logger.apilog.core.service; import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; import javax.validation.Valid; +import java.util.concurrent.Future; /** * API 错误日志 Framework Service 接口 @@ -15,7 +16,8 @@ public interface ApiErrorLogFrameworkService { * 创建 API 错误日志 * * @param createDTO 创建信息 + * @return 是否创建成功 */ - void createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO); + Future createApiErrorLogAsync(@Valid ApiErrorLogCreateDTO createDTO); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java index a5bc820c2..991987d0e 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogExportReqVO.java @@ -14,7 +14,7 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU public class InfApiErrorLogExportReqVO { @ApiModelProperty(value = "用户编号", example = "666") - private Integer userId; + private Long userId; @ApiModelProperty(value = "用户类型", example = "1") private Integer userType; diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java index 26f32411b..c966ab068 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/logger/vo/apierrorlog/InfApiErrorLogPageReqVO.java @@ -19,7 +19,7 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU public class InfApiErrorLogPageReqVO extends PageParam { @ApiModelProperty(value = "用户编号", example = "666") - private Integer userId; + private Long userId; @ApiModelProperty(value = "用户类型", example = "1") private Integer userType; diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java index 2a4d2cf19..ff32cea16 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java @@ -37,7 +37,7 @@ public class InfApiAccessLogDO extends BaseDO { /** * 用户编号 */ - private Integer userId; + private Long userId; /** * 用户类型 * diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java index 855c70315..dbe326cb7 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java @@ -30,7 +30,7 @@ public class InfApiErrorLogDO extends BaseDO { /** * 用户编号 */ - private Integer userId; + private Long userId; /** * 链路追踪编号 * @@ -148,6 +148,6 @@ public class InfApiErrorLogDO extends BaseDO { * * 关联 {@link SysUserDO#getId()} */ - private Integer processUserId; + private Long processUserId; } diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java index f0d20aec4..7ed83d9e1 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java @@ -9,12 +9,13 @@ import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogD import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiAccessLogMapper; import cn.iocoder.dashboard.modules.infra.service.logger.InfApiAccessLogService; import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import javax.validation.Valid; import java.util.List; +import java.util.concurrent.Future; /** * API 访问日志 Service 实现类 @@ -30,10 +31,11 @@ public class InfApiAccessLogServiceImpl implements InfApiAccessLogService { @Override @Async - public void createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) { + public Future createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) { // 插入 InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO); - apiAccessLogMapper.insert(apiAccessLog); + int insert = apiAccessLogMapper.insert(apiAccessLog); + return new AsyncResult<>(insert == 1); } @Override diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java index c6a8418e4..647c0621b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java @@ -10,12 +10,14 @@ import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiErrorLogMapper; import cn.iocoder.dashboard.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; import cn.iocoder.dashboard.modules.infra.service.logger.InfApiErrorLogService; import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Date; import java.util.List; +import java.util.concurrent.Future; import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; @@ -35,10 +37,11 @@ public class InfApiErrorLogServiceImpl implements InfApiErrorLogService { @Override @Async - public void createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) { + public Future createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) { InfApiErrorLogDO apiErrorLog = InfApiErrorLogConvert.INSTANCE.convert(createDTO); apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus()); - apiErrorLogMapper.insert(apiErrorLog); + int insert = apiErrorLogMapper.insert(apiErrorLog); + return new AsyncResult<>(insert == 1); } @Override @@ -62,7 +65,7 @@ public class InfApiErrorLogServiceImpl implements InfApiErrorLogService { } // 标记处理 apiErrorLogMapper.updateById(InfApiErrorLogDO.builder().id(id).processStatus(processStatus) - .processUserId(processStatus).processTime(new Date()).build()); + .processUserId(processUserId).processTime(new Date()).build()); } } diff --git a/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java new file mode 100644 index 000000000..51b57fe4e --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiAccessLogServiceImplTest.java @@ -0,0 +1,177 @@ +package cn.iocoder.dashboard.modules.infra.service.logger; + +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.dashboard.BaseDbUnitTest; +import cn.iocoder.dashboard.common.enums.UserTypeEnum; +import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiAccessLogCreateDTO; +import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogExportReqVO; +import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apiaccesslog.InfApiAccessLogPageReqVO; +import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiAccessLogDO; +import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiAccessLogMapper; +import cn.iocoder.dashboard.modules.infra.service.logger.impl.InfApiAccessLogServiceImpl; +import cn.iocoder.dashboard.util.RandomUtils; +import cn.iocoder.dashboard.util.object.ObjectUtils; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Future; + +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * {@link InfApiAccessLogServiceImpl} 单元测试 + */ +@Import(InfApiAccessLogServiceImpl.class) +public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfApiAccessLogService infApiAccessLogServiceImpl; + + @Resource + private InfApiAccessLogMapper infApiAccessLogMapper; + + + @Test + public void testCreateApiAccessLogAsync() throws Exception { + ApiAccessLogCreateDTO createDTO = RandomUtils.randomPojo( + ApiAccessLogCreateDTO.class, + dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue()) + ); + + // 执行service方法 + Future future = infApiAccessLogServiceImpl.createApiAccessLogAsync(createDTO); + + // 等异步执行完 + future.get(); + + InfApiAccessLogDO infApiAccessLogDO = infApiAccessLogMapper.selectOne(null); + // 断言 + assertNotNull(infApiAccessLogDO); + // 断言,忽略基本字段 + assertPojoEquals(createDTO, infApiAccessLogDO); + } + + + @Test + public void testGetApiAccessLogPage() { + // 构造测试数据 + long userId = 2233L; + int userType = UserTypeEnum.ADMIN.getValue(); + String applicationName = "ruoyi-test"; + String requestUrl = "foo"; + Date beginTime = buildTime(2021, 3, 13); + int duration = 1000; + int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode(); + + InfApiAccessLogDO infApiAccessLogDO = RandomUtils.randomPojo(InfApiAccessLogDO.class, dto -> { + dto.setUserId(userId); + dto.setUserType(userType); + dto.setApplicationName(applicationName); + dto.setRequestUrl(requestUrl); + dto.setBeginTime(beginTime); + dto.setDuration(duration); + dto.setResultCode(resultCode); + }); + infApiAccessLogMapper.insert(infApiAccessLogDO); + + // 下面几个都是不匹配的数据 + // userId 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserId(3344L))); + // userType + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); + // applicationName 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setApplicationName("test"))); + // requestUrl 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); + // 构造一个早期时间 2021-02-06 00:00:00 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); + // duration 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setDuration(100))); + // resultCode 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setResultCode(2))); + + // 构造调用参数 + InfApiAccessLogPageReqVO reqVO = new InfApiAccessLogPageReqVO(); + reqVO.setUserId(userId); + reqVO.setUserType(userType); + reqVO.setApplicationName(applicationName); + reqVO.setRequestUrl(requestUrl); + reqVO.setBeginBeginTime(buildTime(2021, 3, 12)); + reqVO.setEndBeginTime(buildTime(2021, 3, 14)); + reqVO.setDuration(duration); + reqVO.setResultCode(resultCode); + + // 调用service方法 + PageResult pageResult = infApiAccessLogServiceImpl.getApiAccessLogPage(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(infApiAccessLogDO, pageResult.getList().get(0)); + } + + @Test + public void testGetApiAccessLogList() { + // 构造测试数据 + long userId = 2233L; + int userType = UserTypeEnum.ADMIN.getValue(); + String applicationName = "ruoyi-test"; + String requestUrl = "foo"; + Date beginTime = buildTime(2021, 3, 13); + int duration = 1000; + int resultCode = GlobalErrorCodeConstants.SUCCESS.getCode(); + + InfApiAccessLogDO infApiAccessLogDO = RandomUtils.randomPojo(InfApiAccessLogDO.class, dto -> { + dto.setUserId(userId); + dto.setUserType(userType); + dto.setApplicationName(applicationName); + dto.setRequestUrl(requestUrl); + dto.setBeginTime(beginTime); + dto.setDuration(duration); + dto.setResultCode(resultCode); + }); + infApiAccessLogMapper.insert(infApiAccessLogDO); + + // 下面几个都是不匹配的数据 + // userId 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserId(3344L))); + // userType + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); + // applicationName 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setApplicationName("test"))); + // requestUrl 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar"))); + // 构造一个早期时间 2021-02-06 00:00:00 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6)))); + // duration 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setDuration(100))); + // resultCode 不同的 + infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setResultCode(2))); + + // 构造调用参数 + InfApiAccessLogExportReqVO reqVO = new InfApiAccessLogExportReqVO(); + reqVO.setUserId(userId); + reqVO.setUserType(userType); + reqVO.setApplicationName(applicationName); + reqVO.setRequestUrl(requestUrl); + reqVO.setBeginBeginTime(buildTime(2021, 3, 12)); + reqVO.setEndBeginTime(buildTime(2021, 3, 14)); + reqVO.setDuration(duration); + reqVO.setResultCode(resultCode); + + // 调用service方法 + List list = infApiAccessLogServiceImpl.getApiAccessLogList(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, list.size()); + assertPojoEquals(infApiAccessLogDO, list.get(0)); + } +} diff --git a/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java new file mode 100644 index 000000000..79a0cfde3 --- /dev/null +++ b/src/test/java/cn/iocoder/dashboard/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java @@ -0,0 +1,207 @@ +package cn.iocoder.dashboard.modules.infra.service.logger; + +import cn.hutool.core.util.RandomUtil; +import cn.iocoder.dashboard.BaseDbUnitTest; +import cn.iocoder.dashboard.common.enums.UserTypeEnum; +import cn.iocoder.dashboard.common.pojo.PageResult; +import cn.iocoder.dashboard.framework.logger.apilog.core.service.dto.ApiErrorLogCreateDTO; +import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO; +import cn.iocoder.dashboard.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO; +import cn.iocoder.dashboard.modules.infra.dal.dataobject.logger.InfApiErrorLogDO; +import cn.iocoder.dashboard.modules.infra.dal.mysql.logger.InfApiErrorLogMapper; +import cn.iocoder.dashboard.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum; +import cn.iocoder.dashboard.modules.infra.service.logger.impl.InfApiErrorLogServiceImpl; +import cn.iocoder.dashboard.util.RandomUtils; +import cn.iocoder.dashboard.util.object.ObjectUtils; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Future; + +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; +import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED; +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException; +import static cn.iocoder.dashboard.util.date.DateUtils.buildTime; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * {@link InfApiErrorLogServiceImpl} 单元测试 + */ +@Import(InfApiErrorLogServiceImpl.class) +public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfApiErrorLogService infApiErrorLogServiceImpl; + + @Resource + private InfApiErrorLogMapper infApiErrorLogMapper; + + + @Test + public void testCreateApiErrorLogAsync() throws Exception { + ApiErrorLogCreateDTO createDTO = RandomUtils.randomPojo( + ApiErrorLogCreateDTO.class, + dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue()) + ); + + // 执行service方法 + Future future = infApiErrorLogServiceImpl.createApiErrorLogAsync(createDTO); + + // 等异步执行完 + future.get(); + + InfApiErrorLogDO infApiErrorLogDO = infApiErrorLogMapper.selectOne(null); + // 断言 + assertNotNull(infApiErrorLogDO); + // 断言,忽略基本字段 + assertPojoEquals(createDTO, infApiErrorLogDO); + } + + + @Test + public void testGetApiErrorLogPage() { + // 构造测试数据 + long userId = 2233L; + int userType = UserTypeEnum.ADMIN.getValue(); + String applicationName = "ruoyi-test"; + String requestUrl = "foo"; + Date beginTime = buildTime(2021, 3, 13); + int progressStatus = InfApiErrorLogProcessStatusEnum.INIT.getStatus(); + + InfApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + logDO.setUserId(userId); + logDO.setUserType(userType); + logDO.setApplicationName(applicationName); + logDO.setRequestUrl(requestUrl); + logDO.setExceptionTime(beginTime); + logDO.setProcessStatus(progressStatus); + }); + infApiErrorLogMapper.insert(infApiErrorLogDO); + + // 下面几个都是不匹配的数据 + // userId 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserId(3344L))); + // userType + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); + // applicationName 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setApplicationName("test"))); + // requestUrl 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar"))); + // 构造一个早期时间 2021-02-06 00:00:00 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6)))); + // progressStatus 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus()))); + + // 构造调用参数 + InfApiErrorLogPageReqVO reqVO = new InfApiErrorLogPageReqVO(); + reqVO.setUserId(userId); + reqVO.setUserType(userType); + reqVO.setApplicationName(applicationName); + reqVO.setRequestUrl(requestUrl); + reqVO.setBeginExceptionTime(buildTime(2021, 3, 12)); + reqVO.setEndExceptionTime(buildTime(2021, 3, 14)); + reqVO.setProcessStatus(progressStatus); + + // 调用service方法 + PageResult pageResult = infApiErrorLogServiceImpl.getApiErrorLogPage(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(infApiErrorLogDO, pageResult.getList().get(0)); + } + + @Test + public void testGetApiErrorLogList() { + // 构造测试数据 + long userId = 2233L; + int userType = UserTypeEnum.ADMIN.getValue(); + String applicationName = "ruoyi-test"; + String requestUrl = "foo"; + Date beginTime = buildTime(2021, 3, 13); + int progressStatus = InfApiErrorLogProcessStatusEnum.INIT.getStatus(); + + InfApiErrorLogDO infApiErrorLogDO = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + logDO.setUserId(userId); + logDO.setUserType(userType); + logDO.setApplicationName(applicationName); + logDO.setRequestUrl(requestUrl); + logDO.setExceptionTime(beginTime); + logDO.setProcessStatus(progressStatus); + }); + infApiErrorLogMapper.insert(infApiErrorLogDO); + + // 下面几个都是不匹配的数据 + // userId 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserId(3344L))); + // userType + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue()))); + // applicationName 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setApplicationName("test"))); + // requestUrl 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar"))); + // 构造一个早期时间 2021-02-06 00:00:00 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6)))); + // progressStatus 不同的 + infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus()))); + + // 构造调用参数 + InfApiErrorLogExportReqVO reqVO = new InfApiErrorLogExportReqVO(); + reqVO.setUserId(userId); + reqVO.setUserType(userType); + reqVO.setApplicationName(applicationName); + reqVO.setRequestUrl(requestUrl); + reqVO.setBeginExceptionTime(buildTime(2021, 3, 12)); + reqVO.setEndExceptionTime(buildTime(2021, 3, 14)); + reqVO.setProcessStatus(progressStatus); + + // 调用service方法 + List list = infApiErrorLogServiceImpl.getApiErrorLogList(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, list.size()); + assertPojoEquals(infApiErrorLogDO, list.get(0)); + } + + + @Test + public void testUpdateApiErrorLogProcess() { + // 先构造两条数据,第一条用于抛出异常,第二条用于正常的执行update操作 + Long processUserId = 2233L; + + InfApiErrorLogDO first = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + logDO.setProcessUserId(processUserId); + logDO.setUserType(UserTypeEnum.ADMIN.getValue()); + logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus()); + }); + infApiErrorLogMapper.insert(first); + + InfApiErrorLogDO second = RandomUtils.randomPojo(InfApiErrorLogDO.class, logDO -> { + logDO.setProcessUserId(1122L); + logDO.setUserType(UserTypeEnum.ADMIN.getValue()); + logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus()); + }); + infApiErrorLogMapper.insert(second); + + Long firstId = first.getId(); + Long secondId = second.getId(); + + // 执行正常的 update 操作 + infApiErrorLogServiceImpl.updateApiErrorLogProcess(secondId, InfApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId); + InfApiErrorLogDO secondSelect = infApiErrorLogMapper.selectOne("id", secondId); + + // id 为 0 查询不到,应该抛出异常 API_ERROR_LOG_NOT_FOUND + assertServiceException(() -> infApiErrorLogServiceImpl.updateApiErrorLogProcess(0L, InfApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId), API_ERROR_LOG_NOT_FOUND); + // id 为 first 的 progressStatus 为 DONE ,应该抛出 API_ERROR_LOG_PROCESSED + assertServiceException(() -> infApiErrorLogServiceImpl.updateApiErrorLogProcess(firstId, InfApiErrorLogProcessStatusEnum.DONE.getStatus(), processUserId), API_ERROR_LOG_PROCESSED); + // 验证 progressStatus 是否修改成功 + assertEquals(InfApiErrorLogProcessStatusEnum.DONE.getStatus(), secondSelect.getProcessStatus()); + // 验证 progressUserId 是否修改成功 + assertEquals(processUserId, secondSelect.getProcessUserId()); + } +} diff --git a/src/test/resources/sql/create_tables.sql b/src/test/resources/sql/create_tables.sql index 4a9d218b9..26c588717 100644 --- a/src/test/resources/sql/create_tables.sql +++ b/src/test/resources/sql/create_tables.sql @@ -241,3 +241,60 @@ create table IF NOT EXISTS "sys_user" ( "deleted" bit not null default false, primary key ("id") ) comment '用户信息表'; + + +create table "inf_api_access_log" ( + "id" bigint not null GENERATED BY DEFAULT AS IDENTITY, + "trace_id" varchar(64) not null default '', + "user_id" bigint not null default '0', + "user_type" tinyint not null default '0', + "application_name" varchar(50) not null, + "request_method" varchar(16) not null default '', + "request_url" varchar(255) not null default '', + "request_params" varchar(8000) not null default '', + "user_ip" varchar(50) not null, + "user_agent" varchar(512) not null, + "begin_time" timestamp not null, + "end_time" timestamp not null, + "duration" integer not null, + "result_code" integer not null default '0', + "result_msg" varchar(512) default '', + "creator" varchar(64) default '', + "create_time" timestamp not null default current_timestamp, + "updater" varchar(64) default '', + "update_time" timestamp not null default current_timestamp, + "deleted" bit not null default false, + primary key ("id") +) comment 'API 访问日志表'; + + +create table "inf_api_error_log" ( + "id" integer not null GENERATED BY DEFAULT AS IDENTITY, + "trace_id" varchar(64) not null, + "user_id" bigint not null default '0', + "user_type" tinyint not null default '0', + "application_name" varchar(50) not null, + "request_method" varchar(16) not null, + "request_url" varchar(255) not null, + "request_params" varchar(8000) not null, + "user_ip" varchar(50) not null, + "user_agent" varchar(512) not null, + "exception_time" timestamp not null, + "exception_name" varchar(128) not null default '', + "exception_message" clob not null, + "exception_root_cause_message" clob not null, + "exception_stack_trace" clob not null, + "exception_class_name" varchar(512) not null, + "exception_file_name" varchar(512) not null, + "exception_method_name" varchar(512) not null, + "exception_line_number" integer not null, + "process_status" tinyint not null, + "process_time" timestamp default null, + "process_user_id" bigint default '0', + "creator" varchar(64) default '', + "create_time" timestamp not null default current_timestamp, + "updater" varchar(64) default '', + "update_time" timestamp not null default current_timestamp, + "deleted" bit not null default false, + primary key ("id") +) comment '系统异常日志'; \ No newline at end of file From 6e7f8f570de3700cd3826fdcf9f8a6fb9540913a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 14 Mar 2021 00:02:23 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=85=A8=E5=B1=80=20lo?= =?UTF-8?q?mbok=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lombok.config | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 lombok.config diff --git a/lombok.config b/lombok.config new file mode 100644 index 000000000..c6488faea --- /dev/null +++ b/lombok.config @@ -0,0 +1,4 @@ +config.stopBubbling = true +lombok.tostring.callsuper=true +lombok.equalsandhashcode.callsuper=true +lombok.accessors.chain=true From 2fcb54b57661a935cbe650610e31929e4af9dbfd Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 14 Mar 2021 00:58:39 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E6=96=87=E6=A1=A3=E7=9A=84=20html=E3=80=81word?= =?UTF-8?q?=E3=80=81markdown=20=E7=9A=84=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-ui/src/api/infra/dbDoc.js | 16 +++++++ ruoyi-ui/src/main.js | 8 +++- ruoyi-ui/src/utils/ruoyi.js | 15 +++++++ ruoyi-ui/src/views/tool/dbDoc/index.vue | 42 ++++++++++++++++--- .../controller/doc/InfDbDocController.java | 20 +++------ 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/ruoyi-ui/src/api/infra/dbDoc.js b/ruoyi-ui/src/api/infra/dbDoc.js index de54981d1..015c6d71d 100644 --- a/ruoyi-ui/src/api/infra/dbDoc.js +++ b/ruoyi-ui/src/api/infra/dbDoc.js @@ -8,3 +8,19 @@ export function exportHtml() { responseType: 'blob' }) } + +export function exportWord() { + return request({ + url: '/infra/db-doc/export-word', + method: 'get', + responseType: 'blob' + }) +} + +export function exportMarkdown() { + return request({ + url: '/infra/db-doc/export-markdown', + method: 'get', + responseType: 'blob' + }) +} diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js index 91556bf68..e1f067fa1 100644 --- a/ruoyi-ui/src/main.js +++ b/ruoyi-ui/src/main.js @@ -25,7 +25,10 @@ import { download, handleTree, downloadExcel, - downloadZip + downloadWord, + downloadZip, + downloadHtml, + downloadMarkdown, } from "@/utils/ruoyi"; import Pagination from "@/components/Pagination"; // 自定义表格工具扩展 @@ -48,6 +51,9 @@ Vue.prototype.getDictDataLabel = getDictDataLabel Vue.prototype.DICT_TYPE = DICT_TYPE Vue.prototype.download = download Vue.prototype.downloadExcel = downloadExcel +Vue.prototype.downloadWord = downloadWord +Vue.prototype.downloadHtml = downloadHtml +Vue.prototype.downloadMarkdown = downloadMarkdown Vue.prototype.downloadZip = downloadZip Vue.prototype.handleTree = handleTree diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js index 17f235f22..82f8aecc5 100644 --- a/ruoyi-ui/src/utils/ruoyi.js +++ b/ruoyi-ui/src/utils/ruoyi.js @@ -120,11 +120,26 @@ export function downloadExcel(data, fileName) { download0(data, fileName, 'application/vnd.ms-excel'); } +// 下载 Word 方法 +export function downloadWord(data, fileName) { + download0(data, fileName, 'application/msword'); +} + // 下载 Zip 方法 export function downloadZip(data, fileName) { download0(data, fileName, 'application/zip'); } +// 下载 Html 方法 +export function downloadHtml(data, fileName) { + download0(data, fileName, 'text/html'); +} + +// 下载 Markdown 方法 +export function downloadMarkdown(data, fileName) { + download0(data, fileName, 'text/markdown'); +} + function download0(data, fileName, mineType) { // 创建 blob let blob = new Blob([data], {type: mineType}); diff --git a/ruoyi-ui/src/views/tool/dbDoc/index.vue b/ruoyi-ui/src/views/tool/dbDoc/index.vue index e0c71564b..274d1372e 100644 --- a/ruoyi-ui/src/views/tool/dbDoc/index.vue +++ b/ruoyi-ui/src/views/tool/dbDoc/index.vue @@ -1,10 +1,21 @@