diff --git a/frontend/src/pages/ForumDetail.jsx b/frontend/src/pages/ForumDetail.jsx index a944022..8b286ff 100644 --- a/frontend/src/pages/ForumDetail.jsx +++ b/frontend/src/pages/ForumDetail.jsx @@ -2,7 +2,7 @@ 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 } from 'antd'; import { UserOutlined, ClockCircleOutlined, EyeOutlined, CheckCircleFilled, LeftOutlined, UploadOutlined, EditOutlined } from '@ant-design/icons'; -import { getTopicDetail, createReply, uploadMedia } from '../api'; +import { getTopicDetail, createReply, uploadMedia, getStarUsers } from '../api'; import { useAuth } from '../context/AuthContext'; import LoginModal from '../components/LoginModal'; import CreateTopicModal from '../components/CreateTopicModal'; @@ -41,6 +41,9 @@ const ForumDetail = () => { const [replyUploading, setReplyUploading] = useState(false); const [replyMediaIds, setReplyMediaIds] = useState([]); + // Star Users State + const [starUsers, setStarUsers] = useState([]); + const fetchTopic = async () => { try { const res = await getTopicDetail(id); @@ -53,14 +56,31 @@ const ForumDetail = () => { } }; + const fetchStarUsers = async () => { + try { + const res = await getStarUsers(); + setStarUsers(res.data || []); + } catch (error) { + console.error('Fetch star users failed', error); + } + }; + const hasFetched = React.useRef(false); useEffect(() => { if (!hasFetched.current) { fetchTopic(); + fetchStarUsers(); hasFetched.current = true; } }, [id]); + const handleReplyToUser = (nickname) => { + const mentionText = `@${nickname} `; + setReplyContent(prev => prev + mentionText); + // Focus logic if needed, but simple append works + message.info(`已添加 @${nickname}`); + }; + const handleSubmitReply = async () => { if (!user) { setLoginModalVisible(true); @@ -272,6 +292,14 @@ const ForumDetail = () => { {reply.author_info?.nickname} {new Date(reply.created_at).toLocaleString()} + #{index + 1} @@ -308,6 +336,25 @@ const ForumDetail = () => { placeholder="友善回复,分享你的见解... (支持 Markdown)" style={{ marginBottom: 16, background: '#111', border: '1px solid #333', color: '#fff' }} /> + + {starUsers.length > 0 && ( +
+ @技术专家: + + {starUsers.map(user => ( + handleReplyToUser(user.nickname)} + > + {user.nickname} + + ))} + +
+ )} +
{ const [sending, setSending] = useState(false) const [htmlContent, setHtmlContent] = useState('') const [userInfo, setUserInfo] = useState(null) + + // Star Users & Mention + const [starUsers, setStarUsers] = useState([]) + const [showStarUsers, setShowStarUsers] = useState(false) const fetchDetail = async () => { try { @@ -38,12 +42,24 @@ const ForumDetail = () => { } } + const fetchStarUsers = async () => { + try { + const res = await getStarUsers() + // API might return array directly or { data: [] } + const users = Array.isArray(res) ? res : (res.data || []) + setStarUsers(users) + } catch (error) { + console.error('Fetch star users failed', error) + } + } + useEffect(() => { const info = Taro.getStorageSync('userInfo') if (info) setUserInfo(info) if (id) { fetchDetail() + fetchStarUsers() } }, [id]) @@ -53,6 +69,12 @@ const ForumDetail = () => { } }) + const handleReplyToUser = (nickname) => { + const mentionText = `@${nickname} ` + setReplyContent(prev => prev + mentionText) + setShowStarUsers(false) + } + useShareAppMessage(() => { return { title: topic?.title || '技术社区', @@ -199,7 +221,12 @@ const ForumDetail = () => { {reply.author_info?.nickname} #{idx + 1} • {new Date(reply.created_at).toLocaleDateString()} - + + handleReplyToUser(reply.author_info?.nickname)} style={{marginRight: 10, padding: '2px 6px', background: '#f0f0f0', borderRadius: 4}}> + 回复 + + + {/* Simple markdown render for replies or just text if complex */} @@ -216,6 +243,9 @@ const ForumDetail = () => { + setShowStarUsers(true)} style={{marginLeft: 0}}> + + { {sending ? : 发送} + + setShowStarUsers(false)} onClose={() => setShowStarUsers(false)}> + {starUsers.map(user => ( + handleReplyToUser(user.nickname)}> + + + {user.nickname} + ({user.title || '专家'}) + + + ))} + ) }