feat(personal-center): 个人头像更新
This commit is contained in:
@@ -60,6 +60,10 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode USER_MANAGEMENT_RELATION_NOT_FOUND = new ErrorCode(1_002_003_100, "用户管理链路不存在");
|
||||
ErrorCode USER_MANAGEMENT_RELATION_MANAGER_EXISTS = new ErrorCode(1_002_003_101, "该用户已有直属上级,不能重复添加");
|
||||
ErrorCode USER_MANAGEMENT_RELATION_EXISTS = new ErrorCode(1_002_003_102, "该用户在管理链路中还在使用,不可删除!");
|
||||
ErrorCode USER_AVATAR_SUFFIX_ERROR = new ErrorCode(1_002_003_103, "头像文件格式错误");
|
||||
ErrorCode USER_AVATAR_SIZE_ERROR = new ErrorCode(1_002_003_104, "头像文件大小不能超过 5M");
|
||||
ErrorCode USER_AVATAR_UPLOAD_FAILED = new ErrorCode(1_002_003_105, "头像上传失败");
|
||||
|
||||
|
||||
// ========== 部门模块 1-002-004-000 ==========
|
||||
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.njcn.rdms.module.system.controller.admin.user;
|
||||
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.encrypt.core.annotation.ApiEncrypt;
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||
@@ -9,6 +9,7 @@ import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileU
|
||||
import com.njcn.rdms.module.system.convert.user.UserConvert;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.dept.PostDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.file.FileDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.permission.RoleDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.njcn.rdms.module.system.service.dept.DeptService;
|
||||
@@ -22,11 +23,8 @@ import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -84,4 +82,12 @@ public class UserProfileController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-avatar")
|
||||
@Operation(summary = "修改用户个人头像")
|
||||
public CommonResult<FileDO> updateUserAvatar(@RequestParam("file") MultipartFile file) {
|
||||
// 获得用户基本信息
|
||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||
FileDO fileDO = userService.uploadAvatar(file, user);
|
||||
return success(fileDO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,12 @@ import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportExcel
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportRespVO;
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserPageReqVO;
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.file.FileDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 后台用户 Service 接口
|
||||
@@ -52,7 +50,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 更新用户的最后登录信息
|
||||
*
|
||||
* @param id 用户编号
|
||||
* @param id 用户编号
|
||||
* @param loginIp 登录 IP
|
||||
*/
|
||||
void updateUserLogin(Long id, String loginIp);
|
||||
@@ -60,7 +58,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 修改用户个人信息
|
||||
*
|
||||
* @param id 用户编号
|
||||
* @param id 用户编号
|
||||
* @param reqVO 用户个人信息
|
||||
*/
|
||||
void updateUserProfile(Long id, @Valid UserProfileUpdateReqVO reqVO);
|
||||
@@ -68,7 +66,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 修改用户个人密码
|
||||
*
|
||||
* @param id 用户编号
|
||||
* @param id 用户编号
|
||||
* @param reqVO 更新用户个人密码
|
||||
*/
|
||||
void updateUserPassword(Long id, @Valid UserProfileUpdatePasswordReqVO reqVO);
|
||||
@@ -76,7 +74,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 修改密码
|
||||
*
|
||||
* @param id 用户编号
|
||||
* @param id 用户编号
|
||||
* @param password 密码
|
||||
*/
|
||||
void updateUserPassword(Long id, String password);
|
||||
@@ -84,7 +82,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 修改状态
|
||||
*
|
||||
* @param id 用户编号
|
||||
* @param id 用户编号
|
||||
* @param status 状态
|
||||
*/
|
||||
void updateUserStatus(Long id, Integer status);
|
||||
@@ -193,7 +191,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 批量导入用户
|
||||
*
|
||||
* @param importUsers 导入用户列表
|
||||
* @param importUsers 导入用户列表
|
||||
* @param isUpdateSupport 是否支持更新
|
||||
* @return 导入结果
|
||||
*/
|
||||
@@ -210,7 +208,7 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 判断密码是否匹配
|
||||
*
|
||||
* @param rawPassword 未加密的密码
|
||||
* @param rawPassword 未加密的密码
|
||||
* @param encodedPassword 加密后的密码
|
||||
* @return 是否匹配
|
||||
*/
|
||||
@@ -226,7 +224,7 @@ public interface AdminUserService {
|
||||
|
||||
/**
|
||||
* 判断用户当前是否可用
|
||||
*
|
||||
* <p>
|
||||
* 口径:
|
||||
* 1. `status` 必须为启用
|
||||
* 2. `resignedAt` 为空,或者晚于当前时间
|
||||
@@ -252,4 +250,13 @@ public interface AdminUserService {
|
||||
* @return 可用用户 ID 集合
|
||||
*/
|
||||
Set<Long> listEnabledUserIdsByDeptIds(Collection<Long> deptIds);
|
||||
|
||||
/**
|
||||
* 上传头像
|
||||
*
|
||||
* @param file
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
FileDO uploadAvatar(MultipartFile file, AdminUserDO user);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.njcn.rdms.module.system.service.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.mzt.logapi.context.LogRecordContext;
|
||||
import com.mzt.logapi.service.impl.DiffParseFunction;
|
||||
@@ -23,11 +27,16 @@ import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserPageReqVO;
|
||||
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserSaveReqVO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.config.ConfigDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.dept.DeptDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.file.FileDO;
|
||||
import com.njcn.rdms.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import com.njcn.rdms.module.system.dal.mysql.file.FileMapper;
|
||||
import com.njcn.rdms.module.system.dal.mysql.user.AdminUserMapper;
|
||||
import com.njcn.rdms.module.system.framework.file.core.client.FileClient;
|
||||
import com.njcn.rdms.module.system.framework.file.core.utils.FileTypeUtils;
|
||||
import com.njcn.rdms.module.system.service.config.ConfigService;
|
||||
import com.njcn.rdms.module.system.service.dept.DeptService;
|
||||
import com.njcn.rdms.module.system.service.dept.PostService;
|
||||
import com.njcn.rdms.module.system.service.file.FileConfigService;
|
||||
import com.njcn.rdms.module.system.service.oauth2.OAuth2TokenService;
|
||||
import com.njcn.rdms.module.system.service.permission.PermissionService;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -37,6 +46,7 @@ import org.springframework.context.annotation.Lazy;
|
||||
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 java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
@@ -77,6 +87,10 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
private ConfigService configService;
|
||||
@Resource
|
||||
private UserManagementRelationService userManagementRelationService;
|
||||
@Resource
|
||||
private FileConfigService fileConfigService;
|
||||
@Resource
|
||||
private FileMapper fileMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -216,7 +230,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteUserList(List<Long> ids) {
|
||||
//批量删除前查看是否管理链路表还在使用该用户
|
||||
for (Long id : ids){
|
||||
for (Long id : ids) {
|
||||
Boolean res = userManagementRelationService.hasRelation(id);
|
||||
if (res) {
|
||||
throw exception(USER_MANAGEMENT_RELATION_EXISTS);
|
||||
@@ -404,7 +418,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
/**
|
||||
* 校验旧密码
|
||||
*
|
||||
* @param id 用户 ID
|
||||
* @param id 用户 ID
|
||||
* @param oldPassword 旧密码
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@@ -513,6 +527,79 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
return getUserListByDeptIds(deptCondition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileDO uploadAvatar(MultipartFile file, AdminUserDO user) {
|
||||
String type = file.getContentType();
|
||||
String name = file.getOriginalFilename();
|
||||
FileDO fileDO = null;
|
||||
try {
|
||||
byte[] content = IoUtil.readBytes(file.getInputStream());
|
||||
|
||||
// 1.1 处理 type 为空的情况
|
||||
if (StrUtil.isEmpty(type)) {
|
||||
type = FileTypeUtils.getMineType(content, name);
|
||||
}
|
||||
// 验证文件类型
|
||||
validateImageFile(file);
|
||||
|
||||
// 1.2 处理 name 为空的情况
|
||||
if (StrUtil.isEmpty(name)) {
|
||||
name = DigestUtil.sha256Hex(content);
|
||||
}
|
||||
if (StrUtil.isEmpty(FileUtil.extName(name))) {
|
||||
// 如果 name 没有后缀 type,则补充后缀
|
||||
String extension = FileTypeUtils.getExtension(type);
|
||||
if (StrUtil.isNotEmpty(extension)) {
|
||||
name = name + extension;
|
||||
}
|
||||
}
|
||||
|
||||
// 2.1 生成上传的 path,需要保证唯一
|
||||
String path = FileUtil.FILE_SEPARATOR + "rdms\\avatar" + FileUtil.FILE_SEPARATOR + generateUniqueFileName(name);
|
||||
// 2.2 上传到文件存储器
|
||||
FileClient client = fileConfigService.getMasterFileClient();
|
||||
Assert.notNull(client, "客户端(master) 不能为空");
|
||||
String url = null;
|
||||
|
||||
url = client.upload(content, path, type);
|
||||
|
||||
//删除旧的
|
||||
client.delete(user.getAvatar());
|
||||
|
||||
// 3. 保存到数据库
|
||||
fileDO = new FileDO().setConfigId(client.getId())
|
||||
.setName(name).setPath(path).setUrl(url)
|
||||
.setType(type).setSize((long) content.length);
|
||||
fileMapper.insert(fileDO);
|
||||
user.setAvatar(fileDO.getUrl());
|
||||
this.userMapper.updateById(user);
|
||||
} catch (Exception e) {
|
||||
throw exception(USER_AVATAR_UPLOAD_FAILED);
|
||||
}
|
||||
return fileDO;
|
||||
}
|
||||
|
||||
private void validateImageFile(MultipartFile file) {
|
||||
// 检查文件类型
|
||||
String contentType = file.getContentType();
|
||||
if (contentType == null || !contentType.startsWith("image/")) {
|
||||
throw exception(USER_AVATAR_SUFFIX_ERROR);
|
||||
}
|
||||
|
||||
// 检查文件大小(例如限制5MB)
|
||||
if (file.getSize() > 5 * 1024 * 1024) {
|
||||
throw exception(USER_AVATAR_SIZE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private String generateUniqueFileName(String originalFilename) {
|
||||
String extension = "";
|
||||
if (originalFilename != null && originalFilename.contains(".")) {
|
||||
extension = originalFilename.substring(originalFilename.lastIndexOf("."));
|
||||
}
|
||||
return UUID.randomUUID().toString() + extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对密码进行加密
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user