All checks were successful
test/timeline-frontend/pipeline/head This commit looks good
- 实现评论系统,包括评论输入、列表展示和集成指南 - 添加反应功能组件(ReactionBar、ReactionButton、ReactionPicker) - 实现离线编辑支持,包括同步状态管理和冲突解决 - 添加主题定制功能,支持多种配色方案和主题预览 - 新增多视图布局选项(时间线、分组、砌体视图) - 实现个人资料编辑器,支持头像、简介和自定义字段编辑 - 添加统计页面,展示存储使用情况和上传趋势 - 新增相册管理功能,支持相册创建、编辑和照片管理 - 实现响应式设计和加载骨架屏组件 - 扩展国际化支持,新增孟加拉语、波斯语、印尼语、日语、葡萄牙语等语言 - 添加错误边界组件和离线指示器 - 更新配置文件、路由和依赖项 - 新增完整的文档、测试用例和集成指南
816 lines
14 KiB
Markdown
816 lines
14 KiB
Markdown
# API Documentation - Personal User Enhancements
|
|
|
|
This document provides comprehensive API documentation for the personal user enhancements features.
|
|
|
|
## Table of Contents
|
|
|
|
1. [Smart Collections](#smart-collections)
|
|
2. [Album Management](#album-management)
|
|
3. [Personal Statistics](#personal-statistics)
|
|
4. [Offline Sync](#offline-sync)
|
|
5. [Comments](#comments)
|
|
6. [Reactions](#reactions)
|
|
7. [User Preferences](#user-preferences)
|
|
8. [Profile Customization](#profile-customization)
|
|
|
|
---
|
|
|
|
## Smart Collections
|
|
|
|
### Get Smart Collections
|
|
|
|
Retrieve all smart collections for the current user.
|
|
|
|
**Endpoint:** `GET /api/v1/collections/smart`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
collections: Array<{
|
|
id: string;
|
|
userId: string;
|
|
type: 'date' | 'location' | 'person';
|
|
name: string;
|
|
criteria: {
|
|
year?: number;
|
|
month?: number;
|
|
day?: number;
|
|
location?: {
|
|
name: string;
|
|
latitude: number;
|
|
longitude: number;
|
|
radius?: number;
|
|
};
|
|
personId?: string;
|
|
personName?: string;
|
|
};
|
|
contentCount: number;
|
|
thumbnailUrl?: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
### Get Collection Content
|
|
|
|
Retrieve content items within a specific smart collection.
|
|
|
|
**Endpoint:** `GET /api/v1/collections/smart/:id/content`
|
|
|
|
**Query Parameters:**
|
|
- `page` (number): Page number (default: 1)
|
|
- `pageSize` (number): Items per page (default: 20)
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
collectionId: string;
|
|
items: Array<{
|
|
id: string;
|
|
type: 'photo' | 'story';
|
|
thumbnailUrl: string;
|
|
createdAt: string;
|
|
metadata: Record<string, any>;
|
|
}>;
|
|
total: number;
|
|
page: number;
|
|
pageSize: number;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Album Management
|
|
|
|
### List Albums
|
|
|
|
Get all albums for the current user.
|
|
|
|
**Endpoint:** `GET /api/v1/albums`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
albums: Array<{
|
|
id: string;
|
|
userId: string;
|
|
name: string;
|
|
description?: string;
|
|
coverPhotoId?: string;
|
|
coverPhotoUrl?: string;
|
|
photoCount: number;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
### Create Album
|
|
|
|
Create a new album.
|
|
|
|
**Endpoint:** `POST /api/v1/albums`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
name: string; // Required
|
|
description?: string;
|
|
coverPhotoId?: string;
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
id: string;
|
|
userId: string;
|
|
name: string;
|
|
description?: string;
|
|
coverPhotoId?: string;
|
|
coverPhotoUrl?: string;
|
|
photoCount: number;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
```
|
|
|
|
### Get Album Details
|
|
|
|
Get detailed information about a specific album including photos.
|
|
|
|
**Endpoint:** `GET /api/v1/albums/:id`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
id: string;
|
|
userId: string;
|
|
name: string;
|
|
description?: string;
|
|
coverPhotoId?: string;
|
|
coverPhotoUrl?: string;
|
|
photoCount: number;
|
|
photos: Array<{
|
|
id: string;
|
|
photoId: string;
|
|
albumId: string;
|
|
order: number;
|
|
photoUrl: string;
|
|
thumbnailUrl: string;
|
|
addedAt: string;
|
|
}>;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
```
|
|
|
|
### Update Album
|
|
|
|
Update album information.
|
|
|
|
**Endpoint:** `PUT /api/v1/albums/:id`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
name?: string;
|
|
description?: string;
|
|
coverPhotoId?: string;
|
|
}
|
|
```
|
|
|
|
### Delete Album
|
|
|
|
Delete an album (photos are preserved).
|
|
|
|
**Endpoint:** `DELETE /api/v1/albums/:id`
|
|
|
|
**Response:** `204 No Content`
|
|
|
|
### Add Photos to Album
|
|
|
|
Add one or more photos to an album.
|
|
|
|
**Endpoint:** `POST /api/v1/albums/:id/photos`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
photoIds: string[]; // Array of photo IDs to add
|
|
}
|
|
```
|
|
|
|
### Remove Photos from Album
|
|
|
|
Remove photos from an album.
|
|
|
|
**Endpoint:** `DELETE /api/v1/albums/:id/photos`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
photoIds: string[]; // Array of photo IDs to remove
|
|
}
|
|
```
|
|
|
|
### Reorder Photos
|
|
|
|
Change the order of photos in an album.
|
|
|
|
**Endpoint:** `PUT /api/v1/albums/:id/photos/order`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
photoIds: string[]; // Array of photo IDs in desired order
|
|
}
|
|
```
|
|
|
|
### Set Cover Photo
|
|
|
|
Set the cover photo for an album.
|
|
|
|
**Endpoint:** `PUT /api/v1/albums/:id/cover`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
coverPhotoId: string;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Personal Statistics
|
|
|
|
### Get Statistics Overview
|
|
|
|
Get comprehensive statistics for the current user.
|
|
|
|
**Endpoint:** `GET /api/v1/statistics/overview`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
userId: string;
|
|
totalPhotos: number;
|
|
totalStories: number;
|
|
totalStorageBytes: number;
|
|
calculatedAt: string;
|
|
}
|
|
```
|
|
|
|
### Get Upload Trends
|
|
|
|
Get monthly and yearly upload trends.
|
|
|
|
**Endpoint:** `GET /api/v1/statistics/uploads`
|
|
|
|
**Query Parameters:**
|
|
- `period` (string): 'monthly' or 'yearly' (default: 'monthly')
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
trends: Array<{
|
|
period: string; // 'YYYY-MM' or 'YYYY'
|
|
photoCount: number;
|
|
storyCount: number;
|
|
storageBytes: number;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
### Get Storage Breakdown
|
|
|
|
Get storage usage breakdown by content type.
|
|
|
|
**Endpoint:** `GET /api/v1/statistics/storage`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
breakdown: {
|
|
photos: number;
|
|
videos: number;
|
|
documents: number;
|
|
other: number;
|
|
};
|
|
}
|
|
```
|
|
|
|
### Refresh Statistics
|
|
|
|
Force recalculation of statistics.
|
|
|
|
**Endpoint:** `POST /api/v1/statistics/refresh`
|
|
|
|
**Response:** `202 Accepted`
|
|
|
|
---
|
|
|
|
## Offline Sync
|
|
|
|
### Upload Offline Changes
|
|
|
|
Upload a batch of offline changes for synchronization.
|
|
|
|
**Endpoint:** `POST /api/v1/sync/changes`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
changes: Array<{
|
|
id: string;
|
|
entityType: 'story' | 'album' | 'photo';
|
|
entityId: string;
|
|
operation: 'create' | 'update' | 'delete';
|
|
data: any;
|
|
timestamp: string;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
success: boolean;
|
|
syncedCount: number;
|
|
failedCount: number;
|
|
conflicts: Array<{
|
|
changeId: string;
|
|
entityType: string;
|
|
entityId: string;
|
|
localVersion: any;
|
|
serverVersion: any;
|
|
conflictType: 'modified' | 'deleted';
|
|
}>;
|
|
}
|
|
```
|
|
|
|
### Get Sync Status
|
|
|
|
Get current synchronization status.
|
|
|
|
**Endpoint:** `GET /api/v1/sync/status`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
lastSyncAt?: string;
|
|
pendingChanges: number;
|
|
isSyncing: boolean;
|
|
}
|
|
```
|
|
|
|
### Resolve Conflict
|
|
|
|
Resolve a synchronization conflict.
|
|
|
|
**Endpoint:** `POST /api/v1/sync/resolve-conflict`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
conflictId: string;
|
|
strategy: 'keep-local' | 'keep-server' | 'merge';
|
|
mergedData?: any; // Required if strategy is 'merge'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Comments
|
|
|
|
### Get Comments
|
|
|
|
Get comments for a specific entity (story or photo).
|
|
|
|
**Endpoint:** `GET /api/v1/comments/:entityType/:entityId`
|
|
|
|
**Path Parameters:**
|
|
- `entityType`: 'story' or 'photo'
|
|
- `entityId`: ID of the entity
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
comments: Array<{
|
|
id: string;
|
|
entityType: 'story' | 'photo';
|
|
entityId: string;
|
|
userId: string;
|
|
userName: string;
|
|
userAvatarUrl?: string;
|
|
text: string;
|
|
createdAt: string;
|
|
updatedAt?: string;
|
|
isEdited: boolean;
|
|
canEdit: boolean;
|
|
canDelete: boolean;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
### Create Comment
|
|
|
|
Add a comment to an entity.
|
|
|
|
**Endpoint:** `POST /api/v1/comments`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
entityType: 'story' | 'photo';
|
|
entityId: string;
|
|
text: string; // 1-1000 characters
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
id: string;
|
|
entityType: 'story' | 'photo';
|
|
entityId: string;
|
|
userId: string;
|
|
userName: string;
|
|
userAvatarUrl?: string;
|
|
text: string;
|
|
createdAt: string;
|
|
isEdited: false;
|
|
canEdit: true;
|
|
canDelete: true;
|
|
}
|
|
```
|
|
|
|
### Update Comment
|
|
|
|
Edit an existing comment (within 24 hours).
|
|
|
|
**Endpoint:** `PUT /api/v1/comments/:id`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
text: string; // 1-1000 characters
|
|
}
|
|
```
|
|
|
|
### Delete Comment
|
|
|
|
Delete a comment.
|
|
|
|
**Endpoint:** `DELETE /api/v1/comments/:id`
|
|
|
|
**Response:** `204 No Content`
|
|
|
|
---
|
|
|
|
## Reactions
|
|
|
|
### Get Reactions
|
|
|
|
Get reactions for a specific entity.
|
|
|
|
**Endpoint:** `GET /api/v1/reactions/:entityType/:entityId`
|
|
|
|
**Path Parameters:**
|
|
- `entityType`: 'story' or 'photo'
|
|
- `entityId`: ID of the entity
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
entityType: 'story' | 'photo';
|
|
entityId: string;
|
|
counts: {
|
|
like: number;
|
|
love: number;
|
|
laugh: number;
|
|
wow: number;
|
|
sad: number;
|
|
};
|
|
userReaction?: 'like' | 'love' | 'laugh' | 'wow' | 'sad';
|
|
recentReactions: Array<{
|
|
id: string;
|
|
userId: string;
|
|
userName: string;
|
|
userAvatarUrl?: string;
|
|
type: 'like' | 'love' | 'laugh' | 'wow' | 'sad';
|
|
createdAt: string;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
### Add/Update Reaction
|
|
|
|
Add or update a reaction on an entity.
|
|
|
|
**Endpoint:** `POST /api/v1/reactions`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
entityType: 'story' | 'photo';
|
|
entityId: string;
|
|
type: 'like' | 'love' | 'laugh' | 'wow' | 'sad';
|
|
}
|
|
```
|
|
|
|
### Remove Reaction
|
|
|
|
Remove user's reaction from an entity.
|
|
|
|
**Endpoint:** `DELETE /api/v1/reactions/:entityType/:entityId`
|
|
|
|
**Response:** `204 No Content`
|
|
|
|
---
|
|
|
|
## User Preferences
|
|
|
|
### Get Preferences
|
|
|
|
Get all user preferences.
|
|
|
|
**Endpoint:** `GET /api/v1/preferences`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
userId: string;
|
|
theme: {
|
|
mode: 'light' | 'dark' | 'auto';
|
|
colorScheme: string;
|
|
};
|
|
layout: {
|
|
galleryLayout: 'grid' | 'list';
|
|
timelineLayout: 'grid' | 'list';
|
|
albumLayout: 'grid' | 'list';
|
|
cardSize: 'small' | 'medium' | 'large';
|
|
};
|
|
timeline: {
|
|
displayMode: 'chronological' | 'grouped' | 'masonry';
|
|
};
|
|
updatedAt: string;
|
|
}
|
|
```
|
|
|
|
### Update Theme Preferences
|
|
|
|
Update theme settings.
|
|
|
|
**Endpoint:** `PUT /api/v1/preferences/theme`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
mode?: 'light' | 'dark' | 'auto';
|
|
colorScheme?: string;
|
|
}
|
|
```
|
|
|
|
### Update Layout Preferences
|
|
|
|
Update layout settings.
|
|
|
|
**Endpoint:** `PUT /api/v1/preferences/layout`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
galleryLayout?: 'grid' | 'list';
|
|
timelineLayout?: 'grid' | 'list';
|
|
albumLayout?: 'grid' | 'list';
|
|
cardSize?: 'small' | 'medium' | 'large';
|
|
}
|
|
```
|
|
|
|
### Update Timeline Preferences
|
|
|
|
Update timeline display settings.
|
|
|
|
**Endpoint:** `PUT /api/v1/preferences/timeline`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
displayMode: 'chronological' | 'grouped' | 'masonry';
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Profile Customization
|
|
|
|
### Get Profile
|
|
|
|
Get user profile information.
|
|
|
|
**Endpoint:** `GET /api/v1/profile`
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
userId: string;
|
|
coverPhotoUrl?: string;
|
|
bio?: string;
|
|
customFields: Array<{
|
|
id: string;
|
|
name: string;
|
|
value: string;
|
|
visibility: 'public' | 'private';
|
|
order: number;
|
|
}>;
|
|
updatedAt: string;
|
|
}
|
|
```
|
|
|
|
### Update Profile
|
|
|
|
Update profile information.
|
|
|
|
**Endpoint:** `PUT /api/v1/profile`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
bio?: string; // 0-500 characters
|
|
}
|
|
```
|
|
|
|
### Upload Cover Photo
|
|
|
|
Upload a new cover photo.
|
|
|
|
**Endpoint:** `POST /api/v1/profile/cover`
|
|
|
|
**Request:** `multipart/form-data`
|
|
- `file`: Image file (max 5MB, min 1200x400px)
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
coverPhotoUrl: string;
|
|
}
|
|
```
|
|
|
|
### Update Custom Fields
|
|
|
|
Update profile custom fields.
|
|
|
|
**Endpoint:** `PUT /api/v1/profile/custom-fields`
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
fields: Array<{
|
|
id?: string; // Omit for new fields
|
|
name: string;
|
|
value: string;
|
|
visibility: 'public' | 'private';
|
|
order: number;
|
|
}>;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## WebSocket Topics
|
|
|
|
Real-time updates are delivered via WebSocket (STOMP protocol).
|
|
|
|
### Comment Updates
|
|
|
|
**Topic:** `/topic/comments/{entityType}/{entityId}`
|
|
|
|
**Message Format:**
|
|
```typescript
|
|
{
|
|
type: 'comment_added' | 'comment_updated' | 'comment_deleted';
|
|
comment: Comment; // Full comment object
|
|
}
|
|
```
|
|
|
|
### Reaction Updates
|
|
|
|
**Topic:** `/topic/reactions/{entityType}/{entityId}`
|
|
|
|
**Message Format:**
|
|
```typescript
|
|
{
|
|
type: 'reaction_added' | 'reaction_updated' | 'reaction_removed';
|
|
reaction: Reaction; // Full reaction object
|
|
summary: ReactionSummary; // Updated counts
|
|
}
|
|
```
|
|
|
|
### Collection Updates
|
|
|
|
**Topic:** `/topic/collections/updates`
|
|
|
|
**Message Format:**
|
|
```typescript
|
|
{
|
|
type: 'collection_created' | 'collection_updated';
|
|
collection: SmartCollection;
|
|
}
|
|
```
|
|
|
|
### Personal Notifications
|
|
|
|
**Topic:** `/user/queue/notifications`
|
|
|
|
**Message Format:**
|
|
```typescript
|
|
{
|
|
type: 'comment' | 'reaction' | 'sync_complete' | 'sync_conflict';
|
|
title: string;
|
|
message: string;
|
|
data: any;
|
|
timestamp: string;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Responses
|
|
|
|
All endpoints follow a consistent error response format:
|
|
|
|
```typescript
|
|
{
|
|
error: {
|
|
code: string; // Error code (e.g., 'VALIDATION_ERROR')
|
|
message: string; // Human-readable error message
|
|
details?: any; // Additional error details
|
|
timestamp: string; // ISO 8601 timestamp
|
|
}
|
|
}
|
|
```
|
|
|
|
### Common HTTP Status Codes
|
|
|
|
- `200 OK`: Successful request
|
|
- `201 Created`: Resource created successfully
|
|
- `204 No Content`: Successful request with no response body
|
|
- `400 Bad Request`: Invalid request data
|
|
- `401 Unauthorized`: Authentication required
|
|
- `403 Forbidden`: Insufficient permissions
|
|
- `404 Not Found`: Resource not found
|
|
- `409 Conflict`: Resource conflict (e.g., sync conflict)
|
|
- `422 Unprocessable Entity`: Validation error
|
|
- `429 Too Many Requests`: Rate limit exceeded
|
|
- `500 Internal Server Error`: Server error
|
|
- `503 Service Unavailable`: Service temporarily unavailable
|
|
|
|
---
|
|
|
|
## Rate Limiting
|
|
|
|
API requests are rate-limited to prevent abuse:
|
|
|
|
- **Standard endpoints**: 100 requests per minute per user
|
|
- **Upload endpoints**: 20 requests per minute per user
|
|
- **Statistics refresh**: 5 requests per hour per user
|
|
|
|
Rate limit headers are included in responses:
|
|
- `X-RateLimit-Limit`: Maximum requests allowed
|
|
- `X-RateLimit-Remaining`: Remaining requests in current window
|
|
- `X-RateLimit-Reset`: Timestamp when limit resets
|
|
|
|
---
|
|
|
|
## Pagination
|
|
|
|
List endpoints support pagination with the following query parameters:
|
|
|
|
- `page` (number): Page number (1-indexed, default: 1)
|
|
- `pageSize` (number): Items per page (default: 20, max: 100)
|
|
|
|
Paginated responses include:
|
|
```typescript
|
|
{
|
|
items: Array<T>;
|
|
total: number;
|
|
page: number;
|
|
pageSize: number;
|
|
totalPages: number;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Authentication
|
|
|
|
All API requests require authentication via JWT token in the Authorization header:
|
|
|
|
```
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
Tokens are obtained through the login endpoint and should be refreshed before expiration.
|