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。
+
+
+
{/* 操作按钮 */}
- {/* 豆瓣代理设置 */}
+ {/* 分割线 */}
+
+
+ {/* 豆瓣代理开关 */}
+
+
+
+ 启用豆瓣代理
+
+
+ 启用后,豆瓣数据将通过代理服务器获取
+
+
+
+
+
+ {/* 豆瓣代理地址设置 */}
+ {/* 分割线 */}
+
+
{/* 图片代理开关 */}
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