NeteaseCloudMusicApiEnhanced/public/playlist_cover_update.html
ElyPrism ce51da9150
build(version): bump 4.30.0 (#102)
* chore(deps): bump actions/checkout from 4 to 6

Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Squashed commit of the following:

commit f73cbbeec37d40383e2b7d411e34048146776345
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sun Feb 1 12:47:57 2026 +0000

    chore(deps): bump actions/download-artifact from 4 to 7

    Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 7.
    - [Release notes](https://github.com/actions/download-artifact/releases)
    - [Commits](https://github.com/actions/download-artifact/compare/v4...v7)

    ---
    updated-dependencies:
    - dependency-name: actions/download-artifact
      dependency-version: '7'
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

* Squashed commit of the following:

commit 4da2d5f3600f52c7087ea350e3ec87a3c7cac535
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sun Feb 1 12:48:00 2026 +0000

    chore(deps): bump actions/github-script from 7 to 8

    Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
    - [Release notes](https://github.com/actions/github-script/releases)
    - [Commits](https://github.com/actions/github-script/compare/v7...v8)

    ---
    updated-dependencies:
    - dependency-name: actions/github-script
      dependency-version: '8'
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

* Squashed commit of the following:

commit 9e65b176252a554decf5574ca6a3463838a7a32f
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sun Feb 1 12:47:49 2026 +0000

    chore(deps): bump actions/setup-node from 4 to 6

    Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
    - [Release notes](https://github.com/actions/setup-node/releases)
    - [Commits](https://github.com/actions/setup-node/compare/v4...v6)

    ---
    updated-dependencies:
    - dependency-name: actions/setup-node
      dependency-version: '6'
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

* Squashed commit of the following:

commit a060f3c4cc5c3a4baf9c4827163acde1589ef26d
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sun Feb 1 12:47:53 2026 +0000

    chore(deps): bump actions/upload-artifact from 4 to 6

    Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
    - [Release notes](https://github.com/actions/upload-artifact/releases)
    - [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

    ---
    updated-dependencies:
    - dependency-name: actions/upload-artifact
      dependency-version: '6'
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

* build(version): bump 4.30.0

* refactor: QR login and voice upload pages with improved UI and error handling

- Enhanced styling for better user experience on qrlogin-nocookie.html and qrlogin.html
- Added loading indicators and improved status messages during QR code login process
- Updated error handling for login status retrieval
- Refactored unblock_test.html for better layout and user interaction
- Improved voice upload page with a more intuitive design and better feedback for file uploads
- Added loading state management for voice list retrieval
- Enhanced accessibility and usability across all modified pages

* fix: Potential fix for code scanning alert no. 6: DOM text reinterpreted as HTML

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 15: DOM text reinterpreted as HTML

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* build: update utils

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-02-09 23:33:26 +08:00

324 lines
7.3 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh">
<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: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
min-height: 100vh;
background: #f5f5f5;
padding: 20px;
}
.container {
max-width: 500px;
margin: 0 auto;
background: white;
border-radius: 12px;
padding: 32px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
text-align: center;
}
h1 {
font-size: 24px;
font-weight: 600;
color: #333;
margin-bottom: 8px;
}
.subtitle {
font-size: 14px;
color: #666;
margin-bottom: 32px;
}
.login-link {
display: block;
margin-bottom: 24px;
color: #666;
font-size: 14px;
text-decoration: none;
}
.login-link:hover {
color: #333;
text-decoration: underline;
}
.cover-wrapper {
position: relative;
width: 180px;
height: 180px;
margin: 0 auto 24px;
}
.cover {
width: 100%;
height: 100%;
border-radius: 50%;
object-fit: cover;
border: 4px solid #fff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.form-group {
margin-bottom: 20px;
text-align: left;
}
label {
display: block;
font-size: 14px;
font-weight: 500;
color: #555;
margin-bottom: 8px;
}
input[type="text"] {
width: 100%;
padding: 10px 14px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
outline: none;
}
input[type="text"]:focus {
border-color: #333;
}
.upload-btn {
display: inline-block;
padding: 12px 28px;
background: #333;
color: white;
font-size: 15px;
font-weight: 500;
border-radius: 6px;
cursor: pointer;
transition: background 0.2s ease;
border: none;
}
.upload-btn:hover {
background: #555;
}
.upload-btn input[type="file"] {
display: none;
}
.loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.2s ease;
}
.loading.active {
opacity: 1;
}
.spinner {
width: 48px;
height: 48px;
border: 4px solid #e0e0e0;
border-top-color: #333;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.result {
margin-top: 20px;
padding: 12px 16px;
border-radius: 6px;
font-size: 14px;
text-align: left;
}
.result.success {
background: #d1fae5;
color: #065f46;
}
.result.error {
background: #fee2e2;
color: #991b1b;
}
</style>
</head>
<body>
<div class="container">
<h1>歌单封面上传</h1>
<p class="subtitle">上传自定义歌单封面图片</p>
<a href="/qrlogin-nocookie.html" class="login-link">还没登录?点击登录</a>
<div class="form-group">
<label for="playlistId">歌单 ID</label>
<input type="text" id="playlistId" placeholder="请输入歌单ID" />
</div>
<div class="cover-wrapper">
<img id="playlist_cover" class="cover" src="" alt="歌单封面" />
<div class="loading" id="loading">
<div class="spinner"></div>
</div>
</div>
<label class="upload-btn">
选择封面图片
<input id="file" type="file" name="filename" accept="image/*" />
</label>
<div id="result" class="result" style="display: none;"></div>
</div>
<script src="https://fastly.jsdelivr.net/npm/axios@0.26.1/dist/axios.min.js"></script>
<script>
const loadingOverlay = document.getElementById('loading')
const playlistIdInput = document.getElementById('playlistId')
const resultDiv = document.getElementById('result')
function showLoading() {
loadingOverlay.classList.add('active')
}
function hideLoading() {
loadingOverlay.classList.remove('active')
}
function showResult(message, type) {
resultDiv.textContent = message
resultDiv.className = 'result ' + type
resultDiv.style.display = 'block'
}
function hideResult() {
resultDiv.style.display = 'none'
}
async function loadPlaylistCover() {
const playlistId = playlistIdInput.value.trim()
if (!playlistId) {
return
}
showLoading()
hideResult()
try {
const res = await axios({
url: `/playlist/detail?id=${playlistId}&timestamp=${Date.now()}`,
})
document.querySelector('#playlist_cover').src = res.data.playlist.coverImgUrl
hideResult()
} catch (error) {
console.error('加载封面失败:', error)
showResult('加载封面失败请检查歌单ID', 'error')
} finally {
hideLoading()
}
}
// 监听歌单ID输入变化
playlistIdInput.addEventListener('input', function() {
loadPlaylistCover()
})
// 监听文件选择
document
.querySelector('input[type="file"]')
.addEventListener('change', async function (e) {
const file = this.files[0]
const playlistId = playlistIdInput.value.trim()
if (!playlistId) {
showResult('请先输入歌单ID', 'error')
return
}
if (!file) {
return
}
showLoading()
hideResult()
try {
await upload(file, playlistId)
} catch (error) {
console.error('上传失败:', error)
showResult('上传失败,请重试', 'error')
} finally {
hideLoading()
}
})
async function upload(file, playlistId) {
var formData = new FormData()
formData.append('imgFile', file)
const imgSize = await getImgSize(file)
const res = await axios({
method: 'post',
url: `/playlist/cover/update?id=${playlistId}&cookie=${localStorage.getItem('cookie')}&imgSize=${imgSize.width}&imgX=0&imgY=0&timestamp=${Date.now()}`,
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
})
document.querySelector('#playlist_cover').src = res.data.data.url
showResult('封面上传成功!', 'success')
}
function getImgSize(file) {
return new Promise((resolve, reject) => {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function (theFile) {
let image = new Image()
image.src = theFile.target.result
image.onload = function () {
resolve({
width: this.width,
height: this.height,
})
}
image.onerror = function() {
reject(new Error('图片加载失败'))
}
}
reader.onerror = function() {
reject(new Error('文件读取失败'))
}
})
}
</script>
</body>
</html>