Browse Source
Merge branch 'milestone-20250722-抽奖' of http://39.101.133.168:8807/hongxilin/activityLink into hongxilin/feature-20250710175148-抽奖
songtongtong/feature-20250717104937-众筹
Merge branch 'milestone-20250722-抽奖' of http://39.101.133.168:8807/hongxilin/activityLink into hongxilin/feature-20250710175148-抽奖
songtongtong/feature-20250717104937-众筹
28 changed files with 2565 additions and 526 deletions
-
44CORS_README.md
-
1154package-lock.json
-
9package.json
-
BINsrc/assets/bg@2x.png
-
BINsrc/assets/loginback.png
-
BINsrc/assets/music.mp3
-
BINsrc/assets/qilin.webp
-
BINsrc/assets/展开.png
-
20src/router/index.js
-
58src/store/lottery.js
-
20src/stores/auth.js
-
2src/utils/request.js
-
102src/views/choujiang/Login.vue
-
129src/views/choujiang/index.vue
-
143src/views/choujiang/lottery/CardItem.vue
-
55src/views/choujiang/lottery/ControlBar.vue
-
300src/views/choujiang/lottery/Lottery3D.vue
-
54src/views/choujiang/lottery/Mascot.vue
-
32src/views/choujiang/lottery/MusicPlayer.vue
-
292src/views/choujiang/lottery/PrizePanel.vue
-
4src/views/choujiang/lottery/UserList.vue
-
217src/views/choujiang/lottery/dataManager.js
-
149src/views/choujiang/lottery/lotteryEngine.js
-
2src/views/homePage.vue
-
2src/views/zhongchou/index.vue
-
98修改完成总结.md
-
92抽奖逻辑修改说明.md
-
113测试用例.md
@ -0,0 +1,44 @@ |
|||||
|
# 跨域问题解决方案 |
||||
|
|
||||
|
## 配置说明 |
||||
|
|
||||
|
本项目已配置Vite代理来解决跨域问题。 |
||||
|
|
||||
|
### 1. Vite配置 (vite.config.js) |
||||
|
|
||||
|
```javascript |
||||
|
server: { |
||||
|
host: '0.0.0.0', |
||||
|
port: 3000, |
||||
|
proxy: { |
||||
|
'/api': { |
||||
|
target: 'https://dbqb.nfdxy.net', |
||||
|
changeOrigin: true, |
||||
|
secure: false, |
||||
|
rewrite: (path) => path.replace(/^\/api/, '/devLotApi/api') |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 2. 请求配置 (src/utils/request.js) |
||||
|
|
||||
|
- `baseURL: '/api'` - 设置基础URL为代理路径 |
||||
|
|
||||
|
### 3. API调用 (src/api/API.js) |
||||
|
|
||||
|
- 使用相对路径 `/prize/list` 而不是完整的URL |
||||
|
- 实际请求会被代理到 `https://dbqb.nfdxy.net/devLotApi/api/prize/list` |
||||
|
|
||||
|
## 工作原理 |
||||
|
|
||||
|
1. 前端发起请求到 `/api/prize/list` |
||||
|
2. Vite开发服务器拦截请求 |
||||
|
3. 代理将请求转发到 `https://dbqb.nfdxy.net/devLotApi/api/prize/list` |
||||
|
4. 服务器响应通过代理返回给前端 |
||||
|
|
||||
|
## 注意事项 |
||||
|
|
||||
|
- 此配置仅在开发环境有效 |
||||
|
- 生产环境需要在服务器端配置CORS或使用nginx代理 |
||||
|
- 确保目标服务器允许跨域请求 |
1154
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
After Width: 3840 | Height: 2160 | Size: 5.6 MiB |
After Width: 1920 | Height: 1080 | Size: 1.7 MiB |
After Width: 40 | Height: 34 | Size: 2.9 KiB |
@ -0,0 +1,20 @@ |
|||||
|
import { defineStore } from 'pinia'; |
||||
|
import { ref } from 'vue'; |
||||
|
export const useAuthStore = defineStore('auth', () => { |
||||
|
// 登录状态
|
||||
|
const isLoggedIn = ref(false); |
||||
|
// 登录方法
|
||||
|
const login = () => { |
||||
|
isLoggedIn.value = true; |
||||
|
}; |
||||
|
// 登出方法
|
||||
|
const logout = () => { |
||||
|
isLoggedIn.value = false; |
||||
|
}; |
||||
|
return { |
||||
|
isLoggedIn, |
||||
|
login, |
||||
|
logout |
||||
|
}; |
||||
|
},{persist : false}); |
||||
|
//开启持久化)
|
@ -0,0 +1,102 @@ |
|||||
|
<template> |
||||
|
<div class="login-container"> |
||||
|
<div class="login-card"> |
||||
|
<form @submit.prevent="handleLogin"> |
||||
|
<div class="form-group"> |
||||
|
<input |
||||
|
type="password" |
||||
|
id="password" |
||||
|
v-model="password" |
||||
|
|
||||
|
placeholder="请输入密码" |
||||
|
/> |
||||
|
</div> |
||||
|
<button type="submit" class="login-button">进入抽奖</button> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref } from 'vue'; |
||||
|
import { useRouter } from 'vue-router'; |
||||
|
import { useAuthStore } from '../../stores/auth'; |
||||
|
const password = ref(''); |
||||
|
const CORRECT_PASSWORD = '123456'; |
||||
|
const router = useRouter(); |
||||
|
const authStore = useAuthStore(); |
||||
|
const handleLogin = () => { |
||||
|
if (password.value === '') { |
||||
|
alert('请输入密码'); |
||||
|
return; |
||||
|
} |
||||
|
if (password.value === CORRECT_PASSWORD) { |
||||
|
alert('登录成功,即将跳转到抽奖页面'); |
||||
|
// 添加登录状态存储 |
||||
|
authStore.login(); // 使用Pinia登录方法 |
||||
|
router.push('/choujiang'); |
||||
|
} else { |
||||
|
alert('密码错误,请重试'); |
||||
|
} |
||||
|
}; |
||||
|
// 登录逻辑处理 |
||||
|
console.log('登录信息:', { |
||||
|
password: password.value, |
||||
|
}); |
||||
|
// 这里可以添加实际的登录API调用 |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.login-container { |
||||
|
background-image: url('../../assets/loginback.png'); /* 确保路径正确 */ |
||||
|
background-position: center; |
||||
|
background-size: cover; |
||||
|
height: 100vh; /* 确保背景图片覆盖整个视口高度 */ |
||||
|
width: 100vw; /* 确保背景图片覆盖整个视口宽度 */ |
||||
|
position: fixed; /* 使用fixed定位确保背景图片覆盖整个页面 */ |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
z-index: -1; /* 确保背景图片在其他内容下方 */ |
||||
|
} |
||||
|
|
||||
|
.login-card { |
||||
|
position: absolute; |
||||
|
top: 50%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
width: 300px; /* 设置固定宽度 */ |
||||
|
height: 200px; /* 设置固定高度 */ |
||||
|
padding: 2rem; |
||||
|
background: rgba(255, 255, 255, 0.8); /* 调整背景颜色为半透明白色 */ |
||||
|
border-radius: 8px; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
||||
|
box-sizing: border-box; |
||||
|
z-index: 1; /* 确保卡片在背景图片上方 */ |
||||
|
} |
||||
|
|
||||
|
input { |
||||
|
width: 100%; |
||||
|
padding: 0.8rem; |
||||
|
border: 1px solid #ddd; |
||||
|
border-radius: 4px; |
||||
|
font-size: 1rem; |
||||
|
margin-bottom: 2rem; |
||||
|
box-sizing: border-box |
||||
|
} |
||||
|
|
||||
|
.login-button { |
||||
|
width: 100%; |
||||
|
padding: 0.8rem; |
||||
|
background-color: #42b983; |
||||
|
color: white; |
||||
|
border: none; |
||||
|
border-radius: 4px; |
||||
|
font-size: 1rem; |
||||
|
cursor: pointer; |
||||
|
transition: background-color 0.3s; |
||||
|
box-sizing: border-box |
||||
|
} |
||||
|
|
||||
|
.login-button:hover { |
||||
|
background-color: #359469; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,54 @@ |
|||||
|
<template> |
||||
|
<div class="mascot-container"> |
||||
|
<img |
||||
|
src="../../../assets/qilin.webp" |
||||
|
alt="可爱的角色" |
||||
|
class="mascot-image" |
||||
|
/> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
// 组件逻辑 |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.mascot-container { |
||||
|
position: fixed; |
||||
|
bottom: -10px; |
||||
|
right: -80px; |
||||
|
z-index: 1000; |
||||
|
pointer-events: none; |
||||
|
} |
||||
|
|
||||
|
.mascot-image { |
||||
|
width: 400px; |
||||
|
height: 400px; |
||||
|
animation: bounce 2s ease-in-out infinite; |
||||
|
} |
||||
|
|
||||
|
/* @keyframes bounce { |
||||
|
0%, 20%, 50%, 80%, 100% { |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
40% { |
||||
|
transform: translateY(-10px); |
||||
|
} |
||||
|
60% { |
||||
|
transform: translateY(-5px); |
||||
|
} |
||||
|
} */ |
||||
|
|
||||
|
/* 响应式设计 */ |
||||
|
@media (max-width: 768px) { |
||||
|
.mascot-image { |
||||
|
width: 180px; |
||||
|
height: 180px; |
||||
|
} |
||||
|
|
||||
|
.mascot-container { |
||||
|
bottom: 10px; |
||||
|
right: 10px; |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,98 @@ |
|||||
|
# 抽奖逻辑修改完成总结 |
||||
|
|
||||
|
## 修改完成情况 |
||||
|
|
||||
|
✅ **已完成所有必要的修改** |
||||
|
|
||||
|
## 修改文件清单 |
||||
|
|
||||
|
### 1. API接口层 (`src/api/API.js`) |
||||
|
- ✅ 新增 `drawLottery` 接口 |
||||
|
- ✅ 支持传递奖项信息和轮次参数 |
||||
|
|
||||
|
### 2. 抽奖引擎 (`src/views/choujiang/lottery/lotteryEngine.js`) |
||||
|
- ✅ 修改 `executeLottery` 函数,每轮抽奖请求后端 |
||||
|
- ✅ 添加错误处理机制,支持回退到前端随机抽奖 |
||||
|
- ✅ 适配新的数据格式 `{ jwcode: "xxx", username: "xxx" }` |
||||
|
|
||||
|
### 3. 数据管理器 (`src/views/choujiang/lottery/dataManager.js`) |
||||
|
- ✅ 使用真实用户数据替代假数据 |
||||
|
- ✅ 确保数据格式与后端返回格式兼容 |
||||
|
- ✅ 支持新旧两种数据格式 |
||||
|
|
||||
|
### 4. 3D显示组件 (`src/views/choujiang/lottery/Lottery3D.vue`) |
||||
|
- ✅ 修改 `changeCard` 函数,适配新的数据格式 |
||||
|
- ✅ 支持显示 `jwcode` 和 `username` 字段 |
||||
|
- ✅ 保持向后兼容性 |
||||
|
|
||||
|
### 5. 主抽奖页面 (`src/views/choujiang/index.vue`) |
||||
|
- ✅ 修改气泡提示逻辑,支持新的数据格式 |
||||
|
- ✅ 确保中奖用户信息正确显示 |
||||
|
|
||||
|
## 核心功能 |
||||
|
|
||||
|
### 1. 后端抽奖接口 |
||||
|
```javascript |
||||
|
// 请求参数 |
||||
|
{ |
||||
|
gradeName: "一等奖", |
||||
|
prizeName: "iPhone 15", |
||||
|
perWin: 5, |
||||
|
round: 1 |
||||
|
} |
||||
|
|
||||
|
// 返回数据 |
||||
|
{ |
||||
|
data: [ |
||||
|
{ jwcode: "5412", username: "猪八戒22" }, |
||||
|
{ jwcode: "45125", username: "宝玉" } |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 2. 错误处理机制 |
||||
|
- 后端请求失败时自动回退到前端随机抽奖 |
||||
|
- 确保抽奖功能不中断 |
||||
|
- 提供详细的错误日志 |
||||
|
|
||||
|
### 3. 数据格式兼容性 |
||||
|
- 支持新格式:`{ jwcode: "5412", username: "猪八戒22" }` |
||||
|
- 支持旧格式:`["5412", "猪八戒22", "PSST"]` |
||||
|
- 自动识别和适配不同格式 |
||||
|
|
||||
|
## 工作流程 |
||||
|
|
||||
|
1. **页面初始化** → 获取奖品列表和用户列表 |
||||
|
2. **开始抽奖** → 用户点击抽奖按钮 |
||||
|
3. **请求后端** → 发送抽奖请求,包含奖项信息和轮次 |
||||
|
4. **获取结果** → 后端返回中奖用户列表 |
||||
|
5. **显示动画** → 前端根据返回的中奖用户显示3D抽奖动画 |
||||
|
6. **保存结果** → 将中奖用户保存到本地状态 |
||||
|
|
||||
|
## 测试建议 |
||||
|
|
||||
|
1. **正常流程测试**:验证完整的抽奖流程 |
||||
|
2. **异常处理测试**:模拟后端接口异常 |
||||
|
3. **数据格式测试**:验证新旧数据格式兼容性 |
||||
|
4. **多轮抽奖测试**:验证轮次管理和奖品切换 |
||||
|
5. **性能测试**:验证大量用户数据下的表现 |
||||
|
|
||||
|
## 部署注意事项 |
||||
|
|
||||
|
1. **后端接口**:确保实现 `/lottery/draw` 接口 |
||||
|
2. **数据格式**:确保返回的数据格式符合要求 |
||||
|
3. **错误处理**:建议后端提供详细的错误信息 |
||||
|
4. **性能优化**:考虑大量并发抽奖请求的处理 |
||||
|
|
||||
|
## 后续优化建议 |
||||
|
|
||||
|
1. **缓存机制**:可以考虑缓存用户数据,减少重复请求 |
||||
|
2. **实时更新**:可以考虑WebSocket实时更新中奖结果 |
||||
|
3. **数据统计**:可以添加抽奖统计和分析功能 |
||||
|
4. **界面优化**:可以根据实际需求优化3D动画效果 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**修改完成时间**:2024年12月19日 |
||||
|
**修改状态**:✅ 已完成 |
||||
|
**测试状态**:🔄 待测试 |
@ -0,0 +1,92 @@ |
|||||
|
# 抽奖逻辑修改说明 |
||||
|
|
||||
|
## 修改概述 |
||||
|
|
||||
|
本次修改将抽奖逻辑从前端随机抽奖改为每轮抽奖都请求后端获取中奖数据。 |
||||
|
|
||||
|
## 主要修改内容 |
||||
|
|
||||
|
### 1. API接口修改 (`src/api/API.js`) |
||||
|
|
||||
|
新增了 `drawLottery` 接口,用于每轮抽奖时请求后端: |
||||
|
|
||||
|
```javascript |
||||
|
export function drawLottery(data){ |
||||
|
return request({ |
||||
|
url: '/lottery/draw', |
||||
|
method: 'post', |
||||
|
data: { |
||||
|
gradeName: data.gradeName, // 奖项名称 |
||||
|
prizeName: data.prizeName, // 奖品名称 |
||||
|
perWin: data.perWin, // 每轮抽奖人数 |
||||
|
round: data.round // 当前轮次 |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 2. 抽奖引擎修改 (`src/views/choujiang/lottery/lotteryEngine.js`) |
||||
|
|
||||
|
- 修改 `executeLottery` 函数,每轮抽奖都请求后端 |
||||
|
- 后端返回数据格式:`{ data: [{ jwcode: "5412", username: "猪八戒22" }, ...] }` |
||||
|
- 添加了错误处理机制,如果后端请求失败会回退到前端随机抽奖 |
||||
|
|
||||
|
### 3. 数据管理器修改 (`src/views/choujiang/lottery/dataManager.js`) |
||||
|
|
||||
|
- 使用真实的用户数据替代假数据 |
||||
|
- 确保数据格式与后端返回格式兼容 |
||||
|
- 用户数据格式:`{ jwcode: "5412", username: "猪八戒22", company: "公司名称" }` |
||||
|
|
||||
|
### 4. 3D显示组件修改 (`src/views/choujiang/lottery/Lottery3D.vue`) |
||||
|
|
||||
|
- 修改 `changeCard` 函数,适配新的数据格式 |
||||
|
- 支持显示 `jwcode` 和 `username` 字段 |
||||
|
|
||||
|
## 后端接口要求 |
||||
|
|
||||
|
### 抽奖接口 `/lottery/draw` |
||||
|
|
||||
|
**请求参数:** |
||||
|
```json |
||||
|
{ |
||||
|
"gradeName": "一等奖", |
||||
|
"prizeName": "iPhone 15", |
||||
|
"perWin": 5, |
||||
|
"round": 1 |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
**返回数据格式:** |
||||
|
```json |
||||
|
{ |
||||
|
"data": [ |
||||
|
{ |
||||
|
"jwcode": "5412", |
||||
|
"username": "猪八戒22" |
||||
|
}, |
||||
|
{ |
||||
|
"jwcode": "45125", |
||||
|
"username": "宝玉" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 工作流程 |
||||
|
|
||||
|
1. **初始化**:页面加载时获取奖品列表和用户列表 |
||||
|
2. **开始抽奖**:用户点击抽奖按钮 |
||||
|
3. **请求后端**:发送抽奖请求到后端,包含奖项信息和轮次 |
||||
|
4. **获取结果**:后端返回中奖用户列表 |
||||
|
5. **显示动画**:前端根据返回的中奖用户显示3D抽奖动画 |
||||
|
6. **保存结果**:将中奖用户保存到本地状态 |
||||
|
|
||||
|
## 错误处理 |
||||
|
|
||||
|
如果后端抽奖接口请求失败,系统会自动回退到前端随机抽奖逻辑,确保抽奖功能不会中断。 |
||||
|
|
||||
|
## 兼容性 |
||||
|
|
||||
|
修改后的代码保持了与原有数据格式的兼容性,支持新旧两种数据格式: |
||||
|
- 新格式:`{ jwcode: "5412", username: "猪八戒22" }` |
||||
|
- 旧格式:`["5412", "猪八戒22", "PSST"]` |
@ -0,0 +1,113 @@ |
|||||
|
# 抽奖逻辑测试用例 |
||||
|
|
||||
|
## 测试环境准备 |
||||
|
|
||||
|
1. 确保后端服务正常运行 |
||||
|
2. 确保以下接口可用: |
||||
|
- `/prize/list` - 获取奖品列表 |
||||
|
- `/user/list` - 获取用户列表 |
||||
|
- `/lottery/draw` - 抽奖接口(新增) |
||||
|
|
||||
|
## 测试用例 |
||||
|
|
||||
|
### 测试用例1:正常抽奖流程 |
||||
|
|
||||
|
**测试步骤:** |
||||
|
1. 打开抽奖页面 |
||||
|
2. 点击"进入抽奖"按钮 |
||||
|
3. 点击"开始抽奖"按钮 |
||||
|
4. 点击"结束抽奖"按钮 |
||||
|
5. 观察抽奖结果 |
||||
|
|
||||
|
**预期结果:** |
||||
|
- 页面正常加载,显示奖品列表和用户卡片 |
||||
|
- 抽奖动画正常播放 |
||||
|
- 后端返回中奖用户数据 |
||||
|
- 3D卡片正确显示中奖用户信息(jwcode和username) |
||||
|
|
||||
|
### 测试用例2:后端接口异常处理 |
||||
|
|
||||
|
**测试步骤:** |
||||
|
1. 模拟后端抽奖接口返回错误 |
||||
|
2. 执行抽奖流程 |
||||
|
3. 观察系统行为 |
||||
|
|
||||
|
**预期结果:** |
||||
|
- 系统自动回退到前端随机抽奖逻辑 |
||||
|
- 抽奖功能不中断 |
||||
|
- 控制台显示错误日志 |
||||
|
|
||||
|
### 测试用例3:数据格式兼容性 |
||||
|
|
||||
|
**测试步骤:** |
||||
|
1. 使用新数据格式:`{ jwcode: "5412", username: "猪八戒22" }` |
||||
|
2. 使用旧数据格式:`["5412", "猪八戒22", "PSST"]` |
||||
|
3. 观察显示效果 |
||||
|
|
||||
|
**预期结果:** |
||||
|
- 两种数据格式都能正确显示 |
||||
|
- 卡片内容包含jwcode和username信息 |
||||
|
|
||||
|
### 测试用例4:多轮抽奖 |
||||
|
|
||||
|
**测试步骤:** |
||||
|
1. 完成第一轮抽奖 |
||||
|
2. 继续第二轮抽奖 |
||||
|
3. 观察轮次信息是否正确传递 |
||||
|
|
||||
|
**预期结果:** |
||||
|
- 每轮抽奖都请求后端 |
||||
|
- 轮次信息正确递增 |
||||
|
- 中奖用户不重复 |
||||
|
|
||||
|
### 测试用例5:奖品切换 |
||||
|
|
||||
|
**测试步骤:** |
||||
|
1. 完成当前奖品的所有轮次抽奖 |
||||
|
2. 观察是否自动切换到下一个奖品 |
||||
|
3. 验证新奖品的抽奖逻辑 |
||||
|
|
||||
|
**预期结果:** |
||||
|
- 奖品自动切换 |
||||
|
- 新奖品的抽奖参数正确传递 |
||||
|
- 轮次重新开始计算 |
||||
|
|
||||
|
## 调试信息 |
||||
|
|
||||
|
在浏览器控制台中查看以下日志: |
||||
|
|
||||
|
1. **用户数据加载:** |
||||
|
``` |
||||
|
userList {data: Array(5)} |
||||
|
``` |
||||
|
|
||||
|
2. **抽奖请求:** |
||||
|
``` |
||||
|
请求后端抽奖,参数: {gradeName: "一等奖", prizeName: "iPhone 15", perWin: 5, round: 1} |
||||
|
``` |
||||
|
|
||||
|
3. **后端返回结果:** |
||||
|
``` |
||||
|
后端抽奖返回结果: {data: Array(5)} |
||||
|
后端返回的中奖用户: [{jwcode: "5412", username: "猪八戒22"}, ...] |
||||
|
``` |
||||
|
|
||||
|
4. **卡片选择:** |
||||
|
``` |
||||
|
executeLottery - selectedCardIndex: [12, 34, 56, 78, 90] |
||||
|
executeLottery - currentLuckys: [{jwcode: "5412", username: "猪八戒22"}, ...] |
||||
|
``` |
||||
|
|
||||
|
## 常见问题排查 |
||||
|
|
||||
|
### 问题1:抽奖接口404错误 |
||||
|
**解决方案:** 检查后端是否实现了 `/lottery/draw` 接口 |
||||
|
|
||||
|
### 问题2:数据格式不匹配 |
||||
|
**解决方案:** 检查后端返回的数据格式是否符合 `{data: [{jwcode: "xxx", username: "xxx"}]}` |
||||
|
|
||||
|
### 问题3:用户数据为空 |
||||
|
**解决方案:** 检查 `/user/list` 接口是否正常返回数据 |
||||
|
|
||||
|
### 问题4:奖品数据为空 |
||||
|
**解决方案:** 检查 `/prize/list` 接口是否正常返回数据 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue