新增求种和个人中心接口

Change-Id: Ibf3eef5b91a45a0ccf7b99d08afa29960884a8cf
diff --git a/front/src/BegSeedPage.js b/front/src/BegSeedPage.js
index a456147..0854535 100644
--- a/front/src/BegSeedPage.js
+++ b/front/src/BegSeedPage.js
@@ -1,46 +1,85 @@
-import React, { useState } from "react";
+import React, { useState, useEffect } from "react";
 import HelpIcon from "@mui/icons-material/Help";
 import { useNavigate } from "react-router-dom";
-
-// 初始硬编码数据
-const initialBegSeedList = [
-    {
-        beg_id: "beg001",
-        info: "求《三体》高清资源",
-        beg_count: 5,
-        reward_magic: 100,
-        deadline: "2025-06-10T23:59:59",
-        has_match: 0,
-    },
-    {
-        beg_id: "beg002",
-        info: "求《灌篮高手》国语配音版",
-        beg_count: 3,
-        reward_magic: 50,
-        deadline: "2024-05-01T23:59:59",
-        has_match: 1,
-    },
-    {
-        beg_id: "beg003",
-        info: "求《黑暗之魂3》PC版种子",
-        beg_count: 2,
-        reward_magic: 80,
-        deadline: "2024-04-01T23:59:59",
-        has_match: 0,
-    },
-];
+import { API_BASE_URL } from "./config";
 
 export default function BegSeedPage() {
     const navigate = useNavigate();
     const now = new Date();
-    const [begSeedList, setBegSeedList] = useState(initialBegSeedList);
+    const [begSeedList, setBegSeedList] = useState([]);
+    const [loading, setLoading] = useState(true);
+    const [error, setError] = useState(null);
     const [showForm, setShowForm] = useState(false);
+    const [refreshKey, setRefreshKey] = useState(0); // 用于强制重新渲染
     const [formData, setFormData] = useState({
         info: "",
         reward_magic: "",
         deadline: "",
     });
 
+    // 从后端获取求种列表
+    const fetchBegSeedList = async () => {
+        setLoading(true);
+        try {
+            const response = await fetch(`${API_BASE_URL}/api/begseed-list`);
+            if (!response.ok) {
+                throw new Error(`请求失败,状态码: ${response.status}`);
+            }
+            const data = await response.json();
+            console.log("获取到的求种列表数据:", data);
+            
+            // 格式化数据以匹配前端期望的格式
+            const formattedData = data.map(item => ({
+                beg_id: item.beg_id || item.begid || item.id,
+                info: item.info || item.description || item.content,
+                beg_count: item.beg_count || item.begCount || 1,
+                reward_magic: item.reward_magic || item.rewardMagic || item.magic,
+                deadline: item.deadline || item.endtime,
+                has_match: item.has_match || item.hasMatch || item.completed || 0,
+            }));
+            
+            setBegSeedList(formattedData);
+            setError(null);
+        } catch (err) {
+            console.error('获取求种列表失败:', err);
+            setError(err.message);
+            // 如果API调用失败,使用默认数据
+            setBegSeedList([
+                {
+                    beg_id: "beg001",
+                    info: "求《三体》高清资源",
+                    beg_count: 5,
+                    reward_magic: 100,
+                    deadline: "2025-06-10T23:59:59",
+                    has_match: 0,
+                },
+                {
+                    beg_id: "beg002",
+                    info: "求《灌篮高手》国语配音版",
+                    beg_count: 3,
+                    reward_magic: 50,
+                    deadline: "2024-05-01T23:59:59",
+                    has_match: 1,
+                },
+                {
+                    beg_id: "beg003",
+                    info: "求《黑暗之魂3》PC版种子",
+                    beg_count: 2,
+                    reward_magic: 80,
+                    deadline: "2024-04-01T23:59:59",
+                    has_match: 0,
+                },
+            ]);
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    // 组件挂载时获取数据
+    useEffect(() => {
+        fetchBegSeedList();
+    }, []);
+
     // 表单输入处理
     const handleFormChange = (e) => {
         const { name, value } = e.target;
@@ -51,23 +90,66 @@
     };
 
     // 提交新求种任务
-    const handleSubmit = (e) => {
+    const handleSubmit = async (e) => {
         e.preventDefault();
-        const newBegId = "beg" + Math.floor(Math.random() * 10000);
-        setBegSeedList([
-            {
-                beg_id: newBegId,
-                info: formData.info,
-                beg_count: 1,
-                reward_magic: Number(formData.reward_magic),
-                deadline: formData.deadline,
-                has_match: 0,
-            },
-            ...begSeedList,
-        ]);
-        setShowForm(false);
-        setFormData({ info: "", reward_magic: "", deadline: "" });
-        alert("发布成功(前端演示)");
+        
+        // 获取用户ID
+        const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
+        const userId = match ? match[2] : null;
+        
+        if (!userId) {
+            alert("请先登录后再发布求种任务");
+            return;
+        }
+
+        try {
+            const response = await fetch(`${API_BASE_URL}/api/create-begseed`, {
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json',
+                },
+                body: JSON.stringify({
+                    userid: userId,
+                    info: formData.info,
+                    reward_magic: Number(formData.reward_magic),
+                    deadline: formData.deadline,
+                }),
+            });
+
+            if (response.ok) {
+                // 成功创建,重新获取列表并强制重新渲染
+                setLoading(true); // 显示加载状态
+                await fetchBegSeedList();
+                setShowForm(false);
+                setFormData({ info: "", reward_magic: "", deadline: "" });
+                setRefreshKey(prev => prev + 1); // 强制重新渲染
+                alert("发布成功!");
+            } else {
+                const errorData = await response.json();
+                alert(`发布失败: ${errorData.message || '未知错误'}`);
+            }
+        } catch (err) {
+            console.error('发布求种任务失败:', err);
+            // 如果后端调用失败,则使用前端演示逻辑
+            // setLoading(true); // 显示加载状态
+            // const newBegId = "beg" + Math.floor(Math.random() * 10000);
+            // setBegSeedList([
+            //     {
+            //         beg_id: newBegId,
+            //         info: formData.info,
+            //         beg_count: 1,
+            //         reward_magic: Number(formData.reward_magic),
+            //         deadline: formData.deadline,
+            //         has_match: 0,
+            //     },
+            //     ...begSeedList,
+            // ]);
+            // setLoading(false); // 隐藏加载状态
+            // setShowForm(false);
+            // setFormData({ info: "", reward_magic: "", deadline: "" });
+            // setRefreshKey(prev => prev + 1); // 强制重新渲染
+            // alert("发布成功(前端演示)");
+        }
     };
 
     return (
@@ -76,19 +158,42 @@
                 <HelpIcon style={{ verticalAlign: "middle", marginRight: 8 }} />
                 求种列表
             </h1>
+            
+            {/* 加载状态 */}
+            {loading && (
+                <div style={{ textAlign: "center", margin: "40px 0", color: "#666" }}>
+                    正在加载求种列表...
+                </div>
+            )}
+            
+            {/* 错误状态 */}
+            {error && (
+                <div style={{ 
+                    textAlign: "center", 
+                    margin: "20px 0", 
+                    padding: "10px", 
+                    background: "#ffebee", 
+                    color: "#c62828", 
+                    borderRadius: "4px" 
+                }}>
+                    加载失败: {error} (已显示默认数据)
+                </div>
+            )}
+            
             <div style={{ margin: "0 0 32px 0", textAlign: "center" }}>
                 <button
                     onClick={() => setShowForm(true)}
+                    disabled={loading}
                     style={{
                         fontSize: 18,
                         padding: "12px 36px",
-                        background: "linear-gradient(90deg, #42a5f5 0%, #1976d2 100%)",
+                        background: loading ? "#ccc" : "linear-gradient(90deg, #42a5f5 0%, #1976d2 100%)",
                         color: "#fff",
                         border: "none",
                         borderRadius: 8,
                         fontWeight: 600,
                         boxShadow: "0 2px 8px #b2d8ea",
-                        cursor: "pointer",
+                        cursor: loading ? "not-allowed" : "pointer",
                         transition: "background 0.2s",
                     }}
                 >
@@ -195,7 +300,7 @@
                     </form>
                 </div>
             )}
-            <div style={{ display: "flex", flexWrap: "wrap", gap: 24 }}>
+            <div key={refreshKey} style={{ display: "flex", flexWrap: "wrap", gap: 24 }}>
                 {begSeedList.map((beg) => {
                     const isExpired =
                         new Date(beg.deadline) < now || beg.has_match === 1;