Files
admin 06488f0237 Initial commit: 帮我选盲选应用
功能:
- Go后端 (Gin + GORM + PostgreSQL)
- UniApp用户端 (iOS/Android/小程序)
- DaisyUI5后台管理
- JWT认证 + 微信登录
- 盲选加权算法
- 会员系统 + 优惠券
- 打分评价 + 偏好学习
2026-06-08 20:18:31 +00:00

928 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# "帮我选"盲选应用 - 开发大纲 v3
## 一、项目概述
AI驱动开发的盲选应用,用户盲选吃喝玩乐套餐,支持会员盈利,
通过用户历史行为智能更新偏好权重,**去了打分**驱动推荐质量。
---
## 二、技术栈
### AI 开发配置
```yaml
api:
key: "sk-26391ddf421f3d09546969d968e73295a3ec493ae327a6792a840c6f5fcdd517"
endpoint: "https://qs.szscp.com"
# 用途:AI推荐、智能分类、用户偏好分析、月度报告
```
### 后端:Go + Gin + GORM + PostgreSQL + Redis
### App前端:UniApp + Vue3(一套代码→iOS/Android/小程序)
### 后台管理:DaisyUI5 + Tailwind + Alpine.js
---
## 三、会员盈利体系(简化:仅VIP)
### 会员方案
```
免费用户:
├── 每天3次盲选机会
├── 基础分类可用
└── 普通优先级
VIP会员(¥29/月 或 ¥199/年):
├── 每天10次盲选
├── 全部分类解锁
├── 优先匹配优质套餐
├── 专属盲选风格
├── 去重天数更长(3天→1天)
└── 月度盲选报告
```
### 盈利模型
```
1. 会员订阅(主要收入)
2. 商家佣金(5-15%
3. 优惠券佣金(联动商家优惠券,每次核销商家付佣金)
4. 品牌盲盒溢价
```
### 商家优惠券联动
```
商家在后台创建优惠券:
├── 券类型:满减券 / 折扣券 / 免费兑换券 / 赠品券
├── 面额:后台设置(如满100减20)
├── 数量:发放总量 + 剩余量
├── 有效期:起止时间
├── 适用套餐:指定某些套餐可用
└── 佣金比例:用户通过盲选核销该券,平台抽佣 10-20%
用户侧表现:
├── 盲选结果卡上显示"附带优惠券"
├── 优惠券卡片样式(像微信卡包)
├── 核销后记录,商家确认使用
└── 优惠券是商家的"引流工具",平台收佣金
```
**优惠券联动逻辑:**
```
商家A想引流 → 后台创建100张"满80减15"券 → 设核销后佣金8元
→ 用户盲选抽到商家A的套餐 → 自动获得该券
→ 用户到店出示核销 → 商家确认 → 平台收8元佣金
→ 用户得到优惠,商家获得客流,平台赚佣金 → 三方共赢
```
---
## 四、用户偏好学习系统(含打分机制)
### 4.1 打分机制(核心)
用户每次盲选揭晓后,可选"去了"或"跳过了"
```
用户选择"去了"后 → 进入打分页:
┌─────────────────────────────┐
│ 你对这次盲选体验打几分? │
│ │
│ ⭐⭐⭐⭐⭐ (1-5星) │
│ │
│ 评分维度(可选填): │
│ 🍽️ 口味: ████░ (1-5) │
│ 💰 性价比: ███░░ (1-5) │
│ 📍 距离: ████░ (1-5) │
│ 🎯 符合预期: ████░ (1-5) │
│ │
│ 备注(可选): │
│ ┌─────────────────────────┐ │
│ │ 写点什么... │ │
│ └─────────────────────────┘ │
│ │
│ [提交] │
└─────────────────────────────┘
```
**打分影响权重:**
```
五星好评(5分):
→ 该分类偏好 +2.0 ★★
→ 该商家偏好 +3.0 ★★★
→ 该标签(如"日料")偏好 +1.5
四星好评(4分):
→ 该分类偏好 +1.0
→ 该商家偏好 +1.5
→ 该标签偏好 +0.8
三星中立(3分):
→ 该分类偏好 +0.3(轻微正向)
→ 无商家偏好加成
二星(2分):
→ 该分类偏好 -0.3
→ 该商家偏好 -0.5
一星差评(1分):
→ 该分类偏好 -1.0
→ 该商家偏好 -2.0 ★★
→ 该商家加入"黑名单"候选(需用户确认)
```
### 4.2 行为追踪
```go
type UserBehavior struct {
ID uint
UserID uint
PackageID uint
BehaviorType string // "viewed" "selected" "attended" "reviewed" "skipped"
Score float64 // 行为权重(非打分,是系统权重)
ReviewRating int8 // 用户打分 1-5
ReviewTags string // "口味好""太贵""环境差"等标签
ReviewText string // 用户文字评价
DistanceScore int8 // 距离评分
ValueScore int8 // 性价比评分
ExpectMatch int8 // 符合预期评分
IsRepeat bool // 是否再次前往
CreatedAt time.Time
}
```
### 4.3 权重算法
```
用户偏好分数 = Σ(行为得分 × 时间衰减系数 × 打分系数)
打分系数:
5星 → ×1.5(放大正向影响)
4星 → ×1.0(标准正向影响)
3星 → ×0.5(轻微影响)
2星 → ×-0.5(轻微负向)
1星 → ×-1.5(放大负向影响)
时间衰减:
最近30天 × 1.0
30-90天 × 0.7
90-180天 × 0.4
180天+ × 0.2
示例计算:
用户A在45天前去了日料店,打了5星 → 权重 = +2.0 × 0.7 × 1.5 = +2.1
用户A在200天前去了日料店,打了2星 → 权重 = -0.5 × 0.2 × -0.5 = +0.05(几乎忽略)
```
### 4.4 偏好标签自动打标
```
基于用户打分数据自动打标:
用户A(日料5星×5次,西餐3星×3次,火锅5星×2次)
→ 标签: ["日料狂魔", "火锅爱好者", "中餐不挑"]
→ 盲选策略: 80%日料/火锅,20%其他探索
用户B(所有都3-4星,没有明显偏好)
→ 标签: ["探索型", "随机接受度高"]
→ 盲选策略: 增加品类多样性,避免重复
用户C(多次1-2星差评)
→ 标签: ["易踩雷", "高要求", "需要精准匹配"]
→ 盲选策略: 提高推荐门槛,降低盲选随机性,接近定向选择
```
### 4.5 商家维度打分积累
```
每个套餐也积累评分:
套餐评分 = Σ(所有用户打分) / 打分人数
影响:
- 套餐评分低的 → 降低盲选权重(少抽到)
- 套餐评分高的 → 提高盲选权重(多抽到)
- 但保留一定随机性(给用户探索惊喜)
```
---
## 五、功能模块
### 5.1 用户端(UniApp
#### 首页
```
├── 顶部:欢迎语(AI生成,基于今日偏好)
│ 例:"今天想带你吃点治愈系的~"
│ 例:"好久没吃辣了,来场火锅盲选?"
│ 例:"根据你的口味,今天推荐隐藏日料店!"
├── 盲选卡片池(可滑动切换类别)
│ ├── 🍜 餐饮盲选
│ ├── 🎮 娱乐盲选
│ ├── 🛍️ 购物盲选
│ └── 🎭 活动盲选
├── 今日推荐(AI分析后推荐类别,VIP专享)
└── 盲选按钮(大,带动画)→ 抽!
```
#### 盲选揭晓页
```
├── 动画效果(翻牌/转盘)
├── 揭晓内容:
│ ├── 商家名称 + 评分 + 距离
│ ├── 套餐描述(模糊描述,价格区间可见)
│ ├── 推荐理由(AI生成,基于匹配度)
│ │ 例:"你的日料偏好度85%,这家匹配度很高!"
│ ├── 优惠券 🎁(如有)
│ │ 例:"满80减15 · 限时3天"
│ └── 匹配度进度条
├── 操作:
│ ├── ✅ 接受/前往(记录行为 +0.5)
│ ├── 🔄 换一个(-0.2分,不消耗机会)
│ ├── ⭐ 标记"已去过"(进入打分流程)
│ ├── 🔖 收藏
│ └── 📍 导航
└── 已去过?→ 跳转打分页
```
#### 打分页
```
┌─────────────────────────┐
│ 🎉 感谢你的盲选体验! │
│ │
│ 你对这次体验打几分? │
│ ⭐⭐⭐⭐⭐ (当前: 4) │
│ │
│ 评分维度: │
│ 🍽️ 口味: ⭐⭐⭐⭐⭐ │
│ 💰 性价比: ⭐⭐⭐⭐░ │
│ 📍 距离: ⭐⭐⭐░░ │
│ 🎯 符合预期:⭐⭐⭐⭐⭐ │
│ │
│ 你想怎么形容这次体验? │
│ [口味赞] [环境好] [性价比] [值得再来] [服务棒] [踩雷] [太贵] [难吃] [远]
│ │
│ 备注(可选): │
│ ┌─────────────────────┐ │
│ │ 写点什么... │ │
│ └─────────────────────┘ │
│ │
│ [提交] │
└─────────────────────────┘
提交后:
├── 更新用户偏好权重
├── 更新商家/套餐评分
├── 更新用户标签
└── 显示:"已记录!这会影响下次推荐哦~"
```
#### 我的偏好
```
├── 偏好雷达图(口味/价格/距离/品质/探索度)
├── 品类偏好排名(柱状图)
│ 日料 ████████░░ 80%
│ 火锅 ██████░░░░ 60%
│ 西餐 ████░░░░░░ 40%
│ 甜品 ███░░░░░░░ 30%
├── AI标签列表
├── 去重设置
├── 黑名单商家
└── 偏好调整滑块
```
#### 优惠券中心
```
├── 我的优惠券
│ ├── 未使用(到期倒计时)
│ ├── 已使用
│ └── 已过期
├── 卡包样式(像微信卡包)
└── 使用说明
```
#### 会员中心
```
├── 当前状态
├── 会员权益对比表
├── 开通/续费按钮
├── 购买记录
└── 邀请好友(双方各得7天VIP)
```
#### 个人
```
├── 个人信息
├── 盲选记录(按时间线)
├── 收藏
├── 评价历史
├── 地址管理
└── 设置
```
### 5.2 后台管理(DaisyUI5
#### 仪表盘
```
├── 今日:新增用户 / 活跃 / 盲选次数 / 订单数
├── 会员:总数 / 转化率 / 月收入 / 续费率
├── 热门:分类TOP / 套餐TOP / 商家TOP
├── 评分:平均打分 / 差评预警
├── 优惠券:发放量 / 核销率 / 佣金收入
└── 趋势图(近30天)
```
#### 商家管理
```
├── 商家列表 + 搜索
├── 入驻审核
├── 编辑/上下架
├── 佣金设置
└── 商家数据(被选次数 / 平均评分 / 优惠券核销)
```
#### 套餐管理
```
├── 套餐CRUD
├── 价格区间设置
├── 标签管理
├── 库存管理
├── 评分查看
└── 权重调整
```
#### 优惠券管理
```
├── 创建优惠券
│ ├── 选择商家
│ ├── 券类型(满减/折扣/兑换/赠品)
│ ├── 面额设置
│ ├── 数量
│ ├── 有效期
│ ├── 适用套餐
│ └── 佣金比例(平台抽佣)
├── 优惠券列表(使用状态/核销情况)
├── 佣金收入统计
└── 核销审核(防作弊)
```
#### 用户管理
```
├── 用户列表 + 搜索
├── 用户详情(行为 + 偏好 + 打分 + 会员)
├── 会员管理
├── 黑名单管理
└── 行为分析
```
#### 打分分析
```
├── 平均打分趋势
├── 各分类平均评分
├── 差评预警(连续低分套餐)
├── 商家质量排名
└── 用户反馈词云
```
#### 算法配置
```
├── 行为权重调整
├── 时间衰减曲线
├── 打分系数
├── 去重天数默认值
├── 会员加成比例
├── 热门权重
└── A/B测试
```
#### 内容管理
```
├── Banner
├── 公告
├── 欢迎语模板
├── 推荐语模板
└── 标签管理
```
#### 数据报表
```
├── 用户增长曲线
├── 收入报表(会员+佣金+优惠券)
├── 转化率漏斗(注册→首盲选→付费会员)
├── 留存分析(7日/30日)
├── 商家质量报告
└── 导出CSV/Excel
```
---
## 六、数据库设计
```sql
-- 用户表
users (
id, nickname, avatar, phone, wechat_openid,
preference JSONB, -- {"日料": 0.85, "火锅": 0.6, ...}
tags TEXT[], -- ["日料狂魔", "品质型"]
member_level INT DEFAULT 0, -- 0免费 1VIP
member_expires_at,
created_at, updated_at
)
-- 商家表
merchants (
id, name, avatar, category_id,
rating, -- 平均评分
price_range, -- "50-100"
location GEOGRAPHY(Point), -- 经纬度
tags TEXT[],
total_reviews INT DEFAULT 0,
total_score NUMERIC DEFAULT 0,
quality_score NUMERIC, -- 综合质量分(用于盲选权重)
status,
created_at, updated_at
)
-- 分类表
categories (
id, name, icon, type, -- food/entertainment/shopping/activity
sort_order,
status,
created_at
)
-- 套餐表
packages (
id, merchant_id, category_id,
name, -- 套餐名
description, -- 模糊描述(盲选可见)
price_min, price_max, -- 价格区间
actual_price, -- 实际价格(盲选揭晓后显示)
tags TEXT[], -- "适合约会""亲子"
stock,
weight, -- 推荐权重
rating, -- 平均评分
review_count, -- 评分人数
status,
created_at, updated_at
)
-- 用户行为表(含打分)
user_behaviors (
id, user_id, package_id,
behavior_type, -- viewed/selected/attended/reviewed/skipped
system_score, -- 系统行为权重
review_rating, -- 用户打分 1-5
taste_score, -- 口味评分 1-5
value_score, -- 性价比评分 1-5
distance_score, -- 距离评分 1-5
match_score, -- 符合预期 1-5
tags TEXT[], -- 反馈标签 ["口味赞","太贵"]
text TEXT, -- 文字评价
is_repeat, -- 是否再次前往
created_at
)
-- 优惠券表
coupons (
id, merchant_id, package_id,
type, -- discount/coupon/free/gift
value, -- 面额或折扣
min_amount, -- 满减门槛
total_count, -- 总量
remain_count, -- 剩余
user_id, -- 领取用户(NULL=池发)
user_code, -- 用户专属码
pool_code, -- 池码(用户领取时复制)
status, -- available/claimed/used/expired
used_at,
valid_start, valid_end,
commission, -- 平台佣金
created_at, updated_at
)
-- 盲选会话表
blind_sessions (
id, user_id, category_id,
price_range, distance_range,
result_package_id,
result_revealed_at,
user_accepted,
created_at
)
-- 订单表
orders (
id, user_id, package_id, blind_session_id,
actual_price,
coupon_id, -- 使用的优惠券
status, -- pending/paid/completed/cancelled
created_at, updated_at
)
-- 会员表
members (
id, user_id, level,
start_date, end_date,
payment_method,
amount,
status,
created_at
)
-- 活动表
activities (
id, name, type, start_date, end_date,
config JSONB,
status
)
-- 管理员表
admins (
id, username, password_hash,
role, permissions,
created_at
)
```
---
## 七、API设计
### 7.1 认证
```
POST /api/v1/auth/register # 注册
POST /api/v1/auth/login # 手机登录
POST /api/v1/auth/wechat/login # 微信登录
POST /api/v1/auth/refresh # 刷新token
POST /api/v1/admin/login # 后台登录
```
### 7.2 用户
```
GET /api/v1/user/profile # 个人信息
PUT /api/v1/user/profile # 更新信息
GET /api/v1/user/preferences # 偏好数据
PUT /api/v1/user/preferences # 调整偏好
GET /api/v1/user/tags # AI标签
GET /api/v1/user/behaviors # 行为记录
```
### 7.3 盲选(核心)
```
GET /api/v1/blind/categories # 分类列表
GET /api/v1/blind/pool # 可选池(模糊信息)
POST /api/v1/blind/choose # 盲选
GET /api/v1/blind/result/:id # 揭晓结果
GET /api/v1/blind/recommend # AI推荐
POST /api/v1/blind/accept # 接受
POST /api/v1/blind/decline # 换一个
GET /api/v1/blind/history # 历史记录
```
### 7.4 打分(核心)
```
POST /api/v1/review/submit # 提交打分评价
GET /api/v1/review/stats # 打分统计
GET /api/v1/review/summary # 商家/套餐评分汇总
```
### 7.5 优惠券
```
GET /api/v1/coupon/list # 我的优惠券
GET /api/v1/coupon/available # 可领取优惠券
POST /api/v1/coupon/claim # 领取优惠券
POST /api/v1/coupon/verify # 核销优惠券
GET /api/v1/coupon/commission # 佣金记录
```
### 7.6 会员
```
GET /api/v1/member/status # 会员状态
GET /api/v1/member/plans # 会员套餐
POST /api/v1/member/subscribe # 开通
POST /api/v1/member/cancel # 取消
GET /api/v1/member/report # 月度报告(VIP)
```
### 7.7 后台管理
```
POST /api/v1/admin/dashboard # 仪表盘
CRUD /api/v1/admin/merchants # 商家管理
CRUD /api/v1/admin/packages # 套餐管理
GET /api/v1/admin/coupons # 优惠券管理
POST /api/v1/admin/coupons/create # 创建优惠券
GET /api/v1/admin/users # 用户列表
GET /api/v1/admin/users/:id # 用户详情
GET /api/v1/admin/reviews # 打分管理
GET /api/v1/admin/statistics # 数据报表
PUT /api/v1/admin/algorithm/config # 算法配置
GET /api/v1/admin/export # 数据导出
```
### 7.8 AI
```
POST /api/v1/ai/recommend # AI推荐
POST /api/v1/ai/analyze-preference # 分析偏好
POST /api/v1/ai/generate-tag # 生成标签
POST /api/v1/ai/generate-report # 生成月报
POST /api/v1/ai/generate-welcome # 生成欢迎语
```
---
## 八、项目结构
```
blind-select/
├── backend/ # Go后端
│ ├── cmd/server/main.go
│ ├── internal/
│ │ ├── config/
│ │ ├── middleware/ # JWT/日志/限流/会员校验
│ │ ├── handler/
│ │ │ ├── v1/
│ │ │ │ ├── auth.go
│ │ │ │ ├── blind.go
│ │ │ │ ├── user.go
│ │ │ │ ├── review.go # 打分
│ │ │ │ ├── coupon.go
│ │ │ │ ├── member.go
│ │ │ │ ├── ai.go
│ │ │ │ └── admin/
│ │ │ │ ├── dashboard.go
│ │ │ │ ├── merchant.go
│ │ │ │ ├── package.go
│ │ │ │ ├── coupon.go
│ │ │ │ ├── user.go
│ │ │ │ ├── review.go
│ │ │ │ ├── stats.go
│ │ │ │ ├── export.go
│ │ │ │ └── config.go
│ │ ├── service/
│ │ │ ├── blind_service.go # 盲选逻辑
│ │ │ ├── preference_service.go # 偏好学习
│ │ │ ├── review_service.go # 打分服务
│ │ │ ├── coupon_service.go # 优惠券
│ │ │ ├── member_service.go # 会员
│ │ │ ├── ai_service.go # AI调用
│ │ │ └── report_service.go # 报表
│ │ ├── model/ # GORM模型
│ │ ├── repository/ # 数据访问
│ │ └── utils/
│ ├── migrations/
│ ├── config.yaml
│ ├── go.mod
│ └── Makefile
├── frontend-admin/ # 后台 (DaisyUI5)
│ ├── index.html
│ ├── src/
│ │ ├── main.js
│ │ ├── App.vue
│ │ ├── views/
│ │ ├── components/
│ │ ├── api/
│ │ └── router/
│ ├── vite.config.js
│ └── package.json
├── frontend-app/ # UniApp多端
│ ├── pages/
│ │ ├── index/index.vue # 首页
│ │ ├── blind/blind.vue # 盲选页
│ │ ├── blind/result.vue # 揭晓
│ │ ├── blind/review.vue # 打分页
│ │ ├── coupon/list.vue # 优惠券
│ │ ├── member/member.vue # 会员中心
│ │ ├── user/profile.vue
│ │ ├── user/preferences.vue
│ │ └── user/history.vue
│ ├── components/
│ ├── api/
│ ├── store/
│ ├── pages.json
│ └── manifest.json
└── docs/
└── API文档.md
```
---
## 九、开发阶段
### Phase 1: 后端基础(Week 1
- [x] 项目初始化
- [ ] Go项目骨架 + 配置
- [ ] 数据库初始化 + 模型
- [ ] JWT认证 + 用户登录
- [ ] 后台管理员登录
### Phase 2: 核心业务(Week 2-3
- [ ] 商家CRUD + 套餐管理
- [ ] 盲选加权随机算法
- [ ] 用户行为追踪
- [ ] 打分系统 + 偏好学习算法
- [ ] AI集成(推荐/标签/报告)
### Phase 3: 会员+优惠券(Week 4
- [ ] VIP会员系统
- [ ] 优惠券创建+领取+核销
- [ ] 佣金计算
- [ ] 中间件:会员校验
### Phase 4: UniApp前端(Week 5-6
- [ ] 项目初始化 + 页面框架
- [ ] 首页 + 盲选入口
- [ ] 揭晓动画 + 打分页
- [ ] 个人中心 + 偏好展示
- [ ] 优惠券中心
- [ ] 会员中心
- [ ] 微信小程序适配
### Phase 5: 后台管理(Week 7
- [ ] DaisyUI5 + Tailwind 搭建
- [ ] 仪表盘 + 数据可视化
- [ ] 商家/套餐管理
- [ ] 优惠券管理
- [ ] 打分分析
- [ ] 数据报表 + 导出
### Phase 6: 测试上线(Week 8-9
- [ ] 端到端测试
- [ ] 性能优化(Redis缓存)
- [ ] App打包
- [ ] 部署上线
---
## 十、关键算法详解
### 10.1 盲选加权随机
```go
func (s *BlindService) Select(user *User, category string, priceRange PriceRange) (*Package, error) {
candidates := s.getCandidates(category, priceRange)
for i := range candidates {
w := 1.0 // 基础权重
// 用户偏好加成
pref := s.getPreferenceScore(user.ID, candidates[i].Category)
w *= (1 + pref)
// 套餐质量分(基于打分积累)
quality := candidates[i].Rating / 5.0
w *= (0.5 + quality * 0.5) // 0.5-1.0范围
// 去重惩罚
if s.isRepeated(user.ID, candidates[i].ID, user.RepeatDays) {
w *= 0.1
}
// 会员加成
if user.MemberLevel == 1 {
w *= 1.2
}
candidates[i].Weight = w
}
return s.weightedRandom(candidates)
}
```
### 10.2 偏好学习 + 打分影响
```go
func (s *PrefService) SubmitReview(userID, packageID uint, review Review) {
// 1. 保存打分
behavior := Behavior{
UserID: userID,
PackageID: packageID,
Type: "reviewed",
ReviewRating: review.Rating,
TasteScore: review.Taste,
ValueScore: review.Value,
DistanceScore: review.Distance,
MatchScore: review.Match,
Tags: review.Tags,
Text: review.Text,
IsRepeat: review.IsRepeat,
CreatedAt: time.Now(),
}
db.Create(&behavior)
// 2. 计算打分系数
scoreMultiplier := reviewScoreMultiplier(review.Rating)
// 5星→1.5, 4星→1.0, 3星→0.5, 2星→-0.5, 1星→-1.5
// 3. 更新用户偏好
pkg := getPackage(packageID)
category := pkg.Category
// 基础行为权重
baseScore := 0.0
switch {
case review.Rating >= 4:
baseScore = 1.0 // 好评,正向影响
case review.Rating == 3:
baseScore = 0.3 // 中立
case review.Rating == 2:
baseScore = -0.3 // 差评
default:
baseScore = -1.0 // 严重差评
}
// 加入商家ID的特殊影响
if review.IsRepeat {
baseScore += 1.0 // 再次前往,大幅正向
}
// 应用打分系数和时间衰减
finalScore := baseScore * scoreMultiplier * getTimeDecay(behavior.CreatedAt)
// 更新偏好
updateCategoryPreference(userID, category, finalScore)
// 4. 更新商家评分
updateMerchantRating(pkg.MerchantID, review.Rating)
// 5. 更新套餐评分
updatePackageRating(packageID, review.Rating)
// 6. 重新生成标签
tags := generateTags(userID)
updateTags(userID, tags)
}
func reviewScoreMultiplier(rating int8) float64 {
switch rating {
case 5: return 1.5
case 4: return 1.0
case 3: return 0.5
case 2: return -0.5
case 1: return -1.5
default: return 0.0
}
}
```
### 10.3 优惠券联动
```go
func (s *CouponService) OnBlindSelectComplete(session *BlindSession) {
pkg := session.Package
// 1. 查找该套餐可用的优惠券
coupons := getCouponsForPackage(pkg.ID)
// 2. 随机发放一张(如果有)
if len(coupons) > 0 {
coupon := coupons[rand.Intn(len(coupons))]
if coupon.RemainCount > 0 {
// 为用户领取
userCoupon := Coupon{
MerchantID: coupon.MerchantID,
PackageID: pkg.ID,
Type: coupon.Type,
Value: coupon.Value,
UserID: session.UserID,
Status: "available",
ValidStart: coupon.ValidStart,
ValidEnd: coupon.ValidEnd,
Commission: coupon.Commission,
CreatedAt: time.Now(),
}
db.Create(&userCoupon)
coupon.RemainCount--
coupon.Save()
}
}
}
func (s *CouponService) OnCouponVerified(couponID uint) {
coupon := getCoupon(couponID)
// 1. 标记已使用
coupon.Status = "used"
coupon.UsedAt = time.Now()
coupon.Save()
// 2. 记录平台佣金
commission := Commission{
CouponID: coupon.ID,
MerchantID: coupon.MerchantID,
Amount: coupon.Commission,
Status: "pending",
CreatedAt: time.Now(),
}
db.Create(&commission)
// 3. 通知商家
notifyMerchant(coupon.MerchantID, "用户核销了优惠券,佣金已记录")
}
```