This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Typography, Card, Avatar, Tag, Space, Button, Divider, Input, message, Upload, Tooltip, Grid, Modal } from 'antd';
|
||||
import { UserOutlined, ClockCircleOutlined, EyeOutlined, CheckCircleFilled, LeftOutlined, UploadOutlined, EditOutlined, StarFilled, CloseOutlined } from '@ant-design/icons';
|
||||
import { getTopicDetail, createReply, uploadMedia, getStarUsers } from '../api';
|
||||
import { UserOutlined, ClockCircleOutlined, EyeOutlined, CheckCircleFilled, LeftOutlined, UploadOutlined, EditOutlined, StarFilled, CloseOutlined, LikeOutlined, LikeFilled } from '@ant-design/icons';
|
||||
import { getTopicDetail, createReply, uploadMedia, getStarUsers, likeTopic, likeReply } from '../api';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import LoginModal from '../components/LoginModal';
|
||||
import CreateTopicModal from '../components/CreateTopicModal';
|
||||
@@ -94,6 +94,44 @@ const ForumDetail = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleLikeTopic = async () => {
|
||||
if (!user) {
|
||||
setLoginModalVisible(true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await likeTopic(topic.id);
|
||||
setTopic(prev => ({
|
||||
...prev,
|
||||
is_liked: res.data.liked,
|
||||
like_count: res.data.count
|
||||
}));
|
||||
} catch (error) {
|
||||
message.error('操作失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleLikeReply = async (replyId) => {
|
||||
if (!user) {
|
||||
setLoginModalVisible(true);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await likeReply(replyId);
|
||||
setTopic(prev => ({
|
||||
...prev,
|
||||
replies: prev.replies.map(r => {
|
||||
if (r.id === replyId) {
|
||||
return { ...r, is_liked: res.data.liked, like_count: res.data.count };
|
||||
}
|
||||
return r;
|
||||
})
|
||||
}));
|
||||
} catch (error) {
|
||||
message.error('操作失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmitReply = async () => {
|
||||
if (!user) {
|
||||
setLoginModalVisible(true);
|
||||
@@ -255,6 +293,10 @@ const ForumDetail = () => {
|
||||
<EyeOutlined />
|
||||
<span style={{ fontSize: isMobile ? 12 : 14 }}>{topic.view_count} 阅读</span>
|
||||
</Space>
|
||||
<Space style={{ cursor: 'pointer' }} onClick={handleLikeTopic}>
|
||||
{topic.is_liked ? <LikeFilled style={{ color: '#00b96b' }} /> : <LikeOutlined />}
|
||||
<span style={{ fontSize: isMobile ? 12 : 14, color: topic.is_liked ? '#00b96b' : 'inherit' }}>{topic.like_count || 0} 点赞</span>
|
||||
</Space>
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
@@ -318,6 +360,12 @@ const ForumDetail = () => {
|
||||
<Text style={{ color: '#aaa', fontWeight: 'bold', fontSize: isMobile ? 13 : 14 }}>{reply.author_info?.nickname}</Text>
|
||||
{reply.is_pinned && <Tag color="red" style={{ margin: 0 }}>置顶</Tag>}
|
||||
<Text style={{ color: '#666', fontSize: 12 }}>{new Date(reply.created_at).toLocaleString()}</Text>
|
||||
</Space>
|
||||
<Space size={isMobile ? 'small' : 'middle'} align="center">
|
||||
<Space onClick={() => handleLikeReply(reply.id)} style={{ cursor: 'pointer' }}>
|
||||
{reply.is_liked ? <LikeFilled style={{ color: '#00b96b' }} /> : <LikeOutlined style={{ color: '#666' }} />}
|
||||
<span style={{ fontSize: 12, color: reply.is_liked ? '#00b96b' : '#666' }}>{reply.like_count || 0}</span>
|
||||
</Space>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
@@ -326,8 +374,8 @@ const ForumDetail = () => {
|
||||
>
|
||||
回复
|
||||
</Button>
|
||||
<Text style={{ color: '#444', fontSize: 12 }}>#{index + 1}</Text>
|
||||
</Space>
|
||||
<Text style={{ color: '#444', fontSize: 12 }}>#{index + 1}</Text>
|
||||
</div>
|
||||
<div style={{ color: '#eee', fontSize: isMobile ? 14 : 16 }} className={styles['markdown-body']}>
|
||||
<ReactMarkdown
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Typography, Input, Button, List, Tag, Avatar, Card, Space, Spin, message, Badge, Tooltip, Tabs, Row, Col, Grid, Carousel, Modal } from 'antd';
|
||||
import { SearchOutlined, PlusOutlined, UserOutlined, MessageOutlined, EyeOutlined, CheckCircleFilled, FireOutlined, StarFilled, QuestionCircleOutlined, ShareAltOutlined, SoundOutlined, RightOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { SearchOutlined, PlusOutlined, UserOutlined, MessageOutlined, EyeOutlined, CheckCircleFilled, FireOutlined, StarFilled, QuestionCircleOutlined, ShareAltOutlined, SoundOutlined, RightOutlined, CloseOutlined, LikeOutlined } from '@ant-design/icons';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { motion } from 'framer-motion';
|
||||
import { getTopics, getStarUsers, getAnnouncements } from '../api';
|
||||
@@ -296,6 +296,10 @@ const ForumList = () => {
|
||||
<EyeOutlined style={{ fontSize: isMobile ? 14 : 16, color: '#666' }} />
|
||||
<div style={{ color: '#888', fontSize: isMobile ? 10 : 12 }}>{item.view_count || 0}</div>
|
||||
</div>
|
||||
<div style={{ textAlign: 'center', marginTop: isMobile ? 2 : 5 }}>
|
||||
<LikeOutlined style={{ fontSize: isMobile ? 14 : 16, color: '#666' }} />
|
||||
<div style={{ color: '#888', fontSize: isMobile ? 10 : 12 }}>{item.like_count || 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user