add Notebook

This commit is contained in:
雨霖铃 2025-07-31 21:24:31 +08:00
parent f46f6d97e1
commit 717c3509b4
23 changed files with 494 additions and 70 deletions

View File

@ -87,6 +87,7 @@ public class AopLog {
/** /**
* 获取方法参数名和参数值 * 获取方法参数名和参数值
*
* @param joinPoint 切入点 * @param joinPoint 切入点
* @return 接口参数和参数值 * @return 接口参数和参数值
*/ */
@ -112,6 +113,7 @@ public class AopLog {
/** /**
* 获取ip地址 * 获取ip地址
*
* @param request 请求体 * @param request 请求体
* @return 返回ip地址 * @return 返回ip地址
*/ */
@ -150,6 +152,7 @@ public class AopLog {
private static boolean isInvalidIp(String ip) { private static boolean isInvalidIp(String ip) {
return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip); return ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip);
} }
@Data @Data
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor

View File

@ -60,6 +60,7 @@ public class SecurityConfig {
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll() .requestMatchers("/auth/**").permitAll()
.requestMatchers("/auth/register").permitAll() .requestMatchers("/auth/register").permitAll()
.requestMatchers("/api/**").permitAll()
// .requestMatchers("/user/**").permitAll() // .requestMatchers("/user/**").permitAll()
.anyRequest().access((authenticationSupplier, requestAuthorizationContext) -> { .anyRequest().access((authenticationSupplier, requestAuthorizationContext) -> {
HttpServletRequest request = requestAuthorizationContext.getRequest(); HttpServletRequest request = requestAuthorizationContext.getRequest();

View File

@ -63,6 +63,12 @@ public enum Status {
/** 无法手动踢出自己,请尝试退出登录操作! */ /** 无法手动踢出自己,请尝试退出登录操作! */
KICKOUT_SELF(5004, "无法手动踢出自己,请尝试退出登录操作!"), KICKOUT_SELF(5004, "无法手动踢出自己,请尝试退出登录操作!"),
/** 账号密码错误 */
USERNAME_OR_PASSWORD_ERROR(200, "账号密码错误"),
/** 账户已被锁定 */
ACCOUNT_LOCKED(200, "账户已被锁定"),
/** 注册成功! */ /** 注册成功! */
REGISTER_SUCCESS(200, "注册成功"); REGISTER_SUCCESS(200, "注册成功");

View File

@ -1,13 +1,25 @@
package asia.yulinling.workflow.controller; package asia.yulinling.workflow.controller;
import asia.yulinling.workflow.constant.Status;
import asia.yulinling.workflow.dto.request.LoginRequest; import asia.yulinling.workflow.dto.request.LoginRequest;
import asia.yulinling.workflow.dto.request.RegisterRequest; import asia.yulinling.workflow.dto.request.RegisterRequest;
import asia.yulinling.workflow.model.ApiResponse; import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.vo.LoginVO; import asia.yulinling.workflow.model.vo.LoginVO;
import asia.yulinling.workflow.model.vo.RegisterVO; import asia.yulinling.workflow.model.vo.RegisterVO;
import asia.yulinling.workflow.service.AuthService; 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.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; 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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -27,15 +39,33 @@ import org.springframework.web.bind.annotation.RestController;
public class AuthController { public class AuthController {
private final AuthService authService; private final AuthService authService;
private final JwtUtil jwtUtil;
private final AuthenticationManager authenticationManager;
@PostMapping("/login") @PostMapping("/login")
public ApiResponse<LoginVO> login(@RequestBody LoginRequest loginRequest) { public ResponseEntity<ApiResponse<LoginVO>> login(@Valid @RequestBody LoginRequest loginRequest) {
return authService.login(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") @PostMapping("/logout")
public ApiResponse<?> logout(HttpServletRequest request) throws SecurityException { public ApiResponse<?> logout(HttpServletRequest request) {
return authService.logout(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") @PostMapping("/register")

View File

@ -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 {
}

View File

@ -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) {
}
}

View File

@ -37,6 +37,7 @@ public class TestController {
/** /**
* 测试方法 GET * 测试方法 GET
*
* @param who 测试参数 * @param who 测试参数
* @return {@link Dict} * @return {@link Dict}
*/ */
@ -47,6 +48,7 @@ public class TestController {
/** /**
* 测试方法 POST * 测试方法 POST
*
* @param map 请求的json参数 * @param map 请求的json参数
* @return {@link Dict} * @return {@link Dict}
*/ */

View File

@ -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;
}

View File

@ -0,0 +1,16 @@
package asia.yulinling.workflow.mapper;
import asia.yulinling.workflow.model.entity.Note;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 笔记本Mapper
* </p>
*
* @author YLL
* @since 2025/7/23
*/
public interface NoteMapper extends BaseMapper<Note> {
}

View File

@ -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;
/**
* <p>
* 笔记本集合Mapper
* </p>
*
* @author YLL
* @since 2025/6/13
*/
@Mapper
@Component
public interface NotebookMapper extends BaseMapper<Notebook> {
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -6,6 +6,7 @@ import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.vo.LoginVO; import asia.yulinling.workflow.model.vo.LoginVO;
import asia.yulinling.workflow.model.vo.RegisterVO; import asia.yulinling.workflow.model.vo.RegisterVO;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
/** /**
* <p> * <p>
@ -19,18 +20,16 @@ public interface AuthService {
/** /**
* 登录系统 * 登录系统
* *
* @param loginRequest 登录请求 * @param authentication 登录信息
* @return token
*/ */
ApiResponse<LoginVO> login(LoginRequest loginRequest); LoginVO login(Authentication authentication, boolean rememberMe);
/** /**
* 退出登录 * 退出登录
* *
* @param request 退出登录请求 * @param token 登录信息
* @return 请求结果
*/ */
ApiResponse<?> logout(HttpServletRequest request) throws SecurityException; void logout(String token) throws SecurityException;
/** /**
* 注册 * 注册

View File

@ -0,0 +1,5 @@
package asia.yulinling.workflow.service;
public interface NoteService {
}

View File

@ -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<Notebook> getNotebookList();
}

View File

@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -47,46 +48,36 @@ public class AuthServiceImpl implements AuthService {
/** /**
* 登录系统 * 登录系统
* *
* @param loginRequest 登录请求 * @param authentication 登录信息
* @return token
*/ */
@Override @Override
public ApiResponse<LoginVO> login(LoginRequest loginRequest) { public LoginVO login(Authentication authentication, boolean rememberMe) {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(), loginRequest.getPassword()
));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
String accessToken = jwtUtil.generateToken(authentication, false); String accessToken = jwtUtil.generateToken(authentication, rememberMe);
Long expiresIn = jwtUtil.getExpiresIn(loginRequest.getRememberMe()); Long expiresIn = jwtUtil.getExpiresIn(rememberMe);
LoginVO loginVO = LoginVO.builder() log.info("用户登录成功: {}", userPrincipal.getUsername());
return LoginVO.builder()
.userId(userPrincipal.getId()) .userId(userPrincipal.getId())
.username(userPrincipal.getUsername()) .username(userPrincipal.getUsername())
.accessToken(accessToken) .accessToken(accessToken)
.expiresIn(expiresIn) .expiresIn(expiresIn)
.build(); .build();
return ApiResponse.ofStatus(Status.LOGIN_SUCCESS, loginVO);
} }
/** /**
* 退出登录 * 退出登录
* *
* @param request 退出登录请求 * @param token 登录信息
* @return 请求结果
*/ */
@Override @Override
public ApiResponse<?> logout(HttpServletRequest request) throws SecurityException { public void logout(String token) throws SecurityException {
try { try {
jwtUtil.invalidateToken(request); jwtUtil.invalidateToken(token);
} catch (SecurityException e) { } catch (SecurityException e) {
log.info("invalidateToken: {}", e.getMessage()); log.info("invalidateToken: {}", e.getMessage());
} }
return ApiResponse.ofStatus(Status.LOGOUT);
} }
/** /**

View File

@ -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 {
}

View File

@ -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<Notebook> getNotebookList() {
return List.of();
}
}

View File

@ -214,10 +214,9 @@ public class JwtUtil {
/** /**
* 设置Token过期 * 设置Token过期
* *
* @param request 请求 * @param token 登录信息
*/ */
public void invalidateToken(HttpServletRequest request) { public void invalidateToken(String token) {
String token = getTokenFromRequest(request);
String username = parseToken(token).getSubject(); String username = parseToken(token).getSubject();
stringRedisTemplate.delete(Const.REDIS_JWT_KEY_PREFIX + username); stringRedisTemplate.delete(Const.REDIS_JWT_KEY_PREFIX + username);
} }

View File

@ -86,7 +86,7 @@ CREATE TABLE `wk_role_user`
DROP TABLE IF EXISTS `wk_notebooks`; DROP TABLE IF EXISTS `wk_notebooks`;
CREATE TABLE `wk_notebooks` CREATE TABLE `wk_notebooks`
( (
id VARCHAR(36) PRIMARY KEY, -- 笔记本唯一标识 id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '笔记本主键', -- 笔记本唯一标识
user_id bigint(64) NOT NULL COMMENT '所属用户ID', -- 笔记本所有者 user_id bigint(64) NOT NULL COMMENT '所属用户ID', -- 笔记本所有者
name VARCHAR(100) NOT NULL COMMENT '笔记本名称', -- 显示名称 name VARCHAR(100) NOT NULL COMMENT '笔记本名称', -- 显示名称
color VARCHAR(20) COMMENT '笔记本颜色标记用于UI显示', -- 如#FF0000 color VARCHAR(20) COMMENT '笔记本颜色标记用于UI显示', -- 如#FF0000
@ -96,14 +96,14 @@ CREATE TABLE `wk_notebooks`
notes_count INT DEFAULT 0 COMMENT '包含的笔记数量', -- 用于快速统计 notes_count INT DEFAULT 0 COMMENT '包含的笔记数量', -- 用于快速统计
FOREIGN KEY (user_id) REFERENCES wk_user (id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES wk_user (id) ON DELETE CASCADE,
CONSTRAINT chk_notebook_name CHECK (name <> '') -- 名称不能为空 CONSTRAINT chk_notebook_name CHECK (name <> '') -- 名称不能为空
) COMMENT '用户笔记本分类表,用于组织管理笔记'; ) COMMENT '用户笔记本';
DROP TABLE IF EXISTS `wk_notes`; DROP TABLE IF EXISTS `wk_notes`;
CREATE TABLE `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', user_id bigint(64) NOT NULL COMMENT '作者用户ID',
notebook_id VARCHAR(36) COMMENT '所属笔记本ID可为空', notebook_id BIGINT COMMENT '所属笔记本ID可为空',
title VARCHAR(255) COMMENT '笔记标题,可为空(自动提取内容首行)', title VARCHAR(255) COMMENT '笔记标题,可为空(自动提取内容首行)',
content TEXT NOT NULL COMMENT '笔记正文内容支持Markdown格式', content TEXT NOT NULL COMMENT '笔记正文内容支持Markdown格式',
preview_text VARCHAR(200) COMMENT '内容预览自动提取前200字符', preview_text VARCHAR(200) COMMENT '内容预览自动提取前200字符',
@ -124,7 +124,7 @@ CREATE TABLE `wk_notes`
DROP TABLE IF EXISTS `wk_tags`; DROP TABLE IF EXISTS `wk_tags`;
CREATE TABLE `wk_tags` CREATE TABLE `wk_tags`
( (
id VARCHAR(36) PRIMARY KEY COMMENT '标签唯一标识', id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '标签唯一标识',
user_id bigint(64) NOT NULL COMMENT '所属用户ID', user_id bigint(64) NOT NULL COMMENT '所属用户ID',
name VARCHAR(50) NOT NULL COMMENT '标签名称', name VARCHAR(50) NOT NULL COMMENT '标签名称',
color VARCHAR(20) COMMENT '标签颜色用于UI显示', color VARCHAR(20) COMMENT '标签颜色用于UI显示',
@ -138,8 +138,8 @@ CREATE TABLE `wk_tags`
DROP TABLE IF EXISTS `wk_note_tags`; DROP TABLE IF EXISTS `wk_note_tags`;
CREATE TABLE `wk_note_tags` CREATE TABLE `wk_note_tags`
( (
note_id VARCHAR(36) NOT NULL COMMENT '关联的笔记ID', note_id BIGINT NOT NULL COMMENT '关联的笔记ID',
tag_id VARCHAR(36) NOT NULL COMMENT '关联的标签ID', tag_id BIGINT NOT NULL COMMENT '关联的标签ID',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '关联创建时间', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '关联创建时间',
PRIMARY KEY (note_id, tag_id) COMMENT '联合主键,防止重复关联', PRIMARY KEY (note_id, tag_id) COMMENT '联合主键,防止重复关联',
FOREIGN KEY (note_id) REFERENCES wk_notes (id) ON DELETE CASCADE, 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`; DROP TABLE IF EXISTS `wk_attachments`;
CREATE TABLE wk_attachments CREATE TABLE wk_attachments
( (
id VARCHAR(36) PRIMARY KEY COMMENT '附件唯一标识', id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '附件唯一标识',
note_id VARCHAR(36) NOT NULL COMMENT '所属笔记ID', note_id BIGINT NOT NULL COMMENT '所属笔记ID',
file_path VARCHAR(255) NOT NULL COMMENT '文件存储路径', file_path VARCHAR(255) NOT NULL COMMENT '文件存储路径',
file_type VARCHAR(50) NOT NULL COMMENT '文件MIME类型如image/png', file_type VARCHAR(50) NOT NULL COMMENT '文件MIME类型如image/png',
file_name VARCHAR(255) NOT NULL COMMENT '原始文件名', file_name VARCHAR(255) NOT NULL COMMENT '原始文件名',

View File

@ -1 +1,6 @@
SELECT * FROM wk_notes; SELECT * FROM wk_notes;
SELECT * FROM wk_attachments;
SELECT * FROM wk_note_tags;
SELECT * FROM wk_tags;
SELECT * FROM wk_notebooks;

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="asia.yulinling.workflow.mapper.NoteMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="asia.yulinling.workflow.mapper.NotebookMapper">
</mapper>