import os from flask import Blueprint, abort, send_file, send_from_directory from backend.config import FRONTEND_DIST spa_bp = Blueprint("spa", __name__) def _frontend_index_path(): return os.path.join(FRONTEND_DIST, "index.html") def _has_frontend_build(): return os.path.isfile(_frontend_index_path()) def serve_spa(): if not _has_frontend_build(): return ( "前端未构建,请在 frontend 目录执行: npm install && npm run build", 503, {"Content-Type": "text/plain; charset=utf-8"}, ) return send_file(_frontend_index_path()) @spa_bp.route("/") def index(): return serve_spa() @spa_bp.route("/debug") def debug_view(): return serve_spa() @spa_bp.route("/assets/") def frontend_assets(filename): assets_dir = os.path.join(FRONTEND_DIST, "assets") if not os.path.isdir(assets_dir): abort(404) return send_from_directory(assets_dir, filename) @spa_bp.route("/") def spa_fallback(path): if path.startswith("api/") or path == "qrcode.png": abort(404) if not _has_frontend_build(): abort(404) dist_file = os.path.join(FRONTEND_DIST, path) if os.path.isfile(dist_file): return send_from_directory(FRONTEND_DIST, path) return send_file(_frontend_index_path())