diff --git a/internal/biz/ding_talk_bot.go b/internal/biz/ding_talk_bot.go index e065ff2..af040c2 100644 --- a/internal/biz/ding_talk_bot.go +++ b/internal/biz/ding_talk_bot.go @@ -161,7 +161,7 @@ func (d *DingTalkBotBiz) handleGroupChat(ctx context.Context, requireData *entit return } - return d.handleMatch(ctx, rec) + return d.handleMatch(ctx, rec, group) } func (d *DingTalkBotBiz) Macro(ctx context.Context, requireData *entitys.RequireDataDingTalkBot, group *model.AiBotGroup) (err error, isFinish bool) { @@ -350,7 +350,7 @@ func (d *DingTalkBotBiz) getUserContent(msgType string, msgContent interface{}) return } -func (d *DingTalkBotBiz) handleMatch(ctx context.Context, rec *entitys.Recognize) (err error) { +func (d *DingTalkBotBiz) handleMatch(ctx context.Context, rec *entitys.Recognize, group *model.AiBotGroup) (err error) { if !rec.Match.IsMatch { if len(rec.Match.Chat) != 0 { @@ -375,6 +375,8 @@ func (d *DingTalkBotBiz) handleMatch(ctx context.Context, rec *entitys.Recognize switch constants.TaskType(pointTask.Type) { case constants.TaskTypeFunc: return d.handleTask(ctx, rec, pointTask) + case constants.TaskTypeReport: + return d.handleReport(ctx, rec, pointTask, group) case constants.TaskTypeCozeWorkflow: return d.handleCozeWorkflow(ctx, rec, pointTask) default: @@ -483,6 +485,75 @@ func handleCozeWorkflowEvents(ctx context.Context, resp coze.Stream[coze.Workflo fmt.Printf("done, log:%s\n", resp.Response().LogID()) } +func (d *DingTalkBotBiz) handleReport(ctx context.Context, rec *entitys.Recognize, task *model.AiBotTool, group *model.AiBotGroup) error { + var configData entitys.ConfigDataReport + err := json.Unmarshal([]byte(rec.Match.Parameters), &configData) + if err != nil { + return err + } + t, err := time.Parse(time.DateTime, configData.Time) + if err != nil { + log.Infof("时间识别失败:%s", configData.Time) + entitys.ResText(rec.Ch, "", "时间识别失败了!可以给我一份比较具体的时间吗,例如“2025-12-31 12:00,抱歉抱歉😀") + return nil + } + rep, err := bbxt.NewBbxtTools() + uploader := bbxt.NewUploader(d.ossClient) + if err != nil { + return err + } + var reports []*bbxt.ReportRes + switch rec.Match.Index { + case "report_loss_analysis": + repo, _err := rep.StatisOursProductLossSum(t) + if _err != nil { + return _err + } + reports = append(reports, repo...) + case "report_sales_analysis": + + repo, _err := rep.GetProfitRankingSum(t) + if _err != nil { + return _err + } + reports = append(reports, repo) + case "report_ranking_of_distributors": + product := strings.Split(group.ProductName, ",") + repo, _err := rep.GetStatisOfficialProductSum(t, product) + if _err != nil { + return _err + } + reports = append(reports, repo) + case "report_daily": + product := strings.Split(group.ProductName, ",") + repo, _err := rep.DailyReport(t, product, nil) + if _err != nil { + return _err + } + reports = append(reports, repo...) + default: + return fmt.Errorf("未找到的报表:%s", rec.Match.Index) + } + + for _, report := range reports { + err = uploader.Run(report) + if err != nil { + log.Error(err) + continue + } + + entitys.ResText(rec.Ch, "", fmt.Sprintf("%s![图片](%s)", report.Title, report.Url)) + //rec.Ch <- report.Title + //reportChan <- fmt.Sprintf("![图片](%s)", report.Url) + //err = d.SendReport(ctx, group, report) + //if err != nil { + // log.Error(err) + // continue + //} + } + return nil +} + func (d *DingTalkBotBiz) handleTask(ctx context.Context, rec *entitys.Recognize, task *model.AiBotTool) (err error) { var configData entitys.ConfigDataTool err = json.Unmarshal([]byte(task.Config), &configData) @@ -555,7 +626,7 @@ func (d *DingTalkBotBiz) GetReportLists(ctx context.Context, group *model.AiBotG return } -func (d *DingTalkBotBiz) SendReport(ctx context.Context, groupInfo model.AiBotGroup, report *bbxt.ReportRes) (err error) { +func (d *DingTalkBotBiz) SendReport(ctx context.Context, groupInfo *model.AiBotGroup, report *bbxt.ReportRes) (err error) { reportChan := make(chan string, 10) defer close(reportChan) @@ -669,5 +740,5 @@ func (d *DingTalkBotBiz) defaultPrompt() string { 4. 格式强制要求: -所有字段值必须是**字符串**(包括 confidence)。 -parameters 必须是 **转义后的 JSON 字符串**(如 "{\"product_name\": \"京东月卡\"}")。 -当前时间:` + now +当前时间:` + now + `,所有的时间识别精确到秒` } diff --git a/internal/data/constants/const.go b/internal/data/constants/const.go index b3c6ef0..f5ac22a 100644 --- a/internal/data/constants/const.go +++ b/internal/data/constants/const.go @@ -17,6 +17,7 @@ const ( TaskTypeBot TaskType = 4 TaskTypeEinoWorkflow TaskType = 5 // eino 工作流 TaskTypeCozeWorkflow TaskType = 6 // coze 工作流 + TaskTypeReport TaskType = 7 //报表 ) type UseFul int32 diff --git a/internal/entitys/types.go b/internal/entitys/types.go index 601f50e..815eeba 100644 --- a/internal/entitys/types.go +++ b/internal/entitys/types.go @@ -92,6 +92,10 @@ type ConfigDataTool struct { Tool string `json:"tool"` } +type ConfigDataReport struct { + Time string `json:"time"` +} + // Message 消息 type Message struct { Role string `json:"role"` diff --git a/internal/services/cron.go b/internal/services/cron.go index cf6599f..4358781 100644 --- a/internal/services/cron.go +++ b/internal/services/cron.go @@ -34,7 +34,7 @@ func (d *CronService) CronReportSend(ctx context.Context) error { //contentChan <- "截止今日23点利润亏损合计:127917.0866元,亏损500元以上的分销商和产品金额如下图:" //contentChan <- "![图片](https://lsxdmgoss.oss-cn-chengdu.aliyuncs.com/MarketingSaaS/image/V2/other/shanghu.png)" for _, report := range reports { - err = d.dingTalkBotBiz.SendReport(ctx, groupInfo, report) + err = d.dingTalkBotBiz.SendReport(ctx, &groupInfo, report) if err != nil { log.Error(err) continue diff --git a/internal/tools/bbxt/bbxt.go b/internal/tools/bbxt/bbxt.go index 3a1619d..4a0893b 100644 --- a/internal/tools/bbxt/bbxt.go +++ b/internal/tools/bbxt/bbxt.go @@ -54,8 +54,9 @@ func (b *BbxtTools) DailyReport(now time.Time, productName []string, ossClient * } reports = append(reports, productLossReport...) reports = append(reports, statisOfficialProductSum, profitRankingSum) - uploader := NewUploader(ossClient) + if ossClient != nil { + uploader := NewUploader(ossClient) for _, report := range reports { _ = uploader.Run(report) } @@ -68,7 +69,7 @@ func (b *BbxtTools) DailyReport(now time.Time, productName []string, ossClient * func (b *BbxtTools) StatisOursProductLossSum(now time.Time) (report []*ReportRes, err 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(time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())), + adjustedTime(now), //adjustedTime(time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())), } data, err := StatisOursProductLossSumApi(&StatisOursProductLossSumReq{ @@ -144,14 +145,14 @@ func (b *BbxtTools) StatisOursProductLossSum(now time.Time) (report []*ReportRes totalSum += v.Total } report = make([]*ReportRes, 2) - + timeCh := now.Format("1月2日15点") //总量生成excel if len(total) > 0 { filePath := b.cacheDir + "/kshj_total" + fmt.Sprintf("%d%d", time.Now().Unix(), rand.Intn(1000)) + ".xlsx" err = b.SimpleFillExcelWithTitle(b.excelTempDir+"/"+"kshj_total.xlsx", filePath, total, "") report[0] = &ReportRes{ ReportName: "负利润分析(合计表)", - Title: "截至今日23点利润累计亏损" + fmt.Sprintf("%.2f", totalSum), + Title: "截至今日" + timeCh + "利润累计亏损" + fmt.Sprintf("%.2f", totalSum), Path: filePath, Data: total, } @@ -164,7 +165,7 @@ func (b *BbxtTools) StatisOursProductLossSum(now time.Time) (report []*ReportRes err = b.resellerDetailFillExcelV2(b.excelTempDir+"/"+"kshj_gt.xlsx", filePath, gt) report[1] = &ReportRes{ ReportName: "负利润分析(亏损500以上)", - Title: "截至今日23点亏顺500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500), + Title: "截至今日" + timeCh + "亏顺500以上利润累计亏损" + fmt.Sprintf("%.2f", totalSum500), Path: filePath, Data: total, } diff --git a/internal/tools/bbxt/upload.go b/internal/tools/bbxt/upload.go index a5d0886..c485c49 100644 --- a/internal/tools/bbxt/upload.go +++ b/internal/tools/bbxt/upload.go @@ -151,3 +151,14 @@ func (u *Uploader) uploadToOSS(fileName string, fileBytes []byte) string { } return url } + +//// uploadToOSS 上传至 oss 返回图片url +//func (r *ReportRes) To(fileName string, fileBytes []byte) string { +// objectKey := fmt.Sprintf("ai-scheduler/data-analytics/images/%s.png", fileName) +// url, err := u.ossClient.UploadBytes(objectKey, fileBytes) +// if err != nil { +// log.Errorf("oss upload failed: %v", err) +// return "" +// } +// return url +//}