From 63781358b28b06c7e98da7b8834a0ba8b949e1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A0=91=E8=90=8C=E8=8A=BD?= <3205788256@qq.com> Date: Fri, 27 Mar 2026 15:10:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E7=BB=93=E6=9E=84=EF=BC=8C=E8=BF=81=E7=A7=BB=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E8=87=B3=20mengyastore-backend-go=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20Java=20=E5=90=8E=E7=AB=AF=E3=80=81=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E5=8A=9F=E8=83=BD=E6=9B=B4=E6=96=B0=E5=8F=8A=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 + DEPLOY.md | 399 ++++++++++++++++++ README.md | 262 ++++++++++-- .../.dockerignore | 0 .../Dockerfile | 0 .../README.md | 0 .../cmd/migrate/main.go | 2 +- .../docker-compose.yml | 5 +- .../go.mod | 0 .../go.sum | 0 mengyastore-backend-go/init.sql | 28 ++ .../internal/auth/sproutgate.go | 12 +- .../internal/config/config.go | 23 +- .../internal/database/db.go | 2 +- .../internal/database/models.go | 0 .../internal/email/email.go | 41 +- .../internal/handlers/admin.go | 19 +- .../internal/handlers/admin_chat.go | 16 +- .../internal/handlers/admin_orders.go | 2 +- .../internal/handlers/admin_product.go | 24 +- .../internal/handlers/admin_site.go | 8 +- .../internal/handlers/chat.go | 6 +- .../internal/handlers/order.go | 35 +- .../internal/handlers/public.go | 5 +- .../internal/handlers/stats.go | 0 .../internal/handlers/wishlist.go | 4 +- .../internal/models/chat.go | 0 .../internal/models/order.go | 0 .../internal/models/product.go | 0 .../internal/storage/chatstore.go | 0 .../internal/storage/orderstore.go | 9 +- .../internal/storage/productstore.go | 37 +- .../internal/storage/sitestore.go | 29 +- .../internal/storage/wishliststore.go | 0 .../main.go | 31 +- .../mengyastore-backend-java/.gitattributes | 3 + .../mengyastore-backend-java/.gitignore | 37 ++ .../mengyastore-backend-java/build.gradle | 39 ++ .../mengyastore-backend-java/compose.yaml | 1 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 48966 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../mengyastore-backend-java/gradlew | 248 +++++++++++ .../mengyastore-backend-java/gradlew.bat | 93 ++++ .../mengyastore-backend-java/settings.gradle | 1 + .../MengyastoreBackendJavaApplication.java | 13 + .../src/main/resources/application.yaml | 3 + ...engyastoreBackendJavaApplicationTests.java | 13 + mengyastore-backend-java/.gitattributes | 2 + mengyastore-backend-java/.gitignore | 33 ++ .../.mvn/wrapper/maven-wrapper.properties | 3 + mengyastore-backend-java/compose.yaml | 1 + mengyastore-backend-java/mvnw | 295 +++++++++++++ mengyastore-backend-java/mvnw.cmd | 189 +++++++++ mengyastore-backend-java/pom.xml | 91 ++++ .../MengyastoreBackendJavaApplication.java | 13 + .../src/main/resources/application.yaml | 3 + ...engyastoreBackendJavaApplicationTests.java | 13 + mengyastore-backend/data/json/settings.json | 3 - mengyastore-frontend/package-lock.json | 36 -- mengyastore-frontend/src/App.vue | 8 +- .../src/modules/admin/AdminPage.vue | 8 - .../admin/components/AdminChatPanel.vue | 2 +- .../admin/components/AdminOrderTable.vue | 2 +- .../modules/admin/components/AdminSMTPRow.vue | 69 ++- .../admin/components/AdminTokenRow.vue | 5 +- .../src/modules/auth/AuthCallback.vue | 4 +- .../src/modules/chat/ChatWidget.vue | 2 +- .../src/modules/shared/api.js | 43 +- .../src/modules/shared/useWishlist.js | 4 +- 萌芽小店项目经历.md | 12 + 项目面试询问相关.md | 72 ++++ 71 files changed, 2123 insertions(+), 250 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 DEPLOY.md rename {mengyastore-backend => mengyastore-backend-go}/.dockerignore (100%) rename {mengyastore-backend => mengyastore-backend-go}/Dockerfile (100%) rename {mengyastore-backend => mengyastore-backend-go}/README.md (100%) rename {mengyastore-backend => mengyastore-backend-go}/cmd/migrate/main.go (99%) rename {mengyastore-backend => mengyastore-backend-go}/docker-compose.yml (60%) rename {mengyastore-backend => mengyastore-backend-go}/go.mod (100%) rename {mengyastore-backend => mengyastore-backend-go}/go.sum (100%) create mode 100644 mengyastore-backend-go/init.sql rename {mengyastore-backend => mengyastore-backend-go}/internal/auth/sproutgate.go (78%) rename {mengyastore-backend => mengyastore-backend-go}/internal/config/config.go (59%) rename {mengyastore-backend => mengyastore-backend-go}/internal/database/db.go (90%) rename {mengyastore-backend => mengyastore-backend-go}/internal/database/models.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/internal/email/email.go (80%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/admin.go (51%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/admin_chat.go (77%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/admin_orders.go (91%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/admin_product.go (84%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/admin_site.go (86%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/chat.go (91%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/order.go (87%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/public.go (93%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/stats.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/internal/handlers/wishlist.go (94%) rename {mengyastore-backend => mengyastore-backend-go}/internal/models/chat.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/internal/models/order.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/internal/models/product.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/internal/storage/chatstore.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/internal/storage/orderstore.go (90%) rename mengyastore-backend/internal/storage/jsonstore.go => mengyastore-backend-go/internal/storage/productstore.go (87%) rename {mengyastore-backend => mengyastore-backend-go}/internal/storage/sitestore.go (75%) rename {mengyastore-backend => mengyastore-backend-go}/internal/storage/wishliststore.go (100%) rename {mengyastore-backend => mengyastore-backend-go}/main.go (83%) create mode 100644 mengyastore-backend-go/mengyastore-backend-java/.gitattributes create mode 100644 mengyastore-backend-go/mengyastore-backend-java/.gitignore create mode 100644 mengyastore-backend-go/mengyastore-backend-java/build.gradle create mode 100644 mengyastore-backend-go/mengyastore-backend-java/compose.yaml create mode 100644 mengyastore-backend-go/mengyastore-backend-java/gradle/wrapper/gradle-wrapper.jar create mode 100644 mengyastore-backend-go/mengyastore-backend-java/gradle/wrapper/gradle-wrapper.properties create mode 100644 mengyastore-backend-go/mengyastore-backend-java/gradlew create mode 100644 mengyastore-backend-go/mengyastore-backend-java/gradlew.bat create mode 100644 mengyastore-backend-go/mengyastore-backend-java/settings.gradle create mode 100644 mengyastore-backend-go/mengyastore-backend-java/src/main/java/com/smyhub/store/mengyastorebackendjava/MengyastoreBackendJavaApplication.java create mode 100644 mengyastore-backend-go/mengyastore-backend-java/src/main/resources/application.yaml create mode 100644 mengyastore-backend-go/mengyastore-backend-java/src/test/java/com/smyhub/store/mengyastorebackendjava/MengyastoreBackendJavaApplicationTests.java create mode 100644 mengyastore-backend-java/.gitattributes create mode 100644 mengyastore-backend-java/.gitignore create mode 100644 mengyastore-backend-java/.mvn/wrapper/maven-wrapper.properties create mode 100644 mengyastore-backend-java/compose.yaml create mode 100644 mengyastore-backend-java/mvnw create mode 100644 mengyastore-backend-java/mvnw.cmd create mode 100644 mengyastore-backend-java/pom.xml create mode 100644 mengyastore-backend-java/src/main/java/com/smyhub/store/mengyastorebackendjava/MengyastoreBackendJavaApplication.java create mode 100644 mengyastore-backend-java/src/main/resources/application.yaml create mode 100644 mengyastore-backend-java/src/test/java/com/smyhub/store/mengyastorebackendjava/MengyastoreBackendJavaApplicationTests.java delete mode 100644 mengyastore-backend/data/json/settings.json create mode 100644 萌芽小店项目经历.md create mode 100644 项目面试询问相关.md diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5480842 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "kiroAgent.configureMCP": "Disabled" +} \ No newline at end of file diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..4f5ff82 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,399 @@ +# 萌芽小店 · 生产环境部署指南 + +> 本指南覆盖从零开始将萌芽小店完整部署到生产服务器的全部步骤,包括后端 Docker 部署与前端静态文件托管。 + +--- + +## 目录 + +1. [环境要求](#1-环境要求) +2. [准备 MySQL 数据库](#2-准备-mysql-数据库) +3. [部署后端(Docker)](#3-部署后端docker) +4. [构建并部署前端](#4-构建并部署前端) +5. [Nginx 反向代理配置](#5-nginx-反向代理配置) +6. [验证部署](#6-验证部署) +7. [常见问题排查](#7-常见问题排查) +8. [升级与回滚](#8-升级与回滚) + +--- + +## 1. 环境要求 + +| 组件 | 最低版本 | 说明 | +|------|----------|------| +| 服务器 OS | Linux (Ubuntu 22.04 / Debian 12 推荐) | 也支持 CentOS / AlmaLinux | +| Docker | 24.x | `docker --version` 确认 | +| Docker Compose | v2.x | `docker compose version` 确认 | +| MySQL | 8.x | 可使用内网 MySQL 实例 | +| Nginx | 1.20+ | 用于前端静态托管 + API 反向代理 | +| Node.js(构建时) | 18+ | 仅前端打包时需要 | + +--- + +## 2. 准备 MySQL 数据库 + +> **表结构无需手动创建**,后端启动时 GORM 会自动执行 `AutoMigrate` 建表。 + +### 2.1 创建数据库和用户 + +在 MySQL 服务器上执行: + +```sql +CREATE DATABASE IF NOT EXISTS `mengyastore` + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +CREATE USER IF NOT EXISTS 'mengyastore'@'%' + IDENTIFIED BY 'your_strong_password'; + +GRANT ALL PRIVILEGES ON `mengyastore`.* TO 'mengyastore'@'%'; + +FLUSH PRIVILEGES; +``` + +或者使用项目提供的初始化脚本: + +```bash +mysql -u root -p < mengyastore-backend/init.sql +``` + +### 2.2 验证连接 + +```bash +mysql -h 192.168.1.100 -P 3306 -u mengyastore -p mengyastore +# 出现 mysql> 提示符即表示连接成功 +``` + +--- + +## 3. 部署后端(Docker) + +### 3.1 将代码上传到服务器 + +```bash +# 方式一:git clone(推荐) +git clone https://your-repo-url/mengyastore.git +cd mengyastore/mengyastore-backend + +# 方式二:scp 上传 +scp -r mengyastore-backend/ user@your-server:/opt/mengyastore/ +``` + +### 3.2 创建 `config.json` + +在 `mengyastore-backend/` 目录下创建配置文件(**此文件不会被提交到 Git,需手动创建**): + +```bash +cat > /opt/mengyastore/mengyastore-backend/config.json << 'EOF' +{ + "adminToken": "your_strong_admin_token", + "databaseDsn": "mengyastore:your_password@tcp(192.168.1.100:3306)/mengyastore?charset=utf8mb4&parseTime=True&loc=Local" +} +EOF +``` + +> ⚠️ `adminToken` 请设置为足够强的随机字符串(建议 16 位以上),这是进入管理后台的唯一凭证。 + +### 3.3 检查 `docker-compose.yml` + +确认 `mengyastore-backend/docker-compose.yml` 中的 `DATABASE_DSN` 与你的生产数据库匹配: + +```yaml +services: + backend: + build: + context: . + container_name: mengyastore-backend + ports: + - "28081:8080" # 宿主机端口:容器端口,可按需修改 + environment: + GIN_MODE: release + TZ: Asia/Shanghai + DATABASE_DSN: "mengyastore:your_password@tcp(192.168.1.100:3306)/mengyastore?charset=utf8mb4&parseTime=True&loc=Local" + volumes: + - ./config.json:/app/config.json:ro # 挂载配置文件(只读) + restart: unless-stopped +``` + +> `DATABASE_DSN` 环境变量优先级高于 `config.json`,两者保持一致即可。 + +### 3.4 构建并启动容器 + +```bash +cd /opt/mengyastore/mengyastore-backend + +# 首次部署 +docker compose up -d --build + +# 查看启动日志 +docker compose logs -f + +# 预期看到: +# [DB] 数据库连接成功,表结构已同步 +# 萌芽小店后端启动于 http://localhost:8080 +``` + +### 3.5 验证后端 + +```bash +curl http://localhost:28081/api/health +# 应返回:{"status":"ok"} + +curl http://localhost:28081/api/products +# 应返回:{"data":[...]}(空数组或商品列表) +``` + +--- + +## 4. 构建并部署前端 + +### 4.1 本地构建(推荐在本地完成后上传 dist) + +```bash +cd mengyastore-frontend + +# 安装依赖 +npm install + +# 生产构建 +npm run build +# 输出目录:dist/ +``` + +### 4.2 配置 API 地址 + +前端通过 Vite 的 `VITE_API_BASE_URL` 环境变量指定后端地址。如果前端与后端同域(通过 Nginx 代理),也可以不配置,默认会使用当前站点域名。 + +如果前后端跨域,在 `mengyastore-frontend/` 目录创建 `.env.production`: + +```ini +VITE_API_BASE_URL=https://store.api.shumengya.top +``` + +然后重新 `npm run build`。 + +### 4.3 上传 dist 到服务器 + +```bash +# 假设静态文件托管在 /var/www/mengyastore/ +scp -r dist/* user@your-server:/var/www/mengyastore/ + +# 或使用 rsync(增量同步更快) +rsync -avz --delete dist/ user@your-server:/var/www/mengyastore/ +``` + +--- + +## 5. Nginx 反向代理配置 + +### 5.1 安装 Nginx + +```bash +# Ubuntu / Debian +sudo apt update && sudo apt install -y nginx + +# CentOS / AlmaLinux +sudo yum install -y nginx +``` + +### 5.2 创建站点配置 + +```bash +sudo nano /etc/nginx/sites-available/mengyastore +``` + +写入以下内容(替换 `your-domain.com` 为你的实际域名): + +```nginx +server { + listen 80; + server_name your-domain.com; + + # 前端静态文件 + root /var/www/mengyastore; + index index.html; + + # Vue Router History 模式:所有路由回退到 index.html + location / { + try_files $uri $uri/ /index.html; + } + + # 反向代理后端 API + location /api/ { + proxy_pass http://127.0.0.1:28081; + 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_connect_timeout 30s; + proxy_read_timeout 60s; + } + + # 静态资源缓存 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2|webmanifest)$ { + expires 7d; + add_header Cache-Control "public, immutable"; + } +} +``` + +### 5.3 启用配置并重启 + +```bash +sudo ln -s /etc/nginx/sites-available/mengyastore /etc/nginx/sites-enabled/ +sudo nginx -t # 测试配置语法 +sudo systemctl reload nginx +``` + +### 5.4 (可选)配置 HTTPS(Let's Encrypt) + +```bash +sudo apt install -y certbot python3-certbot-nginx +sudo certbot --nginx -d your-domain.com +# 按提示操作,certbot 会自动修改 Nginx 配置并续签证书 +``` + +--- + +## 6. 验证部署 + +### 6.1 检查列表 + +- [ ] `https://your-domain.com` 能正常打开首页 +- [ ] 商品列表加载正常(若为空请先登录后台添加商品) +- [ ] 登录 SproutGate 账号后,收藏夹/聊天等功能正常 +- [ ] **Logo 点击 5 次**弹出管理员登录框,输入 `adminToken` 能进入后台 +- [ ] 后台可以新建/编辑/删除商品 +- [ ] 下单流程(自动发货)能正常获取卡密 +- [ ] PWA:在 Chrome 地址栏点击安装图标,可添加到桌面 + +### 6.2 后端日志查看 + +```bash +docker compose -f /opt/mengyastore/mengyastore-backend/docker-compose.yml logs -f +``` + +--- + +## 7. 常见问题排查 + +### 问题:前端白屏 / 控制台报 CORS 错误 + +**原因**:Nginx 未正确代理 `/api/` 请求,或后端未启动。 + +**排查**: +```bash +curl http://127.0.0.1:28081/api/health +docker compose ps # 确认容器正在运行 +``` + +--- + +### 问题:管理员登录失败("验证失败,无法连接服务器") + +**原因**:后端容器未运行,或 Nginx `/api/` 代理配置有误。 + +**排查**: +```bash +docker compose ps +curl http://127.0.0.1:28081/api/health +``` + +--- + +### 问题:管理员登录失败("令牌错误,请重试") + +**原因**:输入的令牌与 `config.json` 中的 `adminToken` 不一致。 + +**排查**:检查服务器上的 `config.json`: +```bash +cat /opt/mengyastore/mengyastore-backend/config.json +``` + +--- + +### 问题:商品列表为空 + +**原因**:数据库为空,需要通过管理后台添加商品。 + +**步骤**: +1. 登录管理后台 +2. 点击"商品管理" → "新增商品" +3. 填写商品名称、价格、卡密(自动发货)或选择手动发货模式 + +--- + +### 问题:数据库连接失败(启动时报错) + +**原因**:`DATABASE_DSN` 配置错误,或 MySQL 服务不可达。 + +**排查**: +```bash +# 在宿主机上测试数据库连接 +mysql -h 192.168.1.100 -P 3306 -u mengyastore -p + +# 查看后端详细日志 +docker compose logs backend | head -50 +``` + +--- + +### 问题:`record not found` 日志警告 + +**说明**:这是 GORM 的正常行为,表示某些站点设置(如维护模式)在数据库中尚未有记录。**不影响功能**,首次设置后会自动写入。 + +--- + +## 8. 升级与回滚 + +### 升级 + +```bash +cd /opt/mengyastore/mengyastore-backend + +# 拉取最新代码(如果使用 git) +git pull + +# 重新构建并重启 +docker compose up -d --build + +# 查看新版本日志 +docker compose logs -f +``` + +### 回滚 + +```bash +# 查看历史镜像 +docker images | grep mengyastore + +# 停止当前容器,启动旧版本 +docker compose down +docker tag mengyastore-backend-backend:previous mengyastore-backend-backend:latest +docker compose up -d +``` + +--- + +## 附:目录结构参考 + +``` +/opt/mengyastore/ + mengyastore-backend/ + config.json ← 生产配置(不要提交到 Git!) + docker-compose.yml + Dockerfile + ...(Go 源码) + +/var/www/mengyastore/ ← 前端 dist 文件 + index.html + assets/ + ... +``` + +--- + +> 如遇到本指南未覆盖的问题,请查看后端实时日志: +> `docker compose -f /opt/mengyastore/mengyastore-backend/docker-compose.yml logs -f` + +**部署完成 🎉** 访问 `https://your-domain.com` 即可看到萌芽小店正式上线。 diff --git a/README.md b/README.md index 47b6ca2..907e541 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,263 @@ -# mengyastore +# 萌芽小店 · Mengyastore -萌芽小店,一个前后端分离的商城项目。 +一个前后端分离的轻量级商城,支持自动/手动发货、邮件通知、聊天客服、收藏夹与 PWA 安装。 -## 项目结构 +--- -- `mengyastore-frontend/`:Vue 3 + Vite 前端 -- `mengyastore-backend/`:Go + Gin 后端 -- `mengyastore-backend/data/json/`:商品、订单、站点配置等本地数据 +## 技术栈 -## 功能 +### 前端 `mengyastore-frontend/` -- 商品浏览、详情查看、下单 -- 登录回调与用户订单页 -- 后台商品管理 -- 访问统计、商品浏览统计 +| 分类 | 技术 | 版本 | 说明 | +|------|------|------|------| +| 框架 | Vue 3 | ^3.4 | Composition API + `