package customer_account import ( "context" "fmt" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) type Service struct { db *gorm.DB accountStore *postgres.AccountStore shopStore *postgres.ShopStore enterpriseStore *postgres.EnterpriseStore } func New( db *gorm.DB, accountStore *postgres.AccountStore, shopStore *postgres.ShopStore, enterpriseStore *postgres.EnterpriseStore, ) *Service { return &Service{ db: db, accountStore: accountStore, shopStore: shopStore, enterpriseStore: enterpriseStore, } } func (s *Service) List(ctx context.Context, req *dto.CustomerAccountListReq) (*dto.CustomerAccountPageResult, error) { page := req.Page pageSize := req.PageSize if page == 0 { page = 1 } if pageSize == 0 { pageSize = constants.DefaultPageSize } query := s.db.WithContext(ctx).Model(&model.Account{}). Where("user_type IN ?", []int{constants.UserTypeAgent, constants.UserTypeEnterprise}) if req.Username != "" { query = query.Where("username LIKE ?", "%"+req.Username+"%") } if req.Phone != "" { query = query.Where("phone LIKE ?", "%"+req.Phone+"%") } if req.UserType != nil { query = query.Where("user_type = ?", *req.UserType) } if req.ShopID != nil { query = query.Where("shop_id = ?", *req.ShopID) } if req.EnterpriseID != nil { query = query.Where("enterprise_id = ?", *req.EnterpriseID) } if req.Status != nil { query = query.Where("status = ?", *req.Status) } var total int64 if err := query.Count(&total).Error; err != nil { return nil, fmt.Errorf("统计账号数量失败: %w", err) } var accounts []model.Account offset := (page - 1) * pageSize if err := query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&accounts).Error; err != nil { return nil, fmt.Errorf("查询账号列表失败: %w", err) } shopIDs := make([]uint, 0) enterpriseIDs := make([]uint, 0) for _, acc := range accounts { if acc.ShopID != nil { shopIDs = append(shopIDs, *acc.ShopID) } if acc.EnterpriseID != nil { enterpriseIDs = append(enterpriseIDs, *acc.EnterpriseID) } } shopMap := make(map[uint]string) if len(shopIDs) > 0 { var shops []model.Shop s.db.WithContext(ctx).Where("id IN ?", shopIDs).Find(&shops) for _, shop := range shops { shopMap[shop.ID] = shop.ShopName } } enterpriseMap := make(map[uint]string) if len(enterpriseIDs) > 0 { var enterprises []model.Enterprise s.db.WithContext(ctx).Where("id IN ?", enterpriseIDs).Find(&enterprises) for _, ent := range enterprises { enterpriseMap[ent.ID] = ent.EnterpriseName } } items := make([]dto.CustomerAccountItem, 0, len(accounts)) for _, acc := range accounts { shopName := "" if acc.ShopID != nil { shopName = shopMap[*acc.ShopID] } enterpriseName := "" if acc.EnterpriseID != nil { enterpriseName = enterpriseMap[*acc.EnterpriseID] } items = append(items, dto.CustomerAccountItem{ ID: acc.ID, Username: acc.Username, Phone: acc.Phone, UserType: acc.UserType, UserTypeName: getUserTypeName(acc.UserType), ShopID: acc.ShopID, ShopName: shopName, EnterpriseID: acc.EnterpriseID, EnterpriseName: enterpriseName, Status: acc.Status, StatusName: getStatusName(acc.Status), CreatedAt: acc.CreatedAt.Format("2006-01-02 15:04:05"), }) } return &dto.CustomerAccountPageResult{ Items: items, Total: total, Page: page, Size: pageSize, }, nil } func (s *Service) Create(ctx context.Context, req *dto.CreateCustomerAccountReq) (*dto.CustomerAccountItem, error) { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } _, err := s.shopStore.GetByID(ctx, req.ShopID) if err != nil { return nil, errors.New(errors.CodeShopNotFound, "店铺不存在") } existingAccount, _ := s.accountStore.GetByPhone(ctx, req.Phone) if existingAccount != nil { return nil, errors.New(errors.CodePhoneExists, "手机号已被使用") } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { return nil, fmt.Errorf("密码加密失败: %w", err) } account := &model.Account{ Username: req.Username, Phone: req.Phone, Password: string(hashedPassword), UserType: constants.UserTypeAgent, ShopID: &req.ShopID, Status: constants.StatusEnabled, } account.Creator = currentUserID account.Updater = currentUserID if err := s.db.WithContext(ctx).Create(account).Error; err != nil { return nil, fmt.Errorf("创建账号失败: %w", err) } shop, _ := s.shopStore.GetByID(ctx, req.ShopID) shopName := "" if shop != nil { shopName = shop.ShopName } return &dto.CustomerAccountItem{ ID: account.ID, Username: account.Username, Phone: account.Phone, UserType: account.UserType, UserTypeName: getUserTypeName(account.UserType), ShopID: account.ShopID, ShopName: shopName, Status: account.Status, StatusName: getStatusName(account.Status), CreatedAt: account.CreatedAt.Format("2006-01-02 15:04:05"), }, nil } func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdateCustomerAccountRequest) (*dto.CustomerAccountItem, error) { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return nil, errors.New(errors.CodeUnauthorized, "未授权访问") } account, err := s.accountStore.GetByID(ctx, id) if err != nil { return nil, errors.New(errors.CodeAccountNotFound, "账号不存在") } if account.UserType != constants.UserTypeAgent && account.UserType != constants.UserTypeEnterprise { return nil, errors.New(errors.CodeForbidden, "无权限操作此账号") } if req.Username != nil { account.Username = *req.Username } if req.Phone != nil { if *req.Phone != account.Phone { existingAccount, _ := s.accountStore.GetByPhone(ctx, *req.Phone) if existingAccount != nil && existingAccount.ID != id { return nil, errors.New(errors.CodePhoneExists, "手机号已被使用") } account.Phone = *req.Phone } } account.Updater = currentUserID if err := s.db.WithContext(ctx).Save(account).Error; err != nil { return nil, fmt.Errorf("更新账号失败: %w", err) } shopName := "" if account.ShopID != nil { if shop, _ := s.shopStore.GetByID(ctx, *account.ShopID); shop != nil { shopName = shop.ShopName } } enterpriseName := "" if account.EnterpriseID != nil { if ent, _ := s.enterpriseStore.GetByID(ctx, *account.EnterpriseID); ent != nil { enterpriseName = ent.EnterpriseName } } return &dto.CustomerAccountItem{ ID: account.ID, Username: account.Username, Phone: account.Phone, UserType: account.UserType, UserTypeName: getUserTypeName(account.UserType), ShopID: account.ShopID, ShopName: shopName, EnterpriseID: account.EnterpriseID, EnterpriseName: enterpriseName, Status: account.Status, StatusName: getStatusName(account.Status), CreatedAt: account.CreatedAt.Format("2006-01-02 15:04:05"), }, nil } func (s *Service) UpdatePassword(ctx context.Context, id uint, password string) error { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } account, err := s.accountStore.GetByID(ctx, id) if err != nil { return errors.New(errors.CodeAccountNotFound, "账号不存在") } if account.UserType != constants.UserTypeAgent && account.UserType != constants.UserTypeEnterprise { return errors.New(errors.CodeForbidden, "无权限操作此账号") } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return fmt.Errorf("密码加密失败: %w", err) } return s.db.WithContext(ctx).Model(&model.Account{}). Where("id = ?", id). Updates(map[string]interface{}{ "password": string(hashedPassword), "updater": currentUserID, }).Error } func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error { currentUserID := middleware.GetUserIDFromContext(ctx) if currentUserID == 0 { return errors.New(errors.CodeUnauthorized, "未授权访问") } account, err := s.accountStore.GetByID(ctx, id) if err != nil { return errors.New(errors.CodeAccountNotFound, "账号不存在") } if account.UserType != constants.UserTypeAgent && account.UserType != constants.UserTypeEnterprise { return errors.New(errors.CodeForbidden, "无权限操作此账号") } return s.db.WithContext(ctx).Model(&model.Account{}). Where("id = ?", id). Updates(map[string]interface{}{ "status": status, "updater": currentUserID, }).Error } func getUserTypeName(userType int) string { switch userType { case constants.UserTypeAgent: return "代理账号" case constants.UserTypeEnterprise: return "企业账号" default: return "未知" } } func getStatusName(status int) string { if status == constants.StatusEnabled { return "启用" } return "禁用" }