# 产品列表功能区分说明 ## 概述 为了确保管理员和用户端的产品列表功能正确区分,我们对产品列表功能进行了重构,实现了以下目标: 1. **管理员端**:可以看到所有产品(包括隐藏的),包含产品的可见状态信息 2. **用户端**:默认只看到可见的产品,包含用户的订阅状态信息 ## 功能区分 ### 管理员端产品列表 (`/api/v1/admin/products`) **特点:** - 可以看到所有产品,包括隐藏的产品 - 返回 `ProductAdminInfoResponse` 结构,包含 `is_visible` 字段 - 不包含用户的订阅状态信息 - 支持按可见状态筛选 **响应结构:** ```json { "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` 字段 - 包含用户的订阅状态信息(如果用户已登录) - 不支持查看隐藏的产品 **响应结构:** ```json { "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` 接口中添加了专用方法: ```go // 管理员专用方法 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. 筛选逻辑区分 **用户端筛选逻辑:** ```go // 可见状态筛选 - 用户端默认只显示可见的产品 if isVisible := c.Query("is_visible"); isVisible != "" { if visible, err := strconv.ParseBool(isVisible); err == nil { filters["is_visible"] = visible } } else { // 如果没有指定可见状态,默认只显示可见的产品 filters["is_visible"] = true } ``` **管理员端筛选逻辑:** ```go // 可见状态筛选 - 管理员可以看到所有产品 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. 订阅状态只在用户端显示,管理员端不需要此信息