Files
gongxue-base/apps/admin/src/pages/TeacherWorkspace/index.tsx

205 lines
5.4 KiB
TypeScript

import React, { useEffect, useState, useMemo } from 'react';
import { Card, Tabs, Table, Tag, Empty, Spin } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import api from '../../api';
import { message } from '../../ui/app-message';
interface AssignedClass {
classId: number;
className: string;
classCode: string;
roleType: string;
subject: string;
}
interface ScheduleItem {
id: number;
classId: number;
weekDay: number;
startTime: string;
endTime: string;
subject: string;
scheduleType: string;
}
interface StudentItem {
studentId: number;
studentName: string;
studentNo: string;
className: string;
classId: number;
joinDate: string;
}
interface WorkspaceData {
assignedClasses: AssignedClass[];
todaySchedules: ScheduleItem[];
myStudents: StudentItem[];
}
const ROLE_LABELS: Record<string, string> = {
head_teacher: '班主任',
life_teacher: '生活老师',
academic_teacher: '教务老师',
subject_teacher: '任课教师',
};
const WEEKDAY_LABELS: Record<string, string> = {
'1': '周一',
'2': '周二',
'3': '周三',
'4': '周四',
'5': '周五',
'6': '周六',
'7': '周日',
};
const TeacherWorkspacePage: React.FC = () => {
const [data, setData] = useState<WorkspaceData | null>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const res = (await api.get('/rbac/teacher-workspace')) as WorkspaceData;
setData(res);
} catch (e) {
console.error(e);
message.error('数据加载失败');
} finally {
setLoading(false);
}
};
fetchData();
}, []);
const classColumns: ColumnsType<AssignedClass> = useMemo(() => [
{
title: '班级名称',
dataIndex: 'className',
render: (v: string, r: AssignedClass) => `${v} (${r.classCode})`,
},
{
title: '角色',
dataIndex: 'roleType',
render: (v: string) => <Tag>{ROLE_LABELS[v] || v}</Tag>,
},
{
title: '科目',
dataIndex: 'subject',
render: (v: string | null) => v || '-',
},
], []);
const scheduleColumns: ColumnsType<ScheduleItem> = useMemo(() => [
{
title: '时间',
key: 'time',
render: (_: unknown, r: ScheduleItem) => `${r.startTime} - ${r.endTime}`,
},
{
title: '星期',
dataIndex: 'weekDay',
render: (v: number) => <Tag>{WEEKDAY_LABELS[String(v)] || v}</Tag>,
},
{
title: '科目',
dataIndex: 'subject',
},
{
title: '类型',
dataIndex: 'scheduleType',
render: (v: string) => (
<Tag color={v === 'INTERNAL' ? 'blue' : 'orange'}>
{v === 'INTERNAL' ? '内部课程' : '租赁'}
</Tag>
),
},
], []);
const studentColumns: ColumnsType<StudentItem> = useMemo(() => [
{ title: '姓名', dataIndex: 'studentName' },
{ title: '学号', dataIndex: 'studentNo', render: (v: string) => v || '-' },
{ title: '班级', dataIndex: 'className' },
{ title: '加入日期', dataIndex: 'joinDate', render: (v: string) => v || '-' },
], []);
if (loading) {
return (
<div style={{ textAlign: 'center', padding: 80 }}>
<Spin size="large" />
</div>
);
}
return (
<Card title="教师工作台">
<Tabs
defaultActiveKey="classes"
items={[
{
key: 'classes',
label: `我的班级 (${data?.assignedClasses.length || 0})`,
children: data?.assignedClasses.length ? (
<Table<AssignedClass>
columns={classColumns}
dataSource={data.assignedClasses}
rowKey="classId"
pagination={{
defaultPageSize: 20,
showSizeChanger: true,
pageSizeOptions: [20, 50, 100],
showTotal: (total) => `${total} 个班级`,
}}
/>
) : (
<Empty description="暂无分配的班级" />
),
},
{
key: 'schedule',
label: `今日课程 (${data?.todaySchedules.length || 0})`,
children: data?.todaySchedules.length ? (
<Table<ScheduleItem>
columns={scheduleColumns}
dataSource={data.todaySchedules}
rowKey="id"
pagination={{
defaultPageSize: 20,
showSizeChanger: true,
pageSizeOptions: [20, 50, 100],
showTotal: (total) => `${total}`,
}}
/>
) : (
<Empty description="今日无排课" />
),
},
{
key: 'students',
label: `我的学生 (${data?.myStudents.length || 0})`,
children: data?.myStudents.length ? (
<Table<StudentItem>
columns={studentColumns}
dataSource={data.myStudents}
rowKey="studentId"
pagination={{
defaultPageSize: 20,
showSizeChanger: true,
pageSizeOptions: [20, 50, 100],
showTotal: (total) => `${total}`,
}}
/>
) : (
<Empty description="暂无学生" />
),
},
]}
/>
</Card>
);
};
export default TeacherWorkspacePage;