# 套餐接口快速导航 ## 🎯 快速查找 ### 按功能查找 | 需求 | 文件 | 行号 | |------|------|------| | 查看套餐数据模型 | `internal/model/package.go` | 28-56 | | 查看套餐 API 请求/响应结构 | `internal/model/dto/package_dto.go` | 1-173 | | 查看套餐 HTTP 处理器 | `internal/handler/admin/package.go` | 1-148 | | 查看套餐业务逻辑 | `internal/service/package/service.go` | 1-745 | | 查看套餐数据访问 | `internal/store/postgres/package_store.go` | 1-150 | | 查看套餐 API 路由 | `internal/routes/package.go` | 1-78 | | 查看路由注册入口 | `internal/routes/admin.go` | 71-78 | ### 按字段查找 | 字段 | Model 位置 | DTO 位置 | 说明 | |------|-----------|---------|------| | `duration_days` | `package.go:46` | `package_dto.go:96` | 套餐天数(按天时必填) | | `calendar_type` | `package.go:45` | `package_dto.go:95` | 套餐周期类型 | | `duration_months` | `package.go:37` | `package_dto.go:79` | 套餐时长(月数) | | `real_data_mb` | `package.go:38` | `package_dto.go:80` | 真流量额度 | | `virtual_data_mb` | `package.go:39` | `package_dto.go:81` | 虚流量额度 | | `enable_virtual_data` | `package.go:40` | `package_dto.go:82` | 是否启用虚流量 | ### 按 API 端点查找 | 端点 | Handler 方法 | 路由文件 | 行号 | |------|-------------|---------|------| | `GET /packages` | `List()` | `package.go` | 15-21 | | `POST /packages` | `Create()` | `package.go` | 23-29 | | `GET /packages/:id` | `Get()` | `package.go` | 31-37 | | `PUT /packages/:id` | `Update()` | `package.go` | 39-45 | | `DELETE /packages/:id` | `Delete()` | `package.go` | 47-53 | | `PATCH /packages/:id/status` | `UpdateStatus()` | `package.go` | 55-61 | | `PATCH /packages/:id/shelf` | `UpdateShelfStatus()` | `package.go` | 63-69 | | `PATCH /packages/:id/retail-price` | `UpdateRetailPrice()` | `package.go` | 71-77 | --- ## 🔍 关键代码片段 ### 1. 套餐周期类型校验 **文件**:`internal/service/package/service.go:65-80` **用途**:创建套餐时验证 `calendar_type` 和 `duration_days` 的配合 ```go if calendarType == constants.PackageCalendarTypeByDay { if req.DurationDays == nil || *req.DurationDays <= 0 { return nil, errors.New(errors.CodeInvalidParam, "按天套餐必须提供有效的duration_days") } } ``` ### 2. 虚流量配置校验 **文件**:`internal/service/package/service.go:51-63` **用途**:验证虚流量配置的合法性 ```go if req.EnableVirtualData { if *req.VirtualDataMB > realDataMB { return nil, errors.New(errors.CodeInvalidParam, "虚流量额度不能大于真流量额度") } } ``` ### 3. 代理用户套餐过滤 **文件**:`internal/store/postgres/package_store.go:57-66` **用途**:代理用户只能看到已分配的套餐 ```go if isAgent { query = query.Joins("INNER JOIN tb_shop_package_allocation ..."). Where("tb_shop_package_allocation.shop_id = ? AND tb_shop_package_allocation.status = ?", shopID, constants.StatusEnabled) } ``` --- ## 📊 数据流向 ``` HTTP 请求 ↓ PackageHandler (internal/handler/admin/package.go) ↓ PackageService (internal/service/package/service.go) ├─ 业务逻辑校验 ├─ 调用 PackageStore └─ 返回 DTO ↓ PackageStore (internal/store/postgres/package_store.go) ├─ 数据库查询 └─ 返回 Model ↓ HTTP 响应 (DTO) ``` --- ## 🛠️ 常见操作 ### 添加新的套餐字段 1. **Model 层**:`internal/model/package.go` 的 `Package` 结构体 2. **DTO 层**:`internal/model/dto/package_dto.go` 的相关 Request/Response 3. **Service 层**:`internal/service/package/service.go` 的业务逻辑 4. **Store 层**:`internal/store/postgres/package_store.go` 的查询条件 5. **数据库**:迁移文件中添加新列 ### 修改套餐 API 响应 1. 修改 `PackageResponse` 结构体(`package_dto.go:71-99`) 2. 修改 Service 的转换逻辑(`service.go` 中的 `toDTO()` 方法) 3. 测试 API 端点 ### 添加新的套餐 API 端点 1. 在 `PackageHandler` 中添加方法(`internal/handler/admin/package.go`) 2. 在 `PackageService` 中添加业务逻辑(`internal/service/package/service.go`) 3. 在 `registerPackageRoutes()` 中注册路由(`internal/routes/package.go`) --- ## 📝 相关文档 - **套餐系统升级**:`docs/package-system-upgrade/` - **套餐与佣金业务模型**:`docs/commission-package-model.md` - **API 文档生成规范**:`docs/api-documentation-guide.md` --- ## 🔗 相关模块 | 模块 | 说明 | 文件 | |------|------|------| | **PackageSeries** | 套餐系列管理 | `internal/routes/package_series.go` | | **PackageUsage** | 套餐使用记录 | `internal/routes/package_usage.go` | | **ShopPackageAllocation** | 套餐分配给代理 | `internal/store/postgres/shop_package_allocation_store.go` | | **ShopSeriesAllocation** | 系列分配给代理 | `internal/store/postgres/shop_series_allocation_store.go` |