2187be7aeb
本次累积提交包含以下功能: 1. 修复:el-date-picker 缺失 value-format 导致日期保存偏移(8处) 2. 新增:协同拜访 visit_group_id 去重机制(完整副本 + 周报合并 + 亮灯去重) 3. 新增:计划自动完成(创建计划检测已有拜访 / 编辑拜访触发) 4. 新增:拜访表单选择客户后自动预填过期计划内容 5. 新增:移动端主题切换按钮 + 后端持久化 6. 新增:操作日志系统 (audit_logs),全覆盖 8 个模块 CRUD 7. 新增:PC端「我的数据」支局长/领导视角客户经理列 Co-Authored-By: Claude <noreply@anthropic.com>
82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from sqlalchemy import select
|
|
from app.config import settings, validate_security_settings
|
|
from app.database import engine, async_session
|
|
from app.api import router as api_router
|
|
from app.api import auth, users, customers, visits, work_plans, mini_business, key_visits
|
|
from app.api import dashboard, upload, export, import_data, wecom, daily_notes, ai_summary, system_config, leaves, audit
|
|
from app.models.system_config import SystemConfig
|
|
from app.services.holidays import refresh_holidays
|
|
from app.services.scheduler_manager import start_scheduler, shutdown_scheduler
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
validate_security_settings()
|
|
# Read notification_time from DB (or use default 17:30)
|
|
notification_hour, notification_minute = 17, 30
|
|
async with async_session() as db:
|
|
row = await db.get(SystemConfig, "notification_time")
|
|
if row and row.value:
|
|
try:
|
|
parts = row.value.strip().split(":")
|
|
notification_hour, notification_minute = int(parts[0]), int(parts[1])
|
|
except (ValueError, IndexError):
|
|
pass
|
|
# Auto-refresh Chinese holiday data from API on startup
|
|
try:
|
|
await refresh_holidays(db)
|
|
except Exception:
|
|
pass # Use cached data if API unavailable
|
|
|
|
# Start daily reporting scheduler
|
|
start_scheduler(notification_hour, notification_minute)
|
|
|
|
yield
|
|
|
|
# Shutdown
|
|
shutdown_scheduler()
|
|
await engine.dispose()
|
|
|
|
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
version="0.1.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# CORS
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Mount all routers
|
|
app.include_router(auth.router, prefix="/api")
|
|
app.include_router(users.router, prefix="/api")
|
|
app.include_router(customers.router, prefix="/api")
|
|
app.include_router(visits.router, prefix="/api")
|
|
app.include_router(work_plans.router, prefix="/api")
|
|
app.include_router(mini_business.router, prefix="/api")
|
|
app.include_router(key_visits.router, prefix="/api")
|
|
app.include_router(dashboard.router, prefix="/api")
|
|
app.include_router(leaves.router, prefix="/api")
|
|
app.include_router(upload.router, prefix="/api")
|
|
app.include_router(export.router, prefix="/api")
|
|
app.include_router(import_data.router, prefix="/api")
|
|
app.include_router(wecom.router, prefix="/api")
|
|
app.include_router(daily_notes.router, prefix="/api")
|
|
app.include_router(ai_summary.router, prefix="/api")
|
|
app.include_router(system_config.router, prefix="/api")
|
|
app.include_router(audit.router, prefix="/api")
|
|
|
|
|
|
@app.get("/health")
|
|
async def health_check():
|
|
return {"status": "ok", "app": settings.APP_NAME}
|