Skip to content

Commit 9737c9d

Browse files
committed
feat(UserEpisodeWatch): implement user episode watch tracking with upsert and mark unwatched functionality
1 parent 0725e39 commit 9737c9d

3 files changed

Lines changed: 47 additions & 31 deletions

File tree

db/anime_flow.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,26 @@ CREATE TABLE `user_bgm_collection` (
267267
INDEX `idx_user_sync_time`(`user_id` ASC, `sync_time` ASC) USING BTREE
268268
) ENGINE = InnoDB AUTO_INCREMENT = 375 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户 Bangumi 收藏关系表' ROW_FORMAT = DYNAMIC;
269269

270+
-- ----------------------------
271+
-- Table structure for user_episode_watch
272+
-- ----------------------------
273+
DROP TABLE IF EXISTS `user_episode_watch`;
274+
CREATE TABLE `user_episode_watch` (
275+
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
276+
`user_id` bigint NOT NULL COMMENT '用户 ID',
277+
`subject_id` int UNSIGNED NOT NULL COMMENT '作品 ID,冗余自 bangumi_episode.subject_id,便于按作品查',
278+
`episode_id` int UNSIGNED NOT NULL COMMENT '章节 ID',
279+
`watch_status` tinyint NOT NULL DEFAULT 1 COMMENT '0未看 1已看,可为将来扩展预留',
280+
`watched_at` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '首次标记已看时间',
281+
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
282+
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
283+
PRIMARY KEY (`id`) USING BTREE,
284+
UNIQUE INDEX `uk_user_episode`(`user_id` ASC, `episode_id` ASC) USING BTREE,
285+
INDEX `idx_user_subject`(`user_id` ASC, `subject_id` ASC) USING BTREE,
286+
INDEX `idx_subject_episode`(`subject_id` ASC, `episode_id` ASC) USING BTREE,
287+
INDEX `idx_user_subject_status`(`user_id` ASC, `subject_id` ASC, `watch_status` ASC) USING BTREE
288+
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户剧集观看记录' ROW_FORMAT = Dynamic;
289+
270290
-- ----------------------------
271291
-- Table structure for user_oauth
272292
-- ----------------------------

flow-client/src/main/java/com/ligg/flowclient/mapper/UserEpisodeWatchMapper.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,32 @@
22

33
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
44
import com.ligg.common.entity.UserEpisodeWatchEntity;
5+
import org.apache.ibatis.annotations.Insert;
56
import org.apache.ibatis.annotations.Mapper;
7+
import org.apache.ibatis.annotations.Param;
8+
import org.apache.ibatis.annotations.Update;
69

710
@Mapper
811
public interface UserEpisodeWatchMapper extends BaseMapper<UserEpisodeWatchEntity> {
12+
13+
@Insert("""
14+
insert into user_episode_watch (user_id, subject_id, episode_id, watch_status, watched_at)
15+
values (#{userId}, #{subjectId}, #{episodeId}, 1, current_timestamp)
16+
on duplicate key update
17+
subject_id = values(subject_id),
18+
watch_status = values(watch_status),
19+
watched_at = coalesce(watched_at, values(watched_at))
20+
""")
21+
int upsertWatched(@Param("userId") Long userId,
22+
@Param("subjectId") Integer subjectId,
23+
@Param("episodeId") Integer episodeId);
24+
25+
@Update("""
26+
update user_episode_watch
27+
set watch_status = 0
28+
where user_id = #{userId}
29+
and episode_id = #{episodeId}
30+
""")
31+
int markUnwatched(@Param("userId") Long userId,
32+
@Param("episodeId") Integer episodeId);
933
}

flow-client/src/main/java/com/ligg/flowclient/service/impl/UserEpisodeWatchServiceImpl.java

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import lombok.RequiredArgsConstructor;
1616
import org.springframework.stereotype.Service;
1717

18-
import java.time.LocalDateTime;
1918
import java.util.Collections;
2019
import java.util.LinkedHashSet;
2120
import java.util.List;
@@ -25,7 +24,6 @@
2524
@RequiredArgsConstructor
2625
public class UserEpisodeWatchServiceImpl implements UserEpisodeWatchService {
2726

28-
private static final int WATCH_STATUS_UNWATCHED = 0;
2927
private static final int WATCH_STATUS_WATCHED = 1;
3028
private static final int EPISODE_TYPE_MAIN = 0;
3129

@@ -42,17 +40,10 @@ public void updateEpisodeWatch(String accessToken, int episodeId, UpdateEpisodeW
4240
throw new IllegalArgumentException("剧集不存在");
4341
}
4442

45-
UserEpisodeWatchEntity existing = userEpisodeWatchMapper.selectOne(
46-
new LambdaQueryWrapper<UserEpisodeWatchEntity>()
47-
.eq(UserEpisodeWatchEntity::getUserId, userId)
48-
.eq(UserEpisodeWatchEntity::getEpisodeId, episodeId)
49-
.last("LIMIT 1"));
50-
5143
if (Boolean.TRUE.equals(dto.getWatched())) {
52-
upsertWatched(userId, episode, existing);
53-
} else if (existing != null) {
54-
existing.setWatchStatus(WATCH_STATUS_UNWATCHED);
55-
userEpisodeWatchMapper.updateById(existing);
44+
userEpisodeWatchMapper.upsertWatched(userId, episode.getSubjectId(), episode.getId());
45+
} else {
46+
userEpisodeWatchMapper.markUnwatched(userId, episodeId);
5647
}
5748

5849
refreshCollectionEpisodeProgress(userId, episode.getSubjectId());
@@ -84,25 +75,6 @@ public Set<Long> listWatchedEpisodeIds(long userId, int subjectId) {
8475
return watchedEpisodeIds;
8576
}
8677

87-
private void upsertWatched(Long userId, BangumiEpisodeEntity episode, UserEpisodeWatchEntity existing) {
88-
if (existing != null) {
89-
existing.setWatchStatus(WATCH_STATUS_WATCHED);
90-
if (existing.getWatchedAt() == null) {
91-
existing.setWatchedAt(LocalDateTime.now());
92-
}
93-
userEpisodeWatchMapper.updateById(existing);
94-
return;
95-
}
96-
97-
UserEpisodeWatchEntity row = new UserEpisodeWatchEntity();
98-
row.setUserId(userId);
99-
row.setSubjectId(episode.getSubjectId());
100-
row.setEpisodeId(episode.getId());
101-
row.setWatchStatus(WATCH_STATUS_WATCHED);
102-
row.setWatchedAt(LocalDateTime.now());
103-
userEpisodeWatchMapper.insert(row);
104-
}
105-
10678
/**
10779
* 维护 user_bgm_collection.ep_status,表示按正片顺序连续看完的话数。
10880
*/

0 commit comments

Comments
 (0)