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