feat: 添加通讯录自动同步功能
Some checks failed
continuous-integration/drone/push Build is failing

- 添加 APScheduler 依赖
- 创建定时任务调度模块 scheduler.py
- 增量同步:每30分钟执行
- 完整同步:每天凌晨2点执行
- 添加定时任务管理 API
- 支持环境变量配置同步参数
This commit is contained in:
yuliang_guo
2026-01-29 15:19:20 +08:00
parent 174929d599
commit c97a09de35
6 changed files with 364 additions and 0 deletions

View File

@@ -234,3 +234,95 @@ async def get_sync_status(
detail=f"查询统计信息失败: {str(e)}"
)
@router.get("/scheduler/jobs", summary="查看定时同步任务")
async def get_scheduler_jobs(
*,
current_user: User = Depends(get_current_user)
) -> Dict[str, Any]:
"""
查看定时同步任务列表
权限要求: 仅管理员可查看
Returns:
定时任务列表,包含下次执行时间等信息
"""
if current_user.role != 'admin':
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="只有管理员可以查看定时任务"
)
try:
from app.core.scheduler import scheduler_manager
jobs = scheduler_manager.get_jobs()
return {
"success": True,
"message": "获取定时任务成功",
"data": {
"auto_sync_enabled": scheduler_manager.AUTO_SYNC_ENABLED,
"incremental_sync_interval_minutes": scheduler_manager.INCREMENTAL_SYNC_INTERVAL_MINUTES,
"full_sync_hour": scheduler_manager.FULL_SYNC_HOUR,
"jobs": jobs
}
}
except Exception as e:
logger.error(f"获取定时任务失败: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取定时任务失败: {str(e)}"
)
@router.post("/scheduler/trigger/{job_id}", summary="手动触发定时任务")
async def trigger_scheduler_job(
*,
job_id: str,
current_user: User = Depends(get_current_user)
) -> Dict[str, Any]:
"""
手动触发指定的定时任务
权限要求: 仅管理员可执行
Args:
job_id: 任务ID (employee_incremental_sync 或 employee_full_sync)
Returns:
任务执行结果
"""
if current_user.role != 'admin':
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="只有管理员可以触发定时任务"
)
logger.info(f"管理员 {current_user.username} 手动触发定时任务: {job_id}")
try:
from app.core.scheduler import scheduler_manager
result = await scheduler_manager.trigger_job(job_id)
return {
"success": True,
"message": f"任务 {job_id} 执行完成",
"data": result
}
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=str(e)
)
except Exception as e:
logger.error(f"触发定时任务失败: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"触发定时任务失败: {str(e)}"
)