代码:
<!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>
:root {
--primary-color: #409EFF;
--success-color: #67C23A;
--bg-color: #f5f7fa;
--card-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
--border-color: #DCDFE6;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.container {
background: white;
padding: 40px 50px;
border-radius: 12px;
box-shadow: var(--card-shadow);
transition: all 0.3s ease;
min-width: 500px;
}
h1 {
color: #303133;
margin: 0 0 30px 0;
font-weight: 500;
position: relative;
padding-bottom: 15px;
}
h1::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 50px;
height: 3px;
background: var(--primary-color);
border-radius: 2px;
}
input[type="number"] {
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 10px 15px;
width: 140px;
transition: all 0.3s;
font-size: 1.1rem;
}
input[type="number"]:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
outline: none;
}
select {
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 10px 35px 10px 15px;
background: white url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23999'%3e%3cpath d='M7 10l5 5 5-5z'/%3e%3c/svg%3e") no-repeat right 12px center/12px;
appearance: none;
font-size: 1.1rem;
}
.number {
font-size: 250pt;
width: 100%;
text-align: center;
border: none;
margin: 30px 0;
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
box-shadow: inset 0 4px 6px rgba(0, 0, 0, 0.05);
color: #2c3e50;
transition: all 0.3s;
}
.button-group {
display: flex;
gap: 15px;
justify-content: center;
margin-top: 20px;
}
button {
font-size: 1.5rem;
padding: 12px 30px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
border: 1px solid transparent;
position: relative;
overflow: hidden;
}
button.primary {
background: var(--primary-color);
color: white;
box-shadow: 0 4px 6px rgba(64, 158, 255, 0.2);
}
button.primary:hover {
background: #66b1ff;
transform: translateY(-1px);
}
button.secondary {
background: var(--bg-color);
color: #606266;
border-color: var(--border-color);
}
button.secondary:hover {
color: var(--primary-color);
border-color: #c6e2ff;
background: #ecf5ff;
}
label {
display: inline-block;
min-width: 80px;
text-align: right;
margin-right: 15px;
color: #606266;
font-size: 1.1rem;
}
.form-group {
margin: 25px 0;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
</head>
<body>
<div id="app" class="container">
<transition name="fade" mode="out-in">
<div v-if="isIndexPage" key="setup">
<h1>学号抽取设置</h1>
<div class="form-group">
<label for="start">起始学号:</label>
<input type="number" v-model.number="start" id="start" min="1">
</div>
<div class="form-group">
<label for="end">结束学号:</label>
<input type="number" v-model.number="end" id="end" :min="start">
</div>
<div class="form-group">
<label for="mode">抽取模式:</label>
<select v-model="mode" id="mode">
<option value="d">单次抽取模式</option>
<option value="s">快速抽取模式</option>
</select>
</div>
<div class="button-group">
<button class="primary" @click="validateAndNavigate">开始抽取</button>
</div>
</div>
<div v-else key="main">
<h1>学号抽取结果</h1>
<input class="number" type="text" v-model="currentNumber" readonly>
<div class="button-group">
<button v-if="mode === 'd'" class="primary" @click="drawNumber">抽取学号</button>
<button v-if="mode === 's'"
class="primary"
@click="toggleContinuous"
:class="{ 'stop-button': isContinuous }">
{
{ isContinuous ? '停止抽取' : '开始抽取' }}
</button>
<button class="secondary" @click="goBack">返回设置</button>
</div>
</div>
</transition>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
animationFrameId: null,
isContinuous: false,
start: 1,
end: 40,
mode: 'd',
currentNumber: '—',
isIndexPage: true
},
methods: {
getRandomNumber() {
return Math.floor(Math.random() * (this.end - this.start + 1)) + this.start;
},
drawNumber() {
this.currentNumber = this.getRandomNumber();
},
toggleContinuous() {
if (this.isContinuous) {
cancelAnimationFrame(this.animationFrameId);
// 不再将 currentNumber 设置为 '—',保留最后一个生成的学号
} else {
const animate = () => {
this.drawNumber();
this.animationFrameId = requestAnimationFrame(animate);
};
animate();
}
this.isContinuous = !this.isContinuous;
},
validateAndNavigate() {
if (this.start > this.end) {
alert('错误:起始学号不能大于结束学号');
return;
}
if (this.start < 1 || this.end < 1) {
alert('错误:学号不能小于1');
return;
}
const params = new URLSearchParams({
mode: this.mode,
start: this.start,
end: this.end
});
window.location.href = `${window.location.pathname}?${params}`;
},
goBack() {
window.location.href = window.location.pathname;
},
initializeParams() {
const params = new URLSearchParams(window.location.search);
if (params.has('start') && params.has('end') && params.has('mode')) {
const start = parseInt(params.get('start'), 10);
const end = parseInt(params.get('end'), 10);
if (!isNaN(start) && !isNaN(end) && start <= end) {
this.start = start;
this.end = end;
this.mode = params.get('mode');
this.isIndexPage = false;
}
}
}
},
mounted() {
this.initializeParams();
}
});
</script>
</body>
</html>