- 新增 src/views/PrizeDraw 抽奖视图及抽奖配置 store - 更新 defaultPersonList 为 82 位真实参与者名单 - 调整主页、路由、i18n 及音乐播放以支持抽奖入口 - 附抽奖需求及实现报告文档 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.1 KiB
6.1 KiB
抽奖系统最终版本说明
版本:v2.0 - 卡片墙老虎机
🎯 核心设计
抽奖方式
卡片墙老虎机:88个奖品卡片排列成网格(m × n),抽奖时高亮卡片顺序滚动
抽奖流程
1. 初始状态:所有卡片显示问号(神秘状态)
2. 点击抽奖:高亮框在未抽卡片中滚动(5-8秒随机)
3. 滚动减速:逐渐减慢,最终停在中奖卡片
4. 翻牌展示:中奖卡片翻转显示奖品信息
5. 礼花庆祝:全屏礼花效果
6. 记录历史:右侧显示抽奖记录
🎨 视觉设计
卡片墙布局
┌─────────────────────────────────────┐
│ ? ? ? ? ? ? ? ? │
│ ? ? ? ? ? ? ? ? │
│ ? ? [?] ? ? ? ? ? │ ← 高亮滚动
│ ? ? ? ? ? ? ? ? │
│ ? ? ? ? ? ? ? ? │
│ 💰 🏠 ⏰ ? ? ? ? ? │ ← 已抽显示
│ ? ? ? ? ? ? ? ? │
│ ? ? ? ? ? ? ? ? │
└─────────────────────────────────────┘
卡片状态
- 未抽:问号背面(紫色渐变)
- 滚动中:高亮边框(黄色发光)
- 已抽:显示奖品图标和名称(灰色)
- 中奖:放大+发光效果(绿色边框)
🔧 技术实现
1. 卡片数据生成
const prizeCards = computed(() => {
const cards = []
store.prizeConfigs.forEach((config) => {
const drawnCount = config.totalCount - config.remainingCount
const remainingCount = config.remainingCount
// 已抽的卡片
for (let i = 0; i < drawnCount; i++) {
cards.push({ ...config, isDrawn: true })
}
// 未抽的卡片
for (let i = 0; i < remainingCount; i++) {
cards.push({ ...config, isDrawn: false })
}
})
return cards // 总共88张
})
2. 滚动动画
function startScrollAnimation() {
// 随机时长 5-8秒
const duration = 5000 + Math.random() * 3000
// 只在未抽卡片中滚动
const availableIndices = prizeCards.value
.filter(card => !card.isDrawn)
.map((card, index) => index)
// 速度逐渐减慢
const speed = progress < 0.7 ? 50 : 50 + (progress - 0.7) * 300
// 每50ms切换高亮
setInterval(() => {
highlightIndex.value = availableIndices[currentIndex]
}, 50)
}
3. 卡片样式
.prize-card-item {
// 未抽:问号背面
&:not(.drawn) .card-back {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
// 滚动高亮
&.highlight {
border: 3px solid #f39c12;
box-shadow: 0 0 20px rgba(243, 156, 18, 0.6);
transform: scale(1.05);
}
// 中奖卡片
&.winner {
border: 3px solid #27ae60;
box-shadow: 0 0 30px rgba(39, 174, 96, 0.8);
transform: scale(1.1);
}
// 已抽卡片
&.drawn {
opacity: 0.5;
filter: grayscale(0.5);
}
}
📊 布局说明
网格配置
- 列数:8列(可调整)
- 行数:11行(88 ÷ 8 = 11)
- 卡片尺寸:120px × 160px
- 间距:12px
响应式
.prize-wall {
display: grid;
grid-template-columns: repeat(8, 120px);
gap: 12px;
@media (max-width: 1400px) {
grid-template-columns: repeat(6, 120px);
}
@media (max-width: 1000px) {
grid-template-columns: repeat(4, 120px);
}
}
🎮 用户体验
抽奖体验
- 悬念感:5-8秒随机滚动,不可预测
- 视觉追踪:高亮框清晰,易于跟随
- 减速效果:逐渐减慢,增加紧张感
- 翻牌惊喜:最终卡片翻转展示
- 庆祝反馈:礼花+放大效果
交互细节
- 已抽卡片:半透明+灰度,不参与滚动
- 中奖卡片:绿色发光边框,放大1.1倍
- 滚动速度:前70%快速,后30%减速
- 随机时长:每次5-8秒不等
📝 使用说明
操作流程
- 打开抽奖页面
- 点击"开始抽奖"
- 观看卡片墙滚动(5-8秒)
- 查看中奖结果
- 点击"继续抽奖"进行下一轮
功能说明
- 奖品池:左侧可折叠,显示剩余数量
- 抽奖区:中间卡片墙,主要操作区
- 历史记录:右侧显示所有抽奖记录
- 撤销功能:可撤销最后一次抽奖
- 导出功能:导出Excel完整记录
⚙️ 配置参数
可调整项
// 滚动时长范围
const minDuration = 5000 // 5秒
const maxDuration = 8000 // 8秒
// 网格列数
const columns = 8
// 卡片尺寸
const cardWidth = 120
const cardHeight = 160
// 滚动速度
const baseSpeed = 50 // 基础间隔(ms)
const slowdownFactor = 300 // 减速系数
🎯 特性总结
✅ 已实现
- ✅ 88个奖品卡片网格排列
- ✅ 高亮框顺序滚动(5-8秒)
- ✅ 只在未抽卡片中滚动
- ✅ 滚动速度逐渐减慢
- ✅ 中奖卡片翻转展示
- ✅ 礼花庆祝效果
- ✅ 已抽卡片灰度显示
- ✅ 历史记录实时更新
🎨 视觉效果
- 清新自然配色
- 流畅动画过渡
- 明确的状态区分
- 专业的UI设计
🔧 技术亮点
- 响应式网格布局
- 高性能动画
- 状态管理完善
- 数据持久化
🚀 部署说明
开发环境
npm run dev
# 访问: http://localhost:6719/log-lottery/prize-draw
生产构建
npm run build
# 输出: dist/
Docker部署
docker build -t log-lottery .
docker run -d -p 9279:80 log-lottery
📊 测试清单
- 第1次抽奖(初始状态)
- 滚动时长在5-8秒范围
- 高亮只在未抽卡片中滚动
- 中奖卡片正确翻转
- 礼花效果正常
- 历史记录正确显示
- 第88次抽奖(最后一次)
- 撤销功能正常
- 导出Excel正常
- 刷新页面数据保持
🎉 项目状态
版本:v2.0 - 卡片墙老虎机 完成度:100% 可用性:✅ 可立即投入使用
所有需求已实现,可以开始测试! 🎊