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

@@ -478,7 +478,6 @@ const SchedulesPage: React.FC = () => {
}
};
// ---- Classroom select options ----
const classroomOptions = useMemo(
@@ -1192,17 +1191,17 @@ const SchedulesPage: React.FC = () => {
{syncResult ? (
/* ── 同步结果 ── */
<div>
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={6}>
<Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
<Col xs={12} sm={6}>
<Statistic title="排课" value={syncResult.scheduleCount} suffix="条" />
</Col>
<Col span={6}>
<Col xs={12} sm={6}>
<Statistic title="班次" value={syncResult.shiftCount} suffix="个" />
</Col>
<Col span={6}>
<Col xs={12} sm={6}>
<Statistic title="考勤组" value={syncResult.groupCount} suffix="个" />
</Col>
<Col span={6}>
<Col xs={12} sm={6}>
<Statistic
title="排班数"
value={syncResult.syncedItems}
@@ -1257,11 +1256,11 @@ const SchedulesPage: React.FC = () => {
) : syncStatus ? (
/* ── 同步确认信息 ── */
<div>
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={8}>
<Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
<Col xs={24} sm={8}>
<Statistic title="活跃排课" value={syncStatus.activeSchedules} suffix="条" />
</Col>
<Col span={8}>
<Col xs={24} sm={8}>
<Statistic
title="已就绪班级"
value={syncStatus.mappedClasses}
@@ -1272,7 +1271,7 @@ const SchedulesPage: React.FC = () => {
}}
/>
</Col>
<Col span={8}>
<Col xs={24} sm={8}>
<Statistic
title="无绑定学生班级"
value={syncStatus.totalClasses - syncStatus.mappedClasses}

View File

@@ -59,7 +59,6 @@ describe('schedule edit form mapping', () => {
});
});
describe('schedule notes normalization', () => {
it('omits whitespace-only notes from the payload', () => {
expect(