blob: 4269c44569506a8a45d1881107ae8986df653628 [file] [log] [blame]
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const UserLevelExperience = ({ userId }) => {
const [experienceInfo, setExperienceInfo] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [upgradeResult, setUpgradeResult] = useState(null);
const [hasCheckedIn, setHasCheckedIn] = useState(false);
const [isUpgrading, setIsUpgrading] = useState(false);
const [lastUpgradeTime, setLastUpgradeTime] = useState(null);
const [justUpgraded, setJustUpgraded] = useState(false); // 新增
useEffect(() => {
if (!userId) return;
fetchAllLevelData();
}, [userId]);
useEffect(() => {
if (
experienceInfo &&
experienceInfo.current_experience >= experienceInfo.next_level_experience &&
!isUpgrading &&
!justUpgraded &&
(!lastUpgradeTime || Date.now() - lastUpgradeTime > 2000)
) {
}
}, [experienceInfo, isUpgrading, lastUpgradeTime, justUpgraded]);
const fetchAllLevelData = async () => {
try {
setIsLoading(true);
setError(null);
const { data } = await axios.get('/echo/level/getExperience', {
params: { user_id: userId },
});
const normalizedData = {
...data,
current_level: data.current_level || data.level,
};
setExperienceInfo(normalizedData);
const today = new Date().toDateString();
const lastCheckIn = localStorage.getItem('lastCheckIn');
setHasCheckedIn(lastCheckIn === today);
} catch (err) {
console.error('经验信息获取失败:', err);
setError('获取经验信息失败');
} finally {
setIsLoading(false);
}
};
const updateExperience = async (source, amount = 10) => {
try {
setIsLoading(true);
setError(null);
const { data } = await axios.post('/echo/level/updateExperience', {
user_id: userId,
experience: amount,
source: source,
});
setExperienceInfo((prev) => ({
...prev,
current_experience: data.current_experience,
}));
alert(`获得${amount}点经验值!来源:${source}`);
if (source === 'check-in') {
localStorage.setItem('lastCheckIn', new Date().toDateString());
setHasCheckedIn(true);
}
} catch (err) {
console.error('更新经验失败:', err);
setError(err.response?.data?.message || '更新经验失败');
} finally {
setIsLoading(false);
}
};
const checkUpgrade = async () => {
if (isUpgrading) return;
try {
setIsLoading(true);
setIsUpgrading(true);
setError(null);
const { data } = await axios.get('/echo/level/upgrade-check', {
params: { user_id: userId },
});
if (data.can_upgrade) {
if (window.confirm('您已满足升级条件,是否要升级?')) {
await performUpgrade();
}
} else {
if (data.is_max_level) {
alert('您已达到最高等级!');
} else {
alert(`还不能升级,还需要${data.next_level_experience - data.current_experience}点经验值`);
}
}
} catch (err) {
console.error('检查升级失败:', err);
setError(err.response?.data?.message || '检查升级失败');
} finally {
setIsLoading(false);
setIsUpgrading(false);
}
};
const performUpgrade = async () => {
try {
setIsUpgrading(true);
setIsLoading(true);
setError(null);
const { data } = await axios.post('/echo/level/upgrades', {
user_id: userId,
can_upgrade: true,
});
console.log('升级响应数据:', data);
if (data.status === 'success') {
setExperienceInfo((prev) => ({
// 更新就会进入useEffect,又执行了checkUpgrade,循环
...prev,
current_level: data.new_level,
current_experience: data.current_experience || 0,
next_level_experience: data.next_level_experience || prev.next_level_experience * 2,
}));
setUpgradeResult(data);
setLastUpgradeTime(Date.now());
setJustUpgraded(true); // 标记为刚升级过
setTimeout(() => setJustUpgraded(false), 3000); // 3 秒冷却期
alert(`恭喜!您已升级到等级 ${data.new_level}!`);
// 再次拉取最新经验数据,避免经验值仍然满足升级条件
await fetchAllLevelData();
} else {
throw new Error(data.message || '升级失败');
}
} catch (err) {
console.error('升级失败:', err);
setError(err.message || '升级失败');
alert(err.message || '升级失败,请稍后再试');
} finally {
setIsLoading(false);
setIsUpgrading(false);
}
};
if (error) return <p className="error">{error}</p>;
if (isLoading) return <p>加载中...</p>;
if (!experienceInfo) return <p>加载经验信息中...</p>;
const { current_experience, next_level_experience, current_level } = experienceInfo;
const progressPercent = Math.min(
100,
(current_experience / (next_level_experience || 1)) * 100
).toFixed(2);
const expToNextLevel = Math.max(0, next_level_experience - current_experience);
return (
<div style={{ padding: '20px', marginTop: '-80px', marginLeft: '70px' }}>
{/* <h3>等级与经验</h3> */}
<div style={{ fontSize: '20px', marginBottom: '10px' }}><strong>当前等级:</strong>lv{current_level || '未知'}</div>
<div style={{ fontSize: '20px', marginBottom: '10px' }}><strong>当前经验:</strong>{current_experience}</div>
{/* <p><strong>距离下一等级还需:</strong>{expToNextLevel} 经验值</p> */}
<div className="exp-bar-wrapper">
<div className="exp-bar" style={{ width: `${progressPercent}%` }} />
</div>
<p className="exp-progress-text">{progressPercent}%</p>
{upgradeResult && (
<div className="upgrade-success">
<p>恭喜!您已成功升级到等级 {upgradeResult.new_level}!</p>
</div>
)}
{error && (
<div className="upgrade-error">
<p>{error}</p>
</div>
)}
<div className="level-actions">
{/* <button onClick={() => updateExperience('check-in', 15)} disabled={hasCheckedIn}>
{hasCheckedIn ? '今日已签到' : '每日签到 (+15经验)'}
</button> */}
{/* <button onClick={() => updateExperience('task', 30)}>完成任务 (+30经验)</button> */}
{/* <button onClick={() => updateExperience('upload', 50)}>上传种子 (+20经验)</button> */}
{/* <button onClick={checkUpgrade} disabled={isUpgrading}>
{isUpgrading ? '升级中...' : '检查升级'}
</button> */}
</div>
</div>
);
};
export default UserLevelExperience;