blob: 1e5b2e8b51fb48f0e62f3820d306238e8f752d8a [file] [log] [blame]
Akane12173a7bb972025-06-01 01:05:27 +08001import React, { useState, useEffect } from 'react';
2import { useNavigate, useLocation } from 'react-router-dom';
3import { generateInviteCode, getUserInviteCodes, exchangeUpload, getUserInfo } from '../../api/personal';
4import './personalSubpage.css';
5
6const Exchange = () => {
7 const navigate = useNavigate();
8 const location = useLocation();
9 const [inviteCodes, setInviteCodes] = useState([]);
10 const [userInfo, setUserInfo] = useState(null);
11 const [magicPoints, setMagicPoints] = useState('0');
12 const [loading, setLoading] = useState(false);
13 const [error, setError] = useState(null);
14
15 // 获取用户信息和邀请码列表
16 useEffect(() => {
17 const fetchData = async () => {
18 try {
19 setLoading(true);
20 const [userData, codes] = await Promise.all([
21 getUserInfo(),
22 getUserInviteCodes()
23 ]);
24 setUserInfo(userData);
25 setInviteCodes(codes);
26 } catch (err) {
27 setError(err.message);
28 } finally {
29 setLoading(false);
30 }
31 };
32 fetchData();
33 }, []);
34
35 // 生成邀请码
36 const handleGenerateInviteCode = async () => {
37 try {
38 setLoading(true);
39 const newCode = await generateInviteCode();
40 setInviteCodes([...inviteCodes, newCode]);
41 // 刷新用户信息
42 const updatedUser = await getUserInfo();
43 setUserInfo(updatedUser);
44 } catch (err) {
45 setError(err.message);
46 } finally {
47 setLoading(false);
48 }
49 };
50
51 const handleExchangeUpload = async () => {
52 const points = Number(magicPoints);
53 if (!points || points <= 0) {
54 setError('请输入有效的魔力值');
55 return;
56 }
57 try {
58 setLoading(true);
59 await exchangeUpload(points);
60 // 刷新用户信息
61 const updatedUser = await getUserInfo();
62 setUserInfo(updatedUser);
63 setMagicPoints('0');
64 setError(null);
65 } catch (err) {
66 setError(err.message);
67 } finally {
68 setLoading(false);
69 }
70 };
71
72 const handleBack = () => {
73 // 返回个人中心,并携带来源标记
74 navigate('/personal', {
75 state: {
76 fromSubpage: true, // 标记来自子页面
77 dashboardTab: location.state?.dashboardTab // 保留Dashboard的标签页状态
78 },
79 replace: true // 替换当前历史记录
80 });
81 };
82
83 if (loading) {
84 return <div className="subpage-container">加载中...</div>;
85 }
86
87 if (error) {
88 return (
89 <div className="subpage-container">
90 <button className="back-button" onClick={handleBack}>
91 返回个人中心
92 </button>
93 <div className="error">错误: {error}</div>
94 </div>
95 );
96 }
97
98 return (
99 <div className="subpage-container">
100 <button className="back-button" onClick={handleBack}>
101 返回个人中心
102 </button>
103
104 <h2 className="page-title">兑换区</h2>
105
106 <div className="exchange-section">
107 <h3>当前魔力值: {userInfo?.magicPoints || 0}</h3>
108
109 <div className="exchange-card">
110 <h4>兑换邀请码</h4>
111 <p>消耗10魔力值兑换一个邀请码</p>
112 <button
113 className="exchange-btn"
114 onClick={handleGenerateInviteCode}
115 disabled={!userInfo || userInfo.magicPoints < 10}
116 >
117 兑换邀请码
118 </button>
119 </div>
120
121 <div className="exchange-card">
122 <h4>兑换上传量</h4>
123 <p>1魔力值 = 1GB上传量</p>
124 <div className="exchange-input-group">
125 <input
126 type="number"
127 value={magicPoints}
128 onChange={(e) => {
129 // 允许空字符串或有效数字
130 const value = e.target.value;
131 if (value === '' || !isNaN(value)) {
132 setMagicPoints(value);
133 }
134 }}
135 min="1"
136 max={userInfo?.magicPoints || 0}
137 placeholder="输入要兑换的魔力值"
138 />
139
140 <button
141 className="exchange-btn"
142 onClick={handleExchangeUpload}
143 disabled={
144 !magicPoints ||
145 Number(magicPoints) <= 0 ||
146 !userInfo ||
147 Number(magicPoints) > userInfo.magicPoints
148 }
149 >
150 兑换上传量
151 </button>
152 </div>
153 </div>
154
155 {inviteCodes.length > 0 && (
156 <div className="invite-code-list">
157 <h4>我的邀请码</h4>
158 <ul>
159 {inviteCodes.map((code, index) => (
160 <li key={index}>
161 <span className="code">{code.code}</span>
162 <span className={`status ${code.isUsed ? 'used' : 'available'}`}>
163 {code.isUsed ? '已使用' : '可用'}
164 </span>
165 </li>
166 ))}
167 </ul>
168 </div>
169 )}
170 </div>
171 </div>
172 );
173};
174
175export default Exchange;