From 0eea75cd6ca365d9505d1243ca1858ada5872e39 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Mon, 5 Jan 2026 17:44:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=94=B5=E5=95=86=E5=85=85=E5=80=BC?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=88=91=E4=BB=AC=E7=9A=84=E5=95=86=E5=93=81?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.yaml | 14 +++++--- config/config_env.yaml | 15 +++++--- config/config_test.yaml | 15 +++++--- internal/biz/ding_talk_bot.go | 24 ++++++------- internal/config/config.go | 7 ++-- internal/domain/component/components.go | 9 +++-- .../statistics_ours_product/client.go | 11 ++---- .../statistics_ours_product/client_test.go | 18 ++-------- .../recharge/statistics_ours_product/types.go | 1 + .../recharge/statistics_ours_product.go | 36 ++++++++++++++----- internal/pkg/lsxd/login.go | 14 ++++---- internal/pkg/lsxd/login_test.go | 12 ++++--- internal/pkg/provider_set.go | 2 ++ internal/services/cron.go | 3 +- internal/services/dtalk_bot_test.go | 5 ++- 15 files changed, 106 insertions(+), 80 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index f577673..b64cfc6 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -30,10 +30,10 @@ coze: lsxd: # 统一登录 - login_url: "http://api.test.user.1688sup.com/v1/login/phone" - phone: "0zmINhJBwsDJYTmeaxXK4A==" - password: "LSSGoWhc63NpZc1rq3LT8g==" - 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==" + check_token_url: "https://api.user.1688sup.com/v1/user/welcome" sys: @@ -136,7 +136,8 @@ eino_tools: # 我们的商品统计 rechargeStatisticsOursProduct: base_url: "http://admin.lanseds.cn/admin/statistics/oursProduct" - + # == 通用工具 == + # 表格转图片 excel2pic: base_url: "http://192.168.6.109:8010/api/v1/convert" @@ -147,6 +148,9 @@ dingtalk: url: "https://alidocs.dingtalk.com/i/nodes/2Amq4vjg89RnYx9DTp66m2orW3kdP0wQ" base_id: "2Amq4vjg89RnYx9DTp66m2orW3kdP0wQ" sheet_id_or_name: "数据表" + # 机器人群组 + bot_group_id: + bbxt: 28 default_prompt: img_recognize: diff --git a/config/config_env.yaml b/config/config_env.yaml index f43c683..b571f51 100644 --- a/config/config_env.yaml +++ b/config/config_env.yaml @@ -25,10 +25,10 @@ coze: lsxd: # 统一登录 - login_url: "http://api.test.user.1688sup.com/v1/login/phone" - phone: "0zmINhJBwsDJYTmeaxXK4A==" - password: "LSSGoWhc63NpZc1rq3LT8g==" - 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==" + check_token_url: "https://api.user.1688sup.com/v1/user/welcome" sys: @@ -131,7 +131,9 @@ eino_tools: # == 电商充值系统 == # 我们的商品统计 rechargeStatisticsOursProduct: - base_url: "http://admin.1688sup.cn:8001/admin/statistics/oursProduct" + base_url: "http://admin.lanseds.cn/admin/statistics/oursProduct" + # == 通用工具 == + # 表格转图片 excel2pic: base_url: "http://192.168.6.109:8010/api/v1/convert" @@ -142,6 +144,9 @@ dingtalk: url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz" base_id: "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz" sheet_id_or_name: "数据表" + # 机器人群组 + bot_group_id: + bbxt: 23 default_prompt: diff --git a/config/config_test.yaml b/config/config_test.yaml index fea7ffe..71aada4 100644 --- a/config/config_test.yaml +++ b/config/config_test.yaml @@ -26,10 +26,10 @@ coze: lsxd: # 统一登录 - login_url: "http://api.test.user.1688sup.com/v1/login/phone" - phone: "0zmINhJBwsDJYTmeaxXK4A==" - password: "LSSGoWhc63NpZc1rq3LT8g==" - 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==" + check_token_url: "https://api.user.1688sup.com/v1/user/welcome" sys: session_len: 6 @@ -134,7 +134,9 @@ eino_tools: # == 电商充值系统 == # 我们的商品统计 rechargeStatisticsOursProduct: - base_url: "http://admin.1688sup.cn:8001/admin/statistics/oursProduct" + base_url: "http://admin.lanseds.cn/admin/statistics/oursProduct" + # == 通用工具 == + # 表格转图片 excel2pic: base_url: "http://192.168.6.109:8010/api/v1/convert" @@ -145,6 +147,9 @@ dingtalk: url: "https://alidocs.dingtalk.com/i/nodes/YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz" base_id: "YQBnd5ExVE6qAbnOiANQg2KKJyeZqMmz" sheet_id_or_name: "数据表" + # 机器人群组 + bot_group_id: + bbxt: 23 default_prompt: img_recognize: diff --git a/internal/biz/ding_talk_bot.go b/internal/biz/ding_talk_bot.go index 56c08a2..726249f 100644 --- a/internal/biz/ding_talk_bot.go +++ b/internal/biz/ding_talk_bot.go @@ -633,20 +633,20 @@ func (d *DingTalkBotBiz) HandleStreamRes(ctx context.Context, data *chatbot.BotC func (d *DingTalkBotBiz) GetReportLists(ctx context.Context, group *model.AiBotGroup) (reports []*bbxt.ReportRes, err error) { - //var product []string - //if group.ProductName != "" { - // product = strings.Split(group.ProductName, ",") - //} + var product []string + if group.ProductName != "" { + product = strings.Split(group.ProductName, ",") + } - //reportList, err := bbxt.NewBbxtTools() - //if err != nil { - // return - //} + reportList, err := bbxt.NewBbxtTools() + if err != nil { + return + } - //reports, err = reportList.DailyReport(time.Now(), bbxt.DownWardValue, product, bbxt.SumFilter, d.ossClient) - //if err != nil { - // return - //} + reports, err = reportList.DailyReport(time.Now(), bbxt.DownWardValue, product, bbxt.SumFilter, d.ossClient) + if err != nil { + return + } //product = []string{"优酷周卡", "优酷季卡", "优酷年卡", "爱奇艺黄金会员天卡"} //追加电商充值系统统计 - 返回统一使用[]*bbxt.ReportRes rechargeReports, err := d.rechargeDailyReport(ctx, time.Now(), nil, d.ossClient) diff --git a/internal/config/config.go b/internal/config/config.go index 3955b44..b8c917d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -66,9 +66,10 @@ type LLMCapabilityConfig struct { // DingtalkConfig 钉钉配置 type DingtalkConfig struct { - ApiKey string `mapstructure:"api_key"` - ApiSecret string `mapstructure:"api_secret"` - TableDemand AITableConfig `mapstructure:"table_demand"` + ApiKey string `mapstructure:"api_key"` + ApiSecret string `mapstructure:"api_secret"` + TableDemand AITableConfig `mapstructure:"table_demand"` + BotGroupID map[string]int `mapstructure:"bot_group_id"` // 机器人群组 } // TableDemandConfig 需求表配置 diff --git a/internal/domain/component/components.go b/internal/domain/component/components.go index 11c8d86..f433aa5 100644 --- a/internal/domain/component/components.go +++ b/internal/domain/component/components.go @@ -2,14 +2,17 @@ package component import ( "ai_scheduler/internal/domain/component/callback" + "ai_scheduler/internal/pkg/lsxd" ) type Components struct { - Callback callback.Manager + Callback callback.Manager + LSXDLogin *lsxd.Login } -func NewComponents(callbackManager callback.Manager) *Components { +func NewComponents(callbackManager callback.Manager, lsxdLogin *lsxd.Login) *Components { return &Components{ - Callback: callbackManager, + Callback: callbackManager, + LSXDLogin: lsxdLogin, } } diff --git a/internal/domain/tools/recharge/statistics_ours_product/client.go b/internal/domain/tools/recharge/statistics_ours_product/client.go index 514e190..ef872a2 100644 --- a/internal/domain/tools/recharge/statistics_ours_product/client.go +++ b/internal/domain/tools/recharge/statistics_ours_product/client.go @@ -3,8 +3,6 @@ package statistics_ours_product import ( "ai_scheduler/internal/config" "ai_scheduler/internal/pkg/l_request" - "ai_scheduler/internal/pkg/lsxd" - "ai_scheduler/utils" "context" "encoding/json" "fmt" @@ -16,16 +14,14 @@ type Client struct { cfg config.ToolConfig } -// New 是一个客户端构造函数,接收一个 config.ToolConfig 类型的配置参数 -// 返回一个初始化后的 Client 指针 func New(cfg config.ToolConfig) *Client { return &Client{ - cfg: cfg, // 将传入的配置参数赋值给 Client 结构体的 cfg 字段 + cfg: cfg, } } // Call 调用我们的商品统计接口 -func (c *Client) Call(ctx context.Context, req StatisticsOursProductRequest, rdb *utils.Rdb, lsxdcfg *config.LSXDConfig) ([]StatisticsOursProductItem, error) { +func (c *Client) Call(ctx context.Context, req StatisticsOursProductRequest) ([]StatisticsOursProductItem, error) { // 构建 URL 参数 var queryParams []string @@ -48,9 +44,8 @@ func (c *Client) Call(ctx context.Context, req StatisticsOursProductRequest, rdb queryString := strings.Join(queryParams, "&") fullURL := fmt.Sprintf("%s?%s", c.cfg.BaseURL, queryString) - token := lsxd.NewLogin(lsxdcfg, rdb).GetToken(ctx) headers := map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", token), + "Authorization": fmt.Sprintf("Bearer %s", req.Token), } reqObj := l_request.Request{ diff --git a/internal/domain/tools/recharge/statistics_ours_product/client_test.go b/internal/domain/tools/recharge/statistics_ours_product/client_test.go index cc464a5..c40b7d9 100644 --- a/internal/domain/tools/recharge/statistics_ours_product/client_test.go +++ b/internal/domain/tools/recharge/statistics_ours_product/client_test.go @@ -2,31 +2,17 @@ package statistics_ours_product import ( "ai_scheduler/internal/config" - "ai_scheduler/utils" "context" "testing" ) func TestClient_Call(t *testing.T) { - rdb := utils.NewRdb(&config.Config{ - Redis: config.Redis{ - Host: "47.97.27.195:6379", - Pass: "lansexiongdi@666", - Key: "report-api-test", - }, - }) configEino := config.ToolConfig{ - BaseURL: "http://admin.1688sup.cn:8001/admin/statistics/oursProduct", + BaseURL: "http://admin.lanseds.cn/admin/statistics/oursProduct", APIKey: "OFJ8UpqOlI7+w3Qklf36ZA==", APISecret: "tEbFegH/DRRh6LutFb7o3g==", } - configLSXD := &config.LSXDConfig{ - LoginURL: "http://api.test.user.1688sup.com/v1/login/phone", - Phone: "0zmINhJBwsDJYTmeaxXK4A==", - Password: "LSSGoWhc63NpZc1rq3LT8g==", - CheckTokenURL: "http://api.test.user.1688sup.com/v1/user/welcome", - } client := New(configEino) @@ -40,7 +26,7 @@ func TestClient_Call(t *testing.T) { // 由于没有真实的后端环境和 Token,这里注释掉实际调用 // 在开发环境中,你可以取消注释并填入有效的 Token 进行测试 - res, err := client.Call(context.Background(), req, rdb, configLSXD) + res, err := client.Call(context.Background(), req) if err != nil { t.Logf("Call failed: %v", err) } else { diff --git a/internal/domain/tools/recharge/statistics_ours_product/types.go b/internal/domain/tools/recharge/statistics_ours_product/types.go index 3d8e86d..ab54010 100644 --- a/internal/domain/tools/recharge/statistics_ours_product/types.go +++ b/internal/domain/tools/recharge/statistics_ours_product/types.go @@ -2,6 +2,7 @@ package statistics_ours_product // StatisticsOursProductRequest 我们的商品统计请求参数 type StatisticsOursProductRequest struct { + Token string `json:"token"` // 登录token Page int `json:"page"` // 页码 Limit int `json:"limit"` // 每页条数 Serial []string `json:"serial"` // 流水号范围 (通常是日期格式,如 YYYYMMDDHH) diff --git a/internal/domain/workflow/recharge/statistics_ours_product.go b/internal/domain/workflow/recharge/statistics_ours_product.go index 549ade4..13a644e 100644 --- a/internal/domain/workflow/recharge/statistics_ours_product.go +++ b/internal/domain/workflow/recharge/statistics_ours_product.go @@ -7,6 +7,7 @@ import ( "ai_scheduler/internal/domain/tools/common/excel_generator" "ai_scheduler/internal/domain/tools/recharge/statistics_ours_product" "ai_scheduler/internal/domain/workflow/runtime" + "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/utils_oss" "ai_scheduler/utils" "context" @@ -25,7 +26,13 @@ const WorkflowIDStatisticsOursProduct = "recharge.statisticsOursProduct" func init() { runtime.Register(WorkflowIDStatisticsOursProduct, func(d *runtime.Deps) (runtime.Workflow, error) { - return &statisticsOursProduct{cfg: d.Conf, toolManager: d.ToolManager, ossClient: d.Repos.OssClient, rdb: d.Repos.Rdb}, nil + return &statisticsOursProduct{ + cfg: d.Conf, + toolManager: d.ToolManager, + ossClient: d.Repos.OssClient, + rdb: d.Repos.Rdb, + lsxdLogin: d.Component.LSXDLogin, + }, nil }) } @@ -34,6 +41,7 @@ type statisticsOursProduct struct { toolManager *toolManager.Manager ossClient *utils_oss.Client rdb *utils.Rdb + lsxdLogin *lsxd.Login } type StatisticsOursProductWorkflowInput struct { @@ -105,8 +113,8 @@ func (w *statisticsOursProduct) buildWorkflow(ctx context.Context) (compose.Runn // formatContext 整理上下文参数 func (w *statisticsOursProduct) formatContext(ctx context.Context, input *StatisticsOursProductWorkflowInput) (*StatisticsOursProductContext, error) { - //startTime := input.Time.Format("2006010200") - startTime := "2025010500" + startTime := input.Time.Format("2006010200") + // startTime := "2025010500" endTime := input.Time.Format("2006010215") endTimeStr := input.Time.Format("1.2号15点") @@ -119,13 +127,20 @@ func (w *statisticsOursProduct) formatContext(ctx context.Context, input *Statis } func (w *statisticsOursProduct) callStatisticsTool(ctx context.Context, state *StatisticsOursProductContext) (*StatisticsOursProductContext, error) { + // 前置获取登录token + token := w.lsxdLogin.GetToken(ctx) + if token == "" { + return nil, fmt.Errorf("登录token为空") + } + req := statistics_ours_product.StatisticsOursProductRequest{ + Token: token, Page: 1, Limit: 100, // 仅取前100条 Serial: []string{state.StartTime, state.EndTime}, } - dataList, err := w.toolManager.Recharge.StatisticsOursProduct.Call(ctx, req, w.rdb, &w.cfg.LSXD) + dataList, err := w.toolManager.Recharge.StatisticsOursProduct.Call(ctx, req) if err != nil { log.Errorf("调用统计我们的商品工具失败: %v", err) return nil, fmt.Errorf("获取统计我们的商品数据失败") @@ -141,7 +156,8 @@ func (w *statisticsOursProduct) callStatisticsTool(ctx context.Context, state *S func (w *statisticsOursProduct) generateExcelAndUpload(ctx context.Context, state *StatisticsOursProductContext) (*StatisticsOursProductContext, error) { // 1. 获取模板路径 - cwd, _ := filepath.Abs("../../") + // cwd, _ := filepath.Abs("../../") // 单元测试用 + cwd, _ := filepath.Abs(".") templatePath := filepath.Join(cwd, "tmpl", "excel_temp", "recharge_statistics_ours_product.xlsx") fileName := fmt.Sprintf("statistics_ours_product_%d%d", time.Now().Unix(), rand.Intn(1000)) @@ -152,7 +168,7 @@ func (w *statisticsOursProduct) generateExcelAndUpload(ctx context.Context, stat req := &excel_generator.ExcelGeneratorRequest{ TemplatePath: templatePath, ExcelData: excelData, - StartRow: 4, + StartRow: 3, StyleRow: 3, Title: state.Title, } @@ -193,16 +209,18 @@ func (w *statisticsOursProduct) convertDataToExcelFormat(data []statistics_ours_ if val, err := strconv.ParseFloat(v, 64); err == nil { profitVal = val } else { - // 解析失败默认为0,或者记录错误 + // 解析失败默认为0,或者记录错误日志 + log.Errorf("解析 Profit 字段失败: %v", v) profitVal = 0 } default: - // 其他类型视为0 + // 其他类型视为0,或者记录错误日志 + log.Errorf("未知 Profit 类型: %T", v) profitVal = 0 } // 过滤利润小于 -100 的记录 - if profitVal < -100 { + if profitVal > -100 { continue } diff --git a/internal/pkg/lsxd/login.go b/internal/pkg/lsxd/login.go index e7be08b..5ea6801 100644 --- a/internal/pkg/lsxd/login.go +++ b/internal/pkg/lsxd/login.go @@ -19,12 +19,12 @@ import ( ) type Login struct { - config *config.LSXDConfig + config *config.Config redisCli *redis.Client mu sync.Mutex } -func NewLogin(config *config.LSXDConfig, rdb *utils.Rdb) *Login { +func NewLogin(config *config.Config, rdb *utils.Rdb) *Login { return &Login{ config: config, redisCli: rdb.Rdb, @@ -32,6 +32,8 @@ func NewLogin(config *config.LSXDConfig, rdb *utils.Rdb) *Login { } func (l *Login) GetToken(ctx context.Context) string { + // ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + // defer cancel() token, err := l.getCachedToken(ctx) if err != nil { @@ -72,7 +74,7 @@ func (l *Login) GetToken(ctx context.Context) string { // 校验token是否有效 func (l *Login) checkTokenValid(ctx context.Context, token string) bool { // 欢迎页校验token有效 - checkTokenURL := l.config.CheckTokenURL + checkTokenURL := l.config.LSXD.CheckTokenURL if checkTokenURL == "" { return token != "" } @@ -94,9 +96,9 @@ func (l *Login) checkTokenValid(ctx context.Context, token string) bool { // 调用登录接口获取token func (l *Login) login(ctx context.Context) (string, error) { // 1.获取配置 - loginURL := l.config.LoginURL - phone := l.config.Phone - password := l.config.Password + loginURL := l.config.LSXD.LoginURL + phone := l.config.LSXD.Phone + password := l.config.LSXD.Password // 2.调用登录接口获取token if loginURL == "" { diff --git a/internal/pkg/lsxd/login_test.go b/internal/pkg/lsxd/login_test.go index 299899c..64cd6a1 100644 --- a/internal/pkg/lsxd/login_test.go +++ b/internal/pkg/lsxd/login_test.go @@ -17,11 +17,13 @@ func TestGetToken(t *testing.T) { }, }) - login := NewLogin(&config.LSXDConfig{ - LoginURL: "http://api.test.user.1688sup.com/v1/login/phone", - Phone: "OFJ8UpqOlI7+w3Qklf36ZA==", - Password: "tEbFegH/DRRh6LutFb7o3g==", - CheckTokenURL: "http://api.test.user.1688sup.com/v1/user/welcome", + login := NewLogin(&config.Config{ + LSXD: config.LSXDConfig{ + LoginURL: "https://api.user.1688sup.com/v1/login/phone", + Phone: "ORlviZN7N06W2+WKLe76xg==", + Password: "V5Uh8C4bamEM6UQZh4TCeQ==", + CheckTokenURL: "https://api.user.1688sup.com/v1/user/welcome", + }, }, rdb) token := login.GetToken(context.Background()) if token == "" { diff --git a/internal/pkg/provider_set.go b/internal/pkg/provider_set.go index dcb5d8f..16bef95 100644 --- a/internal/pkg/provider_set.go +++ b/internal/pkg/provider_set.go @@ -2,6 +2,7 @@ package pkg import ( "ai_scheduler/internal/pkg/dingtalk" + "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/utils_langchain" "ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_oss" @@ -22,4 +23,5 @@ var ProviderSetClient = wire.NewSet( dingtalk.NewNotableClient, utils_oss.NewClient, + lsxd.NewLogin, ) diff --git a/internal/services/cron.go b/internal/services/cron.go index 4358781..7df3f6e 100644 --- a/internal/services/cron.go +++ b/internal/services/cron.go @@ -21,8 +21,7 @@ func NewCronService(config *config.Config, dingTalkBotBiz *biz.DingTalkBotBiz) * } func (d *CronService) CronReportSend(ctx context.Context) error { - - groupId := 28 + groupId := d.config.Dingtalk.BotGroupID["bbxt"] groupInfo, err := d.dingTalkBotBiz.GetGroupInfo(ctx, groupId) if err != nil { return err diff --git a/internal/services/dtalk_bot_test.go b/internal/services/dtalk_bot_test.go index c0a18ce..d4fbaf1 100644 --- a/internal/services/dtalk_bot_test.go +++ b/internal/services/dtalk_bot_test.go @@ -15,6 +15,7 @@ import ( "ai_scheduler/internal/domain/workflow/runtime" "ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg/dingtalk" + "ai_scheduler/internal/pkg/lsxd" "ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_oss" "ai_scheduler/internal/pkg/utils_vllm" @@ -73,8 +74,10 @@ func run() { botDeptImpl := impl.NewBotDeptImpl(db) // 初始化Redis管理器 redisManager := callback.NewRedisManager(pkgRdb) + // 初始化登录组件 + lsxdLogin := lsxd.NewLogin(configConfig, rdb) // 初始化组件 - components := component.NewComponents(redisManager) + components := component.NewComponents(redisManager, lsxdLogin) // 初始化工作流注册表 registry := workflow.NewRegistry(configConfig, client, repos, components) // 初始化钉钉旧版客户端