From d8c1e1ee6c6f6d51a8d8715841691efb510f1b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A0=91=E8=90=8C=E8=8A=BD?= <3205788256@qq.com> Date: Thu, 12 Mar 2026 18:58:36 +0800 Subject: [PATCH] chore: sync local changes (2026-03-12) --- Dockerfile | 48 --------- build_frontend.bat | 9 ++ docker-build-run.sh | 35 ------ docker-compose.yml | 14 --- mengyadriftbottle-backend/.dockerignore | 18 ++++ mengyadriftbottle-backend/Dockerfile | 23 ++++ mengyadriftbottle-backend/app.py | 24 ++++- .../background/image1.png | Bin .../background/image10.png | Bin .../background/image11.png | Bin .../background/image12.png | Bin .../background/image13.png | Bin .../background/image14.png | Bin .../background/image15.png | Bin .../background/image16.png | Bin .../background/image17.png | Bin .../background/image18.png | Bin .../background/image19.png | Bin .../background/image2.png | Bin .../background/image20.png | Bin .../background/image21.png | Bin .../background/image22.png | Bin .../background/image23.png | Bin .../background/image24.png | Bin .../background/image25.png | Bin .../background/image26.png | Bin .../background/image27.png | Bin .../background/image28.png | Bin .../background/image29.png | Bin .../background/image3.png | Bin .../background/image4.png | Bin .../background/image5.png | Bin .../background/image6.png | Bin .../background/image7.png | Bin .../background/image8.png | Bin .../background/image9.png | Bin mengyadriftbottle-backend/docker-compose.yml | 22 ++++ mengyadriftbottle-frontend/ENV_SETUP.md | 28 +++++ mengyadriftbottle-frontend/index.html | 5 + .../public/manifest.webmanifest | 25 +++++ .../public/offline.html | 97 +++++++++++++++++ mengyadriftbottle-frontend/public/sw.js | 102 ++++++++++++++++++ mengyadriftbottle-frontend/src/App.jsx | 23 +++- mengyadriftbottle-frontend/src/main.jsx | 23 ++++ nginx.conf | 54 ---------- start.sh | 28 ----- start_backend.bat | 6 ++ start_frontend.bat | 7 ++ 萌芽漂流瓶 | 0 49 files changed, 409 insertions(+), 182 deletions(-) delete mode 100644 Dockerfile create mode 100644 build_frontend.bat delete mode 100644 docker-build-run.sh delete mode 100644 docker-compose.yml create mode 100644 mengyadriftbottle-backend/.dockerignore create mode 100644 mengyadriftbottle-backend/Dockerfile rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image1.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image10.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image11.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image12.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image13.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image14.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image15.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image16.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image17.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image18.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image19.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image2.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image20.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image21.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image22.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image23.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image24.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image25.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image26.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image27.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image28.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image29.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image3.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image4.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image5.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image6.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image7.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image8.png (100%) rename {mengyadriftbottle-frontend/public => mengyadriftbottle-backend}/background/image9.png (100%) create mode 100644 mengyadriftbottle-backend/docker-compose.yml create mode 100644 mengyadriftbottle-frontend/ENV_SETUP.md create mode 100644 mengyadriftbottle-frontend/public/manifest.webmanifest create mode 100644 mengyadriftbottle-frontend/public/offline.html create mode 100644 mengyadriftbottle-frontend/public/sw.js delete mode 100644 nginx.conf delete mode 100644 start.sh create mode 100644 start_backend.bat create mode 100644 start_frontend.bat create mode 100644 萌芽漂流瓶 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 8baae94..0000000 --- a/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -FROM python:3.11-slim AS base - -# Install Node.js 20 + nginx for building frontend and serving -RUN apt-get update \ - && apt-get install -y curl gnupg nginx \ - && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ - && apt-get install -y nodejs build-essential \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /app - -# Copy source code -COPY mengyadriftbottle-backend ./mengyadriftbottle-backend -COPY mengyadriftbottle-frontend ./mengyadriftbottle-frontend - -# -------- Build frontend -------- -WORKDIR /app/mengyadriftbottle-frontend -RUN npm install \ - && npm run build - -# -------- Install backend deps -------- -WORKDIR /app/mengyadriftbottle-backend -RUN pip install --no-cache-dir -r requirements.txt \ - && pip install --no-cache-dir gunicorn - -# Prepare runtime artifacts -WORKDIR /app -RUN mkdir -p frontend-dist \ - && cp -r /app/mengyadriftbottle-frontend/dist/* /app/frontend-dist/ - -# Seed data directory (can be overridden via volume) -RUN mkdir -p /app/data \ - && cp /app/mengyadriftbottle-backend/*.json /app/data/ - -# Copy nginx config and startup script -COPY nginx.conf /etc/nginx/nginx.conf -COPY start.sh /app/start.sh -RUN chmod +x /app/start.sh - -EXPOSE 6767 - -ENV PORT=6767 \ - BACKEND_PORT=5002 \ - DRIFT_BOTTLE_FRONTEND_DIST=/app/frontend-dist \ - DRIFT_BOTTLE_DATA_DIR=/app/data - -CMD ["/app/start.sh"] diff --git a/build_frontend.bat b/build_frontend.bat new file mode 100644 index 0000000..78966d9 --- /dev/null +++ b/build_frontend.bat @@ -0,0 +1,9 @@ +@echo off +chcp 65001 >nul +echo 构建前端项目... +cd mengyadriftbottle-frontend +if not exist node_modules ( + echo 正在安装依赖... + call npm install +) +npm run build diff --git a/docker-build-run.sh b/docker-build-run.sh deleted file mode 100644 index 2ac2699..0000000 --- a/docker-build-run.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -IMAGE_NAME=${IMAGE_NAME:-mengyadriftbottle} -CONTAINER_NAME=${CONTAINER_NAME:-mengyadriftbottle} -FRONTEND_PORT=${FRONTEND_PORT:-6767} -BACKEND_PORT=${BACKEND_PORT:-5002} -PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" -DATA_DIR="${DATA_DIR:-}" - -echo "[1/3] Building image $IMAGE_NAME ..." -docker build -t "$IMAGE_NAME" "$PROJECT_DIR" - -echo "[2/3] Removing old container if it exists ..." -if docker ps -a --format '{{.Names}}' | grep -Eq "^${CONTAINER_NAME}$"; then - docker rm -f "$CONTAINER_NAME" >/dev/null -fi - -echo "[3/3] Starting container $CONTAINER_NAME ..." -RUN_ARGS=( - -d - --name "$CONTAINER_NAME" - -p ${FRONTEND_PORT}:6767 - -e BACKEND_PORT=5002 -) - -if [ -n "$DATA_DIR" ]; then - mkdir -p "$DATA_DIR" - RUN_ARGS+=( -v "$DATA_DIR:/app/data" ) -fi - -docker run "${RUN_ARGS[@]}" "$IMAGE_NAME" - -echo "Container is up. Frontend: http://localhost:${FRONTEND_PORT}" -echo "Logs: docker logs -f ${CONTAINER_NAME}" diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index a9a5712..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: "3.9" - -services: - mengyadriftbottle: - build: . - container_name: mengyadriftbottle - restart: unless-stopped - ports: - - "6767:6767" - environment: - BACKEND_PORT: "5002" - DRIFT_BOTTLE_DATA_DIR: "/app/data" - volumes: - - /shumengya/docker/storage/mengyadriftbottle:/app/data diff --git a/mengyadriftbottle-backend/.dockerignore b/mengyadriftbottle-backend/.dockerignore new file mode 100644 index 0000000..d923741 --- /dev/null +++ b/mengyadriftbottle-backend/.dockerignore @@ -0,0 +1,18 @@ +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +*.so +*.egg +*.egg-info +dist +build +.venv +venv +.env +.env.local +.git +.gitignore +README.md +*.md diff --git a/mengyadriftbottle-backend/Dockerfile b/mengyadriftbottle-backend/Dockerfile new file mode 100644 index 0000000..66af7b9 --- /dev/null +++ b/mengyadriftbottle-backend/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.11-slim + +WORKDIR /app + +# 复制依赖文件 +COPY requirements.txt . + +# 安装依赖 +RUN pip install --no-cache-dir -r requirements.txt + +# 复制应用代码 +COPY . . + +# 暴露端口 +EXPOSE 4343 + +# 设置环境变量 +ENV DRIFT_BOTTLE_DATA_DIR=/data +ENV FLASK_APP=app.py +ENV PORT=4343 + +# 运行应用 +CMD ["python", "app.py"] diff --git a/mengyadriftbottle-backend/app.py b/mengyadriftbottle-backend/app.py index ccec9c6..b96cc3e 100644 --- a/mengyadriftbottle-backend/app.py +++ b/mengyadriftbottle-backend/app.py @@ -42,6 +42,7 @@ PROJECT_ROOT = BACKEND_ROOT.parent # Root project directory FRONTEND_ROOT = PROJECT_ROOT / "mengyadriftbottle-frontend" # Frontend directory TEMPLATES_DIR = FRONTEND_ROOT / "templates" # Templates in frontend STATIC_DIR = FRONTEND_ROOT / "static" # Static files in frontend +BACKGROUND_DIR = BACKEND_ROOT / "background" # Background images directory FRONTEND_DIST = Path( os.environ.get("DRIFT_BOTTLE_FRONTEND_DIST") or PROJECT_ROOT / "frontend-dist" ) @@ -547,7 +548,20 @@ def admin_settings(): # ---------------------------------------------------------------------- # -# ==============================后端公开API============================== # +# ==============================静态文件服务============================== # +# ---------------------------------------------------------------------- # + + +@app.route("/background/") +def serve_background_image(filename: str): + """Serve background images from the background directory.""" + if not BACKGROUND_DIR.exists(): + abort(404) + return send_from_directory(str(BACKGROUND_DIR), filename) + + +# ---------------------------------------------------------------------- # +# ==============================前端应用服务============================== # # ---------------------------------------------------------------------- # @@ -558,6 +572,10 @@ def serve_frontend_app(path: str): if path.startswith("api/"): abort(404) + + # 如果路径是 background/,由上面的路由处理 + if path.startswith("background/"): + abort(404) if not FRONTEND_DIST.exists(): return ("Frontend build not found. Please run npm run build first.", 404) @@ -569,4 +587,6 @@ def serve_frontend_app(path: str): if __name__ == "__main__": - app.run(host="0.0.0.0", port=5002, debug=True) + port = int(os.environ.get("PORT", 5002)) + debug = os.environ.get("FLASK_DEBUG", "False").lower() == "true" + app.run(host="0.0.0.0", port=port, debug=debug) diff --git a/mengyadriftbottle-frontend/public/background/image1.png b/mengyadriftbottle-backend/background/image1.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image1.png rename to mengyadriftbottle-backend/background/image1.png diff --git a/mengyadriftbottle-frontend/public/background/image10.png b/mengyadriftbottle-backend/background/image10.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image10.png rename to mengyadriftbottle-backend/background/image10.png diff --git a/mengyadriftbottle-frontend/public/background/image11.png b/mengyadriftbottle-backend/background/image11.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image11.png rename to mengyadriftbottle-backend/background/image11.png diff --git a/mengyadriftbottle-frontend/public/background/image12.png b/mengyadriftbottle-backend/background/image12.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image12.png rename to mengyadriftbottle-backend/background/image12.png diff --git a/mengyadriftbottle-frontend/public/background/image13.png b/mengyadriftbottle-backend/background/image13.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image13.png rename to mengyadriftbottle-backend/background/image13.png diff --git a/mengyadriftbottle-frontend/public/background/image14.png b/mengyadriftbottle-backend/background/image14.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image14.png rename to mengyadriftbottle-backend/background/image14.png diff --git a/mengyadriftbottle-frontend/public/background/image15.png b/mengyadriftbottle-backend/background/image15.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image15.png rename to mengyadriftbottle-backend/background/image15.png diff --git a/mengyadriftbottle-frontend/public/background/image16.png b/mengyadriftbottle-backend/background/image16.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image16.png rename to mengyadriftbottle-backend/background/image16.png diff --git a/mengyadriftbottle-frontend/public/background/image17.png b/mengyadriftbottle-backend/background/image17.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image17.png rename to mengyadriftbottle-backend/background/image17.png diff --git a/mengyadriftbottle-frontend/public/background/image18.png b/mengyadriftbottle-backend/background/image18.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image18.png rename to mengyadriftbottle-backend/background/image18.png diff --git a/mengyadriftbottle-frontend/public/background/image19.png b/mengyadriftbottle-backend/background/image19.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image19.png rename to mengyadriftbottle-backend/background/image19.png diff --git a/mengyadriftbottle-frontend/public/background/image2.png b/mengyadriftbottle-backend/background/image2.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image2.png rename to mengyadriftbottle-backend/background/image2.png diff --git a/mengyadriftbottle-frontend/public/background/image20.png b/mengyadriftbottle-backend/background/image20.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image20.png rename to mengyadriftbottle-backend/background/image20.png diff --git a/mengyadriftbottle-frontend/public/background/image21.png b/mengyadriftbottle-backend/background/image21.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image21.png rename to mengyadriftbottle-backend/background/image21.png diff --git a/mengyadriftbottle-frontend/public/background/image22.png b/mengyadriftbottle-backend/background/image22.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image22.png rename to mengyadriftbottle-backend/background/image22.png diff --git a/mengyadriftbottle-frontend/public/background/image23.png b/mengyadriftbottle-backend/background/image23.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image23.png rename to mengyadriftbottle-backend/background/image23.png diff --git a/mengyadriftbottle-frontend/public/background/image24.png b/mengyadriftbottle-backend/background/image24.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image24.png rename to mengyadriftbottle-backend/background/image24.png diff --git a/mengyadriftbottle-frontend/public/background/image25.png b/mengyadriftbottle-backend/background/image25.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image25.png rename to mengyadriftbottle-backend/background/image25.png diff --git a/mengyadriftbottle-frontend/public/background/image26.png b/mengyadriftbottle-backend/background/image26.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image26.png rename to mengyadriftbottle-backend/background/image26.png diff --git a/mengyadriftbottle-frontend/public/background/image27.png b/mengyadriftbottle-backend/background/image27.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image27.png rename to mengyadriftbottle-backend/background/image27.png diff --git a/mengyadriftbottle-frontend/public/background/image28.png b/mengyadriftbottle-backend/background/image28.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image28.png rename to mengyadriftbottle-backend/background/image28.png diff --git a/mengyadriftbottle-frontend/public/background/image29.png b/mengyadriftbottle-backend/background/image29.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image29.png rename to mengyadriftbottle-backend/background/image29.png diff --git a/mengyadriftbottle-frontend/public/background/image3.png b/mengyadriftbottle-backend/background/image3.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image3.png rename to mengyadriftbottle-backend/background/image3.png diff --git a/mengyadriftbottle-frontend/public/background/image4.png b/mengyadriftbottle-backend/background/image4.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image4.png rename to mengyadriftbottle-backend/background/image4.png diff --git a/mengyadriftbottle-frontend/public/background/image5.png b/mengyadriftbottle-backend/background/image5.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image5.png rename to mengyadriftbottle-backend/background/image5.png diff --git a/mengyadriftbottle-frontend/public/background/image6.png b/mengyadriftbottle-backend/background/image6.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image6.png rename to mengyadriftbottle-backend/background/image6.png diff --git a/mengyadriftbottle-frontend/public/background/image7.png b/mengyadriftbottle-backend/background/image7.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image7.png rename to mengyadriftbottle-backend/background/image7.png diff --git a/mengyadriftbottle-frontend/public/background/image8.png b/mengyadriftbottle-backend/background/image8.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image8.png rename to mengyadriftbottle-backend/background/image8.png diff --git a/mengyadriftbottle-frontend/public/background/image9.png b/mengyadriftbottle-backend/background/image9.png similarity index 100% rename from mengyadriftbottle-frontend/public/background/image9.png rename to mengyadriftbottle-backend/background/image9.png diff --git a/mengyadriftbottle-backend/docker-compose.yml b/mengyadriftbottle-backend/docker-compose.yml new file mode 100644 index 0000000..61ce071 --- /dev/null +++ b/mengyadriftbottle-backend/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + backend: + build: . + container_name: mengyadriftbottle-backend + ports: + - "3737:4343" + volumes: + - /shumengya/docker/mengyadriftbottle-backend/data:/data + - ./background:/app/background:ro + environment: + - DRIFT_BOTTLE_DATA_DIR=/data + - DRIFT_BOTTLE_SECRET=${DRIFT_BOTTLE_SECRET:-} + - DRIFT_BOTTLE_ADMIN_TOKEN=${DRIFT_BOTTLE_ADMIN_TOKEN:-shumengya520} + restart: unless-stopped + healthcheck: + test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:4343/api/health')"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s diff --git a/mengyadriftbottle-frontend/ENV_SETUP.md b/mengyadriftbottle-frontend/ENV_SETUP.md new file mode 100644 index 0000000..84dd9f3 --- /dev/null +++ b/mengyadriftbottle-frontend/ENV_SETUP.md @@ -0,0 +1,28 @@ +# 环境变量配置说明 + +## 开发环境 + +创建 `.env.development` 文件(或使用默认值): + +``` +VITE_API_BASE_URL=/api +VITE_ADMIN_URL=http://localhost:5002/admin/login +``` + +## 生产环境 + +创建 `.env.production` 文件: + +``` +VITE_API_BASE_URL=https://bottle.api.shumengya.top/api +VITE_ADMIN_URL=https://bottle.api.shumengya.top/admin/login +``` + +## 说明 + +- `VITE_API_BASE_URL`: 后端 API 的基础 URL +- `VITE_ADMIN_URL`: 管理员登录页面的 URL + +前端会自动根据 `VITE_API_BASE_URL` 来设置背景图片的路径: +- 如果 `VITE_API_BASE_URL` 是完整的 URL(如 `https://bottle.api.shumengya.top/api`),背景图片会从该域名加载 +- 如果 `VITE_API_BASE_URL` 是相对路径(如 `/api`),背景图片会使用相对路径 diff --git a/mengyadriftbottle-frontend/index.html b/mengyadriftbottle-frontend/index.html index c67eae4..d7b0c07 100644 --- a/mengyadriftbottle-frontend/index.html +++ b/mengyadriftbottle-frontend/index.html @@ -8,7 +8,12 @@ name="description" content="让心意随海浪飘向远方,邂逅那个懂你的人——萌芽漂流瓶 React 前端" /> + + + + +
diff --git a/mengyadriftbottle-frontend/public/manifest.webmanifest b/mengyadriftbottle-frontend/public/manifest.webmanifest new file mode 100644 index 0000000..c4fc224 --- /dev/null +++ b/mengyadriftbottle-frontend/public/manifest.webmanifest @@ -0,0 +1,25 @@ +{ + "name": "萌芽漂流瓶", + "short_name": "漂流瓶", + "description": "让心意随海浪飘向远方,邂逅那个懂你的人——萌芽漂流瓶", + "lang": "zh-CN", + "start_url": "/", + "scope": "/", + "display": "standalone", + "background_color": "#0b1020", + "theme_color": "#0ea5e9", + "icons": [ + { + "src": "/logo.png", + "sizes": "2048x2048", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/logo3.png", + "sizes": "2048x2048", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/mengyadriftbottle-frontend/public/offline.html b/mengyadriftbottle-frontend/public/offline.html new file mode 100644 index 0000000..b4b3018 --- /dev/null +++ b/mengyadriftbottle-frontend/public/offline.html @@ -0,0 +1,97 @@ + + + + + + + 离线 - 萌芽漂流瓶 + + + +
+

当前处于离线状态

+

网络连接不可用,已为你保留基础页面。恢复网络后可继续使用完整功能。

+
+ 返回首页 + +
+
+ + + diff --git a/mengyadriftbottle-frontend/public/sw.js b/mengyadriftbottle-frontend/public/sw.js new file mode 100644 index 0000000..ec4a7d7 --- /dev/null +++ b/mengyadriftbottle-frontend/public/sw.js @@ -0,0 +1,102 @@ +const CACHE_PREFIX = 'mengyadriftbottle' +const CACHE_VERSION = 'v1' +const STATIC_CACHE = `${CACHE_PREFIX}-static-${CACHE_VERSION}` +const RUNTIME_CACHE = `${CACHE_PREFIX}-runtime-${CACHE_VERSION}` + +const PRECACHE_URLS = [ + '/', + '/index.html', + '/offline.html', + '/manifest.webmanifest', + '/logo.png', + '/logo3.png', +] + +self.addEventListener('install', (event) => { + event.waitUntil( + (async () => { + const cache = await caches.open(STATIC_CACHE) + await cache.addAll(PRECACHE_URLS) + self.skipWaiting() + })(), + ) +}) + +self.addEventListener('activate', (event) => { + event.waitUntil( + (async () => { + const keys = await caches.keys() + await Promise.all( + keys.map((key) => { + if ( + key.startsWith(`${CACHE_PREFIX}-`) && + key !== STATIC_CACHE && + key !== RUNTIME_CACHE + ) { + return caches.delete(key) + } + return undefined + }), + ) + await self.clients.claim() + })(), + ) +}) + +self.addEventListener('message', (event) => { + if (event?.data?.type === 'SKIP_WAITING') { + self.skipWaiting() + } +}) + +function isSameOrigin(url) { + return url.origin === self.location.origin +} + +self.addEventListener('fetch', (event) => { + const { request } = event + if (request.method !== 'GET') return + + const url = new URL(request.url) + if (!isSameOrigin(url)) return + + if (url.pathname.startsWith('/api')) return + + if (request.mode === 'navigate') { + event.respondWith( + (async () => { + try { + const networkResponse = await fetch(request) + const cache = await caches.open(RUNTIME_CACHE) + cache.put('/index.html', networkResponse.clone()) + return networkResponse + } catch { + const cache = await caches.open(RUNTIME_CACHE) + const cached = + (await cache.match('/index.html')) || + (await caches.match('/index.html')) || + (await caches.match('/offline.html')) + return cached || Response.error() + } + })(), + ) + return + } + + const isAsset = ['script', 'style', 'image', 'font'].includes(request.destination) + + if (isAsset) { + event.respondWith( + (async () => { + const cached = await caches.match(request) + if (cached) return cached + + const response = await fetch(request) + const cache = await caches.open(RUNTIME_CACHE) + cache.put(request, response.clone()) + return response + })(), + ) + return + } +}) diff --git a/mengyadriftbottle-frontend/src/App.jsx b/mengyadriftbottle-frontend/src/App.jsx index 6dd8b87..ac030b1 100644 --- a/mengyadriftbottle-frontend/src/App.jsx +++ b/mengyadriftbottle-frontend/src/App.jsx @@ -11,7 +11,28 @@ const DEFAULT_FORM = Object.freeze({ qq: '', }) -const BACKGROUND_IMAGES = Array.from({ length: 29 }, (_, index) => `/background/image${index + 1}.png`) +// 根据环境变量确定背景图片的基础路径 +// 如果设置了 VITE_API_BASE_URL,则使用该 URL 的基础路径;否则使用相对路径 +const getBackgroundBaseUrl = () => { + const apiUrl = import.meta.env.VITE_API_BASE_URL + if (apiUrl && apiUrl.startsWith('http')) { + // 生产环境:从完整 API URL 中提取基础 URL + try { + const url = new URL(apiUrl) + return `${url.protocol}//${url.host}` + } catch { + return '' + } + } + // 开发环境:使用相对路径 + return '' +} + +const BACKGROUND_BASE_URL = getBackgroundBaseUrl() +const BACKGROUND_IMAGES = Array.from( + { length: 29 }, + (_, index) => `${BACKGROUND_BASE_URL}/background/image${index + 1}.png` +) const formatCount = (value) => { const num = typeof value === 'number' ? value : Number(value || 0) diff --git a/mengyadriftbottle-frontend/src/main.jsx b/mengyadriftbottle-frontend/src/main.jsx index b9a1a6d..4e90fe7 100644 --- a/mengyadriftbottle-frontend/src/main.jsx +++ b/mengyadriftbottle-frontend/src/main.jsx @@ -8,3 +8,26 @@ createRoot(document.getElementById('root')).render( , ) + +if (import.meta.env.PROD && 'serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker + .register('/sw.js', { scope: '/', updateViaCache: 'none' }) + .then((registration) => { + registration.update().catch(() => {}) + registration.addEventListener('updatefound', () => { + const worker = registration.installing + if (!worker) return + worker.addEventListener('statechange', () => { + if (worker.state !== 'installed') return + if (navigator.serviceWorker.controller) { + console.info('发现新版本,请刷新页面以更新。') + } else { + console.info('PWA 已启用,可离线使用。') + } + }) + }) + }) + .catch((err) => console.warn('Service Worker 注册失败:', err)) + }) +} diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 3aa3ea0..0000000 --- a/nginx.conf +++ /dev/null @@ -1,54 +0,0 @@ -worker_processes auto; -error_log /dev/stderr warn; -pid /tmp/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /dev/stdout main; - sendfile on; - keepalive_timeout 65; - client_max_body_size 10M; - - # Temp directories for nginx when running as non-root - client_body_temp_path /tmp/client_body; - proxy_temp_path /tmp/proxy; - fastcgi_temp_path /tmp/fastcgi; - uwsgi_temp_path /tmp/uwsgi; - scgi_temp_path /tmp/scgi; - - upstream backend { - server 127.0.0.1:5002; - } - - server { - listen 6767; - server_name _; - - root /app/frontend-dist; - index index.html; - - # Frontend static files - location / { - try_files $uri $uri/ /index.html; - } - - # Proxy API requests to backend - location /api/ { - proxy_pass http://backend; - 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; - } - } -} diff --git a/start.sh b/start.sh deleted file mode 100644 index 4ec190c..0000000 --- a/start.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -e - -# ensure data dir exists (mounted volume expected) -DATA_DIR=${DRIFT_BOTTLE_DATA_DIR:-/app/data} -mkdir -p "$DATA_DIR" - -for json_file in bottles.json filter_words.json mottos.json config.json; do - if [ -f "/app/mengyadriftbottle-backend/${json_file}" ] && [ ! -f "$DATA_DIR/${json_file}" ]; then - cp "/app/mengyadriftbottle-backend/${json_file}" "$DATA_DIR/${json_file}" - fi -done - -# start backend on localhost:5002 (not exposed outside container) -BACKEND_PORT=${BACKEND_PORT:-5002} - -echo "Starting backend API on localhost:${BACKEND_PORT}" -cd /app/mengyadriftbottle-backend -gunicorn -b 127.0.0.1:${BACKEND_PORT} app:app & -BACKEND_PID=$! - -# start nginx to serve frontend + proxy /api to backend -echo "Starting nginx on port 6767 (proxying /api to backend)" -nginx -g 'daemon off;' & -NGINX_PID=$! - -trap "kill $BACKEND_PID $NGINX_PID" TERM INT -wait -n $BACKEND_PID $NGINX_PID diff --git a/start_backend.bat b/start_backend.bat new file mode 100644 index 0000000..4821776 --- /dev/null +++ b/start_backend.bat @@ -0,0 +1,6 @@ +@echo off +chcp 65001 >nul +echo 启动后端服务器... +cd mengyadriftbottle-backend +go mod tidy +go run main.go diff --git a/start_frontend.bat b/start_frontend.bat new file mode 100644 index 0000000..e40f90a --- /dev/null +++ b/start_frontend.bat @@ -0,0 +1,7 @@ +@echo off +chcp 65001 >nul +echo 启动前端开发服务器... +cd mengyadriftbottle-frontend +echo 正在安装依赖... +call npm install +npm run dev \ No newline at end of file diff --git a/萌芽漂流瓶 b/萌芽漂流瓶 new file mode 100644 index 0000000..e69de29