feat(feed): 分类批量已读提示条加标题行

This commit is contained in:
xiaji
2026-06-16 07:48:16 +08:00
parent de4a88ce8b
commit cfb297ac39
2 changed files with 32 additions and 12 deletions

View File

@@ -192,13 +192,26 @@ async function toggleRead(a: ArticleListItem) {
} else {
await readsApi.mark(a.id)
}
// 标记为已读后,如果当前在 hide_read 模式,卡片要从列表里消失
// === 关键:先 await 提示条 fetch,再 splice ===
// 原因:hide_read 模式下,350ms 后 items.splice 会把 a 移除,wrapper 跟着走。
// 如果 category-count 比 350ms 慢,wrapper 还没渲染就被切走 → 用户看不到。
if (!wasRead && a.category) {
try {
const fetchPromise = maybePromptCategoryRead(a)
const timeout = new Promise<void>((resolve) => setTimeout(resolve, 1500))
await Promise.race([fetchPromise, timeout])
// eslint-disable-next-line no-console
console.debug('[category-prompt] mounted for article', a.id, 'cats=', categoryPromptsByArticle.value.get(a.id))
} catch {
// 静默失败
}
}
// hide_read 模式:卡片从列表里消失(用户预期行为)
if (!wasRead && hideRead.value) {
// 等 leave 动画跑完再从 items 数组里移除(TransitionGroup 才能触发动画)
const idx = items.value.findIndex((x) => x.id === a.id)
if (idx >= 0) {
// 触发 leave 动画:Vue 会保留 DOM 元素直到 transition 结束
// 但 splice(items, idx, 1) 会立即从 v-for 移除 → 用 markPending 标记 → 350ms 后再真正移除
pendingRemoval.value.add(a.id)
setTimeout(() => {
const i = items.value.findIndex((x) => x.id === a.id)
@@ -208,13 +221,6 @@ async function toggleRead(a: ArticleListItem) {
}, 360)
}
}
// === 新增:刚标为已读 → 查该文章前 2 个 category 的 24h 未读数 ===
// unmark 路径不触发(用户反悔了,不该再骚扰);hide_read 模式仍可触发
// (滑出动画只影响当前这一条,提示条展示的是"这个分类下还有别的未读")
if (!wasRead && a.category) {
await maybePromptCategoryRead(a)
}
} catch (e: any) {
// 失败回滚
a.is_read = wasRead
@@ -713,6 +719,12 @@ onMounted(async () => {
:key="`prompt-wrapper-${a.id}`"
class="feed-category-prompt-wrapper"
>
<!-- 标题行:标记已读的确认 + 1~2 条分类提示的容器 -->
<div class="feed-category-prompt-header">
<NSpace align="center" :size="8" :wrap="true">
<NTag type="success" size="small" round :bordered="false">✓ 已将《{{ a.title_zh || a.title }}》标记为已读</NTag>
</NSpace>
</div>
<NAlert
v-for="p in (categoryPromptsByArticle.get(a.id) || [])"
:key="`${a.id}-${p.category}`"
@@ -724,7 +736,6 @@ onMounted(async () => {
>
<template #header>
<NSpace align="center" :size="8" :wrap="true">
<NTag type="success" size="small" round :bordered="false">✓ 已读</NTag>
<NText>「{{ p.category }}」分类下还有 {{ p.unreadCount }} 条 24 小时未读</NText>
</NSpace>
</template>
@@ -1102,6 +1113,12 @@ onMounted(async () => {
flex-direction: column;
gap: 8px;
}
/* 标题行(标已读的确认) 跟下面的 NAlert 视觉分层 */
.feed-category-prompt-header {
padding: 6px 4px 0;
font-size: 13px;
color: var(--color-text-faint);
}
.feed-category-prompt {
background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 100%);
border-left: 3px solid var(--color-primary, #5b86e5);