Compare commits
2 Commits
89bbb45c52
...
73eb1198f6
| Author | SHA1 | Date | |
|---|---|---|---|
| 73eb1198f6 | |||
| f7a4995c58 |
@ -0,0 +1,9 @@
|
|||||||
|
package com.example.copykamanotes.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface NeedLogin {
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.example.copykamanotes.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import com.example.copykamanotes.interceptor.TokenInterceptor;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
@Autowired
|
||||||
|
private TokenInterceptor tokenInterceptor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加拦截器, 拦截所有请求,除了登录和注册
|
||||||
|
* @param registry 拦截器注册器
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(tokenInterceptor)
|
||||||
|
.addPathPatterns("/api/**")
|
||||||
|
.excludePathPatterns("/api/users/login", "/api/users/register");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,14 +1,22 @@
|
|||||||
package com.example.copykamanotes.controller;
|
package com.example.copykamanotes.controller;
|
||||||
|
|
||||||
import com.example.copykamanotes.model.base.ApiResponse;
|
import com.example.copykamanotes.model.base.ApiResponse;
|
||||||
|
import com.example.copykamanotes.model.dto.user.LoginRequest;
|
||||||
import com.example.copykamanotes.model.dto.user.RegisterRequest;
|
import com.example.copykamanotes.model.dto.user.RegisterRequest;
|
||||||
|
import com.example.copykamanotes.model.dto.user.UpdateUserRequest;
|
||||||
|
import com.example.copykamanotes.model.dto.user.UserQueryParam;
|
||||||
|
import com.example.copykamanotes.model.entity.User;
|
||||||
|
import com.example.copykamanotes.model.vo.user.AvatarVO;
|
||||||
|
import com.example.copykamanotes.model.vo.user.LoginUserVO;
|
||||||
import com.example.copykamanotes.model.vo.user.RegisterVO;
|
import com.example.copykamanotes.model.vo.user.RegisterVO;
|
||||||
import com.example.copykamanotes.service.UserService;
|
import com.example.copykamanotes.service.UserService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@ -31,4 +39,41 @@ public class UserController {
|
|||||||
public ApiResponse<String> hello() {
|
public ApiResponse<String> hello() {
|
||||||
return ApiResponse.success("Hello World");
|
return ApiResponse.success("Hello World");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/users/login")
|
||||||
|
public ApiResponse<LoginUserVO> login(
|
||||||
|
@Valid
|
||||||
|
@RequestBody
|
||||||
|
LoginRequest loginRequest
|
||||||
|
) {
|
||||||
|
return userService.login(loginRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/users/whoami")
|
||||||
|
public ApiResponse<LoginUserVO> whoami() {
|
||||||
|
return userService.whoami();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/users/me")
|
||||||
|
public ApiResponse<LoginUserVO> updateUserInfo(
|
||||||
|
@Valid
|
||||||
|
@RequestBody
|
||||||
|
UpdateUserRequest updateUserRequest
|
||||||
|
) {
|
||||||
|
return userService.updateUserInfo(updateUserRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/users/avatar")
|
||||||
|
public ApiResponse<AvatarVO> uploadAvatar(
|
||||||
|
@RequestParam("file") MultipartFile file
|
||||||
|
) {
|
||||||
|
return userService.uploadAvatar(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/admin/users")
|
||||||
|
public ApiResponse<List<User>> adminGetUser(
|
||||||
|
@Valid UserQueryParam userQueryParam
|
||||||
|
) {
|
||||||
|
return userService.getUserList(userQueryParam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.example.copykamanotes.interceptor;
|
||||||
|
|
||||||
|
import com.example.copykamanotes.scope.RequestScopeData;
|
||||||
|
import com.example.copykamanotes.utils.JwtUtil;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TokenInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RequestScopeData requestScopeData;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
String token = request.getHeader("Authorization");
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
requestScopeData.setLogin(false);
|
||||||
|
requestScopeData.setUserId(null);
|
||||||
|
requestScopeData.setUserId(null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = token.replace("Bearer ", "");
|
||||||
|
|
||||||
|
if (!jwtUtil.validateToken(token)) {
|
||||||
|
Long userId = jwtUtil.getUserIdFromToken(token);
|
||||||
|
requestScopeData.setUserId(userId);
|
||||||
|
requestScopeData.setToken(token);
|
||||||
|
requestScopeData.setLogin(true);
|
||||||
|
} else {
|
||||||
|
requestScopeData.setLogin(false);
|
||||||
|
}
|
||||||
|
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,12 @@
|
|||||||
package com.example.copykamanotes.mapper;
|
package com.example.copykamanotes.mapper;
|
||||||
|
|
||||||
|
import com.example.copykamanotes.model.dto.user.UserQueryParam;
|
||||||
import com.example.copykamanotes.model.entity.User;
|
import com.example.copykamanotes.model.entity.User;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface UserMapper {
|
public interface UserMapper {
|
||||||
/**
|
/**
|
||||||
@ -18,4 +21,14 @@ public interface UserMapper {
|
|||||||
User findByEmail(@Param("email") String email);
|
User findByEmail(@Param("email") String email);
|
||||||
|
|
||||||
int updateLastLoginAt(@Param("userId") Long userId);
|
int updateLastLoginAt(@Param("userId") Long userId);
|
||||||
|
|
||||||
|
User findById(@Param("userId") Long userId);
|
||||||
|
|
||||||
|
int update(User user);
|
||||||
|
|
||||||
|
List<User> findByIds(@Param("userIds") List<Long> userIds);
|
||||||
|
|
||||||
|
int countByQueryParam(@Param("queryParams") UserQueryParam userQueryParam);
|
||||||
|
|
||||||
|
List<User> findByQueryParam(@Param("queryParams") UserQueryParam userQueryParam, @Param("limit") int pageSize, @Param("offset") int offset);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ package com.example.copykamanotes.model.base;
|
|||||||
* PaginationApiResponse类用于处理分页的API响应。
|
* PaginationApiResponse类用于处理分页的API响应。
|
||||||
* @param <T> 泛型类型,表示分页数据类型。
|
* @param <T> 泛型类型,表示分页数据类型。
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PaginationApiResponse<T> extends ApiResponse<T> {
|
public class PaginationApiResponse<T> extends ApiResponse<T> {
|
||||||
// 分页对象
|
// 分页对象
|
||||||
private final Pagination pagination;
|
private final Pagination pagination;
|
||||||
|
|||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.example.copykamanotes.service;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
public interface FileService {
|
||||||
|
/**
|
||||||
|
* 上传文件,返回文件路径
|
||||||
|
* @param file 文件
|
||||||
|
* @return 文件路径
|
||||||
|
*/
|
||||||
|
String uploadFile(MultipartFile file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片,返回图片路径
|
||||||
|
* @param file 图片
|
||||||
|
* @return 图片路径
|
||||||
|
*/
|
||||||
|
String uploadImage(MultipartFile file);
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import com.example.copykamanotes.model.base.ApiResponse;
|
|||||||
import com.example.copykamanotes.model.dto.user.LoginRequest;
|
import com.example.copykamanotes.model.dto.user.LoginRequest;
|
||||||
import com.example.copykamanotes.model.dto.user.RegisterRequest;
|
import com.example.copykamanotes.model.dto.user.RegisterRequest;
|
||||||
import com.example.copykamanotes.model.dto.user.UpdateUserRequest;
|
import com.example.copykamanotes.model.dto.user.UpdateUserRequest;
|
||||||
|
import com.example.copykamanotes.model.dto.user.UserQueryParam;
|
||||||
import com.example.copykamanotes.model.entity.User;
|
import com.example.copykamanotes.model.entity.User;
|
||||||
import com.example.copykamanotes.model.vo.user.AvatarVO;
|
import com.example.copykamanotes.model.vo.user.AvatarVO;
|
||||||
import com.example.copykamanotes.model.vo.user.LoginUserVO;
|
import com.example.copykamanotes.model.vo.user.LoginUserVO;
|
||||||
@ -65,6 +66,13 @@ public interface UserService {
|
|||||||
*/
|
*/
|
||||||
Map<Long, User> getUserMapByIds(List<Long> authorIds);
|
Map<Long, User> getUserMapByIds(List<Long> authorIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户列表
|
||||||
|
* @param userQueryParam 查询参数
|
||||||
|
* @return 用户列表
|
||||||
|
*/
|
||||||
|
ApiResponse<List<User>> getUserList(UserQueryParam userQueryParam);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传用户头像
|
* 上传用户头像
|
||||||
*
|
*
|
||||||
|
|||||||
@ -0,0 +1,102 @@
|
|||||||
|
package com.example.copykamanotes.service.impl;
|
||||||
|
|
||||||
|
import com.example.copykamanotes.service.FileService;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Service
|
||||||
|
public class LocalFileServiceImpl implements FileService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础上传路径(本地存储的绝对或相对路径)
|
||||||
|
*/
|
||||||
|
@Value("${upload.path}")
|
||||||
|
private String uploadBasePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回给前端的地址前缀 (可配合CDN/Nginx等)
|
||||||
|
*/
|
||||||
|
@Value("${upload.url-prefix}")
|
||||||
|
private String urlPrefix;
|
||||||
|
|
||||||
|
private static final List<String> ALLOWED_IMAGE_EXTENSIONS = Arrays.asList("jpg", "jpeg", "png", "gif");
|
||||||
|
|
||||||
|
|
||||||
|
private static final long MAX_IMAGE_SIZE = 5 * 1024 * 1024;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String uploadFile(MultipartFile file) {
|
||||||
|
if (file == null || file.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.getSize() > MAX_IMAGE_SIZE) {
|
||||||
|
throw new IllegalArgumentException("file size is too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
String originFilename = file.getOriginalFilename();
|
||||||
|
if (originFilename == null || !originFilename.contains(".")) {
|
||||||
|
throw new IllegalArgumentException("file name is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
String lowerCaseExtension = originFilename.substring(originFilename.lastIndexOf(".") + 1).toLowerCase();
|
||||||
|
|
||||||
|
if (!ALLOWED_IMAGE_EXTENSIONS.contains(lowerCaseExtension)) {
|
||||||
|
throw new IllegalArgumentException("file extension is not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return doUpload(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String uploadImage(MultipartFile file) {
|
||||||
|
if (file == null || file.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("file is empty");
|
||||||
|
}
|
||||||
|
return doUpload(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
* @param file MultipartFile
|
||||||
|
* @return url
|
||||||
|
*/
|
||||||
|
private String doUpload(MultipartFile file) {
|
||||||
|
String filename = file.getOriginalFilename();
|
||||||
|
|
||||||
|
if (filename == null || !filename.contains(".")) {
|
||||||
|
throw new IllegalArgumentException("file name is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileExtension = filename.substring(filename.lastIndexOf(".") + 1);
|
||||||
|
|
||||||
|
String newFileName = UUID.randomUUID() + fileExtension;
|
||||||
|
|
||||||
|
File uploadDir = new File(uploadBasePath);
|
||||||
|
|
||||||
|
if (!uploadDir.exists() && !uploadDir.mkdirs()) {
|
||||||
|
throw new RuntimeException("create upload dir failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
File destFile = new File(uploadBasePath, newFileName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
file.transferTo(destFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("upload file failed", e);
|
||||||
|
throw new RuntimeException("upload file failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return urlPrefix + newFileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,13 @@
|
|||||||
package com.example.copykamanotes.service.impl;
|
package com.example.copykamanotes.service.impl;
|
||||||
|
|
||||||
|
import com.example.copykamanotes.annotation.NeedLogin;
|
||||||
import com.example.copykamanotes.mapper.UserMapper;
|
import com.example.copykamanotes.mapper.UserMapper;
|
||||||
import com.example.copykamanotes.model.base.ApiResponse;
|
import com.example.copykamanotes.model.base.ApiResponse;
|
||||||
|
import com.example.copykamanotes.model.base.Pagination;
|
||||||
import com.example.copykamanotes.model.dto.user.LoginRequest;
|
import com.example.copykamanotes.model.dto.user.LoginRequest;
|
||||||
import com.example.copykamanotes.model.dto.user.RegisterRequest;
|
import com.example.copykamanotes.model.dto.user.RegisterRequest;
|
||||||
import com.example.copykamanotes.model.dto.user.UpdateUserRequest;
|
import com.example.copykamanotes.model.dto.user.UpdateUserRequest;
|
||||||
|
import com.example.copykamanotes.model.dto.user.UserQueryParam;
|
||||||
import com.example.copykamanotes.model.entity.User;
|
import com.example.copykamanotes.model.entity.User;
|
||||||
import com.example.copykamanotes.model.vo.user.AvatarVO;
|
import com.example.copykamanotes.model.vo.user.AvatarVO;
|
||||||
import com.example.copykamanotes.model.vo.user.LoginUserVO;
|
import com.example.copykamanotes.model.vo.user.LoginUserVO;
|
||||||
@ -12,9 +15,12 @@ import com.example.copykamanotes.model.vo.user.RegisterVO;
|
|||||||
import com.example.copykamanotes.model.vo.user.UserVO;
|
import com.example.copykamanotes.model.vo.user.UserVO;
|
||||||
import com.example.copykamanotes.scope.RequestScopeData;
|
import com.example.copykamanotes.scope.RequestScopeData;
|
||||||
import com.example.copykamanotes.service.EmailService;
|
import com.example.copykamanotes.service.EmailService;
|
||||||
|
import com.example.copykamanotes.service.FileService;
|
||||||
import com.example.copykamanotes.service.UserService;
|
import com.example.copykamanotes.service.UserService;
|
||||||
import com.example.copykamanotes.utils.ApiResponseUtil;
|
import com.example.copykamanotes.utils.ApiResponseUtil;
|
||||||
import com.example.copykamanotes.utils.JwtUtil;
|
import com.example.copykamanotes.utils.JwtUtil;
|
||||||
|
import com.example.copykamanotes.utils.PaginationUtil;
|
||||||
|
import com.google.protobuf.Api;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -23,8 +29,10 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
@Service
|
@Service
|
||||||
@ -42,6 +50,9 @@ public class UserServiceImpl implements UserService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RequestScopeData requestScopeData;
|
private RequestScopeData requestScopeData;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FileService fileService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EmailService emailService;
|
private EmailService emailService;
|
||||||
|
|
||||||
@ -86,37 +97,140 @@ public class UserServiceImpl implements UserService {
|
|||||||
return ApiResponseUtil.success("注册成功", registerVO, token);
|
return ApiResponseUtil.success("注册成功", registerVO, token);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("注册失败", e);
|
log.error("注册失败", e);
|
||||||
return ApiResponseUtil.error("注册失败");
|
return ApiResponseUtil.error("注册失败,请稍后再试");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<LoginUserVO> login(LoginRequest loginRequest) {
|
public ApiResponse<LoginUserVO> login(LoginRequest loginRequest) {
|
||||||
return null;
|
User user = null;
|
||||||
|
|
||||||
|
if (loginRequest.getAccount() != null && !loginRequest.getAccount().isEmpty()) {
|
||||||
|
user = userMapper.findByAccount(loginRequest.getAccount());
|
||||||
|
} else if (loginRequest.getEmail() != null && !loginRequest.getEmail().isEmpty()) {
|
||||||
|
user = userMapper.findByEmail(loginRequest.getEmail());
|
||||||
|
} else {
|
||||||
|
return ApiResponseUtil.error("账号或邮箱不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
return ApiResponseUtil.error("账号或邮箱不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passwordEncoder.matches(loginRequest.getPassword(), user.getPassword())) {
|
||||||
|
return ApiResponseUtil.error("密码错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = jwtUtil.generateToken(user.getUserId());
|
||||||
|
|
||||||
|
LoginUserVO loginUserVO = new LoginUserVO();
|
||||||
|
BeanUtils.copyProperties(user, loginUserVO);
|
||||||
|
|
||||||
|
userMapper.updateLastLoginAt(user.getUserId());
|
||||||
|
|
||||||
|
return ApiResponseUtil.success("登录成功", loginUserVO, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<LoginUserVO> whoami() {
|
public ApiResponse<LoginUserVO> whoami() {
|
||||||
return null;
|
Long userId = requestScopeData.getUserId();
|
||||||
|
|
||||||
|
if (userId == null) {
|
||||||
|
return ApiResponseUtil.error("未登录");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
User user = userMapper.findById(userId);
|
||||||
|
if (user == null) {
|
||||||
|
return ApiResponseUtil.error("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
String newToken = jwtUtil.generateToken(userId);
|
||||||
|
if (newToken == null) {
|
||||||
|
return ApiResponseUtil.error("token生成失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginUserVO loginUserVO = new LoginUserVO();
|
||||||
|
BeanUtils.copyProperties(user, loginUserVO);
|
||||||
|
return ApiResponseUtil.success("获取用户信息成功", loginUserVO, newToken);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取用户信息失败", e);
|
||||||
|
return ApiResponseUtil.error("获取用户信息失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<UserVO> getUserInfo(Long userId) {
|
public ApiResponse<UserVO> getUserInfo(Long userId) {
|
||||||
return null;
|
User user = userMapper.findById(userId);
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
return ApiResponseUtil.error("用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
UserVO userVO = new UserVO();
|
||||||
|
BeanUtils.copyProperties(user, userVO);
|
||||||
|
return ApiResponseUtil.success("获取用户信息成功", userVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
|
@NeedLogin
|
||||||
public ApiResponse<LoginUserVO> updateUserInfo(UpdateUserRequest updateUserRequest) {
|
public ApiResponse<LoginUserVO> updateUserInfo(UpdateUserRequest updateUserRequest) {
|
||||||
return null;
|
Long userId = requestScopeData.getUserId();
|
||||||
|
|
||||||
|
if (userId == null) {
|
||||||
|
return ApiResponseUtil.error("未登录");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
BeanUtils.copyProperties(updateUserRequest, user);
|
||||||
|
user.setUserId(userId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
userMapper.update(user);
|
||||||
|
return ApiResponseUtil.success("更新用户信息成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新用户信息失败", e);
|
||||||
|
return ApiResponseUtil.error("更新用户信息失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Long, User> getUserMapByIds(List<Long> authorIds) {
|
public Map<Long, User> getUserMapByIds(List<Long> authorIds) {
|
||||||
return Map.of();
|
if (authorIds.isEmpty()) return Collections.emptyMap();
|
||||||
|
|
||||||
|
List<User> users = userMapper.findByIds(authorIds);
|
||||||
|
|
||||||
|
return users.stream().collect(Collectors.toMap(User::getUserId, user -> user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiResponse<List<User>> getUserList(UserQueryParam userQueryParam) {
|
||||||
|
|
||||||
|
// 分页数据
|
||||||
|
int total = userMapper.countByQueryParam(userQueryParam);
|
||||||
|
int offset = PaginationUtil.calculateOffset(userQueryParam.getPage(), userQueryParam.getPageSize());
|
||||||
|
Pagination pagination = new Pagination(userQueryParam.getPage(), userQueryParam.getPageSize(), total);
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<User> users = userMapper.findByQueryParam(userQueryParam, userQueryParam.getPageSize(), offset);
|
||||||
|
|
||||||
|
return ApiResponseUtil.success("获取用户列表成功", users, pagination);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ApiResponseUtil.error(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApiResponse<AvatarVO> uploadAvatar(MultipartFile file) {
|
public ApiResponse<AvatarVO> uploadAvatar(MultipartFile file) {
|
||||||
return null;
|
try {
|
||||||
|
String url = fileService.uploadImage(file);
|
||||||
|
AvatarVO avatarVO = new AvatarVO();
|
||||||
|
avatarVO.setAvatarUrl(url);
|
||||||
|
return ApiResponseUtil.success("上传成功", avatarVO);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("上传失败", e);
|
||||||
|
return ApiResponseUtil.error("上传失败");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ public class JwtUtil {
|
|||||||
public Long getUserIdFromToken(String token) {
|
public Long getUserIdFromToken(String token) {
|
||||||
try {
|
try {
|
||||||
Claims claims = Jwts.parser()
|
Claims claims = Jwts.parser()
|
||||||
.setSigningKey(secret)
|
.setSigningKey(SECRET_KEY)
|
||||||
.parseClaimsJws(token)
|
.parseClaimsJws(token)
|
||||||
.getBody();
|
.getBody();
|
||||||
return Long.valueOf(claims.get("userId").toString());
|
return Long.valueOf(claims.get("userId").toString());
|
||||||
|
|||||||
@ -9,7 +9,7 @@ public class PaginationUtil {
|
|||||||
* @return 计算出的起始位置
|
* @return 计算出的起始位置
|
||||||
* @throws IllegalArgumentException 如果页码或每页数量小于1,则抛出异常
|
* @throws IllegalArgumentException 如果页码或每页数量小于1,则抛出异常
|
||||||
*/
|
*/
|
||||||
public static int calculatePagination(Integer page, Integer pageSize) {
|
public static int calculateOffset(Integer page, Integer pageSize) {
|
||||||
if (page < 1) {
|
if (page < 1) {
|
||||||
throw new IllegalArgumentException("page must be greater than 0");
|
throw new IllegalArgumentException("page must be greater than 0");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,3 +41,7 @@ spring.mail.default-encoding=utf-8
|
|||||||
mail.verify-code.expire-minutes=15
|
mail.verify-code.expire-minutes=15
|
||||||
mail.verify-code.resend-interval=60
|
mail.verify-code.resend-interval=60
|
||||||
mail.verify-code.template-path="templates/mail/verify-code.html"
|
mail.verify-code.template-path="templates/mail/verify-code.html"
|
||||||
|
|
||||||
|
|
||||||
|
upload.path=C:/uploads
|
||||||
|
upload.url-prefix=C:/uploads
|
||||||
|
|||||||
@ -31,6 +31,12 @@
|
|||||||
NOW())
|
NOW())
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<select id="findById" resultType="com.example.copykamanotes.model.entity.User">
|
||||||
|
select *
|
||||||
|
from user
|
||||||
|
where user_id = #{userId}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="findByEmail" resultType="com.example.copykamanotes.model.entity.User">
|
<select id="findByEmail" resultType="com.example.copykamanotes.model.entity.User">
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM user
|
FROM user
|
||||||
@ -43,5 +49,58 @@
|
|||||||
WHERE user_id = #{userId}
|
WHERE user_id = #{userId}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<update id="update" parameterType="com.example.copykamanotes.model.entity.User">
|
||||||
|
update user
|
||||||
|
<set>
|
||||||
|
<if test="username != null">username = #{username},</if>
|
||||||
|
<if test="gender != null">gender = #{gender},</if>
|
||||||
|
<if test="birthday != null">birthday = #{birthday},</if>
|
||||||
|
<if test="avatarUrl != null">avatar_url = #{avatarUrl},</if>
|
||||||
|
<if test="email != null">email = #{email},</if>
|
||||||
|
<if test="school != null">school = #{school},</if>
|
||||||
|
<if test="signature != null">signature = #{signature},</if>
|
||||||
|
</set>
|
||||||
|
where user_id = #{userId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<select id="findByIds" resultType="com.example.copykamanotes.model.entity.User">
|
||||||
|
SELECT *
|
||||||
|
FROM user
|
||||||
|
WHERE user_id IN
|
||||||
|
<foreach collection="userIds" item="userId" open="(" separator="," close=")">
|
||||||
|
#{userId}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<sql id="whereClause">
|
||||||
|
<where>
|
||||||
|
<if test="queryParams.userId != null">
|
||||||
|
AND user_id = #{queryParams.userId}
|
||||||
|
</if>
|
||||||
|
<if test="queryParams.account != null">
|
||||||
|
AND `account` LIKE CONCAT('%', #{queryParams.account}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="queryParams.username != null">
|
||||||
|
AND username LIKE CONCAT('%', #{queryParams.username}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="queryParams.isAdmin != null">
|
||||||
|
AND is_admin = #{queryParams.isAdmin}
|
||||||
|
</if>
|
||||||
|
<if test="queryParams.isBanned != null">
|
||||||
|
AND is_banned = #{queryParams.isBanned}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="countByQueryParam" resultType="integer">
|
||||||
|
SELECT COUNT(*) FROM user
|
||||||
|
<include refid="whereClause"/>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="findByQueryParam" resultType="com.example.copykamanotes.model.entity.User">
|
||||||
|
SELECT * FROM user
|
||||||
|
<include refid="whereClause"/>
|
||||||
|
LIMIT #{limit} OFFSET #{offset}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
Reference in New Issue
Block a user