import React, { useState } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { Button, Table, Space, Form, Input, message, Modal, Card, Row, Col, Popconfirm, Tag, DatePicker, Select } from 'antd'; import { useQuery } from '@tanstack/react-query'; import dayjs from 'dayjs'; import weekday from 'dayjs/plugin/weekday'; import localeData from 'dayjs/plugin/localeData'; import 'dayjs/locale/zh-cn'; import { ClassroomData, ClassroomStatus, ClassroomStatusNameMap } from '../share/types_stock.ts'; import { getEnumOptions } from './utils.ts'; import { ClassroomDataAPI } from './api/index.ts'; // 配置 dayjs 插件 dayjs.extend(weekday); dayjs.extend(localeData); dayjs.locale('zh-cn'); export const ClassroomDataPage = () => { const queryClient = useQueryClient(); const [modalVisible, setModalVisible] = useState(false); const [formMode, setFormMode] = useState<'create' | 'edit'>('create'); const [editingId, setEditingId] = useState(null); const [form] = Form.useForm(); const [searchForm] = Form.useForm(); const [searchParams, setSearchParams] = useState({ classroom_no: '', code: '', page: 1, limit: 10, }); // 使用React Query获取教室数据列表 const { data: classroomData, isLoading: isListLoading, refetch } = useQuery({ queryKey: ['classroomData', searchParams], queryFn: () => ClassroomDataAPI.getClassroomDatas({ page: searchParams.page, pageSize: searchParams.limit, classroom_no: searchParams.classroom_no, training_date: '', status: undefined }), placeholderData: { data: [], pagination: { current: 1, pageSize: 10, total: 0, totalPages: 1 } } }); const classrooms = React.useMemo(() => classroomData?.data || [], [classroomData]); const pagination = React.useMemo(() => ({ current: classroomData?.pagination?.current || 1, pageSize: classroomData?.pagination?.pageSize || 10, total: classroomData?.pagination?.total || 0, totalPages: classroomData?.pagination?.totalPages || 1 }), [classroomData]); // 获取单个教室数据 const fetchClassroom = async (id: number) => { try { const response = await ClassroomDataAPI.getClassroomData(id); return response.data; } catch (error) { message.error('获取教室数据详情失败'); return null; } }; // 处理表单提交 const handleSubmit = async (values: Partial) => { try { const response = formMode === 'create' ? await ClassroomDataAPI.createClassroomData(values) : await ClassroomDataAPI.updateClassroomData(editingId!, values); message.success(formMode === 'create' ? '创建教室数据成功' : '更新教室数据成功'); setModalVisible(false); form.resetFields(); refetch(); } catch (error) { message.error((error as Error).message); } }; // 处理编辑 const handleEdit = async (id: number) => { const classroom = await fetchClassroom(id); if (classroom) { setFormMode('edit'); setEditingId(id); form.setFieldsValue({ ...classroom, training_date: dayjs(classroom.training_date) }); setModalVisible(true); } }; // 处理删除 const handleDelete = async (id: number) => { try { await ClassroomDataAPI.deleteClassroomData(id); message.success('删除教室数据成功'); refetch(); } catch (error) { message.error((error as Error).message); } }; // 处理搜索 const handleSearch = async (values: any) => { try { queryClient.removeQueries({ queryKey: ['classroomData'] }); setSearchParams({ classroom_no: values.classroom_no || '', code: values.code || '', page: 1, limit: searchParams.limit, }); } catch (error) { message.error('搜索失败'); } }; // 处理分页 const handlePageChange = (page: number, pageSize?: number) => { setSearchParams(prev => ({ ...prev, page, limit: pageSize || prev.limit, })); }; // 处理添加 const handleAdd = () => { setFormMode('create'); setEditingId(null); form.resetFields(); setModalVisible(true); }; // 复制链接到剪贴板 const copyLink = (type: 'exam' | 'stock' | 'admin', classroom_no: string) => { const baseUrl = window.location.origin; let url = ''; let successMsg = ''; switch(type) { case 'exam': url = `${baseUrl}/mobile/exam/card?classroom=${classroom_no}`; successMsg = '答题卡链接已复制'; break; case 'stock': url = `${baseUrl}/mobile/stock?classroom=${classroom_no}`; successMsg = '股票训练链接已复制'; break; case 'admin': url = `${baseUrl}/mobile/exam/admin?classroom=${classroom_no}`; successMsg = '管理员链接已复制'; break; } navigator.clipboard.writeText(url).then(() => { message.success(successMsg); }).catch(() => { message.error('复制失败,请手动复制'); }); }; // 教室状态选项 const statusOptions = getEnumOptions(ClassroomStatus, ClassroomStatusNameMap); // 表格列定义 const columns = [ { title: 'ID', dataIndex: 'id', key: 'id', width: 80, }, { title: '教室号', dataIndex: 'classroom_no', key: 'classroom_no', }, { title: '训练日期', dataIndex: 'training_date', key: 'training_date', render: (date: string) => dayjs(date).format('YYYY-MM-DD'), }, { title: '持股', dataIndex: 'holding_stock', key: 'holding_stock', }, { title: '持币', dataIndex: 'holding_cash', key: 'holding_cash', }, { title: '价格', dataIndex: 'price', key: 'price', }, { title: '代码', dataIndex: 'code', key: 'code', }, { title: '状态', dataIndex: 'status', key: 'status', render: (status: ClassroomStatus) => { const color = status === ClassroomStatus.OPEN ? 'green' : 'red'; const text = ClassroomStatusNameMap[status]; return {text}; }, }, { title: '链接', key: 'links', render: (_: any, record: ClassroomData) => (
), }, { title: '操作', key: 'action', render: (_: any, record: ClassroomData) => ( handleDelete(record.id)} okText="确定" cancelText="取消" > ), }, ]; return (
`共 ${total} 条`, }} /> { form.validateFields() .then(values => { handleSubmit({ ...values, training_date: values.training_date.format('YYYY-MM-DD') }); }) .catch(info => { console.log('表单验证失败:', info); }); }} onCancel={() => setModalVisible(false)} width={800} okText="确定" cancelText="取消" destroyOnClose >
); };