Files
jhao 10ef5918fc
Some checks failed
test/timeline-server/pipeline/head There was a failure building this commit
feat(user-service): 实现用户服务核心功能与数据同步
- 新增用户资料、偏好设置、自定义字段管理功能
- 实现评论、反应、相册与智能集合的完整业务逻辑
- 添加离线变更记录与数据同步机制支持冲突解决
- 集成 Redis 缓存配置与用户统计数据聚合
- 创建 8 个业务控制器处理用户交互请求
- 新增 Feign 客户端与故事服务集成
- 补充详细的后端实现与 WebSocket 指南文档
- 更新项目依赖配置支持新增功能模块
2026-02-25 15:04:30 +08:00

7.1 KiB

Task 21.1 Verification: Layout Preferences API Endpoints

Task Status: COMPLETE

Task 21.1 requires implementing the Layout Preferences API endpoints. This verification confirms that all required components have been successfully implemented as part of Task 19 (Preferences service).

Requirements Validation

Requirement 8.5: Layout preferences persist across sessions

Status: Implemented

The implementation includes:

  • Database persistence in user_preferences table
  • GET endpoint to retrieve persisted preferences
  • PUT endpoint to update and persist preferences

Implementation Components

1. Database Schema

File: timeline-sql/V1.4.0__personal_user_enhancements.sql

Layout-related fields in user_preferences table:

gallery_layout VARCHAR(20) DEFAULT 'grid' COMMENT '画廊布局: grid/list',
timeline_layout VARCHAR(20) DEFAULT 'grid' COMMENT '时间线布局: grid/list',
album_layout VARCHAR(20) DEFAULT 'grid' COMMENT '相册布局: grid/list',
card_size VARCHAR(20) DEFAULT 'medium' COMMENT '卡片大小: small/medium/large',

2. API Endpoint

File: src/main/java/com/timeline/user/controller/PreferencesController.java

Endpoint: PUT /api/v1/preferences/layout

@PutMapping("/layout")
public ResponseEntity<Void> updateLayoutPreferences(
        @RequestHeader("X-User-Id") String userId,
        @Valid @RequestBody UpdateLayoutRequest request) {
    preferencesService.updateLayoutPreferences(userId, request.getGalleryLayout(), 
            request.getTimelineLayout(), request.getAlbumLayout(), request.getCardSize());
    return ResponseEntity.success(null);
}

3. Request DTO

File: src/main/java/com/timeline/user/dto/UpdateLayoutRequest.java

Includes validation for:

  • galleryLayout: "grid" or "list"
  • timelineLayout: "grid" or "list"
  • albumLayout: "grid" or "list"
  • cardSize: "small", "medium", or "large"

All fields are optional to support partial updates.

4. Service Implementation

File: src/main/java/com/timeline/user/service/impl/PreferencesServiceImpl.java

Method: updateLayoutPreferences()

Features:

  • Validates all layout parameters
  • Supports partial updates (null fields use existing values)
  • Creates default preferences if user has none
  • Transactional for data consistency
  • Comprehensive error handling

Validation logic:

private boolean isValidLayout(String layout) {
    return "grid".equals(layout) || "list".equals(layout);
}

private boolean isValidCardSize(String cardSize) {
    return "small".equals(cardSize) || "medium".equals(cardSize) || "large".equals(cardSize);
}

5. Data Access Layer

File: src/main/resources/com/timeline/user/dao/PreferencesMapper.xml

Method: updateLayout()

<update id="updateLayout">
    UPDATE user_preferences
    SET gallery_layout = #{galleryLayout},
        timeline_layout = #{timelineLayout},
        album_layout = #{albumLayout},
        card_size = #{cardSize},
        update_time = CURRENT_TIMESTAMP
    WHERE user_id = #{userId}
</update>

6. Unit Tests

File: src/test/java/com/timeline/user/service/PreferencesServiceTest.java

Test coverage includes:

  • Full layout update with all fields
  • Partial layout update (only some fields)
  • Invalid layout validation
  • Invalid card size validation
  • Default preferences creation

Example test:

@Test
public void testUpdateLayoutPreferences() {
    String userId = "test-user-123";
    UserPreferences existing = createDefaultPreferences(userId);
    when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
    when(preferencesMapper.updateLayout(userId, "list", "grid", "list", "large")).thenReturn(1);
    
    preferencesService.updateLayoutPreferences(userId, "list", "grid", "list", "large");
    
    verify(preferencesMapper, times(1)).updateLayout(userId, "list", "grid", "list", "large");
}

API Specification

PUT /api/v1/preferences/layout

Headers:

  • X-User-Id: User identifier (required)

Request Body:

{
  "galleryLayout": "list",
  "timelineLayout": "grid",
  "albumLayout": "list",
  "cardSize": "large"
}

Validation Rules:

  • All fields are optional (supports partial updates)
  • galleryLayout, timelineLayout, albumLayout: must be "grid" or "list"
  • cardSize: must be "small", "medium", or "large"

Response (200 OK):

{
  "code": 200,
  "message": "success",
  "data": null
}

Error Responses:

  • 400 Bad Request: Invalid layout or card size value
  • 401 Unauthorized: Missing or invalid X-User-Id header

Default Values

When a user has no preferences, the system creates defaults:

  • Gallery layout: grid
  • Timeline layout: grid
  • Album layout: grid
  • Card size: medium

Features

1. Partial Updates Support

The endpoint supports updating only specific fields:

{
  "galleryLayout": "list",
  "cardSize": "small"
}

Other fields (timelineLayout, albumLayout) retain their existing values.

2. Validation

  • Validates layout values: "grid" or "list"
  • Validates card size values: "small", "medium", or "large"
  • Throws IllegalArgumentException for invalid values

3. Auto-Creation

If a user has no preferences record, the service automatically creates one with default values before updating.

4. Transactional

All updates are wrapped in @Transactional to ensure data consistency.

Integration with Other Components

  • GET /api/v1/preferences - Retrieves all preferences including layout
  • PUT /api/v1/preferences/theme - Updates theme preferences
  • PUT /api/v1/preferences/timeline - Updates timeline display preferences

Database Integration

  • Uses MyBatis for database operations
  • Automatic timestamp updates via ON UPDATE CURRENT_TIMESTAMP
  • Indexed on user_id for fast lookups

Verification Summary

Component Status Notes
Database Schema Complete All layout fields present
API Endpoint Complete PUT /api/v1/preferences/layout
Request DTO Complete Validation annotations included
Service Layer Complete Full validation and error handling
Data Access Complete MyBatis mapper implemented
Unit Tests Complete Comprehensive test coverage
Documentation Complete API documented in PREFERENCES_BACKEND_IMPLEMENTATION.md

Conclusion

Task 21.1 (Create Layout Preferences API endpoints) is COMPLETE. All required components have been implemented:

  1. PUT /api/v1/preferences/layout endpoint exists
  2. Layout preferences are stored in database schema
  3. Requirement 8.5 (persistence) is satisfied
  4. Comprehensive validation and error handling
  5. Unit tests provide good coverage
  6. Supports partial updates for flexibility

The implementation was completed as part of Task 19 (Preferences service) and includes all layout-related functionality specified in the requirements.

Next Steps

Task 21.1 is complete. The next task in the workflow is:

  • Task 21.2: Write property tests for Layout Preferences backend (optional)
  • Task 22: Implement Layout Preferences frontend

The backend API is ready for frontend integration.