Files
backend/.qoder/repowiki/zh/content/API参考/材质API/材质删除.md
lan a4b6c5011e
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
chore(git): 更新.gitignore以忽略新的本地文件
2025-11-30 08:33:17 +08:00

306 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 材质删除
<cite>
**本文引用的文件**
- [internal/service/texture_service.go](file://internal/service/texture_service.go)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go)
- [internal/model/texture.go](file://internal/model/texture.go)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go)
- [internal/handler/routes.go](file://internal/handler/routes.go)
- [internal/service/texture_service_test.go](file://internal/service/texture_service_test.go)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
## 简介
本专项文档聚焦“材质删除”API围绕删除操作的权限验证机制展开结合服务层与仓储层的实现说明删除流程、成功响应、错误场景以及删除对数据库记录的影响软删除与关联数据处理收藏关系。同时基于测试用例确认删除权限校验逻辑与行为一致性。
## 项目结构
与材质删除相关的代码分布在以下模块:
- 路由注册定义DELETE /api/v1/texture/:id接口
- 处理器:解析参数、鉴权、调用服务层并返回响应
- 服务层:执行业务规则(权限校验、存在性校验)、调用仓储层
- 仓储层:执行数据库操作(软删除)
- 数据模型:定义材质实体、收藏关系、下载日志等
```mermaid
graph TB
Routes["路由注册<br/>routes.go"] --> Handler["处理器<br/>texture_handler.go"]
Handler --> Service["服务层<br/>texture_service.go"]
Service --> Repo["仓储层<br/>texture_repository.go"]
Repo --> Model["数据模型<br/>texture.go"]
```
图表来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
- [internal/model/texture.go](file://internal/model/texture.go#L16-L35)
章节来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
- [internal/model/texture.go](file://internal/model/texture.go#L16-L35)
## 核心组件
- 路由与鉴权
- DELETE /api/v1/texture/:id 由处理器绑定,使用鉴权中间件,要求携带有效令牌。
- 处理器
- 解析路径参数材质ID从上下文提取当前用户ID调用服务层执行删除并按错误码返回相应HTTP状态与响应体。
- 服务层
- 校验材质存在性;校验删除权限(仅上传者可删);调用仓储层执行软删除。
- 仓储层
- 将材质记录的status字段置为-1实现软删除。
- 数据模型
- 材质实体包含UploaderID、Status等字段收藏关系通过user_texture_favorites表维护。
章节来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
- [internal/model/texture.go](file://internal/model/texture.go#L16-L35)
## 架构总览
下图展示从客户端到数据库的完整调用链路,包括鉴权、参数解析、权限校验、软删除与响应返回。
```mermaid
sequenceDiagram
participant C as "客户端"
participant R as "路由(routes.go)"
participant H as "处理器(texture_handler.go)"
participant S as "服务层(texture_service.go)"
participant P as "仓储层(texture_repository.go)"
participant D as "数据库"
C->>R : "DELETE /api/v1/texture/ : id"
R->>H : "进入处理器"
H->>H : "解析路径参数/校验JWT"
H->>S : "service.DeleteTexture(db, textureID, uploaderID)"
S->>P : "FindTextureByID(textureID)"
P-->>S : "返回材质或nil"
alt "材质不存在"
S-->>H : "返回错误:材质不存在"
H-->>C : "403 错误响应"
else "材质存在"
S->>S : "校验 uploaderID == 请求者ID"
alt "非上传者"
S-->>H : "返回错误:无权删除此材质"
H-->>C : "403 错误响应"
else "上传者本人"
S->>P : "DeleteTexture(textureID)"
P->>D : "UPDATE textures SET status=-1 WHERE id=..."
D-->>P : "OK"
P-->>S : "OK"
S-->>H : "OK"
H-->>C : "200 成功响应"
end
end
```
图表来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
## 详细组件分析
### 删除API请求流程与权限验证
- 路由与鉴权
- DELETE /api/v1/texture/:id 由处理器绑定,使用鉴权中间件,要求携带有效令牌。
- 参数解析与鉴权
- 处理器从路径参数解析材质ID从上下文提取当前用户ID若缺失则返回未授权。
- 权限验证
- 服务层先查询材质是否存在且未被软删除;
- 再校验请求者ID与材质的UploaderID一致否则返回无权删除。
- 执行删除
- 通过仓储层将材质记录的status字段置为-1完成软删除。
- 响应
- 成功返回200与通用成功响应体错误返回403及错误信息。
```mermaid
flowchart TD
Start(["开始"]) --> Parse["解析路径参数<br/>获取材质ID"]
Parse --> Auth{"JWT鉴权通过"}
Auth --> |否| Resp401["返回401 未授权"]
Auth --> |是| Load["查询材质记录"]
Load --> Exists{"是否存在且未软删除?"}
Exists --> |否| Resp403a["返回403 材质不存在/已删除"]
Exists --> |是| Perm{"请求者ID==上传者ID"}
Perm --> |否| Resp403b["返回403 无权删除此材质"]
Perm --> |是| SoftDel["软删除设置status=-1"]
SoftDel --> Resp200["返回200 成功"]
Resp401 --> End(["结束"])
Resp403a --> End
Resp403b --> End
Resp200 --> End
```
图表来源
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
章节来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
### 权限验证机制
- 上传者身份判定
- 服务层比较请求者的用户ID与材质记录中的UploaderID仅当两者相等时才允许删除。
- 存在性与状态校验
- 查询材质时会忽略status=-1的记录软删除因此若返回nil即视为“不存在”。
- 测试覆盖
- 单元测试包含“删除权限检查”的用例验证相同ID允许删除、不同ID拒绝删除的行为。
章节来源
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/service/texture_service_test.go](file://internal/service/texture_service_test.go#L315-L345)
### 删除API的成功响应与错误情况
- 成功响应
- HTTP 200返回通用成功响应体无额外数据
- 常见错误
- 401 未授权缺少或无效的JWT令牌。
- 400 参数错误材质ID格式非法。
- 403 无权删除:请求者非材质上传者。
- 403 材质不存在:目标材质不存在或已被软删除。
- 处理器侧错误分支
- 参数解析失败返回400
- 服务层返回错误时统一转换为403无权删除/不存在)。
章节来源
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
### 数据库记录影响与关联数据处理
- 删除策略
- 采用软删除将textures表的status字段置为-1不物理移除记录。
- 影响范围
- 材质记录仍保留,便于审计与历史追踪;
- 查询接口如获取详情、搜索、我的材质均会忽略status=-1的记录。
- 关联数据
- 收藏关系删除操作不直接清理user_texture_favorites表中的收藏记录
- 若需清理收藏,应在业务层面另行设计或在仓储层扩展软删除时级联处理(当前实现未体现)。
- 下载日志
- 删除操作不涉及texture_download_logs表的清理。
章节来源
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
- [internal/model/texture.go](file://internal/model/texture.go#L16-L35)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L66-L79)
### 类图(代码级)
```mermaid
classDiagram
class Texture {
+int64 id
+int64 uploader_id
+string name
+string description
+TextureType type
+string url
+string hash
+int size
+bool is_public
+int download_count
+int favorite_count
+bool is_slim
+int16 status
+time created_at
+time updated_at
}
class UserTextureFavorite {
+int64 id
+int64 user_id
+int64 texture_id
+time created_at
}
class TextureDownloadLog {
+int64 id
+int64 texture_id
+*int64 user_id
+string ip_address
+string user_agent
+time created_at
}
Texture --> UserTextureFavorite : "收藏关系"
Texture --> TextureDownloadLog : "下载日志"
```
图表来源
- [internal/model/texture.go](file://internal/model/texture.go#L16-L35)
- [internal/model/texture.go](file://internal/model/texture.go#L42-L57)
- [internal/model/texture.go](file://internal/model/texture.go#L60-L71)
## 依赖分析
- 组件耦合
- 处理器依赖服务层;服务层依赖仓储层;仓储层依赖数据库访问工具。
- 关键依赖链
- 路由 -> 处理器 -> 服务层 -> 仓储层 -> 数据库
- 可能的循环依赖
- 当前文件间未发现循环导入;各层职责清晰,符合分层架构。
```mermaid
graph LR
Routes["routes.go"] --> Handler["texture_handler.go"]
Handler --> Service["texture_service.go"]
Service --> Repo["texture_repository.go"]
Repo --> DB["数据库"]
```
图表来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
章节来源
- [internal/handler/routes.go](file://internal/handler/routes.go#L42-L61)
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
- [internal/repository/texture_repository.go](file://internal/repository/texture_repository.go#L126-L130)
## 性能考虑
- 查询与软删除
- 删除前的查询与软删除均为单记录操作,复杂度低。
- 索引与过滤
- 材质查询通常按UploaderID、状态、公开性等条件过滤建议确保相关列具备索引以提升查询效率。
- 批量与事务
- 当前删除为单条记录操作,无需事务;若未来扩展批量删除,需评估事务边界与回滚策略。
## 故障排查指南
- 401 未授权
- 检查请求头Authorization是否携带有效JWT确认中间件已正确注入user_id。
- 400 参数错误
- 检查路径参数id是否为合法整数。
- 403 无权删除
- 确认当前用户ID与材质记录的UploaderID一致核对服务层权限校验逻辑。
- 403 材质不存在
- 确认材质ID有效且未被软删除检查仓储层查询是否正确忽略status=-1。
- 日志定位
- 处理器与服务层均记录错误日志,可据此快速定位问题。
章节来源
- [internal/handler/texture_handler.go](file://internal/handler/texture_handler.go#L371-L419)
- [internal/service/texture_service.go](file://internal/service/texture_service.go#L143-L160)
## 结论
- 权限验证严格仅上传者可删除材质服务层明确校验请求者ID与UploaderID一致性。
- 删除策略为软删除通过status字段标记删除不破坏历史数据与关联完整性。
- 错误处理清晰处理器将服务层错误映射为403配合日志便于排障。
- 关联清理:当前实现未清理收藏关系,如需可在业务层补充或扩展仓储层软删除逻辑。