package service import ( "encoding/json" "fmt" "geo/internal/ai_tool" "geo/internal/biz" "geo/internal/config" "geo/internal/data/impl" "geo/internal/data/model" "geo/internal/entitys" "geo/pkg" "geo/tmpl/dataTemp" "geo/tmpl/errcode" "io" "strconv" "strings" "time" "github.com/go-viper/mapstructure/v2" "github.com/gofiber/fiber/v2" "xorm.io/builder" ) type ProductSourceService struct { cfg *config.Config productImpl *impl.ProductImpl productSourceImpl *impl.ProductSourceImpl articleTypeImpl *impl.ArticleTypeImpl authBiz *biz.AuthBiz aiBiz *biz.AiBiz productBiz *biz.ProductBiz publishBiz *biz.PublishBiz } func NewProductSourceService( cfg *config.Config, ProductImpl *impl.ProductImpl, authBiz *biz.AuthBiz, aiBiz *biz.AiBiz, productBiz *biz.ProductBiz, productSource *impl.ProductSourceImpl, publishBiz *biz.PublishBiz, articleTypeImpl *impl.ArticleTypeImpl, ) *ProductSourceService { return &ProductSourceService{ cfg: cfg, productImpl: ProductImpl, authBiz: authBiz, aiBiz: aiBiz, productBiz: productBiz, productSourceImpl: productSource, publishBiz: publishBiz, articleTypeImpl: articleTypeImpl, } } func (p *ProductSourceService) Create(c *fiber.Ctx, req *entitys.ProductSourceCreateRequest) error { // 验证token _, err := p.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken) if err != nil { return err } product, err := p.productBiz.GetProduct(c.UserContext(), req.ProductId) if err != nil { return err } var brandInfo entitys.BrandInfo err = mapstructure.Decode(product, &brandInfo) if err != nil { return err } BotChatMes := &entitys.BotChat{ Question: req.Ques, ArticleType: req.ArticleType, BrandInfo: &brandInfo, } mes := p.aiBiz.CreateArticlePrompt(c.UserContext(), BotChatMes) content, err := ai_tool.NewHsyq().RequestHsyqBot(c.UserContext(), p.cfg.Hsyq.ApiKey, p.cfg.AiBot.Article, mes) if err != nil { return err } contentByte := []byte(*content) var resp entitys.BotChatResponse if err := json.Unmarshal(contentByte, &resp); err != nil { contentStr, err := pkg.JsonRepair(*content) if err != nil { return errcode.SysErr("文章生成失败,请重试") } if err := json.Unmarshal([]byte(contentStr), &resp); err != nil { return errcode.SysErr("文章生成失败,请重试") } } docxUrl, err := p.productBiz.CreateAndUploadArticle(c.UserContext(), resp.Content, product) if err != nil { return err } add := &model.ProductSource{ Title: resp.Title, Ques: req.Ques, SourceType: 1, ProductId: product.ID, ArticleType: req.ArticleType, SourceURL: docxUrl, RecommendPlatfrom: pkg.JsonStringIgonErr(resp.RecommendPlatform), CreatedAt: time.Now(), } if resp.Tag != nil { add.Tag = strings.Join(resp.Tag, ",") } err = p.productBiz.AddSource(c.UserContext(), add) if err != nil { return err } return nil } func (p *ProductSourceService) List(c *fiber.Ctx, req *entitys.ProductSourceListRequest) error { // 验证token _, err := p.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken) if err != nil { return err } page := req.Page if page < 1 { page = 1 } pageSize := req.PageSize if pageSize < 1 { pageSize = 20 } if pageSize > 100 { pageSize = 100 } var list []*model.ProductSource cond := builder.NewCond(). And(builder.Eq{"product_id": req.ProductId}). And(builder.Eq{"status": 1}) total, err := p.productSourceImpl.GetListToStruct(c.UserContext(), &cond, &dataTemp.ReqPageBo{Page: page, Limit: pageSize}, &list, "id desc") if err != nil { return err } return pkg.SuccessWithPageMsg(c, list, total.Total, page, pageSize) } func (p *ProductSourceService) UploadSource(c *fiber.Ctx) error { access := c.FormValue("access_token", "") if access == "" { return errcode.ParamErr("access_token未找到") } sourceId := c.FormValue("source_id") if sourceId == "" { return errcode.ParamErr("source_id未找到哦") } sourceIdInt, err := strconv.Atoi(sourceId) if err != nil { return errcode.ParamErr("source_id未必须是数字") } // 验证token _, err = p.authBiz.ValidateAccessToken(c.UserContext(), access) if err != nil { return err } fileHeader, err := c.FormFile("file") if err != nil { return errcode.ParamErr("未找到上传文件") } file, err := fileHeader.Open() if err != nil { return errcode.ParamErrf("无法打开文件:%S", err.Error()) } defer file.Close() fileBytes, err := io.ReadAll(file) if err != nil { return errcode.ParamErrf("读取文件失败:%s", err.Error()) } fileName := fmt.Sprintf("article_%d_%d.docx", sourceIdInt, time.Now().Unix()) url, err := p.productBiz.SourceUpload(c.UserContext(), fileBytes, fileName) if err != nil { return err } err = p.productBiz.UpdateSourceById(c.UserContext(), int32(sourceIdInt), &model.ProductSource{SourceURL: url}) if err != nil { return errcode.ParamErrf("文件上传失败") } return nil } func (p *ProductSourceService) Update(c *fiber.Ctx, req *entitys.ProductSourceUpdateRequest) error { // 验证token _, err := p.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken) if err != nil { return err } var update = map[string]any{} if req.Title != nil { update["title"] = *req.Title } if req.Tag != nil { update["tag"] = strings.Join(*req.Tag, ",") } return p.productBiz.UpdateSourceById(c.UserContext(), req.SourceId, update) } func (p *ProductSourceService) Del(c *fiber.Ctx, req *entitys.ProductSourceDelRequest) error { // 验证token _, err := p.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken) if err != nil { return err } return p.productBiz.DelSourceById(c.UserContext(), req.SourceId) } func (p *ProductSourceService) Publish(c *fiber.Ctx, req *entitys.ProductPublishRequest) error { // 验证token tokenInfo, err := p.authBiz.ValidateAccessToken(c.UserContext(), req.AccessToken) if err != nil { return err } var source model.ProductSource err = p.productSourceImpl.GetByKey(c.UserContext(), p.productSourceImpl.PrimaryKey(), req.SourceId, &source) if err != nil { return err } var product model.Product err = p.productImpl.GetByKey(c.UserContext(), p.productImpl.PrimaryKey(), source.ProductId, &product) if err != nil { return err } if product.Imgs == "" { return errcode.NotFound("请先上传产品图片") } ptime, err := time.Parse("2006-01-02T15:04", req.PublishTime) if err != nil { return errcode.ParamErr("发布时间格式错误") } var validRecords = make([]*model.Publish, 0, len(req.Plat)) for _, v := range req.Plat { validRecords = append(validRecords, &model.Publish{ UserIndex: product.UserIndex, SourceID: req.SourceId, RequestID: fmt.Sprintf("%s_%d", pkg.GenerateRandomLowerString(3), time.Now().UnixNano()), Title: source.Title, Tag: source.Tag, Type: source.SourceType, PlatIndex: v, URL: source.SourceURL, PublishTime: ptime, Img: strings.Split(product.Imgs, ",")[0], TokenID: tokenInfo.ID, }) } err = p.publishBiz.BatchInsertPublish(c.UserContext(), validRecords) if err != nil { return err } return pkg.HandleResponse(c, fiber.Map{ "total": len(validRecords), }) } func (p *ProductSourceService) ArticalTypeList(c *fiber.Ctx) error { cond := builder.NewCond(). And(builder.Eq{"status": 1}) var list []*model.ArticleType err := p.articleTypeImpl.GetRangeToMapStruct(c.UserContext(), &cond, &list) if err != nil { return err } return pkg.HandleResponse(c, list) }