From 717c3509b4e9a24b1c7c2c7a0d182e6c68f2293b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= <2712495353@qq.com> Date: Thu, 31 Jul 2025 21:24:31 +0800 Subject: [PATCH] add Notebook --- .../yulinling/workflow/aspectj/AopLog.java | 7 +- .../workflow/config/SecurityConfig.java | 1 + .../yulinling/workflow/constant/Status.java | 6 ++ .../workflow/controller/AuthController.java | 38 ++++++- .../workflow/controller/NoteController.java | 10 ++ .../controller/NotebookController.java | 44 +++++++++ .../workflow/controller/TestController.java | 2 + .../workflow/dto/request/NotebookRequest.java | 29 ++++++ .../yulinling/workflow/mapper/NoteMapper.java | 16 +++ .../workflow/mapper/NotebookMapper.java | 19 ++++ .../yulinling/workflow/model/entity/Note.java | 99 +++++++++++++++++++ .../workflow/model/entity/Notebook.java | 57 +++++++++++ .../workflow/service/AuthService.java | 11 +-- .../workflow/service/NoteService.java | 5 + .../workflow/service/NotebookService.java | 45 +++++++++ .../service/impl/AuthServiceImpl.java | 41 +++----- .../service/impl/NoteServiceImpl.java | 10 ++ .../service/impl/NotebookServiceImpl.java | 44 +++++++++ .../yulinling/workflow/utils/JwtUtil.java | 29 +++--- src/main/resources/db/schema.sql | 34 +++---- src/main/resources/db/test.sql | 7 +- src/main/resources/mapper/NoteMapper.xml | 5 + src/main/resources/mapper/NotebookMapper.xml | 5 + 23 files changed, 494 insertions(+), 70 deletions(-) create mode 100644 src/main/java/asia/yulinling/workflow/controller/NoteController.java create mode 100644 src/main/java/asia/yulinling/workflow/controller/NotebookController.java create mode 100644 src/main/java/asia/yulinling/workflow/dto/request/NotebookRequest.java create mode 100644 src/main/java/asia/yulinling/workflow/mapper/NoteMapper.java create mode 100644 src/main/java/asia/yulinling/workflow/mapper/NotebookMapper.java create mode 100644 src/main/java/asia/yulinling/workflow/model/entity/Note.java create mode 100644 src/main/java/asia/yulinling/workflow/model/entity/Notebook.java create mode 100644 src/main/java/asia/yulinling/workflow/service/NoteService.java create mode 100644 src/main/java/asia/yulinling/workflow/service/NotebookService.java create mode 100644 src/main/java/asia/yulinling/workflow/service/impl/NoteServiceImpl.java create mode 100644 src/main/java/asia/yulinling/workflow/service/impl/NotebookServiceImpl.java create mode 100644 src/main/resources/mapper/NoteMapper.xml create mode 100644 src/main/resources/mapper/NotebookMapper.xml diff --git a/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java b/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java index af608d4..1e70254 100644 --- a/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java +++ b/src/main/java/asia/yulinling/workflow/aspectj/AopLog.java @@ -29,11 +29,11 @@ import java.util.Objects; /** *

- * 使用 aop 切面记录请求日志信息 + * 使用 aop 切面记录请求日志信息 *

* * @author yulinling - * @since 2025/6/5 + * @since 2025/6/5 */ @Aspect @Component @@ -87,6 +87,7 @@ public class AopLog { /** * 获取方法参数名和参数值 + * * @param joinPoint 切入点 * @return 接口参数和参数值 */ @@ -112,6 +113,7 @@ public class AopLog { /** * 获取ip地址 + * * @param request 请求体 * @return 返回ip地址 */ @@ -150,6 +152,7 @@ public class AopLog { private static boolean isInvalidIp(String ip) { return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip); } + @Data @Builder @NoArgsConstructor diff --git a/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java b/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java index 33f93b6..f9e5321 100644 --- a/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java +++ b/src/main/java/asia/yulinling/workflow/config/SecurityConfig.java @@ -60,6 +60,7 @@ public class SecurityConfig { .authorizeHttpRequests(auth -> auth .requestMatchers("/auth/**").permitAll() .requestMatchers("/auth/register").permitAll() + .requestMatchers("/api/**").permitAll() // .requestMatchers("/user/**").permitAll() .anyRequest().access((authenticationSupplier, requestAuthorizationContext) -> { HttpServletRequest request = requestAuthorizationContext.getRequest(); diff --git a/src/main/java/asia/yulinling/workflow/constant/Status.java b/src/main/java/asia/yulinling/workflow/constant/Status.java index 2c8cacb..e74ac74 100644 --- a/src/main/java/asia/yulinling/workflow/constant/Status.java +++ b/src/main/java/asia/yulinling/workflow/constant/Status.java @@ -63,6 +63,12 @@ public enum Status { /** 无法手动踢出自己,请尝试退出登录操作! */ KICKOUT_SELF(5004, "无法手动踢出自己,请尝试退出登录操作!"), + /** 账号密码错误 */ + USERNAME_OR_PASSWORD_ERROR(200, "账号密码错误"), + + /** 账户已被锁定 */ + ACCOUNT_LOCKED(200, "账户已被锁定"), + /** 注册成功! */ REGISTER_SUCCESS(200, "注册成功"); diff --git a/src/main/java/asia/yulinling/workflow/controller/AuthController.java b/src/main/java/asia/yulinling/workflow/controller/AuthController.java index 0116f71..493c037 100644 --- a/src/main/java/asia/yulinling/workflow/controller/AuthController.java +++ b/src/main/java/asia/yulinling/workflow/controller/AuthController.java @@ -1,13 +1,25 @@ package asia.yulinling.workflow.controller; +import asia.yulinling.workflow.constant.Status; import asia.yulinling.workflow.dto.request.LoginRequest; import asia.yulinling.workflow.dto.request.RegisterRequest; import asia.yulinling.workflow.model.ApiResponse; import asia.yulinling.workflow.model.vo.LoginVO; import asia.yulinling.workflow.model.vo.RegisterVO; import asia.yulinling.workflow.service.AuthService; +import asia.yulinling.workflow.utils.JwtUtil; +import com.alibaba.druid.support.spring.stat.annotation.Stat; import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.LockedException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -27,15 +39,33 @@ import org.springframework.web.bind.annotation.RestController; public class AuthController { private final AuthService authService; + private final JwtUtil jwtUtil; + private final AuthenticationManager authenticationManager; @PostMapping("/login") - public ApiResponse login(@RequestBody LoginRequest loginRequest) { - return authService.login(loginRequest); + public ResponseEntity> login(@Valid @RequestBody LoginRequest loginRequest) { + try { + Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( + loginRequest.getUsername(), loginRequest.getPassword() + )); + + LoginVO loginVO = authService.login(authentication, loginRequest.getRememberMe()); + return ResponseEntity.ok().body(ApiResponse.ofStatus(Status.LOGIN_SUCCESS, loginVO)); + } catch (BadCredentialsException e) { + return ResponseEntity.ok().body(ApiResponse.ofStatus(Status.USERNAME_PASSWORD_ERROR)); + } catch (LockedException e) { + return ResponseEntity.ok().body(ApiResponse.ofStatus(Status.ACCOUNT_LOCKED)); + } } @PostMapping("/logout") - public ApiResponse logout(HttpServletRequest request) throws SecurityException { - return authService.logout(request); + public ApiResponse logout(HttpServletRequest request) { + String token = jwtUtil.getTokenFromRequest(request); + if (token == null || token.isBlank()) { + return ApiResponse.ofStatus(Status.TOKEN_EXPIRED); + } + authService.logout(token); + return ApiResponse.ofStatus(Status.SUCCESS); } @PostMapping("/register") diff --git a/src/main/java/asia/yulinling/workflow/controller/NoteController.java b/src/main/java/asia/yulinling/workflow/controller/NoteController.java new file mode 100644 index 0000000..e995295 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/controller/NoteController.java @@ -0,0 +1,10 @@ +package asia.yulinling.workflow.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.RequestMapping; + +@Slf4j +@RequestMapping("/api22") +public class NoteController { + +} diff --git a/src/main/java/asia/yulinling/workflow/controller/NotebookController.java b/src/main/java/asia/yulinling/workflow/controller/NotebookController.java new file mode 100644 index 0000000..535988c --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/controller/NotebookController.java @@ -0,0 +1,44 @@ +package asia.yulinling.workflow.controller; + +import asia.yulinling.workflow.constant.Status; +import asia.yulinling.workflow.dto.request.NotebookRequest; +import asia.yulinling.workflow.model.ApiResponse; +import asia.yulinling.workflow.model.entity.Notebook; +import asia.yulinling.workflow.service.NotebookService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@RequestMapping("/api") +@RestController +@RequiredArgsConstructor +public class NotebookController { + private final NotebookService notebookService; + + @PostMapping("/notebooks") + public ApiResponse notebooks(@Valid @RequestBody NotebookRequest notebookRequest) { + Notebook notebook = new Notebook(); + BeanUtils.copyProperties(notebookRequest, notebook); + notebookService.addNotebook(notebook); + return ApiResponse.ofStatus(Status.SUCCESS); + } + + @GetMapping("/notebooks") + public void notebooksGet() { + } + + @GetMapping("/notebooks/{id}") + public void notebooksGet(@PathVariable String id) { + } + + @PutMapping("/notebooks/{id}") + public void notebooksPut(@PathVariable String id) { + } + + @DeleteMapping("/notebooks/{id}") + public void notebooksDelete(@PathVariable String id) { + } +} diff --git a/src/main/java/asia/yulinling/workflow/controller/TestController.java b/src/main/java/asia/yulinling/workflow/controller/TestController.java index 8f27fad..7522c60 100644 --- a/src/main/java/asia/yulinling/workflow/controller/TestController.java +++ b/src/main/java/asia/yulinling/workflow/controller/TestController.java @@ -37,6 +37,7 @@ public class TestController { /** * 测试方法 GET + * * @param who 测试参数 * @return {@link Dict} */ @@ -47,6 +48,7 @@ public class TestController { /** * 测试方法 POST + * * @param map 请求的json参数 * @return {@link Dict} */ diff --git a/src/main/java/asia/yulinling/workflow/dto/request/NotebookRequest.java b/src/main/java/asia/yulinling/workflow/dto/request/NotebookRequest.java new file mode 100644 index 0000000..c822184 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/dto/request/NotebookRequest.java @@ -0,0 +1,29 @@ +package asia.yulinling.workflow.dto.request; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class NotebookRequest { + /** + * 用户id,外键 + */ + @NotBlank(message = "创建用户为空") + Long userId; + + /** + * 笔记本名称 + */ + @NotBlank(message = "笔记本名称为空") + String name; + + /** + * 笔记本颜色标识 + */ + String color; + + /** + * 笔记本图标标识 + */ + String icon; +} diff --git a/src/main/java/asia/yulinling/workflow/mapper/NoteMapper.java b/src/main/java/asia/yulinling/workflow/mapper/NoteMapper.java new file mode 100644 index 0000000..6fceffc --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/mapper/NoteMapper.java @@ -0,0 +1,16 @@ +package asia.yulinling.workflow.mapper; + +import asia.yulinling.workflow.model.entity.Note; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 笔记本Mapper + *

+ * + * @author YLL + * @since 2025/7/23 + */ +public interface NoteMapper extends BaseMapper { + +} diff --git a/src/main/java/asia/yulinling/workflow/mapper/NotebookMapper.java b/src/main/java/asia/yulinling/workflow/mapper/NotebookMapper.java new file mode 100644 index 0000000..c9111dd --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/mapper/NotebookMapper.java @@ -0,0 +1,19 @@ +package asia.yulinling.workflow.mapper; + +import asia.yulinling.workflow.model.entity.Notebook; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +/** + *

+ * 笔记本集合Mapper + *

+ * + * @author YLL + * @since 2025/6/13 + */ +@Mapper +@Component +public interface NotebookMapper extends BaseMapper { +} diff --git a/src/main/java/asia/yulinling/workflow/model/entity/Note.java b/src/main/java/asia/yulinling/workflow/model/entity/Note.java new file mode 100644 index 0000000..19d082e --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/model/entity/Note.java @@ -0,0 +1,99 @@ +package asia.yulinling.workflow.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +import java.util.Date; + +@Data +public class Note { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + Long id; + + /** + * 用户id,外键 + */ + @TableField("user_id") + Long userId; + + /** + * 笔记本id,外键 + */ + @TableField("notebook_id") + Long notebookId; + + /** + * 笔记标题 + */ + String title; + + /** + * 笔记本内容 + */ + String content; + + /** + * 笔记本内容预览,截取前200字符 + */ + @TableField("preview_text") + String previewText; + + /** + * 笔记内容字数统计 + */ + @TableField("word_count") + Integer wordCount; + + /** + * 是否置顶显示 + */ + @TableField("is_pinned") + Boolean isPinned; + + /** + * 是否归档(不显示在默认列表中) + */ + @TableField("is_archived") + Boolean isArchived; + + /** + * 是否标记为收藏 + */ + @TableField("is_favorite") + Boolean isFavorite; + + /** + * 是否需要密码查看 + */ + @TableField("password_protected") + Boolean passwordProtected; + + /** + * 创建时间 + */ + @TableField("create_time") + Date createTime; + + /** + * 更新时间 + */ + @TableField("update_time") + Date updateTime; + + /** + * 提醒时间 + */ + @TableField("reminder") + Date reminderTime; + + /** + * 笔记封面图片url + */ + @TableField("cover_image") + String coverImage; +} diff --git a/src/main/java/asia/yulinling/workflow/model/entity/Notebook.java b/src/main/java/asia/yulinling/workflow/model/entity/Notebook.java new file mode 100644 index 0000000..0c3ee1f --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/model/entity/Notebook.java @@ -0,0 +1,57 @@ +package asia.yulinling.workflow.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("wk_notebooks") +public class Notebook { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + Long id; + + /** + * 用户id,外键 + */ + @TableField("user_id") + Long userId; + + /** + * 笔记本名称 + */ + String name; + + /** + * 笔记本颜色标识 + */ + String color; + + /** + * 笔记本图标标识 + */ + String icon; + + /** + * 创建时间 + */ + @TableField("created_at") + Date createTime; + + /** + * 更新时间 + */ + @TableField("update_at") + Date updateTime; + + /** + * 笔记本内的笔记数量 + */ + Integer notesCount; +} diff --git a/src/main/java/asia/yulinling/workflow/service/AuthService.java b/src/main/java/asia/yulinling/workflow/service/AuthService.java index 4f9f960..4002cdd 100644 --- a/src/main/java/asia/yulinling/workflow/service/AuthService.java +++ b/src/main/java/asia/yulinling/workflow/service/AuthService.java @@ -6,6 +6,7 @@ import asia.yulinling.workflow.model.ApiResponse; import asia.yulinling.workflow.model.vo.LoginVO; import asia.yulinling.workflow.model.vo.RegisterVO; import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.core.Authentication; /** *

@@ -19,18 +20,16 @@ public interface AuthService { /** * 登录系统 * - * @param loginRequest 登录请求 - * @return token + * @param authentication 登录信息 */ - ApiResponse login(LoginRequest loginRequest); + LoginVO login(Authentication authentication, boolean rememberMe); /** * 退出登录 * - * @param request 退出登录请求 - * @return 请求结果 + * @param token 登录信息 */ - ApiResponse logout(HttpServletRequest request) throws SecurityException; + void logout(String token) throws SecurityException; /** * 注册 diff --git a/src/main/java/asia/yulinling/workflow/service/NoteService.java b/src/main/java/asia/yulinling/workflow/service/NoteService.java new file mode 100644 index 0000000..fd08f08 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/service/NoteService.java @@ -0,0 +1,5 @@ +package asia.yulinling.workflow.service; + +public interface NoteService { + +} diff --git a/src/main/java/asia/yulinling/workflow/service/NotebookService.java b/src/main/java/asia/yulinling/workflow/service/NotebookService.java new file mode 100644 index 0000000..16a7665 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/service/NotebookService.java @@ -0,0 +1,45 @@ +package asia.yulinling.workflow.service; + +import asia.yulinling.workflow.model.entity.Notebook; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Transactional +public interface NotebookService { + /** + * 添加笔记本 + * + * @param notebook 笔记本 + */ + void addNotebook(Notebook notebook); + + /** + * 删除笔记本 + * + * @param id 笔记本id + */ + void deleteNotebook(Long id); + + /** + * 更新笔记本 + * + * @param notebook 笔记本 + */ + void updateNotebook(Notebook notebook); + + /** + * 获取笔记本内容 + * + * @param id 笔记本id + * @return 笔记本 + */ + Notebook getNotebook(Long id); + + /** + * 获取笔记本列表 + * + * @return 笔记本列表 + */ + List getNotebookList(); +} diff --git a/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java b/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java index a251772..7e876ed 100644 --- a/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java +++ b/src/main/java/asia/yulinling/workflow/service/impl/AuthServiceImpl.java @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -47,46 +48,36 @@ public class AuthServiceImpl implements AuthService { /** * 登录系统 * - * @param loginRequest 登录请求 - * @return token + * @param authentication 登录信息 */ @Override - public ApiResponse login(LoginRequest loginRequest) { + public LoginVO login(Authentication authentication, boolean rememberMe) { + UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); - Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( - loginRequest.getUsername(), loginRequest.getPassword() - )); - SecurityContextHolder.getContext().setAuthentication(authentication); + String accessToken = jwtUtil.generateToken(authentication, rememberMe); + Long expiresIn = jwtUtil.getExpiresIn(rememberMe); - UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); - - String accessToken = jwtUtil.generateToken(authentication, false); - Long expiresIn = jwtUtil.getExpiresIn(loginRequest.getRememberMe()); - - LoginVO loginVO = LoginVO.builder() - .userId(userPrincipal.getId()) - .username(userPrincipal.getUsername()) - .accessToken(accessToken) - .expiresIn(expiresIn) - .build(); - - return ApiResponse.ofStatus(Status.LOGIN_SUCCESS, loginVO); + log.info("用户登录成功: {}", userPrincipal.getUsername()); + return LoginVO.builder() + .userId(userPrincipal.getId()) + .username(userPrincipal.getUsername()) + .accessToken(accessToken) + .expiresIn(expiresIn) + .build(); } /** * 退出登录 * - * @param request 退出登录请求 - * @return 请求结果 + * @param token 登录信息 */ @Override - public ApiResponse logout(HttpServletRequest request) throws SecurityException { + public void logout(String token) throws SecurityException { try { - jwtUtil.invalidateToken(request); + jwtUtil.invalidateToken(token); } catch (SecurityException e) { log.info("invalidateToken: {}", e.getMessage()); } - return ApiResponse.ofStatus(Status.LOGOUT); } /** diff --git a/src/main/java/asia/yulinling/workflow/service/impl/NoteServiceImpl.java b/src/main/java/asia/yulinling/workflow/service/impl/NoteServiceImpl.java new file mode 100644 index 0000000..a9cc988 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/service/impl/NoteServiceImpl.java @@ -0,0 +1,10 @@ +package asia.yulinling.workflow.service.impl; + +import asia.yulinling.workflow.service.NoteService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class NoteServiceImpl implements NoteService { +} diff --git a/src/main/java/asia/yulinling/workflow/service/impl/NotebookServiceImpl.java b/src/main/java/asia/yulinling/workflow/service/impl/NotebookServiceImpl.java new file mode 100644 index 0000000..80af121 --- /dev/null +++ b/src/main/java/asia/yulinling/workflow/service/impl/NotebookServiceImpl.java @@ -0,0 +1,44 @@ +package asia.yulinling.workflow.service.impl; + +import asia.yulinling.workflow.mapper.NotebookMapper; +import asia.yulinling.workflow.model.entity.Notebook; +import asia.yulinling.workflow.service.NotebookService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class NotebookServiceImpl implements NotebookService { + private final NotebookMapper notebookMapper; + + @Override + public void addNotebook(Notebook notebook) { + if (notebook == null) { + return; + } + + notebookMapper.insert(notebook); + } + + @Override + public void deleteNotebook(Long id) { + + } + + @Override + public void updateNotebook(Notebook notebook) { + + } + + @Override + public Notebook getNotebook(Long id) { + return null; + } + + @Override + public List getNotebookList() { + return List.of(); + } +} diff --git a/src/main/java/asia/yulinling/workflow/utils/JwtUtil.java b/src/main/java/asia/yulinling/workflow/utils/JwtUtil.java index b720b02..5ebcbeb 100644 --- a/src/main/java/asia/yulinling/workflow/utils/JwtUtil.java +++ b/src/main/java/asia/yulinling/workflow/utils/JwtUtil.java @@ -91,11 +91,11 @@ public class JwtUtil { // 3. 构建JwtBuilder JwtBuilder builder = Jwts.builder() - .setSubject(username) - .claim("userId", userId) - .setIssuedAt(now) - .setExpiration(expiration) - .signWith(this.key()); + .setSubject(username) + .claim("userId", userId) + .setIssuedAt(now) + .setExpiration(expiration) + .signWith(this.key()); // 4. 生成token String token = builder.compact(); @@ -122,10 +122,10 @@ public class JwtUtil { try { // 1. 解析Token Claims claims = Jwts.parserBuilder() - .setSigningKey(this.key()) - .build() - .parseClaimsJws(token) - .getBody(); + .setSigningKey(this.key()) + .build() + .parseClaimsJws(token) + .getBody(); String username = claims.getSubject(); Object userIdObj = claims.get("userId"); long userId; @@ -199,9 +199,9 @@ public class JwtUtil { // 2. 根据密钥解析token try { Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parse(token); + .setSigningKey(key) + .build() + .parse(token); // 3. 解析正确 return true; } catch (JwtException e) { @@ -214,10 +214,9 @@ public class JwtUtil { /** * 设置Token过期 * - * @param request 请求 + * @param token 登录信息 */ - public void invalidateToken(HttpServletRequest request) { - String token = getTokenFromRequest(request); + public void invalidateToken(String token) { String username = parseToken(token).getSubject(); stringRedisTemplate.delete(Const.REDIS_JWT_KEY_PREFIX + username); } diff --git a/src/main/resources/db/schema.sql b/src/main/resources/db/schema.sql index f38ef38..0bd4b16 100644 --- a/src/main/resources/db/schema.sql +++ b/src/main/resources/db/schema.sql @@ -86,26 +86,26 @@ CREATE TABLE `wk_role_user` DROP TABLE IF EXISTS `wk_notebooks`; CREATE TABLE `wk_notebooks` ( - id VARCHAR(36) PRIMARY KEY, -- 笔记本唯一标识 - user_id bigint(64) NOT NULL COMMENT '所属用户ID', -- 笔记本所有者 - name VARCHAR(100) NOT NULL COMMENT '笔记本名称', -- 显示名称 - color VARCHAR(20) COMMENT '笔记本颜色标记,用于UI显示', -- 如#FF0000 - icon VARCHAR(50) COMMENT '笔记本图标标识', -- 如media-book + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '笔记本主键', -- 笔记本唯一标识 + user_id bigint(64) NOT NULL COMMENT '所属用户ID', -- 笔记本所有者 + name VARCHAR(100) NOT NULL COMMENT '笔记本名称', -- 显示名称 + color VARCHAR(20) COMMENT '笔记本颜色标记,用于UI显示', -- 如#FF0000 + icon VARCHAR(50) COMMENT '笔记本图标标识', -- 如media-book created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '最后更新时间', - notes_count INT DEFAULT 0 COMMENT '包含的笔记数量', -- 用于快速统计 + notes_count INT DEFAULT 0 COMMENT '包含的笔记数量', -- 用于快速统计 FOREIGN KEY (user_id) REFERENCES wk_user (id) ON DELETE CASCADE, - CONSTRAINT chk_notebook_name CHECK (name <> '') -- 名称不能为空 -) COMMENT '用户笔记本分类表,用于组织管理笔记'; + CONSTRAINT chk_notebook_name CHECK (name <> '') -- 名称不能为空 +) COMMENT '用户笔记本'; DROP TABLE IF EXISTS `wk_notes`; CREATE TABLE `wk_notes` ( - id VARCHAR(36) PRIMARY KEY COMMENT '笔记唯一标识', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '笔记唯一标识', user_id bigint(64) NOT NULL COMMENT '作者用户ID', - notebook_id VARCHAR(36) COMMENT '所属笔记本ID,可为空', + notebook_id BIGINT COMMENT '所属笔记本ID,可为空', title VARCHAR(255) COMMENT '笔记标题,可为空(自动提取内容首行)', - content TEXT NOT NULL COMMENT '笔记正文内容,支持Markdown格式', + content TEXT NOT NULL COMMENT '笔记正文内容,支持Markdown格式', preview_text VARCHAR(200) COMMENT '内容预览,自动提取前200字符', word_count INTEGER DEFAULT 0 COMMENT '自动计算的字数统计', is_pinned BOOLEAN DEFAULT FALSE COMMENT '是否置顶显示', @@ -124,8 +124,8 @@ CREATE TABLE `wk_notes` DROP TABLE IF EXISTS `wk_tags`; CREATE TABLE `wk_tags` ( - id VARCHAR(36) PRIMARY KEY COMMENT '标签唯一标识', - user_id bigint(64) NOT NULL COMMENT '所属用户ID', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '标签唯一标识', + user_id bigint(64) NOT NULL COMMENT '所属用户ID', name VARCHAR(50) NOT NULL COMMENT '标签名称', color VARCHAR(20) COMMENT '标签颜色,用于UI显示', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', @@ -138,8 +138,8 @@ CREATE TABLE `wk_tags` DROP TABLE IF EXISTS `wk_note_tags`; CREATE TABLE `wk_note_tags` ( - note_id VARCHAR(36) NOT NULL COMMENT '关联的笔记ID', - tag_id VARCHAR(36) NOT NULL COMMENT '关联的标签ID', + note_id BIGINT NOT NULL COMMENT '关联的笔记ID', + tag_id BIGINT NOT NULL COMMENT '关联的标签ID', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '关联创建时间', PRIMARY KEY (note_id, tag_id) COMMENT '联合主键,防止重复关联', FOREIGN KEY (note_id) REFERENCES wk_notes (id) ON DELETE CASCADE, @@ -149,8 +149,8 @@ CREATE TABLE `wk_note_tags` DROP TABLE IF EXISTS `wk_attachments`; CREATE TABLE wk_attachments ( - id VARCHAR(36) PRIMARY KEY COMMENT '附件唯一标识', - note_id VARCHAR(36) NOT NULL COMMENT '所属笔记ID', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '附件唯一标识', + note_id BIGINT NOT NULL COMMENT '所属笔记ID', file_path VARCHAR(255) NOT NULL COMMENT '文件存储路径', file_type VARCHAR(50) NOT NULL COMMENT '文件MIME类型,如image/png', file_name VARCHAR(255) NOT NULL COMMENT '原始文件名', diff --git a/src/main/resources/db/test.sql b/src/main/resources/db/test.sql index 8766c05..46e1247 100644 --- a/src/main/resources/db/test.sql +++ b/src/main/resources/db/test.sql @@ -1 +1,6 @@ -SELECT * FROM wk_notes; \ No newline at end of file +SELECT * FROM wk_notes; +SELECT * FROM wk_attachments; +SELECT * FROM wk_note_tags; +SELECT * FROM wk_tags; +SELECT * FROM wk_notebooks; + diff --git a/src/main/resources/mapper/NoteMapper.xml b/src/main/resources/mapper/NoteMapper.xml new file mode 100644 index 0000000..3dfa231 --- /dev/null +++ b/src/main/resources/mapper/NoteMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/NotebookMapper.xml b/src/main/resources/mapper/NotebookMapper.xml new file mode 100644 index 0000000..a92eb37 --- /dev/null +++ b/src/main/resources/mapper/NotebookMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file