diff --git a/backend/app/models/models.py b/backend/app/models/models.py index 387f670..b20a3a4 100644 --- a/backend/app/models/models.py +++ b/backend/app/models/models.py @@ -255,3 +255,15 @@ class UserRole: cls.USER: "用户" } return names.get(role, "用户") + +class UserFeedback(Base): + """用户反馈表""" + __tablename__ = "user_feedbacks" + + id = Column(Integer, primary_key=True, index=True) + user_id = Column(Integer, ForeignKey("users.f99_90_id"), nullable=False) + content = Column(Text, nullable=False) + contact = Column(String(100), default="") + status = Column(String(20), default="pending") # pending, resolved + created_at = Column(DateTime, default=datetime.utcnow) + diff --git a/backend/app/routers/users.py b/backend/app/routers/users.py index 079be6e..5dfd0c4 100644 --- a/backend/app/routers/users.py +++ b/backend/app/routers/users.py @@ -303,3 +303,47 @@ def delete_user( db.commit() return {"message": "删除成功"} + + +@router.post("/feedback") +async def submit_feedback( + content: str, + contact: str = "", + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """用户提交反馈""" + from app.models import UserFeedback + + feedback = UserFeedback( + user_id=current_user.f99_90_id, + content=content, + contact=contact, + status="pending" + ) + db.add(feedback) + db.commit() + + return {"success": True, "message": "反馈已提交"} + + +@router.get("/feedback/list") +async def list_feedbacks( + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + """获取用户反馈列表(仅管理员)""" + if current_user.role != "admin": + return {"error": "无权限"}, 403 + + from app.models import UserFeedback + feedbacks = db.query(UserFeedback).order_by(UserFeedback.created_at.desc()).all() + + return [{ + "id": f.id, + "user_id": f.user_id, + "content": f.content, + "contact": f.contact, + "status": f.status, + "created_at": f.created_at.isoformat() if f.created_at else None + } for f in feedbacks] diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index 781157d..5c94bf3 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -9,6 +9,9 @@ export default function Home() { const [seekStats, setSeekStats] = useState({ seekCount: 0, matchedCount: 0 }) const [recentPosts, setRecentPosts] = useState([]) const [dragonStats, setDragonStats] = useState({}) + const [showFeedback, setShowFeedback] = useState(false) + const [feedbackContent, setFeedbackContent] = useState('') + const [feedbackContact, setFeedbackContact] = useState('') const currentPath = window.location.hash.slice(1) || '/' useEffect(() => { @@ -65,7 +68,26 @@ export default function Home() { }).catch(() => {}) // 获取最新一尘帖子 - fetch('/api/yichens/stats/dragons-today').then(res => res.json()).then(data => { + // 提交反馈 + const submitFeedback = async () => { + if (!feedbackContent.trim()) return alert('请输入反馈内容') + try { + const res = await fetch('/api/users/feedback', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, + body: JSON.stringify({ content: feedbackContent, contact: feedbackContact }) + }) + const data = await res.json() + if (data.success) { + alert('反馈已提交,感谢您的意见!') + setShowFeedback(false) + setFeedbackContent('') + setFeedbackContact('') + } + } catch (e) { alert('提交失败') } + } + + fetch('/api/yichens/stats/dragons-today').then(res => res.json()).then(data => { setDragonStats(data || {}) }).catch(() => {}) @@ -104,6 +126,34 @@ export default function Home() { { label: '总利润', value: formatMoney(stats.totalProfit) + '万', color: stats.totalProfit >= 0 ? '#10b981' : '#f43f5e' } ] + // 反馈弹窗 + if (showFeedback) { + return ( +