feat: 🎁 新增破冰抽奖功能及 82 人名单
- 新增 src/views/PrizeDraw 抽奖视图及抽奖配置 store - 更新 defaultPersonList 为 82 位真实参与者名单 - 调整主页、路由、i18n 及音乐播放以支持抽奖入口 - 附抽奖需求及实现报告文档 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
140
CLAUDE_CODE_PROMPT.md
Normal file
140
CLAUDE_CODE_PROMPT.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Claude Code 提示词:实现抽奖系统
|
||||
|
||||
## 项目概述
|
||||
这是一个年会抽奖系统,当前已有"抽人"功能(从88人中抽取中奖者)。现在需要新增一个"抽奖"页面,为88个人每人抽取一个奖品。
|
||||
|
||||
## 核心需求
|
||||
为88个人(LN-001 到 LN-088)抽取奖品,每人抽一次,共88次。奖品配置如下:
|
||||
1. 快乐通勤奖(25个)- 可提前1小时下班或晚到1小时
|
||||
2. 跑马场自由日(18个)- 可选在家或其他场所办公
|
||||
3. 前途光明奖(2个)- 获得boss 1对1畅聊1小时
|
||||
4. 现金红包500元(3个)
|
||||
5. 现金红包300元(8个)
|
||||
6. 现金红包200元(15个)
|
||||
7. 现金红包100元(17个)
|
||||
|
||||
## 技术栈
|
||||
- Vue 3 + TypeScript + Vite
|
||||
- Pinia (状态管理)
|
||||
- 复用现有组件和样式
|
||||
|
||||
## 实现步骤
|
||||
|
||||
### Step 1: 创建 Pinia Store
|
||||
创建 `src/store/prizeDrawConfig.ts`,包含:
|
||||
- 奖品配置(7种奖品,共88个)
|
||||
- 人员列表(从 `defaultPersonList` 获取88个人)
|
||||
- 抽奖结果数组
|
||||
- 抽奖逻辑:
|
||||
- `executeDraw()`: 随机从剩余人员中选一个,随机从剩余奖品中选一个,记录结果
|
||||
- `reset()`: 重置所有数据
|
||||
- `canDraw`: 计算属性,判断是否还能继续抽奖
|
||||
- 使用 IndexedDB 持久化数据
|
||||
|
||||
### Step 2: 创建页面组件
|
||||
创建 `src/views/PrizeDraw/index.vue`,布局包含:
|
||||
1. **顶部区域**:标题 + 进度(已抽 X/88)
|
||||
2. **左侧/顶部**:奖品池展示(7个奖品卡片,显示剩余数量)
|
||||
3. **中央区域**:
|
||||
- 大按钮:"开始抽奖" / "继续抽奖" / "抽奖完成"
|
||||
- 抽奖动画区域(可复用现有卡片动画)
|
||||
- 结果展示:人员编号 + 奖品名称
|
||||
4. **右侧/底部**:已抽奖记录列表(可滚动)
|
||||
|
||||
### Step 3: 实现抽奖逻辑
|
||||
```typescript
|
||||
// 核心算法
|
||||
function executeDraw() {
|
||||
// 1. 从剩余人员中随机选一个
|
||||
const randomPersonIndex = Math.floor(Math.random() * remainingPersons.length)
|
||||
const person = remainingPersons.splice(randomPersonIndex, 1)[0]
|
||||
|
||||
// 2. 从剩余奖品中随机选一个
|
||||
const randomPrizeIndex = Math.floor(Math.random() * remainingPrizes.length)
|
||||
const prize = remainingPrizes.splice(randomPrizeIndex, 1)[0]
|
||||
|
||||
// 3. 记录结果
|
||||
drawResults.push({
|
||||
drawIndex: drawResults.length + 1,
|
||||
personId: person.uid,
|
||||
personName: person.name,
|
||||
prizeId: prize.id,
|
||||
prizeName: prize.name,
|
||||
drawTime: new Date().toISOString()
|
||||
})
|
||||
|
||||
// 4. 更新奖品剩余数量
|
||||
updatePrizeRemaining(prize.id)
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: 添加动画效果
|
||||
- 点击按钮后,显示1-2秒的滚动/加载动画
|
||||
- 可以复用 `src/views/Home` 中的卡片动画效果
|
||||
- 结果展示时添加庆祝动画(可选)
|
||||
|
||||
### Step 5: 添加路由
|
||||
在 `src/router/index.ts` 中添加:
|
||||
```typescript
|
||||
{
|
||||
path: '/prize-draw',
|
||||
name: 'PrizeDraw',
|
||||
component: () => import('@/views/PrizeDraw/index.vue'),
|
||||
meta: { title: '抽奖系统' }
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6: 添加导航入口
|
||||
在主页或顶部菜单添加"抽奖"按钮,跳转到 `/prize-draw`
|
||||
|
||||
### Step 7: 实现额外功能
|
||||
1. **导出功能**:将抽奖结果导出为 CSV/Excel
|
||||
2. **重置功能**:清空所有数据,重新开始
|
||||
3. **撤销功能**:撤销最后一次抽奖(可选)
|
||||
|
||||
## 数据结构参考
|
||||
|
||||
```typescript
|
||||
// 奖品配置
|
||||
interface Prize {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
total: number // 总数量
|
||||
remaining: number // 剩余数量
|
||||
color: string // 显示颜色
|
||||
}
|
||||
|
||||
// 抽奖结果
|
||||
interface DrawResult {
|
||||
drawIndex: number // 第几次抽奖
|
||||
personId: string // LN-001
|
||||
personName: string // LN-001
|
||||
prizeId: string
|
||||
prizeName: string
|
||||
drawTime: string
|
||||
}
|
||||
```
|
||||
|
||||
## UI 要求
|
||||
- 复用现有主题配置(绿色系:#4cb050, #05a045, #a5d6a7)
|
||||
- 响应式布局,支持移动端
|
||||
- 动画流畅自然
|
||||
- 进度清晰可见
|
||||
|
||||
## 注意事项
|
||||
1. 确保随机算法公平(使用 `Math.random()`)
|
||||
2. 处理边界情况(最后一个人、最后一个奖品)
|
||||
3. 数据持久化到 IndexedDB(刷新页面不丢失)
|
||||
4. 代码结构清晰,遵循现有项目规范
|
||||
|
||||
## 验收标准
|
||||
- [ ] 可以完整执行88次抽奖
|
||||
- [ ] 每个人只抽一次,每个奖品数量准确
|
||||
- [ ] 动画效果流畅
|
||||
- [ ] 数据可以持久化
|
||||
- [ ] 可以导出结果
|
||||
- [ ] 移动端可用
|
||||
|
||||
## 开始实现
|
||||
请按照上述步骤实现抽奖系统。如果有任何疑问,请先查看现有代码结构(特别是 `src/store/personConfig.ts` 和 `src/views/Home/index.vue`)作为参考。
|
||||
Reference in New Issue
Block a user