From d9de3fe784aed57532b817a678735c4ac981d210 Mon Sep 17 00:00:00 2001 From: dekun Date: Fri, 14 Aug 2026 18:00:56 +0800 Subject: [PATCH] Restore shared CSS/JS static mounts for standalone deploy. Embed UI looked unstyled because hub_bridge no longer registers lib/common/static. Co-authored-by: Cursor --- app.py | 2 + lib/instance/instance_static_lib.py | 68 +++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 lib/instance/instance_static_lib.py diff --git a/app.py b/app.py index ce65878..65ad1b5 100644 --- a/app.py +++ b/app.py @@ -233,8 +233,10 @@ def resolve_path(path_value): app = Flask(__name__) app.secret_key = os.getenv("FLASK_SECRET_KEY") or os.urandom(32) from lib.instance.instance_embed_lib import attach_embed_templates, redirect_to_embed_shell_if_enabled +from lib.instance.instance_static_lib import install_common_static attach_embed_templates(app, _REPO_ROOT) +install_common_static(app, _REPO_ROOT) # ====================== 登录配置 ====================== # 独立部署须在 .env 配置账号;勿在源码写真实口令 diff --git a/lib/instance/instance_static_lib.py b/lib/instance/instance_static_lib.py new file mode 100644 index 0000000..c1b18ec --- /dev/null +++ b/lib/instance/instance_static_lib.py @@ -0,0 +1,68 @@ +"""Serve shared UI assets from lib/common/static under /static/*.""" +from __future__ import annotations + +import os + +from flask import Flask, Response, send_file + +from lib.paths import common_static_dir + +# mime by extension; listed names are served from lib/common/static +_COMMON_STATIC_ASSETS: dict[str, str] = { + "instance_theme.js": "application/javascript; charset=utf-8", + "instance_theme_early.css": "text/css; charset=utf-8", + "instance_theme.css": "text/css; charset=utf-8", + "account_risk_badge.css": "text/css; charset=utf-8", + "account_risk_badge.js": "application/javascript; charset=utf-8", + "instance_ui.js": "application/javascript; charset=utf-8", + "instance_records_mobile.js": "application/javascript; charset=utf-8", + "records_review_page.js": "application/javascript; charset=utf-8", + "form_submit_guard.js": "application/javascript; charset=utf-8", + "autofill_guard.js": "application/javascript; charset=utf-8", + "open_submit_gate.js": "application/javascript; charset=utf-8", + "key_monitor_form.js": "application/javascript; charset=utf-8", + "time_close_ui.js": "application/javascript; charset=utf-8", + "manual_order_rr_preview.js": "application/javascript; charset=utf-8", + "symbol_live_price.js": "application/javascript; charset=utf-8", + "journal_upload_slots.js": "application/javascript; charset=utf-8", + "journal_form_save.js": "application/javascript; charset=utf-8", + "instance_page.css": "text/css; charset=utf-8", + "instance_embed.js": "application/javascript; charset=utf-8", + "instance_mobile_nav.js": "application/javascript; charset=utf-8", + "instance_stats.js": "application/javascript; charset=utf-8", + "instance_live.js": "application/javascript; charset=utf-8", + "instance_settings_prefs.js": "application/javascript; charset=utf-8", + "instance_dashboard.js": "application/javascript; charset=utf-8", + "account_ledger.js": "application/javascript; charset=utf-8", + "options_expiry_countdown.js": "application/javascript; charset=utf-8", + "options_panel.js": "application/javascript; charset=utf-8", + "options_settings.js": "application/javascript; charset=utf-8", + "options_position_cards.js": "application/javascript; charset=utf-8", + "options_review.js": "application/javascript; charset=utf-8", + "hedge_plan.js": "application/javascript; charset=utf-8", + "order_entry_model.js": "application/javascript; charset=utf-8", + "focus_chart_page.js": "application/javascript; charset=utf-8", + "focus_chart_page.css": "text/css; charset=utf-8", + "trade_stats_calendar.js": "application/javascript; charset=utf-8", + "trade_stats_calendar.css": "text/css; charset=utf-8", +} + + +def install_common_static(app: Flask, repo_root: str | None = None) -> None: + """Register /static/ for shared CSS/JS (replaces hub_bridge mount).""" + repo_static = common_static_dir(repo_root) + for name, mime in _COMMON_STATIC_ASSETS.items(): + path = os.path.join(repo_static, name) + + def _view(p: str = path, m: str = mime): + if not os.path.isfile(p): + return Response("not found", status=404, mimetype="text/plain; charset=utf-8") + return send_file(p, mimetype=m) + + endpoint = f"common_static_{name.replace('.', '_').replace('-', '_')}" + # 覆盖同名旧路由(若有),确保样式一定从 lib/common/static 提供 + try: + app.add_url_rule(f"/static/{name}", endpoint=endpoint, view_func=_view) + except AssertionError: + # endpoint 已存在时替换 view + app.view_functions[endpoint] = _view