# 排行榜系统后端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` | ### 榜单类型枚举 ```json { "popularity": "热度榜", "custom": "自制榜", "activity": "活动榜" } ``` ### 时间段枚举 ```json { "online": "在线", "monthly": "本月", "history": "历史" } ``` ### 响应格式 ```json { "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` | ### 响应格式 **已上榜状态**: ```json { "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 } } ``` **未上榜状态**: ```json { "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 类型定义**: ```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 类型定义**: ```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 | ❌ 否 | 不包含作品相关字段 | ### 后端返回字段规则 ```javascript // 热度榜和自制榜 { "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. 错误响应格式 ### 通用错误响应 ```json { "code": 400, "message": "参数错误:rankingType 必须为 popularity、custom 或 activity", "data": null } ``` ### 错误码定义 | 错误码 | 说明 | 示例消息 | |--------|------|---------| | 400 | 请求参数错误 | "参数错误:rankingType 不能为空" | | 401 | 未登录或token失效 | "请先登录" | | 404 | 资源不存在 | "榜单数据不存在" | | 500 | 服务器内部错误 | "服务器错误,请稍后重试" | --- ## 6. 请求示例 ### 示例1: 获取热度榜在线排行 **请求**: ```http GET /api/ranking/list?rankingType=popularity&timePeriod=online&page=1&pageSize=20 Authorization: Bearer {token} ``` **响应**: ```json { "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: 获取活动榜本月排行 **请求**: ```http GET /api/ranking/list?rankingType=activity&timePeriod=monthly&page=1&pageSize=20 Authorization: Bearer {token} ``` **响应**: ```json { "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: 获取当前用户排名 **请求**: ```http GET /api/ranking/current-user?rankingType=popularity&timePeriod=online Authorization: Bearer {token} ``` **响应(已上榜)**: ```json { "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 } } ``` **响应(未上榜)**: ```json { "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 | ### 数据库表结构建议 ```sql -- 用户排行榜表 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 完整类型定义 ```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 { code: number; message: string; data: T | null; } ```