You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

7.4 KiB

Changelog: 文件夹服务规范符合度修复

日期: 2026-01-28
类型: 文档修复
影响范围: docs/requirements/backend/04-services/project/folder-service.md
版本: v3.4


修复概述

完整修复 folder-service.md 文档的技术栈规范符合度问题,包括数据库设计、应用层实现、职责划分等多个方面。


修复内容

阶段 1: 基础规范修复(v3.3)

1.1 移除物理外键约束

问题: 使用了 FOREIGN KEY 物理约束,违反项目规范

修复:

  • 移除所有 FOREIGN KEY 约束
  • 改为逻辑外键(仅注释说明关联关系)
  • 在应用层(Service/Repository)实现引用完整性校验

影响表:

  • folders 表:parent_folder_id, owner_id, cover_image_id
  • folder_members 表:folder_id, user_id, invited_by
  • folder_shares 表:folder_id, shared_with_user_id, created_by
  • folder_export_jobs 表:folder_id, user_id
  • projects 表:folder_id

1.2 修复时间戳字段

问题: 使用了 now() 函数,不符合规范

修复:

  • SQL 层:DEFAULT now()DEFAULT CURRENT_TIMESTAMP
  • Python 层:datetime.now(timezone.utc)datetime.now(UTC)

影响字段:

  • created_at
  • updated_at
  • joined_at
  • started_at
  • completed_at
  • expires_at

1.3 修复枚举类型定义

问题:

  • 缺少 Python IntEnum 定义
  • 缺少枚举值映射表

修复:

  • 添加 FolderCategory(IntEnum) 定义
  • 添加 MemberRole(IntEnum) 定义
  • 添加成员角色枚举值映射表
  • 添加导出状态枚举值映射表

1.4 添加 SQL 注释

问题: 缺少表和字段的 SQL 注释

修复:

  • 为所有表添加 COMMENT ON TABLE
  • 为所有字段添加 COMMENT ON COLUMN
  • 注释中说明逻辑外键关系
  • 注释中说明枚举值含义

影响表:

  • folders
  • folder_members
  • folder_shares
  • folder_export_jobs

1.5 移除 SQLModel foreign_key 参数

问题: SQLModel 模型中使用了 foreign_key 参数

修复:

  • 移除所有 foreign_key 参数
  • 仅保留类型注解和字段定义

1.6 增强引用完整性校验

问题: 缺少应用层的引用完整性校验

修复:

  • 添加 _validate_user_exists() 方法
  • 添加 _validate_folder_exists() 方法
  • 添加 _validate_attachment_exists_and_owned() 方法
  • 在所有相关操作中调用校验方法

1.7 补充完整的 Repository 实现

问题: FolderRepository 实现不完整

修复:

  • 补充所有 CRUD 方法
  • 添加权限检查方法
  • 添加循环引用检测方法
  • 添加树形结构查询方法

1.8 添加日志记录

问题: 缺少操作日志

修复:

  • 在关键操作中添加 logger.info() 记录
  • 记录创建、更新、删除、移动等操作

阶段 2: 深度问题修复(v3.4)

2.1 修复 UUID 生成方式

问题: 使用了 DEFAULT gen_uuid_v7(),违反规范

修复:

  • 移除所有表的 DEFAULT gen_uuid_v7()
  • 改为应用层生成:id=generate_uuid()
  • 添加注释:-- UUID 由应用层生成

影响表:

  • folders
  • folder_members
  • folder_shares
  • folder_export_jobs

2.2 修复 SQL 触发器函数分隔符

问题: 使用单个 $ 作为函数分隔符,语法错误

修复:

  • RETURNS TRIGGER AS $RETURNS TRIGGER AS $$
  • END; $ LANGUAGE plpgsql;END; $$ LANGUAGE plpgsql;

影响函数:

  • update_folder_path()
  • inherit_folder_category()

2.3 修复唯一约束处理 NULL 值

问题: 普通唯一约束无法正确处理 NULL 值

修复:

  • 使用部分唯一索引(Partial Unique Index)
  • 根文件夹和非根文件夹分别创建索引
  • 添加 WHERE 条件过滤 NULL 值

修复前:

CONSTRAINT folders_name_unique UNIQUE (parent_folder_id, owner_id, name)

修复后:

-- 非根文件夹
CREATE UNIQUE INDEX idx_folders_name_unique_with_parent 
ON folders (parent_folder_id, owner_id, name) 
WHERE parent_folder_id IS NOT NULL AND deleted_at IS NULL;

-- 根文件夹
CREATE UNIQUE INDEX idx_folders_name_unique_root 
ON folders (owner_id, name) 
WHERE parent_folder_id IS NULL AND deleted_at IS NULL;

2.4 明确职责划分(数据库 vs 应用层)

问题: 数据库层和应用层职责不清晰

修复:

数据库层(触发器):

  • 自动更新时间戳(update_updated_at_column()
  • 自动计算路径和层级(update_folder_path()
  • 自动继承分类(inherit_folder_category()

应用层(Service):

  • 权限检查(check_user_permission()
  • 循环引用检测(would_create_cycle()
  • 名称唯一性检查(exists_by_name()
  • 引用完整性校验(_validate_*_exists()

移除的 SQL 函数:

  • check_folder_permission() - 改为应用层实现
  • check_folder_cycle() - 改为应用层实现
  • get_accessible_folders() - 改为应用层实现

2.5 双重保护机制

策略: 应用层主动检查 + 数据库索引兜底

实现:

  1. 应用层:在 create_folder()update_folder() 中主动调用 exists_by_name() 检查
  2. 数据库层:使用部分唯一索引作为最后防线
  3. 优势
    • 应用层检查提供友好错误提示
    • 数据库索引确保数据完整性
    • 防止并发场景下的数据冲突

符合度评分

阶段 版本 评分 说明
初始状态 v3.2 60/100 存在多个严重问题
基础修复 v3.3 95/100 修复外键、时间戳、枚举等问题
深度排查 v3.3 45/100 发现 UUID、SQL 语法等新问题
完整修复 v3.4 95/100 所有问题已修复

当前扣分项(5分)

  • 文档完整性(-3分):部分高级功能(克隆、导出、分享)的实现细节需要补充
  • 测试用例(-2分):缺少单元测试和集成测试示例

验证结果

已验证项

  1. UUID 生成: 所有表均无 DEFAULT gen_uuid_v7()
  2. SQL 语法: 触发器函数使用正确的 $$ 分隔符
  3. 唯一约束: 使用部分唯一索引处理 NULL 值
  4. 时间戳: 所有时间字段使用 CURRENT_TIMESTAMP
  5. 枚举类型: 使用 SMALLINT 存储,代码层使用 IntEnum
  6. 外键约束: 无物理外键,仅逻辑关联
  7. SQL 注释: 所有表和字段均有完整注释
  8. 职责划分: 数据完整性用触发器,业务逻辑在应用层

📊 统计数据

  • 修复表数量: 4 个(folders, folder_members, folder_shares, folder_export_jobs)
  • 移除 UUID 默认值: 4 处
  • 修复触发器函数: 2 个
  • 添加部分唯一索引: 2 个
  • 移除 SQL 函数: 3 个
  • 添加应用层校验方法: 3 个
  • 添加 SQL 注释: 50+ 条

相关文件

  • 主文档:docs/requirements/backend/04-services/project/folder-service.md
  • 技术栈规范:.claude/skills/jointo-tech-stack/references/database.md
  • 服务文档规范:docs/requirements/backend/04-services/README.md
  • 数据库规范:docs/architecture/datetime-timezone-standards.md

后续建议

  1. 补充测试用例:为 FolderService 和 FolderRepository 编写完整的测试
  2. 性能优化:考虑为高频查询添加缓存(Redis)
  3. 监控告警:添加关键操作的监控指标
  4. API 文档:使用 OpenAPI 规范生成完整的 API 文档
  5. 实现高级功能:完善克隆、导出、分享功能的实现细节