上传文件至 /
This commit is contained in:
27
add_db.php
Normal file
27
add_db.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
// 运行此脚本为推荐表添加状态字段
|
||||||
|
require 'db_connect.php';
|
||||||
|
|
||||||
|
if ($pdo) {
|
||||||
|
try {
|
||||||
|
// 检查是否已存在status字段
|
||||||
|
$result = $pdo->query("SHOW COLUMNS FROM recommendations LIKE 'status'");
|
||||||
|
$columnExists = $result->fetch();
|
||||||
|
|
||||||
|
if (!$columnExists) {
|
||||||
|
// 添加状态字段(0:待审核, 1:已同意, 2:已驳回)
|
||||||
|
$pdo->exec("ALTER TABLE recommendations
|
||||||
|
ADD COLUMN status TINYINT NOT NULL DEFAULT 0,
|
||||||
|
ADD COLUMN reviewed_at DATETIME NULL");
|
||||||
|
|
||||||
|
echo "状态字段添加成功!请刷新页面继续操作。";
|
||||||
|
} else {
|
||||||
|
echo "状态字段已存在,无需重复添加。";
|
||||||
|
}
|
||||||
|
} catch(PDOException $e) {
|
||||||
|
die("操作失败: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die("数据库连接失败,请先检查连接配置。");
|
||||||
|
}
|
||||||
|
?>
|
||||||
26
add_db_2.php
Normal file
26
add_db_2.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
// 运行此脚本为推荐表添加用户标识字段
|
||||||
|
require 'db_connect.php';
|
||||||
|
|
||||||
|
if ($pdo) {
|
||||||
|
try {
|
||||||
|
// 检查是否已存在user_identifier字段
|
||||||
|
$result = $pdo->query("SHOW COLUMNS FROM recommendations LIKE 'user_identifier'");
|
||||||
|
$columnExists = $result->fetch();
|
||||||
|
|
||||||
|
if (!$columnExists) {
|
||||||
|
// 添加用户标识字段(用于区分不同用户的推荐)
|
||||||
|
$pdo->exec("ALTER TABLE recommendations
|
||||||
|
ADD COLUMN user_identifier VARCHAR(255) NOT NULL DEFAULT ''");
|
||||||
|
|
||||||
|
echo "用户标识字段添加成功!请刷新页面继续操作。";
|
||||||
|
} else {
|
||||||
|
echo "用户标识字段已存在,无需重复添加。";
|
||||||
|
}
|
||||||
|
} catch(PDOException $e) {
|
||||||
|
die("操作失败: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die("数据库连接失败,请先检查连接配置。");
|
||||||
|
}
|
||||||
|
?>
|
||||||
305
admin_music_upload.php
Normal file
305
admin_music_upload.php
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
<?php
|
||||||
|
// 管理员音乐审核页面(支持BV号显示和时长验证)
|
||||||
|
require_once 'db_config.php';
|
||||||
|
|
||||||
|
$message = '';
|
||||||
|
$message_type = '';
|
||||||
|
|
||||||
|
// 获取音频实际时长的函数
|
||||||
|
function getActualAudioDuration($file_path) {
|
||||||
|
// 方法1: 使用ffmpeg(推荐,更准确)
|
||||||
|
if (function_exists('shell_exec')) {
|
||||||
|
$command = "ffmpeg -i " . escapeshellarg($file_path) . " 2>&1 | grep 'Duration' | cut -d ' ' -f 4 | sed s/,//";
|
||||||
|
$output = shell_exec($command);
|
||||||
|
|
||||||
|
if ($output) {
|
||||||
|
$duration = trim($output);
|
||||||
|
// 转换为 MM:SS 格式
|
||||||
|
list($hours, $minutes, $seconds) = explode(':', $duration);
|
||||||
|
$seconds = floor((float)$seconds);
|
||||||
|
if ((int)$hours > 0) {
|
||||||
|
$minutes = (int)$minutes + (int)$hours * 60;
|
||||||
|
}
|
||||||
|
return sprintf('%d:%02d', $minutes, $seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法2: 使用getid3库(如果安装了)
|
||||||
|
if (class_exists('getID3')) {
|
||||||
|
$getID3 = new getID3;
|
||||||
|
$fileInfo = $getID3->analyze($file_path);
|
||||||
|
if (!empty($fileInfo['playtime_seconds'])) {
|
||||||
|
$seconds = floor($fileInfo['playtime_seconds']);
|
||||||
|
$minutes = floor($seconds / 60);
|
||||||
|
$seconds = $seconds % 60;
|
||||||
|
return sprintf('%d:%02d', $minutes, $seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // 无法获取时长
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理审核操作
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
if (isset($_POST['approve_id'])) {
|
||||||
|
$id = $_POST['approve_id'];
|
||||||
|
try {
|
||||||
|
// 1. 获取待审核音乐信息(包含BV号和用户输入的时长)
|
||||||
|
$stmt = $conn->prepare("SELECT * FROM pending_music WHERE id = ?");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$music = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($music) {
|
||||||
|
// 2. 验证音频时长(如果可能)
|
||||||
|
$duration_mismatch = false;
|
||||||
|
$actual_duration = getActualAudioDuration($music['file_path']);
|
||||||
|
|
||||||
|
if ($actual_duration && $actual_duration !== $music['duration']) {
|
||||||
|
// 时长不匹配,设置标志但仍继续处理(只是提醒管理员)
|
||||||
|
$duration_mismatch = true;
|
||||||
|
$message .= "注意:用户填写的时长({$music['duration']})与实际音频时长({$actual_duration})不匹配。";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 将信息插入正式音乐表(包含BV号字段)
|
||||||
|
// 如果有实际时长,使用实际时长覆盖用户输入
|
||||||
|
$final_duration = $actual_duration ?: $music['duration'];
|
||||||
|
|
||||||
|
$stmt_insert = $conn->prepare("INSERT INTO music
|
||||||
|
(title, artist, category, description, file_path, duration, upload_time, uploader_name, bvid)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
$stmt_insert->execute([
|
||||||
|
$music['title'], $music['artist'], $music['category'],
|
||||||
|
$music['description'], $music['file_path'], $final_duration,
|
||||||
|
$music['upload_time'], $music['uploader_name'], $music['bvid'] ?? ''
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 4. 从待审核表中删除
|
||||||
|
$stmt_delete = $conn->prepare("DELETE FROM pending_music WHERE id = ?");
|
||||||
|
$stmt_delete->execute([$id]);
|
||||||
|
|
||||||
|
// 构建成功消息
|
||||||
|
$base_message = "音乐《" . htmlspecialchars($music['title']) . "》已通过审核!";
|
||||||
|
if ($duration_mismatch) {
|
||||||
|
$message = $base_message . " " . $message;
|
||||||
|
} else {
|
||||||
|
$message = $base_message;
|
||||||
|
}
|
||||||
|
$message_type = "success";
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = "数据库错误: " . $e->getMessage();
|
||||||
|
$message_type = "error";
|
||||||
|
}
|
||||||
|
} elseif (isset($_POST['reject_id'])) {
|
||||||
|
$id = $_POST['reject_id'];
|
||||||
|
try {
|
||||||
|
// 获取文件路径用于删除
|
||||||
|
$stmt = $conn->prepare("SELECT file_path, title FROM pending_music WHERE id = ?");
|
||||||
|
$stmt->execute([$id]);
|
||||||
|
$music = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($music) {
|
||||||
|
// 删除服务器上的文件
|
||||||
|
if (file_exists($music['file_path'])) {
|
||||||
|
unlink($music['file_path']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从待审核表中删除记录
|
||||||
|
$stmt_delete = $conn->prepare("DELETE FROM pending_music WHERE id = ?");
|
||||||
|
$stmt_delete->execute([$id]);
|
||||||
|
|
||||||
|
$message = "音乐《" . htmlspecialchars($music['title']) . "》已驳回并删除。";
|
||||||
|
$message_type = "success";
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = "数据库错误: " . $e->getMessage();
|
||||||
|
$message_type = "error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有待审核音乐(包含BV号)并计算实际时长
|
||||||
|
try {
|
||||||
|
$stmt = $conn->query("SELECT * FROM pending_music ORDER BY upload_time DESC");
|
||||||
|
$pending_music = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// 为每条音乐获取实际时长并检查是否匹配
|
||||||
|
foreach ($pending_music as &$music) {
|
||||||
|
$actual_duration = getActualAudioDuration($music['file_path']);
|
||||||
|
$music['actual_duration'] = $actual_duration;
|
||||||
|
$music['duration_match'] = ($actual_duration === $music['duration']);
|
||||||
|
}
|
||||||
|
unset($music); // 解除引用
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = "无法加载待审核列表: " . $e->getMessage();
|
||||||
|
$message_type = "error";
|
||||||
|
$pending_music = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$categories = [
|
||||||
|
'cantonese' => '粤语歌曲', 'mandarin' => '国语歌曲', 'waiyu' => '外语歌曲',
|
||||||
|
'classic' => '经典老歌', 'other' => '其他音乐'
|
||||||
|
];
|
||||||
|
?>
|
||||||
|
<!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://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
<style>
|
||||||
|
body { font-family: 'Arial', sans-serif; background-color: #f7f9fc; margin: 0; }
|
||||||
|
.container { max-width: 1600px; margin: 2rem auto; padding: 0 1rem; }
|
||||||
|
h1 { color: #2c3e50; border-bottom: 2px solid #e74c3c; padding-bottom: 0.5rem; }
|
||||||
|
.message { padding: 1rem; border-radius: 8px; margin-bottom: 1rem; text-align: center; }
|
||||||
|
.success { background-color: #d4edda; color: #155724; }
|
||||||
|
.error { background-color: #f8d7da; color: #721c24; }
|
||||||
|
.warning { background-color: #fff3cd; color: #856404; }
|
||||||
|
table { width: 100%; border-collapse: collapse; background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.08); }
|
||||||
|
th, td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #f1f2f6; }
|
||||||
|
th { background-color: #2c3e50; color: white; }
|
||||||
|
tr:hover { background-color: #fafafa; }
|
||||||
|
.btn { padding: 0.5rem 1rem; border: none; border-radius: 4px; cursor: pointer; font-size: 0.9rem; transition: background-color 0.3s; margin-right: 5px; }
|
||||||
|
.btn-approve { background-color: #2ecc71; color: white; }
|
||||||
|
.btn-approve:hover { background-color: #27ae60; }
|
||||||
|
.btn-reject { background-color: #e74c3c; color: white; }
|
||||||
|
.btn-reject:hover { background-color: #c0392b; }
|
||||||
|
.audio-player { width: 100%; max-width: 250px; }
|
||||||
|
.action-form { display: inline; }
|
||||||
|
.header-actions { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
|
||||||
|
.back-link { color: #2c3e50; text-decoration: none; font-weight: 500; }
|
||||||
|
.back-link:hover { text-decoration: underline; }
|
||||||
|
.bvid-link { color: #3498db; text-decoration: none; }
|
||||||
|
.bvid-link:hover { text-decoration: underline; }
|
||||||
|
.no-bvid { color: #95a5a6; font-style: italic; }
|
||||||
|
.duration-match { color: #27ae60; font-weight: 500; }
|
||||||
|
.duration-mismatch { color: #e74c3c; font-weight: 500; }
|
||||||
|
.duration-info { display: flex; flex-direction: column; gap: 4px; }
|
||||||
|
.duration-note { font-size: 0.8rem; color: #7f8c8d; }
|
||||||
|
.tooltip { position: relative; display: inline-block; }
|
||||||
|
.tooltip .tooltip-text {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 200px;
|
||||||
|
background-color: #333;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: 125%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -100px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.tooltip:hover .tooltip-text {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header-actions">
|
||||||
|
<h1><i class="fas fa-tasks"></i> 音乐审核管理</h1>
|
||||||
|
<a href="index.php" class="back-link"><i class="fas fa-arrow-left"></i> 返回首页</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<div class="message <?php echo $message_type; ?>"><?php echo $message; ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if (empty($pending_music)): ?>
|
||||||
|
<p class="message success">当前没有待审核的音乐。</p>
|
||||||
|
<?php else: ?>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>标题</th>
|
||||||
|
<th>歌手</th>
|
||||||
|
<th>上传者</th>
|
||||||
|
<th>分类</th>
|
||||||
|
<th>BV号</th>
|
||||||
|
<th>时长信息</th> <!-- 改进为时长信息列,包含用户输入和实际时长 -->
|
||||||
|
<th>上传时间</th>
|
||||||
|
<th>预览</th>
|
||||||
|
<th>操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($pending_music as $music): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo $music['id']; ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($music['title']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($music['artist']); ?></td>
|
||||||
|
<td><?php echo htmlspecialchars($music['uploader_name']); ?></td>
|
||||||
|
<td><?php echo $categories[$music['category']]; ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if (!empty($music['bvid'])): ?>
|
||||||
|
<a href="https://www.bilibili.com/video/<?php echo htmlspecialchars($music['bvid']); ?>"
|
||||||
|
target="_blank" class="bvid-link">
|
||||||
|
<?php echo htmlspecialchars($music['bvid']); ?>
|
||||||
|
</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="no-bvid">无</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="duration-info">
|
||||||
|
<?php if ($music['actual_duration']): ?>
|
||||||
|
<div>
|
||||||
|
用户输入: <span><?php echo $music['duration']; ?></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
实际时长: <span class="<?php echo $music['duration_match'] ? 'duration-match' : 'duration-mismatch'; ?>">
|
||||||
|
<?php echo $music['actual_duration']; ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<?php if (!$music['duration_match']): ?>
|
||||||
|
<div class="tooltip">
|
||||||
|
<i class="fas fa-exclamation-triangle"></i>
|
||||||
|
<span class="tooltip-text">时长不匹配,通过审核后将使用实际时长</span>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<div>
|
||||||
|
用户输入: <span><?php echo $music['duration']; ?></span>
|
||||||
|
</div>
|
||||||
|
<div class="duration-note">
|
||||||
|
<i class="fas fa-info-circle"></i> 无法获取实际音频时长
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td><?php echo $music['upload_time']; ?></td>
|
||||||
|
<td><audio controls class="audio-player">
|
||||||
|
<source src="<?php echo htmlspecialchars($music['file_path']); ?>" type="audio/mpeg">
|
||||||
|
您的浏览器不支持音频播放。
|
||||||
|
</audio></td>
|
||||||
|
<td>
|
||||||
|
<form class="action-form" method="post" onsubmit="
|
||||||
|
<?php if (!$music['duration_match'] && $music['actual_duration']): ?>
|
||||||
|
return confirm('注意:用户填写的时长与实际时长不匹配!\n用户输入: <?php echo $music['duration']; ?>\n实际时长: <?php echo $music['actual_duration']; ?>\n\n确定要通过这首音乐吗?将使用实际时长。');
|
||||||
|
<?php else: ?>
|
||||||
|
return confirm('确定要通过这首音乐吗?');
|
||||||
|
<?php endif; ?>
|
||||||
|
">
|
||||||
|
<button type="submit" name="approve_id" value="<?php echo $music['id']; ?>" class="btn btn-approve"><i class="fas fa-check"></i> 通过</button>
|
||||||
|
</form>
|
||||||
|
<form class="action-form" method="post" onsubmit="return confirm('确定要驳回并删除这首音乐吗?此操作不可恢复!');">
|
||||||
|
<button type="submit" name="reject_id" value="<?php echo $music['id']; ?>" class="btn btn-reject"><i class="fas fa-times"></i> 驳回</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
278
api.php
Normal file
278
api.php
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
// 允许跨域请求(方便其他网站调用)
|
||||||
|
header("Access-Control-Allow-Origin: *");
|
||||||
|
header("Access-Control-Allow-Methods: GET");
|
||||||
|
|
||||||
|
// 数据库连接信息
|
||||||
|
$servername = "localhost";
|
||||||
|
$username = "a1sax1m9i";
|
||||||
|
$password = "a1sax1m9i";
|
||||||
|
$dbname = "a1sax1m9i";
|
||||||
|
|
||||||
|
// 创建数据库连接
|
||||||
|
$conn = new mysqli($servername, $username, $password, $dbname);
|
||||||
|
|
||||||
|
// 检查连接
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
die(json_encode(array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "数据库连接失败: " . $conn->connect_error
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置数据库连接字符集
|
||||||
|
$conn->set_charset("utf8mb4");
|
||||||
|
|
||||||
|
// 获取硬编码音乐数据
|
||||||
|
function getHardcodedMusic() {
|
||||||
|
$musicPath = __DIR__ . '/data/music.php';
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (!file_exists($musicPath)) {
|
||||||
|
return array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "硬编码音乐文件不存在",
|
||||||
|
"data" => array()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取硬编码音乐(使用require_once并捕获返回值)
|
||||||
|
$hardcodedMusic = require_once $musicPath;
|
||||||
|
|
||||||
|
// 验证数据格式
|
||||||
|
if (is_array($hardcodedMusic)) {
|
||||||
|
return array(
|
||||||
|
"success" => true,
|
||||||
|
"message" => "成功获取硬编码音乐",
|
||||||
|
"data" => $hardcodedMusic
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "硬编码音乐格式不正确",
|
||||||
|
"data" => array()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从数据库获取音乐
|
||||||
|
function getDatabaseMusic($conn) {
|
||||||
|
$sql = "SELECT id, title, artist, category, mp3, bvid, duration FROM music";
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
$musicList = array();
|
||||||
|
if ($result && $result->num_rows > 0) {
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$musicList[] = $row;
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
"success" => true,
|
||||||
|
"message" => "成功获取数据库音乐",
|
||||||
|
"data" => $musicList
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "数据库中没有找到音乐数据",
|
||||||
|
"data" => array()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有音乐(合并数据库和硬编码)
|
||||||
|
function getAllMusic($conn) {
|
||||||
|
// 获取两种来源的音乐
|
||||||
|
$dbMusic = getDatabaseMusic($conn);
|
||||||
|
$hardcodedMusic = getHardcodedMusic();
|
||||||
|
|
||||||
|
// 合并音乐列表(去重处理)
|
||||||
|
$allMusic = array();
|
||||||
|
$ids = array();
|
||||||
|
|
||||||
|
// 添加数据库音乐
|
||||||
|
foreach ($dbMusic['data'] as $music) {
|
||||||
|
$id = $music['id'];
|
||||||
|
if (!in_array($id, $ids)) {
|
||||||
|
$ids[] = $id;
|
||||||
|
$allMusic[] = $music;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加硬编码音乐
|
||||||
|
foreach ($hardcodedMusic['data'] as $music) {
|
||||||
|
$id = $music['id'];
|
||||||
|
if (!in_array($id, $ids)) {
|
||||||
|
$ids[] = $id;
|
||||||
|
$allMusic[] = $music;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
"success" => true,
|
||||||
|
"message" => "共获取 " . count($allMusic) . " 首音乐(数据库: " . count($dbMusic['data']) . ", 硬编码: " . count($hardcodedMusic['data']) . ")",
|
||||||
|
"data" => $allMusic,
|
||||||
|
"sources" => array(
|
||||||
|
"database" => $dbMusic['success'],
|
||||||
|
"hardcoded" => $hardcodedMusic['success']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取音乐标签(合并数据库和硬编码)
|
||||||
|
function getMusicTags($conn) {
|
||||||
|
// 获取所有音乐
|
||||||
|
$allMusic = getAllMusic($conn);
|
||||||
|
$tags = array();
|
||||||
|
|
||||||
|
if ($allMusic['success']) {
|
||||||
|
foreach ($allMusic['data'] as $music) {
|
||||||
|
if (!empty($music['category']) && !in_array($music['category'], $tags)) {
|
||||||
|
$tags[] = $music['category'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
"success" => !empty($tags),
|
||||||
|
"message" => empty($tags) ? "没有找到音乐标签" : "成功获取 " . count($tags) . " 个标签",
|
||||||
|
"data" => $tags
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取音乐地址(同时检查数据库和硬编码)
|
||||||
|
/**
|
||||||
|
* 获取音乐地址(同时检查数据库和硬编码)- 修复版
|
||||||
|
* 增加了对 SQL 语句准备失败的检查,避免触发 500 错误。
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 获取音乐的分享播放URL
|
||||||
|
* 直接返回格式为 shanwogou.cn/audio/play.php?play=音乐id 的链接
|
||||||
|
*/
|
||||||
|
function getMusicUrl($conn) {
|
||||||
|
// 1. 验证输入的音乐ID
|
||||||
|
$musicId = $_GET['id'] ?? '';
|
||||||
|
if (empty($musicId)) {
|
||||||
|
return array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "音乐 ID 不能为空"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 核心逻辑:检查该ID的音乐是否存在于系统中
|
||||||
|
// (我们不再返回真实MP3地址,但需要确认音乐ID是有效的)
|
||||||
|
$musicExists = false;
|
||||||
|
|
||||||
|
// 2.1 先检查数据库
|
||||||
|
$sql = "SELECT id FROM music WHERE id = ?"; // 只需检查ID是否存在
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
|
||||||
|
if ($stmt) { // 检查prepare是否成功
|
||||||
|
$stmt->bind_param("s", $musicId);
|
||||||
|
$stmt->execute();
|
||||||
|
$stmt->store_result();
|
||||||
|
|
||||||
|
if ($stmt->num_rows > 0) {
|
||||||
|
$musicExists = true;
|
||||||
|
}
|
||||||
|
$stmt->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2 如果数据库中不存在,再检查硬编码文件
|
||||||
|
if (!$musicExists) {
|
||||||
|
$hardcodedMusic = getHardcodedMusic();
|
||||||
|
if ($hardcodedMusic['success']) {
|
||||||
|
foreach ($hardcodedMusic['data'] as $music) {
|
||||||
|
if ((string)$music['id'] === (string)$musicId) {
|
||||||
|
$musicExists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 根据检查结果返回响应
|
||||||
|
if ($musicExists) {
|
||||||
|
// 如果音乐存在,生成并返回分享URL
|
||||||
|
$shareUrl = "https://shanwogou.cn/audio/play.php?play=" . urlencode($musicId);
|
||||||
|
return array(
|
||||||
|
"success" => true,
|
||||||
|
"data" => $shareUrl,
|
||||||
|
"source" => "share_link" // 标记来源为分享链接
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 如果音乐不存在,返回错误信息
|
||||||
|
return array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "没有找到该 ID 的音乐"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAnnouncements($conn) {
|
||||||
|
// 准备SQL查询,从announcements表中获取所有记录,并按ID倒序排列(最新的在前)
|
||||||
|
$sql = "SELECT id, nr, time FROM announcements ORDER BY id DESC";
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
// 初始化一个空数组来存储公告数据
|
||||||
|
$announcementList = array();
|
||||||
|
|
||||||
|
// 检查查询是否成功且有结果
|
||||||
|
if ($result && $result->num_rows > 0) {
|
||||||
|
// 循环遍历所有结果行
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
// 将每一行公告数据添加到数组中
|
||||||
|
$announcementList[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回成功响应,包含公告数据
|
||||||
|
return array(
|
||||||
|
"success" => true,
|
||||||
|
"message" => "成功获取 " . count($announcementList) . " 条公告",
|
||||||
|
"data" => $announcementList
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 如果查询失败或没有数据,返回失败响应
|
||||||
|
return array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "没有找到公告数据或查询失败",
|
||||||
|
"data" => array()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理请求
|
||||||
|
// 处理请求
|
||||||
|
$action = $_GET['action'] ?? '';
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case 'getAllMusic':
|
||||||
|
$response = getAllMusic($conn);
|
||||||
|
break;
|
||||||
|
case 'getMusicTags':
|
||||||
|
$response = getMusicTags($conn);
|
||||||
|
break;
|
||||||
|
case 'getMusicUrl':
|
||||||
|
$response = getMusicUrl($conn);
|
||||||
|
break;
|
||||||
|
// --- 新增部分 ---
|
||||||
|
case 'getAnnouncements':
|
||||||
|
$response = getAnnouncements($conn);
|
||||||
|
break;
|
||||||
|
// --- 新增结束 ---
|
||||||
|
default:
|
||||||
|
$response = array(
|
||||||
|
"success" => false,
|
||||||
|
"message" => "无效的操作,请使用 action=getAllMusic、getMusicTags、getMusicUrl 或 getAnnouncements"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出JSON响应
|
||||||
|
echo json_encode($response, JSON_UNESCAPED_UNICODE);
|
||||||
|
|
||||||
|
// 关闭数据库连接
|
||||||
|
$conn->close();
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user