From d563ca165d044de29217c93841cc4f0df0032989 Mon Sep 17 00:00:00 2001 From: katelya Date: Wed, 3 Sep 2025 14:15:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=BA=90=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E4=B8=80=E9=94=AE=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=89=80=E6=9C=89=E8=A7=86=E9=A2=91=E6=BA=90=E5=B9=B6=E6=94=B9?= =?UTF-8?q?=E5=96=84=E7=94=A8=E6=88=B7=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/admin/page.tsx | 111 +++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 70 deletions(-) diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index da8ebbe..6c2387d 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -741,9 +741,8 @@ const VideoSourceConfig = ({ const handleSelectAll = (checked: boolean) => { if (checked) { - // 只选择可删除的视频源(from !== 'config') - const deletableSources = sources.filter(source => source.from !== 'config'); - setSelectedSources(new Set(deletableSources.map(source => source.key))); + // 选择所有视频源(包括示例源) + setSelectedSources(new Set(sources.map(source => source.key))); } else { setSelectedSources(new Set()); } @@ -757,68 +756,43 @@ const VideoSourceConfig = ({ const selectedArray = Array.from(selectedSources); const result = await Swal.fire({ - title: '确认批量删除', - text: `即将删除 ${selectedArray.length} 个视频源,此操作不可撤销!`, + title: '⚡ 一键批量删除', + html: ` +

即将瞬间删除 ${selectedArray.length} 个视频源

+

包含所有选中的视频源(含示例源)

+

⚠️ 此操作不可撤销!

+ `, icon: 'warning', showCancelButton: true, - confirmButtonText: '确认删除', + confirmButtonText: '⚡ 瞬间删除', cancelButtonText: '取消', confirmButtonColor: '#ef4444', - cancelButtonColor: '#6b7280' + cancelButtonColor: '#6b7280', + showLoaderOnConfirm: true, + allowOutsideClick: () => !Swal.isLoading(), + preConfirm: async () => { + try { + // 并行删除所有选中的视频源,实现真正的一键删除 + const deletePromises = selectedArray.map(key => + callSourceApi({ action: 'delete', key }) + ); + + await Promise.all(deletePromises); + return { success: true, count: selectedArray.length }; + } catch (error) { + Swal.showValidationMessage( + `删除失败: ${error instanceof Error ? error.message : '未知错误'}` + ); + return false; + } + } }); - if (!result.isConfirmed) return; - - // 批量删除 - let successCount = 0; - let errorCount = 0; - const errors: string[] = []; - - for (const key of selectedArray) { - try { - await callSourceApi({ action: 'delete', key }); - successCount++; - } catch (error) { - errorCount++; - const sourceName = sources.find(s => s.key === key)?.name || key; - errors.push(`${sourceName}: ${error instanceof Error ? error.message : '删除失败'}`); - } - } - - // 显示删除结果 - if (errorCount === 0) { - showSuccess(`成功删除 ${successCount} 个视频源`); - setSelectedSources(new Set()); // 清空选择 - setBatchMode(false); // 退出批量模式 - } else { - await Swal.fire({ - title: '删除完成', - html: ` -
-

✅ 成功删除: ${successCount} 个

-

❌ 删除失败: ${errorCount} 个

- ${errors.length > 0 ? ` -
- 查看错误详情 -
- ${errors.map(err => `
${err}
`).join('')} -
-
- ` : ''} -
- `, - icon: successCount > 0 ? 'warning' : 'error', - confirmButtonText: '确定' - }); - - // 清空已成功删除的选择项 - const failedKeys = new Set( - errors.map(err => { - const keyMatch = err.split(':')[0]; - return sources.find(s => s.name === keyMatch)?.key; - }).filter((key): key is string => Boolean(key)) - ); - setSelectedSources(failedKeys); + if (result.isConfirmed && result.value) { + showSuccess(`⚡ 瞬间删除成功!已删除 ${result.value.count} 个视频源`); + setSelectedSources(new Set()); + setBatchMode(false); + await refreshConfig(); } }; @@ -1023,8 +997,7 @@ const VideoSourceConfig = ({ type='checkbox' checked={selectedSources.has(source.key)} onChange={(e) => handleSelectSource(source.key, e.target.checked)} - disabled={source.from === 'config'} - className='w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 disabled:opacity-50' + className='w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600' /> )} @@ -1068,14 +1041,12 @@ const VideoSourceConfig = ({ > {!source.disabled ? '禁用' : '启用'} - {source.from !== 'config' && ( - - )} + ); @@ -1232,7 +1203,7 @@ const VideoSourceConfig = ({ 0 && selectedSources.size === sources.filter(s => s.from !== 'config').length} + checked={selectedSources.size > 0 && selectedSources.size === sources.length} onChange={(e) => handleSelectAll(e.target.checked)} className='w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600' />