refactor(assets): 将CDN资源替换为本地文件并添加推荐功能

将Bootstrap和Font Awesome从CDN引用改为本地文件引用,提高加载可靠性
在首页为登录用户添加基于标签的个性化应用推荐功能
使用SweetAlert2替换原生alert提升用户体验
This commit is contained in:
2025-07-07 16:40:02 +08:00
parent f9f52f1e4b
commit 971e3b8d58
15 changed files with 162 additions and 21 deletions

View File

@@ -102,9 +102,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_app'])) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>添加App - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Fluent Design 模糊效果 -->
<style>
.blur-bg {
@@ -311,14 +312,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_app'])) {
// 验证Windows子选项
if (document.getElementById('windows').checked && !document.querySelector('input[name="windows_version"]:checked')) {
e.preventDefault();
alert('请选择Windows版本XP以前或Win7以后');
Swal.fire({
title: '提示',
text: '请选择Windows版本XP以前或Win7以后',
icon: 'warning',
confirmButtonText: '确定'
});
return;
}
// 验证Linux子选项
if (document.getElementById('linux').checked && !document.querySelector('input[name="linux_distribution"]:checked')) {
e.preventDefault();
alert('请选择Linux发行版Ubuntu、Arch Linux或CentOS');
Swal.fire({
title: '提示',
text: '请选择Linux发行版Ubuntu、Arch Linux或CentOS',
icon: 'warning',
confirmButtonText: '确定'
});
return;
}

View File

@@ -113,9 +113,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['edit_app'])) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>编辑App - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Fluent Design 模糊效果 -->
<style>
.blur-bg {
@@ -352,14 +353,24 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['edit_app'])) {
// 验证Windows子选项
if (document.getElementById('windows').checked && !document.querySelector('input[name="windows_version"]:checked')) {
e.preventDefault();
alert('请选择Windows版本XP以前或Win7以后');
Swal.fire({
title: '提示',
text: '请选择Windows版本XP以前或Win7以后',
icon: 'warning',
confirmButtonText: '确定'
});
return;
}
// 验证Linux子选项
if (document.getElementById('linux').checked && !document.querySelector('input[name="linux_distribution"]:checked')) {
e.preventDefault();
alert('请选择Linux发行版Ubuntu、Arch Linux或CentOS');
Swal.fire({
title: '提示',
text: '请选择Linux发行版Ubuntu、Arch Linux或CentOS',
icon: 'warning',
confirmButtonText: '确定'
});
return;
}

View File

@@ -31,7 +31,7 @@ if (!$resultApps) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>App管理 - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<!-- Fluent Design 模糊效果 -->

View File

@@ -25,7 +25,7 @@ if (!isset($_SESSION['admin'])) {
echo ' <meta name="viewport" content="width=device-width, initial-scale=1.0">';
echo ' <title>管理员登录 - '. APP_STORE_NAME . '</title>';
echo ' <!-- Bootstrap CSS -->';
echo ' <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">';
echo ' <link href="../css/bootstrap.min.css" rel="stylesheet">';
echo ' <!-- 自定义CSS -->';
echo ' <link rel="stylesheet" href="../styles.css">';
echo ' <!-- Fluent Design 模糊效果 -->';

View File

@@ -59,7 +59,7 @@ $tagsResult = $conn->query("SELECT * FROM tags ORDER BY created_at DESC");
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>标签管理 - 应用商店后台</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">

View File

@@ -180,7 +180,7 @@ if (isset($_GET['success'])) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>管理版本 - <?php echo htmlspecialchars($app['name']); ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<style>

View File

@@ -71,7 +71,7 @@ if (!($conn instanceof mysqli)) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>应用审核 - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<!-- Fluent Design 模糊效果 -->

View File

@@ -58,9 +58,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['rating'])) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $app['name']; ?> - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="css/all.min.css">
<!-- 本地 Chart.js -->
<script src="js/charts.js"></script>
<!-- 自定义CSS -->

9
css/all.min.css vendored Normal file

File diff suppressed because one or more lines are too long

6
css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -44,7 +44,7 @@ if (!($conn instanceof mysqli)) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>开发者仪表盘 - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<style>

View File

@@ -195,9 +195,10 @@ if (!($conn instanceof mysqli)) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传应用 - <?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="../styles.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Fluent Design 模糊效果 -->
<style>
.blur-bg {
@@ -302,7 +303,12 @@ if (!($conn instanceof mysqli)) {
const file = this.files[0];
const ext = file.name.split('.').pop().toLowerCase();
if (file.size > 100 * 1024 * 1024) { // 100MB限制
alert('文件大小不能超过100MB');
Swal.fire({
title: '提示',
text: '文件大小不能超过100MB',
icon: 'warning',
confirmButtonText: '确定'
});
this.value = '';
}
}
@@ -313,7 +319,12 @@ if (!($conn instanceof mysqli)) {
for (let i = 0; i < this.files.length; i++) {
const file = this.files[i];
if (file.size > 10 * 1024 * 1024) { // 10MB限制
alert(`图片 ${file.name} 大小不能超过10MB`);
Swal.fire({
title: '提示',
text: `图片 ${file.name} 大小不能超过10MB`,
icon: 'warning',
confirmButtonText: '确定'
});
this.value = '';
return;
}

View File

@@ -12,9 +12,10 @@ if (!isset($conn) || !$conn instanceof mysqli) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo APP_STORE_NAME; ?></title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="styles.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- Fluent Design 模糊效果 -->
<style>
.blur-bg {
@@ -68,7 +69,12 @@ if (!isset($conn) || !$conn instanceof mysqli) {
function validateSearch() {
const searchInput = document.querySelector('input[name="search"]');
if (searchInput.value.trim() === '') {
alert('请填写搜索名称后再进行搜索!');
Swal.fire({
title: '提示',
text: '请填写搜索名称后再进行搜索!',
icon: 'warning',
confirmButtonText: '确定'
});
return false;
}
return true;
@@ -96,6 +102,93 @@ if (!isset($conn) || !$conn instanceof mysqli) {
</div>
</div>
</form>
<?php if (isset($_SESSION['user_id'])): ?>
<h1>为你推荐</h1>
<div class="row">
<?php
// 获取用户下载过的应用标签
$userId = $_SESSION['user_id'];
$tagSql = "SELECT DISTINCT t.id FROM tags t
JOIN app_tags at ON t.id = at.tag_id
JOIN app_versions av ON at.app_id = av.app_id
JOIN download_history dh ON av.id = dh.version_id
WHERE dh.user_id = ?";
$tagStmt = $conn->prepare($tagSql);
$tagStmt->bind_param('i', $userId);
$tagStmt->execute();
$tagResult = $tagStmt->get_result();
$tagIds = [];
while ($tag = $tagResult->fetch_assoc()) {
$tagIds[] = $tag['id'];
}
$tagStmt->close();
// 获取用户已下载的应用
$downloadedSql = "SELECT DISTINCT a.id FROM apps a
JOIN app_versions av ON a.id = av.app_id
JOIN download_history dh ON av.id = dh.version_id
WHERE dh.user_id = ?";
$downloadedStmt = $conn->prepare($downloadedSql);
$downloadedStmt->bind_param('i', $userId);
$downloadedStmt->execute();
$downloadedResult = $downloadedStmt->get_result();
$downloadedIds = [];
while ($app = $downloadedResult->fetch_assoc()) {
$downloadedIds[] = $app['id'];
}
$downloadedStmt->close();
// 基于标签推荐应用
if (!empty($tagIds)) {
$placeholders = implode(',', array_fill(0, count($tagIds), '?'));
$recommendSql = "SELECT a.id, a.name, a.description, a.age_rating, AVG(r.rating) as avg_rating
FROM apps a
LEFT JOIN reviews r ON a.id = r.app_id
JOIN app_tags at ON a.id = at.app_id
WHERE at.tag_id IN ($placeholders)
AND a.id NOT IN (" . (!empty($downloadedIds) ? implode(',', $downloadedIds) : '0') . ")
AND a.status = 'approved'
GROUP BY a.id
ORDER BY COUNT(at.tag_id) DESC
LIMIT 12";
$recommendStmt = $conn->prepare($recommendSql);
$types = str_repeat('i', count($tagIds));
$recommendStmt->bind_param($types, ...$tagIds);
$recommendStmt->execute();
$recommendResult = $recommendStmt->get_result();
} else {
// 如果没有标签数据,显示热门应用
$recommendSql = "SELECT a.id, a.name, a.description, a.age_rating, AVG(r.rating) as avg_rating, SUM(av.download_count) as total_downloads
FROM apps a
LEFT JOIN reviews r ON a.id = r.app_id
LEFT JOIN app_versions av ON a.id = av.app_id
WHERE a.status = 'approved'
GROUP BY a.id
ORDER BY total_downloads DESC
LIMIT 12";
$recommendResult = $conn->query($recommendSql);
}
if ($recommendResult && $recommendResult->num_rows > 0) {
while ($row = $recommendResult->fetch_assoc()) {
echo '<div class="col-md-3 mb-4">';
echo '<div class="card blur-bg">';
echo '<img src="images/default.png" class="card-img-top" alt="'. htmlspecialchars($row['name']) . '">';
echo '<div class="card-body">';
echo '<h5 class="card-title">'. htmlspecialchars($row['name']) . '</h5>';
echo '<p class="card-text">'. substr(htmlspecialchars($row['description']), 0, 100) . '...</p>';
echo '<p class="card-text">评分: '. round($row['avg_rating'] ?? 0, 1) . '/5</p>';
echo '<a href="app.php?id='. $row['id'] . '" class="btn btn-primary">查看详情</a>';
echo '</div></div></div>';
}
} else {
echo '<div class="col-12"><p class="text-center">暂无推荐内容</p></div>';
}
if (isset($recommendStmt)) $recommendStmt->close();
?>
</div>
<?php endif; ?>
<h1>最新应用</h1>
<div class="row">
<!-- 这里将通过PHP动态加载应用列表 -->

View File

@@ -73,7 +73,7 @@ $tagResult = $conn->query("SELECT id, name FROM tags ORDER BY name");
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>应用标签</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="styles.css">
<!-- Fluent Design 模糊效果 -->

View File

@@ -39,7 +39,7 @@ while ($row = $result->fetch_assoc()) {
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo htmlspecialchars($app['name']); ?> - 版本历史</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 自定义CSS -->
<link rel="stylesheet" href="styles.css">
<style>