fonchain-fiee/pkg/service/bundle/bundleBalance.go
2025-10-17 15:32:57 +08:00

439 lines
13 KiB
Go

package bundle
import (
"context"
"encoding/json"
"errors"
"fmt"
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/cast"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/utils"
"io"
"strconv"
"strings"
"time"
bundleModel "fonchain-fiee/pkg/model/bundle"
"fonchain-fiee/pkg/model/login"
"github.com/gin-gonic/gin"
"github.com/xuri/excelize/v2"
)
func BundleExtend(c *gin.Context) {
var req bundle.BundleExtendRequest
userInfo := login.GetUserInfoFromC(c)
req.Type = 1 // 设置未手动扩展'
req.OperatorName = userInfo.Name
req.OperatorPhoneNumber = userInfo.TelNum
req.OperatorId = userInfo.ID
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.BundleExtend(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func BundleExtendRecordsList(c *gin.Context) {
var req bundle.BundleExtendRecordsListRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.BundleExtendRecordsList(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func GetBundleBalance(c *gin.Context) {
var req bundle.GetBundleBalanceListReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetBundleBalanceList(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func GetUsedRecordList(c *gin.Context) {
var req bundle.GetUsedRecordListReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetUsedRecordList(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func GetWorkDetail(c *gin.Context) {
var req cast.WorkDetailReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
// userInfo := login.GetUserInfoFromC(c)
// res, err := service.BundleProvider.GetBundleBalanceByUserId(context.TODO(), &bundle.GetBundleBalanceByUserIdReq{
// UserId: int32(userInfo.ID),
// })
// if err != nil {
// service.Error(c, err)
// return
// }
// if res.ExpiredTime <= time.Now().UnixMilli() {
// service.Success(c, gin.H{
// "status": 1,
// "message": "套餐过期请重新购买",
// })
// return
// }
workRes, err := service.CastProvider.WorkDetail(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
// if len(workRes.Images) > 0 && res.ImageConsumptionNumber >= res.ImageNumber { // 图片用尽
// service.Success(c, gin.H{
// "status": 2,
// "message": "增值服务已用尽",
// })
// return
// } else {
// if res.VideoConsumptionNumber >= res.VideoNumber { // 视频用尽
// service.Success(c, gin.H{
// "status": 2,
// "message": "增值服务已用尽",
// })
// return
// }
// }
service.Success(c, workRes)
}
func GetToBeComfirmedWorks(c *gin.Context) {
var req bundle.ToBeComfirmedWorksReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
userInfo := login.GetUserInfoFromC(c)
req.ArtistUuid = strconv.Itoa(int(userInfo.ID))
res, err := service.BundleProvider.ToBeComfirmedWorks(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func GetUserBalance(c *gin.Context) {
userInfo := login.GetUserInfoFromC(c)
res, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
UserId: int32(userInfo.ID),
})
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func WorkConfirm(c *gin.Context) { // 确认作品并扣除余量
var req bundleModel.UserWorkConfirmReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
if req.ConfirmStatus == 2 { // 驳回完直接结束
res, err := service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 2,
})
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
return
}
userInfo := login.GetUserInfoFromC(c)
balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
UserId: int32(userInfo.ID),
})
if err != nil {
service.Error(c, err)
return
}
wordInfoRes, err := service.CastProvider.WorkDetail(c, &cast.WorkDetailReq{
WorkUuid: req.WorkUuid,
})
if err != nil {
service.Error(c, err)
return
}
if wordInfoRes.WorkStatus != 4 {
service.Error(c, errors.New("作品不是待确认状态"))
return
}
var workCategory = wordInfoRes.WorkCategory
var addBalanceReq bundle.AddBundleBalanceReq
addBalanceReq.UserId = int32(userInfo.ID)
switch workCategory {
case 1:
{
if balanceInfoRes.ImageConsumptionNumber >= balanceInfoRes.ImageNumber { // 图文余量不足
service.Error(c, errors.New("图文余量不足"))
return
}
addBalanceReq.ImageConsumptionNumber = 1
}
case 2:
{
if balanceInfoRes.VideoConsumptionNumber >= balanceInfoRes.VideoNumber { // 视频余量不足
service.Error(c, errors.New("视频余量不足"))
return
}
addBalanceReq.VideoConsumptionNumber = 1
}
default:
service.Error(c, errors.New("不支持的类型"))
return
}
_, err = service.BundleProvider.AddBundleBalance(c, &addBalanceReq)
if err != nil {
service.Error(c, err)
return
}
res, err := service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 1,
})
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func CastLogConfirm(ctx *gin.Context) {
var req bundle.ConfirmWorkReq
if err := ctx.ShouldBindJSON(&req); err != nil {
service.Error(ctx, err)
return
}
res, err := service.BundleProvider.ConfirmWork(context.Background(), &req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, res)
}
func BundleActivate(ctx *gin.Context) {
var req bundle.BundleActivateReq
if err := ctx.ShouldBindJSON(&req); err != nil {
service.Error(ctx, err)
return
}
res, err := service.BundleProvider.BundleActivate(context.Background(), &req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, res)
}
func BundleExport(ctx *gin.Context) {
var req bundle.BundleBalanceExportReq
if err := ctx.ShouldBindJSON(&req); err != nil {
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)
utils.CheckDirPath("./runtime/"+fmt.Sprint(userInfo.ID), true)
res, err := service.BundleProvider.BundleBalanceExport(context.Background(), &req)
if err != nil {
service.Error(ctx, err)
return
}
if err := writeToExcel(filePath, res.Data); err != nil {
service.Error(ctx, err)
return
}
var exportUrl string = fmt.Sprintf("%s:%s/api/fiee/static/%s",ctx.Request.URL.Scheme, ctx.Request.Host,strings.Replace(filePath, "./runtime/", "", 1))
service.Success(ctx, gin.H{
"url": exportUrl,
})
}
func SetBalanceLayout(ctx *gin.Context) {
b, _ := io.ReadAll(ctx.Request.Body)
userInfo := login.GetUserInfoFromC(ctx)
var req = bundle.SetBundleBalanceLayoutReq{
Data: string(b),
UserId: uint32(userInfo.ID),
}
res, err := service.BundleProvider.SetBundleBalanceLayout(context.Background(), &req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, res)
}
func GetBalanceLayout(ctx *gin.Context) {
userInfo := login.GetUserInfoFromC(ctx)
var req = bundle.GetBundleBalanceLayoutReq{
UserId: uint32(userInfo.ID),
}
res, err := service.BundleProvider.GetBundleBalanceLayout(context.Background(), &req)
if err != nil {
service.Error(ctx, err)
return
}
var j any
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
}