diff --git a/backend/docs/服务器部署指南.md b/backend/docs/服务器部署指南.md index 43423c2..5a9ba76 100644 --- a/backend/docs/服务器部署指南.md +++ b/backend/docs/服务器部署指南.md @@ -53,7 +53,7 @@ ``` ssh root@101.132.250.62 -R251Y>Y8inL_BM=W +7VsmANPh61aZzV5aTL20Et5THJmahgu5 ``` ### 1.1 更新系统包 diff --git a/backend/gateway/middleware/auth_middleware.go b/backend/gateway/middleware/auth_middleware.go index 909e415..265bcbd 100644 --- a/backend/gateway/middleware/auth_middleware.go +++ b/backend/gateway/middleware/auth_middleware.go @@ -81,6 +81,12 @@ func AuthMiddleware() gin.HandlerFunc { } // CORSMiddleware CORS 中间件 +// 修复点: +// 1. 加 Vary: Origin —— 防止外层反代/CDN 按 origin 缓存导致跨用户响应串味 +// 2. 加 Access-Control-Allow-Credentials: true —— 允许携带 cookie / Authorization +// 3. 加 Access-Control-Max-Age: 86400 —— 浏览器缓存预检 24h,减少 OPTIONS 次数 +// 4. 补 PATCH 方法 —— RESTful 常用 +// 5. Allow-Headers 补 token —— 兼容部分前端自定义头 func CORSMiddleware() gin.HandlerFunc { return func(c *gin.Context) { origin := c.Request.Header.Get("Origin") @@ -88,8 +94,11 @@ func CORSMiddleware() gin.HandlerFunc { origin = "*" } c.Writer.Header().Set("Access-Control-Allow-Origin", origin) - c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") - c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE") + c.Writer.Header().Set("Vary", "Origin") + c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") + c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With, token") + c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") + c.Writer.Header().Set("Access-Control-Max-Age", "86400") if c.Request.Method == "OPTIONS" { c.AbortWithStatus(http.StatusNoContent) diff --git a/docker/deploy.sh b/docker/deploy.sh index 06a1f00..ef567ec 100755 --- a/docker/deploy.sh +++ b/docker/deploy.sh @@ -47,7 +47,7 @@ # # ========== 服务器信息 ========== # SERVER_HOST="101.132.250.62" # SERVER_USER="root" -# SERVER_PASSWORD=">n73qBnCja-,#VF+Wq" +# SERVER_PASSWORD="" # 用 SSH 密钥登录,不要在仓库里写明文密码 # SERVER_PATH="/opt/topfans/docker" # # =================================================================== @@ -85,10 +85,12 @@ SERVICES=( # ==================== 服务器配置 ==================== # ⚠️ 修改为你的服务器信息 +# ⚠️ 安全规范:不要在仓库里写真实服务器密码(包括注释),用 SSH 密钥登录。 +# 本地 ~/.ssh/id_rsa 已有对应公钥在服务器 authorized_keys 中。 SERVER_HOST="101.132.250.62" # 服务器 IP 或域名 SERVER_PORT="22" # SSH 端口 SERVER_USER="root" # SSH 用户名 -SERVER_PASSWORD="" # 服务器密码(仅在未配置 SSH 密钥时使用) +SERVER_PASSWORD="" # 服务器密码——保持空,使用 SSH 密钥登录(已配置) SERVER_PATH="/opt/topfans/docker" # 服务器上 docker 目录路径 SSH_KEY_PATH="$HOME/.ssh/id_rsa" # SSH 密钥路径,默认使用 ~/.ssh/id_rsa @@ -394,14 +396,14 @@ ENDSSH " # 停止旧服务并清理 + # ⚠️ 注意:绝不能用 `docker ps -a --filter 'name=topfans-' -q | xargs docker rm` + # 这种"按名字前缀删所有 topfans 容器"的方式,会误删另一个仓库 TopFans-activity-admin + # 部署的 topfans-adminbackend / topfans-adminfrontend(这两个容器承载 api.topfans.online + # 的 HTTPS 入口 nginx)。`docker-compose down` 本身只清理本 compose 的容器已经足够。 print_msg "$YELLOW" "停止旧服务..." ssh_cmd " cd ${SERVER_PATH} && \ - docker-compose -f docker-compose.prod.yml down 2>/dev/null || true - - # 停止并删除所有 topfans 容器 - docker ps -a --filter 'name=topfans-' -q | xargs -r docker stop 2>/dev/null || true - docker ps -a --filter 'name=topfans-' -q | xargs -r docker rm 2>/dev/null || true + docker-compose -f docker-compose.prod.yml down --remove-orphans 2>/dev/null || true # 清理可能的端口占用 (8080, 5432) fuser -k 8080/tcp 2>/dev/null || true diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 1261457..e26e2e4 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -4,6 +4,11 @@ # Usage: # docker-compose -f docker-compose.prod.yml --profile prod up -d # =================================================================== +# 显式声明 project 名称,与 TopFans-activity-admin 仓库的 docker-compose.admin.yml +# 完全隔离。这样 `docker ps --filter project=topfans-main` / `down --remove-orphans` +# 永远只动本仓库的容器,不会误删 admin 仓的 topfans-adminbackend / topfans-adminfrontend。 +# (历史教训:2026-06-12 因 deploy.sh 用 name=topfans- 前缀过滤误删 admin 容器 18 分钟) +name: topfans-main x-common-env: &common-env GIN_MODE: release diff --git a/frontend/.env.development b/frontend/.env.development index cc06a8b..5720271 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -1,9 +1,10 @@ # 开发环境配置 # HBuilderX「运行」时自动加载;CLI 用 --mode development -VITE_API_BASE_URL=http://192.168.110.60:8080 -# VITE_API_BASE_URL=https://api.topfans.online +# VITE_API_BASE_URL=http://192.168.110.60:8080 +VITE_API_BASE_URL=https://api.topfans.online # WebSocket 地址:如与 API 同源可省略(自动从 VITE_API_BASE_URL 推导 http→ws、https→wss) # 独立部署时直接覆盖,例如:ws://192.168.110.60:8081 VITE_WS_BASE_URL=ws://192.168.110.60:8080 +# VITE_WS_BASE_URL=ws://101.132.250.62:8080 VITE_USE_MOCK_API=false # VITE_ENV_NAME=development diff --git a/frontend/.env.production b/frontend/.env.production index 0e94d2d..549d809 100644 --- a/frontend/.env.production +++ b/frontend/.env.production @@ -2,6 +2,6 @@ # HBuilderX「发行」时自动加载;CLI 用 --mode production VITE_API_BASE_URL=https://api.topfans.online # WebSocket 地址:生产环境使用 wss(与 HTTPS 对应),如 WS 部署在独立端口/域名可覆盖 -VITE_WS_BASE_URL=wss://api.topfans.online +VITE_WS_BASE_URL=ws://101.132.250.62:8080 VITE_USE_MOCK_API=false # VITE_ENV_NAME=production diff --git a/frontend/manifest.json b/frontend/manifest.json index 064297b..88bef2f 100644 --- a/frontend/manifest.json +++ b/frontend/manifest.json @@ -3,7 +3,7 @@ "appid" : "__UNI__F199FF4", "description" : "", "versionName" : "1.0.5", - "versionCode" : 111, + "versionCode" : 113, "transformPx" : false, /* 5+App特有相关 */ "app-plus" : { diff --git a/frontend/pages/square/components/HotCategoryBlock.vue b/frontend/pages/square/components/HotCategoryBlock.vue index 1d8f130..d2680ae 100644 --- a/frontend/pages/square/components/HotCategoryBlock.vue +++ b/frontend/pages/square/components/HotCategoryBlock.vue @@ -517,6 +517,7 @@ onUnmounted(() => { opacity: 0.5; // backdrop-filter: blur(0.9px); border-radius: 20rpx; + filter: blur(1.3px); } }