migrations_app.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import React, { useState } from 'react';
  2. import { createRoot } from 'react-dom/client';
  3. import { Button, Space, Alert, Spin, Typography } from 'antd';
  4. import axios from 'axios';
  5. import {
  6. QueryClient,
  7. QueryClientProvider,
  8. } from '@tanstack/react-query';
  9. const { Title } = Typography;
  10. // 创建QueryClient实例
  11. const queryClient = new QueryClient();
  12. interface MigrationResponse {
  13. success: boolean;
  14. error?: string;
  15. failedResult?: any;
  16. }
  17. const MigrationsApp: React.FC = () => {
  18. const [loading, setLoading] = useState(false);
  19. const [migrationResult, setMigrationResult] = useState<MigrationResponse | null>(null);
  20. const runMigrations = async () => {
  21. try {
  22. setLoading(true);
  23. setMigrationResult(null);
  24. const response = await axios.get('/api/migrations');
  25. setMigrationResult(response.data);
  26. } catch (error: any) {
  27. setMigrationResult({
  28. success: false,
  29. error: error.response?.data?.error || '数据库迁移失败',
  30. failedResult: error.response?.data?.failedResult
  31. });
  32. } finally {
  33. setLoading(false);
  34. }
  35. };
  36. return (
  37. <div className="p-4">
  38. <Title level={3}>数据库迁移管理</Title>
  39. <Space direction="vertical" size="middle" style={{ width: '100%' }}>
  40. <Button
  41. type="primary"
  42. onClick={runMigrations}
  43. loading={loading}
  44. disabled={loading}
  45. >
  46. 执行迁移
  47. </Button>
  48. {loading && <Spin tip="迁移执行中..." />}
  49. {migrationResult && (
  50. migrationResult.success ? (
  51. <Alert
  52. message="迁移成功"
  53. type="success"
  54. showIcon
  55. />
  56. ) : (
  57. <Alert
  58. message="迁移失败"
  59. description={
  60. <>
  61. <p>{migrationResult.error}</p>
  62. {migrationResult.failedResult && (
  63. <pre style={{ marginTop: 10 }}>
  64. {JSON.stringify(migrationResult.failedResult, null, 2)}
  65. </pre>
  66. )}
  67. </>
  68. }
  69. type="error"
  70. showIcon
  71. />
  72. )
  73. )}
  74. </Space>
  75. </div>
  76. );
  77. };
  78. // 渲染应用
  79. const root = createRoot(document.getElementById('root') as HTMLElement);
  80. root.render(
  81. <QueryClientProvider client={queryClient}>
  82. <MigrationsApp />
  83. </QueryClientProvider>
  84. );