Merge remote-tracking branch 'origin/master'

This commit is contained in:
ikmkj
2025-08-04 19:45:59 +08:00
6 changed files with 372 additions and 22 deletions

View File

@@ -1,6 +0,0 @@
1、执行任务的时候首先分析任务然后将该任务分成多个可执行的小任务一步一步执行。
2、不要启动我项目的服务
3、若是新建项目或者开发新的功能首先使用context7 MCP服务来寻找对应的文档
4、若是修改业务逻辑等就不要使用context7 MCP服务来寻找对应的文档先查看查看前端该功能对应的后端接口查看后端接口的逻辑若是已经实现就返回前端处理逻辑若是后端还们没有实现则先处理后端在处理前端。
5、若是apply_diff失败或者文件修改编辑失败就要先保存该文件然后重新读取在做修改再来apply_diff
6、使用filesystem MCP服务

View File

@@ -1,14 +0,0 @@
{
"mcpServers": {
"sequentialthinking": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sequential-thinking"
],
"alwaysAllow": [
"sequentialthinking"
]
}
}
}

100
README.md Normal file
View 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 指定的端口)。

View File

@@ -45,11 +45,14 @@ public class SecurityConfig {
@Value("${jwt.tokenHead}")
private String tokenHead;
// 配置了密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 配置了安全过滤器链
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter = new JwtAuthenticationTokenFilter(userDetailsService, jwtTokenUtil, tokenHeader, tokenHead);
@@ -69,7 +72,7 @@ public class SecurityConfig {
};
http
.csrf(csrf -> csrf.disable())
.csrf(csrf -> csrf.disable()) // 配置了 CSRF 禁用、无状态会话管理
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authz -> authz
// 1. 动态允许公共端点

View File

@@ -37,7 +37,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
if (ObjectUtil.isNull(user)) {
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

View File

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