From f2c2276ca6370785d7223b54f7daffe785dfb286 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Wed, 14 Jan 2026 18:20:39 +0800 Subject: [PATCH 01/30] =?UTF-8?q?fix=EF=BC=9A=E4=B8=B4=E6=97=B6=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/group_config.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index 21605fc..5d33e7e 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -190,11 +190,11 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz return _err } reports = append(reports, repo...) - rechargeReport, _err := g.rechargeDailyReport(ctx, t, product, nil) - if _err != nil || len(repo) == 0 { - return _err - } - reports = append(reports, rechargeReport...) + // rechargeReport, _err := g.rechargeDailyReport(ctx, t, product, nil) + // if _err != nil || len(repo) == 0 { + // return _err + // } + // reports = append(reports, rechargeReport...) case "report_daily_recharge": product := strings.Split(groupConfig.ProductName, ",") repo, _err := g.rechargeDailyReport(ctx, t, product, nil) From 59a7d1c7a593c27e3db4ef7a8db489aee208f7a5 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 14:22:33 +0800 Subject: [PATCH 02/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index 6586e20..18a232d 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -47,7 +47,7 @@ redis: host: 47.97.27.195:6379 type: node pass: lansexiongdi@666 - key: report-api-test + key: ai_scheduler-test pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池 minIdleConns: 2 #最小空闲连接数 maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭 From 531facbb07acca530a8508659347371a0267c9ee Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 14:34:46 +0800 Subject: [PATCH 03/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- internal/tools/bbxt/api.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/tools/bbxt/api.go b/internal/tools/bbxt/api.go index 2ef4640..cd53f1c 100644 --- a/internal/tools/bbxt/api.go +++ b/internal/tools/bbxt/api.go @@ -4,13 +4,14 @@ import ( "ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg/l_request" "ai_scheduler/internal/pkg/util" - "encoding/json" "fmt" "net/http" "net/url" "strings" + + "github.com/go-kratos/kratos/v2/log" ) type StatisOursProductLossSumReq struct { @@ -252,6 +253,7 @@ func GetManagerAndDefaultLossReasonApi(param *GetManagerAndDefaultLossReasonRequ "Authorization": fmt.Sprintf("Bearer %s", token), }, } + log.Debug(pkg.JsonStringIgonErr(req.Headers)) res, err := req.Send() if err != nil { return nil, err From 056a784dea6a847e6ae044862076d009d7e1fc5e Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 14:36:17 +0800 Subject: [PATCH 04/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index 18a232d..95fc222 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -47,7 +47,7 @@ redis: host: 47.97.27.195:6379 type: node pass: lansexiongdi@666 - key: ai_scheduler-test + key: ai_scheduler_prov pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池 minIdleConns: 2 #最小空闲连接数 maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭 From 7ab366d5d42f01d46ad634d354111cd2c24e5532 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 14:52:35 +0800 Subject: [PATCH 05/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- internal/pkg/lsxd/login.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/pkg/lsxd/login.go b/internal/pkg/lsxd/login.go index 13b7f1c..fbaa30c 100644 --- a/internal/pkg/lsxd/login.go +++ b/internal/pkg/lsxd/login.go @@ -50,7 +50,7 @@ func (l *Login) GetToken(ctx context.Context) string { if err != nil { log.Errorf("lsxd get token from redis failed, err: %v", err) } - if token != "" && l.checkTokenValid(ctx, token) { + if token != "" /*&& l.checkTokenValid(ctx, token)*/ { return token } @@ -165,7 +165,8 @@ func (l *Login) cacheToken(ctx context.Context, token string) error { if token == "" { return errors.New("token is empty") } - return l.redisCli.Set(ctx, l.getCacheKey(), token, constants.EXPIRE_LSXD_TOKEN).Err() + key := l.getCacheKey() + return l.redisCli.Set(ctx, key, token, constants.EXPIRE_LSXD_TOKEN).Err() } func (l *Login) doRequest(ctx context.Context, method string, url string, authorization string, body []byte) (int, error) { From 1e75c689841a70d701226097531ee769a436a6d3 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 14:56:43 +0800 Subject: [PATCH 06/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- internal/pkg/lsxd/login.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/lsxd/login.go b/internal/pkg/lsxd/login.go index fbaa30c..ccc26bf 100644 --- a/internal/pkg/lsxd/login.go +++ b/internal/pkg/lsxd/login.go @@ -50,7 +50,7 @@ func (l *Login) GetToken(ctx context.Context) string { if err != nil { log.Errorf("lsxd get token from redis failed, err: %v", err) } - if token != "" /*&& l.checkTokenValid(ctx, token)*/ { + if token != "" && l.checkTokenValid(ctx, token) { return token } From fcf6bcbe7566bbed22c6b0cde1b84a07eca75c2d Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 15:08:24 +0800 Subject: [PATCH 07/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- internal/pkg/lsxd/login.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/lsxd/login.go b/internal/pkg/lsxd/login.go index ccc26bf..8d33341 100644 --- a/internal/pkg/lsxd/login.go +++ b/internal/pkg/lsxd/login.go @@ -191,7 +191,7 @@ func (l *Login) doRequestWithBody(ctx context.Context, method string, url string req.Header.Set("Content-Type", contentType) } if authorization != "" { - req.Header.Set("Authorization", authorization) + req.Header.Set("Authorization", "Bearer "+authorization) } resp, err := (&http.Client{}).Do(req) From 1b8077f403a1186dfa59ac7feacf3205aaafe919 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 15:19:24 +0800 Subject: [PATCH 08/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- internal/tools/bbxt/api.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/tools/bbxt/api.go b/internal/tools/bbxt/api.go index cd53f1c..4554c4d 100644 --- a/internal/tools/bbxt/api.go +++ b/internal/tools/bbxt/api.go @@ -256,8 +256,10 @@ func GetManagerAndDefaultLossReasonApi(param *GetManagerAndDefaultLossReasonRequ log.Debug(pkg.JsonStringIgonErr(req.Headers)) res, err := req.Send() if err != nil { + log.Debug(err.Error()) return nil, err } + log.Debug(string(res.Content)) if res.StatusCode != http.StatusOK { return nil, fmt.Errorf("request failed, status code: %d,resion: %s", res.StatusCode, res.Reason) } From 12751a64345cf14ff2b13ced42bdb389af8ac9ba Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 15:22:05 +0800 Subject: [PATCH 09/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index 95fc222..ebebf76 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -109,7 +109,7 @@ tools: api_key: "7583905168607100978" api_secret: "pat_eEN0BdLNDughEtABjJJRYTW71olvDU0qUbfQUeaPc2NnYWO8HeyNoui5aR9z0sSZ" zltxResellerAuthProductToManagerAndDefaultLossReason: - base_url: "https://revcl.1688sup.com/api/admin/resellerAuthProductToManagerAndDefaultLossReason" + base_url: "https://revcl.1688sup.com/api/admin/reseller/resellerAuthProduct/getManagerAndDefaultLossReason" # eino tool 配置 eino_tools: From 6d31c923fb6102967430f69d85d262a431449681 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 18:09:45 +0800 Subject: [PATCH 10/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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 --- tmpl/excel_temp/kshj_gt.xlsx | Bin 9911 -> 9919 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tmpl/excel_temp/kshj_gt.xlsx b/tmpl/excel_temp/kshj_gt.xlsx index ef1033dc6028bb113c19ab09d4708bacb53ab033..6496930dc10ea19ff0e0daad21e3492c734deb74 100644 GIT binary patch delta 4557 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 delta 4550 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 biR6EWR*e=H`~UwY_;Je;rm_FIy#W6OX0*B) From 3b8af9ada934c04c8cdf1372f69b4b47141ec08e Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 18:32:42 +0800 Subject: [PATCH 11/30] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E6=B8=85=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/do/macro.go | 19 +++++++++++++++++++ .../data/model/ai_report_daily_cache.gen.go | 1 + 2 files changed, 20 insertions(+) diff --git a/internal/biz/do/macro.go b/internal/biz/do/macro.go index ae6b9fe..2d7e775 100644 --- a/internal/biz/do/macro.go +++ b/internal/biz/do/macro.go @@ -48,12 +48,31 @@ func (m *Macro) Router(ctx context.Context, reqContent string, groupConfig *mode return m.NegativeProfitGet(ctx) case strings.HasPrefix(reqContent, "[负利润分析]更新"): return m.NegativeProfitUpdate(ctx, reqContent, groupConfig) + case strings.HasPrefix(reqContent, "[负利润分析]清理"): + return m.NegativeProfitClear(ctx, reqContent, groupConfig) default: } return } +func (m *Macro) NegativeProfitClear(ctx context.Context, content string, groupConfig *model.AiBotGroupConfig) (successMsg string, err error, isFinish bool) { + dayDate := time.Now().Format(time.DateOnly) + cond := builder.NewCond() + cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) + cond = cond.And(builder.Eq{"cache_key": dayDate}) + err = m.reportDailyCacheImpl.UpdateByCond(&cond, &model.AiReportDailyCache{ + Status: 2, + }) + if err != nil { + err = fmt.Errorf("解析失败:%v", err) + return + } + isFinish = true + successMsg = "清理成功" + return +} + func (m *Macro) NegativeProfitUpdate(ctx context.Context, content string, groupConfig *model.AiBotGroupConfig) (successMsg string, err error, isFinish bool) { //newContent := strings.ReplaceAll(strings.TrimSpace(content), "[负利润分析]更新:", "") jsonData, err := ParseLossData(content) diff --git a/internal/data/model/ai_report_daily_cache.gen.go b/internal/data/model/ai_report_daily_cache.gen.go index bf7057c..3f7015b 100644 --- a/internal/data/model/ai_report_daily_cache.gen.go +++ b/internal/data/model/ai_report_daily_cache.gen.go @@ -12,6 +12,7 @@ type AiReportDailyCache struct { CacheKey string `gorm:"column:cache_key;not null;default:1;comment:索引方式,可以是任意类型" json:"cache_key"` // 索引方式,可以是任意类型 Value string `gorm:"column:value;comment:类型下所需路由以及参数" json:"value"` // 类型下所需路由以及参数 CacheIndex string `gorm:"column:cache_index;not null;comment:类型" json:"cache_index"` // 类型 + Status int32 `gorm:"column:status;not null;default:1" json:"status"` } // TableName AiReportDailyCache's table name From b3c807f0ac8dd943d6d9c3f4997b57116cef5fe6 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 15 Jan 2026 18:38:54 +0800 Subject: [PATCH 12/30] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=9D=A1=E4=BB=B6=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/do/macro.go | 1 + internal/biz/group_config.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/biz/do/macro.go b/internal/biz/do/macro.go index 2d7e775..9d68eda 100644 --- a/internal/biz/do/macro.go +++ b/internal/biz/do/macro.go @@ -61,6 +61,7 @@ func (m *Macro) NegativeProfitClear(ctx context.Context, content string, groupCo cond := builder.NewCond() cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) cond = cond.And(builder.Eq{"cache_key": dayDate}) + cond = cond.And(builder.Eq{"status": 1}) err = m.reportDailyCacheImpl.UpdateByCond(&cond, &model.AiReportDailyCache{ Status: 2, }) diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index b68a29d..4b25bb3 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -421,6 +421,7 @@ func (g *GroupConfigBiz) GetReportCache(ctx context.Context, day time.Time, tota cond := builder.NewCond() cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) cond = cond.And(builder.Eq{"cache_key": dayDate}) + cond = cond.And(builder.Eq{"status": 1}) var cache model.AiReportDailyCache err := g.reportDailyCacheImpl.GetOneBySearchToStrut(&cond, &cache) if err != nil { From ecd2490a243c5ce042f60b612ecbdd72057a9ff7 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Fri, 16 Jan 2026 09:15:07 +0800 Subject: [PATCH 13/30] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=9D=A1=E4=BB=B6=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/group_config.go | 5 +++++ internal/tools/bbxt/bbxt.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index 4b25bb3..8987119 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -452,6 +452,11 @@ func (g *GroupConfigBiz) GetReportCache(ctx context.Context, day time.Time, tota v.Manager = ResellerProductRelation[v.ResellerId].AfterSaleName for _, vv := range v.ProductLoss { if _, ex := ResellerProductRelation[v.ResellerId].Products[vv.ProductId]; !ex { + vv.LossReason = "未填写" + continue + } + if len(ResellerProductRelation[v.ResellerId].Products[vv.ProductId].LossReason) == 0 { + vv.LossReason = "未填写" continue } vv.LossReason = ResellerProductRelation[v.ResellerId].Products[vv.ProductId].LossReason diff --git a/internal/tools/bbxt/bbxt.go b/internal/tools/bbxt/bbxt.go index de1e638..9f20182 100644 --- a/internal/tools/bbxt/bbxt.go +++ b/internal/tools/bbxt/bbxt.go @@ -263,7 +263,7 @@ func (b *BbxtTools) GetResellerLossMannagerAndLossReasonFromApi(ctx context.Cont for _, product := range v.ProductLoss { relationMap[v.ResellerId].Products[product.ProductId] = &LossReason{ ProductName: product.ProductName, - LossReason: "未填写", // 初始化为未填写 + LossReason: "", // 初始化为未填写 } } } From fab60c6fc8a57972af4557f905cdcf6c4922ebd1 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Fri, 16 Jan 2026 11:45:03 +0800 Subject: [PATCH 14/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=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 --- internal/biz/do/macro.go | 212 ++++++++++++++++++++++++++++++----- internal/biz/group_config.go | 63 ++--------- internal/tools/bbxt/bbxt.go | 71 ++++++++++-- 3 files changed, 248 insertions(+), 98 deletions(-) diff --git a/internal/biz/do/macro.go b/internal/biz/do/macro.go index 9d68eda..fe1ffc5 100644 --- a/internal/biz/do/macro.go +++ b/internal/biz/do/macro.go @@ -1,11 +1,15 @@ package do import ( + "ai_scheduler/internal/config" "ai_scheduler/internal/data/impl" "ai_scheduler/internal/data/model" "ai_scheduler/internal/pkg" - + "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/tools/bbxt" + "ai_scheduler/utils" + "database/sql" + "errors" "context" "encoding/json" @@ -23,19 +27,25 @@ import ( type Macro struct { botGroupImpl *impl.BotGroupImpl reportDailyCacheImpl *impl.ReportDailyCacheImpl + config *config.Config + rdb *utils.Rdb } func NewMacro( botGroupImpl *impl.BotGroupImpl, reportDailyCacheImpl *impl.ReportDailyCacheImpl, + config *config.Config, + rdb *utils.Rdb, ) *Macro { return &Macro{ botGroupImpl: botGroupImpl, reportDailyCacheImpl: reportDailyCacheImpl, + config: config, + rdb: rdb, } } -type MacroFunc func(ctx context.Context, content string, groupConfig *model.AiBotGroupConfig) (successMsg string, err error, isFinish bool) +type MacroFunc func(ctx context.Context, content string, groupConfig *model.AiBotGroupConfig, config *config.Config) (successMsg string, err error, isFinish bool) func (m *Macro) Router(ctx context.Context, reqContent string, groupConfig *model.AiBotGroupConfig) (successMsg string, err error, isFinish bool) { reqContent = strings.TrimSpace(reqContent) @@ -47,16 +57,16 @@ func (m *Macro) Router(ctx context.Context, reqContent string, groupConfig *mode case strings.HasPrefix(reqContent, "[负利润分析]导出"): return m.NegativeProfitGet(ctx) case strings.HasPrefix(reqContent, "[负利润分析]更新"): - return m.NegativeProfitUpdate(ctx, reqContent, groupConfig) + return m.NegativeProfitUpdate(ctx, reqContent) case strings.HasPrefix(reqContent, "[负利润分析]清理"): - return m.NegativeProfitClear(ctx, reqContent, groupConfig) + return m.NegativeProfitClear() default: } return } -func (m *Macro) NegativeProfitClear(ctx context.Context, content string, groupConfig *model.AiBotGroupConfig) (successMsg string, err error, isFinish bool) { +func (m *Macro) NegativeProfitClear() (successMsg string, err error, isFinish bool) { dayDate := time.Now().Format(time.DateOnly) cond := builder.NewCond() cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) @@ -74,53 +84,88 @@ func (m *Macro) NegativeProfitClear(ctx context.Context, content string, groupCo return } -func (m *Macro) NegativeProfitUpdate(ctx context.Context, content string, groupConfig *model.AiBotGroupConfig) (successMsg string, err error, isFinish bool) { +func (m *Macro) NegativeProfitUpdate(ctx context.Context, content string) (successMsg string, err error, isFinish bool) { //newContent := strings.ReplaceAll(strings.TrimSpace(content), "[负利润分析]更新:", "") jsonData, err := ParseLossData(content) + b, err := bbxt.NewBbxtTools(m.config, lsxd.NewLogin(m.config, m.rdb)) if err != nil { - err = fmt.Errorf("解析失败:%v", err) return } - dayDate := time.Now().Format(time.DateOnly) + now := time.Now() + dayData := now.Format(time.DateOnly) + value, err := b.GetMapResellerLossSumProductRelation(ctx, now, m.GetReportCache) + if err != nil { + return + } + var setData = make(map[int32]*bbxt.ResellerLossSumProductRelation) + for k, v := range jsonData { + if _, ok := value[k]; !ok { + continue + } + for productId, product := range v.Products { + if _, ok := value[k].Products[productId]; !ok { + continue + } + if value[k].Products[productId].LossReason == product.LossReason { + continue + } + if _, ex := setData[k]; !ex { + setData[k] = &bbxt.ResellerLossSumProductRelation{ + ResellerName: value[k].ResellerName, + AfterSaleName: value[k].AfterSaleName, + Products: make(map[int32]*bbxt.LossReason), + } + } + setData[k].Products[productId] = &bbxt.LossReason{ + ProductName: product.ProductName, + LossReason: product.LossReason, + } + } + } + cond := builder.NewCond() cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) - cond = cond.And(builder.Eq{"cache_key": dayDate}) - err = m.reportDailyCacheImpl.UpdateByCond(&cond, &model.AiReportDailyCache{ - Value: pkg.JsonStringIgonErr(jsonData), - }) + cond = cond.And(builder.Eq{"cache_key": dayData}) + cond = cond.And(builder.Eq{"status": 1}) + var cache model.AiReportDailyCache + err = m.reportDailyCacheImpl.GetOneBySearchToStrut(&cond, &cache) if err != nil { - err = fmt.Errorf("解析失败:%v", err) return } + if cache.ID == 0 { + + cache = model.AiReportDailyCache{ + CacheKey: dayData, + CacheIndex: bbxt.IndexLossSumDetail, + Value: pkg.JsonStringIgonErr(setData), + } + _, err = m.reportDailyCacheImpl.Add(&cache) + if err != nil { + return + } + } else { + err = m.reportDailyCacheImpl.UpdateByCond(&cond, &model.AiReportDailyCache{ + Value: pkg.JsonStringIgonErr(setData), + }) + if err != nil { + return + } + } isFinish = true successMsg = "更新成功" return } func (m *Macro) NegativeProfitGet(ctx context.Context) (successMsg string, err error, isFinish bool) { - var ( - data model.AiReportDailyCache - value map[int32]*bbxt.ResellerLossSumProductRelation - ) - isFinish = true - cond := builder.NewCond() - cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) - cond = cond.And(builder.Eq{"cache_key": time.Now().Format(time.DateOnly)}) - err = m.reportDailyCacheImpl.GetOneBySearchToStrut(&cond, &data) + b, err := bbxt.NewBbxtTools(m.config, lsxd.NewLogin(m.config, m.rdb)) if err != nil { - err = fmt.Errorf("获取失败:%v", err) return } - if data.ID == 0 { - successMsg = "暂未获取今日负利润分析数据,请先呼出报表数据" - return - } - err = json.Unmarshal([]byte(data.Value), &value) + now := time.Now() + value, err := b.GetMapResellerLossSumProductRelation(ctx, now, m.GetReportCache) if err != nil { - err = fmt.Errorf("获取失败,格式解析错误:%v", err) return } - //将value转为string //**[供应商id]供应商名称->商务名称**\n //└──商品名称:亏损原因\n @@ -136,6 +181,7 @@ func (m *Macro) NegativeProfitGet(ctx context.Context) (successMsg string, err e } } successMsg = valueString.String() + isFinish = true return } @@ -306,3 +352,109 @@ func ParseLossData(input string) (map[int32]*bbxt.ResellerLossSumProductRelation return result, nil } + +func (m *Macro) GetReportCache(ctx context.Context, day time.Time, totalDetail []*bbxt.ResellerLoss, bbxtObj *bbxt.BbxtTools) error { + dayDate := day.Format(time.DateOnly) + + // 1. 从 API 获取数据并填充 + apiRelations, err := bbxtObj.GetResellerLossMannagerAndLossReasonFromApi(ctx, totalDetail) + if err != nil { + return fmt.Errorf("get API data failed: %w", err) + } + + // 使用 API 数据填充损失原因 + fillLossReasonFromData(totalDetail, apiRelations, "未填写") + + // 2. 从缓存获取数据并覆盖 + cachedRelations, err := m.getCachedRelations(dayDate) + if err != nil { + return fmt.Errorf("get cache data failed: %w", err) + } + + // 使用缓存数据覆盖损失原因 + if cachedRelations != nil { + fillLossReasonFromData(totalDetail, cachedRelations, "") + } + + return nil +} + +// 从缓存获取关系数据 +func (m *Macro) getCachedRelations(dayDate string) (map[int32]*bbxt.ResellerLossSumProductRelation, error) { + cond := builder.NewCond(). + And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}). + And(builder.Eq{"cache_key": dayDate}). + And(builder.Eq{"status": 1}) + + var cache model.AiReportDailyCache + err := m.reportDailyCacheImpl.GetOneBySearchToStrut(&cond, &cache) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + // 缓存不存在是正常情况 + return nil, nil + } + return nil, fmt.Errorf("query cache failed: %w", err) + } + + if cache.ID == 0 { + return nil, nil + } + + var relations map[int32]*bbxt.ResellerLossSumProductRelation + if err := json.Unmarshal([]byte(cache.Value), &relations); err != nil { + return nil, fmt.Errorf("unmarshal cache failed: %w", err) + } + + return relations, nil +} + +// 使用指定数据源填充损失原因 +func fillLossReasonFromData( + totalDetail []*bbxt.ResellerLoss, + relations map[int32]*bbxt.ResellerLossSumProductRelation, + defaultReason string, // 当数据不存在时使用的默认值 +) { + for _, detail := range totalDetail { + resellerRelation, exists := relations[detail.ResellerId] + if !exists { + continue + } + + // 设置售后经理(只有在有值时才设置) + if resellerRelation.AfterSaleName != "" { + detail.Manager = resellerRelation.AfterSaleName + } + + // 为每个产品设置损失原因 + for _, product := range detail.ProductLoss { + setProductLossReason(product, resellerRelation, defaultReason) + } + } +} + +// 设置单个产品的损失原因 +func setProductLossReason( + product *bbxt.ProductLoss, + resellerRelation *bbxt.ResellerLossSumProductRelation, + defaultReason string, +) { + // 如果该经销商没有产品数据,跳过 + if resellerRelation.Products == nil { + return + } + + productRelation, exists := resellerRelation.Products[product.ProductId] + if !exists { + if defaultReason != "" { + product.LossReason = defaultReason + } + return + } + + // 如果有损失原因则设置,否则使用默认值 + if productRelation.LossReason != "" { + product.LossReason = productRelation.LossReason + } else if defaultReason != "" { + product.LossReason = defaultReason + } +} diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index 8987119..9a8bb82 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -1,6 +1,7 @@ package biz import ( + "ai_scheduler/internal/biz/do" "ai_scheduler/internal/biz/tools_regis" "ai_scheduler/internal/config" "ai_scheduler/internal/data/constants" @@ -9,7 +10,6 @@ import ( "ai_scheduler/internal/domain/workflow/recharge" "ai_scheduler/internal/domain/workflow/runtime" "ai_scheduler/internal/entitys" - "ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg/l_request" "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/utils_oss" @@ -41,6 +41,7 @@ type GroupConfigBiz struct { toolManager *tools.Manager conf *config.Config rdb *utils.Rdb + macro *do.Macro } // NewDingTalkBotBiz @@ -52,6 +53,7 @@ func NewGroupConfigBiz( conf *config.Config, reportDailyCacheImpl *impl.ReportDailyCacheImpl, rdb *utils.Rdb, + macro *do.Macro, ) *GroupConfigBiz { return &GroupConfigBiz{ botTools: tools.BootTools, @@ -61,6 +63,7 @@ func NewGroupConfigBiz( conf: conf, reportDailyCacheImpl: reportDailyCacheImpl, rdb: rdb, + macro: macro, } } @@ -86,7 +89,7 @@ func (g *GroupConfigBiz) GetReportLists(ctx context.Context, groupConfig *model. return } - reports, err = reportList.DailyReport(ctx, time.Now(), bbxt.DownWardValue, product, bbxt.SumFilter, g.ossClient, g.GetReportCache) + reports, err = reportList.DailyReport(ctx, time.Now(), bbxt.DownWardValue, product, bbxt.SumFilter, g.ossClient, g.macro.GetReportCache) if err != nil { return } @@ -163,7 +166,7 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz var reports []*bbxt.ReportRes switch rec.Match.Index { case "report_loss_analysis": - repo, _err := rep.StatisOursProductLossSum(ctx, t, g.GetReportCache) + repo, _err := rep.StatisOursProductLossSum(ctx, t, g.macro.GetReportCache) if _err != nil { return _err } @@ -184,7 +187,7 @@ func (g *GroupConfigBiz) handleReport(ctx context.Context, rec *entitys.Recogniz reports = append(reports, repo) case "report_daily": product := strings.Split(groupConfig.ProductName, ",") - repo, _err := rep.DailyReport(ctx, t, bbxt.DownWardValue, product, bbxt.SumFilter, nil, g.GetReportCache) + repo, _err := rep.DailyReport(ctx, t, bbxt.DownWardValue, product, bbxt.SumFilter, nil, g.macro.GetReportCache) if _err != nil { return _err } @@ -413,55 +416,3 @@ func (g *GroupConfigBiz) otherTask(ctx context.Context, rec *entitys.Recognize) entitys.ResText(rec.Ch, "", rec.Match.Reasoning) return } - -func (g *GroupConfigBiz) GetReportCache(ctx context.Context, day time.Time, totalDetail []*bbxt.ResellerLoss, bbxtObj *bbxt.BbxtTools) error { - var ResellerProductRelation map[int32]*bbxt.ResellerLossSumProductRelation - - dayDate := day.Format(time.DateOnly) - cond := builder.NewCond() - cond = cond.And(builder.Eq{"cache_index": bbxt.IndexLossSumDetail}) - cond = cond.And(builder.Eq{"cache_key": dayDate}) - cond = cond.And(builder.Eq{"status": 1}) - var cache model.AiReportDailyCache - err := g.reportDailyCacheImpl.GetOneBySearchToStrut(&cond, &cache) - if err != nil { - return err - } - if cache.ID == 0 { - ResellerProductRelation, err = bbxtObj.GetResellerLossMannagerAndLossReasonFromApi(ctx, totalDetail) - if err != nil { - return err - } - cache = model.AiReportDailyCache{ - CacheKey: dayDate, - CacheIndex: bbxt.IndexLossSumDetail, - Value: pkg.JsonStringIgonErr(ResellerProductRelation), - } - _, err = g.reportDailyCacheImpl.Add(&cache) - } else { - err = json.Unmarshal([]byte(cache.Value), &ResellerProductRelation) - } - - if err != nil { - return err - } - for _, v := range totalDetail { - if _, ex := ResellerProductRelation[v.ResellerId]; !ex { - continue - } - v.Manager = ResellerProductRelation[v.ResellerId].AfterSaleName - for _, vv := range v.ProductLoss { - if _, ex := ResellerProductRelation[v.ResellerId].Products[vv.ProductId]; !ex { - vv.LossReason = "未填写" - continue - } - if len(ResellerProductRelation[v.ResellerId].Products[vv.ProductId].LossReason) == 0 { - vv.LossReason = "未填写" - continue - } - vv.LossReason = ResellerProductRelation[v.ResellerId].Products[vv.ProductId].LossReason - } - } - - return nil -} diff --git a/internal/tools/bbxt/bbxt.go b/internal/tools/bbxt/bbxt.go index 9f20182..345f982 100644 --- a/internal/tools/bbxt/bbxt.go +++ b/internal/tools/bbxt/bbxt.go @@ -31,7 +31,7 @@ var ( SumFilter int32 = -150 ) -var resellerBlackListProduct = []string{ +var ResellerBlackListProduct = []string{ "悦跑", "电商-独立", "蓝星严选连续包月", @@ -103,9 +103,7 @@ func (b *BbxtTools) DailyReport( return } - -// StatisOursProductLossSum 负利润分析 -func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (report []*ReportRes, err error) { +func (b *BbxtTools) ResellerLossSort(ctx context.Context, now time.Time) ([]*ResellerLoss, error) { ct := []string{ time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Format("2006-01-02 15:04:05"), adjustedTime(now), //adjustedTime(time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())), @@ -115,13 +113,10 @@ func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, Ct: ct, }) if err != nil { - return + return nil, err } var ( resellerMap = make(map[int32]*ResellerLoss) - total [][]string - gt []*ResellerLoss - totalDetail []*ResellerLoss ) for _, info := range data.List { @@ -166,14 +161,66 @@ func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, sort.Slice(resellers, func(i, j int) bool { return resellers[i].Total < resellers[j].Total }) - var ( - totalSum float64 + return resellers, nil +} +func (b *BbxtTools) GetMapResellerLossSumProductRelation(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (map[int32]*ResellerLossSumProductRelation, error) { + resellers, err := b.ResellerLossSort(ctx, now) + if err != nil { + return nil, err + } + var totalDetail []*ResellerLoss + for _, v := range resellers { + if v.Total <= -100 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) { + + totalDetail = append(totalDetail, v) + } + + } + if len(totalDetail) > 0 { + err = initFunc(ctx, now, totalDetail, b) + if err != nil { + return nil, err + } + } + value := b.ResellerLossToMapResellerLossSumProductRelation(totalDetail) + return value, nil +} + +func (b *BbxtTools) ResellerLossToMapResellerLossSumProductRelation(totalDetail []*ResellerLoss) map[int32]*ResellerLossSumProductRelation { + relations := make(map[int32]*ResellerLossSumProductRelation) + for _, detail := range totalDetail { + if _, ok := relations[detail.ResellerId]; !ok { + relations[detail.ResellerId] = &ResellerLossSumProductRelation{ + ResellerName: detail.ResellerName, + AfterSaleName: detail.Manager, + Products: make(map[int32]*LossReason), + } + } + for _, product := range detail.ProductLoss { + relations[detail.ResellerId].Products[product.ProductId] = &LossReason{ + ProductName: product.ProductName, + LossReason: product.LossReason, + } + } + + } + return relations +} + +// StatisOursProductLossSum 负利润分析 +func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, initFunc LossSumInitFunc) (report []*ReportRes, err error) { + resellers, err := b.ResellerLossSort(ctx, now) + var ( + total [][]string + gt []*ResellerLoss + totalDetail []*ResellerLoss + totalSum float64 totalSum500 float64 ) // 构建分组 for _, v := range resellers { - if v.Total <= -100 && !slices.Contains(resellerBlackListProduct, v.ResellerName) { + if v.Total <= -100 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) { total = append(total, []string{ fmt.Sprintf("%s", v.ResellerName), fmt.Sprintf("%.2f", v.Total), @@ -181,7 +228,7 @@ func (b *BbxtTools) StatisOursProductLossSum(ctx context.Context, now time.Time, totalSum += v.Total totalDetail = append(totalDetail, v) } - if v.Total <= -500 && !slices.Contains(resellerBlackListProduct, v.ResellerName) { + if v.Total <= -500 && !slices.Contains(ResellerBlackListProduct, v.ResellerName) { gt = append(gt, v) totalSum500 += v.Total } From f546fad4dc70dd2bcaffda9988d5bded4c8e1232 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 19 Jan 2026 10:10:36 +0800 Subject: [PATCH 15/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=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 --- config/config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index ebebf76..6166634 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -5,9 +5,9 @@ server: ollama: base_url: "http://172.17.0.1:11434" - model: "qwen3-coder:480b-cloud" - generate_model: "qwen3-coder:480b-cloud" - mapping_model: "deepseek-v3.2:cloud" + model: "qwen3:8b" + generate_model: "qwen3:8b" + mapping_model: "qwen3:8b" vl_model: "qwen2.5vl:3b" timeout: "120s" level: "info" From de6783c66e2155a8b3b10d3181af01a897f52fe9 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 19 Jan 2026 10:10:43 +0800 Subject: [PATCH 16/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=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 --- tmpl/excel_temp/kshj_total_ana.xlsx | Bin 10320 -> 10270 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tmpl/excel_temp/kshj_total_ana.xlsx b/tmpl/excel_temp/kshj_total_ana.xlsx index c4824cdce0bbad8704b1c8317ccc6946ee708132..a2b81786c4c87d82fd6fd5dcb54ccff4b2c98411 100644 GIT binary patch delta 1715 zcmV;k22A67BZwO}njjC_-Lt&bhywdr7|7sXF)qV`ZZYL?eO%(7X{+ZwmBMEyFnqtYccR zy3tUeJy^6TFE4W5X1p=*WSSO?lVAf+(l+C5fws=I8OD}xK`|S7hxX#SF^V~VUz!bW z8UJ7#z%d~yR^XUmj^Q2{wj&W8k%EuN_S4h@KyVB-DA3Mg8d3b?bzqeJvtdvsP9@#G z^)nsgPT7JV#L>O8ax`{b7j?-H!{?{?ZT0v(j2cSa?}`H|bHOuifVsw$w?auRtuuX< zV@hW89RK!s_%O@i1rUKxmmOv~DX+=>L$yR@ zOyXHc<1ir=i8DIS2zl=#ob~r<4;Shf@ zlba(EfeLHaHNfZu=5oICEys@z`W_^HdhjiEu$#6{EoQkwdDKWwhGI==ZPtt83&4 ziK`43tRgXbCIa28KYv;^j6aG4A<_YcO2p_OWxez~kse5ih0AJE!JC}%5=(f0&>et&m|@^7nACJf|s1Sb8i;B@GED1(wjiIM7;jY){#{_%e8y~o5-CahaF`>EAowhoJau)F`B4C zDJy^#ew~u4AxBP$pNs&*82aukg!ELq)Rqa_RFf38NpNjUQZ#!rA!-xg+9re(cm8&f zNt*-LHYf1i=s!t7spY`6O`1=X7h^G=F+$s}Mq$0;tZ`tQfFsJo2sXdTvaZ6a)mZKB zU^#`wO%+T0i0v3Lv50{_7zd>YN5lbKi?efoWCDFH3tLF5-E;`8 zC7cBAbat^6iGeKaFm6pC0LN|r!Ffss0>J2x2mm+;2w;}a%oo#j*J65`!$w*W*RDSj zVKJRI+kRxwGaT5jZqhcPx5dnXYj%D~_+FpQ!b#b&g8n1eJ~rC>9w;L(GTP z2qfTwsF4_qF&f0%@VE39j%bV-T+a8+dvEb;sUthD91@pV4%JaIoY^~&&ChUdwA)`ey#=zCCKnSt4G{^qZAEN7E44!tKBRTus=y#9!)&Hw6_ zK~)Yy!&^N5*~a2v#wSoq0|b+SCmORr5FHc&X_H@lW8U`8)+PY2{{1(0Pg_+02BZK000000096X0001mld&d24FVDX z0C;RKb98xZWpk5oBp{O?Ck_EMlP)JV0bG-1CqM%550j@ST?r}B(2h3)007dH4JbVZ J0VDtb006-M6WIU& delta 1734 zcmV;%208hjP|#4YlK}*i9TBUOmjNJuYr`NE#oq_}4#D?SP1>$VnzBFiX@$WuHuffZ z+sdL5b!+?WXVNxH+1R6=bAO(5u~_VNoqU1wsxfm!M+7BcL?e~i%+X7=OlK(Zfg8!| z#=smMz@tTZeN_m{MC0JeH5Ob@;FCx)o(Vfg+Yl_n*o!S_?nlvKqPT9H<{=(`-3D7O zKKKT3M#vOv2wd{OaSKdsPedoA6g|>@y1D~MfuRNsCU{Io6#sYwIPL!&=#+s|t8lQf z(<$zdEyYpn-FvTk<8HSb?eZ>0%un&#>hZa&nkv)oN&qSgDVT7;L*vR@sg+Saxb{@w zfzocV=02?A!q*Dq-Jul9i5loonB+GZC6if!e|sXl>vDVnWD?V{W0$k?n%_TEOH^hg zo1`>Lb5fCv(HSG;y^U}&-=;lY=u?pYiPMzOlujx#VPneZ&473YlwI!2A5wk;vjqdu z0SP`6Q?xw;008Ba-vlFn+b|4$AFzKg^j=?cX@WRK6Q|gK4JdYfR%|5^YFnP9#NFSI zl5EA7Vr^e)n>su^q)4W#yXPWzE`$rp$`}Q%j~r5_ETiQyMn8W%+}t8ZNL*$(XC;Zz zUn0=m`s0UH&G?fz5h5L6C`F7;QdUdP6X}T*Sh%brC7c`>FR+AvPk!`7#R<-|Q;~b2 z@6Wsf(-IkmC4UPCI~-_A5|*9|Qc6R@NscAx7bjYYmhCxv6JN%04Y{^@Iua9eV)=r} zNMAuy&ICJ1H)Vxqq>Zy&c#B@1MLHsSp;!gxPv`0eh$~2LPjf2&>U3K{L|%F7x_0YI zxM|s_=oBcJdqi%3&qA^y!4jkOO5eaE_tvY7LKW53JDeP1bRR5t!4$!PhWw(W7M*uT z;{A7$lT?xndIdSE2lk9TDd1-?`HEZv6eUh2y^t-*^B5(njsEB$@CpGu8=?E&Mtjg* z^T?fy9Pl}pTbBQ(nLNd4fm+))R(~S&c#JoiRkZIY5@x21S35Hh_aRsG!vr z4780AVIQ#_BceVc86zfr#BPk3T7=il4;n<}7rwFf0EhhGwrzeh%d2l^V-T|rV%|q= zTZFo~o0)qRrU?>rJns0hHV(5M0}&mjP7zJsAL8jRrLHm3h!!n+DUF4r^(WxOM$e z5*E`IXVi`HK0Gmcq%&0YdqDH*&Mj&4*-_UNU#{ z3q)f~TNWlhfj&S3BQ&8?WCo)<0RYnv4-Vmm+gRa@;P~JQmez>@2HhwH>DMOc*cs&HA%8Z zZF`Vkl|`b;;*Wctz}Kdg6s=|!Ks7_pk7=ps-1pp!)ny)d9ZQYo>2A!^X#Uo%&Ufi) zlh#{q=2YIe$>S8d&Qrk+=|yAO>9Rs@T2IrDH0}57@ii^i_|>$yP(#NpdyremnAQ5+ zvSYo_c6O2*I#*xQZ27;qnbGey(vmfK{?je;m#g2i@DDo_0h^O7BtQZLAd_w+G7l&q z003WdWo&aVE^=jTbCb~~DwEkHTLhCG5v!9pCC33!k|s6+cOjEuAsmxbCJ-Dx*z^iz z0RR9o0ssIM000000000103ZMW0E-Tjp$-<4mL@6zG?T$5IsrSA{3bR5Vv{o`KmsBV clXWLu2|g23v^@g=0Ogb0Cp`u;Bme*a0D}}2e*gdg From bb1cfed16043d5cdf856c3dae68b55f33be8b504 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 19 Jan 2026 10:16:37 +0800 Subject: [PATCH 17/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=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 --- internal/pkg/utils_ollama/client.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/pkg/utils_ollama/client.go b/internal/pkg/utils_ollama/client.go index febd8cd..16928f6 100644 --- a/internal/pkg/utils_ollama/client.go +++ b/internal/pkg/utils_ollama/client.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "sync" + "time" "github.com/ollama/ollama/api" ) @@ -43,11 +44,12 @@ func (c *Client) ToolSelect(ctx context.Context, messages []api.Message, tools [ // 构建聊天请求 req := &api.ChatRequest{ - Model: c.config.Model, - Messages: messages, - Stream: new(bool), // 设置为false,不使用流式响应 - Think: &api.ThinkValue{Value: false}, - Tools: tools, + Model: c.config.Model, + Messages: messages, + Stream: new(bool), // 设置为false,不使用流式响应 + Think: &api.ThinkValue{Value: false}, + Tools: tools, + KeepAlive: &api.Duration{Duration: 24 * time.Hour}, } err = c.client.Chat(ctx, req, func(resp api.ChatResponse) error { res = resp From c4e2d30fc559b4e25a685151845823a7802748ed Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 19 Jan 2026 15:32:45 +0800 Subject: [PATCH 18/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=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 --- config/config_test.yaml | 20 +++---- internal/biz/ding_talk_bot.go | 10 +++- internal/biz/do/handle.go | 60 +++++++++++++------ internal/biz/do/prompt.go | 1 + internal/biz/group_config.go | 11 +++- internal/entitys/bot.go | 10 ++++ internal/entitys/recognize.go | 1 + internal/entitys/types.go | 4 +- internal/tools/manager.go | 13 +++- internal/tools/public/coze_company.go | 2 +- internal/tools/public/coze_express.go | 2 +- internal/tools/public/konwledge_base.go | 2 +- internal/tools/public/normal_chat.go | 2 +- internal/tools/public/weather.go | 2 +- internal/tools/zltx/order_after_reseller.go | 2 +- .../tools/zltx/order_after_reseller_batch.go | 2 +- internal/tools/zltx/order_after_supplier.go | 2 +- internal/tools/zltx/zltx_order_detail.go | 46 +++++++++----- internal/tools/zltx/zltx_order_direct_log.go | 2 +- internal/tools/zltx/zltx_product.go | 2 +- internal/tools/zltx/zltx_statistics.go | 33 +++++++--- 21 files changed, 160 insertions(+), 69 deletions(-) diff --git a/config/config_test.yaml b/config/config_test.yaml index d7d519d..a6f07b9 100644 --- a/config/config_test.yaml +++ b/config/config_test.yaml @@ -4,10 +4,10 @@ server: host: "0.0.0.0" ollama: - base_url: "http://127.0.0.1:11434" - model: "qwen3-coder:480b-cloud" - generate_model: "qwen3-coder:480b-cloud" - mapping_model: "deepseek-v3.2:cloud" + base_url: "http://192.168.6.115:11434" + model: "qwen3:8b" + generate_model: "qwen3:8b" + mapping_model: "qwen3:8b" vl_model: "gemini-3-pro-preview" timeout: "120s" level: "info" @@ -26,11 +26,11 @@ coze: lsxd: # 统一登录 - 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" + 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" sys: @@ -43,7 +43,7 @@ redis: host: 47.97.27.195:6379 type: node pass: lansexiongdi@666 - key: ai_scheduler-test + key: ai_scheduler_test pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池 minIdleConns: 2 #最小空闲连接数 maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭 diff --git a/internal/biz/ding_talk_bot.go b/internal/biz/ding_talk_bot.go index d2fe01a..6773353 100644 --- a/internal/biz/ding_talk_bot.go +++ b/internal/biz/ding_talk_bot.go @@ -9,6 +9,7 @@ import ( "ai_scheduler/internal/data/impl" "ai_scheduler/internal/data/model" "ai_scheduler/internal/entitys" + "ai_scheduler/internal/pkg" "ai_scheduler/internal/tools" "ai_scheduler/internal/tools/bbxt" "ai_scheduler/tmpl/dataTemp" @@ -223,11 +224,16 @@ func (d *DingTalkBotBiz) recognize(ctx context.Context, requireData *entitys.Req rec.Tasks = append(rec.Tasks, entitys.RegistrationTask{ Name: task.Index, - Desc: task.Desc, + Desc: task.TempPrompt, TaskConfigDetail: taskConfig, // 直接使用解析后的配置,避免重复构建 }) } } + + rec.Ext = pkg.JsonByteIgonErr(&entitys.TaskExt{ + UserName: requireData.Req.SenderNick, + }) + err = d.handle.Recognize(ctx, rec, &do.WithDingTalkBot{}) return } @@ -393,7 +399,7 @@ func (d *DingTalkBotBiz) defaultPrompt() string { - 注意区分 parameters 中的 必须参数(required) 和 可选参数(optional),按下述参数提取规则处理。 - 若**完全无法匹配**,立即设置 is_match: false,并在 chat 中已第一人称的角度提醒用户需要适用何种工具(例:"请问您是要查询订单还是商品呢")。 -1. **参数提取**: +3. **参数提取**: - 根据 parameters 字段列出的参数名,从用户输入中提取对应值。 - **仅提取**明确提及的参数,忽略未列出的内容。 diff --git a/internal/biz/do/handle.go b/internal/biz/do/handle.go index afc4b2b..6001203 100644 --- a/internal/biz/do/handle.go +++ b/internal/biz/do/handle.go @@ -133,7 +133,9 @@ func (r *Handle) HandleMatch(ctx context.Context, client *gateway.Client, rec *e case constants.TaskTypeFunc: return r.handleTask(ctx, rec, pointTask) case constants.TaskTypeBot: - return r.handleBot(ctx, rec, pointTask) + return r.HandleBot(ctx, rec, &entitys.Task{ + Index: pointTask.Index, + }) case constants.TaskTypeEinoWorkflow: return r.handleEinoWorkflow(ctx, rec, pointTask) case constants.TaskTypeCozeWorkflow: @@ -247,23 +249,34 @@ func (r *Handle) handleKnowle(ctx context.Context, rec *entitys.Recognize, task } // bot 临时实现,后续转到 eino 工作流 -func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *model.AiTask) (err error) { +func (r *Handle) HandleBot(ctx context.Context, rec *entitys.Recognize, task *entitys.Task) (err error) { if task.Index == "bug_optimization_submit" { - entitys.ResLoading(rec.Ch, task.Index, "需求记录中...") - - // Ext 中获取 sessionId - sessionID := rec.GetSession() + var unionId string + entitys.ResLoading(rec.Ch, task.Index, "需求记录中...\n") // 获取dingtalk accessToken accessToken, _ := r.dingtalkOldClient.GetAccessToken() - // 获取创建者 dingtalk unionId - unionId := r.getUserDingtalkUnionId(ctx, accessToken, sessionID) + // Ext 中获取 sessionId + taskExt := rec.GetTaskExt() + if taskExt == nil { + return errorcode.ParamErr("taskExt参数错误") + } + if len(taskExt.Session) > 0 { + // 获取创建者 dingtalk unionId + unionId = r.getUserDingtalkUnionId(ctx, accessToken, taskExt.Session) + } else if len(taskExt.UserName) > 0 { + unionId = r.getUserDingtalkUnionIdWithUserName(ctx, accessToken, taskExt.UserName) + } else { + return errorcode.ParamErr("taskExt参数错误,重要参数缺失") + } + // 附件url var attachmentUrl string for _, file := range rec.UserContent.File { attachmentUrl = file.FileUrl break } - recordId, err := r.dingtalkNotableClient.InsertRecord(accessToken, &dingtalk.InsertRecordReq{ + + req := &dingtalk.InsertRecordReq{ BaseId: r.conf.Dingtalk.TableDemand.BaseId, SheetIdOrName: r.conf.Dingtalk.TableDemand.SheetIdOrName, // OperatorId: tool_callback.BotBugOptimizationSubmitAdminUnionId, @@ -271,7 +284,9 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo CreatorUnionId: unionId, Content: rec.UserContent.Text, AttachmentUrl: attachmentUrl, - }) + } + + recordId, err := r.dingtalkNotableClient.InsertRecord(accessToken, req) if err != nil { errCode := r.dingtalkNotableClient.GetHTTPStatus(err) // 权限不足 @@ -284,12 +299,16 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo if recordId == "" { return errors.NewBusinessErr(422, "创建记录失败,请联系管理员") } - + var detailPage string entitys.ResLog(rec.Ch, task.Index, "需求记录完成") - - // 构建跳转链接 - detailPage := util.BuildJumpLink(r.conf.Dingtalk.TableDemand.Url, "去查看") - + switch task.OutPutFormat { + case entitys.OutPutFormatMarkdown: + // 构建跳转链接 + detailPage = "[去查看](" + r.conf.Dingtalk.TableDemand.Url + ")" + default: + // 构建跳转链接 + detailPage = util.BuildJumpLink(r.conf.Dingtalk.TableDemand.Url, "去查看") + } entitys.ResText(rec.Ch, task.Index, fmt.Sprintf("需求已记录,正在分配相关人员处理,请您耐心等待处理结果。点击查看工单进度:%s", detailPage)) return nil @@ -300,16 +319,21 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo // getUserDingtalkUnionId 获取用户的 dingtalk unionId func (r *Handle) getUserDingtalkUnionId(ctx context.Context, accessToken, sessionID string) (unionId string) { - // 查询用户名 + if len(sessionID) == 0 { + // 查询用户名 + return "" + } session, has, err := r.sessionImpl.FindOne(r.sessionImpl.WithSessionId(sessionID)) if err != nil || !has { log.Warnf("session not found: %s", sessionID) return } - creatorName := session.UserName + return r.getUserDingtalkUnionIdWithUserName(ctx, accessToken, session.UserName) +} +func (r *Handle) getUserDingtalkUnionIdWithUserName(ctx context.Context, accessToken, userName string) (unionId string) { // 获取创建者uid 用户名 -> dingtalk uid - creatorId, err := r.dingtalkContactClient.SearchUserOne(accessToken, creatorName) + creatorId, err := r.dingtalkContactClient.SearchUserOne(accessToken, userName) if err != nil { log.Warnf("search dingtalk user one failed: %v", err) return diff --git a/internal/biz/do/prompt.go b/internal/biz/do/prompt.go index 3e4e965..231a31c 100644 --- a/internal/biz/do/prompt.go +++ b/internal/biz/do/prompt.go @@ -166,6 +166,7 @@ func (f *WithDingTalkBot) getUserContent(ctx context.Context, rec *entitys.Recog } if len(rec.ChatHis.Messages) > 0 { + content.WriteString("\n") content.WriteString("### 引用历史聊天记录:\n") content.WriteString(pkg.JsonStringIgonErr(rec.ChatHis)) } diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index 9a8bb82..f6a96eb 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -42,6 +42,7 @@ type GroupConfigBiz struct { conf *config.Config rdb *utils.Rdb macro *do.Macro + handle *do.Handle } // NewDingTalkBotBiz @@ -54,6 +55,8 @@ func NewGroupConfigBiz( reportDailyCacheImpl *impl.ReportDailyCacheImpl, rdb *utils.Rdb, macro *do.Macro, + toolManager *tools.Manager, + handle *do.Handle, ) *GroupConfigBiz { return &GroupConfigBiz{ botTools: tools.BootTools, @@ -64,6 +67,8 @@ func NewGroupConfigBiz( reportDailyCacheImpl: reportDailyCacheImpl, rdb: rdb, macro: macro, + toolManager: toolManager, + handle: handle, } } @@ -254,6 +259,11 @@ func (g *GroupConfigBiz) handleMatch(ctx context.Context, rec *entitys.Recognize switch constants.TaskType(pointTask.Type) { case constants.TaskTypeFunc: return g.handleTask(ctx, rec, pointTask) + case constants.TaskTypeBot: + return g.handle.HandleBot(ctx, rec, &entitys.Task{ + Index: pointTask.Index, + OutPutFormat: entitys.OutPutFormatMarkdown, + }) case constants.TaskTypeReport: return g.handleReport(ctx, rec, pointTask, groupConfig) case constants.TaskTypeCozeWorkflow: @@ -303,7 +313,6 @@ func (q *GroupConfigBiz) handleTask(ctx context.Context, rec *entitys.Recognize, if err != nil { return } - err = q.toolManager.ExecuteTool(ctx, configData.Tool, rec) if err != nil { return diff --git a/internal/entitys/bot.go b/internal/entitys/bot.go index ed0902c..0496898 100644 --- a/internal/entitys/bot.go +++ b/internal/entitys/bot.go @@ -21,3 +21,13 @@ type DingTalkBot struct { ClientId string `json:"client_id"` ClientSecret string `json:"client_secret"` } + +type Task struct { + Index string `json:"bot_index"` + OutPutFormat OutPutFormat `json:"out_put_format"` +} + +type OutPutFormat string + +const OutPutFormatMarkdown OutPutFormat = "markdown" +const OutPutFormatHtml OutPutFormat = "html" diff --git a/internal/entitys/recognize.go b/internal/entitys/recognize.go index fcd2fe5..accee4a 100644 --- a/internal/entitys/recognize.go +++ b/internal/entitys/recognize.go @@ -23,6 +23,7 @@ type TaskExt struct { SessionInfo model.AiSession Sys model.AiSy KnowledgeConf KnowledgeBaseRequest + UserName string } type RegistrationTask struct { diff --git a/internal/entitys/types.go b/internal/entitys/types.go index 815eeba..ab9e245 100644 --- a/internal/entitys/types.go +++ b/internal/entitys/types.go @@ -64,7 +64,9 @@ type FunctionCall struct { type ToolDefinition struct { Type string `json:"type"` Function FunctionDef `json:"function"` + AuthFunc AuthFunc `json:"function"` } +type AuthFunc func(rec *Recognize) (token []byte, err error) // FunctionDef 函数定义 type FunctionDef struct { @@ -77,7 +79,7 @@ type FunctionDef struct { type Tool interface { Name() string Description() string - Definition() ToolDefinition + Definition(ctx context.Context) ToolDefinition Execute(ctx context.Context, requireData *Recognize) error } diff --git a/internal/tools/manager.go b/internal/tools/manager.go index eedb4ee..d46d067 100644 --- a/internal/tools/manager.go +++ b/internal/tools/manager.go @@ -6,6 +6,7 @@ import ( "ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/tools/public" zltxtool "ai_scheduler/internal/tools/zltx" + "ai_scheduler/utils" "context" "fmt" @@ -15,10 +16,11 @@ import ( type Manager struct { tools map[string]entitys.Tool llm *utils_ollama.Client + rdb *utils.Rdb } // NewManager 创建工具管理器 -func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager { +func NewManager(config *config.Config, llm *utils_ollama.Client, rdb *utils.Rdb) *Manager { m := &Manager{ tools: make(map[string]entitys.Tool), llm: llm, @@ -26,7 +28,7 @@ func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager { // 注册直连天下订单详情工具 if config.Tools.ZltxOrderDetail.Enabled { - zltxOrderDetailTool := zltxtool.NewZltxOrderDetailTool(config.Tools.ZltxOrderDetail, m.llm) + zltxOrderDetailTool := zltxtool.NewZltxOrderDetailTool(config, rdb, m.llm) m.tools[zltxOrderDetailTool.Name()] = zltxOrderDetailTool } @@ -43,7 +45,7 @@ func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager { } //注册直连天下订单统计工具 if config.Tools.ZltxOrderStatistics.Enabled { - zltxOrderStatisticsTool := zltxtool.NewZltxOrderStatisticsTool(config.Tools.ZltxOrderStatistics) + zltxOrderStatisticsTool := zltxtool.NewZltxOrderStatisticsTool(config, rdb) m.tools[zltxOrderStatisticsTool.Name()] = zltxOrderStatisticsTool } @@ -104,5 +106,10 @@ func (m *Manager) ExecuteTool(ctx context.Context, name string, rec *entitys.Rec return fmt.Errorf("tool not found: %s", name) } + return m.ExecuteToolWithToolObj(ctx, tool, rec) +} + +// ExecuteTool 执行工具 +func (m *Manager) ExecuteToolWithToolObj(ctx context.Context, tool entitys.Tool, rec *entitys.Recognize) error { return tool.Execute(ctx, rec) } diff --git a/internal/tools/public/coze_company.go b/internal/tools/public/coze_company.go index e061965..722423d 100644 --- a/internal/tools/public/coze_company.go +++ b/internal/tools/public/coze_company.go @@ -50,7 +50,7 @@ func (c *CozeCompany) Description() string { } // Definition 返回工具定义 -func (c *CozeCompany) Definition() entitys.ToolDefinition { +func (c *CozeCompany) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ diff --git a/internal/tools/public/coze_express.go b/internal/tools/public/coze_express.go index 58e6172..f8608fc 100644 --- a/internal/tools/public/coze_express.go +++ b/internal/tools/public/coze_express.go @@ -47,7 +47,7 @@ func (c *CozeExpress) Description() string { } // Definition 返回工具定义 -func (c *CozeExpress) Definition() entitys.ToolDefinition { +func (c *CozeExpress) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ diff --git a/internal/tools/public/konwledge_base.go b/internal/tools/public/konwledge_base.go index 48ddc1e..133b63c 100644 --- a/internal/tools/public/konwledge_base.go +++ b/internal/tools/public/konwledge_base.go @@ -38,7 +38,7 @@ func (k *KnowledgeBaseTool) Description() string { } // Definition 返回工具定义 -func (k *KnowledgeBaseTool) Definition() entitys.ToolDefinition { +func (k *KnowledgeBaseTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ diff --git a/internal/tools/public/normal_chat.go b/internal/tools/public/normal_chat.go index cde667c..9206187 100644 --- a/internal/tools/public/normal_chat.go +++ b/internal/tools/public/normal_chat.go @@ -38,7 +38,7 @@ type NormalChat struct { } // Definition 返回工具定义 -func (w *NormalChatTool) Definition() entitys.ToolDefinition { +func (w *NormalChatTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{} } diff --git a/internal/tools/public/weather.go b/internal/tools/public/weather.go index ca36907..84b7af1 100644 --- a/internal/tools/public/weather.go +++ b/internal/tools/public/weather.go @@ -35,7 +35,7 @@ func (w *WeatherTool) Description() string { } // Definition 返回工具定义 -func (w *WeatherTool) Definition() entitys.ToolDefinition { +func (w *WeatherTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ diff --git a/internal/tools/zltx/order_after_reseller.go b/internal/tools/zltx/order_after_reseller.go index fcb71e0..effa369 100644 --- a/internal/tools/zltx/order_after_reseller.go +++ b/internal/tools/zltx/order_after_reseller.go @@ -33,7 +33,7 @@ func (t *OrderAfterSaleResellerTool) Description() string { } // 未使用-仅实现接口 -func (t *OrderAfterSaleResellerTool) Definition() entitys.ToolDefinition { +func (t *OrderAfterSaleResellerTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{} } diff --git a/internal/tools/zltx/order_after_reseller_batch.go b/internal/tools/zltx/order_after_reseller_batch.go index 664d3d5..e775f0b 100644 --- a/internal/tools/zltx/order_after_reseller_batch.go +++ b/internal/tools/zltx/order_after_reseller_batch.go @@ -31,7 +31,7 @@ func (t *OrderAfterSaleResellerBatchTool) Description() string { } // 未使用-仅实现接口 -func (t *OrderAfterSaleResellerBatchTool) Definition() entitys.ToolDefinition { +func (t *OrderAfterSaleResellerBatchTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{} } diff --git a/internal/tools/zltx/order_after_supplier.go b/internal/tools/zltx/order_after_supplier.go index 196fb64..2a81809 100644 --- a/internal/tools/zltx/order_after_supplier.go +++ b/internal/tools/zltx/order_after_supplier.go @@ -33,7 +33,7 @@ func (t *OrderAfterSaleSupplierTool) Description() string { } // 未使用-仅实现接口 -func (t *OrderAfterSaleSupplierTool) Definition() entitys.ToolDefinition { +func (t *OrderAfterSaleSupplierTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{} } diff --git a/internal/tools/zltx/zltx_order_detail.go b/internal/tools/zltx/zltx_order_detail.go index 6e33e63..19b4452 100644 --- a/internal/tools/zltx/zltx_order_detail.go +++ b/internal/tools/zltx/zltx_order_detail.go @@ -4,26 +4,28 @@ import ( "ai_scheduler/internal/config" "ai_scheduler/internal/entitys" "ai_scheduler/internal/pkg" + "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/rec_extra" "ai_scheduler/internal/pkg/utils_ollama" + "ai_scheduler/utils" "context" "encoding/json" "fmt" "gitea.cdlsxd.cn/self-tools/l_request" - "github.com/gofiber/fiber/v2/log" "github.com/ollama/ollama/api" ) // ZltxOrderDetailTool 直连天下订单详情工具 type ZltxOrderDetailTool struct { - config config.ToolConfig + config *config.Config llm *utils_ollama.Client + rdb *utils.Rdb } // NewZltxOrderDetailTool 创建直连天下订单详情工具 -func NewZltxOrderDetailTool(config config.ToolConfig, llm *utils_ollama.Client) *ZltxOrderDetailTool { - return &ZltxOrderDetailTool{config: config, llm: llm} +func NewZltxOrderDetailTool(config *config.Config, rdb *utils.Rdb, llm *utils_ollama.Client) *ZltxOrderDetailTool { + return &ZltxOrderDetailTool{config: config, rdb: rdb, llm: llm} } // Name 返回工具名称 @@ -37,7 +39,7 @@ func (w *ZltxOrderDetailTool) Description() string { } // Definition 返回工具定义 -func (w *ZltxOrderDetailTool) Definition() entitys.ToolDefinition { +func (w *ZltxOrderDetailTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ @@ -54,6 +56,19 @@ func (w *ZltxOrderDetailTool) Definition() entitys.ToolDefinition { "required": []string{"number"}, }, }, + AuthFunc: func(rec *entitys.Recognize) ([]byte, error) { + ext, err := rec_extra.GetTaskRecExt(rec) + if err != nil { + return nil, err + } + if len(ext.Auth) > 0 { + return []byte(ext.Auth), nil + } else { + login := lsxd.NewLogin(w.config, w.rdb) + token := login.GetToken(ctx) + return []byte(token), nil + } + }, } } @@ -93,7 +108,7 @@ func (w *ZltxOrderDetailTool) Execute(ctx context.Context, rec *entitys.Recogniz } // 这里可以集成真实的直连天下订单详情API - return w.getZltxOrderDetail(rec, req.OrderNumber) + return w.getZltxOrderDetail(ctx, rec, req.OrderNumber) } func (r *ZltxOrderDetailRequest) UnmarshalJSON(data []byte) error { @@ -113,8 +128,8 @@ func (r *ZltxOrderDetailRequest) UnmarshalJSON(data []byte) error { } // getMockZltxOrderDetail 获取模拟直连天下订单详情数据 -func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number interface{}) (err error) { - log.Infof("订单编号:%v,类型:%v") +func (w *ZltxOrderDetailTool) getZltxOrderDetail(ctx context.Context, rec *entitys.Recognize, number interface{}) (err error) { + var orderNum string switch number.(type) { case int, int32, int64: @@ -127,15 +142,15 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number orderNum = fmt.Sprintf("%v", number) } - ext, err := rec_extra.GetTaskRecExt(rec) + token, err := w.Definition(ctx).AuthFunc(rec) if err != nil { - return + return err } //查询订单详情 req := l_request.Request{ - Url: fmt.Sprintf(w.config.BaseURL, orderNum), + Url: fmt.Sprintf(w.config.Tools.ZltxOrderDetail.BaseURL, orderNum), Headers: map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", ext.Auth), + "Authorization": fmt.Sprintf("Bearer %s", token), }, Method: "GET", } @@ -160,11 +175,10 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number if resData.Data.Direct != nil { entitys.ResLoading(rec.Ch, w.Name(), "正在分析订单日志") - req = l_request.Request{ - Url: fmt.Sprintf(w.config.AddURL, resData.Data.Direct["orderOrderNumber"].(string), resData.Data.Direct["serialNumber"].(string)), + Url: fmt.Sprintf(w.config.Tools.ZltxOrderDetail.AddURL, resData.Data.Direct["orderOrderNumber"].(string), resData.Data.Direct["serialNumber"].(string)), Headers: map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", ext.Auth), + "Authorization": fmt.Sprintf("Bearer %s", token), }, Method: "GET", } @@ -184,7 +198,7 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number return fmt.Errorf("订单日志解析失败:%s", err) } - err = w.llm.ChatStream(context.TODO(), rec.Ch, []api.Message{ + err = w.llm.ChatStream(ctx, rec.Ch, []api.Message{ { Role: "system", Content: "你是一个订单日志助手。用户可能会提供订单日志,你需要按以下规则处理:\n" + diff --git a/internal/tools/zltx/zltx_order_direct_log.go b/internal/tools/zltx/zltx_order_direct_log.go index 188a954..3ec9156 100644 --- a/internal/tools/zltx/zltx_order_direct_log.go +++ b/internal/tools/zltx/zltx_order_direct_log.go @@ -23,7 +23,7 @@ func (t *ZltxOrderLogTool) Description() string { return "查询订单日志" } -func (t *ZltxOrderLogTool) Definition() entitys.ToolDefinition { +func (t *ZltxOrderLogTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ diff --git a/internal/tools/zltx/zltx_product.go b/internal/tools/zltx/zltx_product.go index 0c63d84..2ed7e78 100644 --- a/internal/tools/zltx/zltx_product.go +++ b/internal/tools/zltx/zltx_product.go @@ -25,7 +25,7 @@ func (z ZltxProductTool) Description() string { return "获取直连天下商品信息" } -func (z ZltxProductTool) Definition() entitys.ToolDefinition { +func (z ZltxProductTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ diff --git a/internal/tools/zltx/zltx_statistics.go b/internal/tools/zltx/zltx_statistics.go index 29e143a..6c12235 100644 --- a/internal/tools/zltx/zltx_statistics.go +++ b/internal/tools/zltx/zltx_statistics.go @@ -3,7 +3,9 @@ package zltx import ( "ai_scheduler/internal/config" "ai_scheduler/internal/entitys" + "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/rec_extra" + "ai_scheduler/utils" "context" "encoding/json" "fmt" @@ -13,7 +15,8 @@ import ( ) type ZltxOrderStatisticsTool struct { - config config.ToolConfig + config *config.Config + rdb *utils.Rdb } func (z ZltxOrderStatisticsTool) Name() string { @@ -24,7 +27,7 @@ func (z ZltxOrderStatisticsTool) Description() string { return "通过账号获取订单统计信息" } -func (z ZltxOrderStatisticsTool) Definition() entitys.ToolDefinition { +func (z ZltxOrderStatisticsTool) Definition(ctx context.Context) entitys.ToolDefinition { return entitys.ToolDefinition{ Type: "function", Function: entitys.FunctionDef{ @@ -41,6 +44,19 @@ func (z ZltxOrderStatisticsTool) Definition() entitys.ToolDefinition { "required": []string{"number"}, }, }, + AuthFunc: func(rec *entitys.Recognize) ([]byte, error) { + ext, err := rec_extra.GetTaskRecExt(rec) + if err != nil { + return nil, err + } + if len(ext.Auth) > 0 { + return []byte(ext.Auth), nil + } else { + login := lsxd.NewLogin(z.config, z.rdb) + token := login.GetToken(ctx) + return []byte(token), nil + } + }, } } @@ -56,7 +72,7 @@ func (z ZltxOrderStatisticsTool) Execute(ctx context.Context, rec *entitys.Recog if req.Number == nil { return fmt.Errorf("number is required") } - return z.getZltxOrderStatistics(req.Number, rec) + return z.getZltxOrderStatistics(ctx, req.Number, rec) } type ZltxOrderStatisticsResponse struct { @@ -76,17 +92,17 @@ type ZltxOrderStatisticsData struct { Total int `json:"total"` } -func (z ZltxOrderStatisticsTool) getZltxOrderStatistics(number interface{}, rec *entitys.Recognize) error { - ext, err := rec_extra.GetTaskRecExt(rec) +func (z ZltxOrderStatisticsTool) getZltxOrderStatistics(ctx context.Context, number interface{}, rec *entitys.Recognize) error { + token, err := z.Definition(ctx).AuthFunc(rec) if err != nil { return err } //查询订单详情 - url := fmt.Sprintf("%s%s", z.config.BaseURL, fmt.Sprintf("%v", number)) + url := fmt.Sprintf("%s%s", z.config.Tools.ZltxOrderStatistics.BaseURL, fmt.Sprintf("%v", number)) req := l_request.Request{ Url: url, Headers: map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", ext.Auth), + "Authorization": fmt.Sprintf("Bearer %s", string(token)), }, Method: "GET", } @@ -116,8 +132,9 @@ func (z ZltxOrderStatisticsTool) getZltxOrderStatistics(number interface{}, rec return nil } -func NewZltxOrderStatisticsTool(config config.ToolConfig) *ZltxOrderStatisticsTool { +func NewZltxOrderStatisticsTool(config *config.Config, rdb *utils.Rdb) *ZltxOrderStatisticsTool { return &ZltxOrderStatisticsTool{ config: config, + rdb: rdb, } } From 6a58919e8e26c28d977c64ac69ed1e0b6244e5e7 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 19 Jan 2026 16:45:21 +0800 Subject: [PATCH 19/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E8=B4=9F?= =?UTF-8?q?=E5=88=A9=E6=B6=A6=E5=88=86=E6=9E=90=E5=92=8C=E7=BC=93=E5=AD=98?= =?UTF-8?q?=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 --- internal/biz/do/handle.go | 4 +- internal/biz/group_config.go | 5 +- internal/entitys/bot.go | 8 +- internal/entitys/recognize.go | 6 + internal/tools/zltx/zltx_order_detail.go | 173 +++++++++++++++++++++-- 5 files changed, 177 insertions(+), 19 deletions(-) diff --git a/internal/biz/do/handle.go b/internal/biz/do/handle.go index 6001203..81c70b7 100644 --- a/internal/biz/do/handle.go +++ b/internal/biz/do/handle.go @@ -301,8 +301,8 @@ func (r *Handle) HandleBot(ctx context.Context, rec *entitys.Recognize, task *en } var detailPage string entitys.ResLog(rec.Ch, task.Index, "需求记录完成") - switch task.OutPutFormat { - case entitys.OutPutFormatMarkdown: + switch rec.OutPutScene { + case entitys.OutPutSceneDingTalk: // 构建跳转链接 detailPage = "[去查看](" + r.conf.Dingtalk.TableDemand.Url + ")" default: diff --git a/internal/biz/group_config.go b/internal/biz/group_config.go index f6a96eb..0c6dbbc 100644 --- a/internal/biz/group_config.go +++ b/internal/biz/group_config.go @@ -253,16 +253,17 @@ func (g *GroupConfigBiz) handleMatch(ctx context.Context, rec *entitys.Recognize break } } + rec.OutPutScene = entitys.OutPutSceneDingTalk if pointTask == nil || pointTask.Index == "other" { return g.otherTask(ctx, rec) } + switch constants.TaskType(pointTask.Type) { case constants.TaskTypeFunc: return g.handleTask(ctx, rec, pointTask) case constants.TaskTypeBot: return g.handle.HandleBot(ctx, rec, &entitys.Task{ - Index: pointTask.Index, - OutPutFormat: entitys.OutPutFormatMarkdown, + Index: pointTask.Index, }) case constants.TaskTypeReport: return g.handleReport(ctx, rec, pointTask, groupConfig) diff --git a/internal/entitys/bot.go b/internal/entitys/bot.go index 0496898..03b1a09 100644 --- a/internal/entitys/bot.go +++ b/internal/entitys/bot.go @@ -23,11 +23,5 @@ type DingTalkBot struct { } type Task struct { - Index string `json:"bot_index"` - OutPutFormat OutPutFormat `json:"out_put_format"` + Index string `json:"bot_index"` } - -type OutPutFormat string - -const OutPutFormatMarkdown OutPutFormat = "markdown" -const OutPutFormatHtml OutPutFormat = "html" diff --git a/internal/entitys/recognize.go b/internal/entitys/recognize.go index accee4a..57a92e0 100644 --- a/internal/entitys/recognize.go +++ b/internal/entitys/recognize.go @@ -14,8 +14,14 @@ type Recognize struct { Ch chan Response Match *Match Ext []byte + OutPutScene OutPutScene } +type OutPutScene string + +const OutPutSceneDingTalk OutPutScene = "markdown" +const OutPutFormatHtml OutPutScene = "html" + type TaskExt struct { Auth string `json:"auth"` Session string `json:"session"` diff --git a/internal/tools/zltx/zltx_order_detail.go b/internal/tools/zltx/zltx_order_detail.go index 19b4452..7546149 100644 --- a/internal/tools/zltx/zltx_order_detail.go +++ b/internal/tools/zltx/zltx_order_detail.go @@ -11,6 +11,8 @@ import ( "context" "encoding/json" "fmt" + "strings" + "time" "gitea.cdlsxd.cn/self-tools/l_request" "github.com/ollama/ollama/api" @@ -77,14 +79,74 @@ type ZltxOrderDetailRequest struct { OrderNumber interface{} `json:"order_number"` } +//type ZltxOrderDetailResponse struct { +// Code int `json:"code"` +// Error string `json:"error"` +// Data ZltxOrderDetailData `json:"data"` +// Mes string `json:"mes"` +//} + // ZltxOrderDetailResponse 直连天下订单详情响应 type ZltxOrderDetailResponse struct { - Code int `json:"code"` - Error string `json:"error"` - Data ZltxOrderDetailData `json:"data"` - Mes string `json:"mes"` + Code int `json:"code"` + Data Data `json:"data"` + Error string `json:"error"` } +type Data struct { + Direct *Direct `json:"direct"` + Order *Order `json:"order"` +} + +type Direct struct { + SerialNumber string `json:"serialNumber"` + OrderOrderNumber string `json:"orderOrderNumber"` + TerminalAccount string `json:"terminalAccount"` + OursProductId int `json:"oursProductId"` + OursProductName string `json:"oursProductName"` + Status int `json:"status"` + TradePrice float64 `json:"tradePrice"` + PlatformProductId int `json:"platformProductId"` + PlatformProductName string `json:"platformProductName"` + PlatformId int `json:"platformId"` + PlatformName string `json:"platformName"` + PlatformPrice float64 `json:"platformPrice"` + CreateTime int `json:"createTime"` + ExecuteTime int `json:"executeTime"` + Type int `json:"type"` + Reason string `json:"reason"` + ResellerId int `json:"resellerId"` + ResellerName string `json:"resellerName"` + Aftermarket int `json:"aftermarket"` + PurchasePrice float64 `json:"purchasePrice"` + NeedAi bool `json:"needAi"` + AiReason string `json:"aiReason"` +} + +type Order struct { + Id string `json:"id"` + ResellerId int `json:"resellerId"` + ResellerName string `json:"resellerName"` + Status int `json:"status"` + PayStatus int `json:"payStatus"` + CreateTime int `json:"createTime"` + PayTime int `json:"payTime"` + Type int `json:"type"` + Account string `json:"account"` + Quantity int `json:"quantity"` + Amount float64 `json:"amount"` + PayAmount float64 `json:"payAmount"` + ResellerOrderNumber string `json:"resellerOrderNumber"` + Price int `json:"price"` + NotifyTime int `json:"notifyTime"` + FinishTime int `json:"finishTime"` + Aftermarket int `json:"aftermarket"` + Remark string `json:"remark"` + OursProductId int `json:"oursProductId"` + OursProductName string `json:"oursProductName"` + OursProductPrice int `json:"oursProductPrice"` + TradePrice float64 `json:"tradePrice"` +} type ZltxOrderLogResponse struct { Code int `json:"code"` Error string `json:"error"` @@ -171,12 +233,15 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(ctx context.Context, rec *entit if err = json.Unmarshal(res.Content, &resData); err != nil { return } - entitys.ResJson(rec.Ch, w.Name(), res.Text) - - if resData.Data.Direct != nil { + if rec.OutPutScene == entitys.OutPutSceneDingTalk { + entitys.ResJson(rec.Ch, w.Name(), resData.ToForm()) + } else { + entitys.ResJson(rec.Ch, w.Name(), res.Text) entitys.ResLoading(rec.Ch, w.Name(), "正在分析订单日志") + } + if resData.Data.Direct != nil { req = l_request.Request{ - Url: fmt.Sprintf(w.config.Tools.ZltxOrderDetail.AddURL, resData.Data.Direct["orderOrderNumber"].(string), resData.Data.Direct["serialNumber"].(string)), + Url: fmt.Sprintf(w.config.Tools.ZltxOrderDetail.AddURL, resData.Data.Direct.OrderOrderNumber, resData.Data.Direct.SerialNumber), Headers: map[string]string{ "Authorization": fmt.Sprintf("Bearer %s", token), }, @@ -230,3 +295,95 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(ctx context.Context, rec *entit } return } + +func (z *ZltxOrderDetailResponse) ToForm() string { + var res strings.Builder + res.WriteString("**普通订单** \n") + res.WriteString("\n## 订单号:" + z.Data.Order.Id) + res.WriteString("\n## 分销商订单号:" + z.Data.Order.ResellerOrderNumber) + res.WriteString("\n## 分销商:" + z.Data.Order.ResellerName) + res.WriteString("\n## 订单商品:" + z.Data.Order.OursProductName) + res.WriteString("\n## 充值账号:" + z.Data.Order.Account) + res.WriteString("\n## 折扣价/原价:" + fmt.Sprintf("%.2f", z.Data.Order.TradePrice)) + res.WriteString("\n## 数量:" + fmt.Sprintf("%d", z.Data.Order.Quantity)) + res.WriteString("\n## 订单总额:" + fmt.Sprintf("%.2f", z.Data.Order.Amount)) + res.WriteString("\n## 订单状态:" + orderStatusMap(z.Data.Order.Status)) + res.WriteString("\n## 支付状态:" + orderPayStatusMap(z.Data.Order.Status)) + res.WriteString("\n## 创建时间:" + unixToDateFormat(z.Data.Order.CreateTime)) + res.WriteString("\n## 完成时间:" + unixToDateFormat(z.Data.Order.FinishTime)) + res.WriteString("\n---\n") + + res.WriteString("\n**充值流水** \n") + res.WriteString("\n## 订单号:" + z.Data.Direct.OrderOrderNumber) + res.WriteString("\n## 流水号:" + z.Data.Direct.SerialNumber) + res.WriteString("\n## 商品:" + z.Data.Direct.OursProductName) + res.WriteString("\n## 使用接口:" + z.Data.Direct.PlatformName) + res.WriteString("\n## 接口商品名称:" + z.Data.Direct.PlatformProductName) + res.WriteString("\n## 上游价:" + fmt.Sprintf("%.2f", z.Data.Direct.PlatformPrice)) + res.WriteString("\n## 下游价:" + fmt.Sprintf("%.2f", z.Data.Direct.TradePrice)) + res.WriteString("\n## 上游采购价:" + fmt.Sprintf("%.2f", z.Data.Direct.PurchasePrice)) + res.WriteString("\n## 充值账号:" + z.Data.Direct.TerminalAccount) + res.WriteString("\n## 创建时间:" + unixToDateFormat(z.Data.Direct.CreateTime)) + res.WriteString("\n## 处理时间:" + unixToDateFormat(z.Data.Direct.ExecuteTime)) + res.WriteString("\n## 状态:" + directStatusMap(z.Data.Direct.Status)) + res.WriteString("\n") + res.WriteString("\n") + res.WriteString("\n") + return res.String() +} + +func orderStatusMap(status int) string { + var OrderStatus = map[int]string{ + 0: "下单中", + 1: "订单完成", + 2: "部分成功", + 3: "充值处理中", + 4: "已暂停", + -1: "关闭订单", + -2: "全部失败", + } + if _, ok := OrderStatus[status]; !ok { + return "未知" + } + return OrderStatus[status] +} + +func unixToDateFormat(unix int) string { + return time.Unix(int64(unix), 0).Format("2006-01-02 15:04:05") +} +func orderPayStatusMap(status int) string { + var OrderPayStatus = map[int]string{ + 0: "未支付", + 1: "支付中", + 2: "支付成功", + 3: "退款中", + 4: "全部退款", + 5: "部分退款", + -1: "支付失败", + -2: "退款失败", + } + if _, ok := OrderPayStatus[status]; !ok { + return "未知" + } + return OrderPayStatus[status] +} + +func directStatusMap(status int) string { + var DirectStatus = map[int]string{ + 0: "待充值", + 1: "充值成功", + 2: "充值中", + -1: "充值失败", + -2: "失败重试", + -98: "下单异常", + -99: "查询异常", + -6: "手动失败", + -5: "手动重试", + -4: "叠加卡单", + -3: "卡单", + } + if _, ok := DirectStatus[status]; !ok { + return "未知" + } + return DirectStatus[status] +} From 5c2d7176c7b18bd2acceab5b2c27eb428476193a Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Tue, 20 Jan 2026 10:32:42 +0800 Subject: [PATCH 20/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E4=BA=8F?= =?UTF-8?q?=E6=8D=9F=E5=95=86=E5=93=81=E7=BB=9F=E8=AE=A1=E6=A0=87=E9=A2=98?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/domain/workflow/recharge/statistics_ours_product.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/domain/workflow/recharge/statistics_ours_product.go b/internal/domain/workflow/recharge/statistics_ours_product.go index 278d32b..3ef2e5a 100644 --- a/internal/domain/workflow/recharge/statistics_ours_product.go +++ b/internal/domain/workflow/recharge/statistics_ours_product.go @@ -125,7 +125,7 @@ func (w *statisticsOursProduct) formatContext(ctx context.Context, input *Statis Time: time.Now(), StartTime: startTime, EndTime: endTime, - Title: fmt.Sprintf("截止 %s 亏损100以上我们的商品统计", endTimeStr), + Title: fmt.Sprintf("截止 %s 电商系统亏损100以上我们的商品统计", endTimeStr), }, nil } From c478e9f43deb6c1686abe6abccaba958cf8158bf Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Wed, 21 Jan 2026 15:10:24 +0800 Subject: [PATCH 21/30] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=AE=98?= =?UTF-8?q?=E6=96=B9=E4=BA=A7=E5=93=81=E7=BB=9F=E8=AE=A1=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=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 --- internal/tools/bbxt/bbxt.go | 8 ++++---- internal/tools/bbxt/bbxt_test.go | 14 +++++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/internal/tools/bbxt/bbxt.go b/internal/tools/bbxt/bbxt.go index 345f982..3281325 100644 --- a/internal/tools/bbxt/bbxt.go +++ b/internal/tools/bbxt/bbxt.go @@ -428,7 +428,7 @@ func (b *BbxtTools) GetStatisOfficialProductSum(now time.Time, productName []str if err != nil { return } - var total = make([][]string, len(ids)) + var total = make([][]string, 0) for _, v := range data.OfficialProductSum { var ( yeterDatyDiff string @@ -444,16 +444,16 @@ func (b *BbxtTools) GetStatisOfficialProductSum(now time.Time, productName []str } else { lastWeekDiff = fmt.Sprintf("%s↓%d", GreenStyle, v.HistoryTwoDiff) } - total[productMap[v.OfficialProductName]] = []string{ + total = append(total, []string{ fmt.Sprintf("%s", v.OfficialProductName), fmt.Sprintf("%d", v.CurrentNum), fmt.Sprintf("%d", v.HistoryOneNum), yeterDatyDiff, fmt.Sprintf("%d", v.HistoryTwoNum), lastWeekDiff, - } - + }) } + timeCh := now.Format("1月2日15点") title := "截至" + timeCh + "销售同比分析" //总量生成excel diff --git a/internal/tools/bbxt/bbxt_test.go b/internal/tools/bbxt/bbxt_test.go index c586eda..3d0f623 100644 --- a/internal/tools/bbxt/bbxt_test.go +++ b/internal/tools/bbxt/bbxt_test.go @@ -79,14 +79,22 @@ func Test_GetStatisOfficialProductSumDecline(t *testing.T) { } func Test_GetStatisOfficialProductSum(t *testing.T) { - + run() configs := configConfig o, err := NewBbxtTools(nil, lsxd.NewLogin(configs, utils.NewRdb(configConfig))) if err != nil { panic(err) } - s := "官方--美团外卖红包5元,官方--美团外卖红包10元,官方--饿了么超级会员月卡,官方--网易云黑胶vip月卡,官方--喜马拉雅巅峰会员月卡,官方--芒果-PC季卡,官方--芒果-PC月卡,官方--芒果-PC周卡,官方--腾讯-周卡,官方--优酷周卡,官方--QQ音乐-绿钻月卡,官方--爱奇艺-周卡,官方--腾讯-月卡,官方--腾讯-季卡,官方--腾讯-年卡,官方--优酷月卡,官方--优酷季卡,官方--优酷年卡,官方--爱奇艺-月卡,官方--爱奇艺-季卡,官方--爱奇艺-年卡" - report, err := o.GetStatisOfficialProductSum(time.Now(), strings.Split(s, ",")) + s := "官方--腾讯-周卡,官方--腾讯-月卡,官方--腾讯-季卡,官方--腾讯-年卡,官方--优酷周卡,官方--优酷月卡,官方--优酷季卡,官方--优酷年卡,官方--爱奇艺-周卡,官方--爱奇艺-月卡,官方--爱奇艺-季卡,官方--爱奇艺-年卡,官方--芒果-PC周卡,官方--芒果-PC月卡,官方--芒果-PC季卡,官方--美团外卖红包5元,官方--美团外卖红包10元,官方--QQ音乐-绿钻月卡,官方--饿了么超级会员月卡,官方--网易云黑胶vip月卡,官方--喜马拉雅巅峰会员月卡" + now := time.Now() + noon := time.Date( + now.Year(), + now.Month(), + now.Day(), + 12, 0, 0, 0, + now.Location(), + ) + report, err := o.GetStatisOfficialProductSum(noon, strings.Split(s, ",")) t.Log(report, err) From a155cb1e0199ea3ef4a6910e32f66bf5370445f9 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 26 Jan 2026 17:07:04 +0800 Subject: [PATCH 22/30] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=94=80=E9=87=8F?= =?UTF-8?q?=E5=90=8C=E6=AF=94=E5=88=86=E6=9E=90=E6=95=B0=E6=8D=AE=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/tools/bbxt/bbxt.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/internal/tools/bbxt/bbxt.go b/internal/tools/bbxt/bbxt.go index 3281325..7a03cce 100644 --- a/internal/tools/bbxt/bbxt.go +++ b/internal/tools/bbxt/bbxt.go @@ -403,10 +403,6 @@ func (b *BbxtTools) GetProfitRankingSum(now time.Time) (report *ReportRes, err e // GetStatisOfficialProductSum 销量同比分析 func (b *BbxtTools) GetStatisOfficialProductSum(now time.Time, productName []string) (report *ReportRes, err error) { - var productMap = make(map[string]int) - for k, v := range productName { - productMap[v] = k - } ct := []string{ time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Format("2006-01-02 15:04:05"), adjustedTime(now), @@ -428,7 +424,11 @@ func (b *BbxtTools) GetStatisOfficialProductSum(now time.Time, productName []str if err != nil { return } - var total = make([][]string, 0) + + // 创建临时map存储产品数据 + productDataMap := make(map[string][]string) + var productNamesInResult []string + for _, v := range data.OfficialProductSum { var ( yeterDatyDiff string @@ -444,14 +444,28 @@ func (b *BbxtTools) GetStatisOfficialProductSum(now time.Time, productName []str } else { lastWeekDiff = fmt.Sprintf("%s↓%d", GreenStyle, v.HistoryTwoDiff) } - total = append(total, []string{ + + rowData := []string{ fmt.Sprintf("%s", v.OfficialProductName), fmt.Sprintf("%d", v.CurrentNum), fmt.Sprintf("%d", v.HistoryOneNum), yeterDatyDiff, fmt.Sprintf("%d", v.HistoryTwoNum), lastWeekDiff, - }) + } + + // 存储到map中,key为产品名 + productDataMap[v.OfficialProductName] = rowData + productNamesInResult = append(productNamesInResult, v.OfficialProductName) + } + + // 按照productName的顺序构建total + var total [][]string + + for _, name := range productName { + if rowData, exists := productDataMap[name]; exists { + total = append(total, rowData) + } } timeCh := now.Format("1月2日15点") From 88ed4ff714939501e64132e6fba96dcab37aeaf6 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Tue, 27 Jan 2026 17:13:19 +0800 Subject: [PATCH 23/30] =?UTF-8?q?fix:=20=E7=BA=BF=E4=B8=8A=E4=BD=BF?= =?UTF-8?q?=E7=94=A8ollama=E4=BA=91=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index 6166634..dff34ce 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -5,9 +5,12 @@ server: ollama: base_url: "http://172.17.0.1:11434" - model: "qwen3:8b" - generate_model: "qwen3:8b" - mapping_model: "qwen3:8b" + # model: "qwen3:8b" + # generate_model: "qwen3:8b" + # mapping_model: "qwen3:8b" + model: "qwen3-coder:480b-cloud" + generate_model: "qwen3-coder:480b-cloud" + mapping_model: "deepseek-v3.2:cloud" vl_model: "qwen2.5vl:3b" timeout: "120s" level: "info" From ce74a27b539589b1be16f459425abf5cc86a29ac Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Wed, 28 Jan 2026 18:37:26 +0800 Subject: [PATCH 24/30] =?UTF-8?q?fix=EF=BC=9A=E5=88=87=E6=8D=A2=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20excel2pic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index dff34ce..cf02c96 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -149,7 +149,7 @@ eino_tools: # == 通用工具 == # 表格转图片 excel2pic: - base_url: "http://excel2pic:8000/api/v1/convert" + base_url: "http://192.168.6.109:8000/api/v1/convert" dingtalk: api_key: "dingsbbntrkeiyazcfdg" From b1c5bfa6f54b864c755936afaa006df831e0373c Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Wed, 28 Jan 2026 18:44:04 +0800 Subject: [PATCH 25/30] =?UTF-8?q?fix=EF=BC=9A=E5=88=87=E6=8D=A2=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20excel2pic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index cf02c96..3a7f64b 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -149,7 +149,7 @@ eino_tools: # == 通用工具 == # 表格转图片 excel2pic: - base_url: "http://192.168.6.109:8000/api/v1/convert" + base_url: "http://192.168.6.115:8010/api/v1/convert" dingtalk: api_key: "dingsbbntrkeiyazcfdg" From f33096a50673d51182354e848175100d87c8e997 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Wed, 28 Jan 2026 19:05:42 +0800 Subject: [PATCH 26/30] =?UTF-8?q?fix:=20=E8=BF=98=E5=8E=9F=20excel2pic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index 3a7f64b..dff34ce 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -149,7 +149,7 @@ eino_tools: # == 通用工具 == # 表格转图片 excel2pic: - base_url: "http://192.168.6.115:8010/api/v1/convert" + base_url: "http://excel2pic:8000/api/v1/convert" dingtalk: api_key: "dingsbbntrkeiyazcfdg" From 9418d95a659053e7e6beb0319de6fd48b09eba33 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Sat, 31 Jan 2026 17:59:08 +0800 Subject: [PATCH 27/30] fix: heartbeat_interval 30 -> 300 --- config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.yaml b/config/config.yaml index dff34ce..c41dac1 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -39,7 +39,7 @@ sys: channel_pool_len: 100 channel_pool_size: 32 llm_pool_len: 5 - heartbeat_interval: 30 + heartbeat_interval: 300 key: report-api pollSize: 5 #连接池大小,不配置,或配置为0表示不启用连接池 minIdleConns: 2 #最小空闲连接数 From 22b7a3d0960a24884d362d733bf3400ae61ab8ed Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Sat, 31 Jan 2026 18:02:38 +0800 Subject: [PATCH 28/30] fix: llm model cloud -> local --- config/config.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index c41dac1..bbc416d 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -5,12 +5,12 @@ server: ollama: base_url: "http://172.17.0.1:11434" - # model: "qwen3:8b" - # generate_model: "qwen3:8b" - # mapping_model: "qwen3:8b" - model: "qwen3-coder:480b-cloud" - generate_model: "qwen3-coder:480b-cloud" - mapping_model: "deepseek-v3.2:cloud" + model: "qwen3:8b" + generate_model: "qwen3:8b" + mapping_model: "qwen3:8b" + # model: "qwen3-coder:480b-cloud" + # generate_model: "qwen3-coder:480b-cloud" + # mapping_model: "deepseek-v3.2:cloud" vl_model: "qwen2.5vl:3b" timeout: "120s" level: "info" From 71ed8146f590a34c1173a721031b18db75f615da Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Sat, 31 Jan 2026 18:10:05 +0800 Subject: [PATCH 29/30] fix: HeardBeatX 10s -> 100s --- internal/biz/handle/dingtalk/send_card.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/biz/handle/dingtalk/send_card.go b/internal/biz/handle/dingtalk/send_card.go index d2e5cb7..4660f33 100644 --- a/internal/biz/handle/dingtalk/send_card.go +++ b/internal/biz/handle/dingtalk/send_card.go @@ -20,7 +20,7 @@ import ( ) const DefaultInterval = 100 * time.Millisecond -const HeardBeatX = 100 +const HeardBeatX = 1000 type SendCardClient struct { Auth *Auth From 21585e731f4c917b6d3b0b9062c78bef35e3c2ef Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Sat, 31 Jan 2026 18:14:03 +0800 Subject: [PATCH 30/30] fix: llm model local -> cloud --- config/config.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index bbc416d..c41dac1 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -5,12 +5,12 @@ server: ollama: base_url: "http://172.17.0.1:11434" - model: "qwen3:8b" - generate_model: "qwen3:8b" - mapping_model: "qwen3:8b" - # model: "qwen3-coder:480b-cloud" - # generate_model: "qwen3-coder:480b-cloud" - # mapping_model: "deepseek-v3.2:cloud" + # model: "qwen3:8b" + # generate_model: "qwen3:8b" + # mapping_model: "qwen3:8b" + model: "qwen3-coder:480b-cloud" + generate_model: "qwen3-coder:480b-cloud" + mapping_model: "deepseek-v3.2:cloud" vl_model: "qwen2.5vl:3b" timeout: "120s" level: "info"