feat(api): 使用FastAPI重构招聘者账号管理与启动服务器

- 移除旧的命令行工具add_recruiter.py和main.py,统一改用API方式管理招聘者账号
- 新增FastAPI应用,提供招聘者账号的CRUD接口及激活/停用功能
- 添加CORS中间件,支持跨域请求
- 支持通过API接口创建、查询、更新、删除招聘者账号,并返回标准化响应
- 集成异步后台定时任务调度器,定时爬取Boss直聘简历和分析报告
- 新增run_server.py启动脚本,支持启动FastAPI服务器和定时任务调度器的组合应用
- 定时任务支持任务列表查询、暂停、恢复及手动触发爬取任务的API
- 更新pyproject.toml依赖,新增fastapi、uvicorn和apscheduler等库
- 优化系统架构,实现Web API和后台调度功能解耦与整合,提高系统扩展性及易用性
This commit is contained in:
2026-03-24 14:50:50 +08:00
parent 04596d298b
commit 3c29ca04eb
7 changed files with 901 additions and 202 deletions

125
run_server.py Normal file
View File

@@ -0,0 +1,125 @@
"""Server with API and Background Scheduler
Usage:
uv run python run_server.py
uv run python run_server.py --host 0.0.0.0 --port 8000
uv run python run_server.py --no-scheduler # 只启动API不启动定时任务
"""
import argparse
import sys
import asyncio
from pathlib import Path
# 添加源码路径
src_path = Path(__file__).parent / "src" / "main" / "python"
if str(src_path) not in sys.path:
sys.path.insert(0, str(src_path))
import uvicorn
from fastapi import FastAPI
from cn.yinlihupo.ylhp_hr_2_0.controller.api import create_app
from cn.yinlihupo.ylhp_hr_2_0.service.scheduler import get_scheduler
def create_combined_app(enable_scheduler: bool = True) -> FastAPI:
"""创建组合应用API + 定时任务)"""
app = create_app()
if enable_scheduler:
@app.on_event("startup")
async def start_scheduler():
"""应用启动时启动定时任务"""
scheduler = get_scheduler()
scheduler.start()
@app.on_event("shutdown")
async def stop_scheduler():
"""应用关闭时停止定时任务"""
scheduler = get_scheduler()
scheduler.stop()
# 添加调度器管理接口
@app.get("/api/scheduler/jobs")
async def list_scheduler_jobs():
"""获取定时任务列表"""
scheduler = get_scheduler()
return {"jobs": scheduler.get_jobs()}
@app.post("/api/scheduler/jobs/{job_id}/pause")
async def pause_scheduler_job(job_id: str):
"""暂停定时任务"""
scheduler = get_scheduler()
scheduler.pause_job(job_id)
return {"success": True, "message": f"Job {job_id} paused"}
@app.post("/api/scheduler/jobs/{job_id}/resume")
async def resume_scheduler_job(job_id: str):
"""恢复定时任务"""
scheduler = get_scheduler()
scheduler.resume_job(job_id)
return {"success": True, "message": f"Job {job_id} resumed"}
@app.post("/api/scheduler/trigger/crawl")
async def trigger_crawl():
"""手动触发爬取任务"""
scheduler = get_scheduler()
asyncio.create_task(scheduler._crawl_boss())
return {"success": True, "message": "Crawl task triggered"}
return app
def main():
parser = argparse.ArgumentParser(description="简历智能体服务器 (API + 定时任务)")
parser.add_argument("--host", default="0.0.0.0", help="绑定主机 (默认: 0.0.0.0)")
parser.add_argument("--port", "-p", type=int, default=8000, help="绑定端口 (默认: 8000)")
parser.add_argument("--reload", action="store_true", help="启用热重载 (开发模式)")
parser.add_argument("--no-scheduler", action="store_true", help="不启动定时任务")
args = parser.parse_args()
enable_scheduler = not args.no_scheduler
mode = "API + 定时任务" if enable_scheduler else "仅API"
print(f"""
╔══════════════════════════════════════════════════════════════╗
║ 简历智能体服务器 ║
║ 模式: {mode:<20}
╠══════════════════════════════════════════════════════════════╣
║ 文档地址: http://{args.host}:{args.port}/docs ║
║ API地址: http://{args.host}:{args.port}/api ║
╚══════════════════════════════════════════════════════════════╝
""")
# 创建组合应用
if args.reload:
# 热重载模式需要使用导入字符串
import os
os.environ["ENABLE_SCHEDULER"] = "true" if enable_scheduler else "false"
uvicorn.run(
"run_server:app",
host=args.host,
port=args.port,
reload=True
)
else:
app = create_combined_app(enable_scheduler=enable_scheduler)
uvicorn.run(
app,
host=args.host,
port=args.port,
reload=False
)
# 全局应用实例(用于热重载模式)
app = None
if __name__ == "__main__":
main()
else:
# 作为模块导入时(热重载模式)
import os
enable_scheduler = os.environ.get("ENABLE_SCHEDULER", "true") == "true"
app = create_combined_app(enable_scheduler=enable_scheduler)