子仓库提交

This commit is contained in:
2025-11-10 09:19:56 +08:00
parent 62f92213f7
commit 5feb24e4e2
733 changed files with 141413 additions and 0 deletions

View File

@@ -0,0 +1,97 @@
import type { ComponentType } from "react";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { AlertCircle, CheckCircle, Clock, Info, XCircle } from "lucide-react";
import type { ExecuteResult, ExecuteResultDetail, ExecuteResultStatus } from "./types";
interface ExecuteResultDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
result: ExecuteResult | null;
}
type StatusConfig = {
icon: ComponentType<{ className?: string }>;
className: string;
label: string;
};
const statusConfig: Record<ExecuteResultStatus, StatusConfig> = {
success: {
icon: CheckCircle,
className: "text-success",
label: "成功",
},
warning: {
icon: AlertCircle,
className: "text-warning",
label: "警告",
},
error: {
icon: XCircle,
className: "text-destructive",
label: "失败",
},
info: {
icon: Info,
className: "text-info",
label: "信息",
},
};
export function ExecuteResultDialog({ open, onOpenChange, result }: ExecuteResultDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription></DialogDescription>
</DialogHeader>
{result && (
<div className="space-y-4">
<Card className={`p-4 ${result.success ? 'bg-success/10 border-success/30' : 'bg-destructive/10 border-destructive/30'}`}>
<div className="flex items-center gap-2">
<CheckCircle className={`w-5 h-5 ${result.success ? 'text-success' : 'text-destructive'}`} />
<div>
<div className="font-medium">{result.success ? '执行成功' : '执行失败'}</div>
<div className="text-sm text-muted-foreground flex items-center gap-2">
<Clock className="w-3 h-3" />
{result.executedAt}
</div>
</div>
</div>
</Card>
<div className="space-y-2">
{result.details.map((detail: ExecuteResultDetail, index) => {
const config = statusConfig[detail.status] ?? statusConfig.info;
const Icon = config.icon;
return (
<div key={index} className="flex items-start gap-3 p-3 bg-muted rounded">
<Icon className={`w-4 h-4 mt-1 ${config.className}`} />
<div className="flex-1">
<div className="flex items-center gap-2">
<span className="font-medium">{detail.step}</span>
<span className={`text-xs ${config.className}`}>{config.label}</span>
</div>
<div className="text-sm text-muted-foreground">{detail.message}</div>
</div>
</div>
);
})}
</div>
</div>
)}
<DialogFooter>
<Button onClick={() => onOpenChange(false)}></Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}