diff --git a/DEPLOY.md b/DEPLOY.md index 64a33f7..d05a282 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -140,6 +140,53 @@ SKIP_PYTORCH=1 bash deploy.sh deps 下载过程中出现 `Retrying... Read timed out` 属于正常重试,**并非卡死**,请耐心等待 10-30 分钟。 +### 0.7 PWA 安装 App 与 HTTPS 反向代理 + +| 访问方式 | 浏览器行为 | +|----------|------------| +| `http://IP:5683` | 只能「快捷方式 / 添加到主屏幕」,**不能**系统级一键安装 | +| `https://IP` 或 `https://域名` | Chrome/Edge 可弹出 **「安装 Trading Studio」**,独立窗口运行 | + +**原因:** PWA 规范要求 **HTTPS 安全上下文**(`localhost` 除外)。局域网直连 HTTP 是正常现象,不是代码 bug。 + +#### 推荐方案:Nginx + 自签证书(纯局域网) + +```bash +cd /opt/Trading_Studio +bash server-update.sh # 或 git pull + +# 1. 安装 Nginx +sudo apt install -y nginx + +# 2. 生成自签 SSL(替换为你的服务器局域网 IP) +sudo bash scripts/gen_ssl_cert.sh 192.168.8.100 + +# 3. 启用站点配置 +sudo cp nginx/trading_studio.conf /etc/nginx/sites-available/trading_studio.conf +sudo ln -sf /etc/nginx/sites-available/trading_studio.conf /etc/nginx/sites-enabled/ +sudo nginx -t && sudo systemctl reload nginx + +# 4. 确保 Gradio 仍由 PM2 监听 127.0.0.1:5683(仅本机),外网只走 443 +pm2 restart trading_studio +``` + +**访问:** `https://192.168.8.100`(首次需在手机/平板点「高级 → 继续访问」信任证书) + +**安装 App:** +- 电脑 Chrome:地址栏出现 ⊕ 安装图标,或点页面「安装 App」按钮 +- 安卓 Chrome:菜单 → 安装应用 +- iPad/iPhone Safari:分享 → 添加到主屏幕(iOS 无系统安装弹窗,但 HTTPS 下体验更完整) + +#### 有公网域名时 + +在 Nginx 前加 [Let's Encrypt](https://letsencrypt.org/) 免费证书(`certbot`),可免信任自签证书步骤。 + +#### 无反向代理时的替代 + +HTTP 下点击「安装 App」会显示手动引导;桌面快捷方式仍可用,功能不受影响。 + +--- + ### 0.5 PM2 运维(root 环境) ```bash diff --git a/app.py b/app.py index bd6f1a0..94dc38d 100644 --- a/app.py +++ b/app.py @@ -232,15 +232,25 @@ PWA_HEAD = """ document.body.appendChild(overlay); } + function isSecure() { + return location.protocol === "https:" || location.hostname === "localhost" || location.hostname === "127.0.0.1"; + } + function manualInstallGuide() { + var httpWarn = ""; + if (!isSecure()) { + httpWarn = "
当前环境需手动安装,按以下步骤操作:
' + steps + - '安装后可像原生 App 一样从桌面/icon 启动。
' + '按以下步骤操作:
' + steps + + 'HTTPS 安装后可独立窗口运行,体验接近原生 App。
' ); } @@ -583,6 +593,16 @@ gradio-app, .pwa-modal p { color: #cbd5e1 !important; line-height: 1.6 !important; } .pwa-modal ol { color: #e2e8f0 !important; padding-left: 20px !important; line-height: 1.8 !important; } .pwa-modal-tip { font-size: 0.85rem !important; color: #93c5fd !important; margin-top: 16px !important; } +.pwa-modal-warn { + background: #422006 !important; + border: 1px solid #f59e0b !important; + border-radius: 8px !important; + padding: 12px 14px !important; + margin-bottom: 14px !important; + color: #fde68a !important; + font-size: 0.9rem !important; + line-height: 1.6 !important; +} .pwa-modal-close { position: absolute; top: 12px; diff --git a/nginx/trading_studio.conf b/nginx/trading_studio.conf new file mode 100644 index 0000000..25ecc11 --- /dev/null +++ b/nginx/trading_studio.conf @@ -0,0 +1,45 @@ +# Trading Studio — Nginx HTTPS 反向代理 +# 将 https://你的域名或IP 转发到本机 Gradio 5683 +# +# 安装步骤见 DEPLOY.md「PWA 安装与 HTTPS」 + +# HTTP 自动跳转 HTTPS(可选,不需要可删除此 server 块) +server { + listen 80; + listen [::]:80; + server_name trading.local _; + + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name trading.local _; + + # 自签证书路径(先用 scripts/gen_ssl_cert.sh 生成) + ssl_certificate /etc/nginx/ssl/trading_studio.crt; + ssl_certificate_key /etc/nginx/ssl/trading_studio.key; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + client_max_body_size 200M; + + location / { + proxy_pass http://127.0.0.1:5683; + proxy_http_version 1.1; + + # Gradio WebSocket 必需 + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + } +} diff --git a/pwa/icons/icon-192.png b/pwa/icons/icon-192.png new file mode 100644 index 0000000..2057557 Binary files /dev/null and b/pwa/icons/icon-192.png differ diff --git a/pwa/icons/icon-512.png b/pwa/icons/icon-512.png new file mode 100644 index 0000000..7d08ac9 Binary files /dev/null and b/pwa/icons/icon-512.png differ diff --git a/pwa/manifest.webmanifest b/pwa/manifest.webmanifest index a9812ec..ee9e269 100644 --- a/pwa/manifest.webmanifest +++ b/pwa/manifest.webmanifest @@ -11,17 +11,29 @@ "lang": "zh-CN", "categories": ["productivity", "utilities"], "icons": [ + { + "src": "/pwa/icons/icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/pwa/icons/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/pwa/icons/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + }, { "src": "/pwa/icons/icon.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "any" - }, - { - "src": "/pwa/icons/icon.svg", - "sizes": "512x512", - "type": "image/svg+xml", - "purpose": "maskable" } ] } diff --git a/scripts/gen_pwa_icons.sh b/scripts/gen_pwa_icons.sh new file mode 100644 index 0000000..09b6b5f --- /dev/null +++ b/scripts/gen_pwa_icons.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# 从 SVG 生成 PWA 所需 PNG 图标(Chrome 安装条件) +# 用法: bash scripts/gen_pwa_icons.sh +set -euo pipefail +cd "$(dirname "$0")/../pwa/icons" +SVG="icon.svg" + +if command -v rsvg-convert &>/dev/null; then + rsvg-convert -w 192 -h 192 "${SVG}" -o icon-192.png + rsvg-convert -w 512 -h 512 "${SVG}" -o icon-512.png +elif command -v convert &>/dev/null; then + convert -background none "${SVG}" -resize 192x192 icon-192.png + convert -background none "${SVG}" -resize 512x512 icon-512.png +elif command -v ffmpeg &>/dev/null; then + ffmpeg -y -f lavfi -i "color=c=0x0f1419:s=512x512" -frames:v 1 icon-512.png 2>/dev/null + ffmpeg -y -f lavfi -i "color=c=0x0f1419:s=192x192" -frames:v 1 icon-192.png 2>/dev/null + echo "[WARN] 仅用 ffmpeg 生成纯色图标,建议: apt install librsvg2-bin" +else + echo "[ERROR] 需要 rsvg-convert / imagemagick / ffmpeg 之一" + exit 1 +fi + +echo "[OK] 已生成 icon-192.png icon-512.png" diff --git a/scripts/gen_ssl_cert.sh b/scripts/gen_ssl_cert.sh new file mode 100644 index 0000000..66aeaf1 --- /dev/null +++ b/scripts/gen_ssl_cert.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# 生成本地 HTTPS 自签证书(局域网 PWA 安装用) +# 用法: sudo bash scripts/gen_ssl_cert.sh [服务器局域网IP] +set -euo pipefail + +SERVER_IP="${1:-}" +SSL_DIR="/etc/nginx/ssl" +KEY="${SSL_DIR}/trading_studio.key" +CRT="${SSL_DIR}/trading_studio.crt" + +if [[ "${EUID:-0}" -ne 0 ]]; then + echo "请使用 root: sudo bash scripts/gen_ssl_cert.sh 192.168.x.x" + exit 1 +fi + +if [[ -z "${SERVER_IP}" ]]; then + SERVER_IP=$(hostname -I | awk '{print $1}') + echo "[INFO] 未指定 IP,使用: ${SERVER_IP}" +fi + +mkdir -p "${SSL_DIR}" + +openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ + -keyout "${KEY}" \ + -out "${CRT}" \ + -subj "/CN=TradingStudio/O=Trading/C=CN" \ + -addext "subjectAltName=IP:${SERVER_IP},DNS:trading.local,DNS:localhost" + +chmod 600 "${KEY}" +echo "[OK] 证书已生成:" +echo " ${CRT}" +echo " ${KEY}" +echo "" +echo "手机/平板首次访问 HTTPS 需点「继续访问」信任自签证书,之后即可安装 App。"