|
|
@@ -1,160 +1,313 @@
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
-import { Layout, List, Card, Avatar, Button, Input, Space, Typography, Spin, Empty } from 'antd';
|
|
|
-import { UserOutlined, MessageOutlined, HeartOutlined, SendOutlined } from '@ant-design/icons';
|
|
|
-import { useAuth } from '@/client/home/hooks/AuthProvider';
|
|
|
+import { Layout, Button, Typography, Card, Space, Row, Col, Image, Divider, List, Avatar } from 'antd';
|
|
|
+import { UserOutlined, MessageOutlined, HeartOutlined, ArrowRightOutlined, TwitterOutlined, InstagramOutlined, FacebookOutlined } from '@ant-design/icons';
|
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
import { postClient } from '@/client/api';
|
|
|
-import { InferResponseType } from 'hono';
|
|
|
-
|
|
|
+import { InferResponseType } from 'hono/client';
|
|
|
|
|
|
+// 定义帖子类型
|
|
|
type Post = InferResponseType<typeof postClient.$get, 200>['data'][0];
|
|
|
|
|
|
const { Header, Content, Footer } = Layout;
|
|
|
const { Title, Text, Paragraph } = Typography;
|
|
|
|
|
|
const HomePage: React.FC = () => {
|
|
|
- const [posts, setPosts] = useState<Post[]>([]);
|
|
|
+ const [featuredPosts, setFeaturedPosts] = useState<Post[]>([]);
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
- const [content, setContent] = useState('');
|
|
|
- const { user } = useAuth();
|
|
|
const navigate = useNavigate();
|
|
|
|
|
|
- // 获取首页内容流
|
|
|
- const fetchPosts = async () => {
|
|
|
- try {
|
|
|
- setLoading(true);
|
|
|
- const response = await postClient.$get({
|
|
|
- query: {
|
|
|
- page: 1,
|
|
|
- pageSize: 10
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- if (!response.ok) throw new Error('获取内容失败');
|
|
|
-
|
|
|
- const data = await response.json();
|
|
|
- setPosts(data.data);
|
|
|
- } catch (error) {
|
|
|
- console.error('Error fetching posts:', error);
|
|
|
- } finally {
|
|
|
- setLoading(false);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 创建新帖子
|
|
|
- const handlePost = async () => {
|
|
|
- if (!content.trim()) return;
|
|
|
-
|
|
|
- try {
|
|
|
- const response = await postClient.$post({
|
|
|
- json: {
|
|
|
- content
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- if (!response.ok) throw new Error('发布失败');
|
|
|
-
|
|
|
- const newPost = await response.json();
|
|
|
- setPosts([newPost, ...posts]);
|
|
|
- setContent('');
|
|
|
- } catch (error) {
|
|
|
- console.error('Error creating post:', error);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- // 点赞帖子
|
|
|
- const handleLike = async (postId: number) => {
|
|
|
- try {
|
|
|
- await postClient[':id'].like.$post({
|
|
|
- param: { id: postId }
|
|
|
- });
|
|
|
- setPosts(posts.map(post =>
|
|
|
- post.id === postId ? { ...post, likesCount: post.likesCount + 1 } : post
|
|
|
- ));
|
|
|
- } catch (error) {
|
|
|
- console.error('Error liking post:', error);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
+ // 获取热门帖子预览
|
|
|
useEffect(() => {
|
|
|
- fetchPosts();
|
|
|
+ const fetchFeaturedPosts = async () => {
|
|
|
+ try {
|
|
|
+ setLoading(true);
|
|
|
+ const response = await postClient.$get({
|
|
|
+ query: {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 3,
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!response.ok) throw new Error('获取热门内容失败');
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+ setFeaturedPosts(data.data);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Error fetching featured posts:', error);
|
|
|
+ } finally {
|
|
|
+ setLoading(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ fetchFeaturedPosts();
|
|
|
}, []);
|
|
|
|
|
|
return (
|
|
|
<Layout className="min-h-screen">
|
|
|
- <Header style={{ position: 'fixed', zIndex: 1, width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
|
- <Title level={3} style={{ color: 'white', margin: 0 }}>社交媒体平台</Title>
|
|
|
- <div style={{ display: 'flex', alignItems: 'center' }}>
|
|
|
- <Button type="text" style={{ color: 'white', marginRight: 16 }} onClick={() => navigate('/follow?type=following')}>
|
|
|
- 关注
|
|
|
+ {/* 顶部导航栏 */}
|
|
|
+ <Header style={{
|
|
|
+ position: 'fixed',
|
|
|
+ zIndex: 1,
|
|
|
+ width: '100%',
|
|
|
+ display: 'flex',
|
|
|
+ justifyContent: 'space-between',
|
|
|
+ alignItems: 'center',
|
|
|
+ background: '#fff',
|
|
|
+ boxShadow: '0 2px 8px rgba(0, 0, 0, 0.06)'
|
|
|
+ }}>
|
|
|
+ <Title level={3} style={{ color: '#1890ff', margin: 0 }}>社交媒体平台</Title>
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="default"
|
|
|
+ onClick={() => navigate('/login')}
|
|
|
+ style={{ marginRight: 8 }}
|
|
|
+ >
|
|
|
+ 登录
|
|
|
</Button>
|
|
|
- <Button type="text" style={{ color: 'white', marginRight: 16 }} onClick={() => navigate('/follow?type=followers')}>
|
|
|
- 粉丝
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={() => navigate('/register')}
|
|
|
+ >
|
|
|
+ 注册
|
|
|
</Button>
|
|
|
- <Avatar icon={<UserOutlined />} style={{ marginRight: 16 }} onClick={() => navigate(`/users/${user?.id}`)} />
|
|
|
- <Text style={{ color: 'white' }}>{user?.username}</Text>
|
|
|
- </div>
|
|
|
+ </Space>
|
|
|
</Header>
|
|
|
-
|
|
|
+
|
|
|
+ {/* 主内容区 */}
|
|
|
<Content style={{ padding: '0 50px', marginTop: 64 }}>
|
|
|
- <div style={{ background: '#fff', padding: 24, marginTop: 20, borderRadius: 8, maxWidth: 800, margin: '0 auto' }}>
|
|
|
- {/* 发布框 */}
|
|
|
- <Card style={{ marginBottom: 24 }}>
|
|
|
- <Space.Compact style={{ width: '100%' }}>
|
|
|
- <Input.TextArea
|
|
|
- placeholder="分享你的想法..."
|
|
|
- rows={4}
|
|
|
- value={content}
|
|
|
- onChange={e => setContent(e.target.value)}
|
|
|
+ <div style={{ maxWidth: 1200, margin: '0 auto', padding: '40px 0' }}>
|
|
|
+ {/* 英雄区域 */}
|
|
|
+ <Row gutter={[32, 32]} align="middle" style={{ marginBottom: 60 }}>
|
|
|
+ <Col xs={24} lg={12}>
|
|
|
+ <Title level={1} style={{ marginBottom: 16 }}>
|
|
|
+ 连接世界,<br />
|
|
|
+ <span style={{ color: '#1890ff' }}>分享精彩</span>
|
|
|
+ </Title>
|
|
|
+ <Paragraph style={{ fontSize: 18, lineHeight: 1.6, marginBottom: 32 }}>
|
|
|
+ 加入我们的社交平台,与朋友分享生活点滴,发现精彩内容,参与热门话题讨论。
|
|
|
+ 简单注册,开启您的社交之旅。
|
|
|
+ </Paragraph>
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ size="large"
|
|
|
+ onClick={() => navigate('/register')}
|
|
|
+ icon={<ArrowRightOutlined />}
|
|
|
+ >
|
|
|
+ 立即注册
|
|
|
+ </Button>
|
|
|
+ <Button
|
|
|
+ type="default"
|
|
|
+ size="large"
|
|
|
+ onClick={() => navigate('/login')}
|
|
|
+ >
|
|
|
+ 登录账号
|
|
|
+ </Button>
|
|
|
+ </Space>
|
|
|
+ </Col>
|
|
|
+ <Col xs={24} lg={12}>
|
|
|
+ <Image
|
|
|
+ alt="社交平台展示"
|
|
|
+ src="https://gw.alipayobjects.com/zos/rmsportal/XuVpGqBFxXplzvLjJBZB.svg"
|
|
|
+ preview={false}
|
|
|
+ style={{ width: '100%', borderRadius: 8 }}
|
|
|
/>
|
|
|
- <Button type="primary" icon={<SendOutlined />} onClick={handlePost}>
|
|
|
- 发布
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+
|
|
|
+ {/* 功能特点 */}
|
|
|
+ <div style={{ marginBottom: 60 }}>
|
|
|
+ <Title level={2} style={{ textAlign: 'center', marginBottom: 40 }}>平台特点</Title>
|
|
|
+ <Row gutter={[24, 24]}>
|
|
|
+ <Col xs={24} md={8}>
|
|
|
+ <Card
|
|
|
+ hoverable
|
|
|
+ bordered={false}
|
|
|
+ style={{ textAlign: 'center', padding: '32px 24px', height: '100%' }}
|
|
|
+ >
|
|
|
+ <div style={{
|
|
|
+ width: 64,
|
|
|
+ height: 64,
|
|
|
+ borderRadius: 50,
|
|
|
+ background: '#e6f7ff',
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ margin: '0 auto 16px'
|
|
|
+ }}>
|
|
|
+ <UserOutlined style={{ fontSize: 32, color: '#1890ff' }} />
|
|
|
+ </div>
|
|
|
+ <Title level={3} style={{ marginBottom: 16 }}>结识新朋友</Title>
|
|
|
+ <Paragraph>
|
|
|
+ 发现志同道合的朋友,扩展您的社交圈,建立有意义的连接。
|
|
|
+ </Paragraph>
|
|
|
+ </Card>
|
|
|
+ </Col>
|
|
|
+ <Col xs={24} md={8}>
|
|
|
+ <Card
|
|
|
+ hoverable
|
|
|
+ bordered={false}
|
|
|
+ style={{ textAlign: 'center', padding: '32px 24px', height: '100%' }}
|
|
|
+ >
|
|
|
+ <div style={{
|
|
|
+ width: 64,
|
|
|
+ height: 64,
|
|
|
+ borderRadius: 50,
|
|
|
+ background: '#fff1f0',
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ margin: '0 auto 16px'
|
|
|
+ }}>
|
|
|
+ <MessageOutlined style={{ fontSize: 32, color: '#ff4d4f' }} />
|
|
|
+ </div>
|
|
|
+ <Title level={3} style={{ marginBottom: 16 }}>分享生活</Title>
|
|
|
+ <Paragraph>
|
|
|
+ 发布文字、图片和视频,记录生活中的美好瞬间,分享您的故事。
|
|
|
+ </Paragraph>
|
|
|
+ </Card>
|
|
|
+ </Col>
|
|
|
+ <Col xs={24} md={8}>
|
|
|
+ <Card
|
|
|
+ hoverable
|
|
|
+ bordered={false}
|
|
|
+ style={{ textAlign: 'center', padding: '32px 24px', height: '100%' }}
|
|
|
+ >
|
|
|
+ <div style={{
|
|
|
+ width: 64,
|
|
|
+ height: 64,
|
|
|
+ borderRadius: 50,
|
|
|
+ background: '#f6ffed',
|
|
|
+ display: 'flex',
|
|
|
+ alignItems: 'center',
|
|
|
+ justifyContent: 'center',
|
|
|
+ margin: '0 auto 16px'
|
|
|
+ }}>
|
|
|
+ <HeartOutlined style={{ fontSize: 32, color: '#52c41a' }} />
|
|
|
+ </div>
|
|
|
+ <Title level={3} style={{ marginBottom: 16 }}>互动交流</Title>
|
|
|
+ <Paragraph>
|
|
|
+ 点赞、评论、分享,与朋友实时互动,参与热门话题讨论。
|
|
|
+ </Paragraph>
|
|
|
+ </Card>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 热门内容预览 */}
|
|
|
+ <div style={{ marginBottom: 60 }}>
|
|
|
+ <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
|
|
|
+ <Title level={2}>热门内容</Title>
|
|
|
+ <Button type="link" onClick={() => navigate('/login')}>
|
|
|
+ 查看更多 <ArrowRightOutlined style={{ fontSize: 14 }} />
|
|
|
</Button>
|
|
|
- </Space.Compact>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {loading ? (
|
|
|
+ <div style={{ textAlign: 'center', padding: '60px 0' }}>
|
|
|
+ <div className="loader ease-linear rounded-full border-4 border-t-4 border-gray-200 h-12 w-12 mx-auto"></div>
|
|
|
+ </div>
|
|
|
+ ) : featuredPosts.length === 0 ? (
|
|
|
+ <Card style={{ textAlign: 'center', padding: '60px 0' }}>
|
|
|
+ <Text type="secondary">暂无热门内容</Text>
|
|
|
+ </Card>
|
|
|
+ ) : (
|
|
|
+ <List
|
|
|
+ itemLayout="vertical"
|
|
|
+ dataSource={featuredPosts}
|
|
|
+ renderItem={item => (
|
|
|
+ <List.Item
|
|
|
+ key={item.id}
|
|
|
+ actions={[
|
|
|
+ <Text type="secondary"><HeartOutlined /> {item.likesCount}</Text>,
|
|
|
+ <Text type="secondary"><MessageOutlined /> {item.commentsCount}</Text>
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <List.Item.Meta
|
|
|
+ avatar={<Avatar src={item.user?.avatar || <UserOutlined />} />}
|
|
|
+ title={item.user?.username}
|
|
|
+ description={
|
|
|
+ <>
|
|
|
+ <Paragraph ellipsis={{ rows: 2 }} style={{ marginBottom: 8 }}>
|
|
|
+ {item.content}
|
|
|
+ </Paragraph>
|
|
|
+ <Text type="secondary">{new Date(item.createdAt).toLocaleString()}</Text>
|
|
|
+ </>
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </List.Item>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 注册引导区 */}
|
|
|
+ <Card
|
|
|
+ bordered={false}
|
|
|
+ style={{
|
|
|
+ textAlign: 'center',
|
|
|
+ padding: '48px 24px',
|
|
|
+ background: 'linear-gradient(135deg, #e6f7ff 0%, #f0f9ff 100%)'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Title level={2} style={{ marginBottom: 16 }}>准备好加入我们了吗?</Title>
|
|
|
+ <Paragraph style={{ maxWidth: 600, margin: '0 auto 32px' }}>
|
|
|
+ 注册账号,开启您的社交之旅,与数百万用户一起分享精彩生活
|
|
|
+ </Paragraph>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ size="large"
|
|
|
+ onClick={() => navigate('/register')}
|
|
|
+ icon={<ArrowRightOutlined />}
|
|
|
+ >
|
|
|
+ 立即注册,免费使用
|
|
|
+ </Button>
|
|
|
</Card>
|
|
|
-
|
|
|
- {/* 内容流 */}
|
|
|
- <Title level={4}>最新动态</Title>
|
|
|
- {loading ? (
|
|
|
- <Spin size="large" style={{ display: 'block', margin: '40px auto' }} />
|
|
|
- ) : posts.length === 0 ? (
|
|
|
- <Empty description="暂无内容" />
|
|
|
- ) : (
|
|
|
- <List
|
|
|
- dataSource={posts}
|
|
|
- renderItem={item => (
|
|
|
- <List.Item
|
|
|
- key={item.id}
|
|
|
- actions={[
|
|
|
- <Button icon={<HeartOutlined />} onClick={() => handleLike(item.id)}>
|
|
|
- {item.likesCount > 0 && item.likesCount}
|
|
|
- </Button>,
|
|
|
- <Button icon={<MessageOutlined />}>{item.commentsCount > 0 && item.commentsCount}</Button>,
|
|
|
- <Button>分享</Button>
|
|
|
- ]}
|
|
|
- >
|
|
|
- <List.Item.Meta
|
|
|
- avatar={<Avatar src={item.user?.avatar || <UserOutlined />} />}
|
|
|
- title={item.user?.username}
|
|
|
- description={
|
|
|
- <>
|
|
|
- <Paragraph>{item.content}</Paragraph>
|
|
|
- {item.images?.map((img, idx) => (
|
|
|
- <img key={idx} src={img} alt={`Post image ${idx}`} style={{ maxWidth: '100%', margin: '8px 0' }} />
|
|
|
- ))}
|
|
|
- <Text type="secondary">{new Date(item.createdAt).toLocaleString()}</Text>
|
|
|
- </>
|
|
|
- }
|
|
|
- />
|
|
|
- </List.Item>
|
|
|
- )}
|
|
|
- />
|
|
|
- )}
|
|
|
</div>
|
|
|
</Content>
|
|
|
-
|
|
|
- <Footer style={{ textAlign: 'center' }}>
|
|
|
- 社交媒体平台 ©{new Date().getFullYear()} Created with React & Ant Design
|
|
|
+
|
|
|
+ {/* 页脚 */}
|
|
|
+ <Footer style={{
|
|
|
+ background: '#f5f5f5',
|
|
|
+ padding: '48px 0',
|
|
|
+ marginTop: 40
|
|
|
+ }}>
|
|
|
+ <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 24px' }}>
|
|
|
+ <Row gutter={[32, 32]}>
|
|
|
+ <Col xs={24} md={12} lg={6}>
|
|
|
+ <Title level={4} style={{ marginBottom: 16 }}>社交媒体平台</Title>
|
|
|
+ <Paragraph>
|
|
|
+ 连接世界,分享精彩
|
|
|
+ </Paragraph>
|
|
|
+ </Col>
|
|
|
+ <Col xs={12} md={6} lg={4}>
|
|
|
+ <Title level={5} style={{ marginBottom: 16 }}>快速链接</Title>
|
|
|
+ <div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
|
+ <Text onClick={() => navigate('/login')} style={{ cursor: 'pointer', marginBottom: 8 }}>登录</Text>
|
|
|
+ <Text onClick={() => navigate('/register')} style={{ cursor: 'pointer', marginBottom: 8 }}>注册</Text>
|
|
|
+ </div>
|
|
|
+ </Col>
|
|
|
+ <Col xs={12} md={6} lg={4}>
|
|
|
+ <Title level={5} style={{ marginBottom: 16 }}>支持</Title>
|
|
|
+ <div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
|
+ <Text style={{ cursor: 'pointer', marginBottom: 8 }}>帮助中心</Text>
|
|
|
+ <Text style={{ cursor: 'pointer', marginBottom: 8 }}>联系我们</Text>
|
|
|
+ </div>
|
|
|
+ </Col>
|
|
|
+ <Col xs={24} md={12} lg={6}>
|
|
|
+ <Title level={5} style={{ marginBottom: 16 }}>关注我们</Title>
|
|
|
+ <Space size={16}>
|
|
|
+ <Button type="text" icon={<TwitterOutlined />} size="large" />
|
|
|
+ <Button type="text" icon={<FacebookOutlined />} size="large" />
|
|
|
+ <Button type="text" icon={<InstagramOutlined />} size="large" />
|
|
|
+ </Space>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ <Divider style={{ margin: '24px 0' }} />
|
|
|
+ <Text type="secondary" style={{ display: 'block', textAlign: 'center' }}>
|
|
|
+ ©{new Date().getFullYear()} 社交媒体平台. 保留所有权利.
|
|
|
+ </Text>
|
|
|
+ </div>
|
|
|
</Footer>
|
|
|
</Layout>
|
|
|
);
|