refactor(admin): extract StudentProfileContent component and reuse in drawer
This commit is contained in:
@@ -16,7 +16,6 @@ import {
|
||||
Col,
|
||||
Card,
|
||||
Drawer,
|
||||
Tabs,
|
||||
Descriptions,
|
||||
} from 'antd';
|
||||
import {
|
||||
@@ -31,6 +30,7 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import api from '../../api';
|
||||
import PermissionButton from '../../components/PermissionButton';
|
||||
import StudentProfileContent from '../../components/StudentProfileContent';
|
||||
|
||||
const maskPhone = (phone: string) => {
|
||||
if (!phone || phone.length < 7) return phone || '-';
|
||||
@@ -83,18 +83,12 @@ const StudentsPage: React.FC = () => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
||||
const [enrollmentData, setEnrollmentData] = useState<Record<number, EnrollmentInfo[]>>({});
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
const [drawerData, setDrawerData] = useState<any>(null);
|
||||
const [drawerLoading, setDrawerLoading] = useState(false);
|
||||
const [drawerStudentId, setDrawerStudentId] = useState<number | undefined>(undefined);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const openDrawer = async (studentId: number) => {
|
||||
const openDrawer = (studentId: number) => {
|
||||
setDrawerStudentId(studentId);
|
||||
setDrawerOpen(true);
|
||||
setDrawerLoading(true);
|
||||
try {
|
||||
const res = await api.get(`/archive/${studentId}`);
|
||||
setDrawerData(res);
|
||||
} catch { setDrawerData(null); }
|
||||
setDrawerLoading(false);
|
||||
};
|
||||
|
||||
const handleViewSensitive = (studentId: number, field: string, value: string) => {
|
||||
@@ -583,98 +577,18 @@ const StudentsPage: React.FC = () => {
|
||||
</Modal>
|
||||
|
||||
<Drawer
|
||||
title={drawerData?.student?.name ? `${drawerData.student.name} — 学生档案` : '学生档案'}
|
||||
title={null}
|
||||
open={drawerOpen}
|
||||
onClose={() => { setDrawerOpen(false); setDrawerData(null); }}
|
||||
onClose={() => { setDrawerOpen(false); }}
|
||||
width={720}
|
||||
loading={drawerLoading}
|
||||
>
|
||||
{drawerData && (<div>
|
||||
<Tabs items={[
|
||||
{
|
||||
key: 'info', label: '基础信息',
|
||||
children: (
|
||||
<Descriptions column={2} size="small" bordered>
|
||||
<Descriptions.Item label="姓名">{drawerData.student?.name}</Descriptions.Item>
|
||||
<Descriptions.Item label="学号">{drawerData.student?.studentNo || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="电话">{drawerData.student?.phone || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="身份证">{drawerData.student?.idNumber || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="状态"><Tag>{drawerData.student?.status}</Tag></Descriptions.Item>
|
||||
<Descriptions.Item label="目标院校">{drawerData.profile?.targetCollege || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="目标专业">{drawerData.profile?.targetMajor || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="科类方向">{drawerData.profile?.subjectDirection || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="年级">{drawerData.profile?.grade || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="校区">{drawerData.profile?.campusLocation || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="建档日期">{drawerData.profile?.profileDate || '-'}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'enrollments', label: `报读记录 (${drawerData.enrollments?.length || 0})`,
|
||||
children: drawerData.enrollments?.length ? (
|
||||
<Table rowKey="id" size="small" pagination={false} dataSource={drawerData.enrollments} columns={[
|
||||
{ title: '课程类别', dataIndex: 'courseCategory' },
|
||||
{ title: '班型', dataIndex: 'classType' },
|
||||
{ title: '班级', dataIndex: 'className' },
|
||||
{ title: '班主任', dataIndex: 'headTeacher' },
|
||||
{ title: '开课', dataIndex: 'startDate' },
|
||||
{ title: '结课', dataIndex: 'endDate' },
|
||||
]} />
|
||||
) : <div style={{ color: '#999' }}>暂无报读记录</div>,
|
||||
},
|
||||
{
|
||||
key: 'exams', label: `考试成绩 (${drawerData.examScores?.length || 0})`,
|
||||
children: drawerData.examScores?.length ? (
|
||||
<Table rowKey="id" size="small" pagination={false} dataSource={drawerData.examScores} columns={[
|
||||
{ title: '类型', dataIndex: 'examType' },
|
||||
{ title: '科目', dataIndex: 'subject' },
|
||||
{ title: '分数', dataIndex: 'score' },
|
||||
{ title: '班均', dataIndex: 'classAvg', render: (v: number) => v ?? '-' },
|
||||
{ title: '排名', dataIndex: 'rank', render: (v: number) => v ?? '-' },
|
||||
{ title: '日期', dataIndex: 'examDate' },
|
||||
]} />
|
||||
) : <div style={{ color: '#999' }}>暂无考试成绩</div>,
|
||||
},
|
||||
{
|
||||
key: 'result', label: '录取结果',
|
||||
children: drawerData.result ? (
|
||||
<Descriptions column={2} size="small" bordered>
|
||||
<Descriptions.Item label="文化课成绩">{drawerData.result.cultureFinalScore ?? '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="专业课成绩">{drawerData.result.professionalFinalScore ?? '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="录取状态">{drawerData.result.admissionStatus || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="录取院校">{drawerData.result.admittedCollege || '-'}</Descriptions.Item>
|
||||
<Descriptions.Item label="录取专业" span={2}>{drawerData.result.admittedMajor || '-'}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
) : <div style={{ color: '#999' }}>暂无录取结果</div>,
|
||||
},
|
||||
{
|
||||
key: 'learning', label: `学情记录 (${drawerData.learningRecords?.length || 0})`,
|
||||
children: drawerData.learningRecords?.length ? (
|
||||
<Table rowKey="id" size="small" pagination={false} dataSource={drawerData.learningRecords} columns={[
|
||||
{ title: '日期', dataIndex: 'recordDate', width: 100 },
|
||||
{ title: '类型', dataIndex: 'recordType', width: 80 },
|
||||
{ title: '内容', dataIndex: 'content', ellipsis: true },
|
||||
{ title: '跟进方式', dataIndex: 'followUpMethod', width: 100 },
|
||||
{ title: '下一步', dataIndex: 'nextStep', width: 100 },
|
||||
]} />
|
||||
) : <div style={{ color: '#999' }}>暂无学情记录</div>,
|
||||
},
|
||||
{
|
||||
key: 'attachments', label: `附件 (${drawerData.attachments?.length || 0})`,
|
||||
children: drawerData.attachments?.length ? (
|
||||
<Table rowKey="id" size="small" pagination={false} dataSource={drawerData.attachments} columns={[
|
||||
{ title: '分类', dataIndex: 'category', width: 80 },
|
||||
{ title: '文件名', dataIndex: 'fileName', ellipsis: true },
|
||||
{ title: '大小', dataIndex: 'fileSize', width: 80, render: (v: number) => v ? `${(v / 1024).toFixed(1)} KB` : '-' },
|
||||
]} />
|
||||
) : <div style={{ color: '#999' }}>暂无附件</div>,
|
||||
},
|
||||
]} />
|
||||
<Button type="primary" icon={<DownloadOutlined />} style={{ marginTop: 16 }} onClick={() => {
|
||||
const token = localStorage.getItem('token');
|
||||
window.open(`/api/archive/${drawerData?.student?.id}/report?token=${token}`, '_blank');
|
||||
}}>生成档案报表</Button>
|
||||
</div>)}
|
||||
{drawerStudentId && (
|
||||
<StudentProfileContent
|
||||
studentId={drawerStudentId}
|
||||
inDrawer
|
||||
onClose={() => { setDrawerOpen(false); }}
|
||||
/>
|
||||
)}
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user