diff --git a/core/db_config.py b/core/db_config.py index 51da3fa..ffd9271 100644 --- a/core/db_config.py +++ b/core/db_config.py @@ -263,6 +263,25 @@ def print_banner(): _log.info(text_block) +def env_badge(): + """给页面顶部徽标用的环境信息(不含密码)。 + + 防混库的第 4 层:光靠启动日志不够——用户点开任何页面都该一眼看出 + 自己正在操作哪个库。生产用红底。 + """ + try: + from core.models import db + backend = "sqlite" if is_sqlite(db.engine.url) else "mysql" + except Exception: + backend = "?" + try: + target = describe_target() + except Exception: + target = DB_HOST or "(未配置)" + return {"env": DEPLOY_ENV, "is_prod": DEPLOY_ENV == "prod", + "backend": backend, "target": target} + + def _now(): import time return time.strftime("%Y-%m-%d %H:%M:%S") diff --git a/doc/DEPLOY.md b/doc/DEPLOY.md index e068e62..6e05136 100644 --- a/doc/DEPLOY.md +++ b/doc/DEPLOY.md @@ -76,8 +76,9 @@ DB_NAME=auto_control **防混库**(`DEPLOY_ENV` 与库名/库标签双向校验,配置项说明见 [DEVELOPMENT.md](DEVELOPMENT.md) §4.2 与 `.env.example` 的「数据库」段):启动时若 「`.env` 声明的环境」与「库名」或「库中登记的 `app_meta.deployment_env`」不符,**直接拒绝启动**并打印 -两边分别是什么。每次启动还会打印一条横幅写明当前连的是哪个库(生产用 WARNING 级)。两个逃生阀 -`DB_ALLOW_ENV_MISMATCH` / `DB_ALLOW_SQLITE_FALLBACK` 默认关闭。 +两边分别是什么。每次启动还会打印一条横幅写明当前连的是哪个库(生产用 WARNING 级), +页面顶部也常驻一个环境徽标(生产红底 `PROD · <库>`,开发灰底 `DEV`)。 +两个逃生阀 `DB_ALLOW_ENV_MISMATCH` / `DB_ALLOW_SQLITE_FALLBACK` 默认关闭。 其余配置项与默认值见 [DEVELOPMENT.md](DEVELOPMENT.md) §配置速查。 diff --git a/templates/admin/monitor.html b/templates/admin/monitor.html index 976596e..c55e6c4 100644 --- a/templates/admin/monitor.html +++ b/templates/admin/monitor.html @@ -46,6 +46,8 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14 .brand-dot{width:9px;height:9px;border-radius:50%;background:var(--primary);box-shadow:0 0 0 0 rgba(15,118,110,.6);animation:brandPulse 2.4s infinite} @keyframes brandPulse{0%{box-shadow:0 0 0 0 rgba(15,118,110,.45)}70%{box-shadow:0 0 0 8px rgba(15,118,110,0)}100%{box-shadow:0 0 0 0 rgba(15,118,110,0)}} .navbar .tabs{display:flex;gap:2px;flex:1;align-self:stretch} +.env-badge{margin-right:18px;padding:3px 10px;border-radius:10px;font-size:11px;font-weight:700;letter-spacing:.5px;background:#2b3038;color:#9aa3af;border:1px solid #3a4048;white-space:nowrap} +.env-badge-prod{background:#4a1519;color:#ff9b9b;border-color:#8a2b31} .navbar .tab{position:relative;padding:0 18px;color:#9aa3af;font-size:14px;font-weight:500;cursor:pointer;border:none;background:none;transition:color .15s;letter-spacing:.2px} .navbar .tab::after{content:"";position:absolute;left:14px;right:14px;bottom:0;height:2px;border-radius:2px;background:var(--primary);transform:scaleX(0);transition:transform .18s} .navbar .tab:hover{color:#e5e7eb} @@ -392,6 +394,12 @@ body{background:var(--bg);font-family:var(--body);color:var(--text);font-size:14