init: EasyScreen 电子菜单系统
- server: FastAPI 后端(多屏管理、素材上传、节目编排、客户端注册/配置/心跳/崩溃上报、管理台托管) - android: Java 客户端(minSdk 23,全屏图片/视频轮播、远程配置、开机自启、崩溃上报) - web: React + Vite + antd 管理台(屏幕/素材/节目管理) - 屏幕设备 ID 关联机制、gunicorn 生产部署脚本
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
"""EasyScreen 后端入口。"""
|
||||
import os
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import FileResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
from .config import get_server_config
|
||||
from .database import Base, _engine
|
||||
from .routers import admin_assets, admin_auth, admin_playlists, admin_screens, client
|
||||
|
||||
app = FastAPI(title="EasyScreen 电子菜单后台", version="1.0.0")
|
||||
|
||||
# 开发期允许前端跨域(Vite dev server);生产建议同域部署或收紧来源
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# 自动建表
|
||||
Base.metadata.create_all(bind=_engine)
|
||||
|
||||
# 媒体文件访问(客户端播放地址 /media/{file})
|
||||
_upload_dir = os.path.abspath(
|
||||
os.path.join(os.path.dirname(os.path.dirname(__file__)), get_server_config().get("upload_dir", "./uploads"))
|
||||
)
|
||||
os.makedirs(_upload_dir, exist_ok=True)
|
||||
app.mount("/media", StaticFiles(directory=_upload_dir), name="media")
|
||||
|
||||
app.include_router(admin_auth.router)
|
||||
app.include_router(admin_screens.router)
|
||||
app.include_router(admin_assets.router)
|
||||
app.include_router(admin_playlists.router)
|
||||
app.include_router(client.router)
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
def health():
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
# ---------------- 管理台静态托管(生产单端口部署) ----------------
|
||||
# 若存在 web/dist(npm run build 产物),则由本服务直接托管管理台。
|
||||
# 注意:/api 与 /media 路由已在上方注册,此处 catch-all 仅兜底前端路由。
|
||||
_WEB_DIST = os.path.abspath(
|
||||
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "web", "dist")
|
||||
)
|
||||
|
||||
|
||||
@app.get("/{full_path:path}", include_in_schema=False)
|
||||
def serve_web(full_path: str):
|
||||
if not os.path.isdir(_WEB_DIST):
|
||||
return {"message": "EasyScreen API 运行中。管理台未构建:请在 web/ 目录执行 npm run build"}
|
||||
# 优先返回真实文件(JS/CSS/图片等),其余路径回退到 index.html(SPA 路由)
|
||||
file_path = os.path.join(_WEB_DIST, full_path)
|
||||
if full_path and os.path.isfile(file_path):
|
||||
return FileResponse(file_path)
|
||||
return FileResponse(os.path.join(_WEB_DIST, "index.html"))
|
||||
Reference in New Issue
Block a user