mirror of
https://github.com/NeteaseCloudMusicApiEnhanced/api-enhanced.git
synced 2026-08-12 08:50:38 +00:00
Merge pull request #215 from ZxwyWebSite/feat-lottery
This commit is contained in:
parent
fda7c9e5b3
commit
9adfd50c58
@ -1,30 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes">
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="referrer" content="no-referrer" />
|
||||
<link rel="icon" href="docs/netease.png" />
|
||||
<title>云小编每日抽奖 - 网易云音乐 API Enhanced</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-start: #f3f0ff;
|
||||
--bg-end: #e8f4fd;
|
||||
--primary: #7c6cf0;
|
||||
--primary-light: #ede9fe;
|
||||
--accent: #fd79a8;
|
||||
--gold: #fdcb6e;
|
||||
--text: #2d3436;
|
||||
--text-light: #636e72;
|
||||
--card-bg: #ffffff;
|
||||
--border: #e8e8f0;
|
||||
--shadow: 0 8px 30px rgba(108, 92, 231, 0.08);
|
||||
--radius: 20px;
|
||||
--radius-sm: 12px;
|
||||
--transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@ -32,135 +15,269 @@
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', system-ui, -apple-system, 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||||
background: linear-gradient(135deg, var(--bg-start) 0%, var(--bg-end) 50%, #fce4ec 100%);
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1.5rem;
|
||||
color: var(--text);
|
||||
line-height: 1.5;
|
||||
background: #f5f5f5;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 520px;
|
||||
margin: 40px auto;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 32px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.subtitle b {
|
||||
color: #d63031;
|
||||
}
|
||||
|
||||
/* ---- Section ---- */
|
||||
.section {
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.section:last-of-type {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
/* 标题编辑卡片 */
|
||||
.card {
|
||||
background: var(--card-bg);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.8rem 2rem;
|
||||
box-shadow: var(--shadow);
|
||||
border: 1px solid var(--border);
|
||||
transition: var(--transition);
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.title-section {
|
||||
text-align: center;
|
||||
/* ---- Form Elements ---- */
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.title-input {
|
||||
label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
label .tag {
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
padding: 1px 6px;
|
||||
border-radius: 3px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
label .tag.o {
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
textarea {
|
||||
width: 100%;
|
||||
border: 2px solid transparent;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
padding: 0.6rem 1rem;
|
||||
color: var(--text);
|
||||
background: #fafafa;
|
||||
transition: var(--transition);
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.title-input:hover {
|
||||
background: #f5f3ff;
|
||||
input[type="text"]:focus,
|
||||
input[type="number"]:focus,
|
||||
textarea:focus {
|
||||
border-color: #333;
|
||||
}
|
||||
|
||||
.title-input:focus {
|
||||
border-color: var(--primary-light);
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 4px rgba(124, 108, 240, 0.06);
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.title-hint {
|
||||
font-size: 0.8rem;
|
||||
color: #b2bec3;
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
|
||||
/* 抽奖主卡片 */
|
||||
.lottery-card {
|
||||
background: var(--card-bg);
|
||||
border-radius: var(--radius);
|
||||
padding: 2rem 2rem 2.2rem;
|
||||
box-shadow: var(--shadow);
|
||||
border: 1px solid var(--border);
|
||||
.btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: #333;
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
border: none;
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
padding: 6px 16px;
|
||||
background: #333;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
border: none;
|
||||
text-align: center;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.btn-sm:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
.btn-sm:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-sm.gray {
|
||||
background: #6b7280;
|
||||
}
|
||||
|
||||
.btn-sm.gray:hover {
|
||||
background: #4b5563;
|
||||
}
|
||||
|
||||
.btn-sm.gray:disabled {
|
||||
background: #d1d5db;
|
||||
}
|
||||
|
||||
.btn-sm.green {
|
||||
background: #059669;
|
||||
}
|
||||
|
||||
.btn-sm.green:hover {
|
||||
background: #047857;
|
||||
}
|
||||
|
||||
.btn-sm.green:disabled {
|
||||
background: #a7f3d0;
|
||||
}
|
||||
|
||||
.quick-fill {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.quick-fill span {
|
||||
color: #0066cc;
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.quick-fill span:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ---- Lottery Display ---- */
|
||||
.lottery-display {
|
||||
text-align: center;
|
||||
padding: 24px 16px;
|
||||
background: #f9fafb;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.rolling-display {
|
||||
font-size: 2.4rem;
|
||||
font-weight: 800;
|
||||
color: var(--primary);
|
||||
color: #333;
|
||||
min-height: 4rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
letter-spacing: 1px;
|
||||
margin: 0.5rem 0 1rem;
|
||||
word-break: break-all;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.rolling-display.idle {
|
||||
color: #c4b5fd;
|
||||
font-size: 1.3rem;
|
||||
color: #999;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 结果展示 */
|
||||
/* ---- Winner Result ---- */
|
||||
.winner-display {
|
||||
background: linear-gradient(135deg, #fff9e6, #fff3cd);
|
||||
border: 2px solid var(--gold);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.5rem;
|
||||
margin: 1rem 0 1.5rem;
|
||||
animation: popIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
background: #f0fdf4;
|
||||
border: 1px solid #86efac;
|
||||
border-radius: 8px;
|
||||
padding: 20px 16px;
|
||||
margin-top: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.winner-label {
|
||||
font-size: 0.85rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1.5px;
|
||||
color: #b8860b;
|
||||
margin-bottom: 0.3rem;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #065f46;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.winner-name {
|
||||
font-size: 2.2rem;
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
color: #d63031;
|
||||
color: #dc2626;
|
||||
letter-spacing: 1px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.confetti-row {
|
||||
margin-top: 0.5rem;
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.confetti-emoji {
|
||||
font-size: 1.8rem;
|
||||
font-size: 1.6rem;
|
||||
animation: bounce 0.6s ease infinite alternate;
|
||||
}
|
||||
|
||||
@ -172,130 +289,78 @@
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
@keyframes popIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.7);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
from {
|
||||
transform: translateY(0);
|
||||
from { transform: translateY(0); }
|
||||
to { transform: translateY(-8px); }
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
}
|
||||
|
||||
/* 按钮 */
|
||||
.btn {
|
||||
padding: 0.9rem 2.5rem;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
font-weight: 700;
|
||||
font-size: 1.05rem;
|
||||
cursor: pointer;
|
||||
transition: var(--transition);
|
||||
letter-spacing: 0.5px;
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.btn-lottery {
|
||||
background: linear-gradient(135deg, #fd79a8, #e84393);
|
||||
color: #fff;
|
||||
box-shadow: 0 6px 20px rgba(253, 121, 168, 0.35);
|
||||
}
|
||||
|
||||
.btn-lottery:hover:not(:disabled) {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 28px rgba(253, 121, 168, 0.45);
|
||||
}
|
||||
|
||||
.btn-lottery:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.btn-lottery:disabled {
|
||||
background: #b2bec3;
|
||||
box-shadow: none;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.btn-reset {
|
||||
background: transparent;
|
||||
border: 2px solid var(--border);
|
||||
color: var(--text-light);
|
||||
margin-top: 0.8rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.btn-reset:hover {
|
||||
border-color: var(--primary-light);
|
||||
color: var(--primary);
|
||||
background: #f8f7ff;
|
||||
}
|
||||
|
||||
/* 状态提示 */
|
||||
/* ---- Status ---- */
|
||||
.status-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-light);
|
||||
margin-top: 1rem;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
background: #f9fafb;
|
||||
border-radius: 6px;
|
||||
margin-top: 16px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #00b894;
|
||||
background: #059669;
|
||||
flex-shrink: 0;
|
||||
animation: pulse 1.5s ease infinite;
|
||||
}
|
||||
|
||||
.status-dot.error {
|
||||
background: #e17055;
|
||||
background: #dc2626;
|
||||
}
|
||||
|
||||
.status-dot.idle {
|
||||
background: #9ca3af;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.4; }
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.status-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 响应式 */
|
||||
/* ---- Footer ---- */
|
||||
.footer-link {
|
||||
text-align: center;
|
||||
margin-top: 24px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #eee;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.footer-link a {
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-link a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ---- Responsive ---- */
|
||||
@media (max-width: 500px) {
|
||||
|
||||
.card,
|
||||
.lottery-card {
|
||||
padding: 1.4rem 1.2rem;
|
||||
.container {
|
||||
padding: 20px 16px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
.title-input {
|
||||
font-size: 1.3rem;
|
||||
h1 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.rolling-display {
|
||||
@ -304,7 +369,7 @@
|
||||
}
|
||||
|
||||
.winner-name {
|
||||
font-size: 1.7rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -312,37 +377,56 @@
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- 标题编辑区 -->
|
||||
<div class="card title-section">
|
||||
<input type="text" class="title-input" id="titleInput" value="🎉 云小编每日抽奖 🎉" autocomplete="off" disabled>
|
||||
<div class="title-hint">每次抽奖消耗 <b>200 个曲库编辑部积分</b>,每日最多可抽奖 3 次</div>
|
||||
<h1>云小编每日抽奖</h1>
|
||||
<p class="subtitle">每次抽奖消耗 <b>200 个曲库编辑部积分</b>,每日最多可抽奖 3 次</p>
|
||||
|
||||
<!-- Cookie 管理 -->
|
||||
<div class="form-group">
|
||||
<label for="cookieInput">令牌 <span class="tag o">可选</span></label>
|
||||
<input type="text" id="cookieInput" placeholder="留空则默认读取本地存储的令牌" autocomplete="off" />
|
||||
<div class="quick-fill">
|
||||
<span onclick="readLocalCookie()">读取本地令牌</span>
|
||||
<span onclick="clearCookie()">清除令牌</span>
|
||||
<span onclick="saveCookie()">保存令牌</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 抽奖主区域 -->
|
||||
<div class="lottery-card">
|
||||
<!-- 抽奖区域 -->
|
||||
<div class="section">
|
||||
<div class="section-header">
|
||||
<span class="section-title">每日抽奖</span>
|
||||
</div>
|
||||
|
||||
<div class="lottery-display">
|
||||
<div class="rolling-display idle" id="rollingDisplay">等待抽奖</div>
|
||||
<div id="resultContainer"></div>
|
||||
<button class="btn btn-lottery" id="lotteryBtn">
|
||||
<span>🎲</span> 开始抽奖
|
||||
</button>
|
||||
<button class="btn btn-reset" id="resetBtn">
|
||||
<span>🔄</span> 编辑令牌
|
||||
</button>
|
||||
<div class="status-bar" id="statusBar">
|
||||
<span class="status-dot" id="statusDot"></span>
|
||||
<span id="statusText">就绪,点击按钮开始抽奖</span>
|
||||
</div>
|
||||
|
||||
<button class="btn" id="lotteryBtn">
|
||||
🎲 开始抽奖
|
||||
</button>
|
||||
|
||||
<div class="status-bar" id="statusBar">
|
||||
<span class="status-dot idle" id="statusDot"></span>
|
||||
<span class="status-text" id="statusText">就绪,点击按钮开始抽奖</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 页脚 -->
|
||||
<div class="footer-link">
|
||||
<a href="/">← 返回首页</a>
|
||||
<span style="margin: 0 8px; color: #ddd;">·</span>
|
||||
<a href="/ugc.html">云小编任务中心</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
// ============ DOM 元素 ============
|
||||
const titleInput = document.getElementById('titleInput');
|
||||
const cookieInput = document.getElementById('cookieInput');
|
||||
const rollingDisplay = document.getElementById('rollingDisplay');
|
||||
const resultContainer = document.getElementById('resultContainer');
|
||||
const lotteryBtn = document.getElementById('lotteryBtn');
|
||||
const resetBtn = document.getElementById('resetBtn');
|
||||
const statusDot = document.getElementById('statusDot');
|
||||
const statusText = document.getElementById('statusText');
|
||||
|
||||
@ -356,6 +440,10 @@
|
||||
statusDot.className = 'status-dot';
|
||||
if (type === 'error') {
|
||||
statusDot.classList.add('error');
|
||||
} else if (type === 'info') {
|
||||
statusDot.style.background = '#059669';
|
||||
} else {
|
||||
statusDot.classList.add('idle');
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,30 +452,63 @@
|
||||
resultContainer.innerHTML = '';
|
||||
rollingDisplay.textContent = '等待抽奖';
|
||||
rollingDisplay.className = 'rolling-display idle';
|
||||
setStatus('info', '就绪,点击按钮开始抽奖');
|
||||
setStatus('idle', '就绪,点击按钮开始抽奖');
|
||||
}
|
||||
|
||||
// ============ 本地令牌管理 ============
|
||||
const cookieKey = 'ncm_cookie';
|
||||
let cookie = localStorage.getItem(cookieKey) || '';
|
||||
function setCookie() {
|
||||
const ck = prompt('请输入令牌:', cookie);
|
||||
if (ck !== null) {
|
||||
cookie = ck;
|
||||
localStorage.setItem(cookieKey, cookie);
|
||||
if (cookie) {
|
||||
cookieInput.value = cookie;
|
||||
}
|
||||
|
||||
window.readLocalCookie = function () {
|
||||
const local = localStorage.getItem(cookieKey);
|
||||
if (local) {
|
||||
cookie = local;
|
||||
cookieInput.value = local;
|
||||
setStatus('info', '已读取本地令牌');
|
||||
} else {
|
||||
setStatus('error', '未在本地发现令牌,请手动输入');
|
||||
}
|
||||
};
|
||||
|
||||
window.clearCookie = function () {
|
||||
cookie = '';
|
||||
cookieInput.value = '';
|
||||
localStorage.removeItem(cookieKey);
|
||||
setStatus('info', '已清除本地令牌');
|
||||
};
|
||||
|
||||
window.saveCookie = function () {
|
||||
const ck = cookieInput.value.trim();
|
||||
if (ck) {
|
||||
cookie = ck;
|
||||
localStorage.setItem(cookieKey, ck);
|
||||
setStatus('info', '已保存本地令牌');
|
||||
} else {
|
||||
setStatus('error', '令牌内容为空,未保存');
|
||||
}
|
||||
};
|
||||
|
||||
function getCookie() {
|
||||
const ck = cookieInput.value.trim();
|
||||
if (ck) cookie = ck;
|
||||
return ck || cookie || '';
|
||||
}
|
||||
|
||||
// ============ 调用后端接口 ============
|
||||
async function request(url, params) {
|
||||
try {
|
||||
url += '?timestamp=' + Date.now() + params;
|
||||
if (cookie) url += '&cookie=' + encodeURIComponent(cookie);
|
||||
const ck = getCookie();
|
||||
if (ck) url += '&cookie=' + encodeURIComponent(ck);
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
let res;
|
||||
try {
|
||||
var res = await response.json();
|
||||
res = await response.json();
|
||||
} catch (error) {
|
||||
console.error('数据解析错误:', error);
|
||||
throw new Error('接口请求错误: ' + response.status + ': ' + response.statusText);
|
||||
@ -419,13 +540,11 @@
|
||||
|
||||
const res = await request('middle/play/do/lottery', '&activityId=6501202&drawCount=1');
|
||||
|
||||
// 根据你的后端返回格式提取中奖者名称
|
||||
const winner = res.data?.prizeDetailInfoMap?.['8186002']?.prizeName;
|
||||
if (!winner) {
|
||||
throw new Error('无法解析响应数据');
|
||||
}
|
||||
|
||||
// [抽奖结果, 剩余机会]
|
||||
return [winner, res.data.restChance];
|
||||
}
|
||||
|
||||
@ -446,12 +565,10 @@
|
||||
const easeOutProgress = 1 - Math.pow(1 - progress, 3);
|
||||
const currentInterval = startInterval + (endInterval - startInterval) * easeOutProgress;
|
||||
|
||||
// 随机显示占位符
|
||||
const randomPlaceholder = placeholderNames[Math.floor(Math.random() * placeholderNames.length)];
|
||||
rollingDisplay.textContent = randomPlaceholder;
|
||||
|
||||
if (progress >= 1.0) {
|
||||
// 动画结束,显示真实结果
|
||||
clearTimeout(rollingTimer);
|
||||
rollingDisplay.textContent = finalWinner;
|
||||
showWinnerResult(finalWinner);
|
||||
@ -466,17 +583,16 @@
|
||||
}
|
||||
|
||||
function showWinnerResult(winner) {
|
||||
resultContainer.innerHTML = `
|
||||
<div class="winner-display">
|
||||
<div class="winner-label">🏆 恭喜中奖</div>
|
||||
<div class="winner-name">${escapeHTML(winner)}</div>
|
||||
<div class="confetti-row">
|
||||
<span class="confetti-emoji">🎉</span>
|
||||
<span class="confetti-emoji">🎊</span>
|
||||
<span class="confetti-emoji">✨</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
resultContainer.innerHTML =
|
||||
'<div class="winner-display">' +
|
||||
'<div class="winner-label">🏆 恭喜中奖</div>' +
|
||||
'<div class="winner-name">' + escapeHTML(winner) + '</div>' +
|
||||
'<div class="confetti-row">' +
|
||||
'<span class="confetti-emoji">🎉</span>' +
|
||||
'<span class="confetti-emoji">🎊</span>' +
|
||||
'<span class="confetti-emoji">✨</span>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function escapeHTML(str) {
|
||||
@ -488,47 +604,37 @@
|
||||
function finishDrawing() {
|
||||
isDrawing = false;
|
||||
lotteryBtn.disabled = false;
|
||||
resetBtn.disabled = false;
|
||||
// setStatus('info', '抽奖完成!点击重置可再次抽奖');
|
||||
}
|
||||
|
||||
// ============ 主抽奖流程 ============
|
||||
async function startLottery() {
|
||||
if (isDrawing) return;
|
||||
|
||||
// 开始前状态
|
||||
isDrawing = true;
|
||||
lotteryBtn.disabled = true;
|
||||
resetBtn.disabled = true;
|
||||
resultContainer.innerHTML = '';
|
||||
rollingDisplay.className = 'rolling-display';
|
||||
rollingDisplay.textContent = '🎰';
|
||||
setStatus('info', '正在获取抽奖结果...');
|
||||
|
||||
try {
|
||||
// 调用后端接口获取中奖者
|
||||
const res = await fetchLotteryResult();
|
||||
setStatus('info', '抽奖成功,剩余次数 ' + res[1]);
|
||||
// 启动滚动动画,最终定格在中奖者
|
||||
startRollingAnimation(res[0]);
|
||||
} catch (error) {
|
||||
// 请求失败处理
|
||||
rollingDisplay.textContent = '抽奖失败';
|
||||
rollingDisplay.className = 'rolling-display idle';
|
||||
setStatus('error', '抽奖失败: ' + error.message);
|
||||
isDrawing = false;
|
||||
lotteryBtn.disabled = false;
|
||||
resetBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ============ 事件绑定 ============
|
||||
lotteryBtn.addEventListener('click', startLottery);
|
||||
resetBtn.addEventListener('click', setCookie);
|
||||
|
||||
// 空格键快捷抽奖
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === ' ' && document.activeElement !== titleInput) {
|
||||
document.addEventListener('keydown', function (e) {
|
||||
if (e.key === ' ' && document.activeElement !== cookieInput) {
|
||||
e.preventDefault();
|
||||
if (!isDrawing && !lotteryBtn.disabled) {
|
||||
startLottery();
|
||||
@ -536,6 +642,13 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 回车键在输入框中触发保存
|
||||
cookieInput.addEventListener('keypress', function (e) {
|
||||
if (e.key === 'Enter') {
|
||||
saveCookie();
|
||||
}
|
||||
});
|
||||
|
||||
// ============ 初始化 ============
|
||||
resetResult();
|
||||
})();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user