feat(sync): implement sync stubs with env-var gating and status endpoint

This commit is contained in:
2026-07-06 09:53:48 +08:00
parent 2c0ca583a3
commit a568da160c
2 changed files with 36 additions and 10 deletions

View File

@@ -16,6 +16,17 @@ export class SyncController {
return { synced: logs.length, logs };
}
@Get('status')
@RequirePermission('sync:read')
async getStatus() {
const lastDingTalk = await this.syncService.getLastSync('dingtalk');
const lastWeCom = await this.syncService.getLastSync('wecom');
return {
dingTalk: lastDingTalk ? { lastSyncAt: lastDingTalk.finishedAt, status: lastDingTalk.status } : null,
weCom: lastWeCom ? { lastSyncAt: lastWeCom.finishedAt, status: lastWeCom.status } : null,
};
}
@Get('logs')
@RequirePermission('sync:read')
async getLogs(

View File

@@ -91,6 +91,13 @@ export class SyncService {
return this.syncLogRepo.find({ where, order: { createdAt: 'DESC' }, take: limit });
}
async getLastSync(platform: SyncPlatform): Promise<SyncLog | null> {
return this.syncLogRepo.findOne({
where: { platform },
order: { createdAt: 'DESC' },
});
}
// ── Private helpers ──
private async determineSyncType(platform: SyncPlatform): Promise<SyncType> {
@@ -145,20 +152,28 @@ export class SyncService {
* Pass `lastSyncAt` to the DingTalk API for incremental sync.
*/
private async performDingTalkSync(_lastSyncAt: Date | null): Promise<number> {
// TODO: Call DingTalk API — e.g. attendance records, user list, etc.
// const records = await this.dingTalkClient.fetchAttendance({ updatedAfter: lastSyncAt });
// return records.length;
const appKey = process.env.DINGTALK_APP_KEY;
if (!appKey) {
this.logger.warn('DingTalk not configured (DINGTALK_APP_KEY missing), skipping sync');
return 0;
}
this.logger.warn(
'DingTalk integration service not yet implemented — add DingTalkService to SyncModule to enable real sync',
);
return 0;
}
/**
* Perform the actual WeCom data pull.
* Pass `lastSyncAt` to the WeCom API for incremental sync.
*/
private async performWeComSync(_lastSyncAt: Date | null): Promise<number> {
// TODO: Call WeCom API — e.g. contacts, attendance, etc.
// const records = await this.weComClient.fetchContacts({ updatedAfter: lastSyncAt });
// return records.length;
const corpId = process.env.WECOM_CORP_ID;
if (!corpId) {
this.logger.warn('WeCom not configured (WECOM_CORP_ID missing), skipping sync');
return 0;
}
this.logger.warn(
'WeCom integration service not yet implemented — add WeComService to SyncModule to enable real sync',
);
return 0;
}
}