06488f0237
功能: - Go后端 (Gin + GORM + PostgreSQL) - UniApp用户端 (iOS/Android/小程序) - DaisyUI5后台管理 - JWT认证 + 微信登录 - 盲选加权算法 - 会员系统 + 优惠券 - 打分评价 + 偏好学习
928 lines
27 KiB
Markdown
928 lines
27 KiB
Markdown
# "帮我选"盲选应用 - 开发大纲 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, "用户核销了优惠券,佣金已记录")
|
||
}
|
||
```
|