增加可视化视频源权重设置

This commit is contained in:
mtvpls
2026-05-09 18:46:41 +08:00
parent e3f7d43592
commit c55b4bd044
2 changed files with 3443 additions and 1710 deletions
+126 -27
View File
@@ -9,7 +9,18 @@ import { db } from '@/lib/db';
export const runtime = 'nodejs';
// 支持的操作类型
type Action = 'add' | 'disable' | 'enable' | 'delete' | 'sort' | 'batch_disable' | 'batch_enable' | 'batch_delete' | 'toggle_proxy_mode' | 'update_weight';
type Action =
| 'add'
| 'disable'
| 'enable'
| 'delete'
| 'sort'
| 'batch_disable'
| 'batch_enable'
| 'batch_delete'
| 'toggle_proxy_mode'
| 'update_weight'
| 'batch_update_weights';
interface BaseBody {
action?: Action;
@@ -37,7 +48,19 @@ export async function POST(request: NextRequest) {
const username = authInfo.username;
// 基础校验
const ACTIONS: Action[] = ['add', 'disable', 'enable', 'delete', 'sort', 'batch_disable', 'batch_enable', 'batch_delete', 'toggle_proxy_mode', 'update_weight'];
const ACTIONS: Action[] = [
'add',
'disable',
'enable',
'delete',
'sort',
'batch_disable',
'batch_enable',
'batch_delete',
'toggle_proxy_mode',
'update_weight',
'batch_update_weights',
];
if (!username || !action || !ACTIONS.includes(action)) {
return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
}
@@ -127,17 +150,17 @@ export async function POST(request: NextRequest) {
// 检查并清理用户组和用户的权限数组
// 清理用户组权限
if (adminConfig.UserConfig.Tags) {
adminConfig.UserConfig.Tags.forEach(tag => {
adminConfig.UserConfig.Tags.forEach((tag) => {
if (tag.enabledApis) {
tag.enabledApis = tag.enabledApis.filter(api => api !== key);
tag.enabledApis = tag.enabledApis.filter((api) => api !== key);
}
});
}
// 清理用户权限
adminConfig.UserConfig.Users.forEach(user => {
adminConfig.UserConfig.Users.forEach((user) => {
if (user.enabledApis) {
user.enabledApis = user.enabledApis.filter(api => api !== key);
user.enabledApis = user.enabledApis.filter((api) => api !== key);
}
});
break;
@@ -145,9 +168,12 @@ export async function POST(request: NextRequest) {
case 'batch_disable': {
const { keys } = body as { keys?: string[] };
if (!Array.isArray(keys) || keys.length === 0) {
return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
return NextResponse.json(
{ error: '缺少 keys 参数或为空' },
{ status: 400 }
);
}
keys.forEach(key => {
keys.forEach((key) => {
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (entry) {
entry.disabled = true;
@@ -158,9 +184,12 @@ export async function POST(request: NextRequest) {
case 'batch_enable': {
const { keys } = body as { keys?: string[] };
if (!Array.isArray(keys) || keys.length === 0) {
return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
return NextResponse.json(
{ error: '缺少 keys 参数或为空' },
{ status: 400 }
);
}
keys.forEach(key => {
keys.forEach((key) => {
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (entry) {
entry.disabled = false;
@@ -171,13 +200,16 @@ export async function POST(request: NextRequest) {
case 'batch_delete': {
const { keys } = body as { keys?: string[] };
if (!Array.isArray(keys) || keys.length === 0) {
return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 });
return NextResponse.json(
{ error: '缺少 keys 参数或为空' },
{ status: 400 }
);
}
// 过滤掉 from=config 的源,记录跳过的数量
const keysToDelete: string[] = [];
const skippedKeys: string[] = [];
keys.forEach(key => {
keys.forEach((key) => {
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (entry && entry.from === 'config') {
skippedKeys.push(key);
@@ -187,7 +219,7 @@ export async function POST(request: NextRequest) {
});
// 批量删除
keysToDelete.forEach(key => {
keysToDelete.forEach((key) => {
const idx = adminConfig.SourceConfig.findIndex((s) => s.key === key);
if (idx !== -1) {
adminConfig.SourceConfig.splice(idx, 1);
@@ -198,17 +230,21 @@ export async function POST(request: NextRequest) {
if (keysToDelete.length > 0) {
// 清理用户组权限
if (adminConfig.UserConfig.Tags) {
adminConfig.UserConfig.Tags.forEach(tag => {
adminConfig.UserConfig.Tags.forEach((tag) => {
if (tag.enabledApis) {
tag.enabledApis = tag.enabledApis.filter(api => !keysToDelete.includes(api));
tag.enabledApis = tag.enabledApis.filter(
(api) => !keysToDelete.includes(api)
);
}
});
}
// 清理用户权限
adminConfig.UserConfig.Users.forEach(user => {
adminConfig.UserConfig.Users.forEach((user) => {
if (user.enabledApis) {
user.enabledApis = user.enabledApis.filter(api => !keysToDelete.includes(api));
user.enabledApis = user.enabledApis.filter(
(api) => !keysToDelete.includes(api)
);
}
});
}
@@ -254,14 +290,80 @@ export async function POST(request: NextRequest) {
entry.proxyMode = !entry.proxyMode;
break;
}
case 'batch_update_weights': {
const { weights, order } = body as {
weights?: Array<{ key?: string; weight?: number }>;
order?: string[];
};
if (!Array.isArray(weights) || weights.length === 0) {
return NextResponse.json(
{ error: '缺少 weights 参数或为空' },
{ status: 400 }
);
}
for (const item of weights) {
if (!item?.key) {
return NextResponse.json(
{ error: 'weights 中存在无效 key' },
{ status: 400 }
);
}
if (
typeof item.weight !== 'number' ||
item.weight < 0 ||
item.weight > 100
) {
return NextResponse.json(
{ error: '权重必须是 0-100 之间的数字' },
{ status: 400 }
);
}
const entry = adminConfig.SourceConfig.find(
(source) => source.key === item.key
);
if (!entry) {
return NextResponse.json(
{ error: `源不存在: ${item.key}` },
{ status: 404 }
);
}
entry.weight = item.weight;
}
if (Array.isArray(order)) {
const map = new Map(
adminConfig.SourceConfig.map((source) => [source.key, source])
);
const newList: typeof adminConfig.SourceConfig = [];
order.forEach((key) => {
const item = map.get(key);
if (item) {
newList.push(item);
map.delete(key);
}
});
adminConfig.SourceConfig.forEach((item) => {
if (map.has(item.key)) newList.push(item);
});
adminConfig.SourceConfig = newList;
}
break;
}
case 'update_weight': {
const { key, weight } = body as { key?: string; weight?: number };
if (!key)
return NextResponse.json({ error: '缺少 key 参数' }, { status: 400 });
if (weight === undefined || weight === null)
return NextResponse.json({ error: '缺少 weight 参数' }, { status: 400 });
return NextResponse.json(
{ error: '缺少 weight 参数' },
{ status: 400 }
);
if (typeof weight !== 'number' || weight < 0 || weight > 100)
return NextResponse.json({ error: '权重必须是 0-100 之间的数字' }, { status: 400 });
return NextResponse.json(
{ error: '权重必须是 0-100 之间的数字' },
{ status: 400 }
);
const entry = adminConfig.SourceConfig.find((s) => s.key === key);
if (!entry)
return NextResponse.json({ error: '源不存在' }, { status: 404 });
@@ -293,14 +395,11 @@ export async function POST(request: NextRequest) {
responseData.skipped = (body as any)._batchDeleteResult.skipped;
}
return NextResponse.json(
responseData,
{
headers: {
'Cache-Control': 'no-store',
},
}
);
return NextResponse.json(responseData, {
headers: {
'Cache-Control': 'no-store',
},
});
} catch (error) {
console.error('视频源管理操作失败:', error);
return NextResponse.json(