forked from wangziqi/gongxue-base
feat(sync): sync class schedules to DingTalk students
Group active schedules by class, resolve enrolled students through DingTalk mappings, reuse shifts and attendance groups, and expose class-based sync status in the admin UI.
This commit is contained in:
@@ -71,7 +71,7 @@ interface ScheduleSyncResult {
|
||||
groupCount: number;
|
||||
syncedItems: number;
|
||||
skippedNoMapping: number;
|
||||
groups: Array<{ deptName: string; groupId: number; itemCount: number }>;
|
||||
groups: Array<{ className: string; groupId: number; itemCount: number }>;
|
||||
}
|
||||
|
||||
const WEEKDAYS = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
||||
@@ -112,12 +112,12 @@ const SchedulesPage: React.FC = () => {
|
||||
const [syncModalOpen, setSyncModalOpen] = useState(false);
|
||||
const [syncing, setSyncing] = useState(false);
|
||||
const [syncStatus, setSyncStatus] = useState<{
|
||||
activeSchedules: number; mappedTeachers: number; totalTeachers: number;
|
||||
activeSchedules: number; mappedClasses: number; totalClasses: number;
|
||||
} | null>(null);
|
||||
const [syncResult, setSyncResult] = useState<{
|
||||
scheduleCount: number; shiftCount: number; groupCount: number;
|
||||
syncedItems: number; skippedNoMapping: number;
|
||||
groups: Array<{ deptName: string; groupId: number; itemCount: number }>;
|
||||
groups: Array<{ className: string; groupId: number; itemCount: number }>;
|
||||
} | null>(null);
|
||||
const [syncDateFrom, setSyncDateFrom] = useState<Dayjs>(dayjs);
|
||||
const [syncDays, setSyncDays] = useState(30);
|
||||
@@ -128,7 +128,7 @@ const SchedulesPage: React.FC = () => {
|
||||
setSyncResult(null);
|
||||
try {
|
||||
const res = await api.get<{
|
||||
success: boolean; data: { activeSchedules: number; mappedTeachers: number; totalTeachers: number };
|
||||
success: boolean; data: { activeSchedules: number; mappedClasses: number; totalClasses: number };
|
||||
}>('/sync/schedule/status');
|
||||
setSyncStatus(res.data);
|
||||
} catch {
|
||||
@@ -986,17 +986,17 @@ const SchedulesPage: React.FC = () => {
|
||||
{syncResult.skippedNoMapping > 0 && (
|
||||
<Alert
|
||||
type="warning"
|
||||
message={`${syncResult.skippedNoMapping} 条排课因教师未绑定钉钉而跳过`}
|
||||
message={`${syncResult.skippedNoMapping} 条排课因班级无钉钉绑定学生而跳过`}
|
||||
style={{ marginBottom: 16 }}
|
||||
showIcon
|
||||
/>
|
||||
)}
|
||||
{syncResult.groups.length > 0 && (
|
||||
<div>
|
||||
<div style={{ fontWeight: 500, marginBottom: 8 }}>按部门分组:</div>
|
||||
<div style={{ fontWeight: 500, marginBottom: 8 }}>按班级分组:</div>
|
||||
{syncResult.groups.map((g) => (
|
||||
<Tag key={g.groupId} color="blue" style={{ marginBottom: 4 }}>
|
||||
{g.deptName}:{g.itemCount} 条排班
|
||||
{g.className}:{g.itemCount} 条排班
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
@@ -1011,20 +1011,20 @@ const SchedulesPage: React.FC = () => {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Statistic
|
||||
title="已绑定教师"
|
||||
value={syncStatus.mappedTeachers}
|
||||
suffix={`/ ${syncStatus.totalTeachers}`}
|
||||
valueStyle={{ color: syncStatus.mappedTeachers < syncStatus.totalTeachers ? '#faad14' : '#3f8600' }}
|
||||
title="已就绪班级"
|
||||
value={syncStatus.mappedClasses}
|
||||
suffix={`/ ${syncStatus.totalClasses}`}
|
||||
valueStyle={{ color: syncStatus.mappedClasses < syncStatus.totalClasses ? '#faad14' : '#3f8600' }}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Statistic title="未绑定" value={syncStatus.totalTeachers - syncStatus.mappedTeachers} suffix="人" />
|
||||
<Statistic title="无绑定学生班级" value={syncStatus.totalClasses - syncStatus.mappedClasses} suffix="个" />
|
||||
</Col>
|
||||
</Row>
|
||||
{syncStatus.mappedTeachers < syncStatus.totalTeachers && (
|
||||
{syncStatus.mappedClasses < syncStatus.totalClasses && (
|
||||
<Alert
|
||||
type="warning"
|
||||
message={`${syncStatus.totalTeachers - syncStatus.mappedTeachers} 位教师未绑定钉钉,其排课将被跳过。请先执行组织架构同步。`}
|
||||
message={`${syncStatus.totalClasses - syncStatus.mappedClasses} 个班级没有已绑定钉钉的学生,其排课将被跳过。请先在钉钉集成页导入并绑定学生。`}
|
||||
style={{ marginBottom: 16 }}
|
||||
showIcon
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user