fix(playback): 恢复已删除的观看进度
This commit is contained in:
1 parent
5a80e6693f
commit
9c25b1b397
4 files changed
+111
-20
No files matched your search
+26
@@ -4,6 +4,32 @@ package com.fruitshorts.playback.dal.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fruitshorts.playback.dal.entity.WatchProgress;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
public interface WatchProgressMapper extends BaseMapper<WatchProgress> {
|
||||
|
||||
/** 含逻辑删除行。唯一索引不区分 deleted,再看同一部剧必须能找回旧行。 */
|
||||
@Select("""
|
||||
SELECT * FROM watch_progress
|
||||
WHERE user_id = #{userId} AND drama_id = #{dramaId}
|
||||
LIMIT 1
|
||||
""")
|
||||
WatchProgress selectAny(@Param("userId") Long userId, @Param("dramaId") Long dramaId);
|
||||
|
||||
/** 恢复并更新。手写 SQL 不带 deleted=0 条件,逻辑删除行也能写回。 */
|
||||
@Update("""
|
||||
UPDATE watch_progress SET
|
||||
deleted = 0,
|
||||
episode_id = #{episodeId},
|
||||
position_ms = #{positionMs},
|
||||
duration_ms = #{durationMs},
|
||||
finished = #{finished},
|
||||
play_count = #{playCount},
|
||||
device_id = #{deviceId},
|
||||
source = #{source}
|
||||
WHERE id = #{id}
|
||||
""")
|
||||
int updateAny(WatchProgress progress);
|
||||
}
|
||||
+57
-20
@@ -17,6 +17,7 @@ import com.fruitshorts.playback.dal.mapper.WatchProgressMapper;
|
||||
import com.fruitshorts.playback.vo.ProgressRespVO;
|
||||
import com.fruitshorts.playback.vo.ProgressSaveReqVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -58,30 +59,23 @@ public class WatchProgressService {
|
||||
boolean finished = Boolean.TRUE.equals(req.getFinished())
|
||||
|| (duration > 0 && position + FINISH_THRESHOLD_MS >= duration);
|
||||
|
||||
WatchProgress existing = progressMapper.selectOne(Wrappers.<WatchProgress>lambdaQuery()
|
||||
.eq(WatchProgress::getUserId, userId)
|
||||
.eq(WatchProgress::getDramaId, drama.getId())
|
||||
.last("limit 1"));
|
||||
if (existing == null) {
|
||||
WatchProgress progress = new WatchProgress();
|
||||
progress.setUserId(userId);
|
||||
progress.setDramaId(drama.getId());
|
||||
progress.setEpisodeId(episode.getId());
|
||||
progress.setPositionMs(position);
|
||||
progress.setDurationMs(duration);
|
||||
progress.setFinished(finished ? 1 : 0);
|
||||
progress.setPlayCount(1);
|
||||
progress.setDeviceId(req.getDeviceId() == null ? "" : req.getDeviceId());
|
||||
progress.setSource(req.getSource() == null ? "" : req.getSource());
|
||||
progressMapper.insert(progress);
|
||||
LoadedProgress loaded = loadForSave(userId, drama.getId(), episode, position, duration,
|
||||
finished, req);
|
||||
WatchProgress existing = loaded.progress();
|
||||
if (loaded.created()) {
|
||||
appendHistory(userId, drama.getId(), episode.getId(), position, duration,
|
||||
progress.getSource(), progress.getDeviceId());
|
||||
// updated_at 由触发器维护,回读一次,保证响应与后续 recent 列表口径一致
|
||||
return toResp(progressMapper.selectById(progress.getId()));
|
||||
existing.getSource(), existing.getDeviceId());
|
||||
return toResp(progressMapper.selectById(existing.getId()));
|
||||
}
|
||||
|
||||
boolean hidden = existing.getDeleted() != null && existing.getDeleted() != 0;
|
||||
boolean sameEpisode = existing.getEpisodeId() != null
|
||||
&& existing.getEpisodeId().equals(episode.getId());
|
||||
if (hidden && sameEpisode) {
|
||||
existing.setPlayCount((existing.getPlayCount() == null ? 0 : existing.getPlayCount()) + 1);
|
||||
appendHistory(userId, drama.getId(), episode.getId(), position, duration,
|
||||
req.getSource(), existing.getDeviceId());
|
||||
}
|
||||
if (!sameEpisode) {
|
||||
// 换集:直接采纳新集与新的播放位置
|
||||
existing.setEpisodeId(episode.getId());
|
||||
@@ -103,10 +97,52 @@ public class WatchProgressService {
|
||||
}
|
||||
existing.setDeviceId(req.getDeviceId() == null ? "" : req.getDeviceId());
|
||||
existing.setSource(req.getSource() == null ? "" : req.getSource());
|
||||
progressMapper.updateById(existing);
|
||||
if (hidden) {
|
||||
existing.setDeleted(0);
|
||||
progressMapper.updateAny(existing);
|
||||
} else {
|
||||
progressMapper.updateById(existing);
|
||||
}
|
||||
return toResp(progressMapper.selectById(existing.getId()));
|
||||
}
|
||||
|
||||
private LoadedProgress loadForSave(Long userId, Long dramaId, DramaEpisode episode, long position,
|
||||
long duration, boolean finished, ProgressSaveReqVO req) {
|
||||
WatchProgress existing = progressMapper.selectAny(userId, dramaId);
|
||||
if (existing != null) {
|
||||
return new LoadedProgress(existing, false);
|
||||
}
|
||||
WatchProgress created = newProgress(userId, dramaId, episode, position, duration, finished, req);
|
||||
try {
|
||||
progressMapper.insert(created);
|
||||
return new LoadedProgress(created, true);
|
||||
} catch (DuplicateKeyException ex) {
|
||||
WatchProgress raced = progressMapper.selectAny(userId, dramaId);
|
||||
if (raced == null) {
|
||||
throw ex;
|
||||
}
|
||||
return new LoadedProgress(raced, false);
|
||||
}
|
||||
}
|
||||
|
||||
private WatchProgress newProgress(Long userId, Long dramaId, DramaEpisode episode, long position,
|
||||
long duration, boolean finished, ProgressSaveReqVO req) {
|
||||
WatchProgress progress = new WatchProgress();
|
||||
progress.setUserId(userId);
|
||||
progress.setDramaId(dramaId);
|
||||
progress.setEpisodeId(episode.getId());
|
||||
progress.setPositionMs(position);
|
||||
progress.setDurationMs(duration);
|
||||
progress.setFinished(finished ? 1 : 0);
|
||||
progress.setPlayCount(1);
|
||||
progress.setDeviceId(req.getDeviceId() == null ? "" : req.getDeviceId());
|
||||
progress.setSource(req.getSource() == null ? "" : req.getSource());
|
||||
return progress;
|
||||
}
|
||||
|
||||
private record LoadedProgress(WatchProgress progress, boolean created) {
|
||||
}
|
||||
|
||||
public ProgressRespVO ofDrama(Long userId, Long dramaId) {
|
||||
WatchProgress progress = progressMapper.selectOne(Wrappers.<WatchProgress>lambdaQuery()
|
||||
.eq(WatchProgress::getUserId, userId)
|
||||
@@ -185,6 +221,7 @@ public class WatchProgressService {
|
||||
vo.setDramaTitle(drama.getTitle());
|
||||
vo.setDramaCover(drama.getCoverUrl());
|
||||
vo.setTotalEpisodes(drama.getTotalEpisodes());
|
||||
vo.setViewCount(drama.getViewCount());
|
||||
}
|
||||
DramaEpisode episode = episodeById.get(progress.getEpisodeId());
|
||||
if (episode != null) {
|
||||
|
||||
+2
@@ -20,6 +20,8 @@ public class ProgressRespVO {
|
||||
private Integer episodeNumber;
|
||||
/** 短剧总集数;短剧不存在时为空。 */
|
||||
private Integer totalEpisodes;
|
||||
/** 短剧热度,取 drama.view_count。不是用户自己的播放次数。 */
|
||||
private Long viewCount;
|
||||
private Long positionMs;
|
||||
private Long durationMs;
|
||||
private Boolean finished;
|
||||
|
||||
Reference in new issue
Block a user