mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-22 02:16:10 +08:00
fix: detail lack of title
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
|
||||
'use client';
|
||||
|
||||
import Image from 'next/image';
|
||||
@@ -17,6 +19,9 @@ function DetailPageClient() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [playRecord, setPlayRecord] = useState<PlayRecord | null>(null);
|
||||
|
||||
// 当接口缺失标题时,使用 URL 中的 title 参数作为后备
|
||||
const fallbackTitle = searchParams.get('title') || '';
|
||||
|
||||
// 格式化剩余时间(如 1h 50m)
|
||||
const formatDuration = (seconds: number) => {
|
||||
const h = Math.floor(seconds / 3600);
|
||||
@@ -45,7 +50,15 @@ function DetailPageClient() {
|
||||
throw new Error('获取详情失败');
|
||||
}
|
||||
const data = await response.json();
|
||||
setDetail(data);
|
||||
// 如果接口中缺失标题,则补上备用标题
|
||||
let finalData = data;
|
||||
if (!data?.videoInfo?.title && fallbackTitle) {
|
||||
finalData = {
|
||||
...data,
|
||||
videoInfo: { ...data.videoInfo, title: fallbackTitle },
|
||||
};
|
||||
}
|
||||
setDetail(finalData);
|
||||
|
||||
// 获取播放记录
|
||||
const allRecords = await getAllPlayRecords();
|
||||
@@ -117,7 +130,7 @@ function DetailPageClient() {
|
||||
<div className='flex-shrink-0 w-full md:w-72'>
|
||||
<Image
|
||||
src={detail.videoInfo.cover || '/images/placeholder.png'}
|
||||
alt={detail.videoInfo.title}
|
||||
alt={detail.videoInfo.title || fallbackTitle}
|
||||
width={288}
|
||||
height={432}
|
||||
className='w-full rounded-xl object-cover'
|
||||
@@ -131,7 +144,7 @@ function DetailPageClient() {
|
||||
style={{ height: '430px' }}
|
||||
>
|
||||
<h1 className='text-3xl font-bold mb-2 tracking-wide flex items-center flex-shrink-0'>
|
||||
{detail.videoInfo.title}
|
||||
{detail.videoInfo.title || fallbackTitle}
|
||||
</h1>
|
||||
<div className='flex flex-wrap items-center gap-3 text-base mb-4 opacity-80 flex-shrink-0'>
|
||||
{detail.videoInfo.remarks && (
|
||||
@@ -157,7 +170,11 @@ function DetailPageClient() {
|
||||
<a
|
||||
href={`/play?source=${searchParams.get(
|
||||
'source'
|
||||
)}&id=${searchParams.get('id')}`}
|
||||
)}&id=${searchParams.get('id')}${
|
||||
fallbackTitle
|
||||
? `&title=${encodeURIComponent(fallbackTitle)}`
|
||||
: ''
|
||||
}`}
|
||||
className='flex items-center justify-center gap-2 px-6 py-2 bg-green-500 hover:bg-green-600 rounded-lg transition-colors text-white'
|
||||
>
|
||||
<div className='w-0 h-0 border-t-[6px] border-t-transparent border-l-[10px] border-l-white border-b-[6px] border-b-transparent'></div>
|
||||
@@ -167,7 +184,11 @@ function DetailPageClient() {
|
||||
<a
|
||||
href={`/play?source=${searchParams.get(
|
||||
'source'
|
||||
)}&id=${searchParams.get('id')}&index=1&position=0`}
|
||||
)}&id=${searchParams.get('id')}&index=1&position=0${
|
||||
fallbackTitle
|
||||
? `&title=${encodeURIComponent(fallbackTitle)}`
|
||||
: ''
|
||||
}`}
|
||||
className='flex items-center justify-center gap-2 px-6 py-2 bg-gray-500 hover:bg-gray-600 rounded-lg transition-colors text-white'
|
||||
>
|
||||
<div className='w-0 h-0 border-t-[6px] border-t-transparent border-l-[10px] border-l-white border-b-[6px] border-b-transparent'></div>
|
||||
@@ -180,7 +201,11 @@ function DetailPageClient() {
|
||||
<a
|
||||
href={`/play?source=${searchParams.get(
|
||||
'source'
|
||||
)}&id=${searchParams.get('id')}&index=1&position=0`}
|
||||
)}&id=${searchParams.get('id')}&index=1&position=0${
|
||||
fallbackTitle
|
||||
? `&title=${encodeURIComponent(fallbackTitle)}`
|
||||
: ''
|
||||
}`}
|
||||
className='flex items-center justify-center gap-2 px-6 py-2 bg-green-500 hover:bg-green-600 rounded-lg transition-colors text-white'
|
||||
>
|
||||
<div className='w-0 h-0 border-t-[6px] border-t-transparent border-l-[10px] border-l-white border-b-[6px] border-b-transparent'></div>
|
||||
@@ -254,7 +279,11 @@ function DetailPageClient() {
|
||||
key={idx}
|
||||
href={`/play?source=${searchParams.get(
|
||||
'source'
|
||||
)}&id=${searchParams.get('id')}&index=${idx + 1}`}
|
||||
)}&id=${searchParams.get('id')}&index=${idx + 1}${
|
||||
fallbackTitle
|
||||
? `&title=${encodeURIComponent(fallbackTitle)}`
|
||||
: ''
|
||||
}`}
|
||||
className='bg-gray-500/80 hover:bg-green-500 text-white px-5 py-2 rounded-lg transition-colors text-base font-medium w-24 text-center'
|
||||
>
|
||||
第{idx + 1}集
|
||||
|
||||
@@ -42,8 +42,8 @@ function PlayPageClient() {
|
||||
// 使用 useState 保存视频详情
|
||||
const [detail, setDetail] = useState<VideoDetail | null>(null);
|
||||
|
||||
// 轻量级界面状态,仅用于显示
|
||||
const [videoTitle, setVideoTitle] = useState('');
|
||||
// 初始标题:如果 URL 中携带 title 参数,则优先使用
|
||||
const [videoTitle, setVideoTitle] = useState(searchParams.get('title') || '');
|
||||
const [videoCover, setVideoCover] = useState('');
|
||||
|
||||
const [currentSource, setCurrentSource] = useState(
|
||||
@@ -159,7 +159,7 @@ function PlayPageClient() {
|
||||
const data = await response.json();
|
||||
|
||||
// 更新状态保存详情
|
||||
setVideoTitle(data.videoInfo.title);
|
||||
setVideoTitle(data.videoInfo.title || videoTitle);
|
||||
setVideoCover(data.videoInfo.cover);
|
||||
setDetail(data);
|
||||
|
||||
@@ -740,7 +740,11 @@ function PlayPageClient() {
|
||||
};
|
||||
|
||||
// 处理换源
|
||||
const handleSourceChange = async (newSource: string, newId: string) => {
|
||||
const handleSourceChange = async (
|
||||
newSource: string,
|
||||
newId: string,
|
||||
newTitle: string
|
||||
) => {
|
||||
try {
|
||||
// 显示换源加载状态
|
||||
setSourceChanging(true);
|
||||
@@ -782,7 +786,7 @@ function PlayPageClient() {
|
||||
// 关闭换源面板
|
||||
setShowSourcePanel(false);
|
||||
|
||||
setVideoTitle(newDetail.videoInfo.title);
|
||||
setVideoTitle(newDetail.videoInfo.title || newTitle);
|
||||
setVideoCover(newDetail.videoInfo.cover);
|
||||
setCurrentSource(newSource);
|
||||
setCurrentId(newId);
|
||||
@@ -1293,7 +1297,11 @@ function PlayPageClient() {
|
||||
}`}
|
||||
onClick={() =>
|
||||
!isCurrentSource &&
|
||||
handleSourceChange(result.source, result.id)
|
||||
handleSourceChange(
|
||||
result.source,
|
||||
result.id,
|
||||
result.title
|
||||
)
|
||||
}
|
||||
>
|
||||
{/* 视频封面 */}
|
||||
|
||||
@@ -110,7 +110,9 @@ export default function VideoCard({
|
||||
|
||||
return deleted ? null : (
|
||||
<Link
|
||||
href={`/detail?source=${source}&id=${id}${from ? `&from=${from}` : ''}`}
|
||||
href={`/detail?source=${source}&id=${id}&title=${encodeURIComponent(
|
||||
title
|
||||
)}${from ? `&from=${from}` : ''}`}
|
||||
>
|
||||
<div className='group relative w-full rounded-lg bg-transparent shadow-none flex flex-col'>
|
||||
{/* 海报图片 - 2:3 比例 */}
|
||||
@@ -128,7 +130,11 @@ export default function VideoCard({
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
router.push(`/play?source=${source}&id=${id}`);
|
||||
router.push(
|
||||
`/play?source=${source}&id=${id}&title=${encodeURIComponent(
|
||||
title
|
||||
)}`
|
||||
);
|
||||
}}
|
||||
onMouseEnter={() => setPlayHover(true)}
|
||||
onMouseLeave={() => setPlayHover(false)}
|
||||
|
||||
Reference in New Issue
Block a user