From b4f431aa03989c3fa24cced6bad1fc111b8fcff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=9F?= <3111696955@qq.com> Date: Mon, 4 Aug 2025 11:55:16 +0800 Subject: [PATCH 1/3] =?UTF-8?q?build:=20=E7=A7=BB=E9=99=A4=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=E5=B9=B6=E6=B8=85=E7=90=86MCP?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clinerules | 6 - .roo/mcp.json | 14 - .../test/bijihoudaun/util/DateTimeUtil.java | 267 ++++++++++++++++++ 3 files changed, 267 insertions(+), 20 deletions(-) delete mode 100644 .clinerules delete mode 100644 .roo/mcp.json create mode 100644 biji-houdaun/src/main/java/com/test/bijihoudaun/util/DateTimeUtil.java diff --git a/.clinerules b/.clinerules deleted file mode 100644 index d1b5641..0000000 --- a/.clinerules +++ /dev/null @@ -1,6 +0,0 @@ -1、执行任务的时候,首先分析任务,然后将该任务分成多个可执行的小任务,一步一步执行。 -2、不要启动我项目的服务 -3、若是新建项目或者开发新的功能,首先使用context7 MCP服务来寻找对应的文档 -4、若是修改业务逻辑等,就不要使用context7 MCP服务来寻找对应的文档,先查看查看前端该功能对应的后端接口,查看后端接口的逻辑,若是已经实现就返回前端处理逻辑,若是后端还们没有实现,则先处理后端在处理前端。 -5、若是apply_diff失败或者文件修改编辑失败,就要先保存该文件然后重新读取在做修改再来apply_diff -6、使用filesystem MCP服务 \ No newline at end of file diff --git a/.roo/mcp.json b/.roo/mcp.json deleted file mode 100644 index c5282a5..0000000 --- a/.roo/mcp.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "mcpServers": { - "sequentialthinking": { - "command": "npx", - "args": [ - "-y", - "@modelcontextprotocol/server-sequential-thinking" - ], - "alwaysAllow": [ - "sequentialthinking" - ] - } - } -} \ No newline at end of file diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/util/DateTimeUtil.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/util/DateTimeUtil.java new file mode 100644 index 0000000..0d2744c --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/util/DateTimeUtil.java @@ -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; + } + } +} \ No newline at end of file From cb374bbc91827762facb162a85bc0d7da5b52c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=9F?= <3111696955@qq.com> Date: Mon, 4 Aug 2025 15:49:25 +0800 Subject: [PATCH 2/3] =?UTF-8?q?docs(README):=20=E6=B7=BB=E5=8A=A0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=BB=8B=E7=BB=8D=E5=92=8C=E4=BD=BF=E7=94=A8=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 README.md 文件,详细介绍项目功能、技术栈、目录结构和启动步骤- 包含前后端技术选型、环境要求、数据库初始化、配置说明等信息 - 提供快速开始指南,帮助开发者快速上手项目 --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..af094a2 --- /dev/null +++ b/README.md @@ -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 ` +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 指定的端口)。 From 8a52ad708fdc808a474880ff8d1d292990b91ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=9F?= <3111696955@qq.com> Date: Mon, 4 Aug 2025 16:23:02 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat(security):=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=AE=A4=E8=AF=81=E5=92=8C=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加密码编码器,增强密码安全性 - 配置安全过滤链,实现无状态会话管理 - 更新用户详细信息获取逻辑,保留现有行为 --- .../java/com/test/bijihoudaun/config/SecurityConfig.java | 5 ++++- .../com/test/bijihoudaun/service/impl/UserServiceImpl.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/config/SecurityConfig.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/config/SecurityConfig.java index 4291759..6493f76 100644 --- a/biji-houdaun/src/main/java/com/test/bijihoudaun/config/SecurityConfig.java +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/config/SecurityConfig.java @@ -39,17 +39,20 @@ 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); http - .csrf(csrf -> csrf.disable()) + .csrf(csrf -> csrf.disable()) // 配置了 CSRF 禁用、无状态会话管理 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(authz -> authz // 1. 始终允许的核心公共端点 (登录、注册、API文档) diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/UserServiceImpl.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/UserServiceImpl.java index 5e658be..0ff53b3 100644 --- a/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/UserServiceImpl.java +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/UserServiceImpl.java @@ -36,7 +36,7 @@ public class UserServiceImpl extends ServiceImpl implements Us if (user == null) { 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