Files
tyapi-server/docs/产品列表功能区分说明.md
2025-07-30 00:51:22 +08:00

4.7 KiB

产品列表功能区分说明

概述

为了确保管理员和用户端的产品列表功能正确区分,我们对产品列表功能进行了重构,实现了以下目标:

  1. 管理员端:可以看到所有产品(包括隐藏的),包含产品的可见状态信息
  2. 用户端:默认只看到可见的产品,包含用户的订阅状态信息

功能区分

管理员端产品列表 (/api/v1/admin/products)

特点:

  • 可以看到所有产品,包括隐藏的产品
  • 返回 ProductAdminInfoResponse 结构,包含 is_visible 字段
  • 不包含用户的订阅状态信息
  • 支持按可见状态筛选

响应结构:

{
  "total": 100,
  "page": 1,
  "size": 10,
  "items": [
    {
      "id": "product-id",
      "name": "产品名称",
      "code": "PRODUCT001",
      "description": "产品描述",
      "price": 99.99,
      "is_enabled": true,
      "is_visible": false,  // 管理员可以看到可见状态
      "is_package": false,
      "category": {...},
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ]
}

用户端产品列表 (/api/v1/products)

特点:

  • 默认只显示可见的产品
  • 返回 ProductInfoResponse 结构,不包含 is_visible 字段
  • 包含用户的订阅状态信息(如果用户已登录)
  • 不支持查看隐藏的产品

响应结构:

{
  "total": 50,
  "page": 1,
  "size": 10,
  "items": [
    {
      "id": "product-id",
      "name": "产品名称",
      "code": "PRODUCT001",
      "description": "产品描述",
      "price": 99.99,
      "is_enabled": true,
      "is_package": false,
      "is_subscribed": true,  // 用户端包含订阅状态
      "category": {...},
      "created_at": "2024-01-01T00:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ]
}

实现细节

1. 响应结构区分

创建了两个不同的响应结构:

  • ProductInfoResponse:用户端使用,不包含 is_visible 字段
  • ProductAdminInfoResponse:管理员端使用,包含 is_visible 字段

2. 应用服务方法区分

ProductApplicationService 接口中添加了专用方法:

// 管理员专用方法
ListProductsForAdmin(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (*responses.ProductAdminListResponse, error)
GetProductByIDForAdmin(ctx context.Context, query *queries.GetProductQuery) (*responses.ProductAdminInfoResponse, error)

// 用户端专用方法
GetProductByIDForUser(ctx context.Context, query *queries.GetProductQuery) (*responses.ProductInfoResponse, error)

3. 筛选逻辑区分

用户端筛选逻辑:

// 可见状态筛选 - 用户端默认只显示可见的产品
if isVisible := c.Query("is_visible"); isVisible != "" {
    if visible, err := strconv.ParseBool(isVisible); err == nil {
        filters["is_visible"] = visible
    }
} else {
    // 如果没有指定可见状态,默认只显示可见的产品
    filters["is_visible"] = true
}

管理员端筛选逻辑:

// 可见状态筛选 - 管理员可以看到所有产品
if isVisible := c.Query("is_visible"); isVisible != "" {
    if visible, err := strconv.ParseBool(isVisible); err == nil {
        filters["is_visible"] = visible
    }
}

4. 产品详情获取区分

用户端产品详情:

  • 使用 GetProductByIDForUser 方法
  • 验证产品可见性,隐藏产品返回 404
  • 不包含可见状态信息

管理员端产品详情:

  • 使用 GetProductByIDForAdmin 方法
  • 可以获取任何产品的详情
  • 包含可见状态信息

路由区分

管理员路由

  • GET /api/v1/admin/products - 管理员产品列表
  • GET /api/v1/admin/products/{id} - 管理员产品详情

用户路由

  • GET /api/v1/products - 用户产品列表
  • GET /api/v1/products/{id} - 用户产品详情

测试

创建了专门的测试文件 test/admin_product_list_test.go 来验证:

  1. 管理员筛选功能
  2. 用户筛选功能
  3. 响应结构差异
  4. 功能区分逻辑

维护建议

  1. 保持分离:确保管理员端和用户端的功能保持分离,避免混淆
  2. 权限控制:确保路由级别的权限控制正确实现
  3. 文档更新:及时更新 API 文档,明确说明不同端的功能差异
  4. 测试覆盖:确保测试覆盖所有场景,包括边界情况

注意事项

  1. 用户端默认只显示可见产品,这是业务逻辑要求
  2. 管理员端可以看到所有产品,包括隐藏的,便于管理
  3. 响应结构的差异确保了数据安全,用户无法看到产品的可见状态
  4. 订阅状态只在用户端显示,管理员端不需要此信息