修改前端页面

Change-Id: I344849fc3dfca5725e0ef2a107e2c89a14fce8da
diff --git a/front/src/UserProfile.js b/front/src/UserProfile.js
index eed84da..fb44b43 100644
--- a/front/src/UserProfile.js
+++ b/front/src/UserProfile.js
@@ -51,9 +51,11 @@
 

   // 账号迁移相关

   const [migrationOpen, setMigrationOpen] = useState(false);

+  const [migrationUpload, setMigrationUpload] = useState('');

   const [migrationEmail, setMigrationEmail] = useState('');

   const [migrationPassword, setMigrationPassword] = useState('');

   const [migrationStatus, setMigrationStatus] = useState('');

+

   // 兑换结果计算

   React.useEffect(() => {

     if (!exchangeMagic || isNaN(exchangeMagic)) {

@@ -66,17 +68,13 @@
   // 获取用户信息

   useEffect(() => {

     const fetchUserInfo = async () => {

-      // 假设userid存储在localStorage或其他地方

-      // const userid = localStorage.getItem("userid");

-      // const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid

       const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

-    const userid = match ? match[2] : null;

+      const userid = match ? match[2] : null;

       if (!userid) return;

       try {

         const res = await fetch(`${API_BASE_URL}/api/user-profile?userid=${userid}`);

         if (res.ok) {

           const data = await res.json();

-          // console.log("获取用户信息:", data);

           setUserInfo(data);

           setTempUserInfo(data);

         }

@@ -87,13 +85,10 @@
     fetchUserInfo();

   }, []);

 

-  // 获取上传种子

   useEffect(() => {

     const fetchUserSeeds = async () => {

-      // const userid = localStorage.getItem("userid");

-      // const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid

       const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

-    const userid = match ? match[2] : null;

+      const userid = match ? match[2] : null;

       if (!userid) return;

       try {

         const res = await fetch(`${API_BASE_URL}/api/user-seeds?userid=${userid}`);

@@ -107,7 +102,7 @@
     };

     fetchUserSeeds();

   }, []);

-  // 获取收藏种子

+

   useEffect(() => {

     const fetchUserFavorites = async () => {

       const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

@@ -126,7 +121,7 @@
     };

     fetchUserFavorites();

   }, []);

-  // 获取活跃度

+

   useEffect(() => {

     const fetchUserStats = async () => {

       const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

@@ -150,15 +145,13 @@
   };

 

   const handleSave = async () => {

-    if (tempUserInfo.gender === "男"){

+    if (tempUserInfo.gender === "男") {

       tempUserInfo.gender = "m";

-    }else if (tempUserInfo.gender === "女"){

+    } else if (tempUserInfo.gender === "女") {

       tempUserInfo.gender = "f";

     }

     setUserInfo({ ...tempUserInfo });

-    // 获取userid

-    // const userid = localStorage.getItem("userid");

-    // const userid = "550e8400-e29b-41d4-a716-446655440000"; // 示例userid

+

     const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

     const userid = match ? match[2] : null;

     try {

@@ -205,7 +198,7 @@
       return;

     }

     try {

-        const res = await fetch(`${API_BASE_URL}/api/invite`, {

+      const res = await fetch(`${API_BASE_URL}/api/invite`, {

         method: 'POST',

         headers: { 'Content-Type': 'application/json' },

         body: JSON.stringify({ userid, invite_email: inviteEmail }),

@@ -226,7 +219,9 @@
       console.error("邀请失败", err);

       setInviteStatus("邀请失败,请检查网络");

     }

-  };  // 兑换

+  };

+

+  // 兑换魔力值

   const handleExchange = async () => {

     const magic = Number(exchangeMagic);

     if (!magic || isNaN(magic) || magic <= 0) return;

@@ -234,14 +229,14 @@
       alert("魔力值不足!");

       return;

     }

-    

+

     // 检查兑换结果是否为整数

     const calculatedExchangeResult = magic / exchangeRate[exchangeType];

     if (!Number.isInteger(calculatedExchangeResult)) {

       alert("兑换结果必须为整数,请调整魔力值!");

       return;

     }

-    

+

     // 获取userid

     const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

     const userid = match ? match[2] : null;

@@ -256,9 +251,9 @@
       const res = await fetch(`${API_BASE_URL}/api/exchange`, {

         method: 'POST',

         headers: { 'Content-Type': 'application/json' },

-        body: JSON.stringify({ 

-          userid, 

-          magic, 

+        body: JSON.stringify({

+          userid,

+          magic,

           exchangeType,

           exchangeResult: calculatedExchangeResult

         }),

@@ -300,7 +295,7 @@
         method: 'POST',

         headers: { 'Content-Type': 'application/json' },

         body: JSON.stringify({ userid, seedid }),

-      });      if (res.ok) {

+      }); if (res.ok) {

         setUserFavorites(userFavorites.filter((s) => (s.seedid || s.seed_id) !== seedid));

         alert('已取消收藏');

       } else {

@@ -315,14 +310,13 @@
   // 申诉提交逻辑

   const handleAppealSubmit = async () => {

     if (!appealTitle || !appealFile) return;

-    // 获取userid

     const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

     const userid = match ? match[2] : null;

     if (!userid) {

       alert('未获取到用户ID');

       return;

     }

-    // 构建表单数据

+

     const formData = new FormData();

     formData.append('userid', userid);

     formData.append('content', appealTitle);

@@ -346,37 +340,42 @@
       alert('申诉失败,请检查网络');

     }

   };

-  // 账号迁移提交逻辑

+

+  // 账号迁移

   const handleMigrationSubmit = async () => {

     if (!appealFile) {

       setMigrationStatus('请选择PDF文件');

       return;

     }

-    

-    // 获取当前用户ID

+    if (!migrationUpload || isNaN(migrationUpload) || Number(migrationUpload) <= 0) {

+      setMigrationStatus('请输入有效的待发放上传量');

+      return;

+    }

+

     const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

     const currentUserId = match ? match[2] : null;

     if (!currentUserId) {

       setMigrationStatus('未获取到当前用户ID');

       return;

     }

-    

+

     try {

-      // 构建表单数据

       const formData = new FormData();

       formData.append('userid', currentUserId);

       formData.append('file', appealFile);

-      

+      formData.append('uploadtogive', migrationUpload);

+

       const res = await fetch(`${API_BASE_URL}/api/migrate-account`, {

         method: 'POST',

         body: formData,

       });

-      

+

       if (res.ok) {

         setMigrationStatus('账号迁移申请已提交,请等待管理员审核');

         setTimeout(() => {

           setMigrationOpen(false);

           setAppealFile(null);

+          setMigrationUpload('');

           setMigrationStatus('');

         }, 2000);

       } else {

@@ -682,7 +681,7 @@
                     variant="contained"

                     color="error"

                     size="small"

-                    sx={{ marginLeft: 2, borderRadius: 1, minWidth: 60 }}                    onClick={async e => {

+                    sx={{ marginLeft: 2, borderRadius: 1, minWidth: 60 }} onClick={async e => {

                       e.stopPropagation();

                       const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');

                       const userid = match ? match[2] : null;

@@ -734,39 +733,40 @@
         }}>

           {userFavorites.length === 0 ? (

             <div style={{ color: '#b2b2b2', fontSize: 18, textAlign: 'center' }}>(暂无收藏种子)</div>

-          ) : (            <ul style={{ listStyle: 'none', margin: 0, padding: 0 }}>

-              {userFavorites.map((seed, idx) => (

-                <li

-                  key={seed.seedid || idx}

-                  style={{

-                    display: 'flex',

-                    alignItems: 'center',

-                    padding: '12px 0',

-                    borderBottom: idx === userFavorites.length - 1 ? 'none' : '1px solid #e0e7ff',

-                    cursor: 'pointer',

-                    transition: 'background 0.15s'

-                  }}                  onClick={e => {                    if (e.target.classList.contains('remove-favorite-btn')) return;

-                    navigate(`/torrent/${seed.seedid || seed.seed_id}`);

+          ) : (<ul style={{ listStyle: 'none', margin: 0, padding: 0 }}>

+            {userFavorites.map((seed, idx) => (

+              <li

+                key={seed.seedid || idx}

+                style={{

+                  display: 'flex',

+                  alignItems: 'center',

+                  padding: '12px 0',

+                  borderBottom: idx === userFavorites.length - 1 ? 'none' : '1px solid #e0e7ff',

+                  cursor: 'pointer',

+                  transition: 'background 0.15s'

+                }} onClick={e => {

+                  if (e.target.classList.contains('remove-favorite-btn')) return;

+                  navigate(`/torrent/${seed.seedid || seed.seed_id}`);

+                }}

+                onMouseOver={e => e.currentTarget.style.background = '#f3f6ff'}

+                onMouseOut={e => e.currentTarget.style.background = ''}

+              >

+                <span style={{ flex: 2, fontWeight: 500, color: '#1a237e', textDecoration: 'underline', cursor: 'pointer' }}>{seed.seed.title}</span>

+                <span style={{ flex: 1, color: '#5c6bc0' }}>{seed.seed.tags}</span>

+                <span style={{ flex: 1, color: '#ff9800', textAlign: 'right' }}>人气: {seed.seed.downloadtimes}</span>

+                <Button

+                  className="remove-favorite-btn"

+                  variant="contained"

+                  color="warning"

+                  size="small"

+                  sx={{ marginLeft: 2, borderRadius: 1, minWidth: 80 }} onClick={e => {

+                    e.stopPropagation();

+                    handleRemoveFavorite(seed.seedid || seed.seed_id);

                   }}

-                  onMouseOver={e => e.currentTarget.style.background = '#f3f6ff'}

-                  onMouseOut={e => e.currentTarget.style.background = ''}

-                >

-                  <span style={{ flex: 2, fontWeight: 500, color: '#1a237e', textDecoration: 'underline', cursor: 'pointer' }}>{seed.seed.title}</span>

-                  <span style={{ flex: 1, color: '#5c6bc0' }}>{seed.seed.tags}</span>

-                  <span style={{ flex: 1, color: '#ff9800', textAlign: 'right' }}>人气: {seed.seed.downloadtimes}</span>

-                  <Button

-                    className="remove-favorite-btn"

-                    variant="contained"

-                    color="warning"

-                    size="small"

-                    sx={{ marginLeft: 2, borderRadius: 1, minWidth: 80 }}                    onClick={e => {

-                      e.stopPropagation();

-                      handleRemoveFavorite(seed.seedid || seed.seed_id);

-                    }}

-                  >取消收藏</Button>

-                </li>

-              ))}

-            </ul>

+                >取消收藏</Button>

+              </li>

+            ))}

+          </ul>

           )}

         </div>

       </div>

@@ -807,12 +807,24 @@
           <Button onClick={handleAppealSubmit} variant="contained" color="primary" disabled={!appealTitle || !appealFile}>提交</Button>

           <Button onClick={() => setAppealOpen(false)} variant="outlined">取消</Button>

         </DialogActions>

-      </Dialog>      {/* 账号迁移弹窗 */}

+      </Dialog>

+      {/* 账号迁移弹窗 */}

       <Dialog open={migrationOpen} onClose={() => setMigrationOpen(false)}>

         <DialogTitle>账号迁移</DialogTitle>

         <DialogContent>

           <div style={{ marginBottom: 16 }}>

-          </div>          <div>

+            <TextField

+              label="待发放上传量"

+              type="number"

+              fullWidth

+              value={migrationUpload}

+              onChange={e => setMigrationUpload(e.target.value)}

+              size="small"

+              inputProps={{ min: 1 }}

+              style={{ marginBottom: 18 }}

+            />

+          </div>

+          <div>

             <input

               type="file"

               accept=".pdf"