From 7008b3c02d9ad4694659d86f14a6f05f385970b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E5=AD=9F?= <3111696955@qq.com> Date: Fri, 1 Aug 2025 08:36:05 +0800 Subject: [PATCH] =?UTF-8?q?feat(recycle-bin):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=9B=9E=E6=94=B6=E7=AB=99=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增回收站管理相关接口和页面 - 实现笔记和分组的软删除、恢复和永久删除功能 - 添加回收站数据展示和操作界面 - 设计回收站功能的数据库表结构和API接口 --- .../controller/TrashController.java | 47 ++++++++ .../test/bijihoudaun/entity/TrashItemVo.java | 28 +++++ .../bijihoudaun/service/TrashService.java | 33 ++++++ .../service/impl/TrashServiceImpl.java | 90 +++++++++++++++ biji-qianduan/src/components/TrashPage.vue | 104 ++++++++++++++++++ 回收站功能设计.md | 22 ++++ 6 files changed, 324 insertions(+) create mode 100644 biji-houdaun/src/main/java/com/test/bijihoudaun/controller/TrashController.java create mode 100644 biji-houdaun/src/main/java/com/test/bijihoudaun/entity/TrashItemVo.java create mode 100644 biji-houdaun/src/main/java/com/test/bijihoudaun/service/TrashService.java create mode 100644 biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/TrashServiceImpl.java create mode 100644 biji-qianduan/src/components/TrashPage.vue create mode 100644 回收站功能设计.md diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/controller/TrashController.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/controller/TrashController.java new file mode 100644 index 0000000..5e53222 --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/controller/TrashController.java @@ -0,0 +1,47 @@ +package com.test.bijihoudaun.controller; + +import com.test.bijihoudaun.common.response.R; +import com.test.bijihoudaun.entity.TrashItemVo; +import com.test.bijihoudaun.service.TrashService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/trash") +@Tag(name = "回收站管理") +public class TrashController { + + @Autowired + private TrashService trashService; + + @GetMapping + @Operation(summary = "获取回收站列表") + public R> getTrashItems() { + return R.success(trashService.getTrashItems()); + } + + @PostMapping("/restore/{type}/{id}") + @Operation(summary = "恢复项目") + public R restoreItem(@PathVariable String type, @PathVariable String id) { + trashService.restoreItem(id, type); + return R.success(); + } + + @DeleteMapping("/permanently/{type}/{id}") + @Operation(summary = "永久删除项目") + public R permanentlyDeleteItem(@PathVariable String type, @PathVariable String id) { + trashService.permanentlyDeleteItem(id, type); + return R.success(); + } + + @DeleteMapping("/clean") + @Operation(summary = "清空回收站") + public R cleanTrash() { + trashService.cleanTrash(); + return R.success(); + } +} \ No newline at end of file diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/TrashItemVo.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/TrashItemVo.java new file mode 100644 index 0000000..425f408 --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/TrashItemVo.java @@ -0,0 +1,28 @@ +package com.test.bijihoudaun.entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(name = "回收站项目视图对象") +public class TrashItemVo { + + @Schema(description = "项目ID") + private String id; + + @Schema(description = "项目名称(笔记标题或分组名称)") + private String title; + + @Schema(description = "项目类型(note 或 group)") + private String type; + + @Schema(description = "删除时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date deletedAt; + + @Schema(description = "删除者ID") + private String deletedBy; +} \ No newline at end of file diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/service/TrashService.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/TrashService.java new file mode 100644 index 0000000..8fc004c --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/TrashService.java @@ -0,0 +1,33 @@ +package com.test.bijihoudaun.service; + +import com.test.bijihoudaun.entity.TrashItemVo; + +import java.util.List; + +public interface TrashService { + + /** + * 获取回收站中的所有项目 + * @return 回收站项目列表 + */ + List getTrashItems(); + + /** + * 恢复指定的回收站项目 + * @param id 项目ID + * @param type 项目类型 ("note" 或 "group") + */ + void restoreItem(String id, String type); + + /** + * 永久删除指定的回收站项目 + * @param id 项目ID + * @param type 项目类型 ("note" 或 "group") + */ + void permanentlyDeleteItem(String id, String type); + + /** + * 清空回收站 + */ + void cleanTrash(); +} \ No newline at end of file diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/TrashServiceImpl.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/TrashServiceImpl.java new file mode 100644 index 0000000..2abb930 --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/TrashServiceImpl.java @@ -0,0 +1,90 @@ +package com.test.bijihoudaun.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.test.bijihoudaun.entity.Grouping; +import com.test.bijihoudaun.entity.MarkdownFile; +import com.test.bijihoudaun.entity.TrashItemVo; +import com.test.bijihoudaun.mapper.GroupingMapper; +import com.test.bijihoudaun.mapper.MarkdownFileMapper; +import com.test.bijihoudaun.service.TrashService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Service +public class TrashServiceImpl implements TrashService { + + @Autowired + private MarkdownFileMapper markdownFileMapper; + + @Autowired + private GroupingMapper groupingMapper; + + @Override + public List getTrashItems() { + // 调用自定义的Mapper方法查询已删除的笔记,绕过全局逻辑删除过滤器 + List deletedNotes = markdownFileMapper.selectDeleted() + .stream() + .map(file -> { + TrashItemVo vo = new TrashItemVo(); + vo.setId(String.valueOf(file.getId())); + vo.setTitle(file.getTitle()); + vo.setType("note"); + vo.setDeletedAt(file.getDeletedAt()); + vo.setDeletedBy(String.valueOf(file.getDeletedBy())); + return vo; + }) + .collect(Collectors.toList()); + + // 调用自定义的Mapper方法查询已删除的分组 + List deletedGroups = groupingMapper.selectDeleted() + .stream() + .map(group -> { + TrashItemVo vo = new TrashItemVo(); + vo.setId(String.valueOf(group.getId())); + vo.setTitle(group.getGrouping()); + vo.setType("group"); + vo.setDeletedAt(group.getDeletedAt()); + vo.setDeletedBy(String.valueOf(group.getDeletedBy())); + return vo; + }) + .collect(Collectors.toList()); + + // 合并并返回 + return Stream.concat(deletedNotes.stream(), deletedGroups.stream()).collect(Collectors.toList()); + } + + @Override + @Transactional + public void restoreItem(String id, String type) { + if ("note".equals(type)) { + markdownFileMapper.restoreById(Long.parseLong(id)); + } else if ("group".equals(type)) { + groupingMapper.restoreById(Long.parseLong(id)); + } + } + + @Override + @Transactional + public void permanentlyDeleteItem(String id, String type) { + if ("note".equals(type)) { + markdownFileMapper.physicalDeleteById(Long.parseLong(id)); + } else if ("group".equals(type)) { + // 永久删除分组时,也永久删除其下的所有笔记 + groupingMapper.physicalDeleteById(Long.parseLong(id)); + markdownFileMapper.physicalDeleteByGroupingId(Long.parseLong(id)); + } + } + + @Override + @Transactional + public void cleanTrash() { + markdownFileMapper.delete(new QueryWrapper().eq("is_deleted", 1)); + groupingMapper.delete(new QueryWrapper().eq("is_deleted", 1)); + } +} \ No newline at end of file diff --git a/biji-qianduan/src/components/TrashPage.vue b/biji-qianduan/src/components/TrashPage.vue new file mode 100644 index 0000000..c7d43d4 --- /dev/null +++ b/biji-qianduan/src/components/TrashPage.vue @@ -0,0 +1,104 @@ + + + + + \ No newline at end of file diff --git a/回收站功能设计.md b/回收站功能设计.md new file mode 100644 index 0000000..65a66e8 --- /dev/null +++ b/回收站功能设计.md @@ -0,0 +1,22 @@ +# 回收站功能设计方案 + +## 功能需求 +- 实现笔记和分类的软删除功能 +- 提供30天数据保留期 +- 支持恢复和永久删除操作 + +## 前端修改 +1. 侧边栏添加回收站入口 +2. 删除操作改为"移至回收站" +3. 新建TrashPage.vue组件 + +## 后端修改 +```sql +ALTER TABLE markdown ADD COLUMN is_deleted BOOLEAN DEFAULT false; +ALTER TABLE markdown ADD COLUMN deleted_at TIMESTAMP; +``` + +## API接口 +- GET /api/trash - 获取回收站内容 +- POST /api/trash/restore - 恢复项目 +- DELETE /api/trash/clean - 清空回收站 \ No newline at end of file