13 KiB
13 KiB
排行榜系统后端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. 数据验证规则
后端验证要求
-
rankingType 验证
- 必填
- 只能是:
popularity,custom,activity
-
timePeriod 验证
- 必填
- 只能是:
online,monthly,history
-
page 验证
- 可选,默认为 1
- 必须是正整数
- 最小值: 1
-
pageSize 验证
- 可选,默认为 20
- 必须是正整数
- 范围: 1-100
-
用户数据验证
userId: 非空字符串nickname: 非空字符串,最大20字符avatar: 有效的URL格式popularityScore: 非负整数rank: 正整数(从1开始)
-
作品数据验证(仅热度榜和自制榜)
artworkImage: 有效的URL格式artworkId: 非空字符串
8. 性能优化建议
缓存策略
-
排行榜数据缓存
- 缓存时间: 5分钟
- 缓存键:
ranking:{rankingType}:{timePeriod}:{page}
-
用户排名缓存
- 缓存时间: 1分钟
- 缓存键:
user_rank:{userId}:{rankingType}:{timePeriod}
数据库查询优化
- 为
popularityScore字段建立索引 - 为
userId字段建立索引 - 使用 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;
}