From 388089d2a1799c2b2ef7c17357dc7c5b19d8f26f Mon Sep 17 00:00:00 2001 From: shinya Date: Thu, 28 May 2026 13:50:03 +0800 Subject: [PATCH] release 100.1.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复首页热门数据在番剧接口失败时一并空白:改为 Promise.allSettled - 番剧日历改走服务端代理 /api/bangumi/calendar,规避 bgm.tv CORS Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG | 7 +++++ VERSION.txt | 2 +- src/app/api/bangumi/calendar/route.ts | 43 +++++++++++++++++++++++++++ src/app/page.tsx | 34 ++++++++++++++------- src/lib/bangumi.client.ts | 5 +++- src/lib/changelog.ts | 14 +++++++++ src/lib/version.ts | 2 +- 7 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 src/app/api/bangumi/calendar/route.ts diff --git a/CHANGELOG b/CHANGELOG index 0379c4f..7d4ef9a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +## [100.1.3] - 2026-05-28 + +### Fixed + +- 修复首页热门电影、热门剧集、热门综艺在番剧接口失败时一并空白的问题 +- 番剧日历改为通过服务端代理请求,规避 bgm.tv 的 CORS 限制 + ## [100.1.2] - 2026-03-15 ### Changed diff --git a/VERSION.txt b/VERSION.txt index 840071c..9bd6dd2 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -100.1.2 \ No newline at end of file +100.1.3 diff --git a/src/app/api/bangumi/calendar/route.ts b/src/app/api/bangumi/calendar/route.ts new file mode 100644 index 0000000..9d6a83f --- /dev/null +++ b/src/app/api/bangumi/calendar/route.ts @@ -0,0 +1,43 @@ +import { NextResponse } from 'next/server'; + +import { getCacheTime } from '@/lib/config'; + +export const runtime = 'nodejs'; + +export async function GET() { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); + + try { + const response = await fetch('https://api.bgm.tv/calendar', { + signal: controller.signal, + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', + Accept: 'application/json', + }, + }); + clearTimeout(timeoutId); + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + + const data = await response.json(); + const cacheTime = await getCacheTime(); + + return NextResponse.json(data, { + headers: { + 'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`, + 'CDN-Cache-Control': `public, s-maxage=${cacheTime}`, + 'Vercel-CDN-Cache-Control': `public, s-maxage=${cacheTime}`, + }, + }); + } catch (error) { + clearTimeout(timeoutId); + return NextResponse.json( + { error: '获取番剧日历失败', details: (error as Error).message }, + { status: 500 } + ); + } +} diff --git a/src/app/page.tsx b/src/app/page.tsx index f364e69..b4dfaab 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -72,9 +72,10 @@ function HomeClient() { try { setLoading(true); - // 并行获取热门电影、热门剧集和热门综艺 - const [moviesData, tvShowsData, varietyShowsData, bangumiCalendarData] = - await Promise.all([ + // 并行获取热门电影、热门剧集、热门综艺和番剧日历 + // 使用 allSettled 避免单个请求失败导致全部数据为空 + const [moviesRes, tvShowsRes, varietyShowsRes, bangumiRes] = + await Promise.allSettled([ getDoubanCategories({ kind: 'movie', category: '热门', @@ -85,19 +86,32 @@ function HomeClient() { GetBangumiCalendarData(), ]); - if (moviesData.code === 200) { - setHotMovies(moviesData.list); + if (moviesRes.status === 'fulfilled' && moviesRes.value.code === 200) { + setHotMovies(moviesRes.value.list); + } else if (moviesRes.status === 'rejected') { + console.error('获取热门电影失败:', moviesRes.reason); } - if (tvShowsData.code === 200) { - setHotTvShows(tvShowsData.list); + if (tvShowsRes.status === 'fulfilled' && tvShowsRes.value.code === 200) { + setHotTvShows(tvShowsRes.value.list); + } else if (tvShowsRes.status === 'rejected') { + console.error('获取热门剧集失败:', tvShowsRes.reason); } - if (varietyShowsData.code === 200) { - setHotVarietyShows(varietyShowsData.list); + if ( + varietyShowsRes.status === 'fulfilled' && + varietyShowsRes.value.code === 200 + ) { + setHotVarietyShows(varietyShowsRes.value.list); + } else if (varietyShowsRes.status === 'rejected') { + console.error('获取热门综艺失败:', varietyShowsRes.reason); } - setBangumiCalendarData(bangumiCalendarData); + if (bangumiRes.status === 'fulfilled') { + setBangumiCalendarData(bangumiRes.value); + } else { + console.error('获取番剧日历失败:', bangumiRes.reason); + } } catch (error) { console.error('获取推荐数据失败:', error); } finally { diff --git a/src/lib/bangumi.client.ts b/src/lib/bangumi.client.ts index 8f56953..554bd50 100644 --- a/src/lib/bangumi.client.ts +++ b/src/lib/bangumi.client.ts @@ -23,7 +23,10 @@ export interface BangumiCalendarData { } export async function GetBangumiCalendarData(): Promise { - const response = await fetch('https://api.bgm.tv/calendar'); + const response = await fetch('/api/bangumi/calendar'); + if (!response.ok) { + throw new Error(`获取番剧日历失败: HTTP ${response.status}`); + } const data = await response.json(); const filteredData = data.map((item: BangumiCalendarData) => ({ ...item, diff --git a/src/lib/changelog.ts b/src/lib/changelog.ts index 7a55b57..e2dff64 100644 --- a/src/lib/changelog.ts +++ b/src/lib/changelog.ts @@ -10,6 +10,20 @@ export interface ChangelogEntry { } export const changelog: ChangelogEntry[] = [ + { + version: "100.1.3", + date: "2026-05-28", + added: [ + // 无新增内容 + ], + changed: [ + // 无变更内容 + ], + fixed: [ + "修复首页热门电影、热门剧集、热门综艺在番剧接口失败时一并空白的问题", + "番剧日历改为通过服务端代理请求,规避 bgm.tv 的 CORS 限制" + ] + }, { version: "100.1.2", date: "2026-03-15", diff --git a/src/lib/version.ts b/src/lib/version.ts index b4962f9..94fa30c 100644 --- a/src/lib/version.ts +++ b/src/lib/version.ts @@ -1,6 +1,6 @@ /* eslint-disable no-console */ -const CURRENT_VERSION = '100.1.2'; +const CURRENT_VERSION = '100.1.3'; // 导出当前版本号供其他地方使用 export { CURRENT_VERSION };