diff --git a/pkg/service/bundle/bundleBalance.go b/pkg/service/bundle/bundleBalance.go index 624700f..73598f9 100644 --- a/pkg/service/bundle/bundleBalance.go +++ b/pkg/service/bundle/bundleBalance.go @@ -10,9 +10,8 @@ import ( "fonchain-fiee/pkg/service" "log" "io" - "os" - "reflect" "strconv" + "strings" "time" bundleModel "fonchain-fiee/pkg/model/bundle" @@ -277,98 +276,23 @@ func BundleExport(ctx *gin.Context) { service.Error(ctx, err) return } + + userInfo := login.GetUserInfoFromC(ctx) + exportFileName := fmt.Sprintf("%d月份余量信息.xlsx", time.Now().Month()) + filePath := fmt.Sprintf("./runtime/%d/%s", userInfo.ID, exportFileName) res, err := service.BundleProvider.BundleBalanceExport(context.Background(), &req) if err != nil { service.Error(ctx, err) return } - - f := excelize.NewFile() - sheet := "Sheet1" - f.NewSheet(sheet) - - // 写入表头 - headers := []string{ - "所属月份", - "用户编号", - "名字", - "手机号", - "支付时间", - "套餐金额", - "增值服务金额", - "支付金额", - "币种", - "手续费", - "套餐视频单价", - "增值视频单价", - "套餐账号总数", - "增值账号总数", - "套餐账号使用数", - "增值账号使用数", - "当前可用套餐视频数", - "当前可用增值视频数", - "当前已用套餐视频数", - "当前已用增值视频数", - "当前作废套餐视频数", - "当前作废增值视频数", - "当月新增套餐视频数", - "当月新增增值视频数", - "当月作废套餐视频数", - "当月作废增值视频数", - "当前可用套餐图文数", - "当前可用增值图文数", - "当前已用套餐图文数", - "当前已用增值图文数", - "当前作废套餐图文数", - "当前作废增值图文数", - "当月新增套餐图文数", - "当月新增增值图文数", - "当月作废套餐图文数", - "当月作废增值图文数", - "当前可用套餐数据分析数", - "当前可用增值数据分析数", - "当前已用套餐数据分析数", - "当前已用增值数据分析数", - "当前作废套餐数据分析数", - "当前作废增值数据分析数", - "当月新增套餐数据分析数", - "当月新增增值数据分析数", - "当月作废套餐数据分析数", - "当月作废增值数据分析数", - "当月手动扩展账号新增数", - "当月手动扩展视频新增数", - "当月手动扩展图文新增数", - "当月手动扩展数据分析新增数", - "当月新增手动扩展时长(天)", - "当月手动扩展账号使用数", - "当月手动扩展视频使用数", - "当月手动扩展图文使用数", - "当月手动扩展数据分析使用数", - } - - for i, h := range headers { - cell, _ := excelize.CoordinatesToCellName(i+1, 1) - f.SetCellValue(sheet, cell, h) - } - - // 写入数据 - for r, item := range res.Data { - row := r + 2 - v := reflect.ValueOf(item) - for c := 0; c < v.NumField(); c++ { - cell, _ := excelize.CoordinatesToCellName(c+1, row) - f.SetCellValue(sheet, cell, v.Field(c).Interface()) - } - } - - path := fmt.Sprintf("%s/%d/%s月余量导出.xlsx", os.TempDir(), time.Now().UnixMilli(), req.Month) - // 保存文件 - if err := f.SaveAs(path); err != nil { - fmt.Println("保存失败:", err) + if err := writeToExcel(filePath, res.Data); err != nil { + service.Error(ctx, err) return } - defer os.Remove(path) - ctx.File(path) + var exportUrl string = fmt.Sprintf("/static/%s", strings.Replace(filePath, "./runtime/", "", 1)) + service.Success(ctx, gin.H{ + "url": exportUrl, + }) } func SetBalanceLayout(ctx *gin.Context) { @@ -399,3 +323,115 @@ func GetBalanceLayout(ctx *gin.Context) { json.Unmarshal([]byte(res.Data), &j) service.Success(ctx, j) } + +func writeToExcel(filename string, items []*bundle.BundleBalanceExportItem) error { + f := excelize.NewFile() + sheet := "Sheet1" + + // 手动表头(顺序与写入字段顺序必须一致) + headers := []string{ + "所属月份", "用户编号", "名字", "手机号", "支付时间", + "套餐金额", "增值服务金额", "支付金额", "币种", "手续费", "套餐视频单价", "增值视频单价", + "套餐账号总数", "增值账号总数", "套餐账号使用数", "增值账号使用数", + "当前可用套餐视频数", "当前可用增值视频数", "当前已用套餐视频数", "当前已用增值视频数", "当前作废套餐视频数", "当前作废增值视频数", "当月新增套餐视频数", "当月新增增值视频数", "当月作废套餐视频数", "当月作废增值视频数", + "当前可用套餐图文数", "当前可用增值图文数", "当前已用套餐图文数", "当前已用增值图文数", "当前作废套餐图文数", "当前作废增值图文数", "当月新增套餐图文数", "当月新增增值图文数", "当月作废套餐图文数", "当月作废增值图文数", + "当前可用套餐数据分析数", "当前可用增值数据分析数", "当前已用套餐数据分析数", "当前已用增值数据分析数", "当前作废套餐数据分析数", "当前作废增值数据分析数", "当月新增套餐数据分析数", "当月新增增值数据分析数", "当月作废套餐数据分析数", "当月作废增值数据分析数", + "当月手动扩展账号新增数", "当月手动扩展视频新增数", "当月手动扩展图文新增数", "当月手动扩展数据分析新增数", "当月新增手动扩展时长(天)", "当月手动扩展账号使用数", "当月手动扩展视频使用数", "当月手动扩展图文使用数", "当月手动扩展数据分析使用数", + } + + // 写表头 + for i, h := range headers { + col, _ := excelize.ColumnNumberToName(i + 1) + cell := col + "1" + if err := f.SetCellValue(sheet, cell, h); err != nil { + return err + } + } + + // 从第2行开始写数据 + for r, it := range items { + row := r + 2 + // 逐列写入(注意顺序必须和 headers 一致) + write := func(colIdx int, v interface{}) error { + col, _ := excelize.ColumnNumberToName(colIdx) + cell := fmt.Sprintf("%s%d", col, row) + return f.SetCellValue(sheet, cell, v) + } + + // 基本信息 + _ = write(1, int(it.Month)) + _ = write(2, it.CustomerNum) + _ = write(3, it.UserName) + _ = write(4, it.UserPhoneNumber) + _ = write(5, it.PayTime) + _ = write(6, float64(it.BundleAmount)) + _ = write(7, float64(it.IncreaseAmount)) + _ = write(8, float64(it.TotalPayAmount)) + _ = write(9, it.Currency) + _ = write(10, it.Fee) + _ = write(11, float64(it.BundleVideoUnitPrice)) + _ = write(12, float64(it.IncreaseVideoUnitPrice)) + + // 账号类 + _ = write(13, int(it.BundleAccountNumber)) + _ = write(14, int(it.IncreaseAccountNumber)) + _ = write(15, int(it.BundleAccountConsumptionNumber)) + _ = write(16, int(it.IncreaseAccountConsumptionNumber)) + + // 视频类 + _ = write(17, int(it.BundleVideoNumber)) + _ = write(18, int(it.IncreaseVideoNumber)) + _ = write(19, int(it.BundleVideoConsumptionNumber)) + _ = write(20, int(it.IncreaseVideoConsumptionNumber)) + _ = write(21, int(it.InvalidBundleVideoNumber)) + _ = write(22, int(it.InvalidIncreaseVideoNumber)) + _ = write(23, int(it.MonthlyNewBundleVideoNumber)) + _ = write(24, int(it.MonthlyNewIncreaseVideoNumber)) + _ = write(25, int(it.MonthlyInvalidBundleVideoNumber)) + _ = write(26, int(it.MonthlyInvalidIncreaseVideoNumber)) + + // 图文类 + _ = write(27, int(it.BundleImageNumber)) + _ = write(28, int(it.IncreaseImageNumber)) + _ = write(29, int(it.BundleImageConsumptionNumber)) + _ = write(30, int(it.IncreaseImageConsumptionNumber)) + _ = write(31, int(it.InvalidBundleImageNumber)) + _ = write(32, int(it.InvalidIncreaseImageNumber)) + _ = write(33, int(it.MonthlyNewBundleImageNumber)) + _ = write(34, int(it.MonthlyNewIncreaseImageNumber)) + _ = write(35, int(it.MonthlyInvalidBundleImageNumber)) + _ = write(36, int(it.MonthlyInvalidIncreaseImageNumber)) + + // 数据分析类 + _ = write(37, int(it.BundleDataAnalysisNumber)) + _ = write(38, int(it.IncreaseDataAnalysisNumber)) + _ = write(39, int(it.BundleDataAnalysisConsumptionNumber)) + _ = write(40, int(it.IncreaseDataAnalysisConsumptionNumber)) + _ = write(41, int(it.InvalidBundleDataAnalysisNumber)) + _ = write(42, int(it.InvalidIncreaseDataAnalysisNumber)) + _ = write(43, int(it.MonthlyNewBundleDataAnalysisNumber)) + _ = write(44, int(it.MonthlyNewIncreaseDataAnalysisNumber)) + _ = write(45, int(it.MonthlyInvalidBundleDataAnalysisNumber)) + _ = write(46, int(it.MonthlyInvalidIncreaseDataAnalysisNumber)) + + // 手动扩展类 + _ = write(47, int(it.MonthlyNewManualAccountNumber)) + _ = write(48, int(it.MonthlyNewManualVideoNumber)) + _ = write(49, int(it.MonthlyNewManualImageNumber)) + _ = write(50, int(it.MonthlyNewManualDataAnalysisNumber)) + _ = write(51, int(it.MonthlyNewDurationNumber)) + _ = write(52, int(it.MonthlyManualAccountConsumptionNumber)) + _ = write(53, int(it.MonthlyManualVideoConsumptionNumber)) + _ = write(54, int(it.MonthlyManualImageConsumptionNumber)) + _ = write(55, int(it.MonthlyManualDataAnalysisConsumptionNumber)) + } + + // 可选:设置列宽,使表格更美观 + _ = f.SetColWidth(sheet, "A", "AZ", 15) + + // 保存文件 + if err := f.SaveAs(filename); err != nil { + return err + } + return nil +}