feat(widget): 优化访客在线轨迹、GeoIP与多站点渠道
CI / Frontend (typecheck + lint + build) (push) Successful in 2m5s
CI / Backend (go vet + test) (push) Failing after 5m20s

This commit is contained in:
yml2213
2026-11-06 18:21:30 +08:00
parent 24fac1bcf1
commit 38d6fc1684
37 changed files with 1071 additions and 123 deletions
+4
View File
@@ -30,6 +30,10 @@ DB_SSLMODE=disable
# ========== JWT(deploy.sh 可自动生成)==========
JWT_SECRET=请改成随机长字符串
CORS_ALLOW_ORIGINS=https://你的域名
# 可选:离线 GeoIP City 数据库(挂载自 deploy/geoip/)
# GEOIP_DB_PATH=/app/geoip/GeoLite2-City.mmdb
# GEOIP_DB_FILE=./deploy/geoip/GeoLite2-City.mmdb
# GEOIP_DB_URL=https://raw.githubusercontent.com/P3TERX/GeoLite.mmdb/download/GeoLite2-City.mmdb
# ========== MinIO 对象存储 ==========
STORAGE_ACCESS_KEY=kefu_minio
+5
View File
@@ -92,6 +92,7 @@ chmod +x deploy/scripts/*.sh
| `STORAGE_PUBLIC_BASE_URL` | `https://kefu.xx.com/files` | **必须**与应用内 Nginx `/files` 一致 |
| `HTTP_PORT` | `18080` | 宿主机映射端口;已有 Caddy 占 80 时用非 80 端口 |
| `DB_PASSWORD` / `JWT_SECRET` / `STORAGE_*` | 强随机 | 脚本可自动生成密钥 |
| `GEOIP_DB_PATH` | `/app/geoip/GeoLite2-City.mmdb` | 可选离线 IP 城市库;文件放到 `deploy/geoip/` |
脚本会校验占位符是否改掉,并在 `HTTP_PORT` 已被占用时告警/退出。
@@ -161,6 +162,10 @@ STORAGE_PUBLIC_BASE_URL=https://kefu.example.com/files
生产链路由 Caddy → 应用 Nginx → API 时,API 优先读取 `X-Forwarded-For` 最左侧地址,`X-Real-IP` 仅作为回退,因此外部访客会显示其公网地址。请保持示例反代配置中的 `X-Forwarded-For` 转发,不要在边缘代理处清空该请求头。
城市级地区使用 `deploy/geoip/GeoLite2-City.mmdb`。
部署脚本会自动下载并每 30 天刷新该文件;可用 `GEOIP_DB_URL` 覆盖下载源。
下载失败时只会使用 CDN 国家头,公网 IP 通常显示“未知”。
任选其一(与上一节「Caddy 共存」二选一即可):
1. **CLB / CDN** 终结 HTTPS,回源 CVM `HTTP_PORT`(或仍回源 Caddy)
+20
View File
@@ -0,0 +1,20 @@
# GeoIP 数据库
部署脚本会在文件缺失或超过 30 天时自动下载:
```text
deploy/geoip/GeoLite2-City.mmdb
```
Docker Compose 会把本目录只读挂载到 API 容器的 `/app/geoip`,默认读取:
```text
GEOIP_DB_PATH=/app/geoip/GeoLite2-City.mmdb
```
可通过 `GEOIP_DB_URL` 覆盖下载源,或将自有 MaxMind GeoIP2 City 文件放到上述路径。
下载失败时服务仍可正常启动,IP 地区会降级到 CDN 国家请求头或“未知”。
更换数据库后重启 API 容器即可生效。
默认下载源是公开的 GeoLite2 镜像。正式商用请遵守 MaxMind GeoLite2
许可与署名要求,或通过 `GEOIP_DB_URL` 指向自有授权下载地址。
+30
View File
@@ -97,6 +97,35 @@ check_http_port() {
fi
}
ensure_geoip() {
local db_file="${GEOIP_DB_FILE:-deploy/geoip/GeoLite2-City.mmdb}"
local db_url="${GEOIP_DB_URL:-https://raw.githubusercontent.com/P3TERX/GeoLite.mmdb/download/GeoLite2-City.mmdb}"
local refresh=0
if [[ ! -s "$db_file" ]] || [[ "$(wc -c < "$db_file" | tr -d ' ')" -lt 1000000 ]] \
|| ! tail -c 131072 "$db_file" | grep -aq 'MaxMind.com'; then
refresh=1
elif find "$db_file" -mtime +30 -print -quit 2>/dev/null | grep -q .; then
refresh=1
fi
[[ "$refresh" -eq 0 ]] && return 0
need_cmd curl
mkdir -p "$(dirname "$db_file")"
local tmp="${db_file}.download.$$"
log "下载 GeoIP 城市库: $db_url"
rm -f "$tmp"
if curl -fL --retry 3 --connect-timeout 15 --max-time 300 -o "$tmp" "$db_url" \
&& [[ "$(wc -c < "$tmp" | tr -d ' ')" -gt 1000000 ]] \
&& tail -c 131072 "$tmp" | grep -aq 'MaxMind.com'; then
mv "$tmp" "$db_file"
log "GeoIP 数据库已更新: $db_file"
else
rm -f "$tmp"
warn "GeoIP 自动下载失败,服务将降级为 CDN 国家头/未知地区"
fi
}
ensure_env() {
if [[ ! -f "$ENV_FILE" ]]; then
if [[ ! -f "$ENV_EXAMPLE" ]]; then
@@ -227,6 +256,7 @@ cmd_up() {
fi
ensure_env
ensure_geoip
log "拉取基础镜像…"
compose pull postgres minio minio-init || true