feat(biji): 优化笔记展示功能并调整端口
-将服务器端口从 8083 改为 8084 - 在数据库中添加 grouping_id 字段 - 实现笔记分组展示功能 -优化笔记编辑页面布局 -重构后端接口返回类型 - 移除 MarkdownFile 实体中的 userId 字段
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ file:
|
|||||||
|
|
||||||
#??
|
#??
|
||||||
server:
|
server:
|
||||||
port: 8083
|
port: 8084
|
||||||
|
|
||||||
|
|
||||||
## Snowflake ID?????
|
## Snowflake ID?????
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
BIN
mydatabase.db
BIN
mydatabase.db
Binary file not shown.
@@ -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,
|
||||||
@@ -34,4 +35,4 @@ CREATE TABLE IF NOT EXISTS image (
|
|||||||
size INTEGER NOT NULL,
|
size INTEGER NOT NULL,
|
||||||
content_type TEXT NOT NULL,
|
content_type TEXT NOT NULL,
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user