fix(feed): 把 wrapper 嵌入 NCard 内部底部,真正紧贴对应卡片
This commit is contained in:
@@ -44,17 +44,12 @@ let categoryPromptTimer: number | null = null
|
|||||||
// - items 没这条 → 不渲染(孤儿)
|
// - items 没这条 → 不渲染(孤儿)
|
||||||
// - items 有 + Map 也有 → 渲染
|
// - items 有 + Map 也有 → 渲染
|
||||||
// - items 有 + Map 没 → 不渲染(用户已 dismiss/确认/超时)
|
// - items 有 + Map 没 → 不渲染(用户已 dismiss/确认/超时)
|
||||||
const articlesWithPrompts = computed(() => {
|
const articlesWithPrompts = computed(() =>
|
||||||
const r = items.value.filter((a) => (categoryPromptsByArticle.value.get(a.id)?.length ?? 0) > 0)
|
items.value.filter((a) => (categoryPromptsByArticle.value.get(a.id)?.length ?? 0) > 0)
|
||||||
// eslint-disable-next-line no-console
|
)
|
||||||
console.log('[AWP] resultLen=', r.length, 'itemsLen=', items.value.length, 'mapSize=', categoryPromptsByArticle.value.size)
|
|
||||||
return r
|
|
||||||
})
|
|
||||||
|
|
||||||
// 移除某篇文章的所有提示条(8 秒超时 / 确认后 / 过滤变化)
|
// 移除某篇文章的所有提示条(8 秒超时 / 确认后 / 过滤变化)
|
||||||
function clearPromptsForArticle(articleId: number) {
|
function clearPromptsForArticle(articleId: number) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('[CLEAR_ONE]', articleId, 'stack:', new Error().stack?.split('\n').slice(2, 5).join(' | '))
|
|
||||||
if (categoryPromptsByArticle.value.has(articleId)) {
|
if (categoryPromptsByArticle.value.has(articleId)) {
|
||||||
const next = new Map(categoryPromptsByArticle.value)
|
const next = new Map(categoryPromptsByArticle.value)
|
||||||
next.delete(articleId)
|
next.delete(articleId)
|
||||||
@@ -64,8 +59,6 @@ function clearPromptsForArticle(articleId: number) {
|
|||||||
|
|
||||||
// 全清
|
// 全清
|
||||||
function clearAllPrompts() {
|
function clearAllPrompts() {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('[CLEAR_ALL] size=', categoryPromptsByArticle.value.size, 'stack:', new Error().stack?.split('\n').slice(2, 5).join(' | '))
|
|
||||||
if (categoryPromptsByArticle.value.size > 0) {
|
if (categoryPromptsByArticle.value.size > 0) {
|
||||||
categoryPromptsByArticle.value = new Map()
|
categoryPromptsByArticle.value = new Map()
|
||||||
}
|
}
|
||||||
@@ -693,58 +686,57 @@ onMounted(async () => {
|
|||||||
{{ a.is_read ? '已读' : '标为已读' }}
|
{{ a.is_read ? '已读' : '标为已读' }}
|
||||||
</NButton>
|
</NButton>
|
||||||
</div>
|
</div>
|
||||||
|
<!--
|
||||||
|
分类提示条(per-article,紧贴卡片底部):
|
||||||
|
- 嵌在 NCard 内部,确保 DOM 位置紧贴对应卡片
|
||||||
|
- 只有当该 article 在 categoryPromptsByArticle Map 里有值时才渲染
|
||||||
|
- 8s 后 Map 删掉 → wrapper 走 leave 动画
|
||||||
|
- 内部 NAlert v-for 用 ${a.id}-${category} 作为 key,确保多个 category 时各自独立
|
||||||
|
-->
|
||||||
|
<div
|
||||||
|
v-if="(categoryPromptsByArticle.get(a.id)?.length ?? 0) > 0"
|
||||||
|
: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}`"
|
||||||
|
type="success"
|
||||||
|
:show-icon="false"
|
||||||
|
closable
|
||||||
|
@close="dismissPrompt(a.id, p.category)"
|
||||||
|
class="feed-category-prompt"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<NSpace align="center" :size="8" :wrap="true">
|
||||||
|
<NText>「{{ p.category }}」分类下还有 {{ p.unreadCount }} 条 24 小时未读</NText>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
<NSpace :size="8" style="margin-top: 8px">
|
||||||
|
<NButton
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
round
|
||||||
|
:loading="pendingCategory === p.category"
|
||||||
|
:disabled="pendingCategory !== null"
|
||||||
|
@click="confirmMarkCategory(a.id, p.category)"
|
||||||
|
>
|
||||||
|
全部已读
|
||||||
|
</NButton>
|
||||||
|
<NButton size="small" round @click="dismissPrompt(a.id, p.category)">
|
||||||
|
稍后再说
|
||||||
|
</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</NAlert>
|
||||||
|
</div>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NCard>
|
</NCard>
|
||||||
<!--
|
|
||||||
该文章对应的分类提示条(per-article 挂载,卡片**下方**):
|
|
||||||
- 用 articlesWithPrompts(过滤后只有有提示条的 article)做 v-for
|
|
||||||
- 跟 NCard 在同一个 TransitionGroup,但 hide_read 模式不再 splice 移除文章,
|
|
||||||
所以 NCard 不会触发 leave 动画,wrapper 不会被卷走
|
|
||||||
- 8s 后 Map 删掉 → wrapper 走自己的 leave 动画(只影响 wrapper,不影响 NCard)
|
|
||||||
- 内部 NAlert v-for 用 ${a.id}-${category} 作为 key,确保多个 category 时各自独立
|
|
||||||
-->
|
|
||||||
<div
|
|
||||||
v-for="a in articlesWithPrompts"
|
|
||||||
: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}`"
|
|
||||||
type="success"
|
|
||||||
:show-icon="false"
|
|
||||||
closable
|
|
||||||
@close="dismissPrompt(a.id, p.category)"
|
|
||||||
class="feed-category-prompt"
|
|
||||||
>
|
|
||||||
<template #header>
|
|
||||||
<NSpace align="center" :size="8" :wrap="true">
|
|
||||||
<NText>「{{ p.category }}」分类下还有 {{ p.unreadCount }} 条 24 小时未读</NText>
|
|
||||||
</NSpace>
|
|
||||||
</template>
|
|
||||||
<NSpace :size="8" style="margin-top: 8px">
|
|
||||||
<NButton
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
round
|
|
||||||
:loading="pendingCategory === p.category"
|
|
||||||
:disabled="pendingCategory !== null"
|
|
||||||
@click="confirmMarkCategory(a.id, p.category)"
|
|
||||||
>
|
|
||||||
全部已读
|
|
||||||
</NButton>
|
|
||||||
<NButton size="small" round @click="dismissPrompt(a.id, p.category)">
|
|
||||||
稍后再说
|
|
||||||
</NButton>
|
|
||||||
</NSpace>
|
|
||||||
</NAlert>
|
|
||||||
</div>
|
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
|
|
||||||
<!-- 页码分页 -->
|
<!-- 页码分页 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user