Files
likedream/internal/application/xuexitong/xuexitong_document.go
T
sugarBecomer 55fc94c37f 🐛 文档修复
2025-12-19 23:08:16 +08:00

232 lines
6.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package xuexitong
import (
"context"
"encoding/json"
"likedream-goframe/internal/application/xuexitong/entity"
errors2 "likedream-goframe/internal/common/errors"
"likedream-goframe/internal/framework/logger"
"net/url"
"strconv"
"time"
"github.com/avast/retry-go/v4"
"go.uber.org/zap"
)
// attachmentDetectDocument 从附件设置中检测并填充文档信息
func (c *XuexitongCourse) attachmentDetectDocument(attachment *entity.AttachmentSetting, p *entity.ChapterPoint) {
for _, att := range attachment.Attachments {
typeStr := ""
// 进行不同方案的类型值获取
if t, ok := att["type"].(string); ok {
typeStr = t
} else if property, ok := att["property"].(map[string]interface{}); ok {
if module, ok := property["module"].(string); ok {
typeStr = module
}
}
property, ok := att["property"].(map[string]interface{})
if !ok {
continue
}
// 如果未给出文档类型,先进行文档解析尝试
if typeStr == "" {
if name, ok := property["name"].(string); ok {
p.Title = name
}
if jid, ok := property["jobid"].(string); ok {
p.JobID = jid
}
if jtoken, ok := att["jtoken"].(string); ok {
p.Jtoken = jtoken
}
if isJob, ok := att["job"].(bool); ok {
p.IsJob = isJob
} else {
p.IsJob = false
}
if bookname, ok := property["bookname"].(string); ok {
p.Title = bookname
}
// 过滤匹配
objectid, _ := property["objectid"].(string)
jobid, _ := property["jobid"].(string)
if (p.ObjectID != "" && objectid == p.ObjectID) || (jobid != "" && p.JobID == jobid) {
break
}
} else if typeStr == "insertbook" || typeStr == "read" {
if jtoken, ok := att["jtoken"].(string); ok {
p.Jtoken = jtoken
}
if isJob, ok := att["job"].(bool); ok {
p.IsJob = isJob
} else {
p.IsJob = false
}
if bookname, ok := property["bookname"].(string); ok {
p.Title = bookname
}
if typeStr == "insertbook" {
p.DocumentType = "insertbook"
} else {
p.DocumentType = "read"
}
// 过滤匹配
objectid, _ := property["objectid"].(string)
jobid, _ := property["jobid"].(string)
if (p.ObjectID != "" && objectid == p.ObjectID) || (jobid != "" && p.JobID == jobid) {
break
}
} else if typeStr == "document" || typeStr == "insertdoc" {
if isJob, ok := att["job"].(bool); ok {
p.IsJob = isJob
}
objectid, _ := property["objectid"].(string)
if objectid == p.ObjectID {
if name, ok := property["name"].(string); ok {
p.Title = name
}
if jid, ok := property["jobid"].(string); ok {
p.JobID = jid
}
if jtoken, ok := att["jtoken"].(string); ok {
p.Jtoken = jtoken
}
p.DocumentType = "document"
break
}
}
}
}
// DocumentDtoReadingReport 提交文档阅读完成
func (c *XuexitongCourse) DocumentDtoReadingReport(ctx context.Context, p *entity.PointDocumentDto) (string, error) {
params := url.Values{}
params.Add("jobid", p.JobID)
params.Add("knowledgeid", strconv.Itoa(p.KnowledgeID))
params.Add("courseid", p.CourseID)
params.Add("clazzid", p.ClassID)
params.Add("jtoken", p.Jtoken)
params.Add("_dc", strconv.FormatInt(time.Now().UnixMilli(), 10))
apiUrl := ApiDocumentReport
if p.Cpi == "insertbook" {
apiUrl = ApiDocumentBook
}
var body string
err := retry.Do(func() error {
resp, err := c.client.R().SetHeaders(map[string]string{
"User-Agent": GetUA("mobile"),
}).Get(apiUrl + "?" + params.Encode())
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return errors2.NewBusinessError(resp.StatusCode(), "提交文档阅读失败")
}
body = resp.String()
return nil
}, retry.Attempts(3), retry.Delay(2*time.Second))
if err != nil {
return "", err
}
return body, nil
}
// AutoReadDocumentByPoint 自动阅读文档(使用统一的 ChapterPoint)
func (c *XuexitongCourse) AutoReadDocumentByPoint(ctx context.Context, course entity.XueXiTCourse, p *entity.ChapterPoint) error {
// 获取附件信息填充 Jtoken、IsJob 等参数
attachment, _, err := c.PageMobileChapterCard(ctx, course, p.KnowledgeID, p.CardIndex)
if err != nil {
logger.Logger.Error("获取章节卡片失败", zap.String("title", p.Title), zap.Error(err))
return err
}
if attachment != nil {
c.attachmentDetectDocument(attachment, p)
}
logger.Logger.Debug("文档参数",
zap.String("jobID", p.JobID),
zap.String("objectID", p.ObjectID),
zap.String("jtoken", p.Jtoken),
zap.Bool("isJob", p.IsJob),
zap.String("documentType", p.DocumentType))
if !p.IsJob {
logger.Logger.Info("文档不是任务点,跳过", zap.String("jobID", p.JobID), zap.String("title", p.Title))
return nil
}
logger.Logger.Info("开始刷文档",
zap.String("jobID", p.JobID),
zap.String("title", p.Title))
report, err := c.DocumentDtoReadingReportByPoint(ctx, p)
if err != nil {
return err
}
var result map[string]interface{}
if err := json.Unmarshal([]byte(report), &result); err == nil {
if status, ok := result["status"].(bool); ok && status {
logger.Logger.Info("文档刷课完成", zap.String("jobID", p.JobID), zap.String("title", p.Title))
c.onTaskComplete()
return nil
}
if msg, ok := result["msg"].(string); ok {
logger.Logger.Warn("文档无法正常学习", zap.String("msg", msg))
}
}
return nil
}
// DocumentDtoReadingReportByPoint 提交文档阅读完成(使用统一的 ChapterPoint)
func (c *XuexitongCourse) DocumentDtoReadingReportByPoint(ctx context.Context, p *entity.ChapterPoint) (string, error) {
formParams := map[string]string{
"jobid": p.JobID,
"knowledgeid": strconv.Itoa(p.KnowledgeID),
"courseid": p.CourseID,
"clazzid": p.ClassID,
"jtoken": p.Jtoken,
"_dc": strconv.FormatInt(time.Now().UnixMilli(), 10),
}
apiUrl := ApiDocumentReport
if p.DocumentType == "insertbook" {
apiUrl = ApiDocumentBook
} else if p.DocumentType == "read" {
apiUrl = ApiDocumentReadV2
}
// read 类型使用 document 接口
var body string
err := retry.Do(func() error {
resp, err := c.client.R().SetHeaders(map[string]string{
"User-Agent": GetUA("mobile"),
}).SetQueryParams(formParams).Get(apiUrl)
if err != nil {
return err
}
if resp.StatusCode() != 200 {
return errors2.NewBusinessError(resp.StatusCode(), "提交文档阅读失败")
}
body = resp.String()
return nil
}, retry.Attempts(3), retry.Delay(2*time.Second))
if err != nil {
return "", err
}
return body, nil
}