diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index be43d06..248f9a5 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -3751,8 +3751,14 @@ const VideoSourceConfig = ({ throw new Error(data.error || `操作失败: ${resp.status}`); } + // 获取响应数据 + const data = await resp.json(); + // 成功后刷新配置 await refreshConfig(); + + // 返回响应数据供调用者使用 + return data; } catch (err) { showError(err instanceof Error ? err.message : '操作失败', showAlert); throw err; // 向上抛出方便调用处判断 @@ -4256,15 +4262,44 @@ const VideoSourceConfig = ({ message: confirmMessage, onConfirm: async () => { try { - await withLoading(`batchSource_${action}`, () => + const result = await withLoading(`batchSource_${action}`, () => callSourceApi({ action, keys }) ); - showAlert({ - type: 'success', - title: `${actionName}成功`, - message: `${actionName}了 ${keys.length} 个视频源`, - timer: 2000, - }); + + // 根据操作类型和结果显示不同的消息 + if (action === 'batch_delete' && result?.deleted !== undefined && result?.skipped !== undefined) { + const { deleted, skipped } = result; + if (skipped > 0) { + showAlert({ + type: 'warning', + title: '批量删除完成', + message: `成功删除了 ${deleted} 个视频源,跳过了 ${skipped} 个配置文件中的源(不可删除)`, + timer: 3000, + }); + } else if (deleted > 0) { + showAlert({ + type: 'success', + title: '批量删除成功', + message: `成功删除了 ${deleted} 个视频源`, + timer: 2000, + }); + } else { + showAlert({ + type: 'warning', + title: '无法删除', + message: '所选视频源均为配置文件中的源,不可删除', + timer: 3000, + }); + } + } else { + showAlert({ + type: 'success', + title: `${actionName}成功`, + message: `${actionName}了 ${keys.length} 个视频源`, + timer: 2000, + }); + } + // 重置选择状态 setSelectedSources(new Set()); } catch (err) { diff --git a/src/app/api/admin/source/route.ts b/src/app/api/admin/source/route.ts index 88ef61a..dce01e6 100644 --- a/src/app/api/admin/source/route.ts +++ b/src/app/api/admin/source/route.ts @@ -173,10 +173,17 @@ export async function POST(request: NextRequest) { if (!Array.isArray(keys) || keys.length === 0) { return NextResponse.json({ error: '缺少 keys 参数或为空' }, { status: 400 }); } - // 过滤掉 from=config 的源,但不报错 - const keysToDelete = keys.filter(key => { + // 过滤掉 from=config 的源,记录跳过的数量 + const keysToDelete: string[] = []; + const skippedKeys: string[] = []; + + keys.forEach(key => { const entry = adminConfig.SourceConfig.find((s) => s.key === key); - return entry && entry.from !== 'config'; + if (entry && entry.from === 'config') { + skippedKeys.push(key); + } else if (entry) { + keysToDelete.push(key); + } }); // 批量删除 @@ -205,6 +212,12 @@ export async function POST(request: NextRequest) { } }); } + + // 保存批量删除的统计信息,稍后返回 + (body as any)._batchDeleteResult = { + deleted: keysToDelete.length, + skipped: skippedKeys.length, + }; break; } case 'sort': { @@ -257,8 +270,17 @@ export async function POST(request: NextRequest) { // 不影响主流程,继续执行 } + // 构建响应数据 + const responseData: Record = { ok: true }; + + // 如果是批量删除操作,包含统计信息 + if (action === 'batch_delete' && (body as any)._batchDeleteResult) { + responseData.deleted = (body as any)._batchDeleteResult.deleted; + responseData.skipped = (body as any)._batchDeleteResult.skipped; + } + return NextResponse.json( - { ok: true }, + responseData, { headers: { 'Cache-Control': 'no-store',