Compare commits

...

12 Commits

13 changed files with 146 additions and 79 deletions

View File

@ -5,9 +5,9 @@ server:
ollama: ollama:
base_url: "http://172.17.0.1:11434" base_url: "http://172.17.0.1:11434"
# model: "qwen3:8b" # model: "qwen3:8b"
# generate_model: "qwen3:8b" # generate_model: "qwen3:8b"
# mapping_model: "qwen3:8b" # mapping_model: "qwen3:8b"
model: "qwen3-coder:480b-cloud" model: "qwen3-coder:480b-cloud"
generate_model: "qwen3-coder:480b-cloud" generate_model: "qwen3-coder:480b-cloud"
mapping_model: "deepseek-v3.2:cloud" mapping_model: "deepseek-v3.2:cloud"
@ -149,7 +149,7 @@ eino_tools:
# == 通用工具 == # == 通用工具 ==
# 表格转图片 # 表格转图片
excel2pic: excel2pic:
base_url: "http://excel2pic:8000/api/v1/convert" base_url: "http://192.168.6.115:8010/api/v1/convert"
dingtalk: dingtalk:
api_key: "dingsbbntrkeiyazcfdg" api_key: "dingsbbntrkeiyazcfdg"

View File

@ -26,12 +26,11 @@ coze:
lsxd: lsxd:
# 统一登录 # 统一登录
login_url: "http://api.test.user.1688sup.com/v1/login/phone" login_url: "https://api.user.1688sup.com/v1/login/phone"
phone: "OFJ8UpqOlI7+w3Qklf36ZA==" phone: "ORlviZN7N06W2+WKLe76xg=="
password: "tEbFegH/DRRh6LutFb7o3g==" password: "V5Uh8C4bamEM6UQZh4TCeQ=="
code: "123456" code: "456789"
check_token_url: "http://api.test.user.1688sup.com/v1/user/welcome" check_token_url: "https://api.user.1688sup.com/v1/user/welcome"
sys: sys:
session_len: 6 session_len: 6
@ -142,7 +141,7 @@ eino_tools:
# == 通用工具 == # == 通用工具 ==
# 表格转图片 # 表格转图片
excel2pic: excel2pic:
base_url: "http://192.168.6.109:8010/api/v1/convert" base_url: "http://192.168.6.115:8010/api/v1/convert"
dingtalk: dingtalk:
api_key: "dingsbbntrkeiyazcfdg" api_key: "dingsbbntrkeiyazcfdg"

View File

@ -506,7 +506,7 @@ func handleCozeWorkflowEvents(ctx context.Context, resp coze.Stream[coze.Workflo
case coze.WorkflowEventTypeMessage: case coze.WorkflowEventTypeMessage:
entitys.ResStream(ch, index, event.Message.Content) entitys.ResStream(ch, index, event.Message.Content)
case coze.WorkflowEventTypeError: case coze.WorkflowEventTypeError:
entitys.ResError(ch, index, fmt.Sprintf("工作流执行错误: %s", event.Error)) entitys.ResError(ch, index, fmt.Sprintf("工作流执行错误: %v", event.Error))
case coze.WorkflowEventTypeDone: case coze.WorkflowEventTypeDone:
entitys.ResEnd(ch, index, "工作流执行完成") entitys.ResEnd(ch, index, "工作流执行完成")
case coze.WorkflowEventTypeInterrupt: case coze.WorkflowEventTypeInterrupt:

View File

@ -26,6 +26,7 @@ import (
type Macro struct { type Macro struct {
botGroupImpl *impl.BotGroupImpl botGroupImpl *impl.BotGroupImpl
botGroupConfigImpl *impl.BotGroupConfigImpl
reportDailyCacheImpl *impl.ReportDailyCacheImpl reportDailyCacheImpl *impl.ReportDailyCacheImpl
config *config.Config config *config.Config
rdb *utils.Rdb rdb *utils.Rdb
@ -36,12 +37,14 @@ func NewMacro(
reportDailyCacheImpl *impl.ReportDailyCacheImpl, reportDailyCacheImpl *impl.ReportDailyCacheImpl,
config *config.Config, config *config.Config,
rdb *utils.Rdb, rdb *utils.Rdb,
botGroupConfigImpl *impl.BotGroupConfigImpl,
) *Macro { ) *Macro {
return &Macro{ return &Macro{
botGroupImpl: botGroupImpl, botGroupImpl: botGroupImpl,
reportDailyCacheImpl: reportDailyCacheImpl, reportDailyCacheImpl: reportDailyCacheImpl,
config: config, config: config,
rdb: rdb, rdb: rdb,
botGroupConfigImpl: botGroupConfigImpl,
} }
} }
@ -193,7 +196,7 @@ func (m *Macro) ProductModify(ctx context.Context, content string, groupConfig *
groupConfig.ProductName = itemInfo groupConfig.ProductName = itemInfo
cond := builder.NewCond() cond := builder.NewCond()
cond = cond.And(builder.Eq{"config_id": groupConfig.ConfigID}) cond = cond.And(builder.Eq{"config_id": groupConfig.ConfigID})
err = m.botGroupImpl.UpdateByCond(&cond, groupConfig) err = m.botGroupConfigImpl.UpdateByCond(&cond, groupConfig)
if err != nil { if err != nil {
err = fmt.Errorf("修改失败:%v", err) err = fmt.Errorf("修改失败:%v", err)
return return

View File

@ -0,0 +1,32 @@
package do
import (
"ai_scheduler/internal/config"
"ai_scheduler/internal/data/impl"
"ai_scheduler/internal/data/model"
"ai_scheduler/utils"
"context"
"testing"
)
func Test_report(t *testing.T) {
con := "[利润同比报表]商品修改:官方–优酷周卡,官方–优酷月卡,官方–优酷季卡,官方–优酷年卡,,官方–爱奇艺-月卡,官方–爱奇艺-季卡,官方–爱奇艺-年卡,官方–芒果-PC周卡,官方–芒果-PC月卡,官方–芒果-PC季卡,官方QQ音乐-绿钻月卡,官方–饿了么超级会员月卡,官方网易云黑胶vip月卡,官方喜马拉雅巅峰会员月卡剪映会员7天卡剪映会员月卡剪映会员年卡剪映SVIP会员7天卡剪映SVIP会员月卡剪映SVIP会员年卡"
run()
chatId, err, i := ma.ProductModify(context.Background(), con, &model.AiBotGroupConfig{ConfigID: 1, ToolList: "8,9,10,11,12,13,16"})
t.Log(chatId, err, i)
}
var ma *Macro
func run() {
configConfig, _ := config.LoadConfigWithTest()
db, _ := utils.NewGormDb(configConfig)
rdb := utils.NewRdb(configConfig)
reportDailyCacheImpl := impl.NewReportDailyCacheImpl(db)
botGroupImpl := impl.NewBotGroupImpl(db)
botGroupConfigImpl := impl.NewBotGroupConfigImpl(db)
ma = NewMacro(botGroupImpl, reportDailyCacheImpl, configConfig, rdb, botGroupConfigImpl)
}

View File

@ -98,14 +98,12 @@ func (g *GroupConfigBiz) GetReportLists(ctx context.Context, groupConfig *model.
if err != nil { if err != nil {
return return
} }
//追加电商充值系统统计 - 返回统一使用[]*bbxt.ReportRes //追加电商充值系统统计 - 返回统一使用[]*bbxt.ReportRes
rechargeReports, err := g.rechargeDailyReport(ctx, time.Now(), nil, g.ossClient) rechargeReports, err := g.rechargeDailyReport(ctx, time.Now(), nil, g.ossClient)
if err != nil || len(rechargeReports) == 0 { if err != nil || len(rechargeReports) == 0 {
return return
} }
reports = append(rechargeReports, reports...)
reports = append(reports, rechargeReports...)
return return
} }
@ -175,7 +173,7 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz
if _err != nil { if _err != nil {
return _err return _err
} }
reports = append(reports, repo...) reports = append(reports, repo)
case "report_sales_analysis": case "report_sales_analysis":
product := strings.Split(groupConfig.ProductName, ",") product := strings.Split(groupConfig.ProductName, ",")
repo, _err := rep.GetStatisOfficialProductSum(t, product) repo, _err := rep.GetStatisOfficialProductSum(t, product)
@ -200,8 +198,9 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz
if _err != nil { if _err != nil {
return _err return _err
} }
reports = append(reports, repo...)
reports = append(reports, rechargeReport...) reports = append(reports, rechargeReport...)
reports = append(reports, repo...)
case "report_daily_recharge": case "report_daily_recharge":
product := strings.Split(groupConfig.ProductName, ",") product := strings.Split(groupConfig.ProductName, ",")
repo, _err := g.rechargeDailyReport(ctx, t, product, nil) repo, _err := g.rechargeDailyReport(ctx, t, product, nil)

View File

@ -115,6 +115,7 @@ func (s *SendCardClient) NewCard(ctx context.Context, cardSend *CardSend) error
s.processContentChannel(ctx, cardSend, cardInstanceId.String(), client) s.processContentChannel(ctx, cardSend, cardInstanceId.String(), client)
}() }()
wg.Wait() wg.Wait()
log.Info("处理通道结束")
} }
return nil return nil
@ -163,7 +164,7 @@ func (s *SendCardClient) processContentChannel(ctx context.Context, cardSend *Ca
var ( var (
contentBuilder strings.Builder contentBuilder strings.Builder
lastUpdate time.Time lastUpdate = time.Now()
) )
for { for {
@ -173,6 +174,7 @@ func (s *SendCardClient) processContentChannel(ctx context.Context, cardSend *Ca
// 通道关闭,发送最终内容 // 通道关闭,发送最终内容
if contentBuilder.Len() > 0 { if contentBuilder.Len() > 0 {
if err := s.updateCardContent(ctx, cardSend, cardInstanceId, contentBuilder.String(), client); err != nil { if err := s.updateCardContent(ctx, cardSend, cardInstanceId, contentBuilder.String(), client); err != nil {
log.Info("contentBuilder.Len()修改失败1")
s.logger.Errorf("更新卡片失败1:%s", err.Error()) s.logger.Errorf("更新卡片失败1:%s", err.Error())
} }
} }
@ -181,6 +183,7 @@ func (s *SendCardClient) processContentChannel(ctx context.Context, cardSend *Ca
contentBuilder.WriteString(content) contentBuilder.WriteString(content)
if contentBuilder.Len() > 0 { if contentBuilder.Len() > 0 {
if err := s.updateCardContent(ctx, cardSend, cardInstanceId, contentBuilder.String(), client); err != nil { if err := s.updateCardContent(ctx, cardSend, cardInstanceId, contentBuilder.String(), client); err != nil {
log.Info("contentBuilder.Len()修改失败2")
s.logger.Errorf("更新卡片失败2%s", err.Error()) s.logger.Errorf("更新卡片失败2%s", err.Error())
} }
} }
@ -188,10 +191,12 @@ func (s *SendCardClient) processContentChannel(ctx context.Context, cardSend *Ca
case <-heartbeatTicker.C: case <-heartbeatTicker.C:
if time.Now().Unix()-lastUpdate.Unix() >= HeardBeatX { if time.Now().Unix()-lastUpdate.Unix() >= HeardBeatX {
log.Infof("心跳超时,当前时间:%d,最后时间:%d", time.Now().Unix(), lastUpdate.Unix())
return return
} }
case <-ctx.Done(): case <-ctx.Done():
log.Info("send_card上下文失效")
s.logger.Info("context canceled, stop channel processing") s.logger.Info("context canceled, stop channel processing")
return return
} }

View File

@ -309,7 +309,7 @@ func LoadConfigWithEnv() (*Config, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
viper.SetConfigFile(modularDir + "/config/config_env.yaml") viper.SetConfigFile(modularDir + "/config/config.yaml")
viper.SetConfigType("yaml") viper.SetConfigType("yaml")
// 读取配置文件 // 读取配置文件
if err := viper.ReadInConfig(); err != nil { if err := viper.ReadInConfig(); err != nil {

View File

@ -64,9 +64,15 @@ func (d *DingBotService) runBackgroundTasks(ctx context.Context, data *chatbot.B
g.Go(func() error { g.Go(func() error {
defer func() { defer func() {
// 确保通道最终关闭 // 确保通道最终关闭
log.Println("流式处理协程关闭")
close(resChan) close(resChan)
}() }()
return d.dingTalkBotBiz.HandleStreamRes(ctx, data, resChan) err := d.dingTalkBotBiz.HandleStreamRes(ctx, data, resChan)
if err != nil {
log.Println("流式回复产生错误,错误:", err.Error())
}
return err
}) })
// 2. 业务处理协程负责关闭requireData.Ch // 2. 业务处理协程负责关闭requireData.Ch

View File

@ -13,6 +13,8 @@ import (
"sort" "sort"
"time" "time"
"github.com/shopspring/decimal"
) )
const ( const (
@ -37,6 +39,8 @@ var ResellerBlackListProduct = []string{
"蓝星严选连续包月", "蓝星严选连续包月",
"通钱-2025年12月", "通钱-2025年12月",
"彦浩同行", "彦浩同行",
"运营部测试专用",
"彦浩直客商户",
} }
type BbxtTools struct { type BbxtTools struct {
@ -91,9 +95,7 @@ func (b *BbxtTools) DailyReport(
if err != nil { if err != nil {
return return
} }
reports = append(reports, productLossReport...) reports = append(reports, profitRankingSum, statisOfficialProductSum, statisOfficialProductSumDecline, productLossReport)
reports = append(reports, profitRankingSum, statisOfficialProductSum, statisOfficialProductSumDecline)
if ossClient != nil { if ossClient != nil {
uploader := NewUploader(ossClient, b.config) uploader := NewUploader(ossClient, b.config)
for _, report := range reports { for _, report := range reports {
@ -135,7 +137,9 @@ func (b *BbxtTools) ResellerLossSort(ctx context.Context, now time.Time) ([]*Res
reseller := resellerMap[info.ResellerId] reseller := resellerMap[info.ResellerId]
// 累加经销商总亏损 // 累加经销商总亏损
reseller.Total += info.Loss num1 := decimal.NewFromFloat(reseller.Total)
num2 := decimal.NewFromFloat(info.Loss)
reseller.Total, _ = num1.Add(num2).Round(2).Float64()
// 检查产品是否已存在 // 检查产品是否已存在
if _, ok := reseller.ProductLoss[info.OursProductId]; !ok { if _, ok := reseller.ProductLoss[info.OursProductId]; !ok {
@ -209,61 +213,66 @@ func (b *BbxtTools) ResellerLossToMapResellerLossSumProductRelation(totalDetail
} }
// StatisOursProductLossSum 负利润分析 // StatisOursProductLossSum 负利润分析
func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (report []*ReportRes, err error) { func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (report *ReportRes, err error) {
resellers, err := b.ResellerLossSort(ctx, now) resellers, err := b.ResellerLossSort(ctx, now)
var ( var (
total [][]string total [][]string
gt []*ResellerLoss //gt []*ResellerLoss
totalDetail []*ResellerLoss totalDetail []*ResellerLoss
totalSum float64 totalSum = decimal.NewFromFloat(0)
totalSum500 float64 //totalSum500 float64
) )
// 构建分组 // 构建分组
for _, v := range resellers { for _, v := range resellers {
if v.Total <= -100 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) { if slices.Contains(ResellerBlackListProduct, v.ResellerName) {
continue
}
if v.Total <= -100 {
total = append(total, []string{ total = append(total, []string{
fmt.Sprintf("%s", v.ResellerName), fmt.Sprintf("%s", v.ResellerName),
fmt.Sprintf("%.2f", v.Total), fmt.Sprintf("%.2f", v.Total),
}) })
totalSum += v.Total
totalDetail = append(totalDetail, v) totalDetail = append(totalDetail, v)
} }
if v.Total <= -500 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) { num := decimal.NewFromFloat(v.Total)
gt = append(gt, v) totalSum = totalSum.Add(num).Round(2)
totalSum500 += v.Total //if v.Total <= -500 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) {
} // gt = append(gt, v)
// totalSum500 += v.Total
//}
} }
report = make([]*ReportRes, 3) //report = make([]*ReportRes, 3)
timeCh := now.Format("1月2日15点") timeCh := now.Format("1月2日15点")
//总量生成excel //总量生成excel
if len(total) > 0 { //if len(total) > 0 {
filePath := b.cacheDir + "/kshj_total" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx" // filePath := b.cacheDir + "/kshj_total" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
err = b.SimpleFillExcelWithTitle(b.excelTempDir+"/"+"kshj_total.xlsx", filePath, total, "") // err = b.SimpleFillExcelWithTitle(b.excelTempDir+"/"+"kshj_total.xlsx", filePath, total, "")
if err != nil { // if err != nil {
return // return
} // }
report[0] = &ReportRes{ // report[0] = &ReportRes{
ReportName: "分销商负利润统计", // ReportName: "分销商负利润统计",
Title: "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSum), // Title: "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSum),
Path: filePath, // Path: filePath,
Data: total, // Data: total,
} // }
} //}
//
if len(gt) > 0 { //if len(gt) > 0 {
filePath := b.cacheDir + "/kshj_gt" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx" // filePath := b.cacheDir + "/kshj_gt" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
title := "截至" + timeCh + "亏损500以上的分销商和产品" // title := "截至" + timeCh + "亏损500以上的分销商和产品"
err = b.resellerDetailFillExcelV2(b.excelTempDir+"/"+"kshj_gt.xlsx", filePath, gt, title) // err = b.resellerDetailFillExcelV2(b.excelTempDir+"/"+"kshj_gt.xlsx", filePath, gt, title)
if err != nil { // if err != nil {
return // return
} // }
report[1] = &ReportRes{ // report[1] = &ReportRes{
ReportName: "负利润分析(亏损500以上)", // ReportName: "负利润分析(亏损500以上)",
Title: "截至" + timeCh + "亏损500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500), // Title: "截至" + timeCh + "亏损500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500),
Path: filePath, // Path: filePath,
Data: total, // Data: total,
} // }
} //}
if len(totalDetail) > 0 { if len(totalDetail) > 0 {
err = initFunc(ctx, now, totalDetail, b) err = initFunc(ctx, now, totalDetail, b)
@ -271,14 +280,15 @@ func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time,
return return
} }
filePath := b.cacheDir + "/kshj_total_ana" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx" filePath := b.cacheDir + "/kshj_total_ana" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx"
title := "截至" + timeCh + "亏损100以上的分销商&产品负利润原因" totalSumFloat64, _ := totalSum.Float64()
title := "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSumFloat64) + ",亏损100以上利润原因如下"
err = b.resellerDetailFillExcelAna(b.excelTempDir+"/"+"kshj_total_ana.xlsx", filePath, totalDetail, title) err = b.resellerDetailFillExcelAna(b.excelTempDir+"/"+"kshj_total_ana.xlsx", filePath, totalDetail, title)
if err != nil { if err != nil {
return return
} }
report[2] = &ReportRes{ report = &ReportRes{
ReportName: "负利润分析(亏损100以上)", ReportName: "负利润分析(亏损100以上)",
Title: "截至" + timeCh + "亏损100以上利润原因", Title: title,
Path: filePath, Path: filePath,
Data: total, Data: total,
} }

View File

@ -106,7 +106,7 @@ var (
) )
func run() { func run() {
configConfig, _ = config.LoadConfigWithTest() configConfig, _ = config.LoadConfigWithEnv()
// 初始化数据库连接 // 初始化数据库连接
db, _ := utils.NewGormDb(configConfig) db, _ := utils.NewGormDb(configConfig)
reportDailyCacheImpl = impl.NewReportDailyCacheImpl(db) reportDailyCacheImpl = impl.NewReportDailyCacheImpl(db)

View File

@ -343,14 +343,17 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
styleD3, err := f.GetCellStyle(sheet, fmt.Sprintf("D%d", tplRowData)) styleD3, err := f.GetCellStyle(sheet, fmt.Sprintf("D%d", tplRowData))
if err != nil { if err != nil {
styleC3 = 0 styleD3 = 0
} }
styleE3, err := f.GetCellStyle(sheet, fmt.Sprintf("E%d", tplRowData)) styleE3, err := f.GetCellStyle(sheet, fmt.Sprintf("E%d", tplRowData))
if err != nil { if err != nil {
styleC3 = 0 styleE3 = 0
}
styleF3, err := f.GetCellStyle(sheet, fmt.Sprintf("F%d", tplRowData))
if err != nil {
styleF3 = 0
} }
rowHeightData, err := f.GetRowHeight(sheet, tplRowData) rowHeightData, err := f.GetRowHeight(sheet, tplRowData)
if err != nil { if err != nil {
rowHeightData = 20 rowHeightData = 20
@ -372,11 +375,15 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
} }
styleTotalD, err := f.GetCellStyle(sheet, fmt.Sprintf("D%d", tplRowTotal)) styleTotalD, err := f.GetCellStyle(sheet, fmt.Sprintf("D%d", tplRowTotal))
if err != nil { if err != nil {
styleTotalC = 0 styleTotalD = 0
} }
styleTotalE, err := f.GetCellStyle(sheet, fmt.Sprintf("E%d", tplRowTotal)) styleTotalE, err := f.GetCellStyle(sheet, fmt.Sprintf("E%d", tplRowTotal))
if err != nil { if err != nil {
styleTotalC = 0 styleTotalE = 0
}
styleTotalF, err := f.GetCellStyle(sheet, fmt.Sprintf("F%d", tplRowTotal))
if err != nil {
styleTotalF = 0
} }
rowHeightTotal, err := f.GetRowHeight(sheet, tplRowTotal) rowHeightTotal, err := f.GetRowHeight(sheet, tplRowTotal)
if err != nil { if err != nil {
@ -408,8 +415,9 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
f.SetCellValue(sheet, fmt.Sprintf("A%d", currentRow), reseller.ResellerName) f.SetCellValue(sheet, fmt.Sprintf("A%d", currentRow), reseller.ResellerName)
f.SetCellValue(sheet, fmt.Sprintf("B%d", currentRow), p.ProductName) f.SetCellValue(sheet, fmt.Sprintf("B%d", currentRow), p.ProductName)
f.SetCellValue(sheet, fmt.Sprintf("C%d", currentRow), p.Loss) f.SetCellValue(sheet, fmt.Sprintf("C%d", currentRow), p.Loss)
f.SetCellValue(sheet, fmt.Sprintf("D%d", currentRow), reseller.Manager) f.SetCellValue(sheet, fmt.Sprintf("D%d", currentRow), reseller.Total)
f.SetCellValue(sheet, fmt.Sprintf("E%d", currentRow), p.LossReason) f.SetCellValue(sheet, fmt.Sprintf("E%d", currentRow), reseller.Manager)
f.SetCellValue(sheet, fmt.Sprintf("F%d", currentRow), p.LossReason)
// 设置样式 // 设置样式
if styleA3 != 0 { if styleA3 != 0 {
f.SetCellStyle(sheet, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("A%d", currentRow), styleA3) f.SetCellStyle(sheet, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("A%d", currentRow), styleA3)
@ -426,7 +434,9 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
if styleE3 != 0 { if styleE3 != 0 {
f.SetCellStyle(sheet, fmt.Sprintf("E%d", currentRow), fmt.Sprintf("E%d", currentRow), styleE3) f.SetCellStyle(sheet, fmt.Sprintf("E%d", currentRow), fmt.Sprintf("E%d", currentRow), styleE3)
} }
if styleF3 != 0 {
f.SetCellStyle(sheet, fmt.Sprintf("F%d", currentRow), fmt.Sprintf("F%d", currentRow), styleF3)
}
totalLoss += p.Loss totalLoss += p.Loss
currentRow++ currentRow++
} }
@ -436,6 +446,7 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
if endRow > startRow { if endRow > startRow {
f.MergeCell(sheet, fmt.Sprintf("A%d", startRow), fmt.Sprintf("A%d", endRow)) f.MergeCell(sheet, fmt.Sprintf("A%d", startRow), fmt.Sprintf("A%d", endRow))
f.MergeCell(sheet, fmt.Sprintf("D%d", startRow), fmt.Sprintf("D%d", endRow)) f.MergeCell(sheet, fmt.Sprintf("D%d", startRow), fmt.Sprintf("D%d", endRow))
f.MergeCell(sheet, fmt.Sprintf("E%d", startRow), fmt.Sprintf("E%d", endRow))
} }
} }
@ -447,7 +458,7 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
f.SetCellValue(sheet, fmt.Sprintf("A%d", currentRow), "合计") f.SetCellValue(sheet, fmt.Sprintf("A%d", currentRow), "合计")
// B列留空C列填充总亏损 // B列留空C列填充总亏损
f.SetCellValue(sheet, fmt.Sprintf("C%d", currentRow), totalLoss) f.SetCellValue(sheet, fmt.Sprintf("D%d", currentRow), totalLoss)
// 设置合计行样式 // 设置合计行样式
if styleTotalA != 0 { if styleTotalA != 0 {
@ -465,7 +476,9 @@ func (b *BbxtTools) resellerDetailFillExcelAna(templatePath, outputPath string,
if styleTotalE != 0 { if styleTotalE != 0 {
f.SetCellStyle(sheet, fmt.Sprintf("E%d", currentRow), fmt.Sprintf("E%d", currentRow), styleTotalE) f.SetCellStyle(sheet, fmt.Sprintf("E%d", currentRow), fmt.Sprintf("E%d", currentRow), styleTotalE)
} }
if styleTotalF != 0 {
f.SetCellStyle(sheet, fmt.Sprintf("F%d", currentRow), fmt.Sprintf("F%d", currentRow), styleTotalF)
}
// 取消合并合计行的A、B列 // 取消合并合计行的A、B列
// f.MergeCell(sheet, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("B%d", currentRow)) // f.MergeCell(sheet, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("B%d", currentRow))

Binary file not shown.