diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/config/MybatisPlusConfig.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/config/MybatisPlusConfig.java index 3e50436..a55a001 100644 --- a/biji-houdaun/src/main/java/com/test/bijihoudaun/config/MybatisPlusConfig.java +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/config/MybatisPlusConfig.java @@ -3,6 +3,7 @@ package com.test.bijihoudaun.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,11 +11,12 @@ import org.springframework.context.annotation.Configuration; public class MybatisPlusConfig { /** - * 添加分页插件 + * 添加分页插件和逻辑删除插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.SQLITE)); return interceptor; } 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/Grouping.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/Grouping.java index eb464e7..f3260ff 100644 --- a/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/Grouping.java +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/Grouping.java @@ -3,15 +3,19 @@ package com.test.bijihoudaun.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.io.Serializable; +import java.util.Date; + @Data @Schema(name = "分组实体") @TableName("grouping") -public class Grouping { +public class Grouping implements Serializable { @Schema(description = "分组id",implementation = Long.class) @TableId(type = IdType.ASSIGN_ID) @JsonFormat(shape = JsonFormat.Shape.STRING) // 仅作用于此字段 @@ -24,4 +28,14 @@ public class Grouping { @Schema(description = "分组名称",implementation = String.class) private String grouping; + + @Schema(description = "是否删除 0-未删除 1-已删除", implementation = Integer.class) + @TableLogic + private Integer isDeleted; + + @Schema(description = "删除时间", implementation = Date.class) + private Date deletedAt; + + @Schema(description = "删除人ID", implementation = Long.class) + private Long deletedBy; } diff --git a/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/MarkdownFile.java b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/MarkdownFile.java index aa78aad..6c6cfd6 100644 --- a/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/MarkdownFile.java +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/MarkdownFile.java @@ -3,17 +3,19 @@ package com.test.bijihoudaun.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.io.Serializable; import java.util.Date; @Data @Schema(name = "文本实体") @TableName("markdown_file") -public class MarkdownFile { +public class MarkdownFile implements Serializable { @Schema(description = "文本id",implementation = Long.class) @TableId(type = IdType.AUTO) @JsonFormat(shape = JsonFormat.Shape.STRING) // 仅作用于此字段 @@ -33,4 +35,14 @@ public class MarkdownFile { private Date createdAt; @Schema(description = "更新时间",implementation = Date.class) private Date updatedAt; + + @Schema(description = "是否删除 0-未删除 1-已删除", implementation = Integer.class) + @TableLogic + private Integer isDeleted; + + @Schema(description = "删除时间", implementation = Date.class) + private Date deletedAt; + + @Schema(description = "删除人ID", implementation = Long.class) + private Long deletedBy; } 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..4e8368e --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/entity/TrashItemVo.java @@ -0,0 +1,26 @@ +package com.test.bijihoudaun.entity; + +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 name; + + @Schema(description = "项目类型(note 或 group)") + private String type; + + @Schema(description = "删除时间") + 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..1432fc1 --- /dev/null +++ b/biji-houdaun/src/main/java/com/test/bijihoudaun/service/impl/TrashServiceImpl.java @@ -0,0 +1,99 @@ +package com.test.bijihoudaun.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +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() { + // 查询已删除的笔记 + List deletedNotes = markdownFileMapper.selectList(new QueryWrapper().eq("is_deleted", 1)) + .stream() + .map(file -> { + TrashItemVo vo = new TrashItemVo(); + vo.setId(String.valueOf(file.getId())); + vo.setName(file.getTitle()); + vo.setType("note"); + vo.setDeletedAt(file.getDeletedAt()); + vo.setDeletedBy(String.valueOf(file.getDeletedBy())); + return vo; + }) + .collect(Collectors.toList()); + + // 查询已删除的分组 + List deletedGroups = groupingMapper.selectList(new QueryWrapper().eq("is_deleted", 1)) + .stream() + .map(group -> { + TrashItemVo vo = new TrashItemVo(); + vo.setId(String.valueOf(group.getId())); + vo.setName(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)) { + MarkdownFile file = new MarkdownFile(); + file.setId(Long.parseLong(id)); + file.setIsDeleted(0); + file.setDeletedAt(null); + file.setDeletedBy(null); + markdownFileMapper.updateById(file); + } else if ("group".equals(type)) { + Grouping group = new Grouping(); + group.setId(Long.parseLong(id)); + group.setIsDeleted(0); + group.setDeletedAt(null); + group.setDeletedBy(null); + groupingMapper.updateById(group); + } + } + + @Override + @Transactional + public void permanentlyDeleteItem(String id, String type) { + if ("note".equals(type)) { + markdownFileMapper.deleteById(Long.parseLong(id)); + } else if ("group".equals(type)) { + // 删除分组时,也删除其下的所有笔记 + groupingMapper.deleteById(Long.parseLong(id)); + markdownFileMapper.delete(new QueryWrapper().eq("grouping_id", 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-houdaun/src/main/resources/application-dev.yml b/biji-houdaun/src/main/resources/application-dev.yml index 9f0f341..16c8b63 100644 --- a/biji-houdaun/src/main/resources/application-dev.yml +++ b/biji-houdaun/src/main/resources/application-dev.yml @@ -1,8 +1,8 @@ spring: datasource: driver-class-name: org.sqlite.JDBC -# url: jdbc:sqlite:C:\it\houtaigunli\biji\mydatabase.db - url: jdbc:sqlite:C:\KAIFA\2\mydatabase.db + url: jdbc:sqlite:C:\it\houtaigunli\biji\mydatabase.db +# url: jdbc:sqlite:C:\KAIFA\2\mydatabase.db jpa: hibernate: ddl-auto: none diff --git a/biji-houdaun/src/main/resources/application.yml b/biji-houdaun/src/main/resources/application.yml index e85a973..0d94671 100644 --- a/biji-houdaun/src/main/resources/application.yml +++ b/biji-houdaun/src/main/resources/application.yml @@ -29,6 +29,11 @@ mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true + global-config: + db-config: + logic-delete-field: isDeleted # 全局逻辑删除的实体字段名 + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) # JWT 配置 jwt: diff --git a/biji-qianduan/src/api/CommonApi.js b/biji-qianduan/src/api/CommonApi.js index cf4d372..f4eaf91 100644 --- a/biji-qianduan/src/api/CommonApi.js +++ b/biji-qianduan/src/api/CommonApi.js @@ -120,10 +120,10 @@ export const MD5 = (data, file) => { export const getTrash = () => axiosApi.get('/api/trash'); // 恢复项目 -export const restoreTrashItem = (id) => axiosApi.post(`/api/trash/restore/${id}`); +export const restoreTrashItem = (id, type) => axiosApi.post(`/api/trash/restore/${type}/${id}`); // 彻底删除 -export const permanentlyDeleteItem = (id) => axiosApi.delete(`/api/trash/permanently/${id}`); +export const permanentlyDeleteItem = (id, type) => axiosApi.delete(`/api/trash/permanently/${type}/${id}`); // 清空回收站 export const cleanTrash = () => axiosApi.delete('/api/trash/clean'); diff --git a/biji-qianduan/src/components/TrashPage.vue b/biji-qianduan/src/components/TrashPage.vue index 268ed4c..c7d43d4 100644 --- a/biji-qianduan/src/components/TrashPage.vue +++ b/biji-qianduan/src/components/TrashPage.vue @@ -48,7 +48,7 @@ const fetchTrashItems = async () => { const handleRestore = async (item) => { try { - await restoreTrashItem(item.id); + await restoreTrashItem(item.id, item.type); ElMessage.success('恢复成功'); fetchTrashItems(); } catch (error) { @@ -63,7 +63,7 @@ const handleDeletePermanently = async (item) => { type: 'warning', }); try { - await permanentlyDeleteItem(item.id); + await permanentlyDeleteItem(item.id, item.type); ElMessage.success('已永久删除'); fetchTrashItems(); } catch (error) { diff --git a/mydatabase.db b/mydatabase.db index 2b7c05d..99eb939 100644 Binary files a/mydatabase.db and b/mydatabase.db differ diff --git a/sql/data.sql b/sql/data.sql index d221cc3..1aed9b8 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -21,7 +21,10 @@ CREATE TABLE IF NOT EXISTS markdown_file ( file_name TEXT NOT NULL, content TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, + is_deleted INTEGER DEFAULT 0, + deleted_at DATETIME, + deleted_by INTEGER ); -- 图片表 @@ -42,5 +45,8 @@ CREATE TABLE "grouping" ( "id" INTEGER NOT NULL DEFAULT 0, "grouping" TEXT NOT NULL, "parentId" INTEGER, + "is_deleted" INTEGER DEFAULT 0, + "deleted_at" DATETIME, + "deleted_by" INTEGER, PRIMARY KEY ("id") ); \ No newline at end of file