first commit

This commit is contained in:
2026-07-27 14:54:21 +08:00
commit 4d086758e8
161 changed files with 63776 additions and 0 deletions
+364
View File
@@ -0,0 +1,364 @@
# 智绘微刻后端技术栈建议方案
> 本文档面向「智绘微刻」小程序团队,提供从 0 到 1 搭建后端服务的完整技术选型建议。
> 撰写日期:2026-07-27
> 适用场景:初期 MVP 上线(日活 < 1万),兼顾未来扩展。
---
## 一、总体架构概览
```
┌─────────────────────────────────────────────────────────────┐
│ 微信小程序端 │
│ Taro 3.6 + React + Local Storage(当前无后端缓存阶段) │
└──────────────────────────┬──────────────────────────────────┘
│ HTTPS / JSON
┌──────────────────────────▼──────────────────────────────────┐
│ Nginx(反向代理 + 静态文件) │
│ ┌─────────────┬─────────────┐ │
│ │ SSL 证书 │ 负载均衡 │ │
│ └─────────────┴─────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────┐
│ FastAPI (Python 3.11+) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 用户/订单 │ │ 词云生成 │ │ 设计清单 │ │
│ │ REST API │ │ 异步任务 │ │ REST API │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ PostgreSQL │ │ Redis │ │ MinIO │
│ (主数据库) │ │ 缓存/队列 │ │ 对象存储 │
└─────────────┘ └─────────────┘ └─────────────┘
┌──────▼──────┐
│ Celery │
│ 异步任务队列 │
│ (词云渲染) │
└─────────────┘
```
---
## 二、技术选型与理由
### 1. API 框架:FastAPI (Python)
| 维度 | 选型 | 理由 |
|------|------|------|
| 框架 | **FastAPI** | 自动生成 OpenAPI/Swagger 文档;异步原生支持(`async/await`);类型提示驱动开发,与前端 TS 思维一致 |
| 替代方案 | Django / Flask / Go-Gin | Django 太重、Flask 需手写异步、Go 学习成本高;团队若熟悉 Python,FastAPI 是最佳平衡点 |
| Python 版本 | **3.11+** | 性能优化显著(CPython 3.11 比 3.10 快 10~25%),且支持 `TaskGroup` 等现代并发原语 |
**核心职责**
- 用户登录(微信 OAuth2 → JWT Token
- 商品/品类/价格/工期配置读取
- 设计清单 CRUD
- 订单创建/支付回调/状态流转
- 词云生成任务投递(异步)
- 文件上传预签名 URL(MinIO)
---
### 2. 数据库:PostgreSQL 15+
| 维度 | 选型 | 理由 |
|------|------|------|
| 主数据库 | **PostgreSQL 15+** | 开源、稳定、JSONB 支持灵活存储设计稿元数据;PostGIS 扩展未来可做配送区域 |
| ORM | **SQLAlchemy 2.0** + Alembic | 成熟、类型安全、迁移脚本自动化 |
| 连接池 | asyncpg | FastAPI 原生异步兼容 |
**核心表结构设计(MVP 版)**
```sql
-- 用户表(微信授权)
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
openid TEXT UNIQUE NOT NULL,
unionid TEXT,
nickname TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 商品品类表(与前端 productConfig 同步)
CREATE TABLE products (
id TEXT PRIMARY KEY, -- notebook-small, coaster, penbox ...
name TEXT NOT NULL,
desc TEXT,
price INT NOT NULL, -- 单位:分,避免浮点
lead_time TEXT,
description TEXT,
images TEXT[], -- 图片 URL 数组
mask JSONB NOT NULL, -- {shape, width, height, borderRadius}
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 设计清单表
CREATE TABLE designs (
id TEXT PRIMARY KEY, -- DSG + 时间戳
user_id UUID REFERENCES users(id),
product_id TEXT REFERENCES products(id),
count INT NOT NULL DEFAULT 1,
status TEXT NOT NULL CHECK (status IN ('undesigned','designing','ordered')),
design_data JSONB, -- {imageSrc, imagePos, category}
order_id TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 订单表
CREATE TABLE orders (
id TEXT PRIMARY KEY, -- ORD + 时间戳
user_id UUID REFERENCES users(id),
design_id TEXT REFERENCES designs(id),
product_id TEXT REFERENCES products(id),
product_name TEXT NOT NULL,
count INT NOT NULL,
unit_price INT NOT NULL, -- 单位:分
total_price INT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('pending','paid','shipping','done','cancelled')),
sku TEXT,
paid_at TIMESTAMPTZ,
shipped_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 词云生成任务表(追踪异步任务状态)
CREATE TABLE wordcloud_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
base_image_key TEXT NOT NULL, -- MinIO 对象 key
names TEXT[] NOT NULL,
status TEXT NOT NULL CHECK (status IN ('queued','processing','completed','failed')),
result_key TEXT,
error_msg TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ
);
```
---
### 3. 缓存与消息队列:Redis 7+
| 用途 | 说明 |
|------|------|
| **JWT 黑名单 / Session 缓存** | 用户登出时令牌失效 |
| **_rate limiting_** | 防止词云接口被刷(每用户 5 次/分钟) |
| **Celery Broker** | Redis List 作为 Celery 任务队列 |
| **热点数据缓存** | 商品配置表、首页轮播数据(TTL 10 分钟) |
---
### 4. 异步任务:Celery + Redis
| 场景 | 处理方式 |
|------|----------|
| **词云图片生成** | 用户上传底图 → 投递 Celery Task → C++ 布局引擎 / Python 词云库生成 → 结果上传 MinIO → WebSocket/轮询通知前端 |
| **订单支付回调处理** | 微信 notify_url → FastAPI 接收 → Celery Task 异步更新订单状态、发送通知 |
| **批量邮件/短信** | 发货通知、营销短信异步发送 |
**为什么不用 RabbitMQ**
Redis 作为 Broker 在初期足够(架构简单、少维护一个组件)。当每日任务量 > 10万 时,再迁移到 RabbitMQ 或 AWS SQS。
---
### 5. 对象存储:MinIO
| 用途 | 说明 |
|------|------|
| **用户上传底图** | 微信小程序 → 直传 MinIO(预签名 URL)→ 返回 key 给后端 |
| **词云生成结果图** | Celery Worker 生成后上传 → 前端通过 CDN 域名访问 |
| **商品实物照片** | 运营后台上传 → 前端展示 |
**为什么不存数据库?**
图片二进制存数据库会导致表体积膨胀、备份慢、查询性能下降。MinIO(S3 兼容)是对象存储的最优解。
**云服务器部署建议**
- 若使用阿里云:可无缝切换到 **阿里云 OSS**(代码只需改 endpoint + access key)。
- 若自建服务器:MinIO 单机版 Docker 运行,占用 < 200MB 内存。
---
### 6. 部署与运维:Docker Compose(初期)
```yaml
# docker-compose.yml 示例(MVP 单服务器)
version: "3.8"
services:
api:
build: ./backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/smart_engraving
- REDIS_URL=redis://redis:6379/0
- MINIO_ENDPOINT=minio:9000
depends_on:
- db
- redis
- minio
celery_worker:
build: ./backend
command: celery -A tasks worker --loglevel=info --concurrency=2
environment:
- DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/smart_engraving
- REDIS_URL=redis://redis:6379/0
depends_on:
- db
- redis
- minio
db:
image: postgres:15-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: smart_engraving
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
redis:
image: redis:7-alpine
volumes:
- redisdata:/data
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
volumes:
- miniodata:/data
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
volumes:
pgdata:
redisdata:
miniodata:
```
---
## 三、API 设计速查(供前端联调用)
### 认证
```http
POST /api/v1/auth/wechat
Body: { code: "wx_auth_code" }
Response: { access_token: "jwt", refresh_token: "jwt", user: {...} }
```
### 商品
```http
GET /api/v1/products
Response: [ { id, name, desc, price, leadTime, images[], mask } ]
```
### 设计清单
```http
GET /api/v1/designs #
POST /api/v1/designs #
PATCH /api/v1/designs/{id} # 稿
DELETE /api/v1/designs/{id} #
POST /api/v1/designs/{id}/order # design order
```
### 词云
```http
POST /api/v1/wordcloud/jobs
Body: { baseImageKey, names: [] }
Response: { jobId, status: "queued" }
GET /api/v1/wordcloud/jobs/{jobId}
Response: { status, resultUrl, progress }
```
### 订单
```http
GET /api/v1/orders
POST /api/v1/orders #
POST /api/v1/orders/{id}/pay # prepay_id
POST /api/v1/orders/wechat_notify #
```
### 上传
```http
GET /api/v1/upload/presign?filename=xxx.jpg&contentType=image/jpeg
Response: { url, key, expires }
# 使 `url` MinIO / OSS
```
---
## 四、费用预估(阿里云 / 腾讯云,MVP 阶段)
| 资源 | 配置 | 月费用(人民币) |
|------|------|-----------------|
| 云服务器 ECS | 2核4G,共享型 | ~¥60-100 |
| 云数据库 RDS PostgreSQL | 1核1G,基础版 | ~¥35-60 |
| 云数据库 Redis | 256MB 主从 | ~¥20-40 |
| 对象存储 OSS | 50GB 标准存储 | ~¥5-10 |
| CDN 流量 | 100GB/月 | ~¥15-25 |
| 域名 + SSL 证书 | 通配符一年 | ~¥200-400/年 |
| **合计** | | **~¥150-260/月** |
> 若用户量极小(< 1000 日活),可将 PostgreSQL 和 Redis 都部署在同一台 ECS 上,初期费用可压到 **¥60-80/月**。
---
## 五、开发排期建议(后端 MVP,2 人团队)
| 阶段 | 周期 | 内容 |
|------|------|------|
| **Week 1** | 环境搭建 | Docker Compose 本地跑通;FastAPI 项目脚手架;PostgreSQL + Redis 联调 |
| **Week 2** | 核心 API | 微信登录 JWT / 商品列表 / 设计清单 CRUD / 订单创建 |
| **Week 3** | 词云 & 支付 | 词云异步任务接入(Celery);微信支付预支付+回调;MinIO 预签名上传 |
| **Week 4** | 联调 & 部署 | 小程序前端联调;阿里云 ECS 生产部署;监控告警(日志 + 告警) |
---
## 六、风险与预案
| 风险 | 影响 | 预案 |
|------|------|------|
| 微信登录 code 换取 session_key 失败 | 用户无法登录 | 后端增加 Mock 登录接口(开发环境)|
| 词云生成耗时长(>30s) | 用户体验差 | 前端轮询 + 后端加进度反馈;高并发时排队提示 |
| 支付回调网络抖动 | 订单状态不一致 | 支付回调幂等设计(按微信 `out_trade_no` 去重)|
| 图片存储流量激增 | CDN 费用上升 | 启用 OSS 图片压缩 + WebP 转换 |
---
## 七、推荐的开箱即用工具链
| 工具 | 用途 |
|------|------|
| **uv** | Python 包管理与虚拟环境(比 pip + venv 快 10 倍)|
| **Pydantic v2** | 数据校验与序列化(FastAPI 内置)|
| **sqlalchemy[asyncio]** | 异步 ORM |
| **celery[redis]** | 异步任务队列 |
| **boto3** | MinIO / OSS S3 兼容客户端 |
| **loguru** | 结构化日志 |
| **sentry-sdk** | 线上异常追踪(免费额度够用)|
---
## 八、总结
> **推荐技术栈:FastAPI + PostgreSQL + Redis + MinIO + CeleryDocker Compose 单服务器部署。**
- **FastAPI**:异步高性能、自动生成文档、团队上手快。
- **PostgreSQL**JSONB 灵活存储设计稿元数据,未来扩展无需换库。
- **Redis**:一物三用(缓存 + 队列 + 限流)。
- **MinIO**:自托管 S3 兼容对象存储,未来可一键切阿里云 OSS。
- **Celery**:词云生成、支付回调、通知推送全部异步化,前端响应 < 100ms。
该方案在 **日活 1 万以内** 完全不需要 Kubernetes 或微服务拆分,单台 2 核 4G 服务器即可承载。
+121
View File
@@ -0,0 +1,121 @@
# 智绘微刻小程序 - 遮罩尺寸配置指南
## 📌 概述
本小程序的 DIY 工作台使用**遮罩层(Mask)**来模拟实际产品的雕刻区域。用户在画布上看到的半透明黑色区域之外的部分,即为该产品的实际外形轮廓;白色/透明区域则是激光雕刻的可用范围。
当你们确定了各品类的真实尺寸后,**只需修改一个配置文件**,所有页面的渲染就会自动更新。
---
## 🎯 修改位置
**文件路径:**
```
src/utils/productConfig.ts
```
此文件导出一个 `PRODUCTS` 数组,每个品类对象中都有一个 `mask` 属性,就是遮罩的配置。
---
## 📐 尺寸单位说明
| 项目 | 说明 |
|---|---|
| 单位 | `px`(像素) |
| 基准 | 基于 **750px 宽度** 的设计稿 |
| 换算建议 | 实际尺寸(mm)÷ 实物最大宽度(mm)× 画布宽度(px) |
### 举例
假设铜质杯垫实际直径为 **90mm**,画布区域在手机上显示为 **300px 宽**
```
先量出杯垫实际直径对应的像素比例:
90mm ÷ 90mm × 280 = 280px
(如果直接按1:1在画布上展示,就填280)
```
**更简单的方式**:等真实的样品拿到后,直接用手机截图量一下在 375px 逻辑像素下应该占多大,然后把数值填进去即可。
---
## 🔧 遮罩类型
### 1. 矩形遮罩(rect
适用于:笔记本、笔盒、书本灯等方形/圆角矩形产品
```typescript
mask: {
type: 'rect',
width: 300, // 遮罩宽度(px
height: 420, // 遮罩高度(px
radius: 8 // 圆角半径(px),不需要圆角填 0
}
```
### 2. 圆形遮罩(circle
适用于:杯垫、徽章等圆形产品
```typescript
mask: {
type: 'circle',
width: 280, // 椭圆外接矩形宽度(px
height: 280 // 椭圆外接矩形高度(px
}
```
> 如果 `width === height`,即为正圆;如果不相等,则为椭圆。
---
## 📋 当前品类与待填尺寸
| 品类ID | 品类名称 | 当前尺寸 | 状态 |
|---|---|---|---|
| `notebook-small` | 微雕笔记本(小) | 300 × 420 px | 占位待改 |
| `notebook-large` | 微雕笔记本(大) | 340 × 480 px | 占位待改 |
| `coaster` | 铜质杯垫 | 280 px 直径 | 占位待改 |
| `penbox` | 竹制笔盒 | 320 × 160 px | 占位待改 |
| `booklamp` | 书本型灯 | 320 × 240 px | 占位待改 |
---
## 💡 修改步骤
1. 测量实际样品的雕刻区域尺寸(建议用卡尺精确到 mm)
2. 在手机上打开小程序 DIY 页面,截图量出画布的实际显示像素
3. 按比例换算:`(实际尺寸 mm / 画布对应的实际物理宽度 mm) × 画布像素宽度`
4. 打开 `src/utils/productConfig.ts`
5. 修改对应产品 `mask` 对象的 `width``height``radius` 数值
6. 保存文件,重新编译小程序即可看到效果
---
## 🎨 效果说明
遮罩在 UI 上的表现:
- 遮罩区域:**透明/白色**,可看到用户上传的图片,表示这是雕刻范围
- 遮罩外部:**半透明黑色蒙层**,提示用户图片在这个范围之外的部分不会被雕刻到产品上
- 遮罩边框:**白色虚线框**,清晰标识边界
用户上传图片后,可以通过**拖拽**调整图片在遮罩内的位置,通过**缩放按钮**调整图片大小,确保想要雕刻的内容落在白色遮罩区域内。
---
## ⚠️ 注意事项
1. **修改后需重新编译**:Taro 会热更新,但在微信开发者工具中建议点击「编译」确保生效
2. **尺寸不宜过大**:遮罩面积建议不超过画布面积的 80%,否则用户难以感受到「边缘」
3. **留足边距**:设计时建议遮罩四周至少留出 20px 的安全边距,避免用户把图片贴得太边
4. **圆形产品**:如果杯垫等产品有固定内圈雕刻区域(而非整个圆面),可以将 `width/height` 设小一点,模拟内圈
---
## 🔗 相关文件
| 文件 | 作用 |
|---|---|
| `src/utils/productConfig.ts` | 品类与遮罩配置(修改这里) |
| `src/types/index.ts` | 类型定义(一般不需要改) |
| `src/pages/diy/index.tsx` | DIY 工作台页面(读取配置自动渲染) |
| `src/pages/diy/index.scss` | 遮罩样式(一般不需要改) |