Add HTTPS reverse proxy guide and PNG icons for real PWA install.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 = "<div class='pwa-modal-warn'><strong>⚠️ 当前为 HTTP 访问</strong><br>浏览器只能创建<strong>快捷方式</strong>,无法弹出系统级「安装 App」。<br>要一键安装,请配置 <strong>HTTPS 反向代理</strong>(见服务器 DEPLOY.md)。</div>";
|
||||
}
|
||||
var steps = isIOS()
|
||||
? "<ol><li>点击 Safari 底部分享按钮 <strong>□↑</strong></li><li>选择 <strong>「添加到主屏幕」</strong></li><li>点击 <strong>添加</strong> 即可</li></ol>"
|
||||
: "<ol><li>点击浏览器右上角 <strong>⋮</strong> 菜单</li><li>选择 <strong>「安装应用」</strong> 或 <strong>「添加到主屏幕」</strong></li><li>确认安装即可</li></ol>";
|
||||
? "<ol><li>点击 Safari 底部分享按钮 <strong>□↑</strong></li><li>选择 <strong>「添加到主屏幕」</strong></li><li>点击 <strong>添加</strong></li></ol>"
|
||||
: (isSecure()
|
||||
? "<ol><li>Chrome/Edge 地址栏点击 <strong>安装</strong> 图标</li><li>或菜单 → <strong>安装 Trading Studio</strong></li></ol>"
|
||||
: "<ol><li>Chrome 菜单 → <strong>添加到主屏幕</strong> 或 <strong>创建快捷方式</strong></li><li>配置 HTTPS 后可真正「安装应用」</li></ol>");
|
||||
showModal(
|
||||
'<button class="pwa-modal-close" type="button">✕</button>' +
|
||||
'<h3>📲 安装 Trading Studio</h3>' +
|
||||
'<p>当前环境需手动安装,按以下步骤操作:</p>' + steps +
|
||||
'<p class="pwa-modal-tip">安装后可像原生 App 一样从桌面/icon 启动。</p>'
|
||||
'<h3>📲 安装 Trading Studio</h3>' + httpWarn +
|
||||
'<p>按以下步骤操作:</p>' + steps +
|
||||
'<p class="pwa-modal-tip">HTTPS 安装后可独立窗口运行,体验接近原生 App。</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 966 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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。"
|
||||
Reference in New Issue
Block a user