个股论坛重做
This commit is contained in:
@@ -14,7 +14,6 @@ import {
|
||||
Tag,
|
||||
Divider,
|
||||
Textarea,
|
||||
useColorModeValue,
|
||||
Spinner,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
Avatar,
|
||||
IconButton,
|
||||
HStack,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { MdThumbUp, MdReply, MdMoreVert } from 'react-icons/md';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
@@ -26,18 +25,35 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
const [liked, setLiked] = useState(false);
|
||||
const [likeCount, setLikeCount] = useState(reply.likeCount);
|
||||
|
||||
const textColor = useColorModeValue('gray.800', 'gray.100');
|
||||
const mutedColor = useColorModeValue('gray.500', 'gray.400');
|
||||
const replyBg = useColorModeValue('gray.100', 'gray.700');
|
||||
// 深色主题颜色(HeroUI 风格)
|
||||
const textColor = 'gray.100';
|
||||
const mutedColor = 'gray.400';
|
||||
const replyBg = 'rgba(255, 255, 255, 0.05)';
|
||||
|
||||
// 格式化时间
|
||||
// 格式化时间 - 将 UTC 时间转换为北京时间
|
||||
const formatTime = (dateStr: string) => {
|
||||
return formatDistanceToNow(new Date(dateStr), {
|
||||
const date = new Date(dateStr);
|
||||
// 后端存储的是 UTC 时间,需要加 8 小时转换为北京时间
|
||||
const beijingDate = new Date(date.getTime() + 8 * 60 * 60 * 1000);
|
||||
return formatDistanceToNow(beijingDate, {
|
||||
addSuffix: true,
|
||||
locale: zhCN,
|
||||
});
|
||||
};
|
||||
|
||||
// 解析内容中的 Markdown 图片
|
||||
const parseContent = (content: string) => {
|
||||
let html = content;
|
||||
// 匹配  格式,支持 base64 data URL
|
||||
html = html.replace(
|
||||
/!\[([^\]]*)\]\(([^)]+)\)/g,
|
||||
'<img src="$2" alt="$1" style="max-width: 100%; border-radius: 8px; margin: 8px 0;" />'
|
||||
);
|
||||
// 将换行转换为 <br>
|
||||
html = html.replace(/\n/g, '<br />');
|
||||
return html;
|
||||
};
|
||||
|
||||
// 点赞
|
||||
const handleLike = () => {
|
||||
setLiked(!liked);
|
||||
@@ -53,13 +69,14 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
name={reply.authorName}
|
||||
src={reply.authorAvatar}
|
||||
mr={3}
|
||||
bg="linear-gradient(135deg, rgba(139, 92, 246, 0.6), rgba(59, 130, 246, 0.6))"
|
||||
/>
|
||||
|
||||
{/* 内容 */}
|
||||
<Box flex={1}>
|
||||
{/* 作者和时间 */}
|
||||
<HStack spacing={2} mb={1}>
|
||||
<Text fontWeight="semibold" fontSize="sm">
|
||||
<Text fontWeight="semibold" fontSize="sm" color="purple.300">
|
||||
{reply.authorName}
|
||||
</Text>
|
||||
<Text fontSize="xs" color={mutedColor}>
|
||||
@@ -68,9 +85,9 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
{reply.isSolution && (
|
||||
<Text
|
||||
fontSize="xs"
|
||||
color="green.500"
|
||||
color="green.400"
|
||||
fontWeight="semibold"
|
||||
bg="green.50"
|
||||
bg="rgba(34, 197, 94, 0.15)"
|
||||
px={2}
|
||||
py={0.5}
|
||||
borderRadius="full"
|
||||
@@ -96,11 +113,14 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
)}
|
||||
|
||||
{/* 回复内容 */}
|
||||
<Text
|
||||
<Box
|
||||
color={textColor}
|
||||
fontSize="sm"
|
||||
lineHeight="1.6"
|
||||
dangerouslySetInnerHTML={{ __html: reply.contentHtml || reply.content }}
|
||||
dangerouslySetInnerHTML={{ __html: parseContent(reply.contentHtml || reply.content) }}
|
||||
sx={{
|
||||
'img': { maxW: '100%', borderRadius: 'md', my: 2 },
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 操作栏 */}
|
||||
@@ -110,7 +130,9 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
icon={<MdThumbUp />}
|
||||
size="xs"
|
||||
variant={liked ? 'solid' : 'ghost'}
|
||||
colorScheme={liked ? 'blue' : 'gray'}
|
||||
colorScheme={liked ? 'purple' : 'gray'}
|
||||
color={liked ? 'white' : 'gray.400'}
|
||||
_hover={{ bg: 'whiteAlpha.100' }}
|
||||
onClick={handleLike}
|
||||
/>
|
||||
<Text fontSize="xs" color={mutedColor}>
|
||||
@@ -122,6 +144,8 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
icon={<MdReply />}
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
color="gray.400"
|
||||
_hover={{ bg: 'whiteAlpha.100', color: 'white' }}
|
||||
onClick={onReply}
|
||||
/>
|
||||
|
||||
@@ -130,6 +154,8 @@ const ReplyItem: React.FC<ReplyItemProps> = ({ reply, onReply }) => {
|
||||
icon={<MdMoreVert />}
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
color="gray.400"
|
||||
_hover={{ bg: 'whiteAlpha.100', color: 'white' }}
|
||||
/>
|
||||
</HStack>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user