feat(用户): 修改密码

This commit is contained in:
ovo 2024-12-23 14:55:04 +08:00
parent 91b482d0bc
commit 7f94911665
21 changed files with 453 additions and 40 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,25 @@
package com.guwan.backend.common;
public class BusinessException extends RuntimeException {
@java.io.Serial private static final long serialVersionUID = -2119302295305964305L;
public BusinessException() {}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(
String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -8,7 +8,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EsMapperScan("com.guwan.backend.es.mapper")
@EsMapperScan("com.guwan.backend.elasticsearch.mapper")
@EnableConfigurationProperties(EasyEsConfigProperties.class)
public class EasyEsConfig {
@Bean

View File

@ -1,14 +1,12 @@
package com.guwan.backend.controller;
import com.guwan.backend.common.Result;
import com.guwan.backend.entity.BookCategory;
import com.guwan.backend.service.BookCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
/**
* (BookCategory)表控制层
@ -61,7 +59,13 @@ public class BookCategoryController {
@PostMapping
public Result<BookCategory> add(BookCategory bookCategory) {
// return Result.success(this.bookCategoryService.insert(bookCategory));
return Result.success();
if (bookCategoryService.save(bookCategory)) {
return Result.success();
}else {
return Result.error("保存失败");
}
}
/**

View File

@ -1,6 +1,7 @@
package com.guwan.backend.controller;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.common.BusinessException;
import com.guwan.backend.common.Result;
import com.guwan.backend.entity.BookContent;
import com.guwan.backend.mongodb.EveryReadDetailOfMongodb;

View File

@ -2,8 +2,8 @@ package com.guwan.backend.controller;
import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import com.guwan.backend.common.Result;
import com.guwan.backend.es.document.ProductDocument;
import com.guwan.backend.es.mapper.ProductEsMapper;
import com.guwan.backend.elasticsearch.document.ProductDocument;
import com.guwan.backend.elasticsearch.mapper.ProductEsMapper;
import com.guwan.backend.util.MinioUtil;
import io.minio.MinioClient;
import lombok.RequiredArgsConstructor;

View File

@ -98,9 +98,13 @@ public class UserController {
log.info("邮箱注册: {}", email);
Context context = new Context();
context.setVariable("nowDate", DateUtil.now());
String code = RandomUtil.randomNumbers(6);
redisUtils.set(email, code, 10);
context.setVariable("code", code.toCharArray());
emailService.sendHtmlMessage(email,
@ -112,7 +116,9 @@ public class UserController {
@PostMapping("/getPhoneCode")
public Result registerByPhone(@RequestBody @Valid PhoneDto phoneDto) throws Exception {
String phone = phoneDto.getPhone();
log.info("手机号注册: {}", phone);
String random = RandomUtil.randomNumbers(6);
SmsUtils.sendMessage(phone, random);
@ -127,9 +133,14 @@ public class UserController {
@PostMapping("/password/reset")
public Result<Void> resetPassword(@RequestParam @Email String email) {
public Result<Void> resetPassword(@RequestBody ChangePasswordDTO changePasswordDTO) {
log.debug("更改方式: {}, 内容: {}",
changePasswordDTO.getChangeWay(),
changePasswordDTO.getInfo());
try {
userService.resetPassword(email);
userService.resetPassword(changePasswordDTO);
return Result.success();
} catch (Exception e) {
log.error("重置密码失败", e);

View File

@ -0,0 +1,24 @@
package com.guwan.backend.dto.user;
import lombok.Data;
@Data
public class ChangePasswordDTO {
/**
* 修改方式
*/
String changeWay;
/**
* 账号邮箱手机号
*/
String info;
/**
* 密码验证码
*/
String code;
/**
* 新密码
*/
String newPassword;
}

View File

@ -1,4 +1,4 @@
package com.guwan.backend.es.document;
package com.guwan.backend.elasticsearch.document;
import cn.easyes.annotation.IndexField;
import cn.easyes.annotation.IndexId;

View File

@ -1,4 +1,4 @@
package com.guwan.backend.es.document;
package com.guwan.backend.elasticsearch.document;
import cn.easyes.annotation.IndexField;
import cn.easyes.annotation.IndexId;

View File

@ -1,7 +1,7 @@
package com.guwan.backend.es.mapper;
package com.guwan.backend.elasticsearch.mapper;
import cn.easyes.core.conditions.interfaces.BaseEsMapper;
import com.guwan.backend.es.document.ProductDocument;
import com.guwan.backend.elasticsearch.document.ProductDocument;
import org.springframework.stereotype.Repository;
@Repository

View File

@ -1,7 +1,7 @@
package com.guwan.backend.es.mapper;
package com.guwan.backend.elasticsearch.mapper;
import cn.easyes.core.conditions.interfaces.BaseEsMapper;
import com.guwan.backend.es.document.VideoDocument;
import com.guwan.backend.elasticsearch.document.VideoDocument;
import org.springframework.stereotype.Repository;
@Repository

View File

@ -10,7 +10,7 @@ public class Book {
@TableId(type = IdType.AUTO)
private Long id;
private String isbn; // ISBN编号
private String title; // 书名
private String name; // 书名
private String author; // 作者
private String publisher; // 出版社
private String description; // 描述

View File

@ -0,0 +1,27 @@
package com.guwan.backend.enums;
public enum UserEnums {
ACCOUNT("account"),
EMAIL("email"),
PHONE("phone"),
FACE("face");
private String value;
UserEnums(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static UserEnums fromValue(String value) {
for (UserEnums userEnum : values()) {
if (userEnum.getValue().equals(value)) {
return userEnum;
}
}
throw new IllegalArgumentException("Unexpected value: " + value);
}
}

View File

@ -2,8 +2,8 @@ package com.guwan.backend.service;
import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import com.guwan.backend.dto.product.ProductDTO;
import com.guwan.backend.es.document.ProductDocument;
import com.guwan.backend.es.mapper.ProductEsMapper;
import com.guwan.backend.elasticsearch.document.ProductDocument;
import com.guwan.backend.elasticsearch.mapper.ProductEsMapper;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

View File

@ -1,5 +1,6 @@
package com.guwan.backend.service;
import com.guwan.backend.dto.user.ChangePasswordDTO;
import com.guwan.backend.dto.user.LoginDto;
import com.guwan.backend.dto.user.RegisterDTO;
import com.guwan.backend.dto.user.UserDTO;
@ -23,7 +24,7 @@ public interface UserService {
UserDTO getUserById(Long id);
UserDTO updateUserInfo(UserDTO userDTO);
void resetPassword(String email);
void resetPassword(ChangePasswordDTO changePasswordDTO);
public String refreshToken(String token);
UserDTO findByUsername(String username);

View File

@ -4,8 +4,8 @@ import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import cn.easyes.core.conditions.LambdaEsUpdateWrapper;
import com.guwan.backend.dto.video.VideoDTO;
import com.guwan.backend.entity.Video;
import com.guwan.backend.es.document.VideoDocument;
import com.guwan.backend.es.mapper.VideoEsMapper;
import com.guwan.backend.elasticsearch.document.VideoDocument;
import com.guwan.backend.elasticsearch.mapper.VideoEsMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

View File

@ -3,32 +3,83 @@ package com.guwan.backend.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.common.BusinessException;
import com.guwan.backend.entity.Book;
import com.guwan.backend.entity.BookCategory;
import com.guwan.backend.entity.BookContent;
import com.guwan.backend.mapper.BookCategoryMapper;
import com.guwan.backend.mapper.BookMapper;
import com.guwan.backend.service.BookContentService;
import com.guwan.backend.service.BookService;
import com.mongoplus.conditions.query.LambdaQueryChainWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.ArrayList;
import static com.guwan.backend.util.BookContentUtil.getTextUsingOkHttp;
import static com.guwan.backend.util.BookContentUtil.processContent;
@Slf4j
@Service
@RequiredArgsConstructor
public class BookServiceImpl implements BookService {
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {
private final BookContentService bookContentService;
private final BookMapper bookMapper;
@Override
@Transactional
@OperationLog(description = "添加图书")
public Book addBook(Book book) {
Book one = this.getOne(new LambdaQueryWrapper<Book>().eq(Book::getBookUrl, book.getBookUrl()));
// new LambdaQueryWrapper<>()
// new LambdaQueryChainWrapper<>()
if (one != null){
//复制处理
//不允许
throw new BusinessException("此图书url已被使用");
}
// new LambdaQueryWrapper<>()
// new LambdaQueryChainWrapper<>()
bookMapper.insert(book);
log.debug(book.getBookUrl());
OkHttpClient client = new OkHttpClient();
// 创建一个请求对象
Request request = new Request.Builder()
.url(book.getBookUrl())
.build();
// 发起同步请求
try {
String content = getTextUsingOkHttp(client, request);
ArrayList<BookContent> bookContents = processContent(content, book.getName());
bookContentService.saveBatch(bookContents);
} catch (IOException e) {
e.printStackTrace();
log.error(e.getMessage());
}
return book;
}
@ -36,6 +87,14 @@ public class BookServiceImpl implements BookService {
@Transactional
public Book updateBook(Book book) {
bookMapper.updateById(book);
Book book1 = bookMapper.selectOne(new LambdaQueryWrapper<Book>()
.eq(Book::getBookUrl, book.getBookUrl()));
return book;
}
@ -62,7 +121,7 @@ public class BookServiceImpl implements BookService {
public IPage<Book> getBookList(Integer pageNum, Integer pageSize, String keyword) {
LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<>();
if (keyword != null && !keyword.isEmpty()) {
wrapper.like(Book::getTitle, keyword)
wrapper.like(Book::getName, keyword)
.or()
.like(Book::getAuthor, keyword)
.or()
@ -77,4 +136,4 @@ public class BookServiceImpl implements BookService {
wrapper.eq(Book::getCategory, category);
return bookMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
}
}
}

View File

@ -1,11 +1,14 @@
package com.guwan.backend.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.dto.user.ChangePasswordDTO;
import com.guwan.backend.dto.user.LoginDto;
import com.guwan.backend.dto.user.RegisterDTO;
import com.guwan.backend.dto.user.UserDTO;
import com.guwan.backend.entity.User;
import com.guwan.backend.enums.UserEnums;
import com.guwan.backend.mapper.UserMapper;
import com.guwan.backend.mybatis.query.LambdaQueryWrapperX;
import com.guwan.backend.service.EmailService;
@ -25,7 +28,7 @@ import java.time.LocalDateTime;
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;
@ -159,6 +162,7 @@ public class UserServiceImpl implements UserService {
@Override
@OperationLog(description = "根据Id获取用户信息")
public UserDTO getUserById(Long id) {
// 先从缓存获取
Object cached = redisUtil.get(USER_CACHE_KEY + id);
@ -184,7 +188,18 @@ public class UserServiceImpl implements UserService {
@Override
public void resetPassword(String email) {
public void resetPassword(ChangePasswordDTO changePasswordDTO) {
if(changePasswordDTO.getChangeWay().equals(UserEnums.ACCOUNT.getValue())){
User user = this.getOne(new LambdaQueryWrapper<User>()
.eq(User::getUsername, changePasswordDTO.getInfo()));
}
if (changePasswordDTO.getChangeWay().equals(UserEnums.ACCOUNT.getValue())){
}
}

View File

@ -0,0 +1,128 @@
package com.guwan.backend.util;
import com.guwan.backend.entity.BookContent;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BookContentUtil {
// 通过 OkHttpClient 发起同步请求获取文件内容
public static String getTextUsingOkHttp(OkHttpClient client, Request request) throws IOException {
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string(); // 返回文件内容
} else {
throw new IOException("Unexpected code " + response);
}
}
}
public static ArrayList<BookContent> processContent(String content, String bookName) {
// 正则表达式提取卷和节
String volumePattern = "第([一二三四五六七八九十]+)卷"; // 提取卷
String sectionPattern = "第([一二三四五六七八九十零百]+)节:(.*)"; // 提取节及其节名
// 提取卷
Pattern volumeRegex = Pattern.compile(volumePattern);
Matcher volumeMatcher = volumeRegex.matcher(content);
// 提取节
Pattern sectionRegex = Pattern.compile(sectionPattern);
Matcher sectionMatcher = sectionRegex.matcher(content);
// 列表来存储所有卷和节的内容
List<String> volumes = new ArrayList<>(); // 存储所有卷的标题
List<String> sections = new ArrayList<>(); // 存储所有节的标题
List<String> sectionContents = new ArrayList<>(); // 存储每节的正文内容
// 收集卷的信息
while (volumeMatcher.find()) {
String volume = "" + volumeMatcher.group(1) + "";
volumes.add(volume);
}
// 收集节的信息
while (sectionMatcher.find()) {
String sectionTitle = "" + sectionMatcher.group(1) + "节:" + sectionMatcher.group(2).trim(); // 这里去掉节名前后空格
sections.add(sectionTitle);
// 获取节的正文内容
int start = sectionMatcher.end(); // 获取节标题之后的位置
int end = content.length(); // 默认到文件末尾
// 查找下一个节的位置即本节内容的结束位置
Matcher nextSectionMatcher = sectionRegex.matcher(content);
if (nextSectionMatcher.find(start)) {
end = nextSectionMatcher.start();
}
// 获取当前节的正文内容
String sectionContent = content.substring(start, end).trim();
sectionContents.add(sectionContent);
}
// 标记是否是第一次匹配到第一节
boolean isFirstSection = true;
ArrayList<BookContent> bookContents = new ArrayList<>();
int sectionId = 1;
// 输出卷和节信息
for (int i = 0; i < volumes.size(); i++) {
// 输出卷的标题
// 输出该卷的每一节标题和正文内容
for (int j = 0; j < sections.size(); j++) {
// System.out.print(volumes.get(i));
String section = sections.get(j);
String sectionContent = sectionContents.get(j);
// 输出节标题
// System.out.println(" " + section);
// 输出节的正文内容
// System.out.println(" 正文: " + sectionContent);
// 如果是第一节并且不是第一次出现递增卷的索引
if (section.contains("第一节") && !isFirstSection) {
i++; // 不是第一次才递增
}
// 第一次匹配到第一节标记为false
isFirstSection = false;
BookContent bookContent = new BookContent();
bookContent.setBookName(bookName);
bookContent.setVolume(volumes.get(i));
bookContent.setSection(section);
bookContent.setSectionContent(sectionContent);
bookContent.setSectionId(sectionId++);
System.out.println("bookContent = " + bookContent);
bookContents.add(bookContent);
}
}
return bookContents;
}
}

View File

@ -9,8 +9,6 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.time.LocalDateTime;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
@ -32,7 +30,7 @@ class BookServiceTest {
void addBook_Success() {
// 准备测试数据
Book book = new Book();
book.setTitle("测试书籍");
book.setName("测试书籍");
book.setAuthor("测试作者");
book.setIsbn("9787000000000");
@ -43,7 +41,7 @@ class BookServiceTest {
// 验证结果
assertNotNull(result);
assertEquals("测试书籍", result.getTitle());
assertEquals("测试书籍", result.getName());
verify(bookMapper, times(1)).insert(any(Book.class));
}
@ -52,7 +50,7 @@ class BookServiceTest {
// 准备测试数据
Book book = new Book();
book.setId(1L);
book.setTitle("测试书籍");
book.setName("测试书籍");
book.setIsbn("9787000000000");
when(bookMapper.selectOne(any())).thenReturn(book);
@ -62,7 +60,7 @@ class BookServiceTest {
// 验证结果
assertNotNull(result);
assertEquals("测试书籍", result.getTitle());
assertEquals("测试书籍", result.getName());
assertEquals("9787000000000", result.getIsbn());
}
}