Files
jhao 5a0aa2b3c1
All checks were successful
test/timeline-frontend/pipeline/head This commit looks good
feat: 添加评论、反应、离线编辑及主题定制功能
- 实现评论系统,包括评论输入、列表展示和集成指南
- 添加反应功能组件(ReactionBar、ReactionButton、ReactionPicker)
- 实现离线编辑支持,包括同步状态管理和冲突解决
- 添加主题定制功能,支持多种配色方案和主题预览
- 新增多视图布局选项(时间线、分组、砌体视图)
- 实现个人资料编辑器,支持头像、简介和自定义字段编辑
- 添加统计页面,展示存储使用情况和上传趋势
- 新增相册管理功能,支持相册创建、编辑和照片管理
- 实现响应式设计和加载骨架屏组件
- 扩展国际化支持,新增孟加拉语、波斯语、印尼语、日语、葡萄牙语等语言
- 添加错误边界组件和离线指示器
- 更新配置文件、路由和依赖项
- 新增完整的文档、测试用例和集成指南
2026-02-25 15:02:05 +08:00

14 KiB

API Documentation - Personal User Enhancements

This document provides comprehensive API documentation for the personal user enhancements features.

Table of Contents

  1. Smart Collections
  2. Album Management
  3. Personal Statistics
  4. Offline Sync
  5. Comments
  6. Reactions
  7. User Preferences
  8. Profile Customization

Smart Collections

Get Smart Collections

Retrieve all smart collections for the current user.

Endpoint: GET /api/v1/collections/smart

Response:

{
  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:

{
  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:

{
  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:

{
  name: string;           // Required
  description?: string;
  coverPhotoId?: string;
}

Response:

{
  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:

{
  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:

{
  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:

{
  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:

{
  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:

{
  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:

{
  coverPhotoId: string;
}

Personal Statistics

Get Statistics Overview

Get comprehensive statistics for the current user.

Endpoint: GET /api/v1/statistics/overview

Response:

{
  userId: string;
  totalPhotos: number;
  totalStories: number;
  totalStorageBytes: number;
  calculatedAt: string;
}

Get monthly and yearly upload trends.

Endpoint: GET /api/v1/statistics/uploads

Query Parameters:

  • period (string): 'monthly' or 'yearly' (default: 'monthly')

Response:

{
  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:

{
  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:

{
  changes: Array<{
    id: string;
    entityType: 'story' | 'album' | 'photo';
    entityId: string;
    operation: 'create' | 'update' | 'delete';
    data: any;
    timestamp: string;
  }>;
}

Response:

{
  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:

{
  lastSyncAt?: string;
  pendingChanges: number;
  isSyncing: boolean;
}

Resolve Conflict

Resolve a synchronization conflict.

Endpoint: POST /api/v1/sync/resolve-conflict

Request Body:

{
  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:

{
  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:

{
  entityType: 'story' | 'photo';
  entityId: string;
  text: string;  // 1-1000 characters
}

Response:

{
  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:

{
  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:

{
  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:

{
  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:

{
  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:

{
  mode?: 'light' | 'dark' | 'auto';
  colorScheme?: string;
}

Update Layout Preferences

Update layout settings.

Endpoint: PUT /api/v1/preferences/layout

Request Body:

{
  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:

{
  displayMode: 'chronological' | 'grouped' | 'masonry';
}

Profile Customization

Get Profile

Get user profile information.

Endpoint: GET /api/v1/profile

Response:

{
  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:

{
  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:

{
  coverPhotoUrl: string;
}

Update Custom Fields

Update profile custom fields.

Endpoint: PUT /api/v1/profile/custom-fields

Request Body:

{
  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:

{
  type: 'comment_added' | 'comment_updated' | 'comment_deleted';
  comment: Comment;  // Full comment object
}

Reaction Updates

Topic: /topic/reactions/{entityType}/{entityId}

Message Format:

{
  type: 'reaction_added' | 'reaction_updated' | 'reaction_removed';
  reaction: Reaction;  // Full reaction object
  summary: ReactionSummary;  // Updated counts
}

Collection Updates

Topic: /topic/collections/updates

Message Format:

{
  type: 'collection_created' | 'collection_updated';
  collection: SmartCollection;
}

Personal Notifications

Topic: /user/queue/notifications

Message Format:

{
  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:

{
  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:

{
  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.