GLM-5 创意体验营 | 我用 HTML5 实现了 年会抽奖系统
本文介绍了一个基于GLM-5模型开发的年会抽奖系统,采用纯前端技术(HTML5+CSS3+JavaScript)实现。系统支持1-10个奖项等级,可随机抽取74名获奖者,具有真随机算法、实时显示、名单导入导出等功能。项目通过AtomGit平台向GLM-5提出需求后自动生成完整代码,包含精美UI设计、响应式布局和动画效果,无需后端即可单文件部署。系统操作简单,适合年会、团建等场景使用,并提供了完整的
本文参与 AtomGit 「0daymodel」首发模型体验活动,聚焦 GLM-5 在前端开发中的实际赋能。
相关链接:
一、项目背景
# 🎉 年会抽奖系统
一个简单易用的年会抽奖网页应用,支持1-10等奖的抽奖功能,适合公司年会、团建活动等场景使用。
## ✨ 功能特点
- 🎯 支持1-10等奖,共10个奖项等级
- 🎲 真随机抽奖算法,公平公正
- 📊 实时显示中奖名单和剩余人数
- 💾 支持导入自定义人员名单(JSON格式)
- 📤 支持导出抽奖结果
- 🎨 精美的动画效果和渐变背景
- 📱 响应式设计,支持各种屏幕尺寸
- 🚀 单文件部署,无需后端服务器
## 🎁 奖项设置
| 奖项 | 人数 |
|------|------|
| 一等奖 | 2人 |
| 二等奖 | 3人 |
| 三等奖 | 4人 |
| 四等奖 | 5人 |
| 五等奖 | 6人 |
| 六等奖 | 7人 |
| 七等奖 | 8人 |
| 八等奖 | 9人 |
| 九等奖 | 10人 |
| 十等奖 | 20人 |
**总计:74人**
## 🚀 快速开始
### 方法一:直接使用
1. 下载 `lottery.html` 文件
2. 双击打开文件,即可在浏览器中使用
3. 系统默认包含100人的示例名单(员工001-员工100)
### 方法二:自定义人员名单
1. 准备人员名单JSON文件(参考下方格式)
2. 打开 `lottery.html`
3. 点击"导入人员名单"按钮,选择你的JSON文件
4. 开始抽奖
### 人员名单格式
创建一个 `participants.json` 文件,格式如下:
```json
[
"张三",
"李四",
"王五",
"赵六",
"..."
]
```
**注意:** 必须是JSON数组格式,每个元素是一个字符串(人员姓名)。
## 📖 使用说明
### 1. 选择奖项
点击对应的奖项按钮(如"一等奖 (2人)"),按钮会高亮显示。
### 2. 开始抽奖
点击"开始抽奖"按钮,屏幕上会快速滚动显示随机名字。
### 3. 停止抽奖
再次点击"停止"按钮,系统会随机选出获奖者并显示在屏幕上。
### 4. 查看结果
所有中奖名单会实时显示在页面下方的"中奖名单"区域。
### 5. 导出结果
抽奖完成后,点击"导出结果"按钮,可以下载包含所有中奖信息的JSON文件。
### 6. 重置抽奖
如需重新开始,点击"重置抽奖"按钮,所有数据将被清空。
## 🎮 操作流程
```
导入人员名单(可选)
↓
选择奖项(如:一等奖)
↓
点击"开始抽奖"
↓
点击"停止"确定获奖者
↓
继续抽取其他奖项
↓
导出结果(可选)
```
## 💡 使用技巧
1. **建议抽奖顺序**:从一等奖开始抽,逐级往下,营造悬念感
2. **大屏幕展示**:使用投影仪或大屏幕展示,效果更佳
3. **全屏模式**:按 `F11` 进入全屏模式,获得更好的视觉效果
4. **音效配合**:可以配合背景音乐使用,增强现场气氛
5. **备份结果**:抽奖完成后及时导出结果,避免误操作丢失数据
## 🔧 技术栈
- 纯HTML5 + CSS3 + JavaScript
- 无任何第三方依赖
- 无需Node.js或其他运行环境
- 无需后端服务器
## 📂 文件说明
```
.
├── lottery.html # 抽奖系统主文件(包含所有代码)
├── README.md # 说明文档
└── participants.json # 人员名单示例(可选)
```
二、AI 赋能:向 GLM-5 提出需求
我在 AtomGit AI 平台 向最新发布的 GLM-5 模型提出具体开发需求:
帮我生成一个在年会上使用的抽奖页面(包含完整代码),分别抽取1-10等奖,1等奖2人,2等奖3人,3等奖4人,4等奖5人,5等奖6人,6等奖7人,7等奖8人,8等奖9人,9等奖10人,10等奖20人,随机导入100人,并包含几等奖提示以及中奖的人数,同时生成对应的README,让我可以直接发布github

图:GLM-5 在 AtomGit AI 平台给出的初始实现建议
三、代码内容
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>年会抽奖系统</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
color: #fff;
}
.container {
max-width: 1200px;
width: 100%;
}
h1 {
text-align: center;
font-size: 3em;
margin: 30px 0;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
animation: glow 2s ease-in-out infinite alternate;
}
@keyframes glow {
from { text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #e60073; }
to { text-shadow: 0 0 20px #fff, 0 0 30px #ff4da6, 0 0 40px #ff4da6; }
}
.control-panel {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.prize-selector {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
}
.prize-btn {
padding: 12px 24px;
font-size: 16px;
border: none;
border-radius: 8px;
cursor: pointer;
background: rgba(255, 255, 255, 0.2);
color: #fff;
transition: all 0.3s;
font-weight: bold;
}
.prize-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
.prize-btn.active {
background: #ff4757;
box-shadow: 0 4px 15px rgba(255, 71, 87, 0.4);
}
.prize-btn.completed {
background: #2ed573;
cursor: not-allowed;
}
.action-buttons {
display: flex;
gap: 15px;
justify-content: center;
margin-top: 20px;
}
.btn {
padding: 15px 40px;
font-size: 18px;
border: none;
border-radius: 10px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.btn-start {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: #fff;
}
.btn-start:hover {
transform: scale(1.05);
}
.btn-start:disabled {
background: #ccc;
cursor: not-allowed;
transform: none;
}
.btn-reset {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: #fff;
}
.btn-export {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
color: #fff;
}
.display-area {
background: rgba(255, 255, 255, 0.95);
border-radius: 15px;
padding: 40px;
margin-bottom: 30px;
min-height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.current-prize {
font-size: 2.5em;
color: #ff4757;
margin-bottom: 20px;
font-weight: bold;
}
.rolling-names {
font-size: 3em;
color: #2f3542;
font-weight: bold;
min-height: 100px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 20px;
}
.winner-name {
animation: bounce 0.5s;
padding: 10px 20px;
background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
.results-panel {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 30px;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.results-title {
font-size: 2em;
margin-bottom: 20px;
text-align: center;
}
.prize-result {
background: rgba(255, 255, 255, 0.1);
border-radius: 10px;
padding: 15px;
margin-bottom: 15px;
}
.prize-result h3 {
color: #ffd700;
margin-bottom: 10px;
font-size: 1.3em;
}
.prize-result .winners {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.winner-tag {
background: rgba(255, 255, 255, 0.2);
padding: 8px 15px;
border-radius: 20px;
font-size: 0.9em;
}
.stats {
text-align: center;
margin-top: 20px;
font-size: 1.1em;
opacity: 0.9;
}
.file-upload {
margin-bottom: 20px;
text-align: center;
}
.file-upload input {
display: none;
}
.file-upload label {
padding: 10px 20px;
background: rgba(255, 255, 255, 0.2);
border-radius: 8px;
cursor: pointer;
display: inline-block;
transition: all 0.3s;
}
.file-upload label:hover {
background: rgba(255, 255, 255, 0.3);
}
</style>
</head>
<body>
<div class="container">
<h1>🎉 年会抽奖系统 🎉</h1>
<div class="control-panel">
<div class="file-upload">
<label for="fileInput">📁 导入人员名单(JSON格式)</label>
<input type="file" id="fileInput" accept=".json">
<span id="fileStatus" style="margin-left: 15px;"></span>
</div>
<div class="prize-selector" id="prizeSelector"></div>
<div class="action-buttons">
<button class="btn btn-start" id="startBtn" onclick="startLottery()">开始抽奖</button>
<button class="btn btn-reset" onclick="resetLottery()">重置抽奖</button>
<button class="btn btn-export" onclick="exportResults()">导出结果</button>
</div>
</div>
<div class="display-area">
<div class="current-prize" id="currentPrize">请选择奖项</div>
<div class="rolling-names" id="rollingNames"></div>
</div>
<div class="results-panel">
<h2 class="results-title">🏆 中奖名单 🏆</h2>
<div id="resultsContainer"></div>
<div class="stats" id="stats"></div>
</div>
</div>
<script>
// 奖项配置
const prizeConfig = [
{ level: 1, name: '一等奖', count: 2, color: '#ff4757' },
{ level: 2, name: '二等奖', count: 3, color: '#ff6348' },
{ level: 3, name: '三等奖', count: 4, color: '#ff7f50' },
{ level: 4, name: '四等奖', count: 5, color: '#ffa502' },
{ level: 5, name: '五等奖', count: 6, color: '#ffb142' },
{ level: 6, name: '六等奖', count: 7, color: '#ffd93d' },
{ level: 7, name: '七等奖', count: 8, color: '#6bcf7f' },
{ level: 8, name: '八等奖', count: 9, color: '#4bcffa' },
{ level: 9, name: '九等奖', count: 10, color: '#5f27cd' },
{ level: 10, name: '十等奖', count: 20, color: '#c44569' }
];
// 默认人员名单(100人)
let allParticipants = [];
for (let i = 1; i <= 100; i++) {
allParticipants.push(`员工${i.toString().padStart(3, '0')}`);
}
let availableParticipants = [...allParticipants];
let currentPrizeIndex = null;
let isRolling = false;
let rollingInterval = null;
let results = {};
// 初始化
function init() {
renderPrizeButtons();
updateResults();
updateStats();
}
// 渲染奖项按钮
function renderPrizeButtons() {
const container = document.getElementById('prizeSelector');
container.innerHTML = '';
prizeConfig.forEach((prize, index) => {
const btn = document.createElement('button');
btn.className = 'prize-btn';
btn.textContent = `${prize.name} (${prize.count}人)`;
btn.onclick = () => selectPrize(index);
if (results[prize.level] && results[prize.level].length === prize.count) {
btn.classList.add('completed');
btn.disabled = true;
}
container.appendChild(btn);
});
}
// 选择奖项
function selectPrize(index) {
if (isRolling) return;
currentPrizeIndex = index;
const prize = prizeConfig[index];
// 更新按钮状态
document.querySelectorAll('.prize-btn').forEach((btn, i) => {
btn.classList.toggle('active', i === index);
});
document.getElementById('currentPrize').textContent =
`${prize.name} - 抽取 ${prize.count} 人`;
document.getElementById('rollingNames').textContent = '';
document.getElementById('startBtn').disabled = false;
}
// 开始抽奖
function startLottery() {
if (currentPrizeIndex === null) {
alert('请先选择奖项!');
return;
}
if (isRolling) {
stopLottery();
return;
}
const prize = prizeConfig[currentPrizeIndex];
if (availableParticipants.length < prize.count) {
alert('剩余人数不足!');
return;
}
isRolling = true;
document.getElementById('startBtn').textContent = '停止';
// 滚动显示随机名字
rollingInterval = setInterval(() => {
const randomNames = [];
for (let i = 0; i < prize.count; i++) {
const randomIndex = Math.floor(Math.random() * availableParticipants.length);
randomNames.push(availableParticipants[randomIndex]);
}
document.getElementById('rollingNames').innerHTML =
randomNames.map(name => `<span class="winner-name">${name}</span>`).join('');
}, 100);
}
// 停止抽奖
function stopLottery() {
if (!isRolling) return;
clearInterval(rollingInterval);
isRolling = false;
document.getElementById('startBtn').textContent = '开始抽奖';
const prize = prizeConfig[currentPrizeIndex];
const winners = [];
// 随机抽取获奖者
for (let i = 0; i < prize.count; i++) {
const randomIndex = Math.floor(Math.random() * availableParticipants.length);
winners.push(availableParticipants[randomIndex]);
availableParticipants.splice(randomIndex, 1);
}
// 保存结果
results[prize.level] = winners;
// 显示获奖者
document.getElementById('rollingNames').innerHTML =
winners.map(name => `<span class="winner-name">${name}</span>`).join('');
// 更新界面
renderPrizeButtons();
updateResults();
updateStats();
// 重置选择
setTimeout(() => {
currentPrizeIndex = null;
document.querySelectorAll('.prize-btn').forEach(btn => {
btn.classList.remove('active');
});
document.getElementById('currentPrize').textContent = '请选择下一个奖项';
document.getElementById('startBtn').disabled = true;
}, 3000);
}
// 更新结果显示
function updateResults() {
const container = document.getElementById('resultsContainer');
container.innerHTML = '';
prizeConfig.forEach(prize => {
if (results[prize.level] && results[prize.level].length > 0) {
const div = document.createElement('div');
div.className = 'prize-result';
div.innerHTML = `
<h3>${prize.name} (${results[prize.level].length}/${prize.count}人)</h3>
<div class="winners">
${results[prize.level].map(name =>
`<span class="winner-tag">${name}</span>`
).join('')}
</div>
`;
container.appendChild(div);
}
});
}
// 更新统计信息
function updateStats() {
const totalWinners = Object.values(results).reduce((sum, arr) => sum + arr.length, 0);
const totalPrizes = prizeConfig.reduce((sum, prize) => sum + prize.count, 0);
document.getElementById('stats').textContent =
`已抽取: ${totalWinners}/${totalPrizes} 人 | 剩余: ${availableParticipants.length} 人`;
}
// 重置抽奖
function resetLottery() {
if (!confirm('确定要重置所有抽奖结果吗?')) return;
availableParticipants = [...allParticipants];
results = {};
currentPrizeIndex = null;
isRolling = false;
if (rollingInterval) {
clearInterval(rollingInterval);
}
document.getElementById('currentPrize').textContent = '请选择奖项';
document.getElementById('rollingNames').textContent = '';
document.getElementById('startBtn').textContent = '开始抽奖';
document.getElementById('startBtn').disabled = true;
renderPrizeButtons();
updateResults();
updateStats();
}
// 导出结果
function exportResults() {
const exportData = {
timestamp: new Date().toLocaleString('zh-CN'),
totalParticipants: allParticipants.length,
results: {}
};
prizeConfig.forEach(prize => {
if (results[prize.level]) {
exportData.results[prize.name] = results[prize.level];
}
});
const dataStr = JSON.stringify(exportData, null, 2);
const blob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `抽奖结果_${new Date().getTime()}.json`;
a.click();
URL.revokeObjectURL(url);
}
// 文件上传
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(event) {
try {
const data = JSON.parse(event.target.result);
if (Array.isArray(data) && data.length > 0) {
allParticipants = data;
availableParticipants = [...allParticipants];
results = {};
updateStats();
document.getElementById('fileStatus').textContent =
`✅ 已导入 ${allParticipants.length} 人`;
document.getElementById('fileStatus').style.color = '#2ed573';
} else {
throw new Error('格式错误');
}
} catch (error) {
alert('文件格式错误!请上传正确的JSON数组格式。');
document.getElementById('fileStatus').textContent = '❌ 导入失败';
document.getElementById('fileStatus').style.color = '#ff4757';
}
};
reader.readAsText(file);
});
// 页面加载时初始化
init();
</script>
</body>
</html>
四、项目开源
- 源码地址:https://atomgit.com/2302_77582029/test
- 技术栈:HTML5 + CSS3 + 原生JavaScript (ES6+)
- 适用场景:年会公司抽奖使用
参与说明:本文为 AtomGit「0daymodel」GLM-5 首发体验活动投稿。
⭐ 如果这个项目对你有帮助,欢迎给个Star!
🎊 祝你的年会圆满成功!
更多推荐





所有评论(0)