refactor(frontend): Rework home and video detail interactions

This commit is contained in:
2026-04-24 17:35:13 +08:00
parent 833dd3451a
commit 59af57c0fa
38 changed files with 2693 additions and 986 deletions
@@ -11,7 +11,7 @@
</button>
<div>
<strong>{{ favoriteTitle }}</strong>
<span>{{ total }} 个视频</span>
<span>{{ displayTotal }} 个视频</span>
</div>
</div>
<div class="head-actions">
@@ -101,10 +101,12 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { showConfirmDialog, showSuccessToast, showToast } from 'vant'
import { showConfirmDialog } from 'vant'
import { showSuccessToast, showToast } from '@/utils/toast'
import VideoCard from '@/components/video/VideoCard.vue'
import { favoriteApi, type Favorite } from '@/api/favorite.ts'
import { videoApi } from '@/api/video.ts'
import { userApi } from '@/api/user.ts'
import type { VideoInfo } from '@/types'
const route = useRoute()
@@ -113,6 +115,7 @@ const favoriteId = computed(() => Number(route.params.id))
const currentFavorite = ref<Favorite | null>(null)
const favoriteTitle = computed(() => currentFavorite.value?.name || '收藏夹')
const videos = ref<VideoInfo[]>([])
const displayTotal = computed(() => Math.max(total.value, videos.value.length))
const loading = ref(false)
const finished = ref(false)
const page = ref(1)
@@ -126,6 +129,43 @@ const editForm = ref({
isPrivate: 0
})
const hydrateVideoAuthors = async (items: VideoInfo[]) => {
const missingUserIds = [...new Set(
items
.filter((item) => item.userId && (!item.userNickname || !item.userAvatar))
.map((item) => item.userId)
)]
if (!missingUserIds.length) {
return items
}
const profiles = await Promise.all(
missingUserIds.map(async (userId) => {
try {
const profile = await userApi.getPublicProfile(userId)
return [userId, profile] as const
} catch {
return [userId, null] as const
}
})
)
const profileMap = new Map(profiles)
return items.map((item) => {
const profile = profileMap.get(item.userId)
if (!profile) {
return item
}
return {
...item,
userNickname: item.userNickname || profile.nickname,
userAvatar: item.userAvatar || profile.avatar
}
})
}
const loadFavoriteMeta = async () => {
try {
const favorites = await favoriteApi.getFavoriteList()
@@ -151,7 +191,8 @@ const loadMore = async () => {
pageNum: page.value,
pageSize: 12
})
videos.value.push(...res.records)
const hydratedRecords = await hydrateVideoAuthors(res.records)
videos.value.push(...hydratedRecords)
total.value = res.total
if (videos.value.length >= res.total || res.records.length < 12) finished.value = true
page.value += 1