1187 lines
39 KiB
Go
1187 lines
39 KiB
Go
package cast
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"fonchain-fiee/api/aryshare"
|
||
"fonchain-fiee/api/bundle"
|
||
"fonchain-fiee/api/cast"
|
||
"fonchain-fiee/pkg/cache"
|
||
"fonchain-fiee/pkg/e"
|
||
modelCast "fonchain-fiee/pkg/model/cast"
|
||
"fonchain-fiee/pkg/model/login"
|
||
"fonchain-fiee/pkg/service"
|
||
"fonchain-fiee/pkg/utils"
|
||
"strconv"
|
||
"time"
|
||
|
||
"dubbo.apache.org/dubbo-go/v3/common/constant"
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/google/uuid"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// CreateWorkAnalysis 创建作品分析
|
||
func CreateWorkAnalysis(ctx *gin.Context) {
|
||
var req *cast.CreateWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
artistID, _ := strconv.ParseUint(req.ArtistID, 10, 64)
|
||
if err = CheckUserBundleBalance(int32(artistID), modelCast.BalanceTypeDataValue); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
resp, err := service.CastProvider.CreateWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// UpdateWorkAnalysis 更新作品分析
|
||
func UpdateWorkAnalysis(ctx *gin.Context) {
|
||
var req *cast.UpdateWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
_, err = service.CastProvider.UpdateWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, nil)
|
||
return
|
||
}
|
||
|
||
// UpdateWorkAnalysisStatus 更新作品分析状态
|
||
func UpdateWorkAnalysisStatus(ctx *gin.Context) {
|
||
var req *cast.UpdateWorkAnalysisStatusReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
_, err = service.CastProvider.UpdateWorkAnalysisStatus(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, nil)
|
||
return
|
||
}
|
||
|
||
// GetWorkAnalysis 获取作品分析详情
|
||
func GetWorkAnalysis(ctx *gin.Context) {
|
||
var req *cast.GetWorkAnalysisDetailReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.GetWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// GetLatestWorkAnalysis 获取最新作品分析
|
||
func GetLatestWorkAnalysis(ctx *gin.Context) {
|
||
var req *cast.GetLatestWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.GetLatestWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// ListWorkAnalysis 获取作品分析列表
|
||
func ListWorkAnalysis(ctx *gin.Context) {
|
||
var req *cast.ListWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.ListWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
RefreshWorkAnalysisApproval(ctx, resp.Data)
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// RefreshWorkAnalysisApproval 刷新作品分析审批状态
|
||
func RefreshWorkAnalysisApproval(ctx *gin.Context, data []*cast.WorkAnalysisInfo) {
|
||
if len(data) > 0 {
|
||
var analysisUuidApprovalIDMap = make(map[int]string)
|
||
for _, v := range data {
|
||
// 状态为2表示待审批,需要获取详情来获取ApprovalID
|
||
if v.WorkAnalysisStatus == 2 && v.ApprovalID != "" {
|
||
zap.L().Info("RefreshWorkAnalysisApproval", zap.Any("approvalID", v.ApprovalID))
|
||
approvalID, _ := strconv.ParseUint(v.ApprovalID, 10, 64)
|
||
analysisUuidApprovalIDMap[int(approvalID)] = v.Uuid
|
||
}
|
||
}
|
||
if len(analysisUuidApprovalIDMap) > 0 {
|
||
_ = RefreshWorkAnalysisApprovalStatus(ctx, analysisUuidApprovalIDMap)
|
||
}
|
||
}
|
||
}
|
||
|
||
// RefreshWorkAnalysisApprovalStatus 刷新作品分析审批状态详情
|
||
func RefreshWorkAnalysisApprovalStatus(ctx *gin.Context, approvalIDAnalysisUuidMap map[int]string) (err error) {
|
||
var castS = new(CastService)
|
||
var data = make(map[int]modelCast.Item)
|
||
var approvalIDs []int
|
||
for approvalId := range approvalIDAnalysisUuidMap {
|
||
approvalIDs = append(approvalIDs, approvalId)
|
||
}
|
||
if len(approvalIDs) == 0 {
|
||
return
|
||
}
|
||
data, err = castS.ApprovalDetail(approvalIDs)
|
||
if err != nil {
|
||
return
|
||
}
|
||
// status: 1待审批 2审批通过 3审批不通过 6撤销发其中 7撤销完成
|
||
var newData = make(map[int]modelCast.Item, len(approvalIDs))
|
||
for _, v := range approvalIDs {
|
||
newData[v] = data[v]
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
if len(newData) > 0 {
|
||
for approvalId, v := range newData {
|
||
if v.ID == 0 {
|
||
_, _ = service.CastProvider.UpdateWorkAnalysisStatus(newCtx, &cast.UpdateWorkAnalysisStatusReq{
|
||
WorkAction: cast.WorkActionENUM_APPROVAL_DELETE,
|
||
Uuid: approvalIDAnalysisUuidMap[approvalId],
|
||
ApprovalID: fmt.Sprint(approvalId),
|
||
ApprovalReply: "",
|
||
})
|
||
continue
|
||
}
|
||
var workAction cast.WorkActionENUM
|
||
if v.Status == 2 {
|
||
workAction = cast.WorkActionENUM_APPROVAL_PASS
|
||
} else if v.Status == 3 {
|
||
workAction = cast.WorkActionENUM_APPROVAL_REJECT
|
||
} else {
|
||
continue
|
||
}
|
||
_, _ = service.CastProvider.UpdateWorkAnalysisStatus(newCtx, &cast.UpdateWorkAnalysisStatusReq{
|
||
WorkAction: workAction,
|
||
Uuid: approvalIDAnalysisUuidMap[approvalId],
|
||
ApprovalID: fmt.Sprint(approvalId),
|
||
ApprovalReply: v.Reply,
|
||
})
|
||
}
|
||
}
|
||
return
|
||
}
|
||
|
||
// DeleteWorkAnalysis 删除作品分析
|
||
func DeleteWorkAnalysis(ctx *gin.Context) {
|
||
var req *cast.DeleteWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
_, err = service.CastProvider.DeleteWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, nil)
|
||
return
|
||
}
|
||
|
||
// getWorkAnalysisStatusText 获取作品分析状态文本
|
||
func getWorkAnalysisStatusText(status uint32) string {
|
||
switch status {
|
||
case 1:
|
||
return "待提交"
|
||
case 2:
|
||
return "审批中"
|
||
case 3:
|
||
return "审批驳回"
|
||
case 4:
|
||
return "待艺人验收"
|
||
case 5:
|
||
return "验收失败"
|
||
case 6:
|
||
return "待阅读"
|
||
case 7:
|
||
return "已阅读"
|
||
default:
|
||
return ""
|
||
}
|
||
}
|
||
|
||
// getComfirmTypeText 获取确认类型文本
|
||
func getComfirmTypeText(comfirmType int32) string {
|
||
switch comfirmType {
|
||
case 1:
|
||
return "艺人确认"
|
||
case 2:
|
||
return "系统确认"
|
||
default:
|
||
return ""
|
||
}
|
||
}
|
||
|
||
// ListWorkAnalysisExport 获取作品分析列表并导出Excel
|
||
func ListWorkAnalysisExport(ctx *gin.Context) {
|
||
var req *cast.ListWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
req.Page = 1
|
||
req.PageSize = 999999999
|
||
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.ListWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
|
||
titleList := []string{
|
||
"艺人", "用户编号", "手机号", "状态", "验收确认类型", "原因", "状态变更时间", "提交时间", "操作人", "pdf链接",
|
||
}
|
||
|
||
var dataList []interface{}
|
||
for _, i := range resp.Data {
|
||
data := []any{
|
||
i.ArtistName,
|
||
i.SubNum,
|
||
i.ArtistPhone,
|
||
getWorkAnalysisStatusText(i.WorkAnalysisStatus),
|
||
getComfirmTypeText(i.ComfirmType),
|
||
i.Reason,
|
||
i.StatusUpdateTime,
|
||
i.SubmitTime,
|
||
i.OperatorName,
|
||
i.PdfUrl,
|
||
}
|
||
dataList = append(dataList, &data)
|
||
}
|
||
|
||
content, err := utils.ToExcelByType(titleList, dataList, "slice", "")
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
utils.ResponseXls(ctx, content, "数据分析列表")
|
||
return
|
||
}
|
||
|
||
// ListWorkAnalysisSingleExport 获取作品分析列表并导出Excel
|
||
func ListWorkAnalysisSingleExport(ctx *gin.Context) {
|
||
var req *cast.ListWorkAnalysisReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
req.Page = 1
|
||
req.PageSize = 999999999
|
||
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.ListWorkAnalysis(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
|
||
titleList := []string{
|
||
"状态", "验收确认类型", "原因", "状态变更时间", "操作人", "提交时间", "pdf链接",
|
||
}
|
||
|
||
var dataList []interface{}
|
||
for _, i := range resp.Data {
|
||
data := []any{
|
||
getWorkAnalysisStatusText(i.WorkAnalysisStatus),
|
||
getComfirmTypeText(i.ComfirmType),
|
||
i.Reason,
|
||
i.StatusUpdateTime,
|
||
i.OperatorName,
|
||
i.SubmitTime,
|
||
i.PdfUrl,
|
||
}
|
||
dataList = append(dataList, &data)
|
||
}
|
||
|
||
content, err := utils.ToExcelByType(titleList, dataList, "slice", "")
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
utils.ResponseXls(ctx, content, "数据分析列表")
|
||
return
|
||
}
|
||
|
||
// ArtistDataList 艺人数据列表
|
||
func ArtistDataList(ctx *gin.Context) {
|
||
var req *cast.ArtistDataListReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.ArtistDataList(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// MediaDataList 自媒体数据列表
|
||
func MediaDataList(ctx *gin.Context) {
|
||
var req *cast.MediaDataListReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.MediaDataList(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// DataOverview 数据概览
|
||
func DataOverview(ctx *gin.Context) {
|
||
var req *cast.DataOverviewReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.DataOverview(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// ArtistMetricsSeries 艺人指标系列
|
||
func ArtistMetricsSeries(ctx *gin.Context) {
|
||
var req *cast.ArtistMetricsSeriesReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.ArtistMetricsSeries(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// ArtistMetricsDailyWindow 艺人指标日窗口
|
||
func ArtistMetricsDailyWindow(ctx *gin.Context) {
|
||
var req *cast.ArtistMetricsDailyWindowReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.ArtistMetricsDailyWindow(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// TobeConfirmedList 待确认数据列表
|
||
func TobeConfirmedList(ctx *gin.Context) {
|
||
var req *cast.TobeConfirmedListReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
userInfo := login.GetUserInfoFromC(ctx)
|
||
req.ArtistUuid = strconv.Itoa(int(userInfo.ID))
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.CastProvider.TobeConfirmedList(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// UpdateWorkAnalysisApprovalID 更新作品分析审批ID
|
||
func UpdateWorkAnalysisApprovalID(ctx *gin.Context) {
|
||
var req *cast.UpdateWorkAnalysisApprovalIDReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
_, err = service.CastProvider.UpdateWorkAnalysisApprovalID(newCtx, req)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
service.Success(ctx, nil)
|
||
return
|
||
}
|
||
|
||
type CheckBundleBalanceReq struct {
|
||
ArtistID string `protobuf:"bytes,4,opt,name=artistID,proto3" json:"artistID"` // 艺人ID
|
||
BalanceType modelCast.BalanceTypeEnum `json:"balanceType"` // 套餐类型
|
||
}
|
||
|
||
// CheckBundleBalance 检查套餐余量
|
||
func CheckBundleBalance(ctx *gin.Context) {
|
||
var req *CheckBundleBalanceReq
|
||
var err error
|
||
if err = ctx.ShouldBind(&req); err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
artistID, err := strconv.ParseUint(req.ArtistID, 10, 64)
|
||
if err != nil {
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
zap.L().Info("CheckUserBundleBalance", zap.Any("userID", artistID), zap.Any("balanceType", req.BalanceType))
|
||
newCtx := NewCtxWithUserInfo(ctx)
|
||
resp, err := service.BundleProvider.GetBundleBalanceByUserId(newCtx, &bundle.GetBundleBalanceByUserIdReq{UserId: int32(artistID)})
|
||
if err != nil {
|
||
zap.L().Error("CheckUserBundleBalance", zap.Any("err", err))
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
zap.L().Info("CheckUserBundleBalance", zap.Any("resp", resp))
|
||
switch req.BalanceType {
|
||
case modelCast.BalanceTypeAccountValue:
|
||
if resp.AccountNumber-resp.AccountConsumptionNumber <= 0 {
|
||
err = errors.New(e.ErrorBalanceInsufficient)
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
case modelCast.BalanceTypeImageValue:
|
||
if resp.ImageNumber-resp.ImageConsumptionNumber <= 0 {
|
||
err = errors.New(e.ErrorBalanceInsufficient)
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
case modelCast.BalanceTypeVideoValue:
|
||
if resp.VideoNumber-resp.VideoConsumptionNumber <= 0 {
|
||
err = errors.New(e.ErrorBalanceInsufficient)
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
case modelCast.BalanceTypeDataValue:
|
||
if resp.DataAnalysisNumber-resp.DataAnalysisConsumptionNumber <= 0 {
|
||
err = errors.New(e.ErrorBalanceInsufficient)
|
||
service.Error(ctx, err)
|
||
return
|
||
}
|
||
}
|
||
|
||
service.Success(ctx, resp)
|
||
return
|
||
}
|
||
|
||
// ProcessAnalysisTask 处理数据分析自动确认任务
|
||
func ProcessAnalysisTask(ctx context.Context, analysisUuid string) {
|
||
lockKey := fmt.Sprintf(modelCast.AutoConfirmAnalysisLockKey, analysisUuid)
|
||
reply := cache.RedisClient.SetNX(lockKey, "1", 5*time.Minute)
|
||
if !reply.Val() {
|
||
zap.L().Warn("数据分析任务正在被其他实例处理", zap.String("analysisUuid", analysisUuid))
|
||
return
|
||
}
|
||
defer func() {
|
||
cache.RedisClient.Del(lockKey)
|
||
}()
|
||
err := autoConfirmAnalysis(ctx, analysisUuid)
|
||
if err != nil {
|
||
zap.L().Error("数据分析自动确认失败",
|
||
zap.String("analysisUuid", analysisUuid),
|
||
zap.Error(err))
|
||
return
|
||
}
|
||
// 从队列中移除
|
||
args := make([]interface{}, len(analysisUuid))
|
||
for i, m := range analysisUuid {
|
||
args[i] = m
|
||
}
|
||
err = cache.RedisClient.ZRem(modelCast.AutoConfirmAnalysisQueueKey, args...).Err()
|
||
if err != nil {
|
||
zap.L().Error("从队列移除数据分析任务失败",
|
||
zap.String("analysisUuid", analysisUuid),
|
||
zap.Error(err))
|
||
}
|
||
zap.L().Info("数据分析自动确认成功", zap.String("analysisUuid", analysisUuid))
|
||
}
|
||
|
||
// autoConfirmAnalysis 自动确认数据分析
|
||
func autoConfirmAnalysis(ctx context.Context, analysisUuid string) (err error) {
|
||
var confirmRemark string
|
||
var isFailed bool
|
||
var usedType uint32
|
||
infoResp, err := service.CastProvider.GetWorkAnalysis(context.Background(), &cast.GetWorkAnalysisDetailReq{
|
||
Uuid: analysisUuid,
|
||
})
|
||
if err != nil {
|
||
zap.L().Error("autoConfirmAnalysis GetWorkAnalysis", zap.Any("err", err))
|
||
confirmRemark = "获取数据分析详情失败:" + err.Error()
|
||
isFailed = true
|
||
}
|
||
|
||
if infoResp.WorkAnalysisStatus != 4 { // 4是待确认状态,需要根据实际情况调整
|
||
return
|
||
}
|
||
userID, _ := strconv.ParseInt(infoResp.ArtistID, 10, 64)
|
||
balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
|
||
UserId: int32(userID),
|
||
})
|
||
if err != nil {
|
||
zap.L().Error("autoConfirmAnalysis GetBundleBalanceByUserId", zap.Any("err", err))
|
||
confirmRemark = "获取余额失败:" + err.Error()
|
||
isFailed = true
|
||
}
|
||
|
||
var addBalanceReq bundle.AddBundleBalanceReq
|
||
addBalanceReq.UserId = int32(userID)
|
||
// 检查数据分析余量
|
||
if balanceInfoRes.DataAnalysisConsumptionNumber >= balanceInfoRes.DataAnalysisNumber {
|
||
confirmRemark = "数据分析余量不足"
|
||
isFailed = true
|
||
}
|
||
addBalanceReq.DataAnalysisConsumptionNumber = 1
|
||
|
||
zap.L().Info("autoConfirmAnalysis AddBundleBalanceReq", zap.Any("addBalanceReq", &addBalanceReq))
|
||
resp, err := service.BundleProvider.AddBundleBalance(context.Background(), &addBalanceReq)
|
||
if err != nil {
|
||
zap.L().Error("autoConfirmAnalysis AddBundleBalance", zap.Any("err", err))
|
||
confirmRemark = "扣除失败:" + err.Error()
|
||
isFailed = true
|
||
}
|
||
zap.L().Info("autoConfirmAnalysis AddBundleBalanceResp", zap.Any("resp", resp))
|
||
var confirmStatus uint32 = 1
|
||
if isFailed {
|
||
usedType = 0
|
||
confirmStatus = 3
|
||
} else {
|
||
usedType = resp.UsedType
|
||
confirmRemark = "系统自动确认"
|
||
confirmStatus = 1
|
||
}
|
||
var mm = make(map[string]interface{}, 3)
|
||
mm["userid"] = 0
|
||
mm["name"] = "系统自动确定"
|
||
mm["phone"] = ""
|
||
newCtx := context.WithValue(context.Background(), constant.DubboCtxKey("attachment"), mm)
|
||
_, err = service.CastProvider.UpdateWorkAnalysisStatus(newCtx, &cast.UpdateWorkAnalysisStatusReq{
|
||
WorkAction: cast.WorkActionENUM_CONFIRM,
|
||
Uuid: analysisUuid,
|
||
ConfirmRemark: confirmRemark,
|
||
CostType: usedType,
|
||
ConfirmStatus: confirmStatus,
|
||
ConfirmType: 2,
|
||
})
|
||
if err != nil {
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
// TriggerAyrshareMetricsCollector 手动触发 Ayrshare 指标采集任务
|
||
func TriggerAyrshareMetricsCollector(ctx *gin.Context) {
|
||
// 在后台 goroutine 中执行任务,避免阻塞 HTTP 请求
|
||
go func() {
|
||
// 同时使用 zap 和 fmt.Printf 确保日志输出到终端
|
||
zap.L().Info("手动触发 Ayrshare 指标采集任务")
|
||
fmt.Printf("[%s] 手动触发 Ayrshare 指标采集任务\n", time.Now().Format("2006-01-02 15:04:05"))
|
||
executeAyrshareMetricsCollector()
|
||
}()
|
||
service.Success(ctx, map[string]string{
|
||
"message": "任务已触发,正在后台执行",
|
||
})
|
||
return
|
||
}
|
||
|
||
// ExecuteAyrshareMetricsCollector 提供给定时任务调用的 Ayrshare 指标采集入口
|
||
func ExecuteAyrshareMetricsCollector() {
|
||
executeAyrshareMetricsCollector()
|
||
}
|
||
|
||
// executeAyrshareMetricsCollector 执行 Ayrshare 指标采集任务
|
||
func executeAyrshareMetricsCollector() {
|
||
ctx := context.Background()
|
||
zap.L().Info("开始执行 Ayrshare 指标采集任务")
|
||
fmt.Printf("[%s] [INFO] 开始执行 Ayrshare 指标采集任务\n", time.Now().Format("2006-01-02 15:04:05"))
|
||
|
||
// 获取当前日期(中国时区,格式:YYYYMMDD)
|
||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||
now := time.Now().In(loc)
|
||
dateCN := now.Year()*10000 + int(now.Month())*100 + now.Day()
|
||
|
||
// 第一步:获取所有状态为1的艺人AyrShare信息
|
||
mediaMetricsList, err := collectMediaMetricsForAyrshare(ctx, dateCN)
|
||
if err != nil {
|
||
zap.L().Error("采集账号指标失败", zap.Error(err))
|
||
fmt.Printf("[%s] [ERROR] 采集账号指标失败: %v\n", time.Now().Format("2006-01-02 15:04:05"), err)
|
||
return
|
||
}
|
||
|
||
// 批量插入账号指标
|
||
if len(mediaMetricsList) > 0 {
|
||
req := &cast.UpsertMediaMetricsDailyBatchReq{
|
||
Data: mediaMetricsList,
|
||
}
|
||
resp, err := service.CastProvider.UpsertMediaMetricsDailyBatch(ctx, req)
|
||
if err != nil {
|
||
zap.L().Error("批量插入账号指标失败", zap.Error(err))
|
||
fmt.Printf("[%s] [ERROR] 批量插入账号指标失败: %v\n", time.Now().Format("2006-01-02 15:04:05"), err)
|
||
} else if resp != nil && resp.Success {
|
||
zap.L().Info("批量插入账号指标成功", zap.Int("count", len(mediaMetricsList)))
|
||
fmt.Printf("[%s] [INFO] 批量插入账号指标成功,数量: %d\n", time.Now().Format("2006-01-02 15:04:05"), len(mediaMetricsList))
|
||
}
|
||
}
|
||
|
||
// 第二步:获取作品指标
|
||
workMetricsList, err := collectWorkMetricsForAyrshare(ctx, dateCN)
|
||
if err != nil {
|
||
zap.L().Error("采集作品指标失败", zap.Error(err))
|
||
fmt.Printf("[%s] [ERROR] 采集作品指标失败: %v\n", time.Now().Format("2006-01-02 15:04:05"), err)
|
||
return
|
||
}
|
||
|
||
// 批量插入作品指标
|
||
if len(workMetricsList) > 0 {
|
||
req := &cast.UpsertWorkMetricsDailyBatchReq{
|
||
Data: workMetricsList,
|
||
}
|
||
resp, err := service.CastProvider.UpsertWorkMetricsDailyBatch(ctx, req)
|
||
if err != nil {
|
||
zap.L().Error("批量插入作品指标失败", zap.Error(err))
|
||
fmt.Printf("[%s] [ERROR] 批量插入作品指标失败: %v\n", time.Now().Format("2006-01-02 15:04:05"), err)
|
||
} else if resp != nil && resp.Success {
|
||
zap.L().Info("批量插入作品指标成功", zap.Int("count", len(workMetricsList)))
|
||
fmt.Printf("[%s] [INFO] 批量插入作品指标成功,数量: %d\n", time.Now().Format("2006-01-02 15:04:05"), len(workMetricsList))
|
||
}
|
||
}
|
||
|
||
zap.L().Info("Ayrshare 指标采集任务执行完成")
|
||
fmt.Printf("[%s] [INFO] Ayrshare 指标采集任务执行完成\n", time.Now().Format("2006-01-02 15:04:05"))
|
||
}
|
||
|
||
// collectMediaMetricsForAyrshare 采集账号指标
|
||
func collectMediaMetricsForAyrshare(ctx context.Context, dateCN int) ([]*cast.MediaMetricsDailyItem, error) {
|
||
metricsList := make([]*cast.MediaMetricsDailyItem, 0)
|
||
page := int32(1)
|
||
pageSize := int32(500)
|
||
fmt.Printf("[%s] [INFO] 开始采集账号指标\n", time.Now().Format("2006-01-02 15:04:05"))
|
||
|
||
for {
|
||
// 获取状态为1的艺人AyrShare信息
|
||
req := &cast.GetArtistAyrShareInfoReq{
|
||
Status: 1, // 状态为1表示有效
|
||
Page: page,
|
||
PageSize: pageSize,
|
||
}
|
||
resp, err := service.CastProvider.GetArtistAyrShareInfo(ctx, req)
|
||
if err != nil {
|
||
zap.L().Error("获取艺人AyrShare信息失败", zap.Error(err), zap.Int32("page", page))
|
||
fmt.Printf("[%s] [ERROR] 获取艺人AyrShare信息失败,页码: %d, 错误: %v\n", time.Now().Format("2006-01-02 15:04:05"), page, err)
|
||
return metricsList, err
|
||
}
|
||
|
||
if resp == nil || resp.Data == nil || len(resp.Data) == 0 {
|
||
break
|
||
}
|
||
|
||
fmt.Printf("[%s] [INFO] 获取到第 %d 页艺人信息,数量: %d\n", time.Now().Format("2006-01-02 15:04:05"), page, len(resp.Data))
|
||
|
||
// 对每个艺人调用 GetSocialAnalytics
|
||
for _, artistInfo := range resp.Data {
|
||
if artistInfo.ProfileKey == "" {
|
||
zap.L().Warn("艺人ProfileKey为空,跳过", zap.String("artistUuid", artistInfo.ArtistUuid))
|
||
fmt.Printf("[%s] [WARN] 艺人ProfileKey为空,跳过,artistUuid: %s\n", time.Now().Format("2006-01-02 15:04:05"), artistInfo.ArtistUuid)
|
||
continue
|
||
}
|
||
|
||
// 调用 GetSocialAnalytics,平台为 ["instagram", "tiktok"]
|
||
socialReq := &aryshare.GetSocialAnalyticsRequest{
|
||
Platforms: []string{"instagram", "tiktok"},
|
||
ProfileKey: artistInfo.ProfileKey,
|
||
}
|
||
socialResp, err := service.AyrshareProvider.GetSocialAnalytics(ctx, socialReq)
|
||
if err != nil {
|
||
zap.L().Warn("获取社交分析数据失败", zap.Error(err), zap.String("profileKey", artistInfo.ProfileKey))
|
||
fmt.Printf("[%s] [WARN] 获取社交分析数据失败,profileKey: %s, 错误: %v\n", time.Now().Format("2006-01-02 15:04:05"), artistInfo.ProfileKey, err)
|
||
continue
|
||
}
|
||
|
||
fmt.Println("socialResp", socialResp)
|
||
|
||
// 解析 JSON 数据并构建指标
|
||
items := parseSocialAnalyticsToMediaMetricsForAyrshare(socialResp, artistInfo, dateCN)
|
||
metricsList = append(metricsList, items...)
|
||
|
||
// 避免请求过于频繁
|
||
time.Sleep(200 * time.Millisecond)
|
||
}
|
||
|
||
// 如果返回的数据少于 pageSize,说明已经是最后一页
|
||
if len(resp.Data) < int(pageSize) {
|
||
break
|
||
}
|
||
page++
|
||
}
|
||
|
||
fmt.Printf("[%s] [INFO] 账号指标采集完成,共采集 %d 条\n", time.Now().Format("2006-01-02 15:04:05"), len(metricsList))
|
||
fmt.Println("metricsList", metricsList)
|
||
return metricsList, nil
|
||
}
|
||
|
||
// parseSocialAnalyticsToMediaMetricsForAyrshare 解析社交分析数据并转换为媒体指标
|
||
func parseSocialAnalyticsToMediaMetricsForAyrshare(socialResp *aryshare.GetSocialAnalyticsResponse, artistInfo *cast.ArtistAyrShareInfo, dateCN int) []*cast.MediaMetricsDailyItem {
|
||
items := make([]*cast.MediaMetricsDailyItem, 0)
|
||
|
||
// 解析 Instagram 数据
|
||
if socialResp.Instagram != "" {
|
||
// 调试:打印 Instagram JSON 字符串的前500字符
|
||
instaPreview := socialResp.Instagram
|
||
if len(instaPreview) > 500 {
|
||
instaPreview = instaPreview[:500] + "..."
|
||
}
|
||
fmt.Printf("[%s] [DEBUG] Instagram JSON 字符串预览: %s\n", time.Now().Format("2006-01-02 15:04:05"), instaPreview)
|
||
|
||
item := parsePlatformDataForAyrshare(socialResp.Instagram, "instagram", artistInfo, dateCN)
|
||
if item != nil {
|
||
items = append(items, item)
|
||
fmt.Printf("[%s] [INFO] 解析 Instagram 账号指标成功,艺人: %s\n", time.Now().Format("2006-01-02 15:04:05"), artistInfo.ArtistUuid)
|
||
}
|
||
}
|
||
|
||
// 解析 TikTok 数据
|
||
if socialResp.Tiktok != "" {
|
||
// 调试:打印 TikTok JSON 字符串的前500字符
|
||
tiktokPreview := socialResp.Tiktok
|
||
if len(tiktokPreview) > 500 {
|
||
tiktokPreview = tiktokPreview[:500] + "..."
|
||
}
|
||
fmt.Printf("[%s] [DEBUG] TikTok JSON 字符串预览: %s\n", time.Now().Format("2006-01-02 15:04:05"), tiktokPreview)
|
||
|
||
item := parsePlatformDataForAyrshare(socialResp.Tiktok, "tiktok", artistInfo, dateCN)
|
||
if item != nil {
|
||
items = append(items, item)
|
||
fmt.Printf("[%s] [INFO] 解析 TikTok 账号指标成功,艺人: %s\n", time.Now().Format("2006-01-02 15:04:05"), artistInfo.ArtistUuid)
|
||
}
|
||
}
|
||
|
||
fmt.Println("items", items)
|
||
fmt.Println("items length", len(items))
|
||
|
||
return items
|
||
}
|
||
|
||
// parsePlatformDataForAyrshare 解析平台数据(JSON格式)
|
||
func parsePlatformDataForAyrshare(jsonData, platform string, artistInfo *cast.ArtistAyrShareInfo, dateCN int) *cast.MediaMetricsDailyItem {
|
||
// 调试:打印原始 JSON 数据(截取前500字符避免日志过长)
|
||
jsonPreview := jsonData
|
||
fmt.Printf("parsePlatformDataForAyrshare 原始 JSON 数据: %s\n", jsonPreview)
|
||
|
||
var rootData map[string]interface{}
|
||
if err := json.Unmarshal([]byte(jsonData), &rootData); err != nil {
|
||
zap.L().Warn("解析平台数据失败", zap.Error(err), zap.String("platform", platform))
|
||
fmt.Printf("parsePlatformDataForAyrshare 解析平台数据失败,平台: %s, 错误: %v\n", platform, err)
|
||
return nil
|
||
}
|
||
|
||
// 调试:打印根数据的所有 key
|
||
rootKeys := make([]string, 0, len(rootData))
|
||
for k := range rootData {
|
||
rootKeys = append(rootKeys, k)
|
||
}
|
||
fmt.Printf("parsePlatformDataForAyrshare 根数据字段: %v\n", rootKeys)
|
||
|
||
// 根据平台映射平台ID:1 TikTok, 3 Instagram
|
||
var platformID uint32
|
||
if platform == "tiktok" {
|
||
platformID = 1
|
||
} else if platform == "instagram" {
|
||
platformID = 3
|
||
} else {
|
||
return nil
|
||
}
|
||
|
||
// 从根数据中提取 analytics 对象,实际数据在 analytics 字段下
|
||
var analyticsData map[string]interface{}
|
||
if analyticsVal, ok := rootData["analytics"]; ok {
|
||
if analyticsMap, ok := analyticsVal.(map[string]interface{}); ok {
|
||
analyticsData = analyticsMap
|
||
} else {
|
||
fmt.Printf("parsePlatformDataForAyrshare analytics 字段类型不正确: %T\n", analyticsVal)
|
||
}
|
||
} else {
|
||
fmt.Printf("[%s] [WARN] %s 根数据中没有找到 analytics 字段\n", time.Now().Format("2006-01-02 15:04:05"), platform)
|
||
}
|
||
|
||
// 如果没有 analytics 字段,尝试直接从根数据提取(兼容旧格式)
|
||
if analyticsData == nil {
|
||
analyticsData = rootData
|
||
fmt.Printf("parsePlatformDataForAyrshare 使用根数据作为 analytics 数据\n")
|
||
}
|
||
|
||
// 调试:打印 analytics 数据的所有 key,帮助诊断字段名
|
||
if len(analyticsData) > 0 {
|
||
keys := make([]string, 0, len(analyticsData))
|
||
for k := range analyticsData {
|
||
keys = append(keys, k)
|
||
}
|
||
fmt.Printf("parsePlatformDataForAyrshare analytics 数据字段: %v\n", keys)
|
||
} else {
|
||
fmt.Printf("parsePlatformDataForAyrshare analytics 数据为空\n")
|
||
}
|
||
|
||
// 提取指标数据(根据 Ayrshare API 的实际返回结构)
|
||
// Instagram 字段:followersCount, likeCount, mediaCount, viewsCount, commentsCount
|
||
// TikTok 字段:videoCountTotal, viewCountTotal, commentCountTotal, shareCountTotal
|
||
item := &cast.MediaMetricsDailyItem{
|
||
Uuid: uuid.NewString(),
|
||
ArtistUuid: artistInfo.ArtistUuid,
|
||
MediaAccUserID: "", // MediaAccUserID 需要通过其他接口获取,暂时留空
|
||
MediaName: "", // MediaName 需要通过其他接口获取,暂时留空
|
||
ArtistName: "", // ArtistName 需要通过其他接口获取,暂时留空
|
||
ArtistPhone: "", // ArtistPhone 需要通过其他接口获取,暂时留空
|
||
PlatformID: platformID,
|
||
Date: int32(dateCN),
|
||
// 粉丝数:Instagram 使用 followsCount,TikTok 可能没有直接对应字段
|
||
FansCount: extractInt64ForAyrshare(analyticsData, "followsCount", "followersCount", "followers", "followerCount", "fans", "fanCount"),
|
||
// 观看量:Instagram 使用 viewsCount,TikTok 使用 viewCountTotal
|
||
ViewsCount: extractInt64ForAyrshare(analyticsData, "viewCountTotal", "viewsCount", "views", "viewCount", "viewCountPeriod"),
|
||
// 点赞数:Instagram 使用 likeCount
|
||
LikesCount: extractInt64ForAyrshare(analyticsData, "likeCount", "likes", "likesCount", "likeCountTotal"),
|
||
// 评论数:Instagram 使用 commentsCount,TikTok 使用 commentCountTotal
|
||
CommentsCount: extractInt64ForAyrshare(analyticsData, "commentCountTotal", "commentsCount", "comments", "commentCount", "commentCountPeriod"),
|
||
// 分享数:Instagram 使用 reachCount,TikTok 使用 shareCountTotal
|
||
SharesCount: extractInt64ForAyrshare(analyticsData, "shareCountTotal", "shares", "shareCount", "sharesCount", "shareCountPeriod"),
|
||
// 视频数:Instagram 使用 mediaCount,TikTok 使用 videoCountTotal
|
||
VideoCount: extractInt64ForAyrshare(analyticsData, "mediaCount", "videoCountTotal", "videos", "videoCount", "videosCount"),
|
||
// 图片/媒体数:Instagram 可能没有直接对应字段,使用 posts 等
|
||
ImageCount: extractInt64ForAyrshare(analyticsData, "posts", "postCount", "postsCount", "images", "imageCount", "imagesCount"),
|
||
}
|
||
|
||
// 调试:打印提取到的指标值
|
||
fmt.Printf("parsePlatformDataForAyrshare 提取的指标 - 粉丝数: %d, 观看量: %d, 点赞数: %d, 评论数: %d, 分享数: %d, 视频数: %d, 图片数: %d\n",
|
||
item.FansCount, item.ViewsCount, item.LikesCount, item.CommentsCount, item.SharesCount, item.VideoCount, item.ImageCount)
|
||
|
||
return item
|
||
}
|
||
|
||
// extractInt64ForAyrshare 从 map 中提取 int64 值,尝试多个可能的 key
|
||
// getMapKeys 获取 map 的所有键,用于调试
|
||
func getMapKeys(m map[string]interface{}) []string {
|
||
keys := make([]string, 0, len(m))
|
||
for k := range m {
|
||
keys = append(keys, k)
|
||
}
|
||
return keys
|
||
}
|
||
|
||
func extractInt64ForAyrshare(data map[string]interface{}, keys ...string) int64 {
|
||
for _, key := range keys {
|
||
if val, ok := data[key]; ok {
|
||
// 调试:打印找到的字段和值
|
||
fmt.Printf("extractInt64ForAyrshare 找到字段 %s, 值: %v, 类型: %T\n", key, val, val)
|
||
switch v := val.(type) {
|
||
case float64:
|
||
return int64(v)
|
||
case int64:
|
||
return v
|
||
case int:
|
||
return int64(v)
|
||
case int32:
|
||
return int64(v)
|
||
case string:
|
||
// 如果是字符串,尝试解析为数字
|
||
if key == "viewCountPeriod" || key == "commentCountPeriod" || key == "shareCountPeriod" {
|
||
// 这些字段是字符串,跳过
|
||
continue
|
||
}
|
||
// 尝试将字符串解析为数字
|
||
if num, err := strconv.ParseInt(v, 10, 64); err == nil {
|
||
return num
|
||
}
|
||
if num, err := strconv.ParseFloat(v, 64); err == nil {
|
||
return int64(num)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// collectWorkMetricsForAyrshare 采集作品指标
|
||
func collectWorkMetricsForAyrshare(ctx context.Context, dateCN int) ([]*cast.WorkMetricsDailyItem, error) {
|
||
metricsList := make([]*cast.WorkMetricsDailyItem, 0)
|
||
fmt.Printf("[%s] [INFO] 开始采集作品指标\n", time.Now().Format("2006-01-02 15:04:05"))
|
||
|
||
// 调用 ListWorkPlatformInfo,PlatformIDs=[1,3], PublishMediaStatus=2, PageSize=99999999
|
||
req := &cast.ListWorkPlatformInfoReq{
|
||
PlatformIDs: []uint32{1, 3}, // 1 TikTok, 3 Instagram
|
||
PublishMediaStatus: 2, // 状态为2
|
||
Page: 1,
|
||
PageSize: 99999999,
|
||
}
|
||
resp, err := service.CastProvider.ListWorkPlatformInfo(ctx, req)
|
||
if err != nil {
|
||
return metricsList, err
|
||
}
|
||
|
||
fmt.Println("--------------------------------")
|
||
fmt.Println("66666666666666666666666666666")
|
||
fmt.Println("resp", resp)
|
||
fmt.Println("66666666666666666666666666666")
|
||
fmt.Println("--------------------------------")
|
||
|
||
if resp == nil || resp.Data == nil || len(resp.Data) == 0 {
|
||
zap.L().Info("没有作品平台信息")
|
||
return metricsList, nil
|
||
}
|
||
|
||
// 对每个作品调用 GetPostAnalytics
|
||
for _, platformInfo := range resp.Data {
|
||
if platformInfo.PublishMediaID == "" || platformInfo.WorkUuid == "" {
|
||
continue
|
||
}
|
||
|
||
// 只处理 TikTok(1) 和 Instagram(3) 平台
|
||
if platformInfo.PlatformID != 1 && platformInfo.PlatformID != 3 {
|
||
continue
|
||
}
|
||
|
||
// 通过 ArtistUuid 获取艺人的 AyrShare 信息,获取 profileKey
|
||
artistAyrShareReq := &cast.GetArtistAyrShareInfoReq{
|
||
ArtistUuid: platformInfo.ArtistUuid,
|
||
Status: 1, // 状态为1表示有效
|
||
Page: 1,
|
||
PageSize: 1,
|
||
}
|
||
artistAyrShareResp, err := service.CastProvider.GetArtistAyrShareInfo(ctx, artistAyrShareReq)
|
||
if err != nil || artistAyrShareResp == nil || len(artistAyrShareResp.Data) == 0 {
|
||
zap.L().Warn("获取艺人AyrShare信息失败", zap.Error(err), zap.String("artistUuid", platformInfo.ArtistUuid))
|
||
fmt.Printf("collectWorkMetricsForAyrshare 获取艺人AyrShare信息失败,artistUuid: %s, 错误: %v\n", platformInfo.ArtistUuid, err)
|
||
continue
|
||
}
|
||
|
||
profileKey := artistAyrShareResp.Data[0].ProfileKey
|
||
if profileKey == "" {
|
||
zap.L().Warn("作品ProfileKey为空,跳过", zap.String("workUuid", platformInfo.WorkUuid))
|
||
fmt.Printf("collectWorkMetricsForAyrshare 作品ProfileKey为空,跳过,workUuid: %s\n", platformInfo.WorkUuid)
|
||
continue
|
||
}
|
||
|
||
// 调用 GetPostAnalytics 接口
|
||
var postReq *aryshare.GetPostAnalyticsRequest
|
||
if platformInfo.PlatformID == 1 {
|
||
// TikTok 平台
|
||
postReq = &aryshare.GetPostAnalyticsRequest{
|
||
Id: platformInfo.PublishMediaID,
|
||
Platforms: []string{"tiktok"},
|
||
ProfileKey: profileKey,
|
||
}
|
||
} else if platformInfo.PlatformID == 3 {
|
||
// Instagram 平台
|
||
postReq = &aryshare.GetPostAnalyticsRequest{
|
||
Id: platformInfo.PublishMediaID,
|
||
Platforms: []string{"instagram"},
|
||
ProfileKey: profileKey,
|
||
}
|
||
}
|
||
|
||
postResp, err := service.AyrshareProvider.GetPostAnalytics(ctx, postReq)
|
||
fmt.Println("--------------------------------")
|
||
fmt.Println("postResp", postResp)
|
||
fmt.Println("--------------------------------")
|
||
if err != nil {
|
||
zap.L().Warn("获取作品分析数据失败", zap.Error(err), zap.String("publishMediaID", platformInfo.PublishMediaID))
|
||
fmt.Printf("collectWorkMetricsForAyrshare 获取作品分析数据失败,publishMediaID: %s, 错误: %v\n", platformInfo.PublishMediaID, err)
|
||
continue
|
||
}
|
||
|
||
// 解析作品分析数据并构建指标
|
||
item := parsePostAnalyticsToWorkMetricsForAyrshare(postResp, platformInfo, dateCN)
|
||
if item != nil {
|
||
fmt.Println("--------------------------------")
|
||
fmt.Println("test")
|
||
fmt.Println("item", item)
|
||
fmt.Println("--------------------------------")
|
||
metricsList = append(metricsList, item)
|
||
fmt.Printf("collectWorkMetricsForAyrshare 解析作品指标成功,workUuid: %s, platformID: %d\n", platformInfo.WorkUuid, platformInfo.PlatformID)
|
||
}
|
||
|
||
// 避免请求过于频繁
|
||
time.Sleep(200 * time.Millisecond)
|
||
}
|
||
|
||
fmt.Println("--------------------------------")
|
||
fmt.Println("metricsList", metricsList)
|
||
fmt.Println("--------------------------------")
|
||
|
||
fmt.Printf("collectWorkMetricsForAyrshare 作品指标采集完成,共采集 %d 条\n", len(metricsList))
|
||
return metricsList, nil
|
||
}
|
||
|
||
// parsePostAnalyticsToWorkMetricsForAyrshare 解析作品分析数据并转换为作品指标
|
||
func parsePostAnalyticsToWorkMetricsForAyrshare(postResp *aryshare.GetPostAnalyticsResponse, platformInfo *cast.WorkPlatformInfo, dateCN int) *cast.WorkMetricsDailyItem {
|
||
fmt.Println("--------------------------------")
|
||
fmt.Println("44444444444444444444444444444")
|
||
fmt.Println("platformInfo", platformInfo)
|
||
fmt.Println("44444444444444444444444444444")
|
||
fmt.Println("--------------------------------")
|
||
// 根据平台ID选择对应的 JSON 数据
|
||
var jsonData string
|
||
if platformInfo.PlatformID == 1 { // TikTok
|
||
jsonData = postResp.Tiktok
|
||
} else if platformInfo.PlatformID == 3 { // Instagram
|
||
jsonData = postResp.Instagram
|
||
} else {
|
||
return nil
|
||
}
|
||
|
||
if jsonData == "" {
|
||
return nil
|
||
}
|
||
|
||
// 解析 JSON 数据
|
||
var rootData map[string]interface{}
|
||
if err := json.Unmarshal([]byte(jsonData), &rootData); err != nil {
|
||
zap.L().Warn("解析作品分析数据失败", zap.Error(err))
|
||
fmt.Printf("parsePostAnalyticsToWorkMetricsForAyrshare 解析作品分析数据失败,workUuid: %s, 错误: %v\n", platformInfo.WorkUuid, err)
|
||
return nil
|
||
}
|
||
|
||
// 调试:打印根数据的键
|
||
fmt.Printf("[DEBUG] 根数据包含的键: %v\n", getMapKeys(rootData))
|
||
|
||
// 从根数据中提取 analytics 对象,实际数据可能在 analytics 字段下
|
||
var analyticsData map[string]interface{}
|
||
if analyticsVal, ok := rootData["analytics"]; ok {
|
||
if analyticsMap, ok := analyticsVal.(map[string]interface{}); ok {
|
||
analyticsData = analyticsMap
|
||
fmt.Printf("analytics 字段提取数据,包含的键: %v\n", getMapKeys(analyticsData))
|
||
}
|
||
}
|
||
|
||
// 如果没有 analytics 字段,尝试直接从根数据提取(兼容旧格式)
|
||
if analyticsData == nil {
|
||
analyticsData = rootData
|
||
fmt.Printf("parsePostAnalyticsToWorkMetricsForAyrshare 使用根数据作为 analyticsData,包含的键: %v\n", getMapKeys(analyticsData))
|
||
}
|
||
|
||
// 构建作品指标项,使用 ListWorkPlatformInfo 返回的字段信息
|
||
item := &cast.WorkMetricsDailyItem{
|
||
Uuid: uuid.NewString(),
|
||
WorkUuid: platformInfo.WorkUuid,
|
||
ArtistUuid: platformInfo.ArtistUuid,
|
||
MediaAccUserID: platformInfo.PlatformUserID, // 使用平台用户ID
|
||
MediaName: platformInfo.PlatformUserName, // 平台用户名
|
||
ArtistName: platformInfo.ArtistName, // 艺人名字
|
||
ArtistPhone: platformInfo.ArtistPhone, // 艺人手机号
|
||
PlatformID: platformInfo.PlatformID,
|
||
Date: int32(dateCN),
|
||
}
|
||
|
||
// 根据平台ID使用不同的字段提取逻辑
|
||
if platformInfo.PlatformID == 3 {
|
||
// Instagram 平台
|
||
// 访问量:使用 viewsCount
|
||
item.ViewsCount = extractInt64ForAyrshare(analyticsData, "viewsCount", "viewCount", "views")
|
||
// 点赞数:使用 likeCount
|
||
item.LikesCount = extractInt64ForAyrshare(analyticsData, "likeCount", "likes", "likesCount")
|
||
// 评论数:Instagram 可能没有评论数字段,尝试多种可能
|
||
item.CommentsCount = extractInt64ForAyrshare(analyticsData, "commentsCount", "commentCount", "comments")
|
||
// 分享数:使用 sharesCount(注意是复数形式)
|
||
item.SharesCount = extractInt64ForAyrshare(analyticsData, "sharesCount", "shareCount", "shares")
|
||
|
||
// 打印解析结果
|
||
fmt.Printf("parsePostAnalyticsToWorkMetricsForAyrshare Instagram 作品指标解析完成 - workUuid: %s, 访问量: %d, 点赞数: %d, 评论数: %d, 分享数: %d\n",
|
||
platformInfo.WorkUuid,
|
||
item.ViewsCount, item.LikesCount, item.CommentsCount, item.SharesCount)
|
||
} else if platformInfo.PlatformID == 1 {
|
||
// TikTok 平台
|
||
// 访问量:使用 viewCountTotal
|
||
item.ViewsCount = extractInt64ForAyrshare(analyticsData, "viewCountTotal", "viewCount", "views", "videoViews")
|
||
// 点赞数:使用 likeCount
|
||
item.LikesCount = extractInt64ForAyrshare(analyticsData, "likeCount", "likes", "likesCount")
|
||
// 评论数:使用 commentCountTotal
|
||
item.CommentsCount = extractInt64ForAyrshare(analyticsData, "commentCountTotal", "commentCount", "comments", "commentsCount")
|
||
// 分享数:使用 shareCountTotal
|
||
item.SharesCount = extractInt64ForAyrshare(analyticsData, "shareCountTotal", "shareCount", "shares", "sharesCount")
|
||
|
||
// 打印解析结果
|
||
fmt.Printf("parsePostAnalyticsToWorkMetricsForAyrshare TikTok 作品指标解析完成 - workUuid: %s, 访问量: %d, 点赞数: %d, 评论数: %d, 分享数: %d\n",
|
||
platformInfo.WorkUuid,
|
||
item.ViewsCount, item.LikesCount, item.CommentsCount, item.SharesCount)
|
||
}
|
||
|
||
fmt.Println("--------------------------------")
|
||
fmt.Println("5555555555555555555555")
|
||
fmt.Println("item", item)
|
||
fmt.Println("5555555555555555555555")
|
||
fmt.Println("--------------------------------")
|
||
|
||
return item
|
||
}
|