blob: cae4f6d97957aa0ea98a8da9ad3d0a6a024c55b7 [file] [log] [blame]
import { Avatar, Button, Card, Col, Row, Space, Typography, Divider, Badge, Empty, Spin } from 'antd';
import { UserOutlined, MailOutlined, PlusOutlined, BellOutlined, EyeOutlined, CalendarOutlined } from '@ant-design/icons';
import axios from 'axios';
import { useEffect, useState } from 'react';
import { useAppSelector, useAppDispatch } from '../../store/hooks';
import { getUserDetail, getUserInfo } from './userSlice';
const { Title, Text, Paragraph } = Typography;
// 定义 WorkResponse 接口,与后端 WorkResponse 类对应
interface WorkResponse {
id: number;
title: string;
author: string;
views: number;
categoryId: number;
description: string;
createTime: string;
}
// 模拟通知数据
const mockNotifications = [
{
id: 1,
title: '系统通知',
content: '您的作品《创意设计》获得了新的点赞!',
time: '2小时前',
type: 'like',
unread: true
},
{
id: 2,
title: '评论通知',
content: '用户"设计师小王"评论了您的作品',
time: '1天前',
type: 'comment',
unread: true
},
{
id: 3,
title: '系统消息',
content: '平台将于本周末进行系统维护',
time: '3天前',
type: 'system',
unread: false
}
];
function UserHome() {
const userState = useAppSelector(state => state.user);
const dispatch = useAppDispatch();
const [userWorks, setUserWorks] = useState<WorkResponse[]>([]);
const [loading, setLoading] = useState(false);
const [pageLoading, setPageLoading] = useState(true);
// 检查token并获取用户信息
useEffect(() => {
const initializeUser = async () => {
if (userState.userid) {
await dispatch(getUserDetail(userState.userid));
}
// 如果用户信息为空或状态为idle,重新获取
if (!userState.username || userState.status === 'idle') {
try {
await dispatch(getUserInfo()).then(
() => {
dispatch(getUserDetail(userState.userid));
}
)
} catch (error) {
console.error('获取用户信息失败:', error);
// 如果获取用户信息失败,可能token过期,重定向到登录页
localStorage.removeItem('token');
window.location.href = '/login';
return;
}
}
setPageLoading(false);
};
initializeUser();
}, [dispatch, userState.username, userState.status]);
// 获取用户作品
useEffect(() => {
const fetchUserWorks = async () => {
if (!userState.username) return;
try {
setLoading(true);
const token = localStorage.getItem('token');
if (token) {
const response = await axios.get('/api/works/works/byAuthor', {
headers: {
token: token
},
params: {
author: userState.username
}
});
if (response.data.code === 200) {
setUserWorks(response.data.data || []);
} else {
console.error('获取作品失败:', response.data.message);
setUserWorks([]);
}
}
} catch (error) {
console.error('获取用户作品信息失败:', error);
setUserWorks([]);
} finally {
setLoading(false);
}
};
// 只有当用户信息加载完成且用户名存在时才获取作品
if (userState.username && userState.status === 'succeeded') {
fetchUserWorks();
}
}, [userState.username, userState.status]);
// 格式化时间显示
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('zh-CN');
};
// 获取分类名称
const getCategoryName = (categoryId: number) => {
const categories: { [key: number]: string } = {
1: '文学创作',
2: '视觉设计',
3: '音乐创作',
4: '影视制作',
5: '其他'
};
return categories[categoryId] || '未分类';
};
// 如果页面正在初始化,显示加载状态
if (pageLoading || userState.status === 'loading') {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '400px'
}}>
<Spin size="large" tip="加载用户信息中..." />
</div>
);
}
// 如果获取用户信息失败
if (userState.status === 'failed' || !userState.username) {
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '400px',
flexDirection: 'column'
}}>
<Empty
description="无法获取用户信息"
style={{ marginBottom: 16 }}
/>
<Button
type="primary"
onClick={() => dispatch(getUserInfo())}
>
重新加载
</Button>
</div>
);
}
return (
<div className="user-home-container" style={{ padding: '0 24px' }}>
{/* 用户信息横栏 */}
<Card
style={{
marginBottom: 24,
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
border: 'none'
}}
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Space size="large" align="center">
<Avatar
size={80}
icon={<UserOutlined />}
style={{ backgroundColor: '#fff', color: '#667eea' }}
/>
<div>
<Title level={2} style={{ color: 'white', margin: 0 }}>
{userState.username}
</Title>
<Text style={{ color: 'rgba(255,255,255,0.8)', fontSize: '16px' }}>
<MailOutlined /> {userState.email || '暂无邮箱'}
</Text>
<div style={{ marginTop: 8 }}>
<Text style={{ color: 'rgba(255,255,255,0.6)' }}>
用户ID: {userState.userid}
</Text>
</div>
</div>
</Space>
<div style={{ textAlign: 'center', color: 'white' }}>
<div style={{ fontSize: '24px', fontWeight: 'bold' }}>{userWorks.length}</div>
<div style={{ opacity: 0.8 }}>发布作品</div>
</div>
</div>
</Card>
{/* 两栏布局 */}
<Row gutter={24}>
{/* 左侧:作品展示栏 */}
<Col span={16}>
<Card
title={
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<span>我的作品</span>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => {
// 这里后续添加跳转到发布作品页面的逻辑
console.log('跳转到发布作品页面');
}}
>
发布作品
</Button>
</div>
}
style={{ minHeight: '600px' }}
>
{loading ? (
<div style={{ textAlign: 'center', padding: '50px 0' }}>
<Spin size="large" tip="加载作品中..." />
</div>
) : userWorks.length === 0 ? (
<Empty
description="暂无作品,快去发布第一个作品吧!"
style={{ padding: '50px 0' }}
/>
) : (
<Row gutter={[16, 16]}>
{userWorks.map((work) => (
<Col span={12} key={work.id}>
<Card
hoverable
style={{ height: '100%' }}
actions={[
<div key="views" style={{ color: '#666' }}>
<EyeOutlined /> {work.views}
</div>,
<div key="category" style={{ color: '#666' }}>
{getCategoryName(work.categoryId)}
</div>
]}
>
<Card.Meta
title={
<div style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}}>
{work.title}
</div>
}
description={
<div>
<Paragraph
ellipsis={{ rows: 2 }}
style={{ marginBottom: 8, minHeight: '40px' }}
>
{work.description || '暂无描述'}
</Paragraph>
<div style={{
display: 'flex',
justifyContent: 'space-between',
fontSize: '12px',
color: '#999'
}}>
<span>
<CalendarOutlined /> {formatDate(work.createTime)}
</span>
<span>ID: {work.id}</span>
</div>
</div>
}
/>
</Card>
</Col>
))}
</Row>
)}
</Card>
</Col>
{/* 右侧:通知栏 */}
<Col span={8}>
<Card
title={
<div style={{ display: 'flex', alignItems: 'center' }}>
<BellOutlined style={{ marginRight: 8 }} />
通知中心
<Badge count={2} style={{ marginLeft: 8 }} />
</div>
}
style={{ minHeight: '600px' }}
>
<div>
{mockNotifications.map((notification, index) => (
<div key={notification.id}>
<div
style={{
padding: '12px',
backgroundColor: notification.unread ? '#f6ffed' : 'transparent',
borderRadius: '4px',
}}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
<div style={{ flex: 1 }}>
<div style={{
fontWeight: notification.unread ? 'bold' : 'normal',
marginBottom: '4px',
display: 'flex',
alignItems: 'center'
}}>
{notification.title}
{notification.unread && (
<Badge
color="red"
style={{ marginLeft: '8px' }}
/>
)}
</div>
<div style={{
color: '#666',
fontSize: '14px',
lineHeight: '1.4',
marginBottom: '8px'
}}>
{notification.content}
</div>
<div style={{ color: '#999', fontSize: '12px' }}>
{notification.time}
</div>
</div>
</div>
</div>
{index < mockNotifications.length - 1 && <Divider style={{ margin: '0' }} />}
</div>
))}
{/* 查看更多按钮 */}
<div style={{ textAlign: 'center', marginTop: '16px' }}>
<Button type="link">查看全部通知</Button>
</div>
</div>
</Card>
</Col>
</Row>
</div>
);
}
export default UserHome;