topfans/frontend/RANKING_API_SPECIFICATION.md
2026-04-07 23:08:49 +08:00

13 KiB
Raw Blame History

排行榜系统后端API数据格式规范

概述

本文档定义了排行榜系统的后端API接口规范包括请求参数、响应格式和数据模型。


1. 获取排行榜数据

接口信息

  • 接口路径: /api/ranking/list
  • 请求方法: GET
  • 接口描述: 获取指定类型和时间段的排行榜数据

请求参数

参数名 类型 必填 说明 示例值
rankingType string 榜单类型 popularity / custom / activity
timePeriod string 时间段 online / monthly / history
page number 页码默认1 1
pageSize number 每页数量默认20 20

榜单类型枚举

{
  "popularity": "热度榜",
  "custom": "自制榜",
  "activity": "活动榜"
}

时间段枚举

{
  "online": "在线",
  "monthly": "本月",
  "history": "历史"
}

响应格式

{
  "code": 200,
  "message": "success",
  "data": {
    "rankingType": "popularity",
    "timePeriod": "online",
    "hasArtwork": true,
    "total": 100,
    "page": 1,
    "pageSize": 20,
    "list": [
      {
        "rank": 1,
        "userId": "user001",
        "avatar": "https://example.com/avatar/1.jpeg",
        "nickname": "星光璀璨",
        "popularityScore": 73654,
        "artworkImage": "https://example.com/artwork/001.png",
        "artworkId": "artwork001"
      }
    ]
  }
}

2. 获取当前用户排名信息

接口信息

  • 接口路径: /api/ranking/current-user
  • 请求方法: GET
  • 接口描述: 获取当前登录用户在指定榜单中的排名信息

请求参数

参数名 类型 必填 说明 示例值
rankingType string 榜单类型 popularity
timePeriod string 时间段 online

响应格式

已上榜状态:

{
  "code": 200,
  "message": "success",
  "data": {
    "userId": "currentUser",
    "avatar": "https://example.com/avatar/7.jpeg",
    "nickname": "我",
    "popularityScore": 45000,
    "rank": 5,
    "artworkImage": "https://example.com/artwork/current.png",
    "artworkId": "currentUserArtwork",
    "isRanked": true
  }
}

未上榜状态:

{
  "code": 200,
  "message": "success",
  "data": {
    "userId": "currentUser",
    "avatar": "https://example.com/avatar/7.jpeg",
    "nickname": "我",
    "popularityScore": 371,
    "rank": null,
    "artworkImage": "https://example.com/artwork/current.png",
    "artworkId": "currentUserArtwork",
    "isRanked": false
  }
}

3. 数据模型定义

RankingUser (排行榜用户对象)

字段名 类型 必填 说明 备注
rank number 排名 从1开始
userId string 用户ID 唯一标识
avatar string 头像URL 完整URL地址
nickname string 用户昵称 最大长度20字符
popularityScore number 人气值/积分 非负整数
artworkImage string 作品图片URL 热度榜和自制榜必填
artworkId string 作品ID 热度榜和自制榜必填

TypeScript 类型定义:

interface RankingUser {
  rank: number;
  userId: string;
  avatar: string;
  nickname: string;
  popularityScore: number;
  artworkImage?: string;  // 活动榜不需要
  artworkId?: string;     // 活动榜不需要
}

CurrentUserRanking (当前用户排名对象)

字段名 类型 必填 说明
userId string 用户ID
avatar string 头像URL
nickname string 用户昵称
popularityScore number 人气值/积分
rank number | null 排名null表示未上榜
artworkImage string 作品图片URL
artworkId string 作品ID
isRanked boolean 是否已上榜

TypeScript 类型定义:

interface CurrentUserRanking {
  userId: string;
  avatar: string;
  nickname: string;
  popularityScore: number;
  rank: number | null;
  artworkImage?: string;
  artworkId?: string;
  isRanked: boolean;
}

4. 榜单特性配置

榜单类型特性

榜单类型 类型代码 是否包含作品 说明
热度榜 popularity 包含 artworkImage 和 artworkId
自制榜 custom 包含 artworkImage 和 artworkId
活动榜 activity 不包含作品相关字段

后端返回字段规则

// 热度榜和自制榜
{
  "hasArtwork": true,
  "list": [
    {
      "rank": 1,
      "userId": "user001",
      "avatar": "...",
      "nickname": "...",
      "popularityScore": 73654,
      "artworkImage": "...",  // 必须返回
      "artworkId": "..."      // 必须返回
    }
  ]
}

// 活动榜
{
  "hasArtwork": false,
  "list": [
    {
      "rank": 1,
      "userId": "user201",
      "avatar": "...",
      "nickname": "...",
      "popularityScore": 58321
      // 不包含 artworkImage 和 artworkId
    }
  ]
}

5. 错误响应格式

通用错误响应

{
  "code": 400,
  "message": "参数错误rankingType 必须为 popularity、custom 或 activity",
  "data": null
}

错误码定义

错误码 说明 示例消息
400 请求参数错误 "参数错误rankingType 不能为空"
401 未登录或token失效 "请先登录"
404 资源不存在 "榜单数据不存在"
500 服务器内部错误 "服务器错误,请稍后重试"

6. 请求示例

示例1: 获取热度榜在线排行

请求:

GET /api/ranking/list?rankingType=popularity&timePeriod=online&page=1&pageSize=20
Authorization: Bearer {token}

响应:

{
  "code": 200,
  "message": "success",
  "data": {
    "rankingType": "popularity",
    "timePeriod": "online",
    "hasArtwork": true,
    "total": 14,
    "page": 1,
    "pageSize": 20,
    "list": [
      {
        "rank": 1,
        "userId": "user001",
        "avatar": "https://cdn.example.com/avatar/1.jpeg",
        "nickname": "星光璀璨",
        "popularityScore": 73654,
        "artworkImage": "https://cdn.example.com/artwork/001.png",
        "artworkId": "artwork001"
      },
      {
        "rank": 2,
        "userId": "user002",
        "avatar": "https://cdn.example.com/avatar/2.jpeg",
        "nickname": "梦想追逐者",
        "popularityScore": 68921,
        "artworkImage": "https://cdn.example.com/artwork/002.jpeg",
        "artworkId": "artwork002"
      }
    ]
  }
}

示例2: 获取活动榜本月排行

请求:

GET /api/ranking/list?rankingType=activity&timePeriod=monthly&page=1&pageSize=20
Authorization: Bearer {token}

响应:

{
  "code": 200,
  "message": "success",
  "data": {
    "rankingType": "activity",
    "timePeriod": "monthly",
    "hasArtwork": false,
    "total": 3,
    "page": 1,
    "pageSize": 20,
    "list": [
      {
        "rank": 1,
        "userId": "user203",
        "avatar": "https://cdn.example.com/avatar/5.jpeg",
        "nickname": "活跃用户",
        "popularityScore": 87654
      },
      {
        "rank": 2,
        "userId": "user201",
        "avatar": "https://cdn.example.com/avatar/3.jpeg",
        "nickname": "活动之星",
        "popularityScore": 76543
      }
    ]
  }
}

示例3: 获取当前用户排名

请求:

GET /api/ranking/current-user?rankingType=popularity&timePeriod=online
Authorization: Bearer {token}

响应(已上榜):

{
  "code": 200,
  "message": "success",
  "data": {
    "userId": "currentUser",
    "avatar": "https://cdn.example.com/avatar/7.jpeg",
    "nickname": "我",
    "popularityScore": 45000,
    "rank": 5,
    "artworkImage": "https://cdn.example.com/artwork/current.png",
    "artworkId": "currentUserArtwork",
    "isRanked": true
  }
}

响应(未上榜):

{
  "code": 200,
  "message": "success",
  "data": {
    "userId": "currentUser",
    "avatar": "https://cdn.example.com/avatar/7.jpeg",
    "nickname": "我",
    "popularityScore": 371,
    "rank": null,
    "artworkImage": "https://cdn.example.com/artwork/current.png",
    "artworkId": "currentUserArtwork",
    "isRanked": false
  }
}

7. 数据验证规则

后端验证要求

  1. rankingType 验证

    • 必填
    • 只能是: popularity, custom, activity
  2. timePeriod 验证

    • 必填
    • 只能是: online, monthly, history
  3. page 验证

    • 可选,默认为 1
    • 必须是正整数
    • 最小值: 1
  4. pageSize 验证

    • 可选,默认为 20
    • 必须是正整数
    • 范围: 1-100
  5. 用户数据验证

    • userId: 非空字符串
    • nickname: 非空字符串最大20字符
    • avatar: 有效的URL格式
    • popularityScore: 非负整数
    • rank: 正整数从1开始
  6. 作品数据验证(仅热度榜和自制榜)

    • artworkImage: 有效的URL格式
    • artworkId: 非空字符串

8. 性能优化建议

缓存策略

  1. 排行榜数据缓存

    • 缓存时间: 5分钟
    • 缓存键: ranking:{rankingType}:{timePeriod}:{page}
  2. 用户排名缓存

    • 缓存时间: 1分钟
    • 缓存键: user_rank:{userId}:{rankingType}:{timePeriod}

数据库查询优化

  1. popularityScore 字段建立索引
  2. userId 字段建立索引
  3. 使用 Redis 存储实时排行榜数据Sorted Set

9. 前后端数据映射

前端 Mock 数据 → 后端数据库字段

前端字段 后端数据库字段 类型 说明
rank - computed 根据 popularityScore 计算
userId user_id varchar(50) 用户唯一标识
avatar avatar_url varchar(255) 头像URL
nickname nickname varchar(50) 用户昵称
popularityScore popularity_score int 人气值
artworkImage artwork_image_url varchar(255) 作品图片URL
artworkId artwork_id varchar(50) 作品ID

数据库表结构建议

-- 用户排行榜表
CREATE TABLE user_rankings (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id VARCHAR(50) NOT NULL,
    ranking_type ENUM('popularity', 'custom', 'activity') NOT NULL,
    time_period ENUM('online', 'monthly', 'history') NOT NULL,
    popularity_score INT NOT NULL DEFAULT 0,
    artwork_id VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_ranking_score (ranking_type, time_period, popularity_score DESC),
    INDEX idx_user_ranking (user_id, ranking_type, time_period)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 用户基本信息表
CREATE TABLE users (
    user_id VARCHAR(50) PRIMARY KEY,
    nickname VARCHAR(50) NOT NULL,
    avatar_url VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 作品信息表
CREATE TABLE artworks (
    artwork_id VARCHAR(50) PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    image_url VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_artwork (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

10. 版本历史

版本 日期 修改内容 修改人
1.0.0 2024-03-11 初始版本 -

附录: TypeScript 完整类型定义

// 榜单类型枚举
export enum RankingType {
  POPULARITY = 'popularity',
  CUSTOM = 'custom',
  ACTIVITY = 'activity'
}

// 时间段枚举
export enum TimePeriod {
  ONLINE = 'online',
  MONTHLY = 'monthly',
  HISTORY = 'history'
}

// 排行榜用户接口
export interface RankingUser {
  rank: number;
  userId: string;
  avatar: string;
  nickname: string;
  popularityScore: number;
  artworkImage?: string;
  artworkId?: string;
}

// 当前用户排名接口
export interface CurrentUserRanking extends RankingUser {
  rank: number | null;
  isRanked: boolean;
}

// 排行榜列表请求参数
export interface RankingListRequest {
  rankingType: RankingType;
  timePeriod: TimePeriod;
  page?: number;
  pageSize?: number;
}

// 排行榜列表响应数据
export interface RankingListResponse {
  rankingType: RankingType;
  timePeriod: TimePeriod;
  hasArtwork: boolean;
  total: number;
  page: number;
  pageSize: number;
  list: RankingUser[];
}

// 当前用户排名请求参数
export interface CurrentUserRankingRequest {
  rankingType: RankingType;
  timePeriod: TimePeriod;
}

// API 响应包装
export interface ApiResponse<T> {
  code: number;
  message: string;
  data: T | null;
}