feat(viewer): waterfall feed with lazy load, filter and new-photo hint
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ApiError, NETWORK_ERROR_CODE, getPublicAlbum, type PublicAlbum } from '../api/client';
|
||||
import { errorMessageKey } from '../api/errors';
|
||||
import PhotoFeed from '../components/PhotoFeed.vue';
|
||||
|
||||
// 观众活动页(P1b Task 6):信息区 + 空态 + 时区展示;瀑布流(Task 7)与大图
|
||||
// (Task 8,复用本组件于 /a/:token/p/:photoId 深链)随后补充。
|
||||
@@ -92,6 +93,14 @@ const venueText = computed(() => {
|
||||
.filter((part): part is string => part !== null)
|
||||
.join(' · ');
|
||||
});
|
||||
|
||||
// 分类筛选(Task 7):id 级持有(语言切换只换名称,选中态跨语言保留——
|
||||
// PhotoFeed 收到同一 category 值不重置,locale 变化才整表重取)。
|
||||
const selectedCategory = ref<string | null>(null);
|
||||
|
||||
function selectCategory(categoryId: string | null): void {
|
||||
selectedCategory.value = categoryId;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -127,17 +136,32 @@ const venueText = computed(() => {
|
||||
</dl>
|
||||
</header>
|
||||
|
||||
<!-- Task 7 接线分类过滤;当前仅展示(禁用态占位)。 -->
|
||||
<!-- 分类筛选 chips:全部 + 各分类;选中态高亮(aria-pressed)。 -->
|
||||
<nav v-if="album.categories.length > 0" class="categories" :aria-label="t('album.categories')">
|
||||
<button v-for="category in album.categories" :key="category.id" type="button" class="chip" disabled>
|
||||
<button
|
||||
type="button"
|
||||
class="chip"
|
||||
:class="{ active: selectedCategory === null }"
|
||||
:aria-pressed="selectedCategory === null"
|
||||
@click="selectCategory(null)"
|
||||
>
|
||||
{{ t('album.all') }}
|
||||
</button>
|
||||
<button
|
||||
v-for="category in album.categories"
|
||||
:key="category.id"
|
||||
type="button"
|
||||
class="chip"
|
||||
:class="{ active: selectedCategory === category.id }"
|
||||
:aria-pressed="selectedCategory === category.id"
|
||||
@click="selectCategory(category.id)"
|
||||
>
|
||||
{{ category.name }}
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<!-- 瀑布流(Task 7)前的列表占位:空态文案由 i18n 提供。 -->
|
||||
<div class="feed">
|
||||
<p class="empty-notice">{{ t('album.emptyNotice') }}</p>
|
||||
</div>
|
||||
<!-- 瀑布流(Task 7):懒加载/无限滚动/轮询提示在 PhotoFeed 内实现。 -->
|
||||
<PhotoFeed :token="token" :locale="locale" :category="selectedCategory" />
|
||||
<!-- viewCount 契约占位 null:不渲染任何浏览计数节点。 -->
|
||||
</template>
|
||||
</section>
|
||||
@@ -207,18 +231,11 @@ const venueText = computed(() => {
|
||||
color: #374151;
|
||||
padding: 2px 12px;
|
||||
font-size: 0.875rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.chip:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
.feed {
|
||||
border: 1px dashed #e5e7eb;
|
||||
border-radius: 8px;
|
||||
padding: 48px 16px;
|
||||
text-align: center;
|
||||
}
|
||||
.empty-notice {
|
||||
margin: 0;
|
||||
color: #9ca3af;
|
||||
.chip.active {
|
||||
border-color: #1d4ed8;
|
||||
background: #eff6ff;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user