feat: fulfillment modes, MQ, admin status, docs; scrub compose secrets
Made-with: Cursor
This commit is contained in:
289
README.md
289
README.md
@@ -1,6 +1,6 @@
|
||||
# 萌芽小店 · Mengyastore
|
||||
|
||||
一个前后端分离的轻量级商城,支持自动/手动发货、邮件通知、聊天客服、收藏夹与 PWA 安装。
|
||||
一个前后端分离的轻量级数字商品商城,支持**卡密 / 固定内容**两种发货、扫码收款演示流程、邮件通知(直发或 RabbitMQ 队列)、聊天客服、收藏夹、管理端系统状态面板与 PWA 安装。
|
||||
|
||||
---
|
||||
|
||||
@@ -8,231 +8,141 @@
|
||||
|
||||
### 前端 `mengyastore-frontend/`
|
||||
|
||||
| 分类 | 技术 | 版本 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 框架 | Vue 3 | ^3.4 | Composition API + `<script setup>` |
|
||||
| 构建工具 | Vite 5 | ^5.2 | 开发服务器 / 生产打包 |
|
||||
| 路由 | Vue Router 4 | ^4.3 | Hash / History 模式 |
|
||||
| 状态管理 | Pinia 2 | ^2.1 | 全局 auth 状态 |
|
||||
| HTTP 客户端 | Axios | ^1.6 | API 请求封装 |
|
||||
| Markdown 渲染 | markdown-it | ^14.1 | 商品描述富文本 |
|
||||
| PWA | vite-plugin-pwa | ^1.2 | Service Worker + Web Manifest |
|
||||
| PWA 图标生成 | @vite-pwa/assets-generator | ^1.0 | 从 logo 自动生成各尺寸 PNG |
|
||||
| 认证 | SproutGate OAuth | — | 第三方账号系统,redirect 回调 |
|
||||
| 样式 | 原生 CSS + Scoped | — | CSS 变量、Flexbox、Grid、媒体查询 |
|
||||
| 分类 | 技术 | 说明 |
|
||||
|------|------|------|
|
||||
| 框架 | Vue 3 | Composition API + `<script setup>` |
|
||||
| 构建 | Vite 5 + `@tailwindcss/vite` | 开发与生产打包 |
|
||||
| 路由 | Vue Router 4 | History 模式 |
|
||||
| 状态 | Pinia、本地 reactive | 收藏与认证等 |
|
||||
| HTTP | Axios | `modules/shared/api.js` |
|
||||
| Markdown | markdown-it | 商品描述 |
|
||||
| PWA | vite-plugin-pwa | Service Worker、Manifest、更新提示 |
|
||||
| 认证 | SproutGate OAuth | 回调 `AuthCallback.vue` |
|
||||
|
||||
**主要模块**
|
||||
|
||||
```
|
||||
src/
|
||||
modules/
|
||||
admin/ # 管理员后台(商品/订单/聊天/站点设置)
|
||||
auth/ # OAuth 回调处理
|
||||
chat/ # 用户端悬浮聊天窗口
|
||||
maintenance/ # 维护模式页面
|
||||
shared/ # api.js / auth.js / SplashScreen.vue / useWishlist.js
|
||||
store/ # 商品列表、详情、结账
|
||||
admin/ # 管理后台(商品/订单/聊天/站点设置/系统状态)
|
||||
auth/ # OAuth 回调
|
||||
chat/ # 用户悬浮聊天
|
||||
maintenance/ # 维护页
|
||||
shared/ # api.js、auth、fulfillment.js、useWishlist、SplashScreen
|
||||
store/ # 商店、详情、结算(含真实收款码展示)
|
||||
user/ # 我的订单
|
||||
wishlist/ # 收藏夹
|
||||
assets/styles.css # 全局样式变量
|
||||
router/index.js # 路由定义 + 全局导航守卫
|
||||
main.js # 应用入口
|
||||
assets/
|
||||
payment/ # 支付宝/微信收款图(打包进产物,供结算页演示)
|
||||
styles.css
|
||||
App.vue # 顶栏;窄屏为汉堡菜单 + 下拉导航
|
||||
router/index.js # 路由与维护模式守卫
|
||||
```
|
||||
|
||||
**PWA 特性**
|
||||
|
||||
- `display: standalone` 独立窗口模式,可添加到主屏
|
||||
- Service Worker:静态资源 `CacheFirst`,API 请求 `NetworkFirst`(5 分钟缓存)
|
||||
- 自动检测新版本,底部 toast 提示更新
|
||||
- 启动画面(SplashScreen.vue):渐变背景 + Logo 浮动 + 扩散环 + 绿色圆点加载动画
|
||||
|
||||
---
|
||||
|
||||
### 后端 `mengyastore-backend/`
|
||||
### 后端 `mengyastore-backend-go/`
|
||||
|
||||
| 分类 | 技术 | 版本 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 语言 | Go | 1.21+ | 静态编译,单二进制部署 |
|
||||
| Web 框架 | Gin | ^1.9 | HTTP 路由、中间件、JSON 绑定 |
|
||||
| ORM | GORM | ^1.25 | MySQL 数据库操作 |
|
||||
| MySQL 驱动 | go-sql-driver/mysql | ^1.9 | GORM MySQL 方言 |
|
||||
| CORS | gin-contrib/cors | — | 跨域请求支持 |
|
||||
| UUID | google/uuid | — | 订单 ID 生成 |
|
||||
| 邮件 | net/smtp + crypto/tls | 标准库 | SMTP 邮件通知,支持 SSL/TLS(端口 465) |
|
||||
| 认证 | SproutGate OAuth | — | `/api/auth/verify` Token 验证 |
|
||||
| 数据库 | MySQL 8.x | — | 生产:192.168.1.100:3306,测试:10.1.1.100:3306 |
|
||||
| 容器化 | Docker + docker-compose | — | 镜像构建与部署 |
|
||||
| 分类 | 技术 | 说明 |
|
||||
|------|------|------|
|
||||
| 语言 | Go 1.21+ | 单二进制部署 |
|
||||
| Web | Gin | REST、CORS |
|
||||
| ORM | GORM | MySQL,`Open` 时 AutoMigrate |
|
||||
| 消息 | RabbitMQ(可选) | `internal/mq`,订单邮件可走队列;连接异常自动重连 |
|
||||
| 缓存 | Redis(可选) | 配置项齐全,可用于扩展;管理端状态可探测 |
|
||||
| 邮件 | `internal/email` | SMTP;与 MQ 二选一或降级 |
|
||||
| 配置 | 环境变量 + `.env` | `internal/config`,见下文 |
|
||||
|
||||
**主要模块**
|
||||
|
||||
```
|
||||
internal/
|
||||
auth/ # SproutGate OAuth 客户端
|
||||
config/ # config.json 读写(adminToken、DSN 等)
|
||||
database/ # GORM 初始化 (db.go) + 表结构定义 (models.go)
|
||||
email/ # SMTP 邮件发送服务
|
||||
handlers/ # HTTP 处理器(按功能拆分文件)
|
||||
admin.go # 通用管理员接口
|
||||
admin_chat.go # 聊天管理
|
||||
admin_orders.go # 订单管理(查看/确认/删除/分页)
|
||||
admin_product.go # 商品 CRUD
|
||||
admin_site.go # 站点设置(维护模式、SMTP 配置)
|
||||
chat.go # 用户聊天消息读写
|
||||
order.go # 下单 / 自动发货 / 邮件通知
|
||||
stats.go # 访问统计
|
||||
wishlist.go # 收藏夹
|
||||
models/ # 业务模型(Product、Order、Chat 等)
|
||||
storage/ # 数据库 CRUD 封装(每类资源一个文件)
|
||||
cmd/
|
||||
migrate/main.go # 数据库 Schema 初始化 / 迁移脚本
|
||||
main.go # 路由注册 + 依赖注入入口
|
||||
auth/ # SproutGate 校验
|
||||
cache/ # Redis 等(按项目演进)
|
||||
config/ # Load():APP_ENV、DB、Redis、RabbitMQ、HTTP 监听等
|
||||
database/ # db.go、models.go
|
||||
email/
|
||||
handlers/ # public、order、stats、wishlist、chat、admin_*、admin_status
|
||||
mq/ # AMQP 发布/消费、拓扑、重连
|
||||
models/
|
||||
storage/ # product、order、site、wishlist、chat(productstore 含 fulfillment)
|
||||
cmd/migrate/ # 历史 JSON → MySQL 迁移
|
||||
main.go # 依赖注入、路由
|
||||
```
|
||||
|
||||
**数据库表**
|
||||
**数据库表(要点)**
|
||||
|
||||
| 表名 | 主要字段 |
|
||||
|------|---------|
|
||||
| `products` | id, name, description, price, discount_price, cover_url, screenshot_urls, tags, codes(卡密), delivery_mode, require_login, max_per_account, total_sold, view_count, active, created_at |
|
||||
| `product_codes` | id, product_id, code(卡密条目) |
|
||||
| `orders` | id, product_id, product_name, user_account, user_name, quantity, status, delivery_mode, delivered_codes, note, contact_phone, contact_email, notify_email, created_at |
|
||||
| `chat_messages` | id, account_id, account_name, content, sent_at, from_admin |
|
||||
| `wishlists` | id, account, product_id |
|
||||
| `site_settings` | key, value(KV 存储:maintenance、SMTP 配置等) |
|
||||
| 表 | 说明 |
|
||||
|----|------|
|
||||
| `products` | 含 `fulfillment_type`(`card`/`fixed`)、`fixed_content`、`delivery_mode`(订单侧自动/手动)等 |
|
||||
| `product_codes` | 卡密行表;`fixed` 商品可不使用 |
|
||||
| `orders` | `delivered_codes`、`notify_email`、`delivery_mode`、`status` |
|
||||
| `site_settings` | 维护、SMTP、访问量等 KV |
|
||||
| `wishlists` / `chat_messages` | 收藏与聊天 |
|
||||
|
||||
---
|
||||
|
||||
## 功能列表
|
||||
## 功能列表(摘要)
|
||||
|
||||
| 功能 | 前端 | 后端 |
|
||||
|------|------|------|
|
||||
| 商品浏览(分页:桌面 4×5 / 手机 5×2) | ✅ | ✅ |
|
||||
| 商品详情 + Markdown 描述 | ✅ | ✅ |
|
||||
| 下单(自动/手动发货) | ✅ | ✅ |
|
||||
| 订单邮件通知(SMTP 可配置) | ✅ | ✅ |
|
||||
| 用户收藏夹 | ✅ | ✅ |
|
||||
| 我的订单 | ✅ | ✅ |
|
||||
| SproutGate 账号登录 | ✅ | ✅ |
|
||||
| 用户聊天客服(HTTP 轮询) | ✅ | ✅ |
|
||||
| 维护模式 | ✅ | ✅ |
|
||||
| 管理后台 - 商品 CRUD | ✅ | ✅ |
|
||||
| 管理后台 - 订单查看/确认/删除/分页 | ✅ | ✅ |
|
||||
| 管理后台 - 聊天消息管理 | ✅ | ✅ |
|
||||
| 管理后台 - SMTP 邮件配置(含启用/关闭开关) | ✅ | ✅ |
|
||||
| 管理后台 - 站点设置(维护模式) | ✅ | ✅ |
|
||||
| 访问统计 & 订单统计 | ✅ | ✅ |
|
||||
| PWA 安装 + 离线缓存 | ✅ | — |
|
||||
| 移动端响应式 | ✅ | — |
|
||||
| 能力 | 前端 | 后端 |
|
||||
|------|:----:|:----:|
|
||||
| 商品浏览、详情、Markdown | ✅ | ✅ |
|
||||
| **发货方式**:卡密(逐条库存)/ 固定内容(不限库存) | ✅ | ✅ |
|
||||
| 结算页:应付金额、**本地上传收款码**、订单号一键复制 | ✅ | 订单仍返回 `qrCodeUrl` 作凭证 |
|
||||
| 订单确认、我的订单 | ✅ | ✅ |
|
||||
| SMTP 邮件;可选 **RabbitMQ** 排队发信 | — | ✅ |
|
||||
| 管理端 **系统状态**(API/ MySQL/ Redis/ RabbitMQ) | ✅ | ✅ |
|
||||
| 收藏夹、聊天、维护模式 | ✅ | ✅ |
|
||||
| SproutGate 登录 | ✅ | ✅ |
|
||||
| PWA | ✅ | — |
|
||||
| **窄屏顶栏**(汉堡菜单) | ✅ | — |
|
||||
|
||||
---
|
||||
|
||||
## 快速开始(从零部署)
|
||||
## 快速开始
|
||||
|
||||
### 1. 准备 MySQL 数据库
|
||||
### 1. MySQL
|
||||
|
||||
> **表结构无需手动创建**,后端启动时 GORM 会自动 `AutoMigrate`。
|
||||
> 只需创建数据库和用户:
|
||||
创建库与用户后,**无需手写表结构**,后端首次连接会 `AutoMigrate`。
|
||||
|
||||
可参考 `mengyastore-backend-go/init.sql` 中的建库语句。
|
||||
|
||||
### 2. 后端配置
|
||||
|
||||
在 **`mengyastore-backend-go/`** 使用 **`.env`**(或环境变量)。常用项:
|
||||
|
||||
- `APP_ENV`:`development` / `production`(影响默认 DSN、RabbitMQ/Redis 默认地址等)
|
||||
- `DATABASE_DSN`:MySQL 连接串
|
||||
- `ADMIN_TOKEN`:管理端令牌
|
||||
- `AUTH_API_URL`:SproutGate 网关
|
||||
- `RABBITMQ_ENABLED`、`RABBITMQ_URL`(或密码拼装变量)
|
||||
- `REDIS_ENABLED`、`REDIS_ADDR` 等(可选)
|
||||
- `HTTP_LISTEN_ADDR`、`PUBLIC_API_BASE_URL`(系统状态展示用,可选)
|
||||
|
||||
```bash
|
||||
mysql -u root -p < mengyastore-backend/init.sql
|
||||
cd mengyastore-backend-go
|
||||
go run . # 默认 :8080,见配置
|
||||
```
|
||||
|
||||
或手动执行:
|
||||
|
||||
```sql
|
||||
CREATE DATABASE IF NOT EXISTS `mengyastore` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
CREATE USER IF NOT EXISTS 'mengyastore'@'%' IDENTIFIED BY 'your_password';
|
||||
GRANT ALL PRIVILEGES ON `mengyastore`.* TO 'mengyastore'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
### 2. 配置后端
|
||||
|
||||
在 `mengyastore-backend/` 目录创建 `config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"adminToken": "your_admin_token_here",
|
||||
"databaseDsn": "mengyastore:your_password@tcp(127.0.0.1:3306)/mengyastore?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
}
|
||||
```
|
||||
|
||||
也可以用环境变量覆盖(优先级更高):
|
||||
|
||||
```bash
|
||||
export DATABASE_DSN="mengyastore:your_password@tcp(127.0.0.1:3306)/mengyastore?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
```
|
||||
|
||||
### 3. 启动后端
|
||||
|
||||
```bash
|
||||
cd mengyastore-backend
|
||||
go run . # http://localhost:8080
|
||||
# 首次启动会自动创建全部表结构
|
||||
```
|
||||
|
||||
### 4. 启动前端
|
||||
### 3. 前端
|
||||
|
||||
```bash
|
||||
cd mengyastore-frontend
|
||||
npm install
|
||||
npm run dev # http://localhost:5173
|
||||
npm run dev # 默认 :5173
|
||||
```
|
||||
|
||||
### 5. 访问管理后台
|
||||
`.env.development` 中设置 `VITE_API_BASE_URL` 指向后端。
|
||||
|
||||
在网站 Logo 上快速点击 **5 次**,输入 `config.json` 中的 `adminToken` 进入管理后台。
|
||||
### 4. 管理后台
|
||||
|
||||
> **安全说明**:后端采用 `POST /api/admin/verify` 接口验证令牌,只返回 `{"valid": true/false}`,不会将令牌明文传输到前端。
|
||||
在站点 **Logo 上连续点击 5 次**,输入 `ADMIN_TOKEN`;或使用带 `?token=` 的 `/admin` 链接。
|
||||
|
||||
---
|
||||
|
||||
## 生产部署(Docker)
|
||||
|
||||
```bash
|
||||
cd mengyastore-backend
|
||||
|
||||
# 1. 创建 config.json(同上)
|
||||
# 2. 修改 docker-compose.yml 中的 DATABASE_DSN 指向生产数据库
|
||||
# 3. 启动
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
`docker-compose.yml` 配置说明:
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|--------|------|
|
||||
| `DATABASE_DSN` | 生产 MySQL 连接串(覆盖 config.json) |
|
||||
| `./config.json:/app/config.json:ro` | 只读挂载配置文件 |
|
||||
|
||||
---
|
||||
|
||||
## 本地开发
|
||||
|
||||
```bash
|
||||
# 前端热重载
|
||||
cd mengyastore-frontend
|
||||
npm install
|
||||
npm run dev # http://localhost:5173
|
||||
|
||||
# 后端热重载(需安装 air)
|
||||
cd mengyastore-backend
|
||||
go run .
|
||||
```
|
||||
|
||||
**构建前端**
|
||||
|
||||
```bash
|
||||
cd mengyastore-frontend
|
||||
npm run build # 输出到 dist/
|
||||
```
|
||||
|
||||
**构建后端二进制**
|
||||
|
||||
```bash
|
||||
cd mengyastore-backend
|
||||
go build -o mengyastore-backend .
|
||||
./mengyastore-backend
|
||||
```
|
||||
见 `mengyastore-backend-go/docker-compose.yml`:通过环境变量注入 `DATABASE_DSN`、`ADMIN_TOKEN`、`REDIS_*`、`RABBITMQ_*` 等,不要将真实密钥提交到 Git。
|
||||
|
||||
---
|
||||
|
||||
@@ -240,24 +150,21 @@ go build -o mengyastore-backend .
|
||||
|
||||
```
|
||||
mengyastore/
|
||||
mengyastore-frontend/ # Vue 3 + Vite 前端
|
||||
mengyastore-backend/ # Go + Gin 后端
|
||||
API_DOCS.md # API 接口文档
|
||||
README.md # 本文件
|
||||
mengyastore-frontend/ # Vue 3 + Vite 前端
|
||||
mengyastore-backend-go/ # Go + Gin 后端
|
||||
README.md # 本文件
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 工程亮点
|
||||
|
||||
- **安全**:管理员令牌通过 `POST /api/admin/verify` 服务端验证,令牌不在网络中明文传输
|
||||
- **防刷**:购买数量限制同时统计 `pending` 和 `completed` 状态,防止并发绕过
|
||||
- **兼容**:管理员鉴权支持 `X-Admin-Token` 请求头(Spring Security 标准)/ `Authorization` / `?token` 三种方式
|
||||
- **PWA**:Service Worker 离线缓存 + 启动动画 + 自动更新提示
|
||||
- **可移植**:API 设计对齐 Spring Boot 风格,便于后端语言迁移
|
||||
- **两种发货**:卡密扣 `product_codes`;固定内容不扣库存,每笔订单复制 `fixed_content` 至 `delivered_codes`。
|
||||
- **管理员鉴权**:`X-Admin-Token`(推荐)/ `Authorization` / `?token=`;`POST /api/admin/verify` 仅返回 `valid`。
|
||||
- **MQ 韧性**:AMQP 504/断线后客户端会尝试重连并重启消费协程。
|
||||
- **公开接口**:列表/详情不返回卡密与 `fixedContent`。
|
||||
- **PWA**:离线缓存、启动屏、新版本 Toast。
|
||||
|
||||
---
|
||||
|
||||
© 2025 – 2026 萌芽小店 · Powered by Vue 3 + Go + MySQL
|
||||
© 2025 – 2026 萌芽小店 · Vue 3 + Go + MySQL
|
||||
|
||||
Reference in New Issue
Block a user