feat: 添加 is_adult 字段以支持成人内容标记,更新相关逻辑处理
This commit is contained in:
+28
-3
@@ -70,6 +70,7 @@ interface DataSource {
|
||||
detail?: string;
|
||||
disabled?: boolean;
|
||||
from: 'config' | 'custom';
|
||||
is_adult?: boolean; // 添加成人内容标记字段
|
||||
}
|
||||
|
||||
// 可折叠标签组件
|
||||
@@ -643,6 +644,7 @@ const VideoSourceConfig = ({
|
||||
detail: '',
|
||||
disabled: false,
|
||||
from: 'config',
|
||||
is_adult: false, // 默认不是成人内容
|
||||
});
|
||||
|
||||
// dnd-kit 传感器
|
||||
@@ -721,6 +723,7 @@ const VideoSourceConfig = ({
|
||||
name: newSource.name,
|
||||
api: newSource.api,
|
||||
detail: newSource.detail,
|
||||
is_adult: newSource.is_adult, // 传递成人内容标记
|
||||
})
|
||||
.then(() => {
|
||||
setNewSource({
|
||||
@@ -730,6 +733,7 @@ const VideoSourceConfig = ({
|
||||
detail: '',
|
||||
disabled: false,
|
||||
from: 'custom',
|
||||
is_adult: false, // 重置为默认值
|
||||
});
|
||||
setShowAddForm(false);
|
||||
})
|
||||
@@ -866,7 +870,8 @@ const VideoSourceConfig = ({
|
||||
exportConfig.api_site[source.key] = {
|
||||
api: source.api,
|
||||
name: source.name,
|
||||
...(source.detail && { detail: source.detail })
|
||||
...(source.detail && { detail: source.detail }),
|
||||
...(source.is_adult !== undefined && { is_adult: source.is_adult }) // 确保导出 is_adult 字段
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -939,7 +944,7 @@ const VideoSourceConfig = ({
|
||||
throw new Error(`${key}: 无效的配置对象`);
|
||||
}
|
||||
|
||||
const sourceObj = source as { api?: string; name?: string; detail?: string };
|
||||
const sourceObj = source as { api?: string; name?: string; detail?: string; is_adult?: boolean };
|
||||
|
||||
if (!sourceObj.api || !sourceObj.name) {
|
||||
throw new Error(`${key}: 缺少必要字段 api 或 name`);
|
||||
@@ -950,7 +955,8 @@ const VideoSourceConfig = ({
|
||||
key: key,
|
||||
name: sourceObj.name,
|
||||
api: sourceObj.api,
|
||||
detail: sourceObj.detail || ''
|
||||
detail: sourceObj.detail || '',
|
||||
is_adult: sourceObj.is_adult || false // 确保处理 is_adult 字段
|
||||
});
|
||||
successCount++;
|
||||
} catch (error) {
|
||||
@@ -1246,6 +1252,25 @@ const VideoSourceConfig = ({
|
||||
}
|
||||
className='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'
|
||||
/>
|
||||
|
||||
{/* 成人内容标记复选框 */}
|
||||
<div className='flex items-center space-x-2'>
|
||||
<input
|
||||
type='checkbox'
|
||||
id='is_adult'
|
||||
checked={newSource.is_adult || false}
|
||||
onChange={(e) =>
|
||||
setNewSource((prev) => ({ ...prev, is_adult: e.target.checked }))
|
||||
}
|
||||
className='w-4 h-4 text-red-600 bg-gray-100 border-gray-300 rounded focus:ring-red-500 dark:bg-gray-700 dark:border-gray-600'
|
||||
/>
|
||||
<label
|
||||
htmlFor='is_adult'
|
||||
className='text-sm font-medium text-gray-900 dark:text-gray-300'
|
||||
>
|
||||
🔞 成人内容资源站
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex justify-end'>
|
||||
<button
|
||||
|
||||
@@ -59,11 +59,12 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
switch (action) {
|
||||
case 'add': {
|
||||
const { key, name, api, detail } = body as {
|
||||
const { key, name, api, detail, is_adult } = body as {
|
||||
key?: string;
|
||||
name?: string;
|
||||
api?: string;
|
||||
detail?: string;
|
||||
is_adult?: boolean;
|
||||
};
|
||||
if (!key || !name || !api) {
|
||||
return NextResponse.json({ error: '缺少必要参数' }, { status: 400 });
|
||||
@@ -78,6 +79,7 @@ export async function POST(request: NextRequest) {
|
||||
detail,
|
||||
from: 'custom',
|
||||
disabled: false,
|
||||
is_adult: is_adult || false, // 确保处理 is_adult 字段
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
+30
-2
@@ -262,6 +262,7 @@ export async function getConfig(): Promise<AdminConfig> {
|
||||
detail: site.detail,
|
||||
from: 'config',
|
||||
disabled: false,
|
||||
is_adult: (site as any).is_adult || false, // 确保处理 is_adult 字段
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -271,6 +272,12 @@ export async function getConfig(): Promise<AdminConfig> {
|
||||
adminConfig.SourceConfig.forEach((source) => {
|
||||
if (!apiSiteKeys.has(source.key)) {
|
||||
source.from = 'custom';
|
||||
} else {
|
||||
// 更新现有源的 is_adult 字段
|
||||
const siteConfig = fileConfig.api_site[source.key];
|
||||
if (siteConfig) {
|
||||
source.is_adult = (siteConfig as any).is_adult || false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -388,7 +395,20 @@ export async function getCacheTime(): Promise<number> {
|
||||
|
||||
export async function getAvailableApiSites(filterAdult = false): Promise<ApiSite[]> {
|
||||
const config = await getConfig();
|
||||
let sites = config.SourceConfig.filter((s) => !s.disabled);
|
||||
|
||||
// 防御性检查:确保 SourceConfig 存在且为数组
|
||||
if (!config.SourceConfig || !Array.isArray(config.SourceConfig)) {
|
||||
console.warn('SourceConfig is missing or not an array, returning empty array');
|
||||
return [];
|
||||
}
|
||||
|
||||
// 防御性处理:为每个源确保 is_adult 字段存在
|
||||
let sites = config.SourceConfig
|
||||
.filter((s) => !s.disabled)
|
||||
.map((s) => ({
|
||||
...s,
|
||||
is_adult: s.is_adult === true // 严格检查,只有明确为 true 的才是成人内容
|
||||
}));
|
||||
|
||||
// 如果需要过滤成人内容,则排除标记为成人内容的资源站
|
||||
if (filterAdult) {
|
||||
@@ -406,8 +426,16 @@ export async function getAvailableApiSites(filterAdult = false): Promise<ApiSite
|
||||
// 获取成人内容资源站
|
||||
export async function getAdultApiSites(): Promise<ApiSite[]> {
|
||||
const config = await getConfig();
|
||||
|
||||
// 防御性检查:确保 SourceConfig 存在且为数组
|
||||
if (!config.SourceConfig || !Array.isArray(config.SourceConfig)) {
|
||||
console.warn('SourceConfig is missing or not an array, returning empty array');
|
||||
return [];
|
||||
}
|
||||
|
||||
// 防御性处理:严格检查成人内容标记
|
||||
const adultSites = config.SourceConfig
|
||||
.filter((s) => !s.disabled && s.is_adult);
|
||||
.filter((s) => !s.disabled && s.is_adult === true); // 只有明确为 true 的才被认为是成人内容
|
||||
|
||||
return adultSites.map((s) => ({
|
||||
key: s.key,
|
||||
|
||||
Reference in New Issue
Block a user