书籍列表接口新增参数
This commit is contained in:
@ -180,13 +180,34 @@ func (s *sChapter) AppList(ctx context.Context, in *model.ChapterAppListIn) (out
|
||||
return nil, ecode.Fail.Sub("read_record_query_failed")
|
||||
}
|
||||
|
||||
// 查询购买记录
|
||||
purchaseRecords := make([]struct {
|
||||
ChapterId int64 `json:"chapterId"`
|
||||
}, 0)
|
||||
|
||||
err = dao.UserChapterPurchases.Ctx(ctx).
|
||||
Fields("chapter_id").
|
||||
Where(dao.UserChapterPurchases.Columns().UserId, in.UserId).
|
||||
Where(dao.UserChapterPurchases.Columns().BookId, in.BookId).
|
||||
WhereIn(dao.UserChapterPurchases.Columns().ChapterId, chapterIds).
|
||||
Scan(&purchaseRecords)
|
||||
if err != nil {
|
||||
return nil, ecode.Fail.Sub("purchase_record_query_failed")
|
||||
}
|
||||
|
||||
// 构建阅读记录映射
|
||||
readMap := make(map[int64]*gtime.Time)
|
||||
for _, record := range readRecords {
|
||||
readMap[record.ChapterId] = record.ReadAt
|
||||
}
|
||||
|
||||
// 为每个章节设置阅读进度
|
||||
// 构建购买记录映射
|
||||
purchaseMap := make(map[int64]bool)
|
||||
for _, record := range purchaseRecords {
|
||||
purchaseMap[record.ChapterId] = true
|
||||
}
|
||||
|
||||
// 为每个章节设置阅读进度和购买状态
|
||||
for i := range out.List {
|
||||
if readAt, exists := readMap[out.List[i].Id]; exists {
|
||||
out.List[i].ReadAt = readAt
|
||||
@ -195,6 +216,19 @@ func (s *sChapter) AppList(ctx context.Context, in *model.ChapterAppListIn) (out
|
||||
out.List[i].ReadProgress = 0 // 未读
|
||||
out.List[i].ReadAt = nil
|
||||
}
|
||||
|
||||
// 设置购买状态
|
||||
if out.List[i].IsLocked == 0 {
|
||||
// 免费章节,直接设置为已购买
|
||||
out.List[i].IsPurchased = true
|
||||
} else {
|
||||
// 付费章节,根据购买记录设置
|
||||
if purchaseMap[out.List[i].Id] {
|
||||
out.List[i].IsPurchased = true
|
||||
} else {
|
||||
out.List[i].IsPurchased = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -473,7 +507,7 @@ func (s *sChapter) AppProgress(ctx context.Context, in *model.ChapterAppProgress
|
||||
readChapters, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
|
||||
Where(dao.UserReadRecords.Columns().UserId, in.UserId).
|
||||
Where(dao.UserReadRecords.Columns().BookId, in.BookId).
|
||||
Where(dao.UserReadRecords.Columns().ChapterId, ">", 0).
|
||||
WhereGT(dao.UserReadRecords.Columns().ChapterId, 0).
|
||||
Count()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("read_chapter_count_failed")
|
||||
@ -525,3 +559,211 @@ func (s *sChapter) AppProgress(ctx context.Context, in *model.ChapterAppProgress
|
||||
out.Success = true
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AppBatchProgress uploads batch reading progress for app
|
||||
func (s *sChapter) AppBatchProgress(ctx context.Context, in *model.ChapterAppBatchProgressIn) (out *model.ChapterAppProgressOut, err error) {
|
||||
out = &model.ChapterAppProgressOut{}
|
||||
|
||||
// 必须指定用户ID
|
||||
if in.UserId == 0 {
|
||||
return nil, ecode.Fail.Sub("user_id_required")
|
||||
}
|
||||
|
||||
// 必须指定书籍ID
|
||||
if in.BookId == 0 {
|
||||
return nil, ecode.Fail.Sub("book_id_required")
|
||||
}
|
||||
|
||||
// 必须指定章节列表
|
||||
if len(in.Chapters) == 0 {
|
||||
return nil, ecode.Fail.Sub("chapters_required")
|
||||
}
|
||||
|
||||
// 检查用户是否存在
|
||||
exist, err := dao.Users.Ctx(ctx).Where(dao.Users.Columns().Id, in.UserId).Exist()
|
||||
if err != nil {
|
||||
return nil, ecode.Fail.Sub("user_query_failed")
|
||||
}
|
||||
if !exist {
|
||||
return nil, ecode.NotFound.Sub("user_not_found")
|
||||
}
|
||||
|
||||
// 验证所有章节进度
|
||||
for _, chapter := range in.Chapters {
|
||||
if chapter.ChapterId == 0 {
|
||||
return nil, ecode.Fail.Sub("chapter_id_required")
|
||||
}
|
||||
if chapter.Progress < 0 || chapter.Progress > 100 {
|
||||
return nil, ecode.Fail.Sub("progress_invalid")
|
||||
}
|
||||
}
|
||||
|
||||
// 检查所有章节是否存在
|
||||
chapterIds := make([]int64, 0)
|
||||
for _, chapter := range in.Chapters {
|
||||
chapterIds = append(chapterIds, chapter.ChapterId)
|
||||
}
|
||||
|
||||
exist, err = dao.Chapters.Ctx(ctx).
|
||||
WhereIn(dao.Chapters.Columns().Id, chapterIds).
|
||||
Where(dao.Chapters.Columns().BookId, in.BookId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return nil, ecode.Fail.Sub("chapter_query_failed")
|
||||
}
|
||||
if !exist {
|
||||
return nil, ecode.NotFound.Sub("chapter_not_found")
|
||||
}
|
||||
|
||||
// 开启事务处理
|
||||
if err := dao.UserReadRecords.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
// 批量处理每个章节的进度
|
||||
for _, chapter := range in.Chapters {
|
||||
// 1. 更新或创建阅读记录
|
||||
exist, err := dao.UserReadRecords.Ctx(ctx).TX(tx).
|
||||
Where(dao.UserReadRecords.Columns().UserId, in.UserId).
|
||||
Where(dao.UserReadRecords.Columns().BookId, in.BookId).
|
||||
Where(dao.UserReadRecords.Columns().ChapterId, chapter.ChapterId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("read_record_query_failed")
|
||||
}
|
||||
|
||||
if exist {
|
||||
// 更新现有记录
|
||||
_, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
|
||||
Where(dao.UserReadRecords.Columns().UserId, in.UserId).
|
||||
Where(dao.UserReadRecords.Columns().BookId, in.BookId).
|
||||
Where(dao.UserReadRecords.Columns().ChapterId, chapter.ChapterId).
|
||||
Data(do.UserReadRecords{
|
||||
Progress: chapter.Progress,
|
||||
ReadAt: gtime.Now(),
|
||||
}).Update()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("read_record_update_failed")
|
||||
}
|
||||
} else {
|
||||
// 创建新记录
|
||||
_, err = dao.UserReadRecords.Ctx(ctx).TX(tx).Data(do.UserReadRecords{
|
||||
UserId: in.UserId,
|
||||
BookId: in.BookId,
|
||||
ChapterId: chapter.ChapterId,
|
||||
Progress: chapter.Progress,
|
||||
ReadAt: gtime.Now(),
|
||||
}).Insert()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("read_record_create_failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 更新或创建历史记录(使用最后一个章节作为当前阅读章节)
|
||||
lastChapter := in.Chapters[len(in.Chapters)-1]
|
||||
exist, err = dao.UserReadHistory.Ctx(ctx).TX(tx).
|
||||
Where(dao.UserReadHistory.Columns().UserId, in.UserId).
|
||||
Where(dao.UserReadHistory.Columns().BookId, in.BookId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("history_query_failed")
|
||||
}
|
||||
|
||||
if exist {
|
||||
// 更新现有历史记录
|
||||
_, err = dao.UserReadHistory.Ctx(ctx).TX(tx).
|
||||
Where(dao.UserReadHistory.Columns().UserId, in.UserId).
|
||||
Where(dao.UserReadHistory.Columns().BookId, in.BookId).
|
||||
Data(do.UserReadHistory{
|
||||
ChapterId: lastChapter.ChapterId,
|
||||
ReadAt: gtime.Now(),
|
||||
}).Update()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("history_update_failed")
|
||||
}
|
||||
} else {
|
||||
// 创建新历史记录
|
||||
_, err = dao.UserReadHistory.Ctx(ctx).TX(tx).Data(do.UserReadHistory{
|
||||
UserId: in.UserId,
|
||||
BookId: in.BookId,
|
||||
ChapterId: lastChapter.ChapterId,
|
||||
ReadAt: gtime.Now(),
|
||||
}).Insert()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("history_create_failed")
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 更新书架记录(如果存在)
|
||||
exist, err = dao.Bookshelves.Ctx(ctx).TX(tx).
|
||||
Where(dao.Bookshelves.Columns().UserId, in.UserId).
|
||||
Where(dao.Bookshelves.Columns().BookId, in.BookId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("bookshelf_query_failed")
|
||||
}
|
||||
|
||||
if exist {
|
||||
// 计算阅读进度百分比
|
||||
totalChapters, err := dao.Chapters.Ctx(ctx).TX(tx).
|
||||
Where(dao.Chapters.Columns().BookId, in.BookId).
|
||||
Count()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("chapter_count_failed")
|
||||
}
|
||||
|
||||
var readChapters int
|
||||
if totalChapters > 0 {
|
||||
readChapters, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
|
||||
Where(dao.UserReadRecords.Columns().UserId, in.UserId).
|
||||
Where(dao.UserReadRecords.Columns().BookId, in.BookId).
|
||||
WhereGT(dao.UserReadRecords.Columns().ChapterId, 0).
|
||||
Count()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("read_chapter_count_failed")
|
||||
}
|
||||
}
|
||||
|
||||
readPercent := 0.0
|
||||
if totalChapters > 0 {
|
||||
readPercent = float64(readChapters) / float64(totalChapters) * 100
|
||||
if readPercent > 100 {
|
||||
readPercent = 100
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为最后一章
|
||||
lastChapterInfo, err := dao.Chapters.Ctx(ctx).TX(tx).
|
||||
Where(dao.Chapters.Columns().BookId, in.BookId).
|
||||
OrderDesc(dao.Chapters.Columns().Sort).
|
||||
One()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("chapter_query_failed")
|
||||
}
|
||||
|
||||
readStatus := 1 // 默认为正在读
|
||||
if lastChapterInfo != nil && lastChapterInfo["id"].Int64() == lastChapter.ChapterId {
|
||||
readStatus = 2 // 如果是最后一章,标记为已读完
|
||||
}
|
||||
|
||||
// 更新书架记录
|
||||
_, err = dao.Bookshelves.Ctx(ctx).TX(tx).
|
||||
Where(dao.Bookshelves.Columns().UserId, in.UserId).
|
||||
Where(dao.Bookshelves.Columns().BookId, in.BookId).
|
||||
Data(do.Bookshelves{
|
||||
LastReadChapterId: lastChapter.ChapterId,
|
||||
LastReadPercent: readPercent,
|
||||
LastReadAt: gtime.Now(),
|
||||
ReadStatus: readStatus,
|
||||
}).Update()
|
||||
if err != nil {
|
||||
return ecode.Fail.Sub("bookshelf_update_failed")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.Success = true
|
||||
return out, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user