diff --git a/biji-qianduan/src/App.vue b/biji-qianduan/src/App.vue
index dcb4a14..89b963b 100644
--- a/biji-qianduan/src/App.vue
+++ b/biji-qianduan/src/App.vue
@@ -3,21 +3,65 @@
diff --git a/biji-qianduan/src/assets/styles/global.css b/biji-qianduan/src/assets/styles/global.css
new file mode 100644
index 0000000..5277f59
--- /dev/null
+++ b/biji-qianduan/src/assets/styles/global.css
@@ -0,0 +1,85 @@
+/* assets/styles/global.css */
+@import './theme.css';
+
+/* 全局基础样式 */
+body {
+ margin: 0;
+ font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ transition: background-color var(--transition-duration), color var(--transition-duration);
+}
+
+/* 滚动条美化 */
+::-webkit-scrollbar {
+ width: 6px;
+ height: 6px;
+}
+
+::-webkit-scrollbar-track {
+ background-color: transparent;
+}
+
+::-webkit-scrollbar-thumb {
+ background-color: var(--border-color);
+ border-radius: 3px;
+ transition: background-color var(--transition-duration);
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background-color: var(--text-color-secondary);
+}
+
+/* 基础动画 Keyframes */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes slideInUp {
+ from {
+ transform: translateY(20px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes slideInDown {
+ from {
+ transform: translateY(-20px);
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
+
+@keyframes slideInLeft {
+ from {
+ transform: translateX(-20px);
+ opacity: 0;
+ }
+ to {
+ transform: translateX(0);
+ opacity: 1;
+ }
+}
+
+/* 可复用的动画类 */
+.fade-in {
+ animation: fadeIn var(--transition-duration) ease-in-out;
+}
+
+.slide-in-up {
+ animation: slideInUp var(--transition-duration) ease-in-out;
+}
\ No newline at end of file
diff --git a/biji-qianduan/src/assets/styles/theme.css b/biji-qianduan/src/assets/styles/theme.css
new file mode 100644
index 0000000..df4b1ed
--- /dev/null
+++ b/biji-qianduan/src/assets/styles/theme.css
@@ -0,0 +1,47 @@
+/* assets/styles/theme.css */
+
+/* 默认浅色主题 */
+:root {
+ --bg-color: #ffffff;
+ --bg-color-secondary: #f7f8fa;
+ --bg-color-tertiary: #eff2f5;
+ --text-color: #303133;
+ --text-color-secondary: #606266;
+ --text-color-placeholder: #a8abb2;
+ --border-color: #dcdfe6;
+ --border-color-light: #e4e7ed;
+ --primary-color: #409eff;
+ --primary-color-light: #ecf5ff;
+ --danger-color: #f56c6c;
+ --success-color: #67c23a;
+ --warning-color: #e6a23c;
+ --info-color: #909399;
+
+ --box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ --box-shadow-light: 0 2px 4px rgba(0, 0, 0, 0.08);
+ --box-shadow-dark: 0 4px 16px rgba(0, 0, 0, 0.15);
+
+ --transition-duration: 0.3s;
+}
+
+/* 深色主题 */
+.dark-theme {
+ --bg-color: #141414;
+ --bg-color-secondary: #1a1a1a;
+ --bg-color-tertiary: #222222;
+ --text-color: #e5e5e5;
+ --text-color-secondary: #a3a3a3;
+ --text-color-placeholder: #5c5c5c;
+ --border-color: #3a3a3a;
+ --border-color-light: #2a2a2a;
+ --primary-color: #409eff;
+ --primary-color-light: #26334f;
+ --danger-color: #f56c6c;
+ --success-color: #67c23a;
+ --warning-color: #e6a23c;
+ --info-color: #909399;
+
+ --box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
+ --box-shadow-light: 0 2px 4px rgba(0, 0, 0, 0.25);
+ --box-shadow-dark: 0 4px 16px rgba(0, 0, 0, 0.4);
+}
\ No newline at end of file
diff --git a/biji-qianduan/src/components/HomePage.vue b/biji-qianduan/src/components/HomePage.vue
index f32ff00..e58ce94 100644
--- a/biji-qianduan/src/components/HomePage.vue
+++ b/biji-qianduan/src/components/HomePage.vue
@@ -707,30 +707,153 @@ const handleExportMd = () => {
};
+
+
diff --git a/biji-qianduan/src/components/LoginPage.vue b/biji-qianduan/src/components/LoginPage.vue
index 2bde4e9..8d7b202 100644
--- a/biji-qianduan/src/components/LoginPage.vue
+++ b/biji-qianduan/src/components/LoginPage.vue
@@ -66,15 +66,59 @@ const goToRegister = () => {
justify-content: center;
align-items: center;
height: 100vh;
- background-color: #f5f7fa;
+ background-color: var(--bg-color-secondary);
+ background-image: linear-gradient(135deg, var(--bg-color) 0%, var(--bg-color-secondary) 100%);
}
.login-card {
- width: 400px;
+ width: 420px;
+ padding: 20px 30px;
+ border-radius: 12px;
+ background-color: var(--bg-color);
+ box-shadow: var(--box-shadow-dark);
+ border: 1px solid var(--border-color);
+ animation: slideInDown 0.5s ease-out;
+ overflow: hidden;
}
.card-header {
text-align: center;
- font-size: 20px;
+ font-size: 24px;
+ font-weight: 600;
+ color: var(--text-color);
+ padding-bottom: 20px;
+ margin-bottom: 20px;
+ border-bottom: 1px solid var(--border-color-light);
+}
+
+.el-form-item {
+ margin-bottom: 25px;
+}
+
+.el-button {
+ width: 100%;
+ transition: all var(--transition-duration) ease;
+}
+
+.el-button--primary {
+ height: 40px;
+}
+
+.el-button--primary:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 10px rgba(64, 158, 255, 0.4);
+}
+
+.el-button:last-child {
+ margin-left: 0;
+ margin-top: 10px;
+ color: var(--text-color-secondary);
+ border: none;
+ background: none;
+}
+
+.el-button:last-child:hover {
+ color: var(--primary-color);
+ background-color: var(--primary-color-light);
}
\ No newline at end of file
diff --git a/biji-qianduan/src/components/RegisterPage.vue b/biji-qianduan/src/components/RegisterPage.vue
index 2e10b74..ca5f0fe 100644
--- a/biji-qianduan/src/components/RegisterPage.vue
+++ b/biji-qianduan/src/components/RegisterPage.vue
@@ -80,15 +80,59 @@ const goToLogin = () => {
justify-content: center;
align-items: center;
height: 100vh;
- background-color: #f5f7fa;
+ background-color: var(--bg-color-secondary);
+ background-image: linear-gradient(135deg, var(--bg-color) 0%, var(--bg-color-secondary) 100%);
}
.register-card {
- width: 400px;
+ width: 420px;
+ padding: 20px 30px;
+ border-radius: 12px;
+ background-color: var(--bg-color);
+ box-shadow: var(--box-shadow-dark);
+ border: 1px solid var(--border-color);
+ animation: slideInDown 0.5s ease-out;
+ overflow: hidden;
}
.card-header {
text-align: center;
- font-size: 20px;
+ font-size: 24px;
+ font-weight: 600;
+ color: var(--text-color);
+ padding-bottom: 20px;
+ margin-bottom: 20px;
+ border-bottom: 1px solid var(--border-color-light);
+}
+
+.el-form-item {
+ margin-bottom: 25px;
+}
+
+.el-button {
+ width: 100%;
+ transition: all var(--transition-duration) ease;
+}
+
+.el-button--primary {
+ height: 40px;
+}
+
+.el-button--primary:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 10px rgba(64, 158, 255, 0.4);
+}
+
+.el-button:last-child {
+ margin-left: 0;
+ margin-top: 10px;
+ color: var(--text-color-secondary);
+ border: none;
+ background: none;
+}
+
+.el-button:last-child:hover {
+ color: var(--primary-color);
+ background-color: var(--primary-color-light);
}
\ No newline at end of file
diff --git a/biji-qianduan/src/main.js b/biji-qianduan/src/main.js
index 959fed8..09c59d4 100644
--- a/biji-qianduan/src/main.js
+++ b/biji-qianduan/src/main.js
@@ -1,4 +1,5 @@
import { createApp } from 'vue'
+import './assets/styles/global.css'
import App from './App.vue'
import router from './router/'
import ElementPlus from 'element-plus'
diff --git a/doc/development_plan.md b/doc/development_plan.md
index f3e473f..eea6567 100644
--- a/doc/development_plan.md
+++ b/doc/development_plan.md
@@ -2,55 +2,61 @@
本计划旨在为您的笔记项目提供一个清晰、分步走的开发与美化路线图。
-## 第一阶段:核心体验提升 - UI美化与交互优化
+## 第一阶段:核心体验提升 - UI美化与交互优化 (已完成)
这个阶段的目标是全面提升应用的颜值和易用性。
-- **任务1.1:引入Element Plus UI库**
- - [ ] **前端**: 安装并配置 Element Plus。
- - [ ] 运行 `npm install element-plus --save`。
- - [ ] 在 `main.js` 中全局引入 Element Plus。
- - [ ] 使用 Element Plus 的组件重构现有页面,如按钮、表单、布局等。
-- **任务1.2:响应式布局**
- - [ ] **前端**: 使用 Element Plus 的栅格系统或 CSS Flexbox/Grid 来实现响应式布局,确保在不同设备上都能良好显示。
-- **任务1.3:升级Markdown编辑器**
- - [ ] **前端**: 调研并集成一个功能更强大的Markdown编辑器,例如 `vditor` 或 `cherry-markdown`。
- - [ ] 替换现有的 `MarkdownEditor.vue` 组件。
- - [ ] 确保新编辑器与应用的集成,包括内容的双向绑定和图片的上传。
+- **任务1.1:引入Element Plus UI库 (已完成)**
+ - **前端**: 安装并配置 Element Plus,并使用其组件重构了页面。
+- **任务1.2:响应式布局 (已完成)**
+ - **前端**: 使用 Element Plus 的栅格系统和CSS媒体查询实现了响应式布局,确保应用在不同尺寸的设备上都能良好显示。
+- **任务1.3:升级Markdown编辑器 (已完成)**
+ - **前端**: 集成了功能更强大的 `vditor` 编辑器,替换了原有的组件,并确保了内容的双向绑定和图片的上传功能。
- **(可选任务)任务:重构前端页面**
- - [ ] **前端**: 重新对整个页面进行重构,使其更简洁、易用。
+ - **前端**: 重新对整个页面进行重构,使其更简洁、易用。
-## 第二阶段:基础功能完善与安全加固
+## 第二阶段:基础功能完善与安全加固 (已完成)
这个阶段的目标是补齐核心功能,并确保应用的安全性。
-- **任务2.1:实现用户认证与授权**
- - [ ] **后端**: JWT。
- - [ ] 实现 UserDetailsService 来加载用户信息。
- - [ ] 创建 JWT 工具类,用于生成和验证 Token。
- - [ ] 创建登录接口,成功后返回 JWT。
- - [ ] 创建一个 JWT 过滤器,用于保护需要授权的接口。
- - [ ] **前端**: 实现登录页面和 Token 管理。
- - [ ] 创建登录页面组件。
- - [ ] 调用登录接口,并将获取到的 JWT 存储在 `localStorage` 或 `sessionStorage` 中。
- - [ ] 封装 `axios`,在请求头中自动添加 `Authorization` 字段。
- - [ ] 实现路由守卫,未登录用户访问受保护页面时跳转到登录页。
- - [ ] 实现登出功能。
-## 第三阶段:高级功能拓展
+- **任务2.1:实现用户认证与授权 (已完成)**
+ - **后端**: 使用 Spring Security 和 JWT 实现了一套完整的认证授权系统。
+ - 实现了 `UserDetailsService` 来加载用户信息。
+ - 创建了 JWT 工具类,用于生成和验证 Token。
+ - 创建了登录接口,成功后返回 JWT。
+ - 创建了一个 JWT 过滤器,用于保护需要授权的接口。
+ - **前端**: 实现了登录、注册页面和 Token 管理。
+ - 创建了登录和注册页面组件。
+ - 使用 Pinia 进行状态管理,并将获取到的 JWT 存储在 `localStorage` 中。
+ - 封装了 `axios`,在请求头中自动添加 `Authorization` 字段。
+ - 实现了登出功能。
-这个阶段我们将为应用增加更多有价值的功能。
+## 第三阶段:高级功能拓展 (已完成)
-- **任务3.1:实现笔记名模糊搜索**
- - [ ] **后端**: 。
- - [ ] 可以通过搜索的笔记的名称来模糊搜索笔记。
- - [ ] 在 Spring Boot 中添加相应的客户端依赖。
- - [ ] 创建搜索接口。
- - [ ] **前端**: 添加搜索框和搜索结果展示页面。
-- **任务3.2:实现笔记分享**
- - [ ] **后端**:
- - [ ] 为笔记表增加一个 `share_token` 字段。
- - [ ] 创建生成分享链接的接口。
- - [ ] 创建通过分享链接访问笔记的公开接口。
- - [ ] **前端**:
- - [ ] 在笔记操作中增加“分享”按钮。
- - [ ] 创建一个公开的笔记展示页面,用于显示分享的笔记。
+这个阶段我们为应用增加了更多有价值的功能。
+
+- **任务3.1:实现笔记名模糊搜索 (已完成)**
+ - **后端**: 在 `MarkdownController` 中添加了 `/search` 接口,使用 Mybatis-Plus 的 `like` 查询实现标题的模糊搜索。
+ - **前端**: 在主页添加了搜索框,并实现了调用后端接口进行搜索和展示结果的逻辑。
+- **~~任务3.2:实现笔记分享~~ (已取消)**
+ - 根据您的要求,此任务已取消。
+
+## 第四阶段:核心功能增强 (已完成)
+
+这个阶段我们进一步强化了应用的核心功能,提升了用户体验。
+
+- **任务4.1:实现编辑/新增时自动保存 (已完成)**
+ - **前端**: 在 `HomePage.vue` 中,通过监听编辑器内容变化并结合防抖(debounce)技术,实现了在用户停止输入2秒后自动保存笔记的功能,并提供了实时的保存状态提示。
+- **任务4.2:实现修改文件名和分类名 (已完成)**
+ - **后端**:
+ - 在 `GroupingController` 中利用现有接口实现了修改分类名称的功能。
+ - 在 `MarkdownController` 中添加了新的 `PUT` 接口,用于修改笔记标题。
+ - **前端**:
+ - 在分类和笔记标题旁添加了编辑图标。
+ - 实现了点击编辑图标后弹出对话框,让用户可以输入新名称并保存的功能。
+- **任务4.3:实现单文件导入/导出 (已完成)**
+ - **后端**: 删除了原有的批量导入/导出接口。
+ - **前端**:
+ - 移除了批量导入/导出的UI。
+ - 在笔记预览页面添加了“导出为.md”按钮,可将当前笔记内容直接下载为 Markdown 文件。
+ - 优化了“上传Markdown”功能,用户上传文件后会弹出对话框,让用户选择要导入的分类。