geoGo/internal/service/product_source.go

279 lines
7.5 KiB
Go

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)
}