feat: 添加歌曲智能排序功能(默认启用)

- 实现智能排序:数字 -> 字母 -> 其他符号
- 添加 smartSort() 方法支持自然数值排序
- 默认启用排序功能,用户无需设置
- 支持多语言字符(中文、日文、英文等)
- 添加完整的测试工具和文档

新增文件:
- test_sort.html (可视化测试页面)
- verify_sort.py (Python验证脚本)
- verify_sort.js (Node.js验证脚本)
- SORT_FEATURE.md (功能说明)
- SORT_USAGE.md (使用指南)
- QUICKSTART_SORT.md (快速开始)
- IMPLEMENTATION_SUMMARY.md (实现总结)
- CHANGELOG_SORT.md (更新日志)
- UPDATE_SUMMARY.md (更新说明)

修改文件:
- public/src/js/songselect.js (添加智能排序逻辑)
- README.md (更新功能介绍)
This commit is contained in:
2025-11-15 15:59:08 +08:00
parent 4ba37435da
commit 25c26b2b2e
11 changed files with 1989 additions and 8 deletions

227
test_sort.html Normal file
View File

@@ -0,0 +1,227 @@
<!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>
body {
font-family: 'Arial', 'Microsoft YaHei', sans-serif;
max-width: 1000px;
margin: 50px auto;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.container {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
}
h1 {
text-align: center;
margin-bottom: 30px;
font-size: 2.5em;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
margin-top: 20px;
}
.column {
background: rgba(255, 255, 255, 0.15);
padding: 20px;
border-radius: 15px;
}
h2 {
margin-top: 0;
color: #ffeb3b;
border-bottom: 2px solid #ffeb3b;
padding-bottom: 10px;
}
.song-list {
list-style: none;
padding: 0;
}
.song-item {
padding: 10px;
margin: 5px 0;
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
transition: all 0.3s ease;
}
.song-item:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateX(5px);
}
.type-label {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.8em;
margin-left: 10px;
font-weight: bold;
}
.type-number {
background: #4caf50;
}
.type-letter {
background: #2196f3;
}
.type-other {
background: #ff9800;
}
button {
display: block;
width: 200px;
margin: 20px auto;
padding: 15px;
font-size: 1.2em;
background: #ffeb3b;
color: #333;
border: none;
border-radius: 10px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
}
button:hover {
background: #fdd835;
transform: scale(1.05);
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
.info {
background: rgba(255, 255, 255, 0.2);
padding: 15px;
border-radius: 10px;
margin: 20px 0;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1>🥁 歌曲智能排序测试</h1>
<div class="info">
<p><strong>排序规则:</strong>数字 → 字母 → 其他符号(中文、日文等)</p>
<p><strong>同类型内:</strong>自然排序(支持数值比较和多语言)</p>
</div>
<button onclick="testSort()">运行排序测试</button>
<div class="columns">
<div class="column">
<h2>排序前</h2>
<ul class="song-list" id="before"></ul>
</div>
<div class="column">
<h2>排序后</h2>
<ul class="song-list" id="after"></ul>
</div>
</div>
</div>
<script>
// 测试歌曲数据
const testSongs = [
"太鼓の達人",
"Zyxwv Test",
"123 Song",
"abc melody",
"456 rhythm",
"*Special*",
"10 drums",
"あいうえお",
"2 beats",
"ZZZ Final",
"1st Place",
"100 percent",
"ドンだー!",
"Battle No.1",
"~奇跡~",
"777",
"Angel Beats",
"カノン",
"Don't Stop",
"零 -ZERO-",
"3pieces",
"Apple",
"燎原ノ舞",
"99 Balloons",
"Brave Heart",
"夏祭り"
];
// 智能排序函数(与实际代码相同)
function smartSort(titleA, titleB) {
const getCharType = (char) => {
if (!char) return 3;
const code = char.charCodeAt(0);
if (code >= 48 && code <= 57) return 0; // 数字
if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) return 1; // 字母
return 2; // 其他
};
const getFirstCharInfo = (title) => {
if (!title || title.length === 0) return { type: 3, char: '', title: '' };
const firstChar = title.charAt(0);
const type = getCharType(firstChar);
return { type, char: firstChar, title };
};
const infoA = getFirstCharInfo(titleA);
const infoB = getFirstCharInfo(titleB);
if (infoA.type !== infoB.type) {
return infoA.type - infoB.type;
}
return titleA.localeCompare(titleB, undefined, {
numeric: true,
sensitivity: 'base'
});
}
function getTypeLabel(title) {
const firstChar = title.charAt(0);
const code = firstChar.charCodeAt(0);
if (code >= 48 && code <= 57) {
return '<span class="type-label type-number">数字</span>';
} else if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) {
return '<span class="type-label type-letter">字母</span>';
} else {
return '<span class="type-label type-other">其他</span>';
}
}
function displaySongs(songs, elementId) {
const list = document.getElementById(elementId);
list.innerHTML = songs.map(song =>
`<li class="song-item">${song}${getTypeLabel(song)}</li>`
).join('');
}
function testSort() {
// 显示排序前
displaySongs(testSongs, 'before');
// 排序
const sortedSongs = [...testSongs].sort(smartSort);
// 显示排序后
setTimeout(() => {
displaySongs(sortedSongs, 'after');
}, 300);
}
// 页面加载时自动运行测试
window.onload = testSort;
</script>
</body>
</html>