修复中控
This commit is contained in:
@@ -42,3 +42,19 @@
|
|||||||
# NAV_HUB_PASSWORD=你的中控密码
|
# NAV_HUB_PASSWORD=你的中控密码
|
||||||
# 打开标记为「复盘中控」的服务时自动代登录(1=开启)
|
# 打开标记为「复盘中控」的服务时自动代登录(1=开启)
|
||||||
# NAV_HUB_AUTO_LOGIN=1
|
# NAV_HUB_AUTO_LOGIN=1
|
||||||
|
|
||||||
|
# ---------- gate_scout_order(Gate 扫单,多在云服务器)----------
|
||||||
|
# 本机 LocalNav 内嵌打开云上扫描端 / 执行器(须 Nginx 反代 + 允许 iframe,见 gate_scout 部署说明 §13)
|
||||||
|
# NAV_SEED_GATE_SCOUT=1
|
||||||
|
# NAV_GATE_SCOUT_UPDATE=1
|
||||||
|
# 方式 A:同一域名不同端口(防火墙已放行 8088/8090)
|
||||||
|
# NAV_GATE_SCOUT_SCHEME=https
|
||||||
|
# NAV_GATE_SCOUT_HOST=你的云服务器域名或IP
|
||||||
|
# NAV_GATE_SCOUT_PORT=8088
|
||||||
|
# NAV_GATE_EXECUTOR_PORT=8090
|
||||||
|
# 方式 B:两个子域名反代到 8088 / 8090(推荐,端口填 443)
|
||||||
|
# NAV_GATE_SCOUT_SCHEME=https
|
||||||
|
# NAV_GATE_SCOUT_SCOUT_HOST=scout.你的域名
|
||||||
|
# NAV_GATE_EXECUTOR_HOST=exec.你的域名
|
||||||
|
# NAV_GATE_SCOUT_PORT=443
|
||||||
|
# NAV_GATE_EXECUTOR_PORT=443
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ def create_app() -> Flask:
|
|||||||
_migrate_schema()
|
_migrate_schema()
|
||||||
_ensure_default_user()
|
_ensure_default_user()
|
||||||
_ensure_admin_from_env()
|
_ensure_admin_from_env()
|
||||||
|
_ensure_gate_scout_services()
|
||||||
|
|
||||||
@app.route("/login", methods=["GET", "POST"])
|
@app.route("/login", methods=["GET", "POST"])
|
||||||
def login():
|
def login():
|
||||||
@@ -576,6 +577,92 @@ def _ensure_default_user() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_gate_scout_services() -> None:
|
||||||
|
"""gate_scout_order:扫描端 + 执行器(NAV_SEED_GATE_SCOUT=1;云服务器用域名 + https)。"""
|
||||||
|
flag = (os.environ.get("NAV_SEED_GATE_SCOUT") or "").strip().lower()
|
||||||
|
if flag not in ("1", "true", "yes", "on"):
|
||||||
|
return
|
||||||
|
|
||||||
|
scheme = (os.environ.get("NAV_GATE_SCOUT_SCHEME") or "http").strip().lower()
|
||||||
|
if scheme not in ("http", "https"):
|
||||||
|
scheme = "http"
|
||||||
|
default_host = (os.environ.get("NAV_GATE_SCOUT_HOST") or "127.0.0.1").strip() or "127.0.0.1"
|
||||||
|
scout_host = (os.environ.get("NAV_GATE_SCOUT_SCOUT_HOST") or default_host).strip() or default_host
|
||||||
|
exec_host = (os.environ.get("NAV_GATE_EXECUTOR_HOST") or default_host).strip() or default_host
|
||||||
|
default_port = "443" if scheme == "https" else "8088"
|
||||||
|
default_exec_port = "443" if scheme == "https" else "8090"
|
||||||
|
try:
|
||||||
|
scout_port = int(os.environ.get("NAV_GATE_SCOUT_PORT") or default_port)
|
||||||
|
exec_port = int(os.environ.get("NAV_GATE_EXECUTOR_PORT") or default_exec_port)
|
||||||
|
except ValueError:
|
||||||
|
scout_port = 443 if scheme == "https" else 8088
|
||||||
|
exec_port = 443 if scheme == "https" else 8090
|
||||||
|
|
||||||
|
scout_path = (os.environ.get("NAV_GATE_SCOUT_PATH") or "/dashboard").strip() or "/dashboard"
|
||||||
|
exec_path = (os.environ.get("NAV_GATE_EXECUTOR_PATH") or "/dashboard").strip() or "/dashboard"
|
||||||
|
if not scout_path.startswith("/"):
|
||||||
|
scout_path = "/" + scout_path
|
||||||
|
if not exec_path.startswith("/"):
|
||||||
|
exec_path = "/" + exec_path
|
||||||
|
|
||||||
|
update_existing = (os.environ.get("NAV_GATE_SCOUT_UPDATE") or "").strip().lower() in (
|
||||||
|
"1",
|
||||||
|
"true",
|
||||||
|
"yes",
|
||||||
|
"on",
|
||||||
|
)
|
||||||
|
|
||||||
|
group_name = (os.environ.get("NAV_GATE_SCOUT_GROUP") or "Gate 扫单").strip() or "Gate 扫单"
|
||||||
|
g = ServiceGroup.query.filter_by(name=group_name).first()
|
||||||
|
if not g:
|
||||||
|
g = ServiceGroup(name=group_name, sort_order=50)
|
||||||
|
db.session.add(g)
|
||||||
|
db.session.flush()
|
||||||
|
|
||||||
|
defs = (
|
||||||
|
("Gate 扫描端", scout_host, scout_port, scout_path, 0),
|
||||||
|
("Gate 下单执行器", exec_host, exec_port, exec_path, 10),
|
||||||
|
)
|
||||||
|
added = 0
|
||||||
|
updated = 0
|
||||||
|
for name, h, port, path, order in defs:
|
||||||
|
existing = Service.query.filter_by(group_id=g.id, name=name).first()
|
||||||
|
if existing:
|
||||||
|
if update_existing and (
|
||||||
|
existing.scheme != scheme
|
||||||
|
or existing.host != h
|
||||||
|
or existing.port != port
|
||||||
|
or existing.path != path
|
||||||
|
):
|
||||||
|
existing.scheme = scheme
|
||||||
|
existing.host = h
|
||||||
|
existing.port = port
|
||||||
|
existing.path = path
|
||||||
|
updated += 1
|
||||||
|
continue
|
||||||
|
db.session.add(
|
||||||
|
Service(
|
||||||
|
name=name,
|
||||||
|
scheme=scheme,
|
||||||
|
host=h,
|
||||||
|
port=port,
|
||||||
|
path=path,
|
||||||
|
sort_order=order,
|
||||||
|
group_id=g.id,
|
||||||
|
embed_kind="",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
added += 1
|
||||||
|
if added or updated:
|
||||||
|
db.session.commit()
|
||||||
|
print(
|
||||||
|
f"[nav] Gate 扫单:新增 {added}、更新 {updated}(分组「{group_name}」)。"
|
||||||
|
f" 扫描 {scheme}://{scout_host}:{scout_port}{scout_path};"
|
||||||
|
f"执行器 {scheme}://{exec_host}:{exec_port}{exec_path}",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _ensure_admin_from_env() -> None:
|
def _ensure_admin_from_env() -> None:
|
||||||
"""库中已有用户后,.env 里的管理员账号不会自动覆盖旧库;若配置了用户名且尚不存在则补建。"""
|
"""库中已有用户后,.env 里的管理员账号不会自动覆盖旧库;若配置了用户名且尚不存在则补建。"""
|
||||||
username = (os.environ.get("NAV_ADMIN_USERNAME") or "").strip()
|
username = (os.environ.get("NAV_ADMIN_USERNAME") or "").strip()
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""向 LocalNav SQLite 写入 gate_scout_order 两个服务(可重复执行,已存在则跳过)。"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
if str(_ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(_ROOT))
|
||||||
|
|
||||||
|
os.environ.setdefault("NAV_SEED_GATE_SCOUT", "1")
|
||||||
|
|
||||||
|
from app import app, db # noqa: E402
|
||||||
|
from app import _ensure_gate_scout_services # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
with app.app_context():
|
||||||
|
_ensure_gate_scout_services()
|
||||||
|
db.session.commit()
|
||||||
|
print("完成。请刷新本地导航首页查看「Gate 扫单」分组。")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
+44
@@ -276,6 +276,50 @@ HUB_EMBED_PARENT_ORIGINS=https://你的中控域名,http://192.168.x.x:5070
|
|||||||
|
|
||||||
(`5070` 换成本地导航实际地址;与中控相同的 `HUB_BRIDGE_TOKEN` 必填。)
|
(`5070` 换成本地导航实际地址;与中控相同的 `HUB_BRIDGE_TOKEN` 必填。)
|
||||||
|
|
||||||
|
### 8.7 gate_scout_order(Gate 扫单)接入
|
||||||
|
|
||||||
|
**gate_scout 通常部署在云服务器**;本地导航在本机/局域网,通过 iframe 打开云上面板(不是 `127.0.0.1`)。
|
||||||
|
|
||||||
|
**1. 云上**(Nginx 反代示例):
|
||||||
|
|
||||||
|
| 服务 | 本机端口 | 建议对外 |
|
||||||
|
|------|----------|----------|
|
||||||
|
| 扫描端 | 8088 | `https://scout.你的域名` → `127.0.0.1:8088` |
|
||||||
|
| 执行器 | 8090 | `https://exec.你的域名` → `127.0.0.1:8090` |
|
||||||
|
|
||||||
|
进程环境变量(允许被本地导航嵌入):
|
||||||
|
|
||||||
|
```env
|
||||||
|
NAV_ALLOW_EMBED=true
|
||||||
|
NAV_EMBED_ORIGINS=http://192.168.8.6:5070
|
||||||
|
```
|
||||||
|
|
||||||
|
`5070` 换成本地访问 LocalNav 的地址(可逗号分隔多个)。
|
||||||
|
|
||||||
|
**2. 本机 LocalNav `.env`:**
|
||||||
|
|
||||||
|
```env
|
||||||
|
NAV_SEED_GATE_SCOUT=1
|
||||||
|
NAV_GATE_SCOUT_UPDATE=1
|
||||||
|
NAV_GATE_SCOUT_SCHEME=https
|
||||||
|
NAV_GATE_SCOUT_SCOUT_HOST=scout.你的域名
|
||||||
|
NAV_GATE_EXECUTOR_HOST=exec.你的域名
|
||||||
|
NAV_GATE_SCOUT_PORT=443
|
||||||
|
NAV_GATE_EXECUTOR_PORT=443
|
||||||
|
```
|
||||||
|
|
||||||
|
若云上直接暴露端口、无子域名,可改用同一 `NAV_GATE_SCOUT_HOST=云IP或域名`,端口 `8088` / `8090`。
|
||||||
|
|
||||||
|
**3. 重启 LocalNav**,或在项目目录执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAV_SEED_GATE_SCOUT=1 NAV_GATE_SCOUT_UPDATE=1 python scripts/seed_gate_scout.py
|
||||||
|
```
|
||||||
|
|
||||||
|
也可在 **服务管理** 里手动改已有「Gate 扫描端」的主机与端口。
|
||||||
|
|
||||||
|
**4. 登录**:使用云上各服务 `config.yaml` 的 `auth` 账号密码。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 九、部署指南(以 Ubuntu 为例)
|
## 九、部署指南(以 Ubuntu 为例)
|
||||||
|
|||||||
Reference in New Issue
Block a user