Compare commits

...

1 Commits

Author SHA1 Message Date
bx1834938347-prog
36e3dce21f feat:新增图文增加黄反,视频脚本导出excel 2026-03-13 11:11:31 +08:00
4 changed files with 101 additions and 32 deletions

View File

@ -64,6 +64,7 @@ func MediaRouter(r *gin.RouterGroup) {
script.POST("update", serviceCast.UpdateVideoScript) script.POST("update", serviceCast.UpdateVideoScript)
script.POST("detail", serviceCast.VideoScriptDetail) script.POST("detail", serviceCast.VideoScriptDetail)
script.POST("list", serviceCast.ListVideoScripts) script.POST("list", serviceCast.ListVideoScripts)
script.POST("export-excel", serviceCast.VideoScripExportExcel)
script.POST("import-batch", serviceCast.ImportBatch) script.POST("import-batch", serviceCast.ImportBatch)
script.POST("update-approval", serviceCast.UpdateScriptApproval) script.POST("update-approval", serviceCast.UpdateScriptApproval)
script.POST("delete", serviceCast.DeleteVideoScript) script.POST("delete", serviceCast.DeleteVideoScript)

View File

@ -124,6 +124,50 @@ func ListVideoScripts(ctx *gin.Context) {
return return
} }
var videoScripMap = map[uint32]string{1: "草稿", 2: "审核中", 3: "审核通过", 4: "审核不通过"}
func VideoScripExportExcel(ctx *gin.Context) {
var req *cast.ListVideoScriptsReq
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
resp, err := service.CastProvider.ListVideoScripts(newCtx, req)
if err != nil {
service.Error(ctx, err)
return
}
titleList := []string{
"用户编号", "艺人", "艺人手机号", "引用次数", "状态", "脚本标题", "脚本内容", "创建人", "创建时间",
}
var dataList []interface{}
for _, task := range resp.Data {
data := []interface{}{
task.ArtistName,
task.ArtistName,
task.ArtistPhone,
task.QuoteCount,
videoScripMap[task.Status],
task.Title,
task.Content,
task.CreatorName,
task.CreatedDate,
}
dataList = append(dataList, &data)
}
content, err := utils.ToExcelByType(titleList, dataList, "slice", "")
if err != nil {
service.Error(ctx, errors.New("生成excel失败"))
}
utils.ResponseXls(ctx, content, fmt.Sprintf("视频脚本_%s.xlsx", time.Now().Format(time.DateTime)))
return
}
// DeleteVideoScript 删除视频脚本 // DeleteVideoScript 删除视频脚本
func DeleteVideoScript(ctx *gin.Context) { func DeleteVideoScript(ctx *gin.Context) {
var req *cast.DeleteVideoScriptReq var req *cast.DeleteVideoScriptReq

View File

@ -1513,6 +1513,10 @@ func GetBalanceLayout(ctx *gin.Context) {
service.Success(ctx, j) service.Success(ctx, j)
} }
var (
EnableSecurityCheck = true //是否打开批量导入图文
)
func ImportWorkBatch(ctx *gin.Context) { func ImportWorkBatch(ctx *gin.Context) {
excelFile, err := ctx.FormFile("file") excelFile, err := ctx.FormFile("file")
var ( var (
@ -1584,6 +1588,7 @@ func ImportWorkBatch(ctx *gin.Context) {
Source: 3, Source: 3,
} }
var artistNum string var artistNum string
//检测艺人编号
if len(row) > 1 && utils.CleanString(row[1]) != "" { if len(row) > 1 && utils.CleanString(row[1]) != "" {
artistNum = utils.CleanString(row[1]) artistNum = utils.CleanString(row[1])
artistSubNum := utils.CleanString(row[1]) artistSubNum := utils.CleanString(row[1])
@ -1605,7 +1610,6 @@ func ImportWorkBatch(ctx *gin.Context) {
Domain: "app", Domain: "app",
}) })
//} //}
if err != nil { if err != nil {
temp.Remark = fmt.Sprintf("自媒体用户查询失败:%s", err.Error()) temp.Remark = fmt.Sprintf("自媒体用户查询失败:%s", err.Error())
zap.L().Error("AccountFieeProvider.SubNumGetInfo", zap.Error(err)) zap.L().Error("AccountFieeProvider.SubNumGetInfo", zap.Error(err))
@ -1624,43 +1628,37 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.ArtistPhoneAreaCode = subInfoResp.TelAreaCode temp.ArtistPhoneAreaCode = subInfoResp.TelAreaCode
temp.ArtistSubNum = subInfoResp.SubNum temp.ArtistSubNum = subInfoResp.SubNum
} }
//检测标题
if len(row) > 7 { if len(row) > 7 {
temp.Title = utils.CleanString(row[7]) temp.Title = utils.CleanString(row[7])
// 检查并截取 title 长度(支持中文)
titleRunes := []rune(temp.Title) titleRunes := []rune(temp.Title)
if len(titleRunes) > 600 { if len(titleRunes) > 600 {
temp.Title = string(titleRunes[:600]) temp.Title = string(titleRunes[:600])
} }
ok, _err := check.SecurityText(temp.Title) if EnableSecurityCheck {
_err := SecurityText(temp.Title)
if _err != nil { if _err != nil {
temp.Remark = _err.Error()
req.ImageWorks = append(req.ImageWorks, temp)
break
}
if !ok {
temp.Remark = "标题黄反审核未通过" temp.Remark = "标题黄反审核未通过"
req.ImageWorks = append(req.ImageWorks, temp) req.ImageWorks = append(req.ImageWorks, temp)
break break
} }
} }
}
//检测内容
if len(row) > 8 { if len(row) > 8 {
temp.Content = utils.CleanString(row[8]) temp.Content = utils.CleanString(row[8])
if temp.Content != "" { if temp.Content != "" {
// 检查并截取 content 长度(支持中文)
contentRunes := []rune(temp.Content) contentRunes := []rune(temp.Content)
if len(contentRunes) > 600 { if len(contentRunes) > 600 {
temp.Content = string(contentRunes[:600]) temp.Content = string(contentRunes[:600])
} }
ok, _err := check.SecurityText(temp.Content) if EnableSecurityCheck {
_err := SecurityText(temp.Title)
if _err != nil { if _err != nil {
temp.Remark = _err.Error() temp.Remark = "标题黄反审核未通过"
req.ImageWorks = append(req.ImageWorks, temp) req.ImageWorks = append(req.ImageWorks, temp)
break break
} }
if !ok {
temp.Remark = "内容黄反审核未通过"
req.ImageWorks = append(req.ImageWorks, temp)
break
} }
// 处理内容中的标签:提取、验证并批量导入,以及自动生成标签 // 处理内容中的标签:提取、验证并批量导入,以及自动生成标签
processedContent, err := processContentAndAutoTags(ctx, temp.Content) processedContent, err := processContentAndAutoTags(ctx, temp.Content)
@ -1673,6 +1671,7 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.Content = processedContent temp.Content = processedContent
} }
} }
//检测图片
for i := 10; i <= 20; i++ { for i := 10; i <= 20; i++ {
if len(row) > i { if len(row) > i {
if utils.CleanString(row[i]) != "" { if utils.CleanString(row[i]) != "" {
@ -1698,6 +1697,7 @@ func ImportWorkBatch(ctx *gin.Context) {
req.ImageWorks = append(req.ImageWorks, temp) req.ImageWorks = append(req.ImageWorks, temp)
continue continue
} }
//检测tiktok账号
if len(row) > 2 && utils.CleanString(row[2]) != "" { if len(row) > 2 && utils.CleanString(row[2]) != "" {
mediaInfoResp, err = service.CastProvider.MediaInfo(context.Background(), &cast.MediaInfoReq{ mediaInfoResp, err = service.CastProvider.MediaInfo(context.Background(), &cast.MediaInfoReq{
ArtistUuid: temp.ArtistUuid, ArtistUuid: temp.ArtistUuid,
@ -1722,6 +1722,7 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[2])) temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[2]))
temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid) temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid)
} }
//检测ins账号
if len(row) > 3 && utils.CleanString(row[3]) != "" { if len(row) > 3 && utils.CleanString(row[3]) != "" {
mediaInfoResp, err = service.CastProvider.MediaInfo(context.Background(), &cast.MediaInfoReq{ mediaInfoResp, err = service.CastProvider.MediaInfo(context.Background(), &cast.MediaInfoReq{
ArtistUuid: temp.ArtistUuid, ArtistUuid: temp.ArtistUuid,
@ -1746,6 +1747,7 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[3])) temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[3]))
temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid) temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid)
} }
//检测dm账号
if len(row) > 4 && utils.CleanString(row[4]) != "" { if len(row) > 4 && utils.CleanString(row[4]) != "" {
temp.Remark = fmt.Sprintf("DM不能发图文") temp.Remark = fmt.Sprintf("DM不能发图文")
zap.L().Error("CastProvider.MediaInfo", zap.Error(err)) zap.L().Error("CastProvider.MediaInfo", zap.Error(err))
@ -1774,7 +1776,7 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[4])) temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[4]))
temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid)*/ temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid)*/
} }
// YouTube账号第F列row[5] // 检测油管账号
if len(row) > 5 && utils.CleanString(row[5]) != "" { if len(row) > 5 && utils.CleanString(row[5]) != "" {
temp.Remark = fmt.Sprintf("Youtube不能发图文") temp.Remark = fmt.Sprintf("Youtube不能发图文")
zap.L().Error("CastProvider.MediaInfo", zap.Error(err)) zap.L().Error("CastProvider.MediaInfo", zap.Error(err))
@ -1803,7 +1805,7 @@ func ImportWorkBatch(ctx *gin.Context) {
// temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[5])) // temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[5]))
// temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid) // temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid)
} }
// Bluesky账号第G列row[6] //检测blueSky账号
if len(row) > 6 && utils.CleanString(row[6]) != "" { if len(row) > 6 && utils.CleanString(row[6]) != "" {
mediaInfoResp, err = service.CastProvider.MediaInfo(context.Background(), &cast.MediaInfoReq{ mediaInfoResp, err = service.CastProvider.MediaInfo(context.Background(), &cast.MediaInfoReq{
ArtistUuid: temp.ArtistUuid, ArtistUuid: temp.ArtistUuid,
@ -1828,6 +1830,7 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[6])) temp.MediaAccountNames = append(temp.MediaAccountNames, utils.CleanString(row[6]))
temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid) temp.MediaAccountUuids = append(temp.MediaAccountUuids, mediaInfoResp.Info.MediaAccountUuid)
} }
//最后检测数据
if artistNum == "" { if artistNum == "" {
temp.Remark = "艺人编号不能为空" temp.Remark = "艺人编号不能为空"
req.ImageWorks = append(req.ImageWorks, temp) req.ImageWorks = append(req.ImageWorks, temp)

View File

@ -9,6 +9,7 @@ import (
apiCast "fonchain-fiee/api/cast" apiCast "fonchain-fiee/api/cast"
"fonchain-fiee/pkg/config" "fonchain-fiee/pkg/config"
"fonchain-fiee/pkg/service" "fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/cast"
"image" "image"
"image/draw" "image/draw"
"image/jpeg" "image/jpeg"
@ -654,27 +655,47 @@ func downloadAndUploadToBucket(imageURL string) (string, error) {
//url := fmt.Sprintf("%s/%s", config.ConfigData.Oss.CdnHost, fileName) //url := fmt.Sprintf("%s/%s", config.ConfigData.Oss.CdnHost, fileName)
func (p *BatchProcessor) generateTitleAndContent(req *excelData) (string, string, error) { func (p *BatchProcessor) generateTitleAndContent(req *excelData) (string, string, error) {
var title, content string
var err error
if req.PhotoUrl != "" { if req.PhotoUrl != "" {
title, content, err := NewAiGenerator().GenerateTitleAndContentFromImage( title, content, err = NewAiGenerator().GenerateTitleAndContentFromImage(
req.PhotoUrl, req.PhotoUrl,
req.TitleRequire, req.TitleRequire,
req.ContentRequire, req.ContentRequire,
) )
if err != nil { if err != nil {
return "", "", fmt.Errorf("图生文失败: %v", err) return "", "", fmt.Errorf("图生文失败: %w", err)
} }
return title, content, nil
} else { } else {
title, content, err := NewAiGenerator().GenerateTitleAndContentFromText( title, content, err = NewAiGenerator().GenerateTitleAndContentFromText(
req.TitleRequire, req.TitleRequire,
req.ContentRequire, req.ContentRequire,
) )
if err != nil { if err != nil {
return "", "", fmt.Errorf("生成内容失败: %v", err) return "", "", fmt.Errorf("生成内容失败: %w", err)
}
} }
return title, content, nil
if err = p.securityCheck(title, content); err != nil {
return "", "", err
} }
return title, content, nil
}
func (p *BatchProcessor) securityCheck(title, content string) error {
// 标题审核
if err := cast.SecurityText(title); err != nil {
return fmt.Errorf("标题未通过黄反,原因:%w", err)
}
// 内容审核
if err := cast.SecurityText(content); err != nil {
return fmt.Errorf("内容未通过黄反,原因:%w", err)
}
return nil
} }
func (p *BatchProcessor) generateImage(req *excelData) (string, error) { func (p *BatchProcessor) generateImage(req *excelData) (string, error) {