新增后台接口

Change-Id: Ibd8183079a77aad05b2c81658c2d6fe9b648e042
diff --git a/front/src/MigrationPage.js b/front/src/MigrationPage.js
index ed88a55..f29a534 100644
--- a/front/src/MigrationPage.js
+++ b/front/src/MigrationPage.js
@@ -1,28 +1,5 @@
-import React, { useState } from "react";
-
-// 示例迁移数据
-const migrations = [
-    {
-        migration_id: "m001",
-        user_id: "u001",
-        application_url: "http://sse.bjtu.edu.cn/media/attachments/2024/10/20241012160658.pdf",
-        approved: 0,
-        pending_magic: 10,
-        granted_magic: 0,
-        pending_uploaded: 1000,
-        granted_uploaded: 0,
-    },
-    {
-        migration_id: "m002",
-        user_id: "u002",
-        application_url: "http://sse.bjtu.edu.cn/media/attachments/2024/10/20241012160658.pdf",
-        approved: 1,
-        pending_magic: 20,
-        granted_magic: 20,
-        pending_uploaded: 2000,
-        granted_uploaded: 2000,
-    },
-];
+import React, { useState, useEffect } from "react";
+import { API_BASE_URL } from "./config";
 
 // 简单PDF预览组件
 function FileViewer({ url }) {
@@ -43,14 +20,76 @@
 }
 
 export default function MigrationPage() {
-    const [selectedId, setSelectedId] = useState(migrations[0].migration_id);
-    const selectedMigration = migrations.find(m => m.migration_id === selectedId);
+    const [migrations, setMigrations] = useState([]);
+    const [selectedId, setSelectedId] = useState(null);
+    const [loading, setLoading] = useState(true);
+    const [error, setError] = useState(null);
 
-    const handleApprove = () => {
-        alert("已通过迁移(示例,无实际状态变更)");
+    // Helper to load migrations list
+    const fetchMigrations = async () => {
+        setLoading(true);
+        try {
+            const res = await fetch(`${API_BASE_URL}/api/migrations`);
+            if (!res.ok) throw new Error(`请求失败,状态码 ${res.status}`);
+            const data = await res.json();
+            const formatted = data.map(item => ({
+                migration_id: item.profileurl,
+                user_id: item.user.userid,
+                application_url: item.applicationurl,
+                pending_magic: Number(item.magictogive),
+                granted_magic: Number(item.magicgived),
+                pending_uploaded: Number(item.uploadtogive),
+                granted_uploaded: Number(item.uploadgived),
+                approved: item.exampass ? 1 : 0
+            }));
+            setMigrations(formatted);
+            if (formatted.length > 0) setSelectedId(formatted[0].migration_id);
+            setError(null);
+        } catch (err) {
+            setError(err.message);
+        } finally {
+            setLoading(false);
+        }
     };
-    const handleReject = () => {
-        alert("已拒绝迁移(示例,无实际状态变更)");
+
+    useEffect(() => {
+        fetchMigrations();
+    }, []);
+
+    if (loading) return <div>加载中...</div>;
+    if (error) return <div>加载失败:{error}</div>;
+
+    const selectedMigration = migrations.find(m => m.migration_id === selectedId) || {};
+
+    // Approve selected migration and refresh
+    const handleApprove = async () => {
+        try {
+            const res = await fetch(`${API_BASE_URL}/api/migrations-approve`, {
+                method: "POST",
+                headers: { "Content-Type": "application/json" },
+                body: JSON.stringify({ migration_id: selectedMigration.migration_id })
+            });
+            if (!res.ok) throw new Error(`请求失败,状态码 ${res.status}`);
+            alert("已通过迁移");
+            await fetchMigrations();
+        } catch (err) {
+            alert(`操作失败:${err.message}`);
+        }
+    };
+    // Reject selected migration and refresh
+    const handleReject = async () => {
+        try {
+            const res = await fetch(`${API_BASE_URL}/api/migrations-reject`, {
+                method: "POST",
+                headers: { "Content-Type": "application/json" },
+                body: JSON.stringify({ migration_id: selectedMigration.migration_id })
+            });
+            if (!res.ok) throw new Error(`请求失败,状态码 ${res.status}`);
+            alert("已拒绝迁移");
+            await fetchMigrations();
+        } catch (err) {
+            alert(`操作失败:${err.message}`);
+        }
     };
 
     return (