feat: support merchant team roles and permissions

This commit is contained in:
yml2213
2026-08-13 11:41:34 +08:00
parent 6c98fa557e
commit a4791decb0
21 changed files with 969 additions and 201 deletions
+51 -1
View File
@@ -45,6 +45,27 @@ func (s *TenantService) ResolveMember(userID uint, merchantRef string) (*model.M
return nil, err
}
// ResolveMerchantForAdmin 允许平台管理员显式进入任一启用商户的后台管理上下文。
func (s *TenantService) ResolveMerchantForAdmin(merchantRef string) (*model.Merchant, error) {
if strings.TrimSpace(merchantRef) == "" {
return nil, errors.New("请选择商户")
}
tx := s.db.Where("status = ?", model.MerchantStatusActive)
if id, err := strconv.ParseUint(merchantRef, 10, 64); err == nil {
tx = tx.Where("id = ?", uint(id))
} else {
tx = tx.Where("code = ?", merchantRef)
}
var merchant model.Merchant
if err := tx.First(&merchant).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("商户不存在或已禁用")
}
return nil, err
}
return &merchant, nil
}
func (s *TenantService) EnsureSelfMember(userID uint, role string, status int) error {
var merchant model.Merchant
if err := s.db.Where("code = ?", model.MerchantCodeSelfOperated).First(&merchant).Error; err != nil {
@@ -79,13 +100,42 @@ func (s *TenantService) EnsureMember(merchantID, userID uint, role string, statu
func isValidMemberRole(role string) bool {
switch role {
case model.MemberRoleOwner, model.MemberRoleOperator, model.MemberRoleFinance, model.MemberRoleViewer:
case model.MemberRoleOwner, model.MemberRoleViewer:
return true
default:
return false
}
}
// MerchantRolePermissions 返回保留角色或商户自定义角色的权限集合。
// 负责人始终拥有该商户的全部后台权限,避免被自定义角色配置锁死。
func (s *TenantService) MerchantRolePermissions(merchantID uint, role string) (map[string]struct{}, error) {
permissions := builtinMerchantRolePermissions(role)
if permissions != nil {
return permissions, nil
}
var merchantRole model.MerchantRole
if err := s.db.Where("merchant_id = ? AND code = ? AND status = ?", merchantID, role, 1).First(&merchantRole).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("商户角色不存在或已禁用")
}
return nil, err
}
return ParseScopes(merchantRole.Permissions), nil
}
func builtinMerchantRolePermissions(role string) map[string]struct{} {
all := func(values ...string) map[string]struct{} { return ParseScopes(strings.Join(values, ",")) }
switch role {
case model.MemberRoleOwner:
return all(model.PermissionMembersManage, model.PermissionProductsManage, model.PermissionOrdersManage, model.PermissionWalletView, model.PermissionWalletLedger, model.PermissionRechargeManage, model.PermissionAPIManage, model.PermissionCallbacksManage)
case model.MemberRoleViewer:
return map[string]struct{}{}
default:
return nil
}
}
func MemberCanManage(memberRole string) bool {
return memberRole == model.MemberRoleOwner || memberRole == model.MemberRoleOperator
}