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 + `