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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
literal 0
HcmV?d00001