Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
1、执行任务的时候,首先分析任务,然后将该任务分成多个可执行的小任务,一步一步执行。
|
|
||||||
2、不要启动我项目的服务
|
|
||||||
3、若是新建项目或者开发新的功能,首先使用context7 MCP服务来寻找对应的文档
|
|
||||||
4、若是修改业务逻辑等,就不要使用context7 MCP服务来寻找对应的文档,先查看查看前端该功能对应的后端接口,查看后端接口的逻辑,若是已经实现就返回前端处理逻辑,若是后端还们没有实现,则先处理后端在处理前端。
|
|
||||||
5、若是apply_diff失败或者文件修改编辑失败,就要先保存该文件然后重新读取在做修改再来apply_diff
|
|
||||||
6、使用filesystem MCP服务
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"sequentialthinking": {
|
|
||||||
"command": "npx",
|
|
||||||
"args": [
|
|
||||||
"-y",
|
|
||||||
"@modelcontextprotocol/server-sequential-thinking"
|
|
||||||
],
|
|
||||||
"alwaysAllow": [
|
|
||||||
"sequentialthinking"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
100
README.md
Normal file
100
README.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# 笔记应用 (Biji App)
|
||||||
|
|
||||||
|
这是一个功能完善的全栈笔记应用程序,采用前后端分离架构。前端使用 Vue 3 构建,后端使用 Spring Boot 3 实现。
|
||||||
|
|
||||||
|
## ✨ 功能特性 (Features)
|
||||||
|
|
||||||
|
* **用户认证**: 支持用户注册、登录和 JWT (JSON Web Token) 认证。
|
||||||
|
* **Markdown 笔记**: 提供功能强大的 Markdown 编辑器,支持实时预览和丰富的格式化选项。
|
||||||
|
* **图片管理**: 支持在笔记中上传、插入和管理图片。
|
||||||
|
* **笔记组织**: 用户可以创建分组 (Categories/Groups) 来管理和组织笔记。
|
||||||
|
* **回收站**: 提供回收站功能,可以恢复被误删除的笔记或分组。
|
||||||
|
* **系统设置**: 提供基本的系统配置功能。
|
||||||
|
|
||||||
|
## 🛠️ 技术栈 (Tech Stack)
|
||||||
|
|
||||||
|
### 后端 (Backend - `biji-houdaun`)
|
||||||
|
|
||||||
|
* **框架 (Framework)**: Spring Boot 3.5.0
|
||||||
|
* **语言 (Language)**: Java 17
|
||||||
|
* **数据访问 (Data Access)**: MyBatis-Plus 3.5.7
|
||||||
|
* **数据库 (Database)**: SQLite
|
||||||
|
* **API 文档 (API Docs)**: Knife4j / SpringDoc
|
||||||
|
* **安全 (Security)**: Spring Security, JJWT
|
||||||
|
* **工具库 (Utilities)**: Lombok, Hutool, Commons Codec
|
||||||
|
|
||||||
|
### 前端 (Frontend - `biji-qianduan`)
|
||||||
|
|
||||||
|
* **框架 (Framework)**: Vue 3
|
||||||
|
* **构建工具 (Build Tool)**: Vite
|
||||||
|
* **UI 库 (UI Library)**: Element Plus
|
||||||
|
* **状态管理 (State Management)**: Pinia
|
||||||
|
* **路由 (Routing)**: Vue Router
|
||||||
|
* **Markdown 编辑器**: Vditor / @kangc/v-md-editor
|
||||||
|
* **HTTP 客户端 (HTTP Client)**: Axios (封装在 `src/utils/axios.js` 中)
|
||||||
|
|
||||||
|
## 📂 项目结构 (Project Structure)
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── biji-houdaun/ # 后端 Spring Boot 项目
|
||||||
|
│ ├── src/main/java/ # Java 源码
|
||||||
|
│ │ └── com/test/bijihoudaun/
|
||||||
|
│ │ ├── controller/ # API 控制器
|
||||||
|
│ │ ├── service/ # 业务逻辑服务
|
||||||
|
│ │ ├── mapper/ # MyBatis 数据映射
|
||||||
|
│ │ ├── entity/ # 数据库实体
|
||||||
|
│ │ ├── config/ # 应用配置
|
||||||
|
│ │ └── common/ # 通用工具 (异常处理、响应)
|
||||||
|
│ └── pom.xml # Maven 依赖配置
|
||||||
|
│
|
||||||
|
├── biji-qianduan/ # 前端 Vue 项目
|
||||||
|
│ ├── src/ # 前端源码
|
||||||
|
│ │ ├── api/ # API 请求模块
|
||||||
|
│ │ ├── assets/ # 静态资源 (CSS, images)
|
||||||
|
│ │ ├── components/ # Vue 组件
|
||||||
|
│ │ ├── router/ # 路由配置
|
||||||
|
│ │ ├── stores/ # Pinia 状态管理
|
||||||
|
│ │ └── utils/ # 工具函数
|
||||||
|
│ └── package.json # NPM 依赖配置
|
||||||
|
│
|
||||||
|
├── sql/ # 数据库初始化脚本
|
||||||
|
├── uploads/ # 用户上传文件目录
|
||||||
|
├── doc/ # 项目相关文档
|
||||||
|
└── README.md # 本文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 快速开始 (Getting Started)
|
||||||
|
|
||||||
|
### 环境要求
|
||||||
|
|
||||||
|
* JDK 17
|
||||||
|
* Maven 3.x
|
||||||
|
* Node.js 18+
|
||||||
|
* pnpm (或 npm/yarn)
|
||||||
|
|
||||||
|
### 后端启动
|
||||||
|
|
||||||
|
1. **克隆项目**: `git clone <repository-url>`
|
||||||
|
2. **数据库初始化**: 使用 `sql/` 目录下的脚本初始化 SQLite 数据库 (`mydatabase.db`)。
|
||||||
|
3. **配置**: 检查 `biji-houdaun/src/main/resources/application-dev.yml` 中的配置是否正确。
|
||||||
|
4. **运行**: 在 `biji-houdaun` 目录下,通过 IDE 直接运行 `BijiHoudaunApplication.java` 或使用 Maven:
|
||||||
|
```bash
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端启动
|
||||||
|
|
||||||
|
1. **进入目录**: `cd biji-qianduan`
|
||||||
|
2. **安装依赖**:
|
||||||
|
```bash
|
||||||
|
pnpm install
|
||||||
|
# 或者使用 npm / yarn
|
||||||
|
# npm install
|
||||||
|
# yarn install
|
||||||
|
```
|
||||||
|
3. **运行开发服务器**:
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
4. **访问应用**: 在浏览器中打开 `http://localhost:5173` (或其他 Vite 指定的端口)。
|
||||||
@@ -45,11 +45,14 @@ public class SecurityConfig {
|
|||||||
@Value("${jwt.tokenHead}")
|
@Value("${jwt.tokenHead}")
|
||||||
private String tokenHead;
|
private String tokenHead;
|
||||||
|
|
||||||
|
|
||||||
|
// 配置了密码编码器
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 配置了安全过滤器链
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter = new JwtAuthenticationTokenFilter(userDetailsService, jwtTokenUtil, tokenHeader, tokenHead);
|
JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter = new JwtAuthenticationTokenFilter(userDetailsService, jwtTokenUtil, tokenHeader, tokenHead);
|
||||||
@@ -69,7 +72,7 @@ public class SecurityConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
http
|
http
|
||||||
.csrf(csrf -> csrf.disable())
|
.csrf(csrf -> csrf.disable()) // 配置了 CSRF 禁用、无状态会话管理
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
.authorizeHttpRequests(authz -> authz
|
.authorizeHttpRequests(authz -> authz
|
||||||
// 1. 动态允许公共端点
|
// 1. 动态允许公共端点
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||||||
if (ObjectUtil.isNull(user)) {
|
if (ObjectUtil.isNull(user)) {
|
||||||
throw new UsernameNotFoundException("User not found with username: " + username);
|
throw new UsernameNotFoundException("User not found with username: " + username);
|
||||||
}
|
}
|
||||||
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
|
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>()); // 账号,密码,权限
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,267 @@
|
|||||||
|
package com.test.bijihoudaun.util;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间工具类
|
||||||
|
* 提供常用的时间操作方法
|
||||||
|
*
|
||||||
|
* @author CodeGeeX
|
||||||
|
* @since 2024
|
||||||
|
*/
|
||||||
|
public class DateTimeUtil {
|
||||||
|
|
||||||
|
// 常用的时间格式
|
||||||
|
public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
|
||||||
|
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
|
||||||
|
public static final String COMPACT_DATETIME_FORMAT = "yyyyMMddHHmmss";
|
||||||
|
public static final String COMPACT_DATE_FORMAT = "yyyyMMdd";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间(LocalDateTime)
|
||||||
|
*
|
||||||
|
* @return 当前时间
|
||||||
|
*/
|
||||||
|
public static LocalDateTime getCurrentDateTime() {
|
||||||
|
return LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期(LocalDate)
|
||||||
|
*
|
||||||
|
* @return 当前日期
|
||||||
|
*/
|
||||||
|
public static LocalDate getCurrentDate() {
|
||||||
|
return LocalDate.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间戳(毫秒)
|
||||||
|
*
|
||||||
|
* @return 当前时间戳
|
||||||
|
*/
|
||||||
|
public static long getCurrentTimestamp() {
|
||||||
|
return System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间戳(秒)
|
||||||
|
*
|
||||||
|
* @return 当前时间戳(秒)
|
||||||
|
*/
|
||||||
|
public static long getCurrentTimestampSeconds() {
|
||||||
|
return System.currentTimeMillis() / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转LocalDateTime
|
||||||
|
* 使用默认格式:yyyy-MM-dd HH:mm:ss
|
||||||
|
*
|
||||||
|
* @param dateTimeStr 时间字符串
|
||||||
|
* @return LocalDateTime对象
|
||||||
|
*/
|
||||||
|
public static LocalDateTime stringToDateTime(String dateTimeStr) {
|
||||||
|
return stringToDateTime(dateTimeStr, DEFAULT_DATETIME_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转LocalDateTime
|
||||||
|
*
|
||||||
|
* @param dateTimeStr 时间字符串
|
||||||
|
* @param pattern 时间格式
|
||||||
|
* @return LocalDateTime对象
|
||||||
|
*/
|
||||||
|
public static LocalDateTime stringToDateTime(String dateTimeStr, String pattern) {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
return LocalDateTime.parse(dateTimeStr, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转LocalDate
|
||||||
|
* 使用默认格式:yyyy-MM-dd
|
||||||
|
*
|
||||||
|
* @param dateStr 日期字符串
|
||||||
|
* @return LocalDate对象
|
||||||
|
*/
|
||||||
|
public static LocalDate stringToDate(String dateStr) {
|
||||||
|
return stringToDate(dateStr, DEFAULT_DATE_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转LocalDate
|
||||||
|
*
|
||||||
|
* @param dateStr 日期字符串
|
||||||
|
* @param pattern 日期格式
|
||||||
|
* @return LocalDate对象
|
||||||
|
*/
|
||||||
|
public static LocalDate stringToDate(String dateStr, String pattern) {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
return LocalDate.parse(dateStr, formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDateTime转字符串
|
||||||
|
* 使用默认格式:yyyy-MM-dd HH:mm:ss
|
||||||
|
*
|
||||||
|
* @param dateTime LocalDateTime对象
|
||||||
|
* @return 时间字符串
|
||||||
|
*/
|
||||||
|
public static String dateTimeToString(LocalDateTime dateTime) {
|
||||||
|
return dateTimeToString(dateTime, DEFAULT_DATETIME_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDateTime转字符串
|
||||||
|
*
|
||||||
|
* @param dateTime LocalDateTime对象
|
||||||
|
* @param pattern 时间格式
|
||||||
|
* @return 时间字符串
|
||||||
|
*/
|
||||||
|
public static String dateTimeToString(LocalDateTime dateTime, String pattern) {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
return dateTime.format(formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDate转字符串
|
||||||
|
* 使用默认格式:yyyy-MM-dd
|
||||||
|
*
|
||||||
|
* @param date LocalDate对象
|
||||||
|
* @return 日期字符串
|
||||||
|
*/
|
||||||
|
public static String dateToString(LocalDate date) {
|
||||||
|
return dateToString(date, DEFAULT_DATE_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDate转字符串
|
||||||
|
*
|
||||||
|
* @param date LocalDate对象
|
||||||
|
* @param pattern 日期格式
|
||||||
|
* @return 日期字符串
|
||||||
|
*/
|
||||||
|
public static String dateToString(LocalDate date, String pattern) {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
return date.format(formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳转LocalDateTime
|
||||||
|
*
|
||||||
|
* @param timestamp 时间戳(毫秒)
|
||||||
|
* @return LocalDateTime对象
|
||||||
|
*/
|
||||||
|
public static LocalDateTime timestampToDateTime(long timestamp) {
|
||||||
|
return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDateTime转时间戳
|
||||||
|
*
|
||||||
|
* @param dateTime LocalDateTime对象
|
||||||
|
* @return 时间戳(毫秒)
|
||||||
|
*/
|
||||||
|
public static long dateTimeToTimestamp(LocalDateTime dateTime) {
|
||||||
|
return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date转LocalDateTime
|
||||||
|
*
|
||||||
|
* @param date Date对象
|
||||||
|
* @return LocalDateTime对象
|
||||||
|
*/
|
||||||
|
public static LocalDateTime dateToDateTime(Date date) {
|
||||||
|
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDateTime转Date
|
||||||
|
*
|
||||||
|
* @param dateTime LocalDateTime对象
|
||||||
|
* @return Date对象
|
||||||
|
*/
|
||||||
|
public static Date dateTimeToDate(LocalDateTime dateTime) {
|
||||||
|
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间的字符串表示
|
||||||
|
* 使用默认格式:yyyy-MM-dd HH:mm:ss
|
||||||
|
*
|
||||||
|
* @return 当前时间字符串
|
||||||
|
*/
|
||||||
|
public static String getCurrentDateTimeString() {
|
||||||
|
return dateTimeToString(getCurrentDateTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前时间的字符串表示
|
||||||
|
*
|
||||||
|
* @param pattern 时间格式
|
||||||
|
* @return 当前时间字符串
|
||||||
|
*/
|
||||||
|
public static String getCurrentDateTimeString(String pattern) {
|
||||||
|
return dateTimeToString(getCurrentDateTime(), pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期的字符串表示
|
||||||
|
* 使用默认格式:yyyy-MM-dd
|
||||||
|
*
|
||||||
|
* @return 当前日期字符串
|
||||||
|
*/
|
||||||
|
public static String getCurrentDateString() {
|
||||||
|
return dateToString(getCurrentDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前日期的字符串表示
|
||||||
|
*
|
||||||
|
* @param pattern 日期格式
|
||||||
|
* @return 当前日期字符串
|
||||||
|
*/
|
||||||
|
public static String getCurrentDateString(String pattern) {
|
||||||
|
return dateToString(getCurrentDate(), pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字符串是否为有效的日期时间格式
|
||||||
|
*
|
||||||
|
* @param dateTimeStr 日期时间字符串
|
||||||
|
* @param pattern 格式模式
|
||||||
|
* @return 是否有效
|
||||||
|
*/
|
||||||
|
public static boolean isValidDateTime(String dateTimeStr, String pattern) {
|
||||||
|
try {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
LocalDateTime.parse(dateTimeStr, formatter);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字符串是否为有效的日期格式
|
||||||
|
*
|
||||||
|
* @param dateStr 日期字符串
|
||||||
|
* @param pattern 格式模式
|
||||||
|
* @return 是否有效
|
||||||
|
*/
|
||||||
|
public static boolean isValidDate(String dateStr, String pattern) {
|
||||||
|
try {
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
LocalDate.parse(dateStr, formatter);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user