Files
junhong_cmp_fiber/openspec/changes/archive/2026-01-30-login-response-menus-buttons/tasks.md
2026-01-30 17:22:38 +08:00

115 lines
8.7 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.
## 1. DTO 结构定义
- [x] 1.1 在 `internal/model/dto/auth_dto.go` 中新增 `MenuNode` 结构体,包含 `ID`, `PermCode`, `Name`, `URL`, `Sort`, `Children` 字段,所有字段添加 JSON 标签
- [x] 1.2 修改 `LoginResponse` 结构体,新增 `Menus []MenuNode``Buttons []string` 字段,添加 JSON 标签和 description 注释
- [x] 1.3 运行 `lsp_diagnostics` 验证 DTO 文件无错误
## 2. Service 层核心方法实现
- [x] 2.1 在 `internal/service/auth/service.go` 中新增 `getUserPermissionsAndMenus()` 方法,接收参数 `ctx, userID, userType, device`,返回 `([]string, []MenuNode, []string, error)`
- [x] 2.2 在 `getUserPermissionsAndMenus()` 中实现超级管理员逻辑:调用 `permissionStore.GetAll(ctx, nil)` 查询所有启用的权限
- [x] 2.3 在 `getUserPermissionsAndMenus()` 中实现普通用户逻辑:复用现有的角色权限查询(`accountRoleStore.GetByAccountID()``rolePermStore.GetPermIDsByRoleIDs()``permissionStore.GetByIDs()`
- [x] 2.4 新增 `classifyPermissions()` 方法,接收参数 `permissions []*model.Permission, device string`,实现权限分类和平台过滤逻辑
- [x] 2.5 在 `classifyPermissions()` 中实现平台过滤:`platform == "all"``platform == device` 时保留,否则跳过
- [x] 2.6 在 `classifyPermissions()` 中实现权限分类:`perm_type == 1` 的收集到 `menuPerms``perm_type == 2` 的提取 `perm_code``buttonCodes`
- [x] 2.7 在 `classifyPermissions()` 中收集所有权限码到 `allCodes` 数组(用于 `permissions` 字段)
## 3. 菜单树构建逻辑
- [x] 3.1 新增 `buildMenuTree()` 方法,接收参数 `permissions []*model.Permission`,返回 `[]MenuNode`
- [x] 3.2 在 `buildMenuTree()` 中实现第一步:创建节点映射 `nodeMap := make(map[uint]*dto.MenuNode)`,遍历权限列表构建 MenuNode 对象
- [x] 3.3 在 `buildMenuTree()` 中实现第二步:组织父子关系,根据 `parent_id` 将节点追加到父节点的 `Children` 数组或 `roots` 数组
- [x] 3.4 在 `buildMenuTree()` 中实现孤儿节点处理:如果 `parent_id` 不在 `nodeMap` 中,将节点提升为根节点,并记录警告日志
- [x] 3.5 新增 `sortMenuNodes()` 方法,接收参数 `nodes []MenuNode`,实现递归排序(根据 `Sort` 字段升序)
- [x] 3.6 在 `buildMenuTree()` 中调用 `sortMenuNodes(roots)` 完成排序后返回
## 4. 超级管理员专用逻辑
- [x] 4.1 新增 `getAllPermissionsForSuperAdmin()` 方法,接收参数 `ctx, device`,返回 `([]string, []MenuNode, []string, error)`
- [x] 4.2 在 `getAllPermissionsForSuperAdmin()` 中调用 `permissionStore.GetAll(ctx, nil)` 查询所有启用的权限
- [x] 4.3 在 `getAllPermissionsForSuperAdmin()` 中调用 `classifyPermissions(allPerms, device)` 完成分类和过滤
## 5. 修改 Login 方法
- [x] 5.1 在 `auth.Service.Login()` 方法中,将 `getUserPermissions(ctx, account.ID)` 替换为 `getUserPermissionsAndMenus(ctx, account.ID, account.UserType, device)`
- [x] 5.2 在 `Login()` 方法中,将返回的 `(permissions, menus, buttons, err)` 赋值到 `LoginResponse` 的对应字段
- [x] 5.3 处理错误:如果 `getUserPermissionsAndMenus()` 失败,记录错误日志,返回空的 `menus: []``buttons: []`(不阻塞登录)
- [x] 5.4 运行 `lsp_diagnostics` 验证 Service 文件无错误
## 6. 单元测试 - buildMenuTree
- [x] 6.1 创建 `internal/service/auth/menu_tree_test.go` 文件
- [x] 6.2 编写测试 `TestBuildMenuTree_RootNodes`:测试只有根节点的场景(`parent_id = NULL`
- [x] 6.3 编写测试 `TestBuildMenuTree_MultiLevel`:测试两级或三级嵌套菜单场景
- [x] 6.4 编写测试 `TestBuildMenuTree_OrphanNodes`:测试孤儿节点提升为根节点的场景(`parent_id` 不存在)
- [x] 6.5 编写测试 `TestBuildMenuTree_Sorting`:测试菜单排序(根据 `sort` 字段升序)
- [x] 6.6 编写测试 `TestBuildMenuTree_EmptyInput`:测试空权限列表输入,验证返回空数组
- [x] 6.7 运行单元测试:`source .env.local && go test -v ./internal/service/auth/...`,确保所有测试通过
## 7. 单元测试 - classifyPermissions
- [x] 7.1 创建 `internal/service/auth/classify_test.go` 文件
- [x] 7.2 编写测试 `TestClassifyPermissions_PlatformFilter`:测试平台过滤(`device="web"` 时过滤 `platform="h5"` 的权限)
- [x] 7.3 编写测试 `TestClassifyPermissions_MenuAndButton`:测试菜单和按钮权限分类(`perm_type=1` vs `perm_type=2`
- [x] 7.4 编写测试 `TestClassifyPermissions_AllPermissions`:测试所有权限码收集(包含菜单和按钮)
- [x] 7.5 编写测试 `TestClassifyPermissions_PlatformAll`:测试 `platform="all"` 的权限对所有端口可见
- [x] 7.6 运行单元测试:`source .env.local && go test -v ./internal/service/auth/...`,确保所有测试通过
## 8. 单元测试 - getUserPermissionsAndMenus
- [x] 8.1 编写测试 `TestGetUserPermissionsAndMenus_SuperAdmin`:测试超级管理员返回所有权限
- [x] 8.2 编写测试 `TestGetUserPermissionsAndMenus_NormalUser`:测试普通用户返回角色权限
- [x] 8.3 编写测试 `TestGetUserPermissionsAndMenus_NoPermissions`:测试用户无权限时返回空数组
- [x] 8.4 编写测试 `TestGetUserPermissionsAndMenus_DeviceFilter`:测试 `device` 参数过滤平台
- [x] 8.5 运行单元测试:`source .env.local && go test -v ./internal/service/auth/...`,确保所有测试通过
## 9. 集成测试 - Login API
- [x] 9.1 创建或修改 `tests/integration/admin_auth_test.go` 文件
- [x] 9.2 编写测试 `TestAdminLogin_MenusAndButtons`:验证登录响应包含 `menus`, `buttons`, `permissions` 三个字段
- [x] 9.3 编写测试 `TestAdminLogin_MenuTreeStructure`:验证 `menus` 为树形结构,包含 `id`, `perm_code`, `name`, `url`, `sort`, `children` 字段
- [x] 9.4 编写测试 `TestAdminLogin_ButtonsArray`:验证 `buttons` 为扁平数组,只包含 `perm_type=2` 的权限码
- [x] 9.5 编写测试 `TestAdminLogin_SuperAdmin`:验证超级管理员登录时返回所有菜单和按钮
- [x] 9.6 编写测试 `TestAdminLogin_PlatformFilter`:验证 `device="web"` 时不返回 `platform="h5"` 的菜单
- [x] 9.7 编写测试 `TestAdminLogin_NoPermissions`:验证无权限用户登录时返回空的 `menus``buttons`
- [x] 9.8 运行集成测试:`source .env.local && go test -v ./tests/integration/...`,确保所有测试通过
## 10. 集成测试 - GetMe API
- [x] 10.1 编写测试 `TestAdminGetMe_NoMenus`:验证 GetMe 接口不返回 `menus``buttons` 字段
- [x] 10.2 编写测试 `TestAdminGetMe_OnlyUserAndPermissions`:验证 GetMe 接口只返回 `user``permissions` 字段
- [x] 10.3 运行集成测试:`source .env.local && go test -v ./tests/integration/...`,确保所有测试通过
## 11. 性能测试
- [x] 11.1 编写性能基准测试 `BenchmarkBuildMenuTree`测试不同权限数量50、100、200的菜单树构建性能
- [x] 11.2 编写性能基准测试 `BenchmarkClassifyPermissions`:测试权限分类性能
- [x] 11.3 运行基准测试:`source .env.local && go test -bench=. -benchmem ./internal/service/auth/...`
- [x] 11.4 验证登录接口响应时间增加 < 50ms在 50 个权限的场景下)
## 12. 代码审查和优化
- [x] 12.1 运行 `lsp_diagnostics` 检查所有修改的文件,确保无类型错误和警告
- [x] 12.2 运行 `gofmt -w ./internal/service/auth/service.go` 格式化代码
- [x] 12.3 运行 `gofmt -w ./internal/model/dto/auth_dto.go` 格式化代码
- [x] 12.4 检查所有注释使用中文,变量名和函数名使用英文
- [x] 12.5 检查错误处理:使用 `errors.New()``errors.Wrap()`,不使用 `fmt.Errorf()`
- [x] 12.6 检查日志记录:孤儿节点检测时记录警告日志(使用 Zap
## 13. 文档更新
- [x] 13.1 更新 `README.md`:在"核心功能"部分添加"登录接口返回菜单树和按钮权限"说明
- [x] 13.2 创建 `docs/login-menu-button-response/使用指南.md`:说明前端如何使用 `menus``buttons` 字段
- [x] 13.3 在使用指南中添加 localStorage 缓存示例代码
- [x] 13.4 在使用指南中添加 MenuNode 数据结构说明和示例响应
- [x] 13.5 在使用指南中添加性能影响说明和最佳实践建议
## 14. 最终验证
- [x] 14.1 运行完整测试套件:`source .env.local && go test ./...`,确保所有测试通过
- [x] 14.2 启动 API 服务:`go run cmd/api/main.go`,验证服务正常启动
- [x] 14.3 使用 Postman/curl 测试登录接口:验证响应包含 `menus`, `buttons`, `permissions` 三个字段
- [x] 14.4 验证响应体大小 < 20KB普通用户场景
- [x] 14.5 验证 GetMe 接口不返回 `menus``buttons` 字段
- [x] 14.6 验证向后兼容性:旧版前端仍可使用 `permissions` 字段