diff --git a/deploy/README.en.md b/deploy/README.en.md index 65c9413..de344af 100644 --- a/deploy/README.en.md +++ b/deploy/README.en.md @@ -66,12 +66,12 @@ cp /path/to/your/ego.key certs/ego.key docker compose up -d ``` -Access `https:///`. Nginx terminates TLS on 443 (your cert), proxies all traffic to EGo's HTTP 5000. Path routing is handled internally by EGo — change `path_prefix` in the UI, nginx needs no changes. Port 80 automatically redirects to 443. +Access `https://:4430/`. Nginx terminates TLS on 4430 (your cert), proxies all traffic to EGo's HTTP 5000. Path routing is handled internally by EGo — change `path_prefix` in the UI, nginx needs no changes. Port 800 automatically redirects to 4430. ### T4 (Nginx + acme.sh Auto) **Certificate separation design:** -- nginx 443: uses `certs/ego.crt` + `ego.key` (Let's Encrypt certificate) +- nginx 4430: uses `certs/ego.crt` + `ego.key` (Let's Encrypt certificate) - EGo 5001: uses `certs/ego-selfsigned.crt` + `ego-selfsigned.key` (self-signed certificate) **One-click deployment:** @@ -84,8 +84,8 @@ chmod +x init.sh ``` Supports two verification methods: -- **webroot mode** (default): Requires port 80, domain must resolve to this server's public IP -- **Cloudflare DNS API mode**: No port 80 required, needs Cloudflare API Token +- **webroot mode** (default): Requires port 800, domain must resolve to this server's public IP +- **Cloudflare DNS API mode**: No port 800 required, needs Cloudflare API Token **Manual deployment (for customization):** @@ -94,11 +94,11 @@ cd deploy/t4-certbot mkdir -p certs echo "your.domain" > certs/.domain -# Method 1: webroot mode (requires port 80) +# Method 1: webroot mode (requires port 800) docker compose up -d docker compose exec acme acme.sh --issue --webroot /var/www/acme -d your.domain --server letsencrypt -# Method 2: Cloudflare DNS API mode (no port 80 required) +# Method 2: Cloudflare DNS API mode (no port 800 required) CF_Token=your_token docker compose up -d docker compose exec acme acme.sh --issue --dns dns_cf -d your.domain --server letsencrypt diff --git a/deploy/README.md b/deploy/README.md index 95103a3..eefd54d 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -66,13 +66,13 @@ cp /path/to/your/ego.key certs/ego.key docker compose up -d ``` -访问 `https://<域名或IP>/`。Nginx 在 443 终结 TLS(你的证书),全流量透传 EGo 的 HTTP 5000; -路径路由由 EGo 内部处理(用户在前端改 path_prefix,nginx 无需改动)。80 自动跳 443。 +访问 `https://<域名或IP>:4430/`。Nginx 在 4430 终结 TLS(你的证书),全流量透传 EGo 的 HTTP 5000; +路径路由由 EGo 内部处理(用户在前端改 path_prefix,nginx 无需改动)。800 自动跳 4430。 ### T4(Nginx + acme.sh 自动证书) **证书分离设计:** -- nginx 443: 使用 `certs/ego.crt` + `ego.key`(Let's Encrypt 证书) +- nginx 4430: 使用 `certs/ego.crt` + `ego.key`(Let's Encrypt 证书) - EGo 5001: 使用 `certs/ego-selfsigned.crt` + `ego-selfsigned.key`(自签名证书) **一键部署:** @@ -85,8 +85,8 @@ chmod +x init.sh ``` 支持两种验证方式: -- **webroot 模式**(默认):需要 80 端口,域名需解析到本机公网 IP -- **Cloudflare DNS API 模式**:不需要 80 端口,需要 Cloudflare API Token +- **webroot 模式**(默认):需要 800 端口,域名需解析到本机公网 IP +- **Cloudflare DNS API 模式**:不需要 800 端口,需要 Cloudflare API Token **手动部署(如需自定义):** @@ -95,11 +95,11 @@ cd deploy/t4-certbot mkdir -p certs echo "your.domain" > certs/.domain -# 方式一:webroot 模式(需要 80 端口) +# 方式一:webroot 模式(需要 800 端口) docker compose up -d docker compose exec acme acme.sh --issue --webroot /var/www/acme -d your.domain --server letsencrypt -# 方式二:Cloudflare DNS API 模式(不需要 80 端口) +# 方式二:Cloudflare DNS API 模式(不需要 800 端口) CF_Token=your_token docker compose up -d docker compose exec acme acme.sh --issue --dns dns_cf -d your.domain --server letsencrypt diff --git a/deploy/init.sh b/deploy/init.sh index 1feb022..5f726a8 100644 --- a/deploy/init.sh +++ b/deploy/init.sh @@ -47,8 +47,8 @@ case "$MODE" in read EMAIL echo "" echo "证书验证方式:" - echo " 1) webroot 模式(默认,需要 80 端口,域名需解析到本机公网 IP)" - echo " 2) Cloudflare DNS API 模式(不需要 80 端口,需要 CF_Token)" + echo " 1) webroot 模式(默认,需要 800 端口,域名需解析到本机公网 IP)" + echo " 2) Cloudflare DNS API 模式(不需要 800 端口,需要 CF_Token)" printf "请选择 [1-2,默认 1]: " read CERT_MODE CERT_MODE=$(echo "$CERT_MODE" | tr -d '[:space:]') @@ -107,12 +107,12 @@ case $DEPLOY_DIR in export CF_Token $ACME_SH --issue --dns dns_cf -d "$DOMAIN" -d "*.$DOMAIN" --server letsencrypt else - echo "使用 webroot 模式签发证书(需要 80 端口)..." + echo "使用 webroot 模式签发证书(需要 800 端口)..." - # 检查 80 端口是否被 uhttpd 占用 + # 检查 800 端口是否被 uhttpd 占用 UHTTPD_STOPPED=0 - if netstat -tlnp 2>/dev/null | grep -q ":80.*uhttpd"; then - echo "检测到 80 端口被 uhttpd 占用,临时停止..." + if netstat -tlnp 2>/dev/null | grep -q ":800.*uhttpd"; then + echo "检测到 800 端口被 uhttpd 占用,临时停止..." /etc/init.d/uhttpd stop UHTTPD_STOPPED=1 sleep 2 @@ -121,7 +121,7 @@ case $DEPLOY_DIR in # 启动临时 web 服务器 mkdir -p /tmp/acme_webroot cd /tmp/acme_webroot - python3 -m http.server 80 & + python3 -m http.server 800 & WEB_PID=$! sleep 2 @@ -165,8 +165,8 @@ case $DEPLOY_DIR in echo "Webhook: http://<主机IP>:5000" ;; t3-nginx|t4-certbot) - echo "管理页面: https://$DOMAIN" - echo "Webhook: http://$DOMAIN/in/" + echo "管理页面: https://$DOMAIN:4430" + echo "Webhook: http://$DOMAIN:800/in/" ;; esac echo "" diff --git a/deploy/t3-nginx/docker-compose.yml b/deploy/t3-nginx/docker-compose.yml index 10b357d..984d5ad 100644 --- a/deploy/t3-nginx/docker-compose.yml +++ b/deploy/t3-nginx/docker-compose.yml @@ -29,8 +29,8 @@ services: depends_on: - ego ports: - - "80:80" - - "443:443" + - "800:80" + - "4430:443" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro - ./certs:/etc/nginx/certs:ro diff --git a/deploy/t4-certbot/docker-compose.yml b/deploy/t4-certbot/docker-compose.yml index 1f917ae..292622a 100644 --- a/deploy/t4-certbot/docker-compose.yml +++ b/deploy/t4-certbot/docker-compose.yml @@ -44,8 +44,8 @@ services: depends_on: - ego ports: - - "80:80" - - "443:443" + - "800:80" + - "4430:443" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro - ./certs:/etc/nginx/certs:ro diff --git a/i18n.py b/i18n.py index c761d48..b2de956 100644 --- a/i18n.py +++ b/i18n.py @@ -189,6 +189,8 @@ def get_all(): "src.copy_prompt_fail": "自动复制失败,请手动选中下方文本复制(Ctrl+C / ⌘C):", "ver.new_version": "有新版本", "ver.view_release": "查看发布页", + "nav.github": "GitHub 项目", + "nav.report_bug": "提交 Bug", "src.ai_prompt": "你是一个 Python 脚本生成器。请为下面的数据源编写一个解析器脚本。\n\n## 要求\n\n- 文件名:`parsers/{parserLabel}.py`(全小写,下划线分隔)\n- 必须包含一个 `parse(raw_body: bytes, headers: dict, query_params: dict) -> dict` 函数\n- 函数接收原始 HTTP 请求体、请求头和查询参数,返回一个字典\n- 返回字典的键将作为模板变量使用(如 title, content 等)\n- 请从样本数据中提取有意义的字段\n\n## 样本数据\n\n请求头:\n{rawHeaders}\n\n查询参数:\n{rawQuery}\n\n请求体:\n{sampleBody}\n\n请参考上面的样本数据,输出完整的 Python 解析器脚本代码(仅代码,无需额外说明)。", # -- Channel Plugins UI -- @@ -795,6 +797,8 @@ def get_all(): "src.copy_prompt_fail": "Auto-copy failed. Please select and copy manually (Ctrl+C):", "ver.new_version": "New version available", "ver.view_release": "View release", + "nav.github": "GitHub Project", + "nav.report_bug": "Report Bug", "src.ai_prompt": "You are a Python script generator. Please write a parser script for the following data source.\n\n## Requirements\n\n- Filename: `parsers/{parserLabel}.py` (all lowercase, underscore-separated)\n- Must include a `parse(raw_body: bytes, headers: dict, query_params: dict) -> dict` function\n- The function receives the raw HTTP request body, headers, and query params, and returns a dict\n- The dict keys will be used as template variables (e.g. title, content, etc.)\n- Extract meaningful fields from the sample data\n\n## Sample Data\n\nHeaders:\n{rawHeaders}\n\nQuery Params:\n{rawQuery}\n\nBody:\n{sampleBody}\n\nBased on the sample data above, output the complete Python parser script code (code only, no extra explanation).", # -- Channel Plugins UI -- diff --git a/templates/base.html b/templates/base.html index 464ec72..fd04683 100644 --- a/templates/base.html +++ b/templates/base.html @@ -17,6 +17,10 @@ .sidebar-version { padding: 12px 20px; color: #475569; font-size: 0.75rem; border-top: 1px solid #334155; position: relative; } .sidebar-version .update-dot { display: inline-block; width: 8px; height: 8px; background: #22c55e; border-radius: 50%; margin-left: 4px; vertical-align: middle; cursor: pointer; } .sidebar-version .update-dot:hover { background: #16a34a; } +.sidebar-links { padding: 8px 0; border-top: 1px solid #334155; } +.sidebar-link { display: block; color: #94a3b8; padding: 8px 20px; font-size: 0.8rem; text-decoration: none; } +.sidebar-link:hover { color: #fff; background: #334155; } +.sidebar-link i { margin-right: 8px; } .update-popover { position: fixed; bottom: 50px; left: 12px; width: 440px; max-width: calc(100vw - 24px); max-height: calc(100vh - 120px); overflow-y: auto; background: #fff; border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px; font-size: 0.8rem; color: #1e293b; box-shadow: 0 4px 12px rgba(0,0,0,.15); z-index: 1000; display: none; } .update-popover.show { display: block; } .update-popover h6 { margin: 0 0 6px; font-size: 0.85rem; } @@ -70,6 +74,14 @@
+
{% block content %}{% endblock %}