From 7a4e61ebc4bb01b54231912f6dbf12c23f885918 Mon Sep 17 00:00:00 2001 From: shangfangjian Date: Mon, 21 Sep 2026 01:42:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=B7=BB=E5=8A=A0=E7=82=B9=E5=87=BB=E5=8F=8D=E9=A6=88?= =?UTF-8?q?=E5=92=8C=E6=96=87=E6=A1=88=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 启用/禁用/立即执行/删除按钮添加 loading 状态(Spinner) - 操作成功后显示绿色提示(如「已启用任务 xxx」) - 操作失败后显示红色错误提示 - 按钮禁用期间防止重复点击 Co-Authored-By: new-provider/LongCat-2.0 <> --- frontend/src/admin/pages/Settings.tsx | 64 ++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/frontend/src/admin/pages/Settings.tsx b/frontend/src/admin/pages/Settings.tsx index e22ff62..6800bb5 100644 --- a/frontend/src/admin/pages/Settings.tsx +++ b/frontend/src/admin/pages/Settings.tsx @@ -54,6 +54,8 @@ export default function SettingsPage() { // 定时任务 const [schedules, setSchedules] = useState([]) const [schedulesLoading, setSchedulesLoading] = useState(true) + const [scheduleNotice, setScheduleNotice] = useState<{ ok: boolean; text: string } | null>(null) + const [scheduleBusyId, setScheduleBusyId] = useState(null) // ── 数据加载 ── const loadSettings = useCallback(async () => { @@ -132,6 +134,48 @@ export default function SettingsPage() { } } + // ── 定时任务操作 ── + const handleToggleSchedule = async (s: ScheduleItem) => { + setScheduleBusyId(s.id) + setScheduleNotice(null) + try { + await updateSchedule(s.id, { enabled: !s.enabled }) + setScheduleNotice({ ok: true, text: `已${!s.enabled ? '启用' : '禁用'}任务「${s.id}」` }) + setSchedules(prev => prev.map(x => x.id === s.id ? { ...x, enabled: !x.enabled } : x)) + } catch { + setScheduleNotice({ ok: false, text: '操作失败' }) + } finally { + setScheduleBusyId(null) + } + } + + const handleRunSchedule = async (s: ScheduleItem) => { + setScheduleBusyId(s.id) + setScheduleNotice(null) + try { + await runScheduleNow(s.id) + setScheduleNotice({ ok: true, text: `任务「${s.id}」已启动,请在日志页查看进度` }) + } catch { + setScheduleNotice({ ok: false, text: '启动失败' }) + } finally { + setScheduleBusyId(null) + } + } + + const handleDeleteSchedule = async (s: ScheduleItem) => { + setScheduleBusyId(s.id) + setScheduleNotice(null) + try { + await deleteSchedule(s.id) + setScheduleNotice({ ok: true, text: `已删除任务「${s.id}」` }) + setSchedules(prev => prev.filter(x => x.id !== s.id)) + } catch { + setScheduleNotice({ ok: false, text: '删除失败' }) + } finally { + setScheduleBusyId(null) + } + } + const detectLLMModels = useCallback(async (): Promise => { const r = await fetchLLMModels() if (!r.ok) throw new Error(r.detail) @@ -390,6 +434,11 @@ export default function SettingsPage() { } /> + {scheduleNotice && ( +
+ setScheduleNotice(null)} /> +
+ )} {schedulesLoading ? ( ) : schedules.length === 0 ? ( @@ -414,22 +463,25 @@ export default function SettingsPage() {