简道云V2.0

This commit is contained in:
z66
2025-11-14 11:04:01 +08:00
parent 073f0646a1
commit 49fc75214f
33 changed files with 1811 additions and 4454 deletions
+180 -75
View File
@@ -1,96 +1,201 @@
from fastapi import FastAPI, Request
"""
简道云 FastAPI 服务 - 主应用入口
本文件是 FastAPI 应用的主入口文件,负责:
1. 应用初始化和生命周期管理
2. 模块注册和路由配置
3. 异常处理器配置
4. 中间件配置
作者: 项目团队
版本: 1.0.0
"""
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, HTTPException, status
from fastapi.responses import JSONResponse
import json
import anyio
from fastapi.exceptions import RequestValidationError
import logging
from app.utils.app_tools import AppTools, setup_global_logger
from app.module.F6_Plugin_module import F6PluginModule
from app.module.f6_plugin_module import F6PluginModule
from app.module.module import F6Module
from app.module.other_module import OtherPluginModule
from app.config import Config
from app.schemas import ErrorResponse
from app.core import core_manager
from app.api.routes import router
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(title="简道云FastAPI服务")
@app.on_event("startup")
def on_startup():
"""应用启动时初始化"""
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理 - 启动和关闭"""
# 启动时初始化
app.state.app_tools = AppTools(Config)
app.state.logger = setup_global_logger(Config)
app.state.f6_module = F6Module()
app.state.f6_plugin_module = F6PluginModule()
app.state.other_module = OtherPluginModule()
def get_action_map() -> dict:
"""获取操作映射表"""
f6_module = app.state.f6_module
f6_plugin_module = app.state.f6_plugin_module
other_module = app.state.other_module
return {
'login_in': f6_module.accept_login_message,
'get_company_information': f6_module.get_company_information,
'get_store_information': f6_module.get_store_information,
"keep_alive": f6_module.get_keep_heart,
'check_file': f6_plugin_module.check_file,
'create_brand': f6_plugin_module.create_brand,
'delete_history': f6_plugin_module.delete_history,
'delete_customer': f6_plugin_module.delete_customer,
'delete_cars': f6_plugin_module.delete_cars,
'sms_signature_status': other_module.sms_signature_status,
'modify_customer_info': f6_plugin_module.modify_customer_info,
}
@app.post("/webhook")
async def webhook(request: Request):
"""
接受前端请求后将任务放入消息队列
Returns:
any: 返回任务处理的结果
# 初始化业务模块
f6_module = F6Module()
f6_plugin_module = F6PluginModule()
other_module = OtherPluginModule()
# 将模块实例存储到 app.state(用于依赖注入)
app.state.f6_module = f6_module
app.state.f6_plugin_module = f6_plugin_module
app.state.other_module = other_module
# 注册模块到 registry
core_manager.initialize_modules({
'f6_module': f6_module,
'f6_plugin_module': f6_plugin_module,
'other_module': other_module
})
# 注册所有操作到 module_registry
core_manager.register_action('login_in', f6_module.accept_login_message, 'f6_module',
description='F6系统登录')
core_manager.register_action('get_company_information', f6_module.get_company_information, 'f6_module',
description='获取公司信息')
core_manager.register_action('get_store_information', f6_module.get_store_information, 'f6_module',
description='获取门店信息')
core_manager.register_action('keep_alive', f6_module.get_keep_heart, 'f6_module',
description='保持连接')
core_manager.register_action('check_file', f6_plugin_module.check_file, 'f6_plugin_module',
description='校验上传文件')
core_manager.register_action('create_brand', f6_plugin_module.create_brand, 'f6_plugin_module',
description='创建品牌')
core_manager.register_action('delete_history', f6_plugin_module.delete_history, 'f6_plugin_module',
description='删除历史记录')
core_manager.register_action('delete_customer', f6_plugin_module.delete_customer, 'f6_plugin_module',
description='删除客户')
core_manager.register_action('delete_cars', f6_plugin_module.delete_cars, 'f6_plugin_module',
description='删除车辆')
core_manager.register_action('sms_signature_status', other_module.sms_signature_status, 'other_module',
description='短信签名状态')
core_manager.register_action('modify_customer_info', f6_plugin_module.modify_customer_info, 'f6_plugin_module',
description='修改客户信息')
core_manager.register_action('bi_task', f6_plugin_module.bi_task, 'f6_plugin_module',
description='BI任务')
app.state.logger.info("应用启动完成,已注册所有操作")
yield
# 关闭时清理资源
if hasattr(app.state, 'app_tools') and hasattr(app.state.app_tools, 'scheduler'):
app.state.app_tools.scheduler.shutdown(wait=False)
app.state.logger.info("应用关闭")
app = FastAPI(
title="简道云FastAPI服务",
description="简道云插件后端服务,提供数据同步和处理功能",
version="1.0.0",
lifespan=lifespan
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
app.include_router(router)
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
"""
logger = app.state.logger
app_tools: AppTools = app.state.app_tools
HTTP 异常处理器
处理所有 HTTPException 异常,返回统一的错误响应格式。
Args:
request: FastAPI 请求对象
exc: HTTPException 异常对象
Returns:
JSONResponse: 包含错误详情的 JSON 响应
"""
logger = getattr(app.state, 'logger', None)
if logger:
logger.error(f"HTTP异常: {exc.status_code} - {exc.detail}")
return JSONResponse(
status_code=exc.status_code,
content=ErrorResponse(
detail=exc.detail or "HTTP error",
error_code=f"HTTP_{exc.status_code}"
).dict(),
)
# 获取请求数据
data = await request.json()
header = request.headers
# 解码请求头
decoded_header = app_tools.decode_headers(header)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
"""
请求验证异常处理器
处理 Pydantic 数据验证失败的情况,返回详细的验证错误信息。
Args:
request: FastAPI 请求对象
exc: RequestValidationError 异常对象
Returns:
JSONResponse: 包含验证错误详情的 JSON 响应
"""
logger = getattr(app.state, 'logger', None)
if logger:
logger.warning(f"请求验证失败: {exc.errors()}")
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content=ErrorResponse(
detail="请求数据验证失败",
error_code="VALIDATION_ERROR"
).dict(),
)
# 获取操作映射表
action_map = get_action_map()
action = decoded_header.get('Action')
# 处理 F6_Plugin 特殊逻辑
if action == 'F6_Plugin':
check = decoded_header.get('Check')
if check == '':
handler = app.state.f6_plugin_module.check_file
elif check == '':
print(data)
sub_action = data.get('Action')
print(sub_action)
handler = action_map.get(sub_action, lambda x: {'msg': '未执行'})
else:
return JSONResponse({'msg': '未知的操作'})
else:
handler = action_map.get(action, lambda x: {'msg': '未知的操作'})
@app.exception_handler(Exception)
async def general_exception_handler(request: Request, exc: Exception):
"""
通用异常处理器
捕获所有未处理的异常,防止应用崩溃,并记录详细的错误信息。
Args:
request: FastAPI 请求对象
exc: 异常对象
Returns:
JSONResponse: 包含错误详情的 JSON 响应
"""
logger = getattr(app.state, 'logger', None)
if logger:
logger.error(f"未处理的异常: {type(exc).__name__} - {str(exc)}", exc_info=True)
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content=ErrorResponse(
detail="服务器内部错误",
error_code="INTERNAL_ERROR"
).dict(),
)
# 将任务放入消息队列
response_queue = app_tools.enqueue_task(handler, data)
# 等待任务处理结果
result = await anyio.to_thread.run_sync(response_queue.get)
print(handler)
logger.info(json.dumps(result, ensure_ascii=False, indent=4))
return JSONResponse(result)
# 路由已移动到 app/api/routes.py
if __name__ == '__main__':
"""
直接运行入口
当直接运行此文件时,启动 uvicorn 服务器。
默认配置:
- 主机: 0.0.0.0 (监听所有网络接口)
- 端口: 5003
- 热重载: 关闭 (生产环境建议关闭)
"""
import uvicorn
uvicorn.run("fastapi_app.main:app", host="0.0.0.0", port=5003, reload=False)
uvicorn.run(app, host="0.0.0.0", port=5003, reload=False)