From 0bbc0b5cd2942a6da189960c077aea11c0bf0757 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Fri, 4 Oct 2024 16:48:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=96=B0=E5=A2=9E):=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81=EF=BC=8C=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../generator/AdminCodeGenerator.java | 2 +- .../cn/bunny/dao/dto/i18n/I18nUpdateDto.java | 3 +- .../dao/dto/system/files/FileUploadDto.java | 23 +++++ .../dto/system/user/AdminUserUpdateDto.java | 13 +-- .../user/UserUpdateWithPasswordDto.java | 28 ++++++ .../bunny/dao/pojo/result/ResultCodeEnum.java | 3 + .../bunny/dao/vo/system/files/FileInfoVo.java | 36 ++++++++ .../java/cn/bunny/services/Bunny/Files.java | 41 +++++++++ .../services/controller/FilesController.java | 35 +++++++ .../services/controller/UserController.java | 12 ++- .../controller/UserDeptController.java | 2 + .../cn/bunny/services/mapper/FilesMapper.java | 18 ++++ .../bunny/services/service/FilesService.java | 25 +++++ .../bunny/services/service/UserService.java | 12 ++- .../service/impl/FilesServiceImpl.java | 86 ++++++++++++++++++ .../service/impl/UserServiceImpl.java | 62 +++++++++++-- service/src/main/resources/application.yml | 3 + .../src/main/resources/mapper/FilesMapper.xml | 25 +++++ .../src/main/resources/mapper/UserMapper.xml | 1 - service/src/main/resources/static/user.jpg | Bin 0 -> 29603 bytes 20 files changed, 405 insertions(+), 25 deletions(-) create mode 100644 dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java create mode 100644 dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithPasswordDto.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java create mode 100644 service/src/main/java/cn/bunny/services/Bunny/Files.java create mode 100644 service/src/main/java/cn/bunny/services/controller/FilesController.java create mode 100644 service/src/main/java/cn/bunny/services/mapper/FilesMapper.java create mode 100644 service/src/main/java/cn/bunny/services/service/FilesService.java create mode 100644 service/src/main/java/cn/bunny/services/service/impl/FilesServiceImpl.java create mode 100644 service/src/main/resources/mapper/FilesMapper.xml create mode 100644 service/src/main/resources/static/user.jpg diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java b/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java index 6fc4758..c3de48f 100644 --- a/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java @@ -20,7 +20,7 @@ public class AdminCodeGenerator { public static final String entity = "Bunny"; public static void main(String[] args) { - Generation("sys_dept", "sys_user_dept"); + Generation("sys_files"); } /** diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java index 0cfa3ef..0d8b875 100644 --- a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java @@ -2,6 +2,7 @@ package cn.bunny.dao.dto.i18n; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -15,7 +16,7 @@ import lombok.NoArgsConstructor; public class I18nUpdateDto { @Schema(name = "id", title = "主键") - @NotBlank(message = "id不能为空") + @NotNull(message = "id不能为空") private Long id; @Schema(name = "keyName", title = "多语言key") diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java new file mode 100644 index 0000000..8aaed7b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java @@ -0,0 +1,23 @@ +package cn.bunny.dao.dto.system.files; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FileUploadDto对象", title = "文件上传", description = "文件上传管理") +public class FileUploadDto { + + @Schema(name = "file", title = "文件") + MultipartFile file; + + @Schema(name = "type", title = "文件类型") + String type; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java index 37c6f85..bad7ae5 100644 --- a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java @@ -2,6 +2,7 @@ package cn.bunny.dao.dto.system.user; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -14,6 +15,10 @@ import lombok.NoArgsConstructor; @Schema(name = "AdminUserUpdateDto对象", title = "用户", description = "用户管理") public class AdminUserUpdateDto { + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + @Schema(name = "username", title = "用户名") @NotBlank(message = "用户名不能为空") private String username; @@ -29,20 +34,16 @@ public class AdminUserUpdateDto { @Schema(name = "phone", title = "手机号") private String phone; - @Schema(name = "password", title = "密码") - @NotBlank(message = "密码不能为空") - private String password; - @Schema(name = "avatar", title = "头像") private String avatar; @Schema(name = "sex", title = "性别", description = "0:女 1:男") - private Byte sex = 1; + private Byte sex; @Schema(name = "summary", title = "个人描述") private String summary; @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") - private Boolean status = false; + private Boolean status; } \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithPasswordDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithPasswordDto.java new file mode 100644 index 0000000..5167116 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithPasswordDto.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserUpdateWithPasswordDto对象", title = "管理员用户修改密码", description = "管理员用户修改密码") +public class UserUpdateWithPasswordDto { + + @Schema(name = "userId", title = "用户ID") + @NotNull(message = "用户ID不能为空") + private Long userId; + + @Schema(name = "password", title = "用户密码") + @NotBlank(message = "密码不能为空") + @NotEmpty + private String password; + +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java b/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java index bba2d02..7553a9e 100644 --- a/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java +++ b/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java @@ -32,6 +32,9 @@ public enum ResultCodeEnum { DATA_EXIST(201, "数据已存在"), DATA_NOT_EXIST(201, "数据不存在"), REQUEST_IS_EMPTY(201, "请求数据为空"), + DATA_TOO_LARGE(201, "请求数据为空"), + USER_IS_EMPTY(201, "用户不存在"), + UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD(201, "新密码与密码相同"), // 数据相关 206 ILLEGAL_REQUEST(206, "非法请求"), diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java new file mode 100644 index 0000000..4794bde --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java @@ -0,0 +1,36 @@ +package cn.bunny.dao.vo.system.files; + +import cn.bunny.dao.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +/** + * 返回文件信息 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FileInfoVo对象", title = "管理端返回文件信息", description = "管理端返回文件信息") +public class FileInfoVo extends BaseVo { + + @Schema(name = "url", title = "文件的路径") + private String url; + + @Schema(name = "filename", title = "文件的名称") + private String filename; + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + private String filepath; + + @Schema(name = "fileSize", title = "文件的大小,以字节为单位") + private Long fileSize; + + @Schema(name = "size", title = "文件大小") + private String size; + + @Schema(name = "fileType", title = "文件的MIME类型") + private String fileType; + +} diff --git a/service/src/main/java/cn/bunny/services/Bunny/Files.java b/service/src/main/java/cn/bunny/services/Bunny/Files.java new file mode 100644 index 0000000..f5ef409 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/Bunny/Files.java @@ -0,0 +1,41 @@ +package cn.bunny.services.Bunny; + +import cn.bunny.dao.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 系统文件表 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_files") +@ApiModel(value = "Files对象", description = "系统文件表") +public class Files extends BaseEntity { + + @Schema(name = "filename", title = "文件的名称") + private String filename; + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + private String filepath; + + @Schema(name = "fileSize", title = "文件的大小,以字节为单位") + private Long fileSize; + + @Schema(name = "fileType", title = "文件的MIME类型") + private String fileType; + + @Schema(name = "downloadCount", title = "下载数量") + private Integer downloadCount; + +} diff --git a/service/src/main/java/cn/bunny/services/controller/FilesController.java b/service/src/main/java/cn/bunny/services/controller/FilesController.java new file mode 100644 index 0000000..93f08c0 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/FilesController.java @@ -0,0 +1,35 @@ +package cn.bunny.services.controller; + +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.services.service.FilesService; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + *

+ * 系统文件表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@RestController +@RequestMapping("admin/files") +public class FilesController { + + @Autowired + private FilesService filesService; + + @Operation(summary = "上传文件", description = "上传文件") + @PostMapping("upload") + public Result upload(FileUploadDto dto) { + FileInfoVo vo = filesService.upload(dto); + return Result.success(vo, ResultCodeEnum.SUCCESS_UPLOAD); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/UserController.java b/service/src/main/java/cn/bunny/services/controller/UserController.java index 4e6efe8..4b56fef 100644 --- a/service/src/main/java/cn/bunny/services/controller/UserController.java +++ b/service/src/main/java/cn/bunny/services/controller/UserController.java @@ -1,9 +1,6 @@ package cn.bunny.services.controller; -import cn.bunny.dao.dto.system.user.AdminUserAddDto; -import cn.bunny.dao.dto.system.user.AdminUserDto; -import cn.bunny.dao.dto.system.user.AdminUserUpdateDto; -import cn.bunny.dao.dto.system.user.RefreshTokenDto; +import cn.bunny.dao.dto.system.user.*; import cn.bunny.dao.entity.system.AdminUser; import cn.bunny.dao.pojo.result.PageResult; import cn.bunny.dao.pojo.result.Result; @@ -66,6 +63,13 @@ public class UserController { return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); } + @Operation(summary = "管理员修改管理员用户密码", description = "管理员修改管理员用户密码") + @PutMapping("updateUserPasswordByAdmin") + public Result updateUserPasswordByAdmin(@Valid @RequestBody UserUpdateWithPasswordDto dto) { + userService.updateUserPasswordByAdmin(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + @Operation(summary = "登录发送邮件验证码", description = "登录发送邮件验证码") @PostMapping("noAuth/sendLoginEmail") public Result sendLoginEmail(String email) { diff --git a/service/src/main/java/cn/bunny/services/controller/UserDeptController.java b/service/src/main/java/cn/bunny/services/controller/UserDeptController.java index 9692d79..c27d8b4 100644 --- a/service/src/main/java/cn/bunny/services/controller/UserDeptController.java +++ b/service/src/main/java/cn/bunny/services/controller/UserDeptController.java @@ -1,5 +1,6 @@ package cn.bunny.services.controller; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController; * @author Bunny * @since 2024-10-04 */ +@Tag(name = "用户和部门", description = "用户和部门相关接口") @RestController @RequestMapping("admin/userDept") public class UserDeptController { diff --git a/service/src/main/java/cn/bunny/services/mapper/FilesMapper.java b/service/src/main/java/cn/bunny/services/mapper/FilesMapper.java new file mode 100644 index 0000000..bdab061 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/FilesMapper.java @@ -0,0 +1,18 @@ +package cn.bunny.services.mapper; + +import cn.bunny.services.Bunny.Files; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 系统文件表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Mapper +public interface FilesMapper extends BaseMapper { + +} diff --git a/service/src/main/java/cn/bunny/services/service/FilesService.java b/service/src/main/java/cn/bunny/services/service/FilesService.java new file mode 100644 index 0000000..096e4ea --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/FilesService.java @@ -0,0 +1,25 @@ +package cn.bunny.services.service; + +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.services.Bunny.Files; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 系统文件表 服务类 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +public interface FilesService extends IService { + + /** + * * 上传文件 + * + * @param dto 文件上传 + * @return 管理端返回文件信息 + */ + FileInfoVo upload(FileUploadDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/service/UserService.java b/service/src/main/java/cn/bunny/services/service/UserService.java index 18a6d20..569138d 100644 --- a/service/src/main/java/cn/bunny/services/service/UserService.java +++ b/service/src/main/java/cn/bunny/services/service/UserService.java @@ -1,9 +1,6 @@ package cn.bunny.services.service; -import cn.bunny.dao.dto.system.user.AdminUserAddDto; -import cn.bunny.dao.dto.system.user.AdminUserDto; -import cn.bunny.dao.dto.system.user.AdminUserUpdateDto; -import cn.bunny.dao.dto.system.user.RefreshTokenDto; +import cn.bunny.dao.dto.system.user.*; import cn.bunny.dao.entity.system.AdminUser; import cn.bunny.dao.pojo.result.PageResult; import cn.bunny.dao.vo.system.user.AdminUserVo; @@ -82,4 +79,11 @@ public interface UserService extends IService { * @return 用户信息 */ UserVo getUserinfoById(Long id); + + /** + * * 管理员修改管理员用户密码 + * + * @param dto 管理员用户修改密码 + */ + void updateUserPasswordByAdmin(UserUpdateWithPasswordDto dto); } diff --git a/service/src/main/java/cn/bunny/services/service/impl/FilesServiceImpl.java b/service/src/main/java/cn/bunny/services/service/impl/FilesServiceImpl.java new file mode 100644 index 0000000..32ab581 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/impl/FilesServiceImpl.java @@ -0,0 +1,86 @@ +package cn.bunny.services.service.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.common.service.utils.FileUtil; +import cn.bunny.common.service.utils.minio.MinioUtil; +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.pojo.common.MinioFIlePath; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.services.Bunny.Files; +import cn.bunny.services.mapper.FilesMapper; +import cn.bunny.services.service.FilesService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * 系统文件表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Service +public class FilesServiceImpl extends ServiceImpl implements FilesService { + + @Autowired + private MinioUtil minioUtil; + + @Value("${spring.servlet.multipart.max-file-size}") + private String maxFileSize; + + /** + * * 上传文件 + * + * @param dto 文件上传 + * @return 管理端返回文件信息 + */ + @SneakyThrows + @Override + public FileInfoVo upload(FileUploadDto dto) { + MultipartFile file = dto.getFile(); + String type = dto.getType(); + + // 管理员Id + Long userId = BaseContext.getUserId(); + // 文件大小 + long fileSize = file.getSize(); + // 文件类型 + String contentType = file.getContentType(); + // 文件名 + String filename = file.getOriginalFilename(); + + // 上传文件 + MinioFIlePath minioFIlePath = minioUtil.getUploadMinioObjectFilePath(file, type); + String bucketNameFilepath = minioFIlePath.getBucketNameFilepath(); + + // 盘读研数据是否过大 + String mb = maxFileSize.replace("MB", ""); + if (fileSize / 1024 / 1024 > Long.parseLong(mb)) throw new BunnyException(ResultCodeEnum.DATA_TOO_LARGE); + + // 插入文件信息 + Files adminFiles = new Files(); + adminFiles.setFileSize(fileSize); + adminFiles.setFileType(contentType); + adminFiles.setFilename(filename); + adminFiles.setFilepath(bucketNameFilepath); + adminFiles.setCreateUser(userId); + save(adminFiles); + + // 返回信息内容化 + return FileInfoVo.builder() + .size(FileUtil.getSize(fileSize)) + .filepath(bucketNameFilepath) + .fileSize(fileSize) + .fileType(contentType) + .filename(filename) + .url(minioUtil.getObjectNameFullPath(bucketNameFilepath)) + .build(); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java b/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java index 2596020..2540a6b 100644 --- a/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java +++ b/service/src/main/java/cn/bunny/services/service/impl/UserServiceImpl.java @@ -4,10 +4,7 @@ import cn.bunny.common.service.context.BaseContext; import cn.bunny.common.service.exception.BunnyException; import cn.bunny.common.service.utils.JwtHelper; import cn.bunny.common.service.utils.minio.MinioUtil; -import cn.bunny.dao.dto.system.user.AdminUserAddDto; -import cn.bunny.dao.dto.system.user.AdminUserDto; -import cn.bunny.dao.dto.system.user.AdminUserUpdateDto; -import cn.bunny.dao.dto.system.user.RefreshTokenDto; +import cn.bunny.dao.dto.system.user.*; import cn.bunny.dao.entity.system.AdminUser; import cn.bunny.dao.entity.system.EmailUsers; import cn.bunny.dao.pojo.common.EmailSendInit; @@ -34,6 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.DigestUtils; import org.springframework.util.StringUtils; import java.util.List; @@ -60,6 +58,7 @@ public class UserServiceImpl extends ServiceImpl implemen @Autowired private EmailFactory emailFactory; + @Autowired private MinioUtil minioUtil; @@ -135,6 +134,37 @@ public class UserServiceImpl extends ServiceImpl implemen return userVo; } + /** + * * 管理员修改管理员用户密码 + * + * @param dto 管理员用户修改密码 + */ + @Override + public void updateUserPasswordByAdmin(UserUpdateWithPasswordDto dto) { + Long userId = dto.getUserId(); + String password = dto.getPassword(); + + // 对密码加密 + String md5Password = DigestUtils.md5DigestAsHex(password.getBytes()); + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + + // 判断是否存在这个用户 + if (adminUser == null) { + throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY); + } + + // 判断新密码是否与旧密码相同 + if (adminUser.getPassword().equals(md5Password)) { + throw new BunnyException(ResultCodeEnum.UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD); + } + + // 更新用户密码 + adminUser = new AdminUser(); + adminUser.setPassword(md5Password); + adminUser.setId(userId); + updateById(adminUser); + } + /** * * 用户信息 服务实现类 * @@ -148,9 +178,16 @@ public class UserServiceImpl extends ServiceImpl implemen IPage page = baseMapper.selectListByPage(pageParams, dto); List voList = page.getRecords().stream().map(AdminUser -> { - AdminUserVo AdminUserVo = new AdminUserVo(); - BeanUtils.copyProperties(AdminUser, AdminUserVo); - return AdminUserVo; + // 如果存在用户头像,则设置用户头像 + String avatar = AdminUser.getAvatar(); + if (StringUtils.hasText(avatar)) { + avatar = minioUtil.getObjectNameFullPath(avatar); + } + + AdminUserVo adminUserVo = new AdminUserVo(); + BeanUtils.copyProperties(AdminUser, adminUserVo); + adminUserVo.setAvatar(avatar); + return adminUserVo; }).toList(); return PageResult.builder() @@ -168,9 +205,19 @@ public class UserServiceImpl extends ServiceImpl implemen */ @Override public void addAdminUser(@Valid AdminUserAddDto dto) { + // 对密码加密 + String password = dto.getPassword(); + // 保存数据 AdminUser adminUser = new AdminUser(); BeanUtils.copyProperties(dto, adminUser); + + // 对密码加密 + if (StringUtils.hasText(password)) { + password = DigestUtils.md5DigestAsHex(password.getBytes()); + adminUser.setPassword(password); + } + save(adminUser); } @@ -181,7 +228,6 @@ public class UserServiceImpl extends ServiceImpl implemen */ @Override public void updateAdminUser(@Valid AdminUserUpdateDto dto) { - // 更新内容 AdminUser adminUser = new AdminUser(); BeanUtils.copyProperties(dto, adminUser); updateById(adminUser); diff --git a/service/src/main/resources/application.yml b/service/src/main/resources/application.yml index 6efc37c..96a5dfe 100644 --- a/service/src/main/resources/application.yml +++ b/service/src/main/resources/application.yml @@ -6,6 +6,9 @@ spring: active: @profiles.active@ application: name: bunny-service + servlet: + multipart: + max-file-size: 6MB datasource: # type: com.zaxxer.hikari.HikariDataSource diff --git a/service/src/main/resources/mapper/FilesMapper.xml b/service/src/main/resources/mapper/FilesMapper.xml new file mode 100644 index 0000000..1e03719 --- /dev/null +++ b/service/src/main/resources/mapper/FilesMapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + id, filename, filepath, file_size, file_type, download_count, create_user, update_time, update_user, create_time, is_deleted + + + diff --git a/service/src/main/resources/mapper/UserMapper.xml b/service/src/main/resources/mapper/UserMapper.xml index fbfde89..283eca2 100644 --- a/service/src/main/resources/mapper/UserMapper.xml +++ b/service/src/main/resources/mapper/UserMapper.xml @@ -56,7 +56,6 @@ status = #{dto.status} - order by update_time diff --git a/service/src/main/resources/static/user.jpg b/service/src/main/resources/static/user.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4cb471fbfa21858d257f7121370113492de9537a GIT binary patch literal 29603 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�zMhfYsi zAP>xsUJTody-JC?Mn66}6jS}6U(qmaHM$3+)br%g=UCPXdN`alk_J|%n&ILP(|@P2#~ih2*TU9N@e+XM^We*gk)dlk#M*u>i_#r?~!w{Aoar<22Ll()c=)bg=Gs@T#v wXaF=jg{!&ZbCac&{p3&$^qR_ZuBE9y%hO|CI27Rd7_sZ&#kNfwnESE)-^1N?nE(I) literal 0 HcmV?d00001