169 lines
6.4 KiB
TypeScript
169 lines
6.4 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
import { PageHeader } from '@/components/layout/page-header';
|
||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||
import { apiClient } from '@/lib/api/client';
|
||
import { formatDateTime } from '@/lib/utils/date';
|
||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||
import { Button } from '@/components/ui/button';
|
||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
|
||
import { Skeleton } from '@/components/ui/skeleton';
|
||
import { useToast } from '@/lib/hooks/use-toast';
|
||
import { Play, CheckCircle, AlertCircle, Loader2 } from 'lucide-react';
|
||
|
||
interface InitializationStatus {
|
||
initialized: boolean;
|
||
initializedAt: string | null;
|
||
initializedBy: string | null;
|
||
distributionPoolBalance: string;
|
||
blackHoleBalance: string;
|
||
circulationPoolBalance: string;
|
||
}
|
||
|
||
export default function InitializationPage() {
|
||
const queryClient = useQueryClient();
|
||
const { toast } = useToast();
|
||
const [showConfirm, setShowConfirm] = useState(false);
|
||
|
||
const { data: status, isLoading } = useQuery({
|
||
queryKey: ['initialization', 'status'],
|
||
queryFn: async () => {
|
||
const response = await apiClient.get('/initialization/status');
|
||
return response.data.data as InitializationStatus;
|
||
},
|
||
});
|
||
|
||
const initializeMutation = useMutation({
|
||
mutationFn: async () => {
|
||
const response = await apiClient.post('/initialization/initialize');
|
||
return response.data;
|
||
},
|
||
onSuccess: () => {
|
||
queryClient.invalidateQueries({ queryKey: ['initialization', 'status'] });
|
||
toast({ title: '初始化成功', variant: 'success' as any });
|
||
setShowConfirm(false);
|
||
},
|
||
onError: () => {
|
||
toast({ title: '初始化失败', variant: 'destructive' });
|
||
},
|
||
});
|
||
|
||
const handleInitialize = () => {
|
||
initializeMutation.mutate();
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<PageHeader title="系统初始化" description="初始化挖矿系统的基础数据" />
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg">初始化状态</CardTitle>
|
||
<CardDescription>查看系统是否已完成初始化</CardDescription>
|
||
</CardHeader>
|
||
<CardContent>
|
||
{isLoading ? (
|
||
<Skeleton className="h-24 w-full" />
|
||
) : (
|
||
<div className="space-y-4">
|
||
<div className="flex items-center gap-4">
|
||
{status?.initialized ? (
|
||
<>
|
||
<CheckCircle className="h-8 w-8 text-green-500" />
|
||
<div>
|
||
<p className="font-medium text-green-600">系统已初始化</p>
|
||
<p className="text-sm text-muted-foreground">
|
||
初始化时间: {formatDateTime(status.initializedAt)}
|
||
</p>
|
||
<p className="text-sm text-muted-foreground">操作人: {status.initializedBy}</p>
|
||
</div>
|
||
</>
|
||
) : (
|
||
<>
|
||
<AlertCircle className="h-8 w-8 text-yellow-500" />
|
||
<div>
|
||
<p className="font-medium text-yellow-600">系统未初始化</p>
|
||
<p className="text-sm text-muted-foreground">请点击下方按钮进行系统初始化</p>
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
|
||
{!status?.initialized && (
|
||
<Button onClick={() => setShowConfirm(true)} className="mt-4">
|
||
<Play className="h-4 w-4 mr-2" />
|
||
开始初始化
|
||
</Button>
|
||
)}
|
||
</div>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{status?.initialized && (
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg">系统账户余额</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="grid grid-cols-3 gap-6">
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">分配池</p>
|
||
<p className="text-xl font-bold font-mono">{status.distributionPoolBalance}</p>
|
||
</div>
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">黑洞</p>
|
||
<p className="text-xl font-bold font-mono">{status.blackHoleBalance}</p>
|
||
</div>
|
||
<div>
|
||
<p className="text-sm text-muted-foreground">流通池</p>
|
||
<p className="text-xl font-bold font-mono">{status.circulationPoolBalance}</p>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
)}
|
||
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg">初始化说明</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="prose prose-sm max-w-none">
|
||
<p>系统初始化将执行以下操作:</p>
|
||
<ol className="list-decimal list-inside space-y-2 text-muted-foreground">
|
||
<li>创建分配池账户,初始余额为 2 亿积分股</li>
|
||
<li>创建黑洞账户,初始余额为 0</li>
|
||
<li>创建流通池账户,初始余额为 0</li>
|
||
<li>创建系统运营账户 (12% 分配比例)</li>
|
||
<li>创建系统省级账户 (1% 分配比例)</li>
|
||
<li>创建系统市级账户 (2% 分配比例)</li>
|
||
<li>初始化系统配置参数</li>
|
||
</ol>
|
||
<p className="text-yellow-600 mt-4">注意: 初始化操作只能执行一次,请谨慎操作。</p>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Dialog open={showConfirm} onOpenChange={setShowConfirm}>
|
||
<DialogContent>
|
||
<DialogHeader>
|
||
<DialogTitle>确认初始化</DialogTitle>
|
||
<DialogDescription>
|
||
系统初始化操作只能执行一次,确定要开始初始化吗?
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setShowConfirm(false)}>
|
||
取消
|
||
</Button>
|
||
<Button onClick={handleInitialize} disabled={initializeMutation.isPending}>
|
||
{initializeMutation.isPending && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||
确认初始化
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</div>
|
||
);
|
||
}
|