| import React, { useState, useEffect } from 'react'; | |
| import { useNavigate, useLocation } from 'react-router-dom'; | |
| import { generateInviteCode, getUserInviteCodes, exchangeUpload, getUserInfo } from '../../api/personal'; | |
| import './personalSubpage.css'; | |
| const Exchange = () => { | |
| const navigate = useNavigate(); | |
| const location = useLocation(); | |
| const [inviteCodes, setInviteCodes] = useState([]); | |
| const [userInfo, setUserInfo] = useState(null); | |
| const [magicPoints, setMagicPoints] = useState('0'); | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState(null); | |
| // 获取用户信息和邀请码列表 | |
| useEffect(() => { | |
| const fetchData = async () => { | |
| try { | |
| setLoading(true); | |
| const [userData, codes] = await Promise.all([ | |
| getUserInfo(), | |
| getUserInviteCodes() | |
| ]); | |
| setUserInfo(userData); | |
| setInviteCodes(codes); | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| fetchData(); | |
| }, []); | |
| // 生成邀请码 | |
| const handleGenerateInviteCode = async () => { | |
| try { | |
| setLoading(true); | |
| const newCode = await generateInviteCode(); | |
| setInviteCodes([...inviteCodes, newCode]); | |
| // 刷新用户信息 | |
| const updatedUser = await getUserInfo(); | |
| setUserInfo(updatedUser); | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleExchangeUpload = async () => { | |
| const points = Number(magicPoints); | |
| if (!points || points <= 0) { | |
| setError('请输入有效的魔力值'); | |
| return; | |
| } | |
| try { | |
| setLoading(true); | |
| await exchangeUpload(points); | |
| // 刷新用户信息 | |
| const updatedUser = await getUserInfo(); | |
| setUserInfo(updatedUser); | |
| setMagicPoints('0'); | |
| setError(null); | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| const handleBack = () => { | |
| // 返回个人中心,并携带来源标记 | |
| navigate('/personal', { | |
| state: { | |
| fromSubpage: true, // 标记来自子页面 | |
| dashboardTab: location.state?.dashboardTab // 保留Dashboard的标签页状态 | |
| }, | |
| replace: true // 替换当前历史记录 | |
| }); | |
| }; | |
| if (loading) { | |
| return <div className="subpage-container">加载中...</div>; | |
| } | |
| if (error) { | |
| return ( | |
| <div className="subpage-container"> | |
| <button className="back-button" onClick={handleBack}> | |
| 返回个人中心 | |
| </button> | |
| <div className="error">错误: {error}</div> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className="subpage-container"> | |
| <button className="back-button" onClick={handleBack}> | |
| 返回个人中心 | |
| </button> | |
| <h2 className="page-title">兑换区</h2> | |
| <div className="exchange-section"> | |
| <h3>当前魔力值: {userInfo?.magicPoints || 0}</h3> | |
| <div className="exchange-card"> | |
| <h4>兑换邀请码</h4> | |
| <p>消耗10魔力值兑换一个邀请码</p> | |
| <button | |
| className="exchange-btn" | |
| onClick={handleGenerateInviteCode} | |
| disabled={!userInfo || userInfo.magicPoints < 10} | |
| > | |
| 兑换邀请码 | |
| </button> | |
| </div> | |
| <div className="exchange-card"> | |
| <h4>兑换上传量</h4> | |
| <p>1魔力值 = 1GB上传量</p> | |
| <div className="exchange-input-group"> | |
| <input | |
| type="number" | |
| value={magicPoints} | |
| onChange={(e) => { | |
| // 允许空字符串或有效数字 | |
| const value = e.target.value; | |
| if (value === '' || !isNaN(value)) { | |
| setMagicPoints(value); | |
| } | |
| }} | |
| min="1" | |
| max={userInfo?.magicPoints || 0} | |
| placeholder="输入要兑换的魔力值" | |
| /> | |
| <button | |
| className="exchange-btn" | |
| onClick={handleExchangeUpload} | |
| disabled={ | |
| !magicPoints || | |
| Number(magicPoints) <= 0 || | |
| !userInfo || | |
| Number(magicPoints) > userInfo.magicPoints | |
| } | |
| > | |
| 兑换上传量 | |
| </button> | |
| </div> | |
| </div> | |
| {inviteCodes.length > 0 && ( | |
| <div className="invite-code-list"> | |
| <h4>我的邀请码</h4> | |
| <ul> | |
| {inviteCodes.map((code, index) => ( | |
| <li key={index}> | |
| <span className="code">{code.code}</span> | |
| <span className={`status ${code.isUsed ? 'used' : 'available'}`}> | |
| {code.isUsed ? '已使用' : '可用'} | |
| </span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default Exchange; |