feat(biji): 优化笔记展示功能并调整端口

-将服务器端口从 8083 改为 8084
- 在数据库中添加 grouping_id 字段
- 实现笔记分组展示功能
-优化笔记编辑页面布局
-重构后端接口返回类型
- 移除 MarkdownFile 实体中的 userId 字段
This commit is contained in:
ikmkj
2025-06-17 21:54:53 +08:00
parent 4557bd49f9
commit b1b74f5efd
7 changed files with 90 additions and 31 deletions

View File

@@ -8,7 +8,6 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@@ -33,12 +32,12 @@ public class MarkdownController {
@Parameter(name = "id", description = "文件ID", required = true) @Parameter(name = "id", description = "文件ID", required = true)
}) })
@GetMapping("/{id}") @GetMapping("/{id}")
public ResponseEntity<String> getMarkdownContent(@PathVariable Long id) { public R<String> getMarkdownContent(@PathVariable Long id) {
MarkdownFile file = markdownFileService.getMarkdownById(id); MarkdownFile file = markdownFileService.getMarkdownById(id);
if (file != null) { if (file != null) {
return ResponseEntity.ok(file.getContent()); return R.success(file.getContent());
} }
return ResponseEntity.notFound().build(); return R.fail();
} }
@Operation(summary = "创建markdown文件") @Operation(summary = "创建markdown文件")
@@ -49,7 +48,7 @@ public class MarkdownController {
@Parameter(name = "content", description = "内容",required = true) @Parameter(name = "content", description = "内容",required = true)
}) })
@PostMapping @PostMapping
public ResponseEntity<MarkdownFile> createMarkdown( public R<MarkdownFile> createMarkdown(
@RequestParam Long groupingId, @RequestParam Long groupingId,
@RequestParam String title, @RequestParam String title,
@RequestParam String fileName, @RequestParam String fileName,
@@ -58,7 +57,7 @@ public class MarkdownController {
MarkdownFile file = markdownFileService.createMarkdownFile( MarkdownFile file = markdownFileService.createMarkdownFile(
groupingId, title, fileName, content); groupingId, title, fileName, content);
return ResponseEntity.ok(file); return R.success(file);
} }
@Operation(summary = "更新Markdown文件") @Operation(summary = "更新Markdown文件")
@@ -67,39 +66,38 @@ public class MarkdownController {
@Parameter(name = "content", description = "Markdown文件内容", required = true) @Parameter(name = "content", description = "Markdown文件内容", required = true)
}) })
@PostMapping("/{id}") @PostMapping("/{id}")
public ResponseEntity<MarkdownFile> updateMarkdown( public R<MarkdownFile> updateMarkdown(
@PathVariable Long id, @PathVariable Long id,
@RequestBody String content) { @RequestBody String content) {
MarkdownFile file = markdownFileService.updateMarkdownContent(id, content); MarkdownFile file = markdownFileService.updateMarkdownContent(id, content);
if (file != null) { if (file != null) {
return ResponseEntity.ok(file); return R.success(file);
} }
return ResponseEntity.notFound().build(); return R.fail();
} }
@Operation(summary = "获取所有Markdown文件") @Operation(summary = "获取所有Markdown文件")
@GetMapping @GetMapping
public ResponseEntity<List<MarkdownFile>> getAllMarkdownFiles() { public R<List<MarkdownFile>> getAllMarkdownFiles() {
// 固定用户ID=1因为是个人笔记
List<MarkdownFile> files = markdownFileService.getAllMarkdownFiles(); List<MarkdownFile> files = markdownFileService.getAllMarkdownFiles();
return ResponseEntity.ok(files); return R.success(files);
} }
@Operation(summary = "删除Markdown文件") @Operation(summary = "删除Markdown文件")
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public ResponseEntity<Void> deleteMarkdown(@PathVariable Long id) { public R<Void> deleteMarkdown(@PathVariable Long id) {
if (markdownFileService.deleteMarkdownFile(id)) { if (markdownFileService.deleteMarkdownFile(id)) {
return ResponseEntity.noContent().build(); return R.success();
} }
return ResponseEntity.notFound().build(); return R.fail();
} }
@Operation(summary = "根据分组ID获取Markdown文件") @Operation(summary = "根据分组ID获取Markdown文件")
@GetMapping("/grouping/{groupingId}") @GetMapping("/grouping/{groupingId}")
public ResponseEntity<List<MarkdownFile>> getFilesByGroupingId(@PathVariable String groupingId) { public R<List<MarkdownFile>> getFilesByGroupingId(@PathVariable String groupingId) {
List<MarkdownFile> files = markdownFileService.getFilesByGroupingId(groupingId); List<MarkdownFile> files = markdownFileService.getFilesByGroupingId(groupingId);
return ResponseEntity.ok(files); return R.success(files);
} }
} }

View File

@@ -18,8 +18,6 @@ public class MarkdownFile {
private Long id; private Long id;
@Schema(description = "分组表id",implementation = Long.class) @Schema(description = "分组表id",implementation = Long.class)
private Long groupingId; private Long groupingId;
@Schema(description = "用户ID",implementation = Long.class)
private Long userId;
@Schema(description = "文本标题",implementation = String.class) @Schema(description = "文本标题",implementation = String.class)
private String title; private String title;

View File

@@ -11,7 +11,6 @@ import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;

View File

@@ -13,7 +13,7 @@ file:
#?? #??
server: server:
port: 8083 port: 8084
## Snowflake ID????? ## Snowflake ID?????

View File

@@ -2,22 +2,25 @@
<div class="home-page"> <div class="home-page">
<el-container style="height: 100vh;"> <el-container style="height: 100vh;">
<!-- 左侧菜单栏 --> <!-- 左侧菜单栏 -->
<el-aside width="300px" style="background-color: #f5f7fa; border-right: 1px solid #ebeef5;"> <el-aside :width="isCollapsed ? '64px' : '300px'" style="background-color: #f5f7fa; border-right: 1px solid #ebeef5; transition: width 0.3s;">
<div class="sidebar-header"> <div class="sidebar-header" :style="{ justifyContent: isCollapsed ? 'center' : 'space-between' }">
<h3>笔记分类</h3> <h3 v-if="!isCollapsed">笔记分类</h3>
<el-button @click="isCollapsed = !isCollapsed" size="small" type="text"> <el-button @click="isCollapsed = !isCollapsed" size="small" type="text">
{{ isCollapsed ? '展开' : '收起' }} <el-icon v-if="isCollapsed">
<Expand />
</el-icon>
<span v-else>收起</span>
</el-button> </el-button>
</div> </div>
<el-menu <el-menu
v-if="!isCollapsed" v-show="!isCollapsed"
default-active="all" default-active="all"
class="el-menu-vertical-demo" class="el-menu-vertical-demo"
@select="handleMenuSelect" @select="handleMenuSelect"
> >
<el-menu-item index="all"> <el-menu-item index="all">
<span>全部笔记</span> <span>全部文档</span>
</el-menu-item> </el-menu-item>
<el-submenu v-for="group in groupings" :key="group.id" :index="'group-'+group.id"> <el-submenu v-for="group in groupings" :key="group.id" :index="'group-'+group.id">
@@ -53,6 +56,18 @@
</div> </div>
</div> </div>
<!-- 文件列表 -->
<div v-if="!selectedFile" class="file-list">
<div v-for="group in groupings" :key="group.id" class="group-section">
<h3>{{ group.grouping }}</h3>
<ul>
<li v-for="file in groupFiles[group.id]" :key="file.id" @click="selectFile(file)">
{{ file.title }}
</li>
</ul>
</div>
</div>
<div v-if="selectedFile" class="file-preview"> <div v-if="selectedFile" class="file-preview">
<div class="preview-header"> <div class="preview-header">
<h2>{{ selectedFile.title }}</h2> <h2>{{ selectedFile.title }}</h2>
@@ -79,6 +94,7 @@
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import axios from 'axios'; import axios from 'axios';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { Expand } from '@element-plus/icons-vue';
import MarkdownEditor from './MarkdownEditor.vue'; import MarkdownEditor from './MarkdownEditor.vue';
import VMdPreview from '@kangc/v-md-editor/lib/preview'; import VMdPreview from '@kangc/v-md-editor/lib/preview';
import '@kangc/v-md-editor/lib/style/preview.css'; import '@kangc/v-md-editor/lib/style/preview.css';
@@ -90,10 +106,11 @@ VMdPreview.use(githubTheme);
export default { export default {
components: { components: {
MarkdownEditor, MarkdownEditor,
[VMdPreview.name]: VMdPreview [VMdPreview.name]: VMdPreview,
Expand
}, },
setup() { setup() {
const API_BASE_URL = 'http://localhost:8083'; const API_BASE_URL = 'http://localhost:8084';
const markdownFiles = ref([]); const markdownFiles = ref([]);
const groupings = ref([]); const groupings = ref([]);
const groupFiles = ref({}); const groupFiles = ref({});
@@ -128,6 +145,11 @@ export default {
} }
}; };
// 选择文件预览
const selectFile = (file) => {
selectedFile.value = file;
};
// 编辑笔记 // 编辑笔记
const editNote = (file) => { const editNote = (file) => {
currentFileId.value = file.id; currentFileId.value = file.id;
@@ -154,7 +176,7 @@ export default {
const fileId = index.split('-')[1]; const fileId = index.split('-')[1];
const file = markdownFiles.value.find(f => f.id == fileId); const file = markdownFiles.value.find(f => f.id == fileId);
if (file) { if (file) {
selectedFile.value = file; selectFile(file);
} }
} }
}; };
@@ -203,6 +225,7 @@ export default {
currentFileId, currentFileId,
selectedFile, selectedFile,
isCollapsed, isCollapsed,
selectFile,
editNote, editNote,
deleteNote, deleteNote,
handleMarkdownUpload, handleMarkdownUpload,
@@ -242,6 +265,35 @@ export default {
margin-left: 10px; margin-left: 10px;
} }
.file-list {
margin-top: 20px;
}
.group-section {
margin-bottom: 20px;
}
.group-section h3 {
margin-bottom: 10px;
font-size: 18px;
color: #333;
}
.group-section ul {
list-style: none;
padding: 0;
}
.group-section li {
padding: 8px 0;
border-bottom: 1px solid #eee;
cursor: pointer;
}
.group-section li:hover {
background-color: #f5f7fa;
}
.file-preview { .file-preview {
padding: 20px; padding: 20px;
border: 1px solid #ebeef5; border: 1px solid #ebeef5;
@@ -263,4 +315,15 @@ export default {
border-radius: 4px; border-radius: 4px;
background: #fff; background: #fff;
} }
/* 修复菜单折叠样式 */
.el-menu-vertical-demo {
height: calc(100vh - 60px);
overflow-y: auto;
}
.sidebar-header {
height: 60px;
display: flex;
align-items: center;
}
</style> </style>

Binary file not shown.

View File

@@ -16,6 +16,7 @@ CREATE TABLE "user" (
CREATE TABLE IF NOT EXISTS markdown_file ( CREATE TABLE IF NOT EXISTS markdown_file (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
grouping_id TEXT,
title TEXT NOT NULL, title TEXT NOT NULL,
file_name TEXT NOT NULL, file_name TEXT NOT NULL,
content TEXT NOT NULL, content TEXT NOT NULL,