All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 8m15s
- FamilyMemberItem 新增 auth_type、device_type 字段 - FamilySummary 新增 owner_auth_type 字段 - findUserIdentifiers 返回 identifierInfo(含 auth_type) - 新增 parseDeviceType() 从 UserAgent 解析设备类型 Co-Authored-By: claude-flow <ruv@ruv.net>
151 lines
4.7 KiB
Go
151 lines
4.7 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"strings"
|
|
|
|
modelUser "github.com/perfect-panel/server/internal/model/user"
|
|
"github.com/perfect-panel/server/internal/svc"
|
|
"github.com/perfect-panel/server/internal/types"
|
|
"github.com/perfect-panel/server/pkg/logger"
|
|
"github.com/perfect-panel/server/pkg/xerr"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type GetFamilyListLogic struct {
|
|
ctx context.Context
|
|
svcCtx *svc.ServiceContext
|
|
logger.Logger
|
|
}
|
|
|
|
func NewGetFamilyListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFamilyListLogic {
|
|
return &GetFamilyListLogic{
|
|
ctx: ctx,
|
|
svcCtx: svcCtx,
|
|
Logger: logger.WithContext(ctx),
|
|
}
|
|
}
|
|
|
|
func (l *GetFamilyListLogic) GetFamilyList(req *types.GetFamilyListRequest) (*types.GetFamilyListResponse, error) {
|
|
page := req.Page
|
|
size := req.Size
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if size <= 0 {
|
|
size = 20
|
|
}
|
|
if size > 200 {
|
|
size = 200
|
|
}
|
|
|
|
query := l.svcCtx.DB.WithContext(l.ctx).
|
|
Model(&modelUser.UserFamily{}).
|
|
Where("user_family.deleted_at IS NULL")
|
|
|
|
if req.OwnerUserId != nil {
|
|
query = query.Where("user_family.owner_user_id = ?", *req.OwnerUserId)
|
|
}
|
|
if req.FamilyId != nil {
|
|
query = query.Where("user_family.id = ?", *req.FamilyId)
|
|
}
|
|
if req.UserId != nil {
|
|
query = query.Where(
|
|
"EXISTS (SELECT 1 FROM user_family_member ufm WHERE ufm.family_id = user_family.id AND ufm.deleted_at IS NULL AND ufm.status = ? AND ufm.user_id = ?)",
|
|
modelUser.FamilyMemberActive, *req.UserId,
|
|
)
|
|
}
|
|
if statusValue, ok := normalizeFamilyStatusInput(req.Status); ok {
|
|
query = query.Where("user_family.status = ?", statusValue)
|
|
}
|
|
|
|
keyword := strings.TrimSpace(req.Keyword)
|
|
if keyword != "" {
|
|
keywordLike := "%" + keyword + "%"
|
|
query = query.Where(
|
|
"(CAST(user_family.id AS CHAR) LIKE ? OR CAST(user_family.owner_user_id AS CHAR) LIKE ? OR "+
|
|
"EXISTS (SELECT 1 FROM user_auth_methods owner_auth WHERE owner_auth.user_id = user_family.owner_user_id AND owner_auth.deleted_at IS NULL AND owner_auth.auth_identifier LIKE ?) OR "+
|
|
"EXISTS (SELECT 1 FROM user_family_member keyword_member JOIN user_auth_methods keyword_auth ON keyword_auth.user_id = keyword_member.user_id AND keyword_auth.deleted_at IS NULL WHERE keyword_member.family_id = user_family.id AND keyword_member.deleted_at IS NULL AND keyword_auth.auth_identifier LIKE ?))",
|
|
keywordLike, keywordLike, keywordLike, keywordLike,
|
|
)
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "count family list failed")
|
|
}
|
|
|
|
var families []modelUser.UserFamily
|
|
if err := query.Order("user_family.id DESC").
|
|
Limit(size).
|
|
Offset((page - 1) * size).
|
|
Find(&families).Error; err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family list failed")
|
|
}
|
|
|
|
if len(families) == 0 {
|
|
return &types.GetFamilyListResponse{
|
|
Total: total,
|
|
List: []types.FamilySummary{},
|
|
}, nil
|
|
}
|
|
|
|
ownerIDs := make([]int64, 0, len(families))
|
|
familyIDs := make([]int64, 0, len(families))
|
|
for _, family := range families {
|
|
ownerIDs = append(ownerIDs, family.OwnerUserId)
|
|
familyIDs = append(familyIDs, family.Id)
|
|
}
|
|
|
|
identifierMap, identifierErr := findUserIdentifiers(l.ctx, l.svcCtx.DB, ownerIDs)
|
|
if identifierErr != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family owner identifiers failed")
|
|
}
|
|
|
|
type familyCount struct {
|
|
FamilyId int64
|
|
Count int64
|
|
}
|
|
var counts []familyCount
|
|
if err := l.svcCtx.DB.WithContext(l.ctx).
|
|
Table("user_family_member").
|
|
Select("family_id, COUNT(1) as count").
|
|
Where("family_id IN ? AND deleted_at IS NULL AND status = ?", familyIDs, modelUser.FamilyMemberActive).
|
|
Group("family_id").
|
|
Scan(&counts).Error; err != nil {
|
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family member counts failed")
|
|
}
|
|
countMap := make(map[int64]int64, len(counts))
|
|
for _, count := range counts {
|
|
countMap[count.FamilyId] = count.Count
|
|
}
|
|
|
|
list := make([]types.FamilySummary, 0, len(families))
|
|
for _, family := range families {
|
|
ownerInfo := identifierMap[family.OwnerUserId]
|
|
ownerIdentifier := ownerInfo.Identifier
|
|
ownerAuthType := ownerInfo.AuthType
|
|
if ownerIdentifier == "" {
|
|
ownerIdentifier = strconv.FormatInt(family.OwnerUserId, 10)
|
|
}
|
|
|
|
list = append(list, types.FamilySummary{
|
|
FamilyId: family.Id,
|
|
OwnerUserId: family.OwnerUserId,
|
|
OwnerIdentifier: ownerIdentifier,
|
|
OwnerAuthType: ownerAuthType,
|
|
Status: mapFamilyStatus(family.Status),
|
|
ActiveMemberCount: countMap[family.Id],
|
|
MaxMembers: family.MaxMembers,
|
|
CreatedAt: family.CreatedAt.Unix(),
|
|
UpdatedAt: family.UpdatedAt.Unix(),
|
|
})
|
|
}
|
|
|
|
return &types.GetFamilyListResponse{
|
|
Total: total,
|
|
List: list,
|
|
}, nil
|
|
}
|