diff --git a/docs/admin-openapi.yaml b/docs/admin-openapi.yaml index 4bd0dbc..4df0cdd 100644 --- a/docs/admin-openapi.yaml +++ b/docs/admin-openapi.yaml @@ -979,6 +979,9 @@ components: description: 创建时间 format: date-time type: string + enable_virtual_data: + description: 是否启用虚流量(按套餐使用记录快照返回) + type: boolean expires_at: description: 到期时间(待生效套餐为空) format: date-time diff --git a/docs/asset-detail-refactor-api-changes.md b/docs/asset-detail-refactor-api-changes.md index 0364a25..aa2b0bc 100644 --- a/docs/asset-detail-refactor-api-changes.md +++ b/docs/asset-detail-refactor-api-changes.md @@ -157,6 +157,7 @@ | `virtual_total_mb` | int64 | 套餐业务停机阈值 MB | | `virtual_used_mb` | float64 | 套餐展示已用量 MB | | `reduction_pct` | float64 | 展示增幅比例,公式为 `(real_total_mb / virtual_total_mb) - 1` | +| `enable_virtual_data` | bool | 是否启用虚流量(按套餐使用记录快照返回) | | `activated_at` | time | 激活时间 | | `expires_at` | time | 到期时间 | | `master_usage_id` | uint | 主套餐 ID(加油包时有值) | diff --git a/docs/traffic-model-unification/字段替换矩阵.md b/docs/traffic-model-unification/字段替换矩阵.md index cb6c34d..6d1e9b9 100644 --- a/docs/traffic-model-unification/字段替换矩阵.md +++ b/docs/traffic-model-unification/字段替换矩阵.md @@ -41,6 +41,7 @@ | `virtual_remain_mb` | `(data_limit_mb - data_usage_mb) / virtual_ratio` | 删除 | 不再返回 | | `virtual_ratio` | `tb_package.virtual_ratio` | `reduction_pct` | 只保留外部增幅比例 | | 无 | 无 | `package_usage_id` | 保留既有字段 | +| 无 | `tb_package_usage.enable_virtual_data_snapshot` | `enable_virtual_data` | 返回套餐使用记录快照,供前端区分是否启用虚流量 | ### 3.3 后台 `GET /api/admin/assets/:identifier/packages` @@ -53,6 +54,7 @@ | `virtual_remain_mb` | `(data_limit_mb - data_usage_mb) / virtual_ratio` | 删除 | 不再返回 | | `virtual_ratio` | `tb_package.virtual_ratio` | `reduction_pct` | 只保留外部比例 | | `package_usage_id` | `tb_package_usage.id` | `package_usage_id` | 保留,作为记录主键 | +| 无 | `tb_package_usage.enable_virtual_data_snapshot` | `enable_virtual_data` | 返回套餐使用记录快照,供前端区分是否启用虚流量 | ### 3.4 C 端 `GET /api/c/v1/asset/info` diff --git a/docs/traffic-model-unification/接口回放样例.md b/docs/traffic-model-unification/接口回放样例.md index df39074..8aa241f 100644 --- a/docs/traffic-model-unification/接口回放样例.md +++ b/docs/traffic-model-unification/接口回放样例.md @@ -70,7 +70,7 @@ curl -X GET "http://localhost:8080/api/admin/assets//current-package - 有主套餐时仅返回主套餐记录 - 无主套餐时返回 `200 + null` -- 记录字段包含 `package_usage_id + 统一五字段 + reduction_pct` +- 记录字段包含 `package_usage_id + 统一五字段 + reduction_pct + enable_virtual_data` ### 3.3 套餐历史 @@ -81,7 +81,7 @@ curl -X GET "http://localhost:8080/api/admin/assets//packages?page=1 重点核对: -- 列表每条记录都包含 `package_usage_id + 统一五字段 + reduction_pct` +- 列表每条记录都包含 `package_usage_id + 统一五字段 + reduction_pct + enable_virtual_data` - 不再出现 `virtual_limit_mb` / `virtual_remain_mb` / `virtual_ratio` ## 4. C 端接口回放 diff --git a/internal/model/dto/asset_dto.go b/internal/model/dto/asset_dto.go index a026bb5..e6a8494 100644 --- a/internal/model/dto/asset_dto.go +++ b/internal/model/dto/asset_dto.go @@ -99,28 +99,29 @@ type AssetRealtimeStatusResponse struct { // AssetPackageResponse 资产套餐信息 type AssetPackageResponse struct { - PackageUsageID uint `json:"package_usage_id" description:"套餐使用记录ID"` - PackageID uint `json:"package_id" description:"套餐ID"` - PackageName string `json:"package_name" description:"套餐名称"` - PackageType string `json:"package_type" description:"套餐类型:formal/addon"` - OrderID uint `json:"order_id" description:"关联订单ID(无订单分配时为0)"` - OrderNo string `json:"order_no,omitempty" description:"订单号快照(无订单分配时为空)"` - RefundID *uint `json:"refund_id,omitempty" description:"退款主键ID快照(未退款时为空)"` - RefundNo string `json:"refund_no,omitempty" description:"退款单号快照(未退款时为空)"` - UsageType string `json:"usage_type" description:"使用类型:single_card/device"` - Status int `json:"status" description:"状态:0待生效 1生效中 2已用完 3已过期 4已失效"` - StatusName string `json:"status_name" description:"状态名称"` - RealTotalMB int64 `json:"real_total_mb" description:"套餐真实总量(MB)"` - RealUsedMB int64 `json:"real_used_mb" description:"套餐真实已用量(MB)"` - VirtualTotalMB int64 `json:"virtual_total_mb" description:"套餐业务停机阈值(MB)"` - VirtualUsedMB float64 `json:"virtual_used_mb" description:"套餐展示已用量(MB)"` - ReductionPct float64 `json:"reduction_pct" description:"展示增幅比例,公式为(real_total_mb / virtual_total_mb) - 1"` - ActivatedAt *time.Time `json:"activated_at,omitempty" description:"激活时间(待生效套餐为空)"` - ExpiresAt *time.Time `json:"expires_at,omitempty" description:"到期时间(待生效套餐为空)"` - MasterUsageID *uint `json:"master_usage_id,omitempty" description:"主套餐ID(加油包时有值)"` - Priority int `json:"priority" description:"优先级"` - PaidAmount *int64 `json:"paid_amount,omitempty" description:"购买实付金额(分),线下支付或无订单分配时为空"` - CreatedAt time.Time `json:"created_at" description:"创建时间"` + PackageUsageID uint `json:"package_usage_id" description:"套餐使用记录ID"` + PackageID uint `json:"package_id" description:"套餐ID"` + PackageName string `json:"package_name" description:"套餐名称"` + PackageType string `json:"package_type" description:"套餐类型:formal/addon"` + OrderID uint `json:"order_id" description:"关联订单ID(无订单分配时为0)"` + OrderNo string `json:"order_no,omitempty" description:"订单号快照(无订单分配时为空)"` + RefundID *uint `json:"refund_id,omitempty" description:"退款主键ID快照(未退款时为空)"` + RefundNo string `json:"refund_no,omitempty" description:"退款单号快照(未退款时为空)"` + UsageType string `json:"usage_type" description:"使用类型:single_card/device"` + Status int `json:"status" description:"状态:0待生效 1生效中 2已用完 3已过期 4已失效"` + StatusName string `json:"status_name" description:"状态名称"` + RealTotalMB int64 `json:"real_total_mb" description:"套餐真实总量(MB)"` + RealUsedMB int64 `json:"real_used_mb" description:"套餐真实已用量(MB)"` + VirtualTotalMB int64 `json:"virtual_total_mb" description:"套餐业务停机阈值(MB)"` + VirtualUsedMB float64 `json:"virtual_used_mb" description:"套餐展示已用量(MB)"` + ReductionPct float64 `json:"reduction_pct" description:"展示增幅比例,公式为(real_total_mb / virtual_total_mb) - 1"` + EnableVirtualData bool `json:"enable_virtual_data" description:"是否启用虚流量(按套餐使用记录快照返回)"` + ActivatedAt *time.Time `json:"activated_at,omitempty" description:"激活时间(待生效套餐为空)"` + ExpiresAt *time.Time `json:"expires_at,omitempty" description:"到期时间(待生效套餐为空)"` + MasterUsageID *uint `json:"master_usage_id,omitempty" description:"主套餐ID(加油包时有值)"` + Priority int `json:"priority" description:"优先级"` + PaidAmount *int64 `json:"paid_amount,omitempty" description:"购买实付金额(分),线下支付或无订单分配时为空"` + CreatedAt time.Time `json:"created_at" description:"创建时间"` } // AssetPackagesResult 套餐列表分页结果 diff --git a/internal/service/asset/service.go b/internal/service/asset/service.go index 0894e1f..b6b1553 100644 --- a/internal/service/asset/service.go +++ b/internal/service/asset/service.go @@ -730,28 +730,29 @@ func (s *Service) GetPackages(ctx context.Context, assetType string, id uint, pa pkgType = pkg.PackageType } item := &dto.AssetPackageResponse{ - PackageUsageID: u.ID, - PackageID: u.PackageID, - PackageName: pkgName, - PackageType: pkgType, - OrderID: u.OrderID, - OrderNo: u.OrderNo, - RefundID: u.RefundID, - RefundNo: u.RefundNo, - UsageType: u.UsageType, - Status: u.Status, - StatusName: packageStatusName(u.Status), - RealTotalMB: metrics.RealTotalMB, - RealUsedMB: metrics.RealUsedMB, - VirtualTotalMB: metrics.VirtualTotalMB, - VirtualUsedMB: metrics.VirtualUsedMB, - ReductionPct: metrics.ReductionPct, - ActivatedAt: u.ActivatedAt, - ExpiresAt: u.ExpiresAt, - MasterUsageID: u.MasterUsageID, - Priority: u.Priority, - PaidAmount: u.PaidAmount, - CreatedAt: u.CreatedAt, + PackageUsageID: u.ID, + PackageID: u.PackageID, + PackageName: pkgName, + PackageType: pkgType, + OrderID: u.OrderID, + OrderNo: u.OrderNo, + RefundID: u.RefundID, + RefundNo: u.RefundNo, + UsageType: u.UsageType, + Status: u.Status, + StatusName: packageStatusName(u.Status), + RealTotalMB: metrics.RealTotalMB, + RealUsedMB: metrics.RealUsedMB, + VirtualTotalMB: metrics.VirtualTotalMB, + VirtualUsedMB: metrics.VirtualUsedMB, + ReductionPct: metrics.ReductionPct, + EnableVirtualData: u.EnableVirtualDataSnapshot, + ActivatedAt: u.ActivatedAt, + ExpiresAt: u.ExpiresAt, + MasterUsageID: u.MasterUsageID, + Priority: u.Priority, + PaidAmount: u.PaidAmount, + CreatedAt: u.CreatedAt, } all = append(all, item) } @@ -808,28 +809,29 @@ func (s *Service) GetCurrentPackage(ctx context.Context, assetType string, id ui pkgType = pkg.PackageType } return &dto.AssetPackageResponse{ - PackageUsageID: usage.ID, - PackageID: usage.PackageID, - PackageName: pkgName, - PackageType: pkgType, - OrderID: usage.OrderID, - OrderNo: usage.OrderNo, - RefundID: usage.RefundID, - RefundNo: usage.RefundNo, - UsageType: usage.UsageType, - Status: usage.Status, - StatusName: packageStatusName(usage.Status), - RealTotalMB: metrics.RealTotalMB, - RealUsedMB: metrics.RealUsedMB, - VirtualTotalMB: metrics.VirtualTotalMB, - VirtualUsedMB: metrics.VirtualUsedMB, - ReductionPct: metrics.ReductionPct, - ActivatedAt: usage.ActivatedAt, - ExpiresAt: usage.ExpiresAt, - MasterUsageID: usage.MasterUsageID, - Priority: usage.Priority, - PaidAmount: usage.PaidAmount, - CreatedAt: usage.CreatedAt, + PackageUsageID: usage.ID, + PackageID: usage.PackageID, + PackageName: pkgName, + PackageType: pkgType, + OrderID: usage.OrderID, + OrderNo: usage.OrderNo, + RefundID: usage.RefundID, + RefundNo: usage.RefundNo, + UsageType: usage.UsageType, + Status: usage.Status, + StatusName: packageStatusName(usage.Status), + RealTotalMB: metrics.RealTotalMB, + RealUsedMB: metrics.RealUsedMB, + VirtualTotalMB: metrics.VirtualTotalMB, + VirtualUsedMB: metrics.VirtualUsedMB, + ReductionPct: metrics.ReductionPct, + EnableVirtualData: usage.EnableVirtualDataSnapshot, + ActivatedAt: usage.ActivatedAt, + ExpiresAt: usage.ExpiresAt, + MasterUsageID: usage.MasterUsageID, + Priority: usage.Priority, + PaidAmount: usage.PaidAmount, + CreatedAt: usage.CreatedAt, }, nil }