blob: 0cc9914bae3fc963191666ea83ad2699846398ca [file] [log] [blame]
import React, { useState, useEffect } from 'react';
import { Card, Button, Descriptions, Avatar, Tag, Space, message } from 'antd';
import { UserOutlined, LogoutOutlined, ReloadOutlined } from '@ant-design/icons';
import { getUserInfo, getAuthToken, isLoggedIn, saveAuthInfo, createAuthenticatedRequest } from '../../utils/auth';
import LogoutButton from '../../components/LogoutButton';
import './TestDashboard.css';
const TestDashboard = () => {
const [userInfo, setUserInfo] = useState(null);
const [token, setToken] = useState(null);
const [loading, setLoading] = useState(false);
const [jwtTestLoading, setJwtTestLoading] = useState(false);
useEffect(() => {
// 检查用户是否已登录
if (!isLoggedIn()) {
window.location.href = '/';
return;
}
// 获取用户信息和token
const authToken = getAuthToken();
const authUserInfo = getUserInfo();
setToken(authToken);
setUserInfo(authUserInfo);
}, []);
const handleRefreshProfile = async () => {
if (!token) {
message.error('未找到认证token');
return;
}
setLoading(true);
try {
const response = await fetch('http://10.126.59.25:8082/profile', createAuthenticatedRequest());
const result = await response.json();
if (result.success) {
setUserInfo(result.user);
// 更新存储的用户信息,保持原有的存储方式(localStorage或sessionStorage)
const isRemembered = localStorage.getItem('authToken');
saveAuthInfo(token, result.user, !!isRemembered);
message.success('用户信息刷新成功');
} else {
message.error(`获取用户信息失败: ${result.message}`);
}
} catch (error) {
console.error('刷新用户信息失败:', error);
message.error('网络连接失败');
} finally {
setLoading(false);
}
};
const handleLogout = async () => {
if (!token) {
// 清除存储并跳转
localStorage.removeItem('authToken');
localStorage.removeItem('userInfo');
sessionStorage.removeItem('authToken');
sessionStorage.removeItem('userInfo');
window.location.href = '/';
return;
}
try {
const response = await fetch('http://10.126.59.25:8082/logout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
}
});
const result = await response.json();
if (result.success) {
message.success('退出登录成功');
} else {
message.warning(`退出登录: ${result.message}`);
}
} catch (error) {
console.error('退出登录请求失败:', error);
message.warning('网络请求失败,但将清除本地数据');
} finally {
// 无论请求成功与否,都清除本地存储并跳转
localStorage.removeItem('authToken');
localStorage.removeItem('userInfo');
sessionStorage.removeItem('authToken');
sessionStorage.removeItem('userInfo');
window.location.href = '/';
}
};
const handleTestJWT = async () => {
if (!token) {
message.error('未找到认证token');
return;
}
setJwtTestLoading(true);
try {
const response = await fetch('http://10.126.59.25:8082/test-jwt', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
token: token, // 可选:在请求体中也发送token进行额外验证
test_purpose: 'frontend_jwt_test'
})
});
const result = await response.json();
if (result.success) {
message.success(`JWT令牌验证成功!用户: ${result.user.username}`);
console.log('JWT验证详细结果:', result);
// 如果有额外的token验证结果,也显示出来
if (result.additional_token_verification) {
console.log('额外token验证:', result.additional_token_verification);
}
} else {
message.error(`JWT令牌验证失败: ${result.message}`);
}
} catch (error) {
console.error('JWT令牌验证失败:', error);
message.error('网络连接失败');
} finally {
setJwtTestLoading(false);
}
};
const getRoleColor = (role) => {
switch (role) {
case 'superadmin':
return 'red';
case 'admin':
return 'orange';
case 'user':
default:
return 'blue';
}
};
const getStatusColor = (status) => {
switch (status) {
case 'active':
return 'green';
case 'banned':
return 'red';
case 'muted':
return 'orange';
default:
return 'default';
}
};
if (!userInfo) {
return (
<div className="test-dashboard">
<div className="loading-container">
<div className="spinner"></div>
<p>加载用户信息中...</p>
</div>
</div>
);
}
return (
<div className="test-dashboard">
<div className="dashboard-header">
<h1>测试仪表板</h1>
<p>登录成功!以下是从后端返回的用户信息:</p>
</div>
<div className="dashboard-content">
<Card
title={
<Space>
<Avatar size={40} icon={<UserOutlined />} src={userInfo.avatar} />
<span>用户信息</span>
</Space>
}
extra={
<Space>
<Button
type="primary"
icon={<ReloadOutlined />}
loading={loading}
onClick={handleRefreshProfile}
>
刷新信息
</Button>
<LogoutButton onLogout={() => window.location.href = '/'} />
</Space>
}
className="user-info-card"
>
<Descriptions column={2} bordered>
<Descriptions.Item label="用户ID">{userInfo.id}</Descriptions.Item>
<Descriptions.Item label="用户名">{userInfo.username}</Descriptions.Item>
<Descriptions.Item label="邮箱">{userInfo.email}</Descriptions.Item>
<Descriptions.Item label="角色">
<Tag color={getRoleColor(userInfo.role)}>
{userInfo.role}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="账号状态">
<Tag color={getStatusColor(userInfo.status)}>
{userInfo.status}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="个人简介" span={2}>
{userInfo.bio || '暂无个人简介'}
</Descriptions.Item>
<Descriptions.Item label="创建时间">
{userInfo.created_at ? new Date(userInfo.created_at).toLocaleString() : '未知'}
</Descriptions.Item>
<Descriptions.Item label="更新时间">
{userInfo.updated_at ? new Date(userInfo.updated_at).toLocaleString() : '未知'}
</Descriptions.Item>
</Descriptions>
</Card>
<Card title="登录状态信息" className="login-status-card">
<div className="login-status-display">
<Descriptions column={1} bordered>
<Descriptions.Item label="登录方式">
<Tag color={localStorage.getItem('authToken') ? 'green' : 'blue'}>
{localStorage.getItem('authToken') ? '记住我登录 (持久化)' : '普通登录 (会话)'}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="Token存储位置">
{localStorage.getItem('authToken') ? 'localStorage (浏览器关闭后仍保持登录)' : 'sessionStorage (浏览器关闭后需重新登录)'}
</Descriptions.Item>
<Descriptions.Item label="记住的登录信息">
{localStorage.getItem('rememberMe') === 'true' ?
`已保存邮箱: ${localStorage.getItem('rememberedEmail') || '无'}` :
'未保存登录信息'
}
</Descriptions.Item>
</Descriptions>
</div>
</Card>
<Card title="Token信息" className="token-info-card">
<div className="token-display">
<p><strong>认证Token:</strong></p>
<div className="token-text">
{token ? `${token.substring(0, 50)}...` : '未找到token'}
</div>
<p className="token-note">
* Token已被安全截断显示,完整token存储在浏览器存储中
</p>
</div>
</Card>
<Card title="API测试" className="api-test-card">
<Space direction="vertical" style={{ width: '100%' }}>
<p>您可以使用以下按钮测试不同的API接口:</p>
<Space wrap>
<Button onClick={handleRefreshProfile} loading={loading}>
测试 GET /profile
</Button>
<Button onClick={handleLogout}>
测试 POST /logout
</Button>
<Button
onClick={handleTestJWT}
loading={jwtTestLoading}
type="primary"
>
测试 POST /test-jwt
</Button>
<Button
type="dashed"
onClick={() => window.open('http://10.126.59.25:8082/health', '_blank')}
>
测试 GET /health
</Button>
</Space>
</Space>
</Card>
</div>
</div>
);
};
export default TestDashboard;