feat: add superadmin user interaction views
This commit is contained in:
@@ -116,3 +116,38 @@ type SuperUserRealNameResponse struct {
|
||||
// IDCardMasked 身份证号脱敏展示。
|
||||
IDCardMasked string `json:"id_card_masked"`
|
||||
}
|
||||
|
||||
// SuperUserContentActionListFilter 超管用户互动内容列表过滤条件。
|
||||
type SuperUserContentActionListFilter struct {
|
||||
requests.Pagination
|
||||
// TenantID 内容所属租户ID,精确匹配。
|
||||
TenantID *int64 `query:"tenant_id"`
|
||||
// TenantCode 租户编码,模糊匹配。
|
||||
TenantCode *string `query:"tenant_code"`
|
||||
// TenantName 租户名称,模糊匹配。
|
||||
TenantName *string `query:"tenant_name"`
|
||||
// ContentID 内容ID,精确匹配。
|
||||
ContentID *int64 `query:"content_id"`
|
||||
// Keyword 内容标题/摘要/描述关键字,模糊匹配。
|
||||
Keyword *string `query:"keyword"`
|
||||
// CreatedAtFrom 互动时间起始(RFC3339)。
|
||||
CreatedAtFrom *string `query:"created_at_from"`
|
||||
// CreatedAtTo 互动时间结束(RFC3339)。
|
||||
CreatedAtTo *string `query:"created_at_to"`
|
||||
// Asc 升序字段(id/created_at)。
|
||||
Asc *string `query:"asc"`
|
||||
// Desc 降序字段(id/created_at)。
|
||||
Desc *string `query:"desc"`
|
||||
}
|
||||
|
||||
// SuperUserContentActionItem 超管用户互动内容条目。
|
||||
type SuperUserContentActionItem struct {
|
||||
// ActionID 互动记录ID。
|
||||
ActionID int64 `json:"action_id"`
|
||||
// ActionType 互动类型(like/favorite)。
|
||||
ActionType consts.UserContentActionType `json:"action_type"`
|
||||
// ActionAt 互动发生时间(RFC3339)。
|
||||
ActionAt string `json:"action_at"`
|
||||
// Content 互动对应内容详情(含租户与作者信息)。
|
||||
Content *AdminContentItem `json:"content"`
|
||||
}
|
||||
|
||||
@@ -316,6 +316,24 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
PathParam[int64]("id"),
|
||||
Query[dto.SuperUserCouponListFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/users/:id<int>/favorites -> users.ListFavorites")
|
||||
router.Get("/super/v1/users/:id<int>/favorites"[len(r.Path()):], DataFunc2(
|
||||
r.users.ListFavorites,
|
||||
PathParam[int64]("id"),
|
||||
Query[dto.SuperUserContentActionListFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/users/:id<int>/following -> users.ListFollowing")
|
||||
router.Get("/super/v1/users/:id<int>/following"[len(r.Path()):], DataFunc2(
|
||||
r.users.ListFollowing,
|
||||
PathParam[int64]("id"),
|
||||
Query[dto.SuperUserTenantListFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/users/:id<int>/likes -> users.ListLikes")
|
||||
router.Get("/super/v1/users/:id<int>/likes"[len(r.Path()):], DataFunc2(
|
||||
r.users.ListLikes,
|
||||
PathParam[int64]("id"),
|
||||
Query[dto.SuperUserContentActionListFilter]("filter"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /super/v1/users/:id<int>/notifications -> users.ListNotifications")
|
||||
router.Get("/super/v1/users/:id<int>/notifications"[len(r.Path()):], DataFunc2(
|
||||
r.users.ListNotifications,
|
||||
|
||||
@@ -127,6 +127,60 @@ func (c *users) ListTenants(ctx fiber.Ctx, id int64, filter *dto.SuperUserTenant
|
||||
return services.Super.ListUserTenants(ctx, id, filter)
|
||||
}
|
||||
|
||||
// List user favorites
|
||||
//
|
||||
// @Router /super/v1/users/:id<int>/favorites [get]
|
||||
// @Summary List user favorites
|
||||
// @Description List user's favorited contents
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "User ID"
|
||||
// @Param page query int false "Page number"
|
||||
// @Param limit query int false "Page size"
|
||||
// @Success 200 {object} requests.Pager{items=[]dto.SuperUserContentActionItem}
|
||||
// @Bind id path
|
||||
// @Bind filter query
|
||||
func (c *users) ListFavorites(ctx fiber.Ctx, id int64, filter *dto.SuperUserContentActionListFilter) (*requests.Pager, error) {
|
||||
return services.Super.ListUserFavorites(ctx, id, filter)
|
||||
}
|
||||
|
||||
// List user likes
|
||||
//
|
||||
// @Router /super/v1/users/:id<int>/likes [get]
|
||||
// @Summary List user likes
|
||||
// @Description List user's liked contents
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "User ID"
|
||||
// @Param page query int false "Page number"
|
||||
// @Param limit query int false "Page size"
|
||||
// @Success 200 {object} requests.Pager{items=[]dto.SuperUserContentActionItem}
|
||||
// @Bind id path
|
||||
// @Bind filter query
|
||||
func (c *users) ListLikes(ctx fiber.Ctx, id int64, filter *dto.SuperUserContentActionListFilter) (*requests.Pager, error) {
|
||||
return services.Super.ListUserLikes(ctx, id, filter)
|
||||
}
|
||||
|
||||
// List user following tenants
|
||||
//
|
||||
// @Router /super/v1/users/:id<int>/following [get]
|
||||
// @Summary List user following tenants
|
||||
// @Description List tenants followed by user
|
||||
// @Tags User
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "User ID"
|
||||
// @Param page query int false "Page number"
|
||||
// @Param limit query int false "Page size"
|
||||
// @Success 200 {object} requests.Pager{items=[]dto.UserTenantItem}
|
||||
// @Bind id path
|
||||
// @Bind filter query
|
||||
func (c *users) ListFollowing(ctx fiber.Ctx, id int64, filter *dto.SuperUserTenantListFilter) (*requests.Pager, error) {
|
||||
return services.Super.ListUserFollowing(ctx, id, filter)
|
||||
}
|
||||
|
||||
// Update user status
|
||||
//
|
||||
// @Router /super/v1/users/:id<int>/status [patch]
|
||||
|
||||
@@ -1704,6 +1704,176 @@ func (s *super) ListUserTenants(ctx context.Context, userID int64, filter *super
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *super) ListUserFavorites(ctx context.Context, userID int64, filter *super_dto.SuperUserContentActionListFilter) (*requests.Pager, error) {
|
||||
return s.listUserContentActions(ctx, userID, consts.UserContentActionTypeFavorite, filter)
|
||||
}
|
||||
|
||||
func (s *super) ListUserLikes(ctx context.Context, userID int64, filter *super_dto.SuperUserContentActionListFilter) (*requests.Pager, error) {
|
||||
return s.listUserContentActions(ctx, userID, consts.UserContentActionTypeLike, filter)
|
||||
}
|
||||
|
||||
func (s *super) ListUserFollowing(ctx context.Context, userID int64, filter *super_dto.SuperUserTenantListFilter) (*requests.Pager, error) {
|
||||
if filter == nil {
|
||||
filter = &super_dto.SuperUserTenantListFilter{}
|
||||
}
|
||||
// 关注列表默认只展示普通成员关注关系。
|
||||
role := consts.TenantUserRoleMember
|
||||
filter.Role = &role
|
||||
return s.ListUserTenants(ctx, userID, filter)
|
||||
}
|
||||
|
||||
func (s *super) listUserContentActions(
|
||||
ctx context.Context,
|
||||
userID int64,
|
||||
actionType consts.UserContentActionType,
|
||||
filter *super_dto.SuperUserContentActionListFilter,
|
||||
) (*requests.Pager, error) {
|
||||
if userID == 0 {
|
||||
return nil, errorx.ErrBadRequest.WithMsg("用户ID不能为空")
|
||||
}
|
||||
if filter == nil {
|
||||
filter = &super_dto.SuperUserContentActionListFilter{}
|
||||
}
|
||||
|
||||
tbl, q := models.UserContentActionQuery.QueryContext(ctx)
|
||||
q = q.Where(tbl.UserID.Eq(userID), tbl.Type.Eq(string(actionType)))
|
||||
|
||||
contentIDs, contentFilter, err := s.filterContentIDsForUserActions(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if contentFilter {
|
||||
if len(contentIDs) == 0 {
|
||||
filter.Pagination.Format()
|
||||
return &requests.Pager{
|
||||
Pagination: filter.Pagination,
|
||||
Total: 0,
|
||||
Items: []super_dto.SuperUserContentActionItem{},
|
||||
}, nil
|
||||
}
|
||||
q = q.Where(tbl.ContentID.In(contentIDs...))
|
||||
}
|
||||
|
||||
if filter.CreatedAtFrom != nil {
|
||||
from, err := s.parseFilterTime(filter.CreatedAtFrom)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if from != nil {
|
||||
q = q.Where(tbl.CreatedAt.Gte(*from))
|
||||
}
|
||||
}
|
||||
if filter.CreatedAtTo != nil {
|
||||
to, err := s.parseFilterTime(filter.CreatedAtTo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if to != nil {
|
||||
q = q.Where(tbl.CreatedAt.Lte(*to))
|
||||
}
|
||||
}
|
||||
|
||||
orderApplied := false
|
||||
if filter.Desc != nil && strings.TrimSpace(*filter.Desc) != "" {
|
||||
switch strings.TrimSpace(*filter.Desc) {
|
||||
case "id":
|
||||
q = q.Order(tbl.ID.Desc())
|
||||
case "created_at":
|
||||
q = q.Order(tbl.CreatedAt.Desc())
|
||||
}
|
||||
orderApplied = true
|
||||
} else if filter.Asc != nil && strings.TrimSpace(*filter.Asc) != "" {
|
||||
switch strings.TrimSpace(*filter.Asc) {
|
||||
case "id":
|
||||
q = q.Order(tbl.ID)
|
||||
case "created_at":
|
||||
q = q.Order(tbl.CreatedAt)
|
||||
}
|
||||
orderApplied = true
|
||||
}
|
||||
if !orderApplied {
|
||||
q = q.Order(tbl.CreatedAt.Desc())
|
||||
}
|
||||
|
||||
filter.Pagination.Format()
|
||||
total, err := q.Count()
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
list, err := q.Offset(int(filter.Pagination.Offset())).Limit(int(filter.Pagination.Limit)).Find()
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return &requests.Pager{
|
||||
Pagination: filter.Pagination,
|
||||
Total: total,
|
||||
Items: []super_dto.SuperUserContentActionItem{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
contentIDSet := make(map[int64]struct{}, len(list))
|
||||
contentIDs = make([]int64, 0, len(list))
|
||||
for _, action := range list {
|
||||
if action.ContentID == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := contentIDSet[action.ContentID]; ok {
|
||||
continue
|
||||
}
|
||||
contentIDSet[action.ContentID] = struct{}{}
|
||||
contentIDs = append(contentIDs, action.ContentID)
|
||||
}
|
||||
|
||||
var contents []*models.Content
|
||||
if len(contentIDs) > 0 {
|
||||
contentTbl, contentQuery := models.ContentQuery.QueryContext(ctx)
|
||||
err := contentQuery.Where(contentTbl.ID.In(contentIDs...)).
|
||||
UnderlyingDB().
|
||||
Preload("Author").
|
||||
Preload("ContentAssets.Asset").
|
||||
Find(&contents).Error
|
||||
if err != nil {
|
||||
return nil, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
}
|
||||
|
||||
priceMap, err := s.contentPriceMap(ctx, contents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tenantMap, err := s.contentTenantMap(ctx, contents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contentMap := make(map[int64]*models.Content, len(contents))
|
||||
for _, content := range contents {
|
||||
contentMap[content.ID] = content
|
||||
}
|
||||
|
||||
items := make([]super_dto.SuperUserContentActionItem, 0, len(list))
|
||||
for _, action := range list {
|
||||
var contentItem *super_dto.AdminContentItem
|
||||
if content := contentMap[action.ContentID]; content != nil {
|
||||
item := s.toSuperContentItem(content, priceMap[content.ID], tenantMap[content.TenantID])
|
||||
contentItem = &item
|
||||
}
|
||||
items = append(items, super_dto.SuperUserContentActionItem{
|
||||
ActionID: action.ID,
|
||||
ActionType: actionType,
|
||||
ActionAt: s.formatTime(action.CreatedAt),
|
||||
Content: contentItem,
|
||||
})
|
||||
}
|
||||
|
||||
return &requests.Pager{
|
||||
Pagination: filter.Pagination,
|
||||
Total: total,
|
||||
Items: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *super) ListContents(ctx context.Context, filter *super_dto.SuperContentListFilter) (*requests.Pager, error) {
|
||||
tbl, q := models.ContentQuery.QueryContext(ctx)
|
||||
|
||||
@@ -3444,6 +3614,59 @@ func (s *super) lookupUserIDs(ctx context.Context, username *string) ([]int64, b
|
||||
return ids, true, nil
|
||||
}
|
||||
|
||||
func (s *super) filterContentIDsForUserActions(
|
||||
ctx context.Context,
|
||||
filter *super_dto.SuperUserContentActionListFilter,
|
||||
) ([]int64, bool, error) {
|
||||
if filter == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
tbl, q := models.ContentQuery.QueryContext(ctx)
|
||||
filterApplied := false
|
||||
|
||||
if filter.ContentID != nil && *filter.ContentID > 0 {
|
||||
q = q.Where(tbl.ID.Eq(*filter.ContentID))
|
||||
filterApplied = true
|
||||
}
|
||||
if filter.TenantID != nil && *filter.TenantID > 0 {
|
||||
q = q.Where(tbl.TenantID.Eq(*filter.TenantID))
|
||||
filterApplied = true
|
||||
}
|
||||
|
||||
tenantIDs, tenantFilter, err := s.lookupTenantIDs(ctx, filter.TenantCode, filter.TenantName)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if tenantFilter {
|
||||
filterApplied = true
|
||||
if len(tenantIDs) == 0 {
|
||||
return []int64{}, true, nil
|
||||
}
|
||||
q = q.Where(tbl.TenantID.In(tenantIDs...))
|
||||
}
|
||||
|
||||
if filter.Keyword != nil && strings.TrimSpace(*filter.Keyword) != "" {
|
||||
keyword := "%" + strings.TrimSpace(*filter.Keyword) + "%"
|
||||
q = q.Where(field.Or(
|
||||
tbl.Title.Like(keyword),
|
||||
tbl.Description.Like(keyword),
|
||||
tbl.Summary.Like(keyword),
|
||||
))
|
||||
filterApplied = true
|
||||
}
|
||||
|
||||
if !filterApplied {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
ids, err := q.PluckIDs()
|
||||
if err != nil {
|
||||
return nil, true, errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
return ids, true, nil
|
||||
}
|
||||
|
||||
func (s *super) lookupOrderIDsByContent(ctx context.Context, contentID *int64, contentTitle *string) ([]int64, bool, error) {
|
||||
var id int64
|
||||
if contentID != nil {
|
||||
|
||||
@@ -2059,6 +2059,186 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/favorites": {
|
||||
"get": {
|
||||
"description": "List user's favorited contents",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List user favorites",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/requests.Pager"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.SuperUserContentActionItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/following": {
|
||||
"get": {
|
||||
"description": "List tenants followed by user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List user following tenants",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/requests.Pager"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.UserTenantItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/likes": {
|
||||
"get": {
|
||||
"description": "List user's liked contents",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List user likes",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/requests.Pager"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.SuperUserContentActionItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/notifications": {
|
||||
"get": {
|
||||
"description": "List notifications of a user",
|
||||
@@ -5371,6 +5551,17 @@ const docTemplate = `{
|
||||
"TenantUserRoleTenantAdmin"
|
||||
]
|
||||
},
|
||||
"consts.UserContentActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"like",
|
||||
"favorite"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"UserContentActionTypeLike",
|
||||
"UserContentActionTypeFavorite"
|
||||
]
|
||||
},
|
||||
"consts.UserCouponStatus": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -7605,6 +7796,35 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.SuperUserContentActionItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action_at": {
|
||||
"description": "ActionAt 互动发生时间(RFC3339)。",
|
||||
"type": "string"
|
||||
},
|
||||
"action_id": {
|
||||
"description": "ActionID 互动记录ID。",
|
||||
"type": "integer"
|
||||
},
|
||||
"action_type": {
|
||||
"description": "ActionType 互动类型(like/favorite)。",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/consts.UserContentActionType"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"description": "Content 互动对应内容详情(含租户与作者信息)。",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/dto.AdminContentItem"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.SuperUserCouponItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -2053,6 +2053,186 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/favorites": {
|
||||
"get": {
|
||||
"description": "List user's favorited contents",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List user favorites",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/requests.Pager"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.SuperUserContentActionItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/following": {
|
||||
"get": {
|
||||
"description": "List tenants followed by user",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List user following tenants",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/requests.Pager"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.UserTenantItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/likes": {
|
||||
"get": {
|
||||
"description": "List user's liked contents",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User"
|
||||
],
|
||||
"summary": "List user likes",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "User ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page size",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/requests.Pager"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.SuperUserContentActionItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/super/v1/users/{id}/notifications": {
|
||||
"get": {
|
||||
"description": "List notifications of a user",
|
||||
@@ -5365,6 +5545,17 @@
|
||||
"TenantUserRoleTenantAdmin"
|
||||
]
|
||||
},
|
||||
"consts.UserContentActionType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"like",
|
||||
"favorite"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"UserContentActionTypeLike",
|
||||
"UserContentActionTypeFavorite"
|
||||
]
|
||||
},
|
||||
"consts.UserCouponStatus": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
@@ -7599,6 +7790,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.SuperUserContentActionItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action_at": {
|
||||
"description": "ActionAt 互动发生时间(RFC3339)。",
|
||||
"type": "string"
|
||||
},
|
||||
"action_id": {
|
||||
"description": "ActionID 互动记录ID。",
|
||||
"type": "integer"
|
||||
},
|
||||
"action_type": {
|
||||
"description": "ActionType 互动类型(like/favorite)。",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/consts.UserContentActionType"
|
||||
}
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"description": "Content 互动对应内容详情(含租户与作者信息)。",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/dto.AdminContentItem"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.SuperUserCouponItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -136,6 +136,14 @@ definitions:
|
||||
x-enum-varnames:
|
||||
- TenantUserRoleMember
|
||||
- TenantUserRoleTenantAdmin
|
||||
consts.UserContentActionType:
|
||||
enum:
|
||||
- like
|
||||
- favorite
|
||||
type: string
|
||||
x-enum-varnames:
|
||||
- UserContentActionTypeLike
|
||||
- UserContentActionTypeFavorite
|
||||
consts.UserCouponStatus:
|
||||
enum:
|
||||
- unused
|
||||
@@ -1691,6 +1699,23 @@ definitions:
|
||||
- $ref: '#/definitions/dto.SuperUserLite'
|
||||
description: User 用户信息。
|
||||
type: object
|
||||
dto.SuperUserContentActionItem:
|
||||
properties:
|
||||
action_at:
|
||||
description: ActionAt 互动发生时间(RFC3339)。
|
||||
type: string
|
||||
action_id:
|
||||
description: ActionID 互动记录ID。
|
||||
type: integer
|
||||
action_type:
|
||||
allOf:
|
||||
- $ref: '#/definitions/consts.UserContentActionType'
|
||||
description: ActionType 互动类型(like/favorite)。
|
||||
content:
|
||||
allOf:
|
||||
- $ref: '#/definitions/dto.AdminContentItem'
|
||||
description: Content 互动对应内容详情(含租户与作者信息)。
|
||||
type: object
|
||||
dto.SuperUserCouponItem:
|
||||
properties:
|
||||
coupon_id:
|
||||
@@ -3916,6 +3941,117 @@ paths:
|
||||
summary: List user coupons
|
||||
tags:
|
||||
- User
|
||||
/super/v1/users/{id}/favorites:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: List user's favorited contents
|
||||
parameters:
|
||||
- description: User ID
|
||||
format: int64
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: Page number
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: Page size
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/requests.Pager'
|
||||
- properties:
|
||||
items:
|
||||
items:
|
||||
$ref: '#/definitions/dto.SuperUserContentActionItem'
|
||||
type: array
|
||||
type: object
|
||||
summary: List user favorites
|
||||
tags:
|
||||
- User
|
||||
/super/v1/users/{id}/following:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: List tenants followed by user
|
||||
parameters:
|
||||
- description: User ID
|
||||
format: int64
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: Page number
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: Page size
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/requests.Pager'
|
||||
- properties:
|
||||
items:
|
||||
items:
|
||||
$ref: '#/definitions/dto.UserTenantItem'
|
||||
type: array
|
||||
type: object
|
||||
summary: List user following tenants
|
||||
tags:
|
||||
- User
|
||||
/super/v1/users/{id}/likes:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: List user's liked contents
|
||||
parameters:
|
||||
- description: User ID
|
||||
format: int64
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: integer
|
||||
- description: Page number
|
||||
in: query
|
||||
name: page
|
||||
type: integer
|
||||
- description: Page size
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/requests.Pager'
|
||||
- properties:
|
||||
items:
|
||||
items:
|
||||
$ref: '#/definitions/dto.SuperUserContentActionItem'
|
||||
type: array
|
||||
type: object
|
||||
summary: List user likes
|
||||
tags:
|
||||
- User
|
||||
/super/v1/users/{id}/notifications:
|
||||
get:
|
||||
consumes:
|
||||
|
||||
Reference in New Issue
Block a user