248 lines
9.2 KiB
Markdown
248 lines
9.2 KiB
Markdown
# 需求14:导出功能
|
||
|
||
> 复用现有 ExportTask 体系(`tb_export_task` + Asynq)
|
||
|
||
---
|
||
|
||
## 导出模块总览
|
||
|
||
| 编号 | 模块 | 新增/修改 |
|
||
|------|------|---------|
|
||
| EXPD-001~003 | IoT卡导出 | 新增套餐名称、使用流量、剩余流量字段 |
|
||
| 6.8.2 | 代理资金概况-预充值钱包流水导出 | **全新** |
|
||
| 6.8.3 | 套餐列表导出 | **全新** |
|
||
| 6.8.4 | 退款管理退款列表导出 | **全新** |
|
||
| 6.8.5 | 换货管理导出 | **全新** |
|
||
| 6.8.6 | 代理充值导出 | **全新**(去掉"支付通道"字段) |
|
||
|
||
---
|
||
|
||
## 现有导出体系说明
|
||
|
||
系统已有异步导出框架(`internal/exporter/`):
|
||
- `tb_export_task` 表记录导出任务
|
||
- 导出逻辑通过 `DataSource` 接口实现,每个场景一个文件(如 `iot_card_scene.go`)
|
||
- `registry.go` 的 `NewDefaultRegistry()` 统一注册所有场景
|
||
- Asynq Worker 根据任务里的 `scene` 字段,从 Registry 取对应 DataSource 执行
|
||
- 前端轮询任务状态后下载
|
||
|
||
新增导出模块需要:
|
||
1. 在 `pkg/constants/constants.go` 新增 `ExportTaskSceneXxx` 场景常量
|
||
2. 在 `internal/exporter/` 新建 `xxx_scene.go`,实现 `DataSource` 接口(`Scene()`/`Count()`/`Headers()`/`Fetch()`)
|
||
3. 在 `registry.go` 的 `NewDefaultRegistry()` 中注册,并更新 `IsSupportedScene()`
|
||
4. 新增对应的 Export API(创建导出任务,传入 `scene` 字段)
|
||
|
||
---
|
||
|
||
## EXPD-001~003:IoT卡导出字段新增
|
||
|
||
**修改文件**:`internal/exporter/iot_card_scene.go`
|
||
|
||
在 `Headers()` 末尾追加三列,`Fetch()` 的 `Select` 追加字段,`iotCardExportRow` 追加字段:
|
||
|
||
```go
|
||
// Headers() 新增
|
||
"套餐名称", "使用流量(MB)", "剩余流量(MB)"
|
||
|
||
// baseQuery() 或 Fetch() 新增 JOIN
|
||
LEFT JOIN LATERAL (
|
||
SELECT pu.package_id, pu.data_usage_mb, pu.data_limit_mb, p.package_name
|
||
FROM tb_package_usage pu
|
||
JOIN tb_package p ON p.id = pu.package_id AND p.deleted_at IS NULL
|
||
WHERE pu.iot_card_id = c.id AND pu.status = 1
|
||
AND pu.master_usage_id IS NULL AND pu.deleted_at IS NULL
|
||
LIMIT 1
|
||
) AS pkg ON TRUE
|
||
|
||
// iotCardExportRow 新增
|
||
PackageName string `gorm:"column:package_name"`
|
||
DataUsageMB int64 `gorm:"column:data_usage_mb"`
|
||
DataLimitMB int64 `gorm:"column:data_limit_mb"`
|
||
```
|
||
|
||
剩余流量 = `DataLimitMB - DataUsageMB`(在行转换时计算)
|
||
|
||
---
|
||
|
||
## 6.8.2:代理资金概况-预充值钱包流水导出
|
||
|
||
**新增接口**:`POST /admin/agent-wallet-transactions/export`
|
||
|
||
支持与现有钱包流水列表相同的筛选条件,异步生成 Excel。
|
||
|
||
导出字段映射:
|
||
|
||
| 字段 | 数据来源 |
|
||
|------|---------|
|
||
| 店铺名称 | JOIN `tb_shop` |
|
||
| 交易类型 | `transaction_type`(充值/扣款/退款等,中文化) |
|
||
| 交易金额 | `amount / 100` 转元 |
|
||
| 状态 | `status` 中文化 |
|
||
| 资产类型 | `asset_type` 中文化 |
|
||
| 资产标识 | `asset_identifier` |
|
||
| 交易时间 | `created_at` |
|
||
| 交易前金额 | `balance_before / 100` |
|
||
| 交易后金额 | `balance_after / 100` |
|
||
| 购买套餐名称 | `metadata` 中 JSON 字段 `package_name`,或 JOIN 订单 |
|
||
| 操作人 | JOIN `tb_account`(`creator` 字段关联 `tb_account.id`,取 `username`) |
|
||
| 交易 ID | `id` |
|
||
| 关联业务订单号 | `reference_id` 对应的单号(JOIN 对应表) |
|
||
| 交易渠道/支付方式 | `metadata` 中 `payment_method` 字段 |
|
||
|
||
---
|
||
|
||
## 6.8.3:套餐列表导出
|
||
|
||
**新增接口**:`POST /admin/packages/export`
|
||
|
||
支持现有套餐列表筛选条件。
|
||
|
||
导出字段(按需求文档 24 个字段):
|
||
|
||
```go
|
||
type PackageExportRow struct {
|
||
PackageCode string `xlsx:"套餐编码"`
|
||
PackageName string `xlsx:"套餐名称"`
|
||
SeriesName string `xlsx:"套餐系列名称"` // JOIN tb_package_series
|
||
PackageType string `xlsx:"套餐类型"` // formal/addon 中文化
|
||
DurationMonths int `xlsx:"套餐时长(月)"`
|
||
DurationDaysDesc string `xlsx:"套餐时长说明"` // 剩余天数说明
|
||
CalendarType string `xlsx:"套餐周期类型"`
|
||
DurationDays int `xlsx:"套餐天数"`
|
||
RealDataMB int64 `xlsx:"真流量额度(MB)"`
|
||
VirtualDataMB int64 `xlsx:"虚流量额度(MB)"`
|
||
EnableVirtualData string `xlsx:"是否启用虚流量"` // 是/否
|
||
VirtualRatio float64 `xlsx:"虚流量比例"`
|
||
DataResetCycle string `xlsx:"流量重置周期"`
|
||
ExpiryBase string `xlsx:"到期时间基准"`
|
||
CostPrice string `xlsx:"成本价(元)"` // 分→元
|
||
SuggestedRetailPrice string `xlsx:"建议售价(元)"`
|
||
PriceConfigStatus string `xlsx:"价格配置状态"`
|
||
Status string `xlsx:"状态"`
|
||
ShelfStatus string `xlsx:"上架状态"`
|
||
IsGift string `xlsx:"是否赠送套餐"`
|
||
CreatorID uint `xlsx:"创建人ID"`
|
||
UpdaterID uint `xlsx:"更新人ID"`
|
||
CreatedAt string `xlsx:"创建时间"`
|
||
UpdatedAt string `xlsx:"更新时间"`
|
||
DeletedAt string `xlsx:"删除时间"`
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6.8.4:退款管理退款列表导出
|
||
|
||
**新增接口**:`POST /admin/refund-orders/export`
|
||
|
||
导出字段(去掉"退款到账方式",保留其余字段,部门领导/财务审批人依赖审批流):
|
||
|
||
```go
|
||
type RefundExportRow struct {
|
||
RefundNo string `xlsx:"退款单号"`
|
||
ShopName string `xlsx:"代理店铺名称"`
|
||
PaymentOrderNo string `xlsx:"关联的支付订单号"`
|
||
AssetType string `xlsx:"资产类型"`
|
||
AssetIdentifier string `xlsx:"资产标识"`
|
||
PackageName string `xlsx:"套餐名称"`
|
||
OriginalAmount string `xlsx:"原订单金额"`
|
||
ActualAmount string `xlsx:"实收金额"`
|
||
RefundableAmount string `xlsx:"可退金额"`
|
||
AppliedAmount string `xlsx:"申请退款金额"`
|
||
ActualRefundAmount string `xlsx:"实际退款金额"`
|
||
Status string `xlsx:"状态"`
|
||
RefundReason string `xlsx:"退款原因"`
|
||
Remark string `xlsx:"备注"`
|
||
ApprovalRemark string `xlsx:"审批备注"`
|
||
AppliedAt string `xlsx:"退款申请时间"`
|
||
CompletedAt string `xlsx:"退款完成时间"`
|
||
SubmitterName string `xlsx:"提交人"`
|
||
DeptLeaderName string `xlsx:"部门领导审批人"`
|
||
FinanceName string `xlsx:"财务审批人"`
|
||
VoucherURLs string `xlsx:"退款凭证"`
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6.8.5:换货管理导出
|
||
|
||
**新增接口**:`POST /admin/exchange-orders/export`
|
||
|
||
```go
|
||
type ExchangeExportRow struct {
|
||
ExchangeNo string `xlsx:"换货单号"`
|
||
ExchangeType string `xlsx:"换货类型"`
|
||
ExchangeReason string `xlsx:"换货原因"`
|
||
ProblemDesc string `xlsx:"问题描述"`
|
||
OldAssetType string `xlsx:"旧资产类型"`
|
||
OldAssetIdentifier string `xlsx:"旧资产标识符"`
|
||
NewAssetIdentifier string `xlsx:"新资产标识符"`
|
||
ReceiverName string `xlsx:"收货人姓名"`
|
||
ReceiverPhone string `xlsx:"收货人电话"`
|
||
ReceiverAddress string `xlsx:"收货地址"`
|
||
ExpressCompany string `xlsx:"快递公司"`
|
||
TrackingNo string `xlsx:"快递单号"`
|
||
Status string `xlsx:"状态"`
|
||
CreatorName string `xlsx:"创建人"`
|
||
CreatedAt string `xlsx:"创建时间"`
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6.8.6:代理充值导出
|
||
|
||
**新增接口**:`POST /admin/agent-recharge-orders/export`
|
||
|
||
去掉"支付通道"字段(需求文档中明确去掉),保留其他字段:
|
||
|
||
```go
|
||
type AgentRechargeExportRow struct {
|
||
RechargeNo string `xlsx:"充值单号"`
|
||
ShopName string `xlsx:"店铺名称"`
|
||
RechargeType string `xlsx:"充值类型"`
|
||
RechargeAmount string `xlsx:"充值金额"`
|
||
ActualAmount string `xlsx:"实付金额"`
|
||
BalanceBefore string `xlsx:"充值前余额"`
|
||
BalanceAfter string `xlsx:"充值后余额"`
|
||
Status string `xlsx:"状态"`
|
||
PaymentMethod string `xlsx:"支付方式"`
|
||
// 去掉支付通道
|
||
OperationRemark string `xlsx:"运营备注"`
|
||
RejectReason string `xlsx:"驳回原因"`
|
||
CreatedAt string `xlsx:"创建时间"`
|
||
PaidAt string `xlsx:"支付时间"`
|
||
CompletedAt string `xlsx:"完成时间"`
|
||
SubmitterName string `xlsx:"提交人"`
|
||
DeptLeaderName string `xlsx:"部门领导审批人"`
|
||
FinanceName string `xlsx:"财务审批人"`
|
||
VoucherURLs string `xlsx:"支付凭证"`
|
||
Remark string `xlsx:"备注"`
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 前端对接(通用模式)
|
||
|
||
各导出入口:对应列表页右上角"导出"按钮(与现有导出按钮样式一致)。
|
||
|
||
调用流程:
|
||
1. 点击"导出" → 携带当前筛选条件 → `POST /admin/{module}/export`
|
||
2. 返回 `export_task_id`
|
||
3. 前端轮询 `GET /admin/export-tasks/{id}` 直到 `status=completed`
|
||
4. 下载 `download_url`
|
||
|
||
(与现有导出体系完全一致,复用现有前端导出 Hook)
|
||
|
||
---
|
||
|
||
## 权限导出配置(预留)
|
||
|
||
需求提到"不同权限显示的字段不同,角色管理中新增导出字段配置"。
|
||
|
||
**本次迭代**:统一导出全量字段,不做权限差异化(复杂度高,单独排期)。
|
||
|
||
**预留方案**:在导出 Handler 里预留 `filterFieldsByRole(userRoles, rows)` 的调用点,本次返回全量,后续加权限配置后在此处过滤。
|