feat: refine admin forms, attendance and finance workflows

Squash merge PR #23.

Included changes:
- complete occupancy check-in required fields/default payload
- improve responsive admin management pages
- fix attendance edge cases and attendance period config
- refine wallet/finance-related workflow handling

Checks:
- npm run typecheck -w apps/admin
- npm run typecheck -w apps/server
This commit is contained in:
2026-07-18 12:54:10 +00:00
parent 92d303ed01
commit 375c7ec60b
64 changed files with 5169 additions and 2404 deletions

View File

@@ -74,56 +74,65 @@ const TeacherWorkspacePage: React.FC = () => {
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 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 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 || '-' },
], []);
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 (