<!-- 本DIY代码来自于 https://diy.zhongzhipian.top -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>卡密验证 - 网易云音乐风格</title>
<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, #1e1e1e 0%, #000 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
color: #fff;
position: relative;
overflow-x: hidden;
}
/* 音乐图标 */
.music-icon {
width: 120px;
height: 120px;
border-radius: 50%;
object-fit: cover;
position: relative;
margin: 30px 0;
box-shadow: 0 0 30px rgba(230, 57, 70, 0.6);
cursor: pointer;
transition: all 0.3s;
border: 2px solid #e63946;
background-size: cover;
background-position: center;
background-color: #333;
z-index: 2;
}
.music-icon:hover {
transform: scale(1.05);
box-shadow: 0 0 40px rgba(230, 57, 70, 0.8);
}
/* 播放图标 */
.play-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 40px;
color: #fff;
opacity: 0.9;
transition: opacity 0.3s;
z-index: 1;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.music-icon:hover .play-icon {
opacity: 1;
}
/* 歌曲信息 */
.song-info {
text-align: center;
margin-bottom: 10px;
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.list-button {
margin-left: 10px;
cursor: pointer;
}
.header {
text-align: center;
margin-bottom: 20px;
width: 100%;
max-width: 500px;
pointer-events: none;
user-select: none;
}
#titleDisplay {
font-size: 28px;
font-weight: 700;
color: #e63946;
margin-bottom: 8px;
}
.notice-box {
width: 100%;
max-width: 500px;
background: rgba(255, 255, 255, 0.08);
backdrop-filter: blur(10px);
border-radius: 12px;
padding: 15px;
margin-bottom: 30px;
border-left: 4px solid #e63946;
position: relative;
z-index: 5;
}
#noticeDisplay {
font-size: 14px;
line-height: 1.6;
color: #f1f1f1;
}
.music-list {
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
width: 90%;
max-width: 400px;
background: rgba(30, 30, 30, 0.95);
backdrop-filter: blur(10px);
border-radius: 10px;
padding: 15px;
margin-top: 10px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
z-index: 20;
display: none;
max-height: 300px;
overflow-y: auto;
}
.music-list.active {
display: block;
}
.music-item {
padding: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
cursor: pointer;
transition: all 0.3s;
}
.music-item:hover {
background: rgba(230, 57, 70, 0.2);
}
.music-item.active {
background: rgba(230, 57, 70, 0.3);
color: #e63946;
}
.lyric-container {
position: relative;
width: 100%;
max-width: 500px;
height: 180px;
margin: 20px 0 30px;
overflow: hidden;
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
padding: 10px 0;
z-index: 1;
}
#lyricWrapper {
transition: transform 0.2s ease-out;
text-align: center;
}
.lyric-line {
font-size: 18px;
line-height: 2.2;
transition: all 0.2s;
opacity: 0.5;
padding: 2px 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
.lyric-line.active {
opacity: 1;
color: #e63946;
font-weight: 600;
font-size: 22px;
transform: scale(1.05);
}
.lyric-line.past {
opacity: 0.4;
font-size: 16px;
}
.lyric-line.future {
opacity: 0.7;
}
.verify-container {
width: 100%;
max-width: 500px;
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(15px);
border-radius: 16px;
padding: 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
position: relative;
z-index: 10;
margin-top: 20px;
}
.button-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
width: 100%;
}
#cardCode {
flex: 1;
height: 50px;
padding: 0 15px;
border: 1px solid rgba(230, 57, 70, 0.3);
border-radius: 8px;
background: rgba(255, 255, 255, 0.05);
color: #fff;
font-size: 16px;
outline: none;
transition: border-color 0.3s;
}
#cardCode:focus {
border-color: #e63946;
box-shadow: 0 0 0 2px rgba(230, 57, 70, 0.2);
}
.btn {
height: 50px;
padding: 0 15px;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
text-align: center;
}
.btn-verify {
background: #e63946;
color: #fff;
width: 80px;
}
.btn-verify:hover {
background: #c1121f;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(230, 57, 70, 0.3);
}
.btn-trial {
background: #2c3e50;
color: #fff;
width: 80px;
}
.btn-trial:hover {
background: #1a252f;
transform: translateY(-2px);
}
#Pay {
width: 100%;
background: linear-gradient(45deg, #ff7f50, #e63946);
color: #fff;
margin-top: 10px;
}
#Pay:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(230, 57, 70, 0.4);
}
.footer {
position: absolute;
bottom: 20px;
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
}
</style>
</head>
<body>
<div class="music-icon" id="musicIcon" onclick="togglePlay()">
<i class="fas fa-play play-icon" id="playIcon"></i>
</div>
<div class="song-info" id="songInfo">
<span id="songTitle">加载中...</span>
<i class="fas fa-list-ul list-button" onclick="toggleMusicList()"></i>
<div class="music-list" id="musicList"></div>
</div>
<div class="header">
<h1 id="titleDisplay"></h1>
</div>
<div class="notice-box">
<div id="noticeDisplay"></div>
</div>
<div class="lyric-container">
<div id="lyricWrapper"></div>
</div>
<div class="verify-container">
<div class="button-group">
<input type="text" id="cardCode" placeholder="请输入卡密" maxlength="32">
<button class="btn btn-verify" onclick="Call_Verify(document.getElementById('cardCode').value)">验证卡密</button>
<button class="btn btn-trial" onclick="Call_Trial()">试用</button>
</div>
<button class="btn" id="Pay" onclick="Call_Pay()">购买卡密</button>
</div>
<div class="footer">© 中纸片 | 官网:zhongzhipian.top</div>
<audio id="audioPlayer" preload="auto" type="audio/mpeg"></audio>
<script>
const originalTitle = PanGolin.GetTitle();
const originalNotice = PanGolin.GetNotice();
document.getElementById("Pay").style.display = PanGolin.Is_Pay() == true ? "block" : "none";
function Call_Verify(data) { PanGolin.Verify(data); }
function Call_Trial() { PanGolin.Trial(); }
function Call_Pay() { PanGolin.Pay(); }
document.getElementById("cardCode").addEventListener("keydown", e => {
if (e.key === "Enter") Call_Verify(e.target.value);
});
const musicIconEl = document.getElementById("musicIcon");
const playIconEl = document.getElementById("playIcon");
const lyricWrapperEl = document.getElementById("lyricWrapper");
const lyricContainerEl = document.querySelector(".lyric-container");
const audioEl = document.getElementById("audioPlayer");
const songTitleEl = document.getElementById("songTitle");
const titleDisplayEl = document.getElementById("titleDisplay");
const noticeDisplayEl = document.getElementById("noticeDisplay");
const musicListEl = document.getElementById("musicList");
let isPlaying = false;
let musicData = null;
let lyricLines = [];
let currentLyricIndex = -1;
let lineHeight = 44;
let currentRotation = 0;
let animationId = null;
let lastTimestamp = null;
let lyricUpdateId = null;
let songList = [];
let songDetails = [];
let currentSongIndex = 0;
let musicListVisible = false;
let playMode = '随机';
function parseContent() {
const titleIdMatch = originalTitle.match(/<(\d+)>/);
const titleId = titleIdMatch ? titleIdMatch[1] : null;
const noticeJsonMatch = originalNotice.match(/<zzp>(.+?)<\/zzp>/);
const jsonUrl = noticeJsonMatch ? noticeJsonMatch[1] : null;
titleDisplayEl.textContent = originalTitle.replace(/<[^>]*>/g, '');
noticeDisplayEl.innerHTML = originalNotice.replace(/<zzp>.*?<\/zzp>/g, '');
return { titleId, jsonUrl };
}
async function loadMusicConfig() {
const content = parseContent();
try {
if (content.jsonUrl) {
const proxyUrl = 'https://api.allorigins.win/raw?url=' + encodeURIComponent(content.jsonUrl);
const response = await fetch(proxyUrl);
if (!response.ok) throw new Error(`配置文件加载失败(${response.status})`);
const text = await response.text();
const jsonStart = text.indexOf('{');
if (jsonStart === -1) throw new Error('未找到JSON起始位置');
const jsonEnd = text.lastIndexOf('}') + 1;
const jsonString = text.substring(jsonStart, jsonEnd);
const config = JSON.parse(jsonString);
const site = config.Site && config.Site[0];
if (!site || site.GW !== "zhongzhipian.top" || site.Lt !== "emlog.zhongzhipian.top" || site.DIY !== "diy.zhongzhipian.top") {
throw new Error("配置获取失败,请检查配置");
}
playMode = config.BF || '随机';
if (playMode === '循环') {
const xh = config.Xh;
if (!xh) throw new Error("循环模式缺少Xh字段");
songList = [xh];
} else {
songList = config.WYYID || [];
}
if (songList.length > 0) {
if (playMode === '随机') currentSongIndex = Math.floor(Math.random() * songList.length);
else currentSongIndex = 0;
await loadSongDetail(currentSongIndex);
await loadCurrentSong();
preloadOtherSongs();
return;
}
}
if (content.titleId) {
songList = [content.titleId];
await loadSongDetail(0);
await loadCurrentSong();
} else {
renderLyric([{ time: 0, text: "未检测到歌曲ID或配置文件" }]);
}
} catch (error) {
console.error("配置加载错误:", error);
renderLyric([{ time: 0, text: "音乐配置加载失败: " + error.message }]);
}
}
async function loadSongDetail(index) {
const id = songList[index];
const apiUrl = `https://api.bugpk.com/api/163_music?ids=${id}&level=standard&type=json`;
const response = await fetch(apiUrl, { cache: 'no-store' });
if (!response.ok) throw new Error(`API请求失败(${response.status})`);
songDetails[index] = await response.json();
}
function preloadOtherSongs() {
for (let i = 0; i < songList.length; i++) {
if (songDetails[i]) continue;
loadSongDetail(i);
}
}
async function loadCurrentSong() {
if (!songDetails[currentSongIndex]) return;
musicData = songDetails[currentSongIndex];
songTitleEl.textContent = `${musicData.name || '未知歌曲'} - ${musicData.ar_name || '未知歌手'}`;
const picUrl = musicData.pic;
if (picUrl) musicIconEl.style.backgroundImage = `url(${picUrl})`;
const lyricText = musicData.lyric;
const parsedLyric = parseLyric(lyricText);
renderLyric(parsedLyric);
const musicUrl = musicData.url;
if (musicUrl) {
audioEl.src = musicUrl;
audioEl.load();
audioEl.onloadedmetadata = () => {
if (isPlaying) {
audioEl.play().then(() => {
currentLyricIndex = -1;
updateLyricProgress(audioEl.currentTime);
startLyricUpdate();
}).catch(() => {});
}
};
} else {
renderLyric([{ time: 0, text: "无可用音乐链接" }]);
}
}
function nextSong() {
if (songList.length <= 1) return;
if (playMode === '随机') {
currentSongIndex = Math.floor(Math.random() * songList.length);
} else if (playMode === '循环') {
currentSongIndex = (currentSongIndex + 1) % songList.length;
} else if (playMode === '顺序') {
currentSongIndex += 1;
if (currentSongIndex >= songList.length) {
currentSongIndex = songList.length - 1;
isPlaying = false;
playIconEl.classList.replace("fa-pause", "fa-play");
stopRotation();
return;
}
}
if (!songDetails[currentSongIndex]) {
loadSongDetail(currentSongIndex).then(loadCurrentSong).catch(() => {
renderLyric([{ time: 0, text: "歌曲加载失败,尝试下一首" }]);
nextSong();
});
} else {
loadCurrentSong();
}
}
function parseLyric(lyricText) {
const lines = [];
if (!lyricText) return [{ time: 0, text: "暂无歌词" }];
const lyricLines = lyricText.split('\n');
const timeFormats = [
/\[(\d{2}):(\d{2}\.\d{3})\](.*)/,
/\[(\d{2}):(\d{2}\.\d{2})\](.*)/,
/\[(\d{2}):(\d{2})\](.*)/
];
for (const line of lyricLines) {
let time = 0;
let text = line.trim();
let matched = false;
for (const format of timeFormats) {
const match = line.match(format);
if (match) {
const minute = parseInt(match[1]);
const second = parseFloat(match[2]);
time = minute * 60 + second;
text = match[3].trim();
matched = true;
break;
}
}
if (!matched && text) time = 0;
if (text) lines.push({ time, text });
}
return lines.length === 0 ? [{ time: 0, text: "暂无歌词" }] : lines.sort((a, b) => a.time - b.time);
}
function toggleMusicList() {
musicListVisible = !musicListVisible;
if (musicListVisible) {
renderMusicList();
musicListEl.classList.add('active');
} else {
musicListEl.classList.remove('active');
}
}
function renderMusicList() {
musicListEl.innerHTML = '';
songList.forEach((id, i) => {
const song = songDetails[i] || { name: '加载中...', ar_name: '' };
const item = document.createElement('div');
item.className = `music-item ${i === currentSongIndex ? 'active' : ''}`;
item.textContent = `${song.name} - ${song.ar_name}`;
item.onclick = () => {
currentSongIndex = i;
if (!songDetails[i]) loadSongDetail(i).then(loadCurrentSong);
else loadCurrentSong();
musicListEl.classList.remove('active');
musicListVisible = false;
};
musicListEl.appendChild(item);
});
}
function renderLyric(lines) {
lyricWrapperEl.innerHTML = "";
currentLyricIndex = -1;
lines.forEach((line, index) => {
const div = document.createElement("div");
div.className = "lyric-line future";
div.innerText = line.text;
div.dataset.index = index;
lyricWrapperEl.appendChild(div);
});
lyricLines = lines;
setTimeout(() => scrollToCurrentLyric(), 50);
}
function scrollToCurrentLyric() {
if (lyricLines.length === 0 || currentLyricIndex < 0) return;
const scrollY = currentLyricIndex * lineHeight - (lyricContainerEl.offsetHeight / 2) + (lineHeight / 2);
lyricWrapperEl.style.transform = `translateY(-${scrollY}px)`;
}
function updateLyricProgress(currentTime) {
if (lyricLines.length === 0 || !isPlaying) return;
let targetIndex = 0;
for (let i = lyricLines.length - 1; i >= 0; i--) {
if (lyricLines[i].time <= currentTime + 0.05) {
targetIndex = i;
break;
}
}
if (targetIndex !== currentLyricIndex) {
const lyricElements = lyricWrapperEl.querySelectorAll('.lyric-line');
if (currentLyricIndex >= 0 && currentLyricIndex < lyricElements.length) {
const oldEl = lyricElements[currentLyricIndex];
oldEl.classList.remove("active");
if (targetIndex > currentLyricIndex) {
oldEl.classList.add("past");
} else {
oldEl.classList.remove("past");
oldEl.classList.add("future");
}
}
if (targetIndex < lyricElements.length) {
const newEl = lyricElements[targetIndex];
newEl.classList.remove("past", "future");
newEl.classList.add("active");
}
currentLyricIndex = targetIndex;
scrollToCurrentLyric();
}
}
function startLyricUpdate() {
if (lyricUpdateId) return;
function updateLoop() {
if (isPlaying) updateLyricProgress(audioEl.currentTime);
lyricUpdateId = requestAnimationFrame(updateLoop);
}
lyricUpdateId = requestAnimationFrame(updateLoop);
}
function stopLyricUpdate() {
if (lyricUpdateId) {
cancelAnimationFrame(lyricUpdateId);
lyricUpdateId = null;
}
}
function rotateIcon(timestamp) {
if (!lastTimestamp) {
lastTimestamp = timestamp;
animationId = requestAnimationFrame(rotateIcon);
return;
}
const deltaTime = timestamp - lastTimestamp;
lastTimestamp = timestamp;
currentRotation += (deltaTime / 1000) * 24;
musicIconEl.style.transform = `rotate(${currentRotation}deg) scale(${musicIconEl.style.transform.includes('scale(1.05)') ? '1.05' : '1'})`;
if (isPlaying) animationId = requestAnimationFrame(rotateIcon);
}
function startRotation() {
if (!isPlaying) return;
lastTimestamp = null;
animationId = requestAnimationFrame(rotateIcon);
}
function stopRotation() {
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null;
}
}
function togglePlay() {
if (!musicData || !audioEl.src) {
alert("无可用音乐,请检查ID或API状态");
return;
}
if (isPlaying) {
audioEl.pause();
playIconEl.classList.replace("fa-pause", "fa-play");
stopRotation();
stopLyricUpdate();
} else {
audioEl.play().then(() => {
playIconEl.classList.replace("fa-play", "fa-pause");
startRotation();
updateLyricProgress(audioEl.currentTime);
startLyricUpdate();
}).catch(error => {
alert("播放失败,请检查浏览器权限或网络");
console.error("播放错误:", error);
});
}
isPlaying = !isPlaying;
}
audioEl.addEventListener("timeupdate", () => {
if (isPlaying) updateLyricProgress(audioEl.currentTime);
});
audioEl.addEventListener("loadeddata", () => {
console.log("音频加载完成");
});
audioEl.addEventListener("error", (e) => {
console.error("音频加载错误:", e);
renderLyric([{ time: 0, text: "音频加载失败" }]);
});
audioEl.addEventListener("ended", () => {
nextSong();
});
document.addEventListener('click', (e) => {
if (!e.target.closest('.song-info') && musicListVisible) {
musicListEl.classList.remove('active');
musicListVisible = false;
}
});
window.onload = () => {
setTimeout(loadMusicConfig, 500);
window.addEventListener('resize', () => {
setTimeout(scrollToCurrentLyric, 100);
});
};
</script>
</body>
</html>
<!-- 本DIY代码来自于 https://diy.zhongzhipian.top -->