feat: add creator member management

This commit is contained in:
2026-01-17 20:42:43 +08:00
parent 984a404b5f
commit 7fca7a40e7
14 changed files with 2915 additions and 81 deletions

View File

@@ -70,6 +70,91 @@ func (c *Creator) CreateMemberInvite(
return services.Tenant.CreateInvite(ctx, tenantID, user.ID, form)
}
// List tenant members
//
// @Router /t/:tenantCode/v1/creator/members [get]
// @Summary List tenant members
// @Description List tenant members with filters
// @Tags CreatorCenter
// @Accept json
// @Produce json
// @Param filter query dto.TenantMemberListFilter false "Member list filter"
// @Success 200 {object} requests.Pager{items=[]dto.TenantMemberItem}
// @Bind user local key(__ctx_user)
// @Bind filter query
func (c *Creator) ListMembers(ctx fiber.Ctx, user *models.User, filter *dto.TenantMemberListFilter) (*requests.Pager, error) {
tenantID := getTenantID(ctx)
return services.Tenant.ListMembers(ctx, tenantID, user.ID, filter)
}
// List member invites
//
// @Router /t/:tenantCode/v1/creator/members/invites [get]
// @Summary List member invites
// @Description List member invites with filters
// @Tags CreatorCenter
// @Accept json
// @Produce json
// @Param filter query dto.TenantInviteListFilter false "Invite list filter"
// @Success 200 {object} requests.Pager{items=[]dto.TenantInviteListItem}
// @Bind user local key(__ctx_user)
// @Bind filter query
func (c *Creator) ListMemberInvites(ctx fiber.Ctx, user *models.User, filter *dto.TenantInviteListFilter) (*requests.Pager, error) {
tenantID := getTenantID(ctx)
return services.Tenant.ListInvites(ctx, tenantID, user.ID, filter)
}
// Disable member invite
//
// @Router /t/:tenantCode/v1/creator/members/invites/:id<int> [delete]
// @Summary Disable member invite
// @Description Disable a member invite by ID
// @Tags CreatorCenter
// @Accept json
// @Produce json
// @Param id path int64 true "Invite ID"
// @Success 200 {string} string "Disabled"
// @Bind user local key(__ctx_user)
// @Bind id path
func (c *Creator) DisableMemberInvite(ctx fiber.Ctx, user *models.User, id int64) error {
tenantID := getTenantID(ctx)
return services.Tenant.DisableInvite(ctx, tenantID, user.ID, id)
}
// List member join requests
//
// @Router /t/:tenantCode/v1/creator/members/join-requests [get]
// @Summary List member join requests
// @Description List tenant join requests
// @Tags CreatorCenter
// @Accept json
// @Produce json
// @Param filter query dto.TenantJoinRequestListFilter false "Join request list filter"
// @Success 200 {object} requests.Pager{items=[]dto.TenantJoinRequestItem}
// @Bind user local key(__ctx_user)
// @Bind filter query
func (c *Creator) ListMemberJoinRequests(ctx fiber.Ctx, user *models.User, filter *dto.TenantJoinRequestListFilter) (*requests.Pager, error) {
tenantID := getTenantID(ctx)
return services.Tenant.ListJoinRequests(ctx, tenantID, user.ID, filter)
}
// Remove tenant member
//
// @Router /t/:tenantCode/v1/creator/members/:id<int> [delete]
// @Summary Remove tenant member
// @Description Remove a tenant member by relation ID
// @Tags CreatorCenter
// @Accept json
// @Produce json
// @Param id path int64 true "Member ID"
// @Success 200 {string} string "Removed"
// @Bind user local key(__ctx_user)
// @Bind id path
func (c *Creator) RemoveMember(ctx fiber.Ctx, user *models.User, id int64) error {
tenantID := getTenantID(ctx)
return services.Tenant.RemoveMember(ctx, tenantID, user.ID, id)
}
// Get report overview
//
// @Router /t/:tenantCode/v1/creator/reports/overview [get]

View File

@@ -1,5 +1,10 @@
package dto
import (
"quyun/v2/app/requests"
"quyun/v2/pkg/consts"
)
type TenantJoinApplyForm struct {
// Reason 申请加入原因(可选,空值会使用默认文案)。
Reason string `json:"reason"`
@@ -44,3 +49,110 @@ type TenantInviteItem struct {
// Remark 备注说明。
Remark string `json:"remark"`
}
type TenantMemberListFilter struct {
// Pagination 分页参数page/limit
requests.Pagination
// Keyword 关键词搜索(匹配用户名/昵称/手机号)。
Keyword *string `query:"keyword"`
// Role 成员角色筛选member/tenant_admin
Role *consts.TenantUserRole `query:"role"`
// Status 成员状态筛选active/verified/banned 等)。
Status *consts.UserStatus `query:"status"`
}
type TenantMemberUserLite struct {
// ID 用户ID。
ID int64 `json:"id"`
// Username 用户名。
Username string `json:"username"`
// Phone 手机号。
Phone string `json:"phone"`
// Nickname 昵称。
Nickname string `json:"nickname"`
// Avatar 头像URL。
Avatar string `json:"avatar"`
}
type TenantMemberItem struct {
// ID 成员关系记录ID。
ID int64 `json:"id"`
// TenantID 租户ID。
TenantID int64 `json:"tenant_id"`
// User 成员用户信息。
User *TenantMemberUserLite `json:"user"`
// Role 成员角色列表。
Role []consts.TenantUserRole `json:"role"`
// RoleDescription 角色描述列表。
RoleDescription []string `json:"role_description"`
// Status 成员状态。
Status consts.UserStatus `json:"status"`
// StatusDescription 成员状态描述。
StatusDescription string `json:"status_description"`
// CreatedAt 加入时间RFC3339
CreatedAt string `json:"created_at"`
// UpdatedAt 更新时间RFC3339
UpdatedAt string `json:"updated_at"`
}
type TenantInviteListFilter struct {
// Pagination 分页参数page/limit
requests.Pagination
// Status 邀请状态筛选active/disabled/expired
Status *consts.TenantInviteStatus `query:"status"`
}
type TenantInviteListItem struct {
// ID 邀请记录ID。
ID int64 `json:"id"`
// Code 邀请码。
Code string `json:"code"`
// Status 邀请状态active/disabled/expired
Status string `json:"status"`
// StatusDescription 状态描述。
StatusDescription string `json:"status_description"`
// MaxUses 最大可使用次数。
MaxUses int32 `json:"max_uses"`
// UsedCount 已使用次数。
UsedCount int32 `json:"used_count"`
// ExpiresAt 过期时间RFC3339空字符串表示不限制
ExpiresAt string `json:"expires_at"`
// CreatedAt 创建时间RFC3339
CreatedAt string `json:"created_at"`
// Remark 备注说明。
Remark string `json:"remark"`
// Creator 创建者信息(可选)。
Creator *TenantMemberUserLite `json:"creator"`
}
type TenantJoinRequestListFilter struct {
// Pagination 分页参数page/limit
requests.Pagination
// Status 申请状态筛选pending/approved/rejected
Status *consts.TenantJoinRequestStatus `query:"status"`
// Keyword 关键词搜索(匹配用户名/昵称/手机号)。
Keyword *string `query:"keyword"`
}
type TenantJoinRequestItem struct {
// ID 申请记录ID。
ID int64 `json:"id"`
// User 申请用户信息。
User *TenantMemberUserLite `json:"user"`
// Status 申请状态。
Status string `json:"status"`
// StatusDescription 状态描述。
StatusDescription string `json:"status_description"`
// Reason 申请说明。
Reason string `json:"reason"`
// DecidedAt 审核时间RFC3339
DecidedAt string `json:"decided_at"`
// DecidedOperatorUserID 审核操作者ID。
DecidedOperatorUserID int64 `json:"decided_operator_user_id"`
// DecidedReason 审核备注/原因。
DecidedReason string `json:"decided_reason"`
// CreatedAt 申请时间RFC3339
CreatedAt string `json:"created_at"`
// UpdatedAt 更新时间RFC3339
UpdatedAt string `json:"updated_at"`
}

View File

@@ -157,6 +157,18 @@ func (r *Routes) Register(router fiber.Router) {
Local[*models.User]("__ctx_user"),
PathParam[int64]("id"),
))
r.log.Debugf("Registering route: Delete /t/:tenantCode/v1/creator/members/:id<int> -> creator.RemoveMember")
router.Delete("/t/:tenantCode/v1/creator/members/:id<int>"[len(r.Path()):], Func2(
r.creator.RemoveMember,
Local[*models.User]("__ctx_user"),
PathParam[int64]("id"),
))
r.log.Debugf("Registering route: Delete /t/:tenantCode/v1/creator/members/invites/:id<int> -> creator.DisableMemberInvite")
router.Delete("/t/:tenantCode/v1/creator/members/invites/:id<int>"[len(r.Path()):], Func2(
r.creator.DisableMemberInvite,
Local[*models.User]("__ctx_user"),
PathParam[int64]("id"),
))
r.log.Debugf("Registering route: Delete /t/:tenantCode/v1/creator/payout-accounts -> creator.RemovePayoutAccount")
router.Delete("/t/:tenantCode/v1/creator/payout-accounts"[len(r.Path()):], Func2(
r.creator.RemovePayoutAccount,
@@ -192,6 +204,24 @@ func (r *Routes) Register(router fiber.Router) {
r.creator.Dashboard,
Local[*models.User]("__ctx_user"),
))
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/members -> creator.ListMembers")
router.Get("/t/:tenantCode/v1/creator/members"[len(r.Path()):], DataFunc2(
r.creator.ListMembers,
Local[*models.User]("__ctx_user"),
Query[dto.TenantMemberListFilter]("filter"),
))
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/members/invites -> creator.ListMemberInvites")
router.Get("/t/:tenantCode/v1/creator/members/invites"[len(r.Path()):], DataFunc2(
r.creator.ListMemberInvites,
Local[*models.User]("__ctx_user"),
Query[dto.TenantInviteListFilter]("filter"),
))
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/members/join-requests -> creator.ListMemberJoinRequests")
router.Get("/t/:tenantCode/v1/creator/members/join-requests"[len(r.Path()):], DataFunc2(
r.creator.ListMemberJoinRequests,
Local[*models.User]("__ctx_user"),
Query[dto.TenantJoinRequestListFilter]("filter"),
))
r.log.Debugf("Registering route: Get /t/:tenantCode/v1/creator/orders -> creator.ListOrders")
router.Get("/t/:tenantCode/v1/creator/orders"[len(r.Path()):], DataFunc2(
r.creator.ListOrders,