|
|
||
|---|---|---|
| clip_server | ||
| cmd | ||
| internal | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| apifox-import.json | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| main.go | ||
| README.md | ||
| schema.sql | ||
FloorVisualizer
AI 换地板可视化后端服务 — 上传房间照片,AI 自动识别地面区域并生成换地板效果图。
技术栈
- 语言: Go 1.23+
- 数据库: PostgreSQL 15(GORM + 原生 SQL)
- 缓存/队列: Redis 7
- AI: OpenRouter API (Gemini 3 Pro / Flash)
- 部署: Docker Compose
快速开始
首次部署
# 1. 初始化数据库(仅一次)
psql -U postgres < schema.sql
# 2. 导入产品数据
go run cmd/import/main.go # 3539 条产品
go run cmd/import_articles/main.go # 30 篇科普文章
# 3. 启动开发服务(本地 DB + Redis)
docker compose -f docker-compose.dev.yml up -d
go run main.go
服务运行在 http://localhost:8099。
生产部署
docker compose up -d --build
项目结构
├── main.go
├── schema.sql # 建表脚本(导入一次)
├── cmd/
│ ├── import/main.go # 产品数据导入
│ ├── import_articles/main.go # 科普文章导入
│ └── scrape_logos/main.py # 品牌 Logo 刮取
├── internal/
│ ├── api/
│ │ └── router.go # 路由注册 + 依赖注入 + 响应 helper
│ ├── handler/ # HTTP 处理器(函数导出)
│ │ ├── router.go # writeJSON/writeErr
│ │ ├── auth_handler.go # Register / Login
│ │ ├── user_handler.go # Me / UploadAvatar / Favorites / Projects / FrequentBrands
│ │ ├── product_handler.go # Products / ProductOptions / FilterOptions
│ │ ├── recommend_handler.go # Recommend
│ │ ├── calc_handler.go # Calc
│ │ ├── floor_handler.go # FloorGenerate / FloorStatus / FloorOptions
│ │ ├── article_handler.go # Articles / ArticleRecommend
│ │ ├── health_handler.go # Healthz
│ │ └── upload_handler.go # Upload
│ ├── model/ # 数据模型 + 返回结构体
│ │ ├── response.go # ApiResponse / ApiError
│ │ ├── calc.go # CalcInput / CalcResult / CalcDeduction
│ │ ├── product.go # Product / ProductSpec
│ │ ├── brand.go # BrandInfo
│ │ └── ...
│ ├── repository/ # 数据访问(GORM + 原生 SQL)
│ │ ├── gorm.go # GORM 初始化
│ │ ├── db.go # PostgreSQL 连接
│ │ ├── product_repo.go # 产品查询(简单 GORM,复杂 SQL)
│ │ ├── brand_view_repo.go # 品牌浏览统计
│ │ └── ...
│ ├── service/ # 业务逻辑(推荐算法)
│ ├── middleware/ # JWT 认证 + 访问日志
│ ├── queue/ # Redis 异步任务队列
│ │ ├── redis.go # 入队/出队/状态管理
│ │ └── worker.go # Worker 池(并发消费)
│ ├── openrouter/ # OpenRouter API 客户端
│ └── logger/ # 分级日志(日切 + 30 天清理)
├── data/products/ # 产品 JSON(3539 条,不入 git)
├── Dockerfile
├── docker-compose.yml
├── docker-compose.dev.yml
└── apifox-import.json # API 文档
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
PORT |
8099 |
HTTP 端口 |
DATABASE_URL |
postgres://postgres:dev123456@localhost:5432/floorvisualizer?sslmode=disable |
数据库连接 |
REDIS_ADDR |
localhost:6379 |
Redis 地址 |
JWT_SECRET |
内置默认值 | JWT 签名密钥(生产务必修改) |
OPENROUTER_API_KEY |
内置默认值 | OpenRouter API Key |
PROXY_URL |
127.0.0.1:7897 |
HTTP 代理(留空禁用) |
DISABLE_PROXY |
— | 设为 true 强制禁用代理 |
WORKER_COUNT |
5 |
AI 生成并发 worker 数(1-20) |
LOG_DIR |
logs |
日志目录 |
LOG_LEVEL |
INFO |
DEBUG / INFO / WARN / ERROR |
API 总览
所有接口统一返回 {"code": 200, "data": {...}} 信封格式。
认证
POST /auth/register— 注册POST /auth/login— 登录
产品(公开)
GET /products— 列表(多维度筛选+搜索+分页)GET /products/{sku}— 详情(含 specs 规格、收藏状态、热点缓存)GET /product-options— 筛选选项(含品牌 logo、款式数、合集数)
推荐(公开)
GET /recommend/api?sku=xxx— 跨品牌相似推荐(specs 感知)
地板更换(需 Redis)
GET /floor/options— 地板样式+铺设方式+房间类型POST /floor/generate— 提交 AI 生成任务 → 返回job_idGET /floor/status?job_id=xxx— 查询异步任务进度
用户(需 JWT)
GET /user/me/PUT /user/me— 个人信息POST /user/avatar— 上传头像GET /user/favorites/POST/DELETE— 收藏管理GET /user/projects/POST/PUT/DELETE— 项目(生成记录)GET /user/frequent-brands— 常用品牌(自动统计,浏览≥3 或 收藏≥2)
计算器
POST /calculator/calc— 多房间面积+损耗+费用计算
文章(公开)
GET /articles— 科普文章列表GET /articles/{id}— 文章详情GET /articles/recommend— 随机推荐
其他
POST /upload— 通用图片上传(20MB)GET /healthz— 健康检查
数字编码
铺设方式 (pattern_code)
| Code | 木地板 | 瓷砖 |
|---|---|---|
| 1 | Straight Lay | — |
| 2 | Horizontal Lay | — |
| 3 | Herringbone | — |
| 4 | Chevron | — |
| 5 | — | Straight Grid |
| 6 | — | Running Bond |
| 7 | — | 1/3 Offset |
| 8 | — | Hexagonal |
| 9 | — | Diagonal (45°) |
房间类型 (room_code)
| Code | 房间 |
|---|---|
| 0 | Auto Detect |
| 1 | Living Room |
| 2 | Bedroom |
| 3 | Kitchen |
| 4 | Dining Room |
| 5 | Bathroom |
| 6 | Study Room |
| 7 | Hallway |
产品数据
10 个品牌,3539 条产品,覆盖 Hardwood / Engineered Wood / Laminate / SPC/LVP / Wood-Look Tile 五大品类。
数据存储在 data/products/*.json(不入 git),首次使用需运行 go run cmd/import/main.go 导入 PostgreSQL。
数据库
表结构统一管理在 schema.sql,服务启动时不再自动建表。修改表结构后更新此文件即可。
查询层使用 GORM + 原生 SQL 混合:
- 简单 CRUD(
GetProductBySKU)→ GORM - 复杂查询(动态筛选
DISTINCT ON、批量统计)→ 原生 SQL
日志
- 格式:
2026-07-10 16:30:01.234 [INFO] main.go:96 Server started - 存储:
logs/app-YYYY-MM-DD.log,每天自动切文件 - 清理: 自动删除 30 天前的日志
- 输出: 同时写 stdout + 文件
缓存
- 热点产品缓存: Redis sorted set 统计浏览量,Top 200 自动缓存,TTL 1h ± 10min 随机抖动防雪崩
- 品牌浏览统计: 自动记录(查询产品详情时触发)
异步队列
AI 图片生成使用 Redis List 做消息队列,Worker 池消费:
- 提交任务 → RPUSH 入队 → 立即返回
job_id - Worker 从 BRPOP 出队 → 调用 OpenRouter → 写入结果
- 并发数通过
WORKER_COUNT控制,默认 5 - 进度查询:
GET /floor/status?job_id=xxx