feat: add Jinshuju student sync

This commit is contained in:
2026-07-22 11:37:20 +08:00
parent 1dc13274de
commit 393ee62168
18 changed files with 1378 additions and 12 deletions

View File

@@ -39,6 +39,7 @@ export { LearningRecord } from './learning-record.entity';
export { ResultArchive } from './result-archive.entity';
export { ArchiveAttachment } from './archive-attachment.entity';
export { StudentDingMapping } from './student-ding-mapping.entity';
export { JinshujuMatchRule } from './jinshuju-match-rule.entity';
export { AiConfig } from '../ai-config/ai-config.entity';
export * from './student-wallet.entity';

View File

@@ -0,0 +1,53 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
/**
* Field mappings from Jinshuju field keys (field_1, field_2, ...) to Student columns.
* Only mapped fields are extracted; unmapped fields are ignored.
*/
export interface JinshujuFieldMapping {
/** Jinshuju field key → Student column name */
name?: string; // e.g. "field_1"
phone?: string; // e.g. "field_2"
idNumber?: string; // e.g. "field_3"
gender?: string;
ethnicity?: string;
emergencyContact?: string;
emergencyPhone?: string;
studentNo?: string;
}
export const DEFAULT_MAPPING: JinshujuFieldMapping = {
name: 'field_1',
phone: 'field_2',
};
const mappingTransformer = {
to(value: JinshujuFieldMapping): string {
return JSON.stringify(value);
},
from(value: string | null): JinshujuFieldMapping {
if (!value) return {};
return JSON.parse(value);
},
};
@Entity('jinshuju_match_rules')
export class JinshujuMatchRule {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100 })
name: string;
@Column({ name: 'form_token', length: 64 })
formToken: string;
@Column({ type: 'text', transformer: mappingTransformer })
mappings: JinshujuFieldMapping;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
}

View File

@@ -1,6 +1,6 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm';
export type SyncPlatform = 'dingtalk_students' | 'dingtalk_attendance' | 'wecom';
export type SyncPlatform = 'dingtalk_students' | 'dingtalk_attendance' | 'wecom' | 'jinshuju';
export type SyncType = 'full' | 'incremental';
export type SyncStatus = 'running' | 'success' | 'partial' | 'failed';