一、功能概述
互动式优惠券功能旨在通过用户参与互动行为(如签到、分享、完成任务等)获取优惠券,提升用户活跃度和购买转化率。该功能将结合游戏化元素,使优惠券发放更具趣味性和参与感。
二、核心功能设计
1. 优惠券类型设计
- 签到优惠券:连续签到N天获得不同面额优惠券
- 任务优惠券:完成指定任务(如首次下单、邀请好友、评价商品)获得
- 抽奖优惠券:通过转盘/刮刮卡等形式随机获得
- 等级优惠券:根据用户成长等级自动发放
- 互动游戏券:参与小游戏(如消消乐、答题)获得
2. 用户交互流程
```
用户登录 → 进入优惠券中心 → 选择互动方式 → 完成任务 → 获得优惠券 → 使用优惠券
```
三、技术实现方案
1. 后端实现
数据库设计
```sql
-- 优惠券表
CREATE TABLE coupons (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(32) UNIQUE NOT NULL,
type TINYINT NOT NULL COMMENT 1-签到 2-任务 3-抽奖 4-等级 5-游戏,
face_value DECIMAL(10,2) NOT NULL,
min_order_amount DECIMAL(10,2),
start_time DATETIME,
end_time DATETIME,
status TINYINT DEFAULT 1 COMMENT 1-有效 0-失效,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 用户优惠券表
CREATE TABLE user_coupons (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
coupon_id BIGINT NOT NULL,
status TINYINT DEFAULT 0 COMMENT 0-未使用 1-已使用 2-已过期,
get_time DATETIME DEFAULT CURRENT_TIMESTAMP,
use_time DATETIME,
order_id BIGINT,
FOREIGN KEY (coupon_id) REFERENCES coupons(id)
);
-- 用户签到记录
CREATE TABLE user_sign_in (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
sign_date DATE NOT NULL,
continuous_days INT DEFAULT 0,
UNIQUE KEY (user_id, sign_date)
);
-- 用户任务记录
CREATE TABLE user_tasks (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
task_type TINYINT NOT NULL COMMENT 任务类型,
status TINYINT DEFAULT 0 COMMENT 0-未完成 1-已完成,
complete_time DATETIME,
reward_id BIGINT COMMENT 关联的优惠券或积分ID
);
```
核心API设计
```java
// 签到接口
@PostMapping("/api/coupon/signIn")
public ResponseEntity<?> signIn(@RequestParam Long userId) {
// 1. 检查今日是否已签到
// 2. 计算连续签到天数
// 3. 根据连续签到天数发放对应优惠券
// 4. 更新签到记录
// 5. 返回签到结果和获得的优惠券
}
// 完成任务接口
@PostMapping("/api/coupon/completeTask")
public ResponseEntity<?> completeTask(@RequestParam Long userId,
@RequestParam Integer taskType) {
// 1. 验证任务是否可完成
// 2. 标记任务为已完成
// 3. 发放对应优惠券
// 4. 返回任务完成结果和优惠券
}
// 抽奖接口
@PostMapping("/api/coupon/lottery")
public ResponseEntity<?> lotteryDraw(@RequestParam Long userId) {
// 1. 检查用户抽奖次数
// 2. 随机算法确定中奖结果
// 3. 发放优惠券
// 4. 更新用户抽奖记录
// 5. 返回抽奖结果
}
```
2. 前端实现
关键页面/组件
1. 优惠券中心页面
- 展示用户已获得和可获得的优惠券
- 分类展示不同类型优惠券
- 优惠券有效期倒计时显示
2. 签到弹窗组件
- 日历形式展示签到情况
- 连续签到奖励提示
- 签到动画效果
3. 任务中心页面
- 任务列表展示
- 任务进度显示
- 完成任务动画反馈
4. 抽奖互动页面
- 转盘/刮刮卡UI
- 中奖动画效果
- 剩余抽奖次数显示
关键交互代码示例(Vue.js)
```javascript
// 签到组件
export default {
data() {
return {
signInData: null,
showSignInModal: false
}
},
methods: {
async handleSignIn() {
try {
const res = await api.signIn(this.userId);
this.signInData = res.data;
this.showSignInModal = true;
// 播放签到成功动画
this.playSignInAnimation();
} catch (error) {
console.error(签到失败:, error);
}
},
playSignInAnimation() {
// 使用GSAP或CSS动画实现签到效果
this.$animate(.sign-in-btn, {
scale: 1.2,
duration: 0.3,
complete: () => {
this.$animate(.sign-in-btn, { scale: 1 });
}
});
}
}
}
```
四、关键业务逻辑实现
1. 连续签到逻辑
```java
public SignInResult signIn(Long userId) {
LocalDate today = LocalDate.now();
// 检查今日是否已签到
if (userSignInRepository.existsByUserIdAndSignDate(userId, today)) {
throw new BusinessException("今日已签到");
}
// 获取昨日签到记录计算连续天数
LocalDate yesterday = today.minusDays(1);
UserSignIn lastSignIn = userSignInRepository.findTopByUserIdAndSignDateBeforeOrderBySignDateDesc(
userId, today);
int continuousDays = (lastSignIn != null && lastSignIn.getSignDate().equals(yesterday))
? lastSignIn.getContinuousDays() + 1
: 1;
// 根据连续天数确定奖励
Coupon rewardCoupon = determineCouponByContinuousDays(continuousDays);
// 保存签到记录
UserSignIn newSignIn = new UserSignIn();
newSignIn.setUserId(userId);
newSignIn.setSignDate(today);
newSignIn.setContinuousDays(continuousDays);
userSignInRepository.save(newSignIn);
// 发放优惠券
if (rewardCoupon != null) {
issueCouponToUser(userId, rewardCoupon.getId());
}
return new SignInResult(continuousDays, rewardCoupon);
}
```
2. 抽奖概率控制
```java
public LotteryResult drawLottery(Long userId) {
// 检查用户今日抽奖次数
int todayCount = userLotteryRepository.countByUserIdAndCreateTimeAfter(
userId, LocalDate.now().atStartOfDay());
if (todayCount >= MAX_DAILY_DRAWS) {
throw new BusinessException("今日抽奖次数已用完");
}
// 权重配置(示例)
Map prizeWeights = new HashMap<>();
prizeWeights.put(1, 50); // 50%概率无奖
prizeWeights.put(2, 30); // 30%概率小奖
prizeWeights.put(3, 15); // 15%概率中奖
prizeWeights.put(4, 5); // 5%概率大奖
// 随机数生成
Random random = new Random();
int randomNum = random.nextInt(100) + 1;
// 根据权重确定奖品
int prizeType = determinePrizeByWeight(prizeWeights, randomNum);
// 获取对应奖品
Coupon coupon = couponRepository.findByTypeAndPrizeType(CouponType.LOTTERY, prizeType)
.orElseThrow(() -> new BusinessException("奖品不存在"));
// 发放奖品
issueCouponToUser(userId, coupon.getId());
// 记录抽奖
UserLotteryRecord record = new UserLotteryRecord();
record.setUserId(userId);
record.setPrizeType(prizeType);
record.setCouponId(coupon.getId());
userLotteryRepository.save(record);
return new LotteryResult(prizeType, coupon);
}
private int determinePrizeByWeight(Map weights, int randomNum) {
int cumulativeWeight = 0;
for (Map.Entry entry : weights.entrySet()) {
cumulativeWeight += entry.getValue();
if (randomNum <= cumulativeWeight) {
return entry.getKey();
}
}
return 1; // 默认返回无奖
}
```
五、测试方案
1. 单元测试
- 签到连续天数计算测试
- 抽奖概率算法测试
- 优惠券发放逻辑测试
- 优惠券使用条件验证测试
2. 集成测试
- 签到→抽奖→使用优惠券完整流程测试
- 多用户并发签到测试
- 优惠券过期自动失效测试
3. 性能测试
- 高并发下优惠券发放性能测试
- 抽奖接口响应时间测试
- 优惠券列表加载性能测试
六、部署与监控
1. 部署方案
- 优惠券服务独立部署,与主应用通过RPC通信
- 使用Redis缓存热门优惠券数据
- 异步处理优惠券发放(使用消息队列)
2. 监控指标
- 优惠券发放成功率
- 用户参与互动率
- 优惠券使用率
- 各渠道优惠券获取占比
- 系统接口响应时间
七、优化方向
1. 个性化推荐:根据用户购买习惯推荐相关优惠券
2. 社交裂变:分享优惠券可获得额外奖励
3. AR互动:通过AR扫描商品获得优惠券
4. 游戏化升级:设计更复杂的互动游戏获取优惠券
5. 智能有效期:根据用户活跃度动态调整优惠券有效期
通过实现互动式优惠券功能,小象买菜系统可以有效提升用户活跃度、增加用户粘性,并通过优惠券的精准发放提高订单转化率和客单价。