diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index d1302da..8d91667 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -336,6 +336,7 @@ interface SiteConfig {
PansouApiUrl?: string;
PansouUsername?: string;
PansouPassword?: string;
+ PansouKeywordBlocklist?: string;
EnableComments: boolean;
EnableRegistration?: boolean;
RegistrationRequireTurnstile?: boolean;
@@ -6679,6 +6680,7 @@ const SiteConfigComponent = ({
PansouApiUrl: '',
PansouUsername: '',
PansouPassword: '',
+ PansouKeywordBlocklist: '',
EnableComments: false,
EnableRegistration: false,
RegistrationRequireTurnstile: false,
@@ -6769,6 +6771,7 @@ const SiteConfigComponent = ({
PansouApiUrl: config.SiteConfig.PansouApiUrl || '',
PansouUsername: config.SiteConfig.PansouUsername || '',
PansouPassword: config.SiteConfig.PansouPassword || '',
+ PansouKeywordBlocklist: config.SiteConfig.PansouKeywordBlocklist || '',
EnableComments: config.SiteConfig.EnableComments || false,
});
}
@@ -7508,6 +7511,28 @@ const SiteConfigComponent = ({
配置账号密码后,系统会自动登录并缓存 Token
+
+ {/* 关键词屏蔽 */}
+
+
+
+ setSiteSettings((prev) => ({
+ ...prev,
+ PansouKeywordBlocklist: e.target.value,
+ }))
+ }
+ 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'
+ />
+
+ 设置后会过滤包含这些关键词的搜索结果
+
+
{/* 评论功能配置 */}
diff --git a/src/app/api/admin/site/route.ts b/src/app/api/admin/site/route.ts
index 4be703b..2a35297 100644
--- a/src/app/api/admin/site/route.ts
+++ b/src/app/api/admin/site/route.ts
@@ -49,6 +49,7 @@ export async function POST(request: NextRequest) {
PansouApiUrl,
PansouUsername,
PansouPassword,
+ PansouKeywordBlocklist,
EnableComments,
CustomAdFilterCode,
CustomAdFilterVersion,
@@ -89,6 +90,7 @@ export async function POST(request: NextRequest) {
PansouApiUrl?: string;
PansouUsername?: string;
PansouPassword?: string;
+ PansouKeywordBlocklist?: string;
EnableComments: boolean;
CustomAdFilterCode?: string;
CustomAdFilterVersion?: number;
@@ -129,6 +131,7 @@ export async function POST(request: NextRequest) {
(TMDBReverseProxy !== undefined && typeof TMDBReverseProxy !== 'string') ||
(BannerDataSource !== undefined && typeof BannerDataSource !== 'string') ||
(RecommendationDataSource !== undefined && typeof RecommendationDataSource !== 'string') ||
+ (PansouKeywordBlocklist !== undefined && typeof PansouKeywordBlocklist !== 'string') ||
typeof EnableComments !== 'boolean' ||
(CustomAdFilterCode !== undefined && typeof CustomAdFilterCode !== 'string') ||
(CustomAdFilterVersion !== undefined && typeof CustomAdFilterVersion !== 'number') ||
@@ -184,6 +187,7 @@ export async function POST(request: NextRequest) {
PansouApiUrl,
PansouUsername,
PansouPassword,
+ PansouKeywordBlocklist,
EnableComments,
CustomAdFilterCode,
CustomAdFilterVersion,
diff --git a/src/app/api/pansou/search/route.ts b/src/app/api/pansou/search/route.ts
index 7f10dff..89e87e4 100644
--- a/src/app/api/pansou/search/route.ts
+++ b/src/app/api/pansou/search/route.ts
@@ -3,7 +3,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { getConfig } from '@/lib/config';
-import { searchPansou } from '@/lib/pansou.client';
+import { PansouLink, searchPansou } from '@/lib/pansou.client';
export const runtime = 'nodejs';
@@ -44,13 +44,50 @@ export async function POST(request: NextRequest) {
password,
});
+ const rawBlocklist = config.SiteConfig.PansouKeywordBlocklist || '';
+ const normalizedBlocklist = rawBlocklist.replace(/,/g, ',');
+ const blockedKeywords = normalizedBlocklist
+ .split(',')
+ .map((item) => item.trim())
+ .filter(Boolean);
+
+ let filteredResults = results;
+
+ if (blockedKeywords.length > 0 && results.merged_by_type) {
+ const mergedByType: Record = {};
+ let total = 0;
+
+ const shouldBlock = (link: PansouLink) => {
+ const content = `${link.note || ''} ${link.url || ''} ${link.source || ''}`.toLowerCase();
+ return blockedKeywords.some((item) =>
+ content.includes(item.toLowerCase())
+ );
+ };
+
+ Object.entries(results.merged_by_type).forEach(([type, links]) => {
+ const filteredLinks = links.filter((link) => !shouldBlock(link));
+ if (filteredLinks.length > 0) {
+ mergedByType[type] = filteredLinks;
+ total += filteredLinks.length;
+ }
+ });
+
+ filteredResults = {
+ ...results,
+ merged_by_type: mergedByType,
+ total,
+ };
+ }
+
console.log('Pansou 搜索结果:', {
- total: results.total,
- hasData: !!results.merged_by_type,
- types: results.merged_by_type ? Object.keys(results.merged_by_type) : [],
+ total: filteredResults.total,
+ hasData: !!filteredResults.merged_by_type,
+ types: filteredResults.merged_by_type
+ ? Object.keys(filteredResults.merged_by_type)
+ : [],
});
- return NextResponse.json(results);
+ return NextResponse.json(filteredResults);
} catch (error: any) {
console.error('Pansou 搜索失败:', error);
return NextResponse.json(
diff --git a/src/lib/admin.types.ts b/src/lib/admin.types.ts
index 2adde6f..3eff29f 100644
--- a/src/lib/admin.types.ts
+++ b/src/lib/admin.types.ts
@@ -29,6 +29,7 @@ export interface AdminConfig {
PansouApiUrl?: string;
PansouUsername?: string;
PansouPassword?: string;
+ PansouKeywordBlocklist?: string;
// 评论功能开关
EnableComments: boolean;
// 自定义去广告代码
diff --git a/src/lib/config.ts b/src/lib/config.ts
index 74ad294..6c09dd7 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -251,6 +251,11 @@ async function getInitConfig(configFile: string, subConfig: {
TMDBApiKey: process.env.TMDB_API_KEY || '',
TMDBProxy: process.env.TMDB_PROXY || '',
TMDBReverseProxy: process.env.TMDB_REVERSE_PROXY || '',
+ // Pansou配置
+ PansouApiUrl: '',
+ PansouUsername: '',
+ PansouPassword: '',
+ PansouKeywordBlocklist: '',
// 评论功能开关
EnableComments: false,
},
@@ -446,6 +451,10 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
FluidSearch: true,
DanmakuApiBase: 'http://localhost:9321',
DanmakuApiToken: '87654321',
+ PansouApiUrl: '',
+ PansouUsername: '',
+ PansouPassword: '',
+ PansouKeywordBlocklist: '',
EnableComments: false,
};
}
@@ -460,6 +469,9 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
if (adminConfig.SiteConfig.EnableComments === undefined) {
adminConfig.SiteConfig.EnableComments = false;
}
+ if (adminConfig.SiteConfig.PansouKeywordBlocklist === undefined) {
+ adminConfig.SiteConfig.PansouKeywordBlocklist = '';
+ }
if (!adminConfig.UserConfig) {
adminConfig.UserConfig = { Users: [] };
}
@@ -665,4 +677,4 @@ export async function setCachedConfig(config: AdminConfig) {
export async function clearConfigCache() {
cachedConfig = null as any;
configInitPromise = null;
-}
\ No newline at end of file
+}