| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import React, { useState } from 'react';
- import { createRoot } from 'react-dom/client';
- import { Button, Space, Alert, Spin, Typography, Table } from 'antd';
- import axios from 'axios';
- import dayjs from 'dayjs';
- import {
- QueryClient,
- QueryClientProvider,
- useQuery,
- } from '@tanstack/react-query';
- const { Title } = Typography;
- // 创建QueryClient实例
- const queryClient = new QueryClient();
- interface MigrationResponse {
- success: boolean;
- error?: string;
- failedResult?: any;
- }
- interface MigrationHistory {
- id: string;
- name: string;
- status: string;
- timestamp: string;
- batch: string;
- }
- const MigrationsApp: React.FC = () => {
- const [loading, setLoading] = useState(false);
- const [migrationResult, setMigrationResult] = useState<MigrationResponse | null>(null);
- const { data: historyData, isLoading: isHistoryLoading, error: historyError } = useQuery({
- queryKey: ['migrations-history'],
- queryFn: async () => {
- const response = await axios.get('/api/migrations/history');
- return response.data.history;
- }
- });
- const runMigrations = async () => {
- try {
- setLoading(true);
- setMigrationResult(null);
-
- const response = await axios.get('/api/migrations');
- setMigrationResult(response.data);
- } catch (error: any) {
- setMigrationResult({
- success: false,
- error: error.response?.data?.error || '数据库迁移失败',
- failedResult: error.response?.data?.failedResult
- });
- } finally {
- setLoading(false);
- }
- };
- const columns = [
- {
- title: '迁移名称',
- dataIndex: 'name',
- key: 'name',
- sorter: (a: MigrationHistory, b: MigrationHistory) => a.name.localeCompare(b.name),
- },
- {
- title: '批次',
- dataIndex: 'batch',
- key: 'batch',
- },
- {
- title: '状态',
- dataIndex: 'status',
- key: 'status',
- render: (status: string) => (
- <span style={{ color: status === 'completed' ? 'green' : 'red' }}>
- {status === 'completed' ? '已完成' : '失败'}
- </span>
- )
- },
- {
- title: '时间',
- dataIndex: 'migration_time',
- key: 'migration_time',
- render: (migration_time: string) => dayjs(migration_time).format('YYYY-MM-DD HH:mm:ss')
- },
- ];
- return (
- <div className="p-4">
- <Title level={3}>数据库迁移管理</Title>
-
- <Space direction="vertical" size="middle" style={{ width: '100%' }}>
- <Button
- type="primary"
- onClick={runMigrations}
- loading={loading}
- disabled={loading}
- >
- 执行迁移
- </Button>
- {loading && <Spin tip="迁移执行中..." />}
- {migrationResult && (
- migrationResult.success ? (
- <Alert
- message="迁移成功"
- type="success"
- showIcon
- />
- ) : (
- <Alert
- message="迁移失败"
- description={
- <>
- <p>{migrationResult.error}</p>
- {migrationResult.failedResult && (
- <pre style={{ marginTop: 10 }}>
- {JSON.stringify(migrationResult.failedResult, null, 2)}
- </pre>
- )}
- </>
- }
- type="error"
- showIcon
- />
- )
- )}
- <Title level={4}>迁移历史记录</Title>
-
- {isHistoryLoading ? (
- <Spin tip="加载历史记录中..." />
- ) : historyError ? (
- <Alert
- message="加载历史记录失败"
- description={historyError.message}
- type="error"
- showIcon
- />
- ) : (
- <Table
- columns={columns}
- dataSource={historyData}
- rowKey="id"
- pagination={{
- pageSize: 10,
- showSizeChanger: true,
- pageSizeOptions: ['10', '20', '50', '100'],
- showTotal: (total) => `共 ${total} 条记录`,
- }}
- bordered
- className="migration-history-table"
- style={{ marginTop: 16 }}
- />
- )}
- </Space>
- </div>
- );
- };
- // 渲染应用
- const root = createRoot(document.getElementById('root') as HTMLElement);
- root.render(
- <QueryClientProvider client={queryClient}>
- <MigrationsApp />
- </QueryClientProvider>
- );
|