279 lines
7.5 KiB
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, "bot-20260413000114-8bw62", 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)
|
|
}
|