merge: 修复弹窗队列的 id 空间冲突
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,7 @@ function playNext() {
|
||||
visible.value = true
|
||||
timer = setTimeout(async () => {
|
||||
visible.value = false
|
||||
await store.markRead(item.id)
|
||||
await store.markRead(item)
|
||||
gapTimer = setTimeout(playNext, 400)
|
||||
}, 3000)
|
||||
}
|
||||
@@ -49,7 +49,9 @@ onUnmounted(() => {
|
||||
>
|
||||
<div class="icon">{{ current.icon }}</div>
|
||||
<div class="body">
|
||||
<div class="label">成就解锁</div>
|
||||
<div class="label">
|
||||
{{ current.kind === "badge" ? "获得奖章" : "成就解锁" }}
|
||||
</div>
|
||||
<div class="name">{{ current.name }}</div>
|
||||
<div class="desc">{{ current.description }}</div>
|
||||
</div>
|
||||
|
||||
@@ -18,14 +18,20 @@ export const useAchievementStore = defineStore("achievement", () => {
|
||||
const queue = ref<PendingAchievement[]>([])
|
||||
const current = ref<PendingAchievement | null>(null)
|
||||
|
||||
// 成就和题单奖章的 id 来自两张不同的表,数值会重叠,
|
||||
// 只按 id 去重会让奖章 5 把成就 5 挤掉
|
||||
function keyOf(item: PendingAchievement) {
|
||||
return `${item.kind ?? "achievement"}:${item.id}`
|
||||
}
|
||||
|
||||
function enqueue(items: PendingAchievement[]) {
|
||||
if (!items?.length) return
|
||||
// 去重:WebSocket 推来的和 pending 拉来的可能是同一批
|
||||
const known = new Set([
|
||||
...queue.value.map((i) => i.id),
|
||||
...(current.value ? [current.value.id] : []),
|
||||
...queue.value.map(keyOf),
|
||||
...(current.value ? [keyOf(current.value)] : []),
|
||||
])
|
||||
queue.value.push(...items.filter((i) => !known.has(i.id)))
|
||||
queue.value.push(...items.filter((i) => !known.has(keyOf(i))))
|
||||
}
|
||||
|
||||
async function fetchPending() {
|
||||
@@ -43,9 +49,12 @@ export const useAchievementStore = defineStore("achievement", () => {
|
||||
return current.value
|
||||
}
|
||||
|
||||
async function markRead(id: number) {
|
||||
async function markRead(item: PendingAchievement) {
|
||||
// 奖章不在 UserAchievement 表里,它的 id 传给标记接口会被当成成就 id,
|
||||
// 把一个恰好同号、还没弹过的成就静默标记为已弹——那个奖杯就再也不会出现
|
||||
if (item.kind === "badge") return
|
||||
try {
|
||||
await markAchievementsRead([id])
|
||||
await markAchievementsRead([item.id])
|
||||
} catch {
|
||||
// 标记失败下次会重复弹一次,可接受
|
||||
}
|
||||
|
||||
@@ -759,6 +759,10 @@ export interface PendingAchievement {
|
||||
description: string
|
||||
icon: string
|
||||
rarity: AchievementRarity
|
||||
// 弹窗队列里混着两种东西:全站成就和题单奖章。它们的 id 来自两张不同的表,
|
||||
// 数值会重叠,所以去重和标记已读都必须带上 kind 一起判断。
|
||||
// pending 接口只返回成就,不带这个字段,缺省按 achievement 处理。
|
||||
kind?: "achievement" | "badge"
|
||||
}
|
||||
|
||||
export interface AchievementSummary {
|
||||
|
||||
Reference in New Issue
Block a user