转盘组件设计与防刷方案
转盘抽奖组件的设计要点和前端防刷策略
问题
如何设计一个转盘抽奖组件?需要和业务方确认哪些技术细节?如何从前端角度实现防刷?
解答
组件设计考虑
功能需求
明确抽奖逻辑、转盘样式和动画效果。确定是否需要音效、中奖弹窗、历史记录等功能。
技术选型
根据需求选择实现方式:
- CSS3 动画:适合简单的旋转效果,性能好
- Canvas:适合复杂的绘图需求,灵活度高
- SVG:适合需要缩放和交互的场景
数据处理
设计与后端的交互流程:
// 抽奖请求
async function drawLottery() {
const response = await fetch('/api/lottery/draw', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Request-ID': generateRequestId() // 请求唯一标识
},
body: JSON.stringify({
activityId: 'xxx',
userId: 'xxx',
timestamp: Date.now()
})
});
const result = await response.json();
// result: { prizeId, prizeName, angle, ... }
return result;
}
用户体验
- 加载状态:显示 loading 动画
- 错误处理:网络异常、次数不足等提示
- 动画流畅:使用 requestAnimationFrame 优化
- 防止重复点击:抽奖过程中禁用按钮
业务方确认的技术细节
抽奖规则
- 奖品种类、库存数量
- 中奖概率配置
- 每日/每人抽奖次数限制
- 奖品兑换方式和有效期
后端接口规范
// 接口示例
POST /api/lottery/draw
Request: {
activityId: string,
userId: string,
timestamp: number,
sign: string // 签名
}
Response: {
code: number,
data: {
prizeId: string,
prizeName: string,
angle: number, // 转盘停止角度
remainCount: number // 剩余次数
}
}
防刷策略
- 前端限制:按钮防抖、次数校验
- 后端限制:IP 频率限制、用户维度限制
- 验证机制:滑块验证、短信验证码
奖品发放
- 实物奖品:收集收货地址、身份验证
- 虚拟奖品:优惠券、积分等自动发放
- 发放时机:即时发放或审核后发放
前端防刷方案
限制抽奖次数
class LotteryController {
constructor() {
this.isDrawing = false;
this.remainCount = 0;
}
async draw() {
// 防止重复点击
if (this.isDrawing) {
return;
}
// 检查次数
if (this.remainCount <= 0) {
showToast('抽奖次数不足');
return;
}
this.isDrawing = true;
try {
const result = await drawLottery();
this.remainCount = result.remainCount;
await this.startAnimation(result.angle);
} finally {
this.isDrawing = false;
}
}
}
请求签名
function generateSign(params, secret) {
// 参数排序
const sortedKeys = Object.keys(params).sort();
const str = sortedKeys.map(key => `${key}=${params[key]}`).join('&');
// 生成签名(实际应使用更安全的算法)
return md5(str + secret);
}
// 使用
const params = {
activityId: 'xxx',
userId: 'xxx',
timestamp: Date.now()
};
params.sign = generateSign(params, SECRET_KEY);
设备指纹
// 收集设备信息生成唯一标识
function getDeviceFingerprint() {
const info = {
userAgent: navigator.userAgent,
language: navigator.language,
platform: navigator.platform,
screenResolution: `${screen.width}x${screen.height}`,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
};
return hashCode(JSON.stringify(info));
}
验证码集成
async function drawWithCaptcha() {
// 触发验证码
const captchaToken = await showCaptcha();
// 带上验证码 token 请求
const response = await fetch('/api/lottery/draw', {
method: 'POST',
body: JSON.stringify({
// ... 其他参数
captchaToken
})
});
}
关键点
- 前端防刷只是辅助手段,真正的防刷逻辑必须在后端实现
- 使用请求签名、时间戳、设备指纹等多重验证提高安全性
- 关键接口需要限流、防重放攻击,配合验证码机制
- 与业务方明确抽奖规则、接口规范、奖品发放流程
- 优化用户体验:loading 状态、错误提示、防止重复点击
目录