From 941827ce410ff763cc749ac089ef73a374a7386a Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 14:12:27 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=92=8CAPI=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/server/main.go | 3 +- config/config.yaml | 2 + config/config_test.yaml | 14 +++--- deploy.sh | 6 ++- internal/biz/group_config.go | 5 +-- internal/config/config.go | 4 +- internal/tools/bbxt/api.go | 67 ++++++++++++++-------------- internal/tools/bbxt/bbxt.go | 59 ++++++++++++------------ internal/tools/bbxt/bbxt_test.go | 10 ++--- tmpl/excel_temp/kshj_gt.xlsx | Bin 9907 -> 9911 bytes tmpl/excel_temp/kshj_total_ana.xlsx | Bin 10304 -> 10320 bytes 11 files changed, 90 insertions(+), 80 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index cf658c3..806c43d 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -12,6 +12,7 @@ import ( func main() { configPath := flag.String("config", "./config/config_test.yaml", "Path to configuration file") onBot := flag.String("bot", "", "bot start") + cron := flag.String("cron", "", "close") flag.Parse() ctx := context.Background() bc, err := config.LoadConfig(*configPath) @@ -29,7 +30,7 @@ func main() { //钉钉机器人 app.DingBotServer.Run(ctx, *onBot) //定时任务 - 测试环境不启用 - if configPath != nil && *configPath == "./config/config.yaml" { + if *cron == "start" { app.Cron.Run(ctx) } diff --git a/config/config.yaml b/config/config.yaml index 3b4fab8..6586e20 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -108,6 +108,8 @@ tools: base_url: "https://api.coze.cn" api_key: "7583905168607100978" api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ" + zltxResellerAuthProductToManagerAndDefaultLossReason: + base_url: "https://revcl.1688sup.com/api/admin/resellerAuthProductToManagerAndDefaultLossReason" # eino tool 配置 eino_tools: diff --git a/config/config_test.yaml b/config/config_test.yaml index 4c8d69e..d7d519d 100644 --- a/config/config_test.yaml +++ b/config/config_test.yaml @@ -26,14 +26,12 @@ coze: lsxd: # 统一登录 - login_url: "http://api.test.user.1688sup.com/v1/login/phone" - phone: "OFJ8UpqOlI7+w3Qklf36ZA==" - password: "tEbFegH/DRRh6LutFb7o3g==" - code: "123456" - check_token_url: "http://api.test.user.1688sup.com/v1/user/welcome" + login_url: "https://api.user.1688sup.com/v1/login/phone" + phone: "ORlviZN7N06W2+WKLe76xg==" + password: "V5Uh8C4bamEM6UQZh4TCeQ==" + code: "456789" + check_token_url: "https://api.user.1688sup.com/v1/user/welcome" -zltx: - req_url: "https://gateway.dev.cdlsxd.cn/zltx_api" sys: session_len: 6 @@ -106,6 +104,8 @@ tools: base_url: "https://api.coze.cn" api_key: "7583905168607100978" api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ" + zltxResellerAuthProductToManagerAndDefaultLossReason: + base_url: "https://revcl.1688sup.com/api/admin/reseller/resellerAuthProduct/getManagerAndDefaultLossReason" # eino tool 配置 eino_tools: diff --git a/deploy.sh b/deploy.sh index 1ad338a..a9f6bd0 100644 --- a/deploy.sh +++ b/deploy.sh @@ -16,10 +16,12 @@ fi CONFIG_FILE="config/config.yaml" BRANCH="master" BOT="All" +CRON="start" if [ "$MODE" = "dev" ]; then CONFIG_FILE="config/config_test.yaml" BOT="zltx" BRANCH="test" + CRON="close" fi git fetch origin @@ -47,6 +49,8 @@ docker run -itd \ -v ./cache:/app/cache \ -v ./tmpl:/app/tmpl \ -v ./go.mod:/app/go.mod \ - "${CONTAINER_NAME}" ./server --config "./${CONFIG_FILE}" --bot "${BOT}" + "${CONTAINER_NAME}" ./server \ + --config "./${CONFIG_FILE}" --bot "${BOT}" --cron "${CRON}" + docker logs -f ${CONTAINER_NAME} \ No newline at end of file diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index 89d5d62..b68a29d 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -188,11 +188,11 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz if _err != nil { return _err } - reports = append(reports, repo...) rechargeReport, _err := g.rechargeDailyReport(ctx, t, product, nil) - if _err != nil || len(repo) == 0 { + if _err != nil { return _err } + reports = append(reports, repo...) reports = append(reports, rechargeReport...) case "report_daily_recharge": product := strings.Split(groupConfig.ProductName, ",") @@ -223,7 +223,6 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz } entitys.ResText(rec.Ch, "", fmt.Sprintf("%s![图片](%s)", report.Title, report.Url)) - } return nil } diff --git a/internal/config/config.go b/internal/config/config.go index b4f05d9..64857a9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -27,7 +27,6 @@ type Config struct { LLM LLM `mapstructure:"llm"` Dingtalk DingtalkConfig `mapstructure:"dingtalk"` Qywx QywxConfig `mapstructure:"qywx"` - ZLTX ZLTX `mapstructure:"zltx"` } type ZLTX struct { @@ -196,7 +195,8 @@ type ToolsConfig struct { // Coze 快递查询工具 CozeExpress ToolConfig `mapstructure:"cozeExpress"` // Coze 公司查询工具 - CozeCompany ToolConfig `mapstructure:"cozeCompany"` + CozeCompany ToolConfig `mapstructure:"cozeCompany"` + ZltxResellerAuthProductToManagerAndDefaultLossReason ToolConfig `mapstructure:"zltxResellerAuthProductToManagerAndDefaultLossReason"` } // ToolConfig 单个工具配置 diff --git a/internal/tools/bbxt/api.go b/internal/tools/bbxt/api.go index 4dd645b..2ef4640 100644 --- a/internal/tools/bbxt/api.go +++ b/internal/tools/bbxt/api.go @@ -195,48 +195,49 @@ type GetManagerAndDefaultLossReasonResponse struct { } type GetManagerAndDefaultLossReasonResponseList struct { - ResellerInfo *GetManagerAndDefaultLossReasonResponse_ResellerInfo `json:"GetManagerAndDefaultLossReasonResponse_ResellerInfo,omitempty"` - ProductList []*GetManagerAndDefaultLossReasonResponse_ProductList `json:"GetManagerAndDefaultLossReasonResponse_ProductList,omitempty"` + ResellerInfo *GetManagerAndDefaultLossReasonResponse_ResellerInfo `json:"resellerInfo,omitempty"` + ProductList []*GetManagerAndDefaultLossReasonResponse_ProductList `json:"productList,omitempty"` } type GetManagerAndDefaultLossReasonResponse_ResellerInfo struct { - ResellerId int32 `json:"reseller_id,omitempty"` - AfterSaleName string `json:"after_sale_name,omitempty"` + ResellerId int32 `json:"resellerId,omitempty"` + AfterSaleName string `json:"AfterSaleName,omitempty"` } type GetManagerAndDefaultLossReasonResponse_ProductList struct { - ProductId int32 `json:"product_id,omitempty"` - LossReason string `json:"loss_reason,omitempty"` + ProductId int32 `json:"productId,omitempty"` + LossReason string `json:"lossReason,omitempty"` } +//return []*GetManagerAndDefaultLossReasonResponseList{ +//{ +//ResellerInfo: &GetManagerAndDefaultLossReasonResponse_ResellerInfo{ +//ResellerId: 25009, +//AfterSaleName: "张三", +//}, +//ProductList: []*GetManagerAndDefaultLossReasonResponse_ProductList{ +//{ +//ProductId: 129, +//LossReason: "小米钱包h5-QQ音乐绿钻季卡原因", +//}, +//{ +//ProductId: 2218, +//LossReason: "小米钱包h5-百度网盘新vip会员月卡原因", +//}, +//{ +//ProductId: 3226, +//LossReason: "小米钱包h5-腾讯视频月卡-小米钱包2024原因", +//}, +//{ +//ProductId: 3364, +//LossReason: "小米钱包h5-腾讯视频月卡-0元直充原因", +//}, +//}, +//}, +//}, nil + // GetStatisFilterOfficialProductApi 官方商品列表 func GetManagerAndDefaultLossReasonApi(param *GetManagerAndDefaultLossReasonRequest, token string, reqUrl string) ([]*GetManagerAndDefaultLossReasonResponseList, error) { - return []*GetManagerAndDefaultLossReasonResponseList{ - { - ResellerInfo: &GetManagerAndDefaultLossReasonResponse_ResellerInfo{ - ResellerId: 25009, - AfterSaleName: "张三", - }, - ProductList: []*GetManagerAndDefaultLossReasonResponse_ProductList{ - { - ProductId: 129, - LossReason: "小米钱包h5-QQ音乐绿钻季卡原因", - }, - { - ProductId: 2218, - LossReason: "小米钱包h5-百度网盘新vip会员月卡原因", - }, - { - ProductId: 3226, - LossReason: "小米钱包h5-腾讯视频月卡-小米钱包2024原因", - }, - { - ProductId: 3364, - LossReason: "小米钱包h5-腾讯视频月卡-0元直充原因", - }, - }, - }, - }, nil reqParam, err := util.StructToMap(param) if err != nil { @@ -244,7 +245,7 @@ func GetManagerAndDefaultLossReasonApi(param *GetManagerAndDefaultLossReasonRequ } req := &l_request.Request{ - Url: reqUrl + "/admin/reseller/resellerAuthProduct/getManagerAndDefaultLossReason", + Url: reqUrl, Method: http.MethodPost, Json: reqParam, Headers: map[string]string{ diff --git a/internal/tools/bbxt/bbxt.go b/internal/tools/bbxt/bbxt.go index 4c77c8c..de1e638 100644 --- a/internal/tools/bbxt/bbxt.go +++ b/internal/tools/bbxt/bbxt.go @@ -189,34 +189,34 @@ func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, report = make([]*ReportRes, 3) timeCh := now.Format("1月2日15点") //总量生成excel - //if len(total) > 0 { - // 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, "") - // if err != nil { - // return - // } - // report[0] = &ReportRes{ - // ReportName: "分销商负利润统计", - // Title: "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSum), - // Path: filePath, - // Data: total, - // } - //} + if len(total) > 0 { + 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, "") + if err != nil { + return + } + report[0] = &ReportRes{ + ReportName: "分销商负利润统计", + Title: "截至" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSum), + Path: filePath, + Data: total, + } + } - //if len(gt) > 0 { - // filePath := b.cacheDir + "/kshj_gt" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx" - // title := "截至" + timeCh + "亏损500以上的分销商和产品" - // err = b.resellerDetailFillExcelV2(b.excelTempDir+"/"+"kshj_gt.xlsx", filePath, gt, title) - // if err != nil { - // return - // } - // report[1] = &ReportRes{ - // ReportName: "负利润分析(亏损500以上)", - // Title: "截至" + timeCh + "亏损500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500), - // Path: filePath, - // Data: total, - // } - //} + if len(gt) > 0 { + filePath := b.cacheDir + "/kshj_gt" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx" + title := "截至" + timeCh + "亏损500以上的分销商和产品" + err = b.resellerDetailFillExcelV2(b.excelTempDir+"/"+"kshj_gt.xlsx", filePath, gt, title) + if err != nil { + return + } + report[1] = &ReportRes{ + ReportName: "负利润分析(亏损500以上)", + Title: "截至" + timeCh + "亏损500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500), + Path: filePath, + Data: total, + } + } if len(totalDetail) > 0 { err = initFunc(ctx, now, totalDetail, b) @@ -269,7 +269,7 @@ func (b *BbxtTools) GetResellerLossMannagerAndLossReasonFromApi(ctx context.Cont } res, err := GetManagerAndDefaultLossReasonApi(&GetManagerAndDefaultLossReasonRequest{ Param: resellerMap, - }, b.login.GetToken(ctx), b.config.ZLTX.ReqUrl) + }, b.login.GetToken(ctx), b.config.Tools.ZltxResellerAuthProductToManagerAndDefaultLossReason.BaseURL) if err != nil { return nil, err } @@ -286,6 +286,9 @@ func (b *BbxtTools) GetResellerLossMannagerAndLossReasonFromApi(ctx context.Cont if _, ex := relationMap[v.ResellerInfo.ResellerId].Products[vv.ProductId]; !ex { continue } + if len(vv.LossReason) == 0 { + continue + } relationMap[v.ResellerInfo.ResellerId].Products[vv.ProductId].LossReason = vv.LossReason } } diff --git a/internal/tools/bbxt/bbxt_test.go b/internal/tools/bbxt/bbxt_test.go index 1bde483..0bf9b61 100644 --- a/internal/tools/bbxt/bbxt_test.go +++ b/internal/tools/bbxt/bbxt_test.go @@ -111,8 +111,8 @@ func GetReportCache(ctx context.Context, day time.Time, totalDetail []*ResellerL var ResellerProductRelation map[int32]*ResellerLossSumProductRelation dayDate := day.Format(time.DateOnly) cond := builder.NewCond() - cond = cond.And(builder.Eq{"`index`": IndexLossSumDetail}) - cond = cond.And(builder.Eq{"`key`": dayDate}) + cond = cond.And(builder.Eq{"cache_index": IndexLossSumDetail}) + cond = cond.And(builder.Eq{"cache_key": dayDate}) var cache model.AiReportDailyCache err := reportDailyCacheImpl.GetOneBySearchToStrut(&cond, &cache) @@ -125,9 +125,9 @@ func GetReportCache(ctx context.Context, day time.Time, totalDetail []*ResellerL return err } cache = model.AiReportDailyCache{ - Key: dayDate, - Index: IndexLossSumDetail, - Value: pkg.JsonStringIgonErr(ResellerProductRelation), + CacheKey: dayDate, + CacheIndex: IndexLossSumDetail, + Value: pkg.JsonStringIgonErr(ResellerProductRelation), } _, err = reportDailyCacheImpl.Add(&cache) if err != nil { diff --git a/tmpl/excel_temp/kshj_gt.xlsx b/tmpl/excel_temp/kshj_gt.xlsx index 459460b5acdc3230fe13709303bea7cc9f388b6b..ef1033dc6028bb113c19ab09d4708bacb53ab033 100644 GIT binary patch delta 3107 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 LJqDH{00000>ABT{ diff --git a/tmpl/excel_temp/kshj_total_ana.xlsx b/tmpl/excel_temp/kshj_total_ana.xlsx index d2774f36304f5afde22664eb808ace7d75651753..c4824cdce0bbad8704b1c8317ccc6946ee708132 100644 GIT binary patch delta 5218 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 delta 5142 zcmZ8lWmMGP)}Eo8p=0RoR2u1_OKHhJog$6IkCv{Xq(KR37)6>95Tu8c7(hZokd_pD z_1?SQ`>uC?*k|qitY<&x(^+RfCI0MjBx?RR7@#ea&?8+ zGDde@?g@k1gfDxrF_Z@dX0XW0rD=D`s}_`7>;Ugmweh4U+n4jACT`>G4hBdb1ZsNc zv3R-Fwv(y@ou7zlm_rGrIJfBCk1c&BpW`MMWW=Xx@WLFo5C^4y=i zXj;0HM)6ZrncSmd^oH7=v{FV(bzJJD47Pg0CHC!Oeo^+;GnL%dG>fe?V3msHM&T2p zzqEE`ThM*$`k^OX%(FtxfB1_}AoR83Dx+3eU3G-DZN>ptg@eT8$us?kORG2Kl&BRACVUXnNJXH3gIBse{V|%}Q>-Z#4 z>lBNj4X5_}l&yzx4yn%G79gPf9qS;OE(hY)x*1k4Uyvg)Q`6j-5|;Y3ddWn@nor`V zB|xtM$ybtaef=WvY9Ny0S-WJfnnWVwk8`Im+Bz?K07<;HJXapSS-iW z)hVg{uV$`t9};H1;Tv$2%$g%u~d?9rzj+ zD=_S}ECT7K*;T;nQm@TjXkr-1iKcdmEZu*V<5CdMQN!U`0j#m|PFX~8wVQ1mk8c*l zvNs+UC!yORLOlHTlx>fEG+wnN=M2%_{W|gXO=4hu{%XB2n*#?U7n{KUuN->)X}h%hKEJ3|Ttquf9Sb1b*v^ z2PaNpyl;J0cdxp8!l9(IrI*n^0f<#`UMmZ6;J&2QomJu;jid@MimG8!*NZGk3Gb)9 zITXOUG~#|M4Re2|XSazpxg@0i%{t@Sc%l&WQH<4vc^9>P29)r=k&n62;o9)&x~J1c3t8)B^c1HgKOQJ4F^ z_f*K>^E)LEBDPs<1EJ+IRyz8CLCD@V$lL_VaVNh7B3WXIHhC(7l7Pj84Fn{|-^4p4 z=be*vivHt9W-a;11wv(WHHgM!*obypzH-VjHFdU!AV~gMRrh!rQ-dBK>n51NN?0ro z#Phnvl8uf?i>7LBinsPQ0A5~V;d(O`c6_Mulo&*%aMHe8YK`5s?bH0K=iKi`_qi`% zbAlE_qn((gtyNPPp>=9yMmVtrX%(ud@?ircE(Wzn>P>lqVtG*-%kMS9z86 zrS->beGN+GATF&K*RgweEcZxdiRuE8;RQ^y7 z8&QSn$5PVLNW-4u6!e%cBE4=}#c7fwwEKJ?|6U2QOK3BGi)r6t6~ThIEKO-TKd{OA zsQ@=%Wkp!xZR2ZseFdEIh(RE*2MF}%00nsn`}zfYIQj|&d3vl^xu-!*>F!ep09xrN zQaoq5%@fDgPG~^4?BfbNH4YXI#SG!i6*BuYS*9v@GC4iajJQqcMTSgRPK3xg3oTkL zBgVB({uIE(o!Gu92~MlusNYbIIGTqym!ET(A)u)EA$pl7?01}@SI(Q}FH9Fpt>O

wHGCv^hHQnW3+sXOm=!3EdHL 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