diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 2a0e141..6acaa02 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -51,6 +51,7 @@ interface SiteConfig { SearchDownstreamMaxPage: number; SiteInterfaceCacheTime: number; ImageProxy: string; + DoubanProxy: string; } // 视频源数据类型 @@ -962,6 +963,7 @@ const SiteConfigComponent = ({ config }: { config: AdminConfig | null }) => { SearchDownstreamMaxPage: 1, SiteInterfaceCacheTime: 7200, ImageProxy: '', + DoubanProxy: '', }); // 保存状态 const [saving, setSaving] = useState(false); @@ -979,6 +981,7 @@ const SiteConfigComponent = ({ config }: { config: AdminConfig | null }) => { setSiteSettings({ ...config.SiteConfig, ImageProxy: config.SiteConfig.ImageProxy || '', + DoubanProxy: config.SiteConfig.DoubanProxy || '', }); } }, [config]); @@ -1172,6 +1175,39 @@ const SiteConfigComponent = ({ config }: { config: AdminConfig | null }) => {

+ {/* 豆瓣代理设置 */} +
+ + + !isD1Storage && + !isUpstashStorage && + setSiteSettings((prev) => ({ + ...prev, + DoubanProxy: e.target.value, + })) + } + disabled={isD1Storage || isUpstashStorage} + className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent ${ + isD1Storage || isUpstashStorage + ? 'opacity-50 cursor-not-allowed' + : '' + }`} + /> +

+ 用于代理豆瓣数据访问,解决跨域或访问限制问题。留空则使用服务端API。 +

+
+ {/* 操作按钮 */}
- {/* 豆瓣代理设置 */} + {/* 分割线 */} +
+ + {/* 豆瓣代理开关 */} +
+
+

+ 启用豆瓣代理 +

+

+ 启用后,豆瓣数据将通过代理服务器获取 +

+
+ +
+ + {/* 豆瓣代理地址设置 */}

- 豆瓣数据代理 + 豆瓣代理地址

- 设置代理URL以绕过豆瓣访问限制,留空则使用服务端API + 仅在启用豆瓣代理时生效,留空则使用服务器 API

handleDoubanProxyUrlChange(e.target.value)} + disabled={!enableDoubanProxy} />
+ {/* 分割线 */} +
+ {/* 图片代理开关 */}
diff --git a/src/lib/admin.types.ts b/src/lib/admin.types.ts index 82ea959..56633b8 100644 --- a/src/lib/admin.types.ts +++ b/src/lib/admin.types.ts @@ -5,6 +5,7 @@ export interface AdminConfig { SearchDownstreamMaxPage: number; SiteInterfaceCacheTime: number; ImageProxy: string; + DoubanProxy: string; }; UserConfig: { AllowRegister: boolean; diff --git a/src/lib/config.ts b/src/lib/config.ts index ec9cac0..dd1a647 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -159,6 +159,7 @@ async function initConfig() { Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5, SiteInterfaceCacheTime: fileConfig.cache_time || 7200, ImageProxy: process.env.NEXT_PUBLIC_IMAGE_PROXY || '', + DoubanProxy: process.env.NEXT_PUBLIC_DOUBAN_PROXY || '', }, UserConfig: { AllowRegister: process.env.NEXT_PUBLIC_ENABLE_REGISTER === 'true', @@ -197,6 +198,7 @@ async function initConfig() { Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5, SiteInterfaceCacheTime: fileConfig.cache_time || 7200, ImageProxy: process.env.NEXT_PUBLIC_IMAGE_PROXY || '', + DoubanProxy: process.env.NEXT_PUBLIC_DOUBAN_PROXY || '', }, UserConfig: { AllowRegister: process.env.NEXT_PUBLIC_ENABLE_REGISTER === 'true', @@ -341,6 +343,7 @@ export async function resetConfig() { Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5, SiteInterfaceCacheTime: fileConfig.cache_time || 7200, ImageProxy: process.env.NEXT_PUBLIC_IMAGE_PROXY || '', + DoubanProxy: process.env.NEXT_PUBLIC_DOUBAN_PROXY || '', }, UserConfig: { AllowRegister: process.env.NEXT_PUBLIC_ENABLE_REGISTER === 'true', diff --git a/src/lib/douban.client.ts b/src/lib/douban.client.ts index a74a6dc..8c78194 100644 --- a/src/lib/douban.client.ts +++ b/src/lib/douban.client.ts @@ -1,4 +1,5 @@ import { DoubanItem, DoubanResult } from './types'; +import { getDoubanProxyUrl } from './utils'; interface DoubanCategoriesParams { kind: 'tv' | 'movie'; @@ -60,16 +61,6 @@ async function fetchWithTimeout( } } -/** - * 获取豆瓣代理 URL 设置 - */ -export function getDoubanProxyUrl(): string | null { - if (typeof window === 'undefined') return null; - - const doubanProxyUrl = localStorage.getItem('doubanProxyUrl'); - return doubanProxyUrl && doubanProxyUrl.trim() ? doubanProxyUrl.trim() : null; -} - /** * 检查是否应该使用客户端获取豆瓣数据 */ diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 824e2c4..cc5152c 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -40,6 +40,44 @@ export function processImageUrl(originalUrl: string): string { return `${proxyUrl}${encodeURIComponent(originalUrl)}`; } +/** + * 获取豆瓣代理 URL 设置 + */ +export function getDoubanProxyUrl(): string | null { + if (typeof window === 'undefined') return null; + + // 本地未开启豆瓣代理,则不使用代理 + const enableDoubanProxy = localStorage.getItem('enableDoubanProxy'); + if (enableDoubanProxy !== null) { + if (!JSON.parse(enableDoubanProxy) as boolean) { + return null; + } + } + + const localDoubanProxy = localStorage.getItem('doubanProxyUrl'); + if (localDoubanProxy != null) { + return localDoubanProxy.trim() ? localDoubanProxy.trim() : null; + } + + // 如果未设置,则使用全局对象 + const serverDoubanProxy = (window as any).RUNTIME_CONFIG?.DOUBAN_PROXY; + return serverDoubanProxy && serverDoubanProxy.trim() + ? serverDoubanProxy.trim() + : null; +} + +/** + * 处理豆瓣 URL,如果设置了豆瓣代理则使用代理 + */ +export function processDoubanUrl(originalUrl: string): string { + if (!originalUrl) return originalUrl; + + const proxyUrl = getDoubanProxyUrl(); + if (!proxyUrl) return originalUrl; + + return `${proxyUrl}${encodeURIComponent(originalUrl)}`; +} + export function cleanHtmlTags(text: string): string { if (!text) return ''; return text