import React, { useState, useCallback, useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useSearchParams } from "react-router"; import dayjs from 'dayjs'; import { message } from 'antd'; import { useExamCurrentQuestion, useExamRoomMessages, useExamAnswerSubmission, useExamUserAnswerHistory, useExamSocketRoom } from './hooks/useSocketClient.ts'; import type { AnswerRecord, ClassroomData, Answer } from './types.ts'; // 答题卡页面 export default function ExamCard() { const [searchParams] = useSearchParams(); const classroom = searchParams.get('classroom'); const nickname = searchParams.get('nickname'); useExamSocketRoom(classroom); const lastMessage = useExamRoomMessages(classroom); const { submitAnswer } = useExamAnswerSubmission(classroom); const { currentQuestion } = useExamCurrentQuestion(classroom); const { userAnswers } = useExamUserAnswerHistory(classroom, nickname); const [currentDate, setCurrentDate] = useState(''); const [currentPrice, setCurrentPrice] = useState('0'); const [holdingStock, setHoldingStock] = useState('0'); const [holdingCash, setHoldingCash] = useState('0'); const [isStarted, setIsStarted] = useState(false); const [answerRecords, setAnswerRecords] = useState([]); const { data: classroomData, isLoading } = useQuery({ queryKey: ['classroom', classroom], queryFn: async () => { if (!classroom) return null; const response = await fetch(`/api/v1/classroom?classroom_no=${classroom}`); const data = await response.json(); if (!data.success) { message.error(data.message || '获取教室数据失败'); return null; } return data.data?.[0] as ClassroomData || null; }, enabled: !!classroom }); useEffect(() => { if (!classroom || !nickname) { globalThis.location.href = '/exam'; return; } if (classroomData && classroomData.status !== "1") { message.error('该教室已关闭'); globalThis.location.href = '/exam'; return; } }, [classroom, nickname, classroomData]); // 处理房间消息 useEffect(() => { if (!lastMessage?.message) return; const { type } = lastMessage.message; // 只处理重开消息的UI重置 if (type === 'restart') { setCurrentDate(''); setCurrentPrice('0'); setHoldingStock('0'); setHoldingCash('0'); setIsStarted(false); setAnswerRecords([]); } }, [lastMessage]); useEffect(() => { if (currentQuestion) { console.log('currentQuestion', currentQuestion); setCurrentDate(currentQuestion.date); setCurrentPrice(String(currentQuestion.price)); setIsStarted(true); } else { // 如果没有当前问题,重置状态 setCurrentDate(''); setCurrentPrice('0'); setIsStarted(false); } }, [currentQuestion]); // 处理选择A(持股) const handleChooseA = useCallback(async () => { setHoldingStock('1'); setHoldingCash('0'); if (classroom && nickname) { const answer = { date: currentDate, holdingStock: '1', holdingCash: '0', userId: nickname, price: currentPrice }; try { await submitAnswer(currentDate, nickname, answer); } catch (error) { message.error('提交答案失败'); } } }, [classroom, nickname, currentDate, currentPrice, submitAnswer]); // 处理选择B(持币) const handleChooseB = useCallback(async () => { setHoldingStock('0'); setHoldingCash('1'); if (classroom && nickname) { const answer = { date: currentDate, holdingStock: '0', holdingCash: '1', userId: nickname, price: currentPrice }; try { await submitAnswer(currentDate, nickname, answer); } catch (error) { message.error('提交答案失败'); } } }, [classroom, nickname, currentDate, currentPrice, submitAnswer]); // 初始化用户的答题记录 useEffect(() => { if (userAnswers && userAnswers.length > 0) { const lastAnswer = userAnswers[userAnswers.length - 1]; setHoldingStock(lastAnswer.holdingStock); setHoldingCash(lastAnswer.holdingCash); // 直接使用 userAnswers 中已计算好的数据 const records = userAnswers.map((answer: Answer, index: number): AnswerRecord => ({ date: answer.date, price: String(answer.price || '0'), holdingStock: answer.holdingStock, holdingCash: answer.holdingCash, profitAmount: answer.profitAmount || 0, profitPercent: answer.profitPercent || 0, index: index + 1 })); setAnswerRecords(records); } }, [userAnswers]); if (isLoading || !classroomData) { return
加载中...
; } return (
{/* 选择区域 */}

持股选A, 持币选B

{isStarted ? ( <> 日期: {currentDate} 价格: {currentPrice} ) : (
等待训练开始...
训练日期: {dayjs(classroomData.training_date).format('YYYY-MM-DD')}
)}
{/* 选择按钮 - 增大点击区域 */}
{isStarted ? '开始' : '等待'}
{/* 信息显示 */}
昵称: {nickname}
代码: {classroomData.code}
{/* 表格头部 */}
训练日期
持股
持币
价格
收益(元)
盈亏率
{/* 表格内容 - 优化滚动体验 */}
{[...answerRecords].reverse().map((record: AnswerRecord) => (
{record.index}
{dayjs(record.date).format('YYYY-MM-DD')}
{record.holdingStock}
{record.holdingCash}
{record.price}
= 0 ? 'text-red-500' : 'text-green-500'}> {record.profitAmount.toFixed(2)}
= 0 ? 'text-red-500' : 'text-green-500'}> {record.profitPercent.toFixed(2)}%
{record.index}
))}
); }