重构前端逻辑

This commit is contained in:
dengqichen 2025-11-07 13:15:14 +08:00
parent ee9c0124fd
commit 344ba25284
9 changed files with 296 additions and 492 deletions

View File

@ -7,16 +7,7 @@ import type { MenuProps } from 'antd';
import { logout } from '@/store/userSlice'; import { logout } from '@/store/userSlice';
import type { RootState } from '@/store'; import type { RootState } from '@/store';
import { useToast } from '@/components/ui/use-toast'; import { useToast } from '@/components/ui/use-toast';
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { AlertCircle } from 'lucide-react'; import { AlertCircle } from 'lucide-react';
import { shallowEqual } from 'react-redux'; import { shallowEqual } from 'react-redux';
@ -44,12 +35,8 @@ const UserPanel: React.FC = React.memo(() => {
setLogoutDialogOpen(true); setLogoutDialogOpen(true);
}; };
const confirmLogout = () => { const confirmLogout = async () => {
dispatch(logout()); dispatch(logout());
toast({
title: '退出成功',
description: '已成功退出系统',
});
navigate('/login', { replace: true }); navigate('/login', { replace: true });
}; };
@ -92,25 +79,25 @@ const UserPanel: React.FC = React.memo(() => {
</Dropdown> </Dropdown>
{/* 退出登录确认对话框 */} {/* 退出登录确认对话框 */}
<AlertDialog open={logoutDialogOpen} onOpenChange={setLogoutDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={logoutDialogOpen}
<AlertDialogHeader> onOpenChange={setLogoutDialogOpen}
<AlertDialogTitle className="flex items-center gap-2"> title={
<AlertCircle className="h-5 w-5 text-amber-500" /> <div className="flex items-center gap-2">
退 <AlertCircle className="h-5 w-5 text-amber-500" />
</AlertDialogTitle> 退
<AlertDialogDescription> </div>
退 }
</AlertDialogDescription> description="确定要退出系统吗?"
</AlertDialogHeader> onConfirm={confirmLogout}
<AlertDialogFooter> onSuccess={() => {
<AlertDialogCancel onClick={() => setLogoutDialogOpen(false)}> toast({
title: '退出成功',
</AlertDialogCancel> description: '已成功退出系统',
<AlertDialogAction onClick={confirmLogout}></AlertDialogAction> });
</AlertDialogFooter> }}
</AlertDialogContent> confirmText="确定"
</AlertDialog> />
</> </>
); );
}); });

View File

@ -6,16 +6,7 @@ import {
DialogBody, DialogBody,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { import {
@ -175,25 +166,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
if (!deleteRecord) return; if (!deleteRecord) return;
await deleteCategory(deleteRecord.id);
try {
await deleteCategory(deleteRecord.id);
toast({
title: "删除成功",
description: `分类 "${deleteRecord.name}" 已删除`,
});
loadCategories();
onSuccess?.();
setDeleteDialogOpen(false);
setDeleteRecord(null);
} catch (error) {
console.error('删除失败:', error);
toast({
variant: "destructive",
title: "删除失败",
description: error instanceof Error ? error.message : '未知错误',
});
}
}; };
// 保存 // 保存
@ -516,53 +489,52 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
</Dialog> </Dialog>
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除分类"
<AlertDialogDescription asChild> description="您确定要删除以下分类吗?此操作无法撤销。"
<div className="space-y-3"> item={deleteRecord}
<p></p> onConfirm={confirmDelete}
{deleteRecord && ( onSuccess={() => {
<div className="rounded-md border p-3 space-y-2 bg-muted/50"> toast({
<div className="flex items-center gap-2"> title: "删除成功",
<span className="text-sm font-medium text-muted-foreground">:</span> description: `分类 "${deleteRecord?.name}" 已删除`,
<span className="font-medium">{deleteRecord.name}</span> });
</div> setDeleteRecord(null);
<div className="flex items-center gap-2"> loadCategories();
<span className="text-sm font-medium text-muted-foreground">:</span> onSuccess?.();
<code className="text-xs bg-background px-2 py-1 rounded"> }}
{deleteRecord.code} variant="destructive"
</code> confirmText="确认删除"
</div> >
{deleteRecord.icon && ( {deleteRecord && (
<div className="flex items-center gap-2"> <div className="rounded-md border p-3 space-y-2 bg-muted/50">
<span className="text-sm font-medium text-muted-foreground">:</span> <div className="flex items-center gap-2">
<DynamicIcon name={deleteRecord.icon} className="h-4 w-4" /> <span className="text-sm font-medium text-muted-foreground">:</span>
</div> <span className="font-medium">{deleteRecord.name}</span>
)} </div>
{deleteRecord.description && ( <div className="flex items-center gap-2">
<div className="flex items-start gap-2"> <span className="text-sm font-medium text-muted-foreground">:</span>
<span className="text-sm font-medium text-muted-foreground">:</span> <code className="text-xs bg-background px-2 py-1 rounded">
<span className="text-sm">{deleteRecord.description}</span> {deleteRecord.code}
</div> </code>
)} </div>
</div> {deleteRecord.icon && (
)} <div className="flex items-center gap-2">
<span className="text-sm font-medium text-muted-foreground">:</span>
<DynamicIcon name={deleteRecord.icon} className="h-4 w-4" />
</div> </div>
</AlertDialogDescription> )}
</AlertDialogHeader> {deleteRecord.description && (
<AlertDialogFooter> <div className="flex items-start gap-2">
<AlertDialogCancel></AlertDialogCancel> <span className="text-sm font-medium text-muted-foreground">:</span>
<AlertDialogAction <span className="text-sm">{deleteRecord.description}</span>
onClick={confirmDelete} </div>
className="bg-destructive text-destructive-foreground hover:bg-destructive/90" )}
> </div>
)}
</AlertDialogAction> </ConfirmDialog>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</> </>
); );
}; };

View File

@ -17,16 +17,7 @@ import {
TableRow, TableRow,
} from '@/components/ui/table'; } from '@/components/ui/table';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { useToast } from '@/components/ui/use-toast'; import { useToast } from '@/components/ui/use-toast';
import { DataTablePagination } from '@/components/ui/pagination'; import { DataTablePagination } from '@/components/ui/pagination';
import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page'; import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page';
@ -176,20 +167,7 @@ const NotificationChannelList: React.FC = () => {
// 删除 // 删除
const handleDelete = async () => { const handleDelete = async () => {
if (!deleteId) return; if (!deleteId) return;
await deleteChannel(deleteId);
try {
await deleteChannel(deleteId);
toast({ title: '删除成功' });
setDeleteDialogOpen(false);
setDeleteId(null);
loadData();
} catch (error: any) {
toast({
variant: 'destructive',
title: '删除失败',
description: error.response?.data?.message || error.message,
});
}
}; };
// 启用/禁用 // 启用/禁用
@ -477,20 +455,22 @@ const NotificationChannelList: React.FC = () => {
/> />
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除"
<AlertDialogDescription> description="确定要删除这个通知渠道吗?此操作不可撤销。"
item={deleteId}
</AlertDialogDescription> onConfirm={handleDelete}
</AlertDialogHeader> onSuccess={() => {
<AlertDialogFooter> toast({ title: '删除成功' });
<AlertDialogCancel onClick={() => setDeleteId(null)}></AlertDialogCancel> setDeleteId(null);
<AlertDialogAction onClick={handleDelete}></AlertDialogAction> loadData();
</AlertDialogFooter> }}
</AlertDialogContent> onCancel={() => setDeleteId(null)}
</AlertDialog> variant="destructive"
confirmText="删除"
/>
</div> </div>
); );
}; };

View File

@ -6,16 +6,7 @@ import {
DialogBody, DialogBody,
DialogTitle, DialogTitle,
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { import {
@ -180,25 +171,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
if (!deleteRecord) return; if (!deleteRecord) return;
await deleteJobCategory(deleteRecord.id);
try {
await deleteJobCategory(deleteRecord.id);
toast({
title: '删除成功',
description: `分类 "${deleteRecord.name}" 已删除`,
});
loadCategories();
onSuccess?.();
setDeleteDialogOpen(false);
setDeleteRecord(null);
} catch (error) {
console.error('删除失败:', error);
toast({
variant: 'destructive',
title: '删除失败',
description: error instanceof Error ? error.message : '未知错误',
});
}
}; };
// 保存 // 保存
@ -542,21 +515,30 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
/> />
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除"
<AlertDialogDescription> description={
<span className="font-semibold">{deleteRecord?.name}</span> <>
<span className="font-semibold">{deleteRecord?.name}</span>
</AlertDialogDescription>
</AlertDialogHeader> </>
<AlertDialogFooter> }
<AlertDialogCancel></AlertDialogCancel> item={deleteRecord}
<AlertDialogAction onClick={confirmDelete}></AlertDialogAction> onConfirm={confirmDelete}
</AlertDialogFooter> onSuccess={() => {
</AlertDialogContent> toast({
</AlertDialog> title: '删除成功',
description: `分类 "${deleteRecord?.name}" 已删除`,
});
setDeleteRecord(null);
loadCategories();
onSuccess?.();
}}
variant="destructive"
confirmText="确认删除"
/>
</> </>
); );
}; };

View File

@ -20,16 +20,7 @@ import CategoryManageDialog from './components/CategoryManageDialog';
import JobLogDialog from './components/JobLogDialog'; import JobLogDialog from './components/JobLogDialog';
import JobEditDialog from './components/JobEditDialog'; import JobEditDialog from './components/JobEditDialog';
import Dashboard from './components/Dashboard'; import Dashboard from './components/Dashboard';
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
/** /**
@ -123,22 +114,7 @@ const ScheduleJobList: React.FC = () => {
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
if (!deleteJob) return; if (!deleteJob) return;
try { await deleteScheduleJob(deleteJob.id);
await deleteScheduleJob(deleteJob.id);
toast({
title: '删除成功',
description: `任务 "${deleteJob.jobName}" 已删除`,
});
loadData();
setDeleteDialogOpen(false);
setDeleteJob(null);
} catch (error) {
toast({
variant: 'destructive',
title: '删除失败',
description: error instanceof Error ? error.message : '未知错误',
});
}
}; };
// 暂停任务 // 暂停任务
@ -612,55 +588,53 @@ const ScheduleJobList: React.FC = () => {
/> />
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除定时任务"
<AlertDialogDescription asChild> description="您确定要删除以下定时任务吗?此操作无法撤销。"
<div className="space-y-3"> item={deleteJob}
<p></p> onConfirm={confirmDelete}
{deleteJob && ( onSuccess={() => {
<div className="rounded-md border p-3 space-y-2 bg-muted/50"> toast({
<div className="flex items-center gap-2"> title: '删除成功',
<span className="text-sm font-medium text-muted-foreground">:</span> description: `任务 "${deleteJob?.jobName}" 已删除`,
<span className="font-medium">{deleteJob.jobName}</span> });
</div> setDeleteJob(null);
<div className="flex items-center gap-2"> loadData();
<span className="text-sm font-medium text-muted-foreground">Bean名称:</span> }}
<code className="text-xs bg-background px-2 py-1 rounded"> variant="destructive"
{deleteJob.beanName} confirmText="确认删除"
</code> >
</div> {deleteJob && (
<div className="flex items-center gap-2"> <div className="rounded-md border p-3 space-y-2 bg-muted/50">
<span className="text-sm font-medium text-muted-foreground">:</span> <div className="flex items-center gap-2">
<code className="text-xs bg-background px-2 py-1 rounded"> <span className="text-sm font-medium text-muted-foreground">:</span>
{deleteJob.methodName} <span className="font-medium">{deleteJob.jobName}</span>
</code> </div>
</div> <div className="flex items-center gap-2">
{deleteJob.cronExpression && ( <span className="text-sm font-medium text-muted-foreground">Bean名称:</span>
<div className="flex items-center gap-2"> <code className="text-xs bg-background px-2 py-1 rounded">
<span className="text-sm font-medium text-muted-foreground">Cron表达式:</span> {deleteJob.beanName}
<code className="text-xs bg-background px-2 py-1 rounded"> </code>
{deleteJob.cronExpression} </div>
</code> <div className="flex items-center gap-2">
</div> <span className="text-sm font-medium text-muted-foreground">:</span>
)} <code className="text-xs bg-background px-2 py-1 rounded">
</div> {deleteJob.methodName}
)} </code>
</div>
{deleteJob.cronExpression && (
<div className="flex items-center gap-2">
<span className="text-sm font-medium text-muted-foreground">Cron表达式:</span>
<code className="text-xs bg-background px-2 py-1 rounded">
{deleteJob.cronExpression}
</code>
</div> </div>
</AlertDialogDescription> )}
</AlertDialogHeader> </div>
<AlertDialogFooter> )}
<AlertDialogCancel></AlertDialogCancel> </ConfirmDialog>
<AlertDialogAction
onClick={confirmDelete}
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</TabsContent> </TabsContent>
{/* 仪表盘视图 */} {/* 仪表盘视图 */}

View File

@ -6,16 +6,7 @@ import {
DialogBody, DialogBody,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { import {
@ -172,25 +163,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
if (!deleteRecord) return; if (!deleteRecord) return;
await deleteCategory(deleteRecord.id);
try {
await deleteCategory(deleteRecord.id);
toast({
title: "删除成功",
description: `分类 "${deleteRecord.name}" 已删除`,
});
loadCategories();
onSuccess?.();
setDeleteDialogOpen(false);
setDeleteRecord(null);
} catch (error) {
console.error('删除失败:', error);
toast({
variant: "destructive",
title: "删除失败",
description: error instanceof Error ? error.message : '未知错误',
});
}
}; };
// 保存 // 保存
@ -509,53 +482,52 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
</Dialog> </Dialog>
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除分类"
<AlertDialogDescription asChild> description="您确定要删除以下分类吗?此操作无法撤销。"
<div className="space-y-3"> item={deleteRecord}
<p></p> onConfirm={confirmDelete}
{deleteRecord && ( onSuccess={() => {
<div className="rounded-md border p-3 space-y-2 bg-muted/50"> toast({
<div className="flex items-center gap-2"> title: "删除成功",
<span className="text-sm font-medium text-muted-foreground">:</span> description: `分类 "${deleteRecord?.name}" 已删除`,
<span className="font-medium">{deleteRecord.name}</span> });
</div> setDeleteRecord(null);
<div className="flex items-center gap-2"> loadCategories();
<span className="text-sm font-medium text-muted-foreground">:</span> onSuccess?.();
<code className="text-xs bg-background px-2 py-1 rounded"> }}
{deleteRecord.code} variant="destructive"
</code> confirmText="确认删除"
</div> >
{deleteRecord.icon && ( {deleteRecord && (
<div className="flex items-center gap-2"> <div className="rounded-md border p-3 space-y-2 bg-muted/50">
<span className="text-sm font-medium text-muted-foreground">:</span> <div className="flex items-center gap-2">
<DynamicIcon name={deleteRecord.icon} className="h-4 w-4" /> <span className="text-sm font-medium text-muted-foreground">:</span>
</div> <span className="font-medium">{deleteRecord.name}</span>
)} </div>
{deleteRecord.description && ( <div className="flex items-center gap-2">
<div className="flex items-start gap-2"> <span className="text-sm font-medium text-muted-foreground">:</span>
<span className="text-sm font-medium text-muted-foreground">:</span> <code className="text-xs bg-background px-2 py-1 rounded">
<span className="text-sm">{deleteRecord.description}</span> {deleteRecord.code}
</div> </code>
)} </div>
</div> {deleteRecord.icon && (
)} <div className="flex items-center gap-2">
<span className="text-sm font-medium text-muted-foreground">:</span>
<DynamicIcon name={deleteRecord.icon} className="h-4 w-4" />
</div> </div>
</AlertDialogDescription> )}
</AlertDialogHeader> {deleteRecord.description && (
<AlertDialogFooter> <div className="flex items-start gap-2">
<AlertDialogCancel></AlertDialogCancel> <span className="text-sm font-medium text-muted-foreground">:</span>
<AlertDialogAction <span className="text-sm">{deleteRecord.description}</span>
onClick={confirmDelete} </div>
className="bg-destructive text-destructive-foreground hover:bg-destructive/90" )}
> </div>
)}
</AlertDialogAction> </ConfirmDialog>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</> </>
); );
}; };

View File

@ -33,7 +33,7 @@ import {
TableRow, TableRow,
} from '@/components/ui/table'; } from '@/components/ui/table';
import { useToast } from '@/components/ui/use-toast'; import { useToast } from '@/components/ui/use-toast';
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog'; import { ConfirmDialog } from '@/components/ui/confirm-dialog';
import { DataTablePagination } from '@/components/ui/pagination'; import { DataTablePagination } from '@/components/ui/pagination';
import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page'; import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page';
import type { ServerCategoryResponse } from '../types'; import type { ServerCategoryResponse } from '../types';
@ -159,25 +159,7 @@ export const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
const confirmDelete = async () => { const confirmDelete = async () => {
if (!categoryToDelete) return; if (!categoryToDelete) return;
await deleteServerCategory(categoryToDelete.id);
try {
await deleteServerCategory(categoryToDelete.id);
toast({
title: '删除成功',
description: `分类"${categoryToDelete.name}"已删除`,
});
loadCategories();
onSuccess?.();
} catch (error) {
toast({
variant: 'destructive',
title: '删除失败',
description: '删除服务器分类失败',
});
} finally {
setDeleteConfirmOpen(false);
setCategoryToDelete(null);
}
}; };
// 提交表单 // 提交表单
@ -499,20 +481,25 @@ export const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
</Dialog> </Dialog>
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteConfirmOpen}
<AlertDialogHeader> onOpenChange={setDeleteConfirmOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除"
<AlertDialogDescription> description={`确定要删除分类"${categoryToDelete?.name}"吗?此操作无法撤销。`}
"{categoryToDelete?.name}" item={categoryToDelete}
</AlertDialogDescription> onConfirm={confirmDelete}
</AlertDialogHeader> onSuccess={() => {
<AlertDialogFooter> toast({
<AlertDialogCancel></AlertDialogCancel> title: '删除成功',
<AlertDialogAction onClick={confirmDelete}></AlertDialogAction> description: `分类"${categoryToDelete?.name}"已删除`,
</AlertDialogFooter> });
</AlertDialogContent> setCategoryToDelete(null);
</AlertDialog> loadCategories();
onSuccess?.();
}}
variant="destructive"
confirmText="确定"
/>
</> </>
); );
}; };

View File

@ -29,16 +29,7 @@ import {
import { import {
TooltipProvider, TooltipProvider,
} from '@/components/ui/tooltip'; } from '@/components/ui/tooltip';
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { useToast } from '@/components/ui/use-toast'; import { useToast } from '@/components/ui/use-toast';
import { DataTablePagination } from '@/components/ui/pagination'; import { DataTablePagination } from '@/components/ui/pagination';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
@ -215,25 +206,7 @@ const ServerList: React.FC = () => {
const confirmDelete = async () => { const confirmDelete = async () => {
if (!serverToDelete) return; if (!serverToDelete) return;
await deleteServer(serverToDelete.id);
try {
await deleteServer(serverToDelete.id);
toast({
title: '删除成功',
description: `服务器"${serverToDelete.serverName}"已删除`,
});
loadServers();
loadStats();
} catch (error: any) {
toast({
variant: 'destructive',
title: '删除失败',
description: error.response?.data?.message || '删除失败',
});
} finally {
setDeleteDialogOpen(false);
setServerToDelete(null);
}
}; };
// 成功回调 // 成功回调
@ -600,20 +573,25 @@ const ServerList: React.FC = () => {
/> />
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除"
<AlertDialogDescription> description={`确定要删除服务器"${serverToDelete?.serverName}"吗?此操作无法撤销。`}
"{serverToDelete?.serverName}" item={serverToDelete}
</AlertDialogDescription> onConfirm={confirmDelete}
</AlertDialogHeader> onSuccess={() => {
<AlertDialogFooter> toast({
<AlertDialogCancel></AlertDialogCancel> title: '删除成功',
<AlertDialogAction onClick={confirmDelete}></AlertDialogAction> description: `服务器"${serverToDelete?.serverName}"已删除`,
</AlertDialogFooter> });
</AlertDialogContent> setServerToDelete(null);
</AlertDialog> loadServers();
loadStats();
}}
variant="destructive"
confirmText="确定"
/>
</TooltipProvider> </TooltipProvider>
); );
}; };

View File

@ -6,16 +6,7 @@ import {
DialogBody, DialogBody,
DialogTitle, DialogTitle,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import { import { ConfirmDialog } from '@/components/ui/confirm-dialog';
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { import {
@ -190,25 +181,7 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
// 确认删除 // 确认删除
const confirmDelete = async () => { const confirmDelete = async () => {
if (!deleteRecord) return; if (!deleteRecord) return;
await deleteWorkflowCategory(deleteRecord.id);
try {
await deleteWorkflowCategory(deleteRecord.id);
toast({
title: "删除成功",
description: `分类 "${deleteRecord.name}" 已删除`,
});
loadCategories();
onSuccess?.();
setDeleteDialogOpen(false);
setDeleteRecord(null);
} catch (error) {
console.error('删除失败:', error);
toast({
variant: "destructive",
title: "删除失败",
description: error instanceof Error ? error.message : '未知错误',
});
}
}; };
// 保存 // 保存
@ -588,53 +561,52 @@ const CategoryManageDialog: React.FC<CategoryManageDialogProps> = ({
</Dialog> </Dialog>
{/* 删除确认对话框 */} {/* 删除确认对话框 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> <ConfirmDialog
<AlertDialogContent> open={deleteDialogOpen}
<AlertDialogHeader> onOpenChange={setDeleteDialogOpen}
<AlertDialogTitle></AlertDialogTitle> title="确认删除分类"
<AlertDialogDescription asChild> description="您确定要删除以下分类吗?此操作无法撤销。"
<div className="space-y-3"> item={deleteRecord}
<p></p> onConfirm={confirmDelete}
{deleteRecord && ( onSuccess={() => {
<div className="rounded-md border p-3 space-y-2 bg-muted/50"> toast({
<div className="flex items-center gap-2"> title: "删除成功",
<span className="text-sm font-medium text-muted-foreground">:</span> description: `分类 "${deleteRecord?.name}" 已删除`,
<span className="font-medium">{deleteRecord.name}</span> });
</div> setDeleteRecord(null);
<div className="flex items-center gap-2"> loadCategories();
<span className="text-sm font-medium text-muted-foreground">:</span> onSuccess?.();
<code className="text-xs bg-background px-2 py-1 rounded"> }}
{deleteRecord.code} variant="destructive"
</code> confirmText="确认删除"
</div> >
{deleteRecord.icon && ( {deleteRecord && (
<div className="flex items-center gap-2"> <div className="rounded-md border p-3 space-y-2 bg-muted/50">
<span className="text-sm font-medium text-muted-foreground">:</span> <div className="flex items-center gap-2">
<DynamicIcon name={deleteRecord.icon} className="h-4 w-4" /> <span className="text-sm font-medium text-muted-foreground">:</span>
</div> <span className="font-medium">{deleteRecord.name}</span>
)} </div>
{deleteRecord.description && ( <div className="flex items-center gap-2">
<div className="flex items-start gap-2"> <span className="text-sm font-medium text-muted-foreground">:</span>
<span className="text-sm font-medium text-muted-foreground">:</span> <code className="text-xs bg-background px-2 py-1 rounded">
<span className="text-sm">{deleteRecord.description}</span> {deleteRecord.code}
</div> </code>
)} </div>
</div> {deleteRecord.icon && (
)} <div className="flex items-center gap-2">
<span className="text-sm font-medium text-muted-foreground">:</span>
<DynamicIcon name={deleteRecord.icon} className="h-4 w-4" />
</div> </div>
</AlertDialogDescription> )}
</AlertDialogHeader> {deleteRecord.description && (
<AlertDialogFooter> <div className="flex items-start gap-2">
<AlertDialogCancel></AlertDialogCancel> <span className="text-sm font-medium text-muted-foreground">:</span>
<AlertDialogAction <span className="text-sm">{deleteRecord.description}</span>
onClick={confirmDelete} </div>
className="bg-destructive text-destructive-foreground hover:bg-destructive/90" )}
> </div>
)}
</AlertDialogAction> </ConfirmDialog>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</> </>
); );
}; };