refactor(assets): 将CDN资源替换为本地文件并添加推荐功能
将Bootstrap和Font Awesome从CDN引用改为本地文件引用,提高加载可靠性 在首页为登录用户添加基于标签的个性化应用推荐功能 使用SweetAlert2替换原生alert提升用户体验
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 模糊效果 -->
|
||||
|
||||
@@ -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 模糊效果 -->';
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 模糊效果 -->
|
||||
|
||||
4
app.php
4
app.php
@@ -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
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
6
css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
97
index.php
97
index.php
@@ -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动态加载应用列表 -->
|
||||
|
||||
2
tags.php
2
tags.php
@@ -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 模糊效果 -->
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user