112 lines
4.3 KiB
Go
112 lines
4.3 KiB
Go
package business
|
||
|
||
import (
|
||
"context"
|
||
"strconv"
|
||
|
||
"github.com/xuri/excelize/v2"
|
||
"kra/internal/service/dto"
|
||
)
|
||
|
||
type ledgerCell struct {
|
||
value string
|
||
numeric bool
|
||
}
|
||
|
||
func textCell(value string) ledgerCell { return ledgerCell{value: value} }
|
||
func numericCell(value string) ledgerCell { return ledgerCell{value: value, numeric: true} }
|
||
func optionalNumber[T ~int | ~int64](value *T) ledgerCell {
|
||
if value == nil {
|
||
return textCell("")
|
||
}
|
||
return numericCell(strconv.FormatInt(int64(*value), 10))
|
||
}
|
||
func optionalID(value *int64) ledgerCell {
|
||
if value == nil {
|
||
return textCell("")
|
||
}
|
||
return textCell(strconv.FormatInt(*value, 10))
|
||
}
|
||
func optionalMoney(value *string) ledgerCell {
|
||
if value == nil {
|
||
return textCell("")
|
||
}
|
||
return numericCell(*value)
|
||
}
|
||
func ledgerWorkbook(sheet string, headers []string, rows [][]ledgerCell) ([]byte, error) {
|
||
file := excelize.NewFile()
|
||
defer file.Close()
|
||
if err := file.SetSheetName(file.GetSheetName(0), sheet); err != nil {
|
||
return nil, err
|
||
}
|
||
for i, label := range headers {
|
||
cell, _ := excelize.CoordinatesToCellName(i+1, 1)
|
||
if err := file.SetCellStr(sheet, cell, label); err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
for i, row := range rows {
|
||
for j, value := range row {
|
||
cell, _ := excelize.CoordinatesToCellName(j+1, i+2)
|
||
var err error
|
||
// 金额直接写入数值 XML,避免先转 float64;文本始终作为文本,保留订单号前导零。
|
||
if value.numeric {
|
||
err = file.SetCellDefault(sheet, cell, value.value)
|
||
} else {
|
||
err = file.SetCellStr(sheet, cell, value.value)
|
||
}
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
}
|
||
last, _ := excelize.ColumnNumberToName(len(headers))
|
||
// 流式读取器依赖 dimension;Excelize 的初始 A1 范围不会随写入单元格自动扩展。
|
||
if err := file.SetSheetDimension(sheet, "A1:"+last+strconv.Itoa(len(rows)+1)); err != nil {
|
||
return nil, err
|
||
}
|
||
if err := file.SetColWidth(sheet, "A", last, 20); err != nil {
|
||
return nil, err
|
||
}
|
||
if err := file.SetPanes(sheet, &excelize.Panes{Freeze: true, YSplit: 1, TopLeftCell: "A2", ActivePane: "bottomLeft"}); err != nil {
|
||
return nil, err
|
||
}
|
||
buffer, err := file.WriteToBuffer()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return buffer.Bytes(), nil
|
||
}
|
||
func (s *LedgerService) ExportRegistrations(ctx context.Context, req *dto.LedgerQuery) ([]byte, error) {
|
||
f, _, err := ledgerRequest(req, false)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
items, err := s.uc.ExportRegistrations(ctx, f)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
rows := make([][]ledgerCell, 0, len(items))
|
||
for _, item := range items {
|
||
r := registrationResponse(item)
|
||
rows = append(rows, []ledgerCell{textCell(r.SourceDB), textCell(r.SourceDBLabel), textCell(strconv.FormatUint(r.ID, 10)), textCell(strconv.FormatUint(r.UserID, 10)), optionalNumber(r.RegisterTime), optionalID(r.FirstGameID), textCell(r.FirstGameName), optionalMoney(r.TotalPayAmount), textCell(r.RegisterIP), textCell(r.DeviceName), textCell(r.PromoteAccount), optionalID(r.PromoteID), textCell(r.BusierName)})
|
||
}
|
||
return ledgerWorkbook("注册明细", []string{"sourceDb", "所属平台", "ID", "玩家ID", "注册时间", "fgameId", "游戏", "累计充值", "注册IP", "机型", "渠道", "promoteId", "所属商务"}, rows)
|
||
}
|
||
func (s *LedgerService) ExportSpends(ctx context.Context, req *dto.LedgerQuery) ([]byte, error) {
|
||
f, _, err := ledgerRequest(req, true)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
items, err := s.uc.ExportSpends(ctx, f)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
rows := make([][]ledgerCell, 0, len(items))
|
||
for _, item := range items {
|
||
r := spendResponse(item)
|
||
rows = append(rows, []ledgerCell{textCell(r.SourceDB), textCell(r.SourceDBLabel), textCell(strconv.FormatUint(r.ID, 10)), optionalID(r.UserID), textCell(r.OrderNumber), optionalID(r.GameID), textCell(r.GameName), textCell(r.ServerID), textCell(r.ServerName), textCell(r.PlayerName), optionalMoney(r.PayAmount), optionalNumber(r.PayTime), optionalNumber(r.PayWay), optionalNumber(r.PayStatus), textCell(r.IP), textCell(r.PromoteAccount), optionalID(r.PromoteID), textCell(r.BusierName)})
|
||
}
|
||
return ledgerWorkbook("充值明细", []string{"sourceDb", "所属平台", "ID", "玩家ID", "订单号", "gameId", "游戏", "serverId", "区服", "角色", "实付金额", "完成时间", "方式", "状态", "IP", "渠道", "promoteId", "所属商务"}, rows)
|
||
}
|