refactor(account): 移除卡类型字段、优化账号列表查询和权限检查
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m18s

- 移除 IoT 卡和号卡的 card_type 字段(数据库迁移)
- 优化账号列表查询,支持按店铺和企业筛选
- 账号响应增加店铺名称和企业名称字段
- 实现批量加载店铺和企业名称,避免 N+1 查询
- 更新权限检查中间件,完善权限验证逻辑
- 更新相关测试用例,确保功能正确性
This commit is contained in:
2026-02-03 10:59:44 +08:00
parent ad6d43e0cd
commit fba8e9e76b
31 changed files with 409 additions and 145 deletions

View File

@@ -336,7 +336,7 @@ func (s *Service) Delete(ctx context.Context, id uint) error {
}
// List 查询账号列表
func (s *Service) List(ctx context.Context, req *dto.AccountListRequest) ([]*model.Account, int64, error) {
func (s *Service) List(ctx context.Context, req *dto.AccountListRequest) ([]*dto.AccountResponse, int64, error) {
opts := &store.QueryOptions{
Page: req.Page,
PageSize: req.PageSize,
@@ -362,8 +362,28 @@ func (s *Service) List(ctx context.Context, req *dto.AccountListRequest) ([]*mod
if req.Status != nil {
filters["status"] = *req.Status
}
if req.ShopID != nil {
filters["shop_id"] = *req.ShopID
}
if req.EnterpriseID != nil {
filters["enterprise_id"] = *req.EnterpriseID
}
return s.accountStore.List(ctx, opts, filters)
accounts, total, err := s.accountStore.List(ctx, opts, filters)
if err != nil {
return nil, 0, err
}
shopMap := s.loadShopNames(ctx, accounts)
enterpriseMap := s.loadEnterpriseNames(ctx, accounts)
responses := make([]*dto.AccountResponse, 0, len(accounts))
for _, acc := range accounts {
resp := s.toAccountResponse(acc, shopMap, enterpriseMap)
responses = append(responses, resp)
}
return responses, total, nil
}
// AssignRoles 为账号分配角色(支持空数组清空所有角色,超级管理员禁止分配)
@@ -696,3 +716,78 @@ func (s *Service) CreateSystemAccount(ctx context.Context, account *model.Accoun
return nil
}
// loadShopNames 批量加载店铺名称
func (s *Service) loadShopNames(ctx context.Context, accounts []*model.Account) map[uint]string {
shopIDs := make([]uint, 0)
shopIDSet := make(map[uint]bool)
for _, acc := range accounts {
if acc.ShopID != nil && *acc.ShopID > 0 && !shopIDSet[*acc.ShopID] {
shopIDs = append(shopIDs, *acc.ShopID)
shopIDSet[*acc.ShopID] = true
}
}
shopMap := make(map[uint]string)
if len(shopIDs) > 0 {
shops, err := s.shopStore.GetByIDs(ctx, shopIDs)
if err == nil {
for _, shop := range shops {
shopMap[shop.ID] = shop.ShopName
}
}
}
return shopMap
}
// loadEnterpriseNames 批量加载企业名称
func (s *Service) loadEnterpriseNames(ctx context.Context, accounts []*model.Account) map[uint]string {
enterpriseIDs := make([]uint, 0)
enterpriseIDSet := make(map[uint]bool)
for _, acc := range accounts {
if acc.EnterpriseID != nil && *acc.EnterpriseID > 0 && !enterpriseIDSet[*acc.EnterpriseID] {
enterpriseIDs = append(enterpriseIDs, *acc.EnterpriseID)
enterpriseIDSet[*acc.EnterpriseID] = true
}
}
enterpriseMap := make(map[uint]string)
if len(enterpriseIDs) > 0 {
enterprises, err := s.enterpriseStore.GetByIDs(ctx, enterpriseIDs)
if err == nil {
for _, ent := range enterprises {
enterpriseMap[ent.ID] = ent.EnterpriseName
}
}
}
return enterpriseMap
}
// toAccountResponse 组装账号响应,填充关联名称
func (s *Service) toAccountResponse(acc *model.Account, shopMap map[uint]string, enterpriseMap map[uint]string) *dto.AccountResponse {
resp := &dto.AccountResponse{
ID: acc.ID,
Username: acc.Username,
Phone: acc.Phone,
UserType: acc.UserType,
ShopID: acc.ShopID,
EnterpriseID: acc.EnterpriseID,
Status: acc.Status,
Creator: acc.Creator,
Updater: acc.Updater,
CreatedAt: acc.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: acc.UpdatedAt.Format("2006-01-02 15:04:05"),
}
if acc.ShopID != nil && *acc.ShopID > 0 {
resp.ShopName = shopMap[*acc.ShopID]
}
if acc.EnterpriseID != nil && *acc.EnterpriseID > 0 {
resp.EnterpriseName = enterpriseMap[*acc.EnterpriseID]
}
return resp
}