修复bug
This commit is contained in:
@@ -6394,6 +6394,10 @@ def strategy_roll_page():
|
||||
return redirect("/strategy")
|
||||
|
||||
|
||||
# 根目录 strategy_* 与币安/Gate 共用同一套属性名(OKX 内部仍用 normalize_okx_symbol / ensure_okx_live_ready)
|
||||
normalize_exchange_symbol = normalize_okx_symbol
|
||||
ensure_exchange_live_ready = ensure_okx_live_ready
|
||||
|
||||
from strategy_register import install_strategy_trading
|
||||
from strategy_trend_register import install_strategy_trend
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ HUB_PORT=5100
|
||||
# HUB_BRIDGE_TOKEN=your-long-random-token
|
||||
|
||||
# 逗号分隔的账户 id,强制关闭(不参与监控/全局全平;设置页对应行勾选框灰掉)
|
||||
# 默认 1 = OKX;不用 OKX 可保持;要用 OKX 请删掉本行或改为空
|
||||
HUB_DISABLED_IDS=1
|
||||
# 留空 = 不强制关闭;仅不想用 OKX 时可设 HUB_DISABLED_IDS=1
|
||||
HUB_DISABLED_IDS=
|
||||
|
||||
# true=允许 RFC1918 私网访问中控页面;false=仅 127.0.0.1
|
||||
HUB_TRUST_LAN=true
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
"""加载 manual_trading_hub/.env(Windows 直接 python hub.py 时也需要)。"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
HUB_DIR = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def load_hub_dotenv() -> None:
|
||||
path = HUB_DIR / ".env"
|
||||
if not path.is_file():
|
||||
return
|
||||
raw_bytes = path.read_bytes()
|
||||
text = ""
|
||||
for enc in ("utf-8-sig", "utf-16", "utf-16-le", "utf-16-be"):
|
||||
try:
|
||||
text = raw_bytes.decode(enc)
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
if not text:
|
||||
text = raw_bytes.decode("utf-8", errors="ignore")
|
||||
text = text.replace("\x00", "")
|
||||
for line in text.splitlines():
|
||||
raw = line.strip()
|
||||
if not raw or raw.startswith("#") or "=" not in raw:
|
||||
continue
|
||||
key, value = raw.split("=", 1)
|
||||
clean_key = key.strip().lstrip("\ufeff")
|
||||
if not clean_key.replace("_", "").isalnum():
|
||||
continue
|
||||
clean_value = value.strip().strip('"').strip("'")
|
||||
os.environ[clean_key] = clean_value
|
||||
@@ -8,6 +8,10 @@ import asyncio
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from env_load import load_hub_dotenv
|
||||
|
||||
load_hub_dotenv()
|
||||
|
||||
import httpx
|
||||
from fastapi import Body, FastAPI, HTTPException, Request
|
||||
from fastapi.responses import FileResponse, JSONResponse
|
||||
@@ -39,7 +43,7 @@ HUB_BRIDGE_TOKEN = (os.getenv("HUB_BRIDGE_TOKEN") or os.getenv("CONTROL_TOKEN")
|
||||
_trust_raw = (os.getenv("HUB_TRUST_LAN", "true") or "").strip().lower()
|
||||
HUB_TRUST_LAN = _trust_raw not in ("0", "false", "no", "off")
|
||||
DIR = Path(__file__).resolve().parent
|
||||
HUB_BUILD = "20260521-no-trade-ui"
|
||||
HUB_BUILD = "20260522-settings-fix"
|
||||
|
||||
|
||||
def _is_local(host: str | None) -> bool:
|
||||
@@ -224,9 +228,17 @@ class SettingsBody(BaseModel):
|
||||
|
||||
@app.post("/api/settings")
|
||||
def api_save_settings(body: SettingsBody):
|
||||
data = {"version": 1, "exchanges": body.exchanges}
|
||||
save_settings(data)
|
||||
return {"ok": True}
|
||||
force_off = env_force_disabled_ids()
|
||||
to_save = []
|
||||
for ex in body.exchanges:
|
||||
row = dict(ex)
|
||||
eid = str(row.get("id", "")).strip()
|
||||
if eid in force_off:
|
||||
row["enabled"] = False
|
||||
row.pop("env_disabled", None)
|
||||
to_save.append(row)
|
||||
save_settings({"version": 1, "exchanges": to_save})
|
||||
return {"ok": True, "settings": load_settings()}
|
||||
|
||||
|
||||
@app.get("/api/settings/meta")
|
||||
@@ -438,6 +450,8 @@ def api_ping():
|
||||
"trade_ui": False,
|
||||
"features": ["monitor", "settings", "auth"],
|
||||
"password_required": password_required(),
|
||||
"env_disabled_ids": sorted(env_force_disabled_ids()),
|
||||
"hub_disabled_ids_raw": (os.getenv("HUB_DISABLED_IDS") or ""),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ DEFAULT_EXCHANGES = [
|
||||
"agent_url": "http://127.0.0.1:15201",
|
||||
"flask_url": "http://127.0.0.1:5004",
|
||||
"review_url": "http://127.0.0.1:5004/records",
|
||||
"enabled": False,
|
||||
"enabled": True,
|
||||
"capabilities": ["key", "trend"],
|
||||
},
|
||||
{
|
||||
@@ -60,7 +60,8 @@ def _ids_from_csv(raw: str | None) -> set[str]:
|
||||
|
||||
|
||||
def env_force_disabled_ids() -> set[str]:
|
||||
raw = os.getenv("HUB_DISABLED_IDS", "1").strip()
|
||||
# 未设置时默认不强制关闭任何账户;要用旧行为可设 HUB_DISABLED_IDS=1
|
||||
raw = (os.getenv("HUB_DISABLED_IDS") or "").strip()
|
||||
return _ids_from_csv(raw)
|
||||
|
||||
|
||||
|
||||
@@ -270,8 +270,11 @@
|
||||
else parts.push("中控未设 HUB_BRIDGE_TOKEN(实例需 APP_AUTH_DISABLED 或同令牌)");
|
||||
if (m.public_origin) parts.push("浏览器外链基址: " + m.public_origin);
|
||||
else parts.push("未设 HUB_PUBLIC_ORIGIN(复盘链接仅本机可开)");
|
||||
if ((m.env_disabled_ids || []).length)
|
||||
parts.push("环境强制关闭 id: " + m.env_disabled_ids.join(", "));
|
||||
if ((m.env_disabled_ids || []).length) {
|
||||
parts.push("环境强制关闭 id: " + m.env_disabled_ids.join(", ") + "(改 .env 后须重启 hub)");
|
||||
} else {
|
||||
parts.push("HUB_DISABLED_IDS 未强制关闭任何账户");
|
||||
}
|
||||
el.textContent = parts.join(" · ");
|
||||
} catch (_) {}
|
||||
}
|
||||
@@ -361,7 +364,13 @@
|
||||
const j = await r.json();
|
||||
if (j.ok) {
|
||||
showToast("设置已保存(已写入 hub_settings.json)");
|
||||
if (j.settings) {
|
||||
settingsCache = j.settings;
|
||||
renderSettingsList(j.settings);
|
||||
loadSettingsMetaLine();
|
||||
} else {
|
||||
await loadSettingsUI();
|
||||
}
|
||||
} else showToast("保存失败", true);
|
||||
} catch (e) {
|
||||
showToast(String(e), true);
|
||||
@@ -395,10 +404,12 @@
|
||||
});
|
||||
settingsCache = data;
|
||||
renderSettingsList(data);
|
||||
showToast("已添加一行,请填写 URL 后点「保存设置」");
|
||||
};
|
||||
|
||||
initAuth().then((ok) => {
|
||||
if (!ok) return;
|
||||
loadSettings().catch(() => {});
|
||||
setActiveNav();
|
||||
window.addEventListener("popstate", setActiveNav);
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="/assets/app.css" />
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260522-settings-fix" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-bg" aria-hidden="true"></div>
|
||||
@@ -80,6 +80,6 @@
|
||||
</div>
|
||||
|
||||
<div id="toast"></div>
|
||||
<script src="/assets/app.js"></script>
|
||||
<script src="/assets/app.js?v=20260522-settings-fix"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user