feat: migrate ORM base to sqlmodel-ext, add file viewers and WOPI integration
All checks were successful
Test / test (push) Successful in 1m45s
All checks were successful
Test / test (push) Successful in 1m45s
- Migrate SQLModel base classes, mixins, and database management to external sqlmodel-ext package; remove sqlmodels/base/, sqlmodels/mixin/, and sqlmodels/database.py - Add file viewer/editor system with WOPI protocol support for collaborative editing (OnlyOffice, Collabora) - Add enterprise edition license verification module (ee/) - Add Dockerfile multi-stage build with Cython compilation support - Add new dependencies: sqlmodel-ext, cryptography, whatthepatch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
61
main.py
61
main.py
@@ -1,16 +1,40 @@
|
||||
from pathlib import Path
|
||||
from typing import NoReturn
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from loguru import logger as l
|
||||
|
||||
from utils.conf import appmeta
|
||||
from utils.http.http_exceptions import raise_internal_error
|
||||
from utils.lifespan import lifespan
|
||||
from routers import router
|
||||
from service.redis import RedisManager
|
||||
from sqlmodels.database_connection import DatabaseManager
|
||||
from sqlmodels.migration import migration
|
||||
from utils import JWT
|
||||
from routers import router
|
||||
from service.redis import RedisManager
|
||||
from loguru import logger as l
|
||||
from utils.conf import appmeta
|
||||
from utils.http.http_exceptions import raise_internal_error
|
||||
from utils.lifespan import lifespan
|
||||
|
||||
# 尝试加载企业版功能
|
||||
try:
|
||||
from ee import init_ee
|
||||
from ee.license import LicenseError
|
||||
|
||||
async def _init_ee_and_routes() -> None:
|
||||
try:
|
||||
await init_ee()
|
||||
except LicenseError as exc:
|
||||
l.critical(f"许可证验证失败: {exc}")
|
||||
raise SystemExit(1) from exc
|
||||
|
||||
from ee.routers import ee_router
|
||||
from routers.api.v1 import router as v1_router
|
||||
v1_router.include_router(ee_router)
|
||||
|
||||
lifespan.add_startup(_init_ee_and_routes)
|
||||
except ImportError:
|
||||
l.info("以 Community 版本运行")
|
||||
|
||||
STATICS_DIR: Path = (Path(__file__).parent / "statics").resolve()
|
||||
"""前端静态文件目录(由 Docker 构建时复制)"""
|
||||
|
||||
async def _init_db() -> None:
|
||||
"""初始化数据库连接引擎"""
|
||||
@@ -64,6 +88,31 @@ async def handle_unexpected_exceptions(
|
||||
# 挂载路由
|
||||
app.include_router(router)
|
||||
|
||||
# 挂载前端静态文件(仅当 statics/ 目录存在时,即 Docker 部署环境)
|
||||
if STATICS_DIR.is_dir():
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
_assets_dir: Path = STATICS_DIR / "assets"
|
||||
if _assets_dir.is_dir():
|
||||
app.mount("/assets", StaticFiles(directory=_assets_dir), name="assets")
|
||||
|
||||
@app.get("/{path:path}")
|
||||
async def spa_fallback(path: str) -> FileResponse:
|
||||
"""
|
||||
SPA fallback 路由
|
||||
|
||||
优先级:API 路由 > /assets 静态挂载 > 此 catch-all 路由。
|
||||
若请求路径对应 statics/ 下的真实文件则直接返回,否则返回 index.html。
|
||||
"""
|
||||
file_path: Path = (STATICS_DIR / path).resolve()
|
||||
# 防止路径穿越
|
||||
if file_path.is_relative_to(STATICS_DIR) and path and file_path.is_file():
|
||||
return FileResponse(file_path)
|
||||
return FileResponse(STATICS_DIR / "index.html")
|
||||
|
||||
l.info(f"前端静态文件已挂载: {STATICS_DIR}")
|
||||
|
||||
# 防止直接运行 main.py
|
||||
if __name__ == "__main__":
|
||||
l.error("请用 fastapi ['dev', 'run'] 命令启动服务")
|
||||
|
||||
Reference in New Issue
Block a user