475 lines
11 KiB
HTML
Executable File
475 lines
11 KiB
HTML
Executable File
{% extends "base.html" %}
|
||
|
||
{% block content %}
|
||
<div class="coming-apps-page">
|
||
<div id="toast" class="developing-tip">
|
||
<span id="toastMessage"></span>
|
||
</div>
|
||
|
||
<div class="header">
|
||
<a href="{{ url_for('explore') }}" class="back-link" title="返回探索">
|
||
<i class="fas fa-arrow-left"></i>
|
||
</a>
|
||
<h1>即将上线</h1>
|
||
</div>
|
||
|
||
<div class="apps-grid">
|
||
{% if coming_apps %}
|
||
{% for app in coming_apps %}
|
||
<div class="app-tile">
|
||
<div class="app-tile-content">
|
||
<div class="app-tile-icon">
|
||
{% if 'http' in app.icon_path %}
|
||
<img src="{{ app.icon_path }}" alt="{{ app.name }}">
|
||
{% else %}
|
||
<img src="{{ url_for('static', filename='uploads/' + app.icon_path) }}" alt="{{ app.name }}">
|
||
{% endif %}
|
||
</div>
|
||
<div class="app-tile-info">
|
||
<div class="app-tile-header">
|
||
<h3>{{ app.name }}</h3>
|
||
<button class="add-reminder-btn" onclick="toggleWishlist('{{ app.name }}')" title="添加提醒" data-app-name="{{ app.name }}">
|
||
<i class="fas fa-bell"></i>
|
||
</button>
|
||
</div>
|
||
<div class="app-tile-meta">
|
||
<span class="coming-soon-tag">即将上线</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
{% else %}
|
||
<div class="no-apps-message">暂无即将上线应用</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.coming-apps-page {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 60px 15px 20px 15px;
|
||
transform: none !important;
|
||
transition: none !important;
|
||
}
|
||
|
||
.header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
margin-bottom: 30px;
|
||
background: white;
|
||
padding: 10px 15px;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
transform: none !important;
|
||
transition: none !important;
|
||
}
|
||
|
||
.back-link {
|
||
color: #666;
|
||
text-decoration: none;
|
||
padding: 8px;
|
||
border-radius: 50%;
|
||
background: #f5f5f7;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 32px;
|
||
height: 32px;
|
||
transform: none !important;
|
||
transition: none !important;
|
||
}
|
||
|
||
.back-link:hover {
|
||
background: #e5e5e7;
|
||
color: #333;
|
||
}
|
||
|
||
.header h1 {
|
||
margin: 0;
|
||
font-size: 20px;
|
||
color: #333;
|
||
font-weight: 500;
|
||
font-family: "SimHei", "黑体", sans-serif;
|
||
transform: none !important;
|
||
transition: none !important;
|
||
}
|
||
|
||
.apps-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||
gap: 15px;
|
||
}
|
||
|
||
.app-tile {
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.app-tile-content {
|
||
padding: 15px;
|
||
display: flex;
|
||
gap: 12px;
|
||
position: relative;
|
||
}
|
||
|
||
.app-tile-icon {
|
||
width: 64px;
|
||
height: 64px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.app-tile-icon img {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 16px;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.app-tile-info {
|
||
flex: 1;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.app-tile-header {
|
||
margin-bottom: 8px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.app-tile-header h3 {
|
||
margin: 0 0 6px 0;
|
||
font-size: 16px;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.coming-soon-tag {
|
||
display: inline-block;
|
||
font-size: 12px;
|
||
color: #0066cc;
|
||
background: rgba(0, 102, 204, 0.1);
|
||
padding: 2px 8px;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
.no-apps-message {
|
||
grid-column: 1 / -1;
|
||
text-align: center;
|
||
padding: 40px;
|
||
color: #666;
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.app-tile-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
.add-reminder-btn {
|
||
border: none;
|
||
background: rgba(0, 102, 204, 0.1);
|
||
color: #0066cc;
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.3s ease;
|
||
margin-left: 8px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.add-reminder-btn:hover {
|
||
background: rgba(0, 102, 204, 0.2);
|
||
color: #0066cc;
|
||
transform: scale(1.05);
|
||
}
|
||
|
||
.add-reminder-btn.active {
|
||
background: #0066cc;
|
||
color: white;
|
||
}
|
||
|
||
.add-reminder-btn.active:hover {
|
||
background: #0052a3;
|
||
color: white;
|
||
}
|
||
|
||
.add-reminder-btn i {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.developing-tip {
|
||
position: fixed;
|
||
bottom: 100px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: rgba(0, 0, 0, 0.8);
|
||
color: white;
|
||
padding: 10px 20px;
|
||
border-radius: 25px;
|
||
font-size: 14px;
|
||
z-index: 1000;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease, transform 0.3s ease;
|
||
pointer-events: none;
|
||
transform: translate(-50%, 20px);
|
||
}
|
||
|
||
[data-theme="dark"] .developing-tip {
|
||
background: rgba(255, 255, 255, 0.9);
|
||
color: black;
|
||
}
|
||
|
||
.developing-tip.show {
|
||
opacity: 1;
|
||
transform: translate(-50%, 0);
|
||
}
|
||
|
||
@keyframes tipAppear {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translate(-50%, 20px);
|
||
}
|
||
20% {
|
||
opacity: 1;
|
||
transform: translate(-50%, 0);
|
||
}
|
||
80% {
|
||
opacity: 1;
|
||
transform: translate(-50%, 0);
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
transform: translate(-50%, -20px);
|
||
}
|
||
}
|
||
|
||
.developing-tip.show {
|
||
animation: tipAppear 2s ease forwards;
|
||
}
|
||
|
||
/* 暗色模式样式 */
|
||
[data-theme="dark"] .add-reminder-btn {
|
||
background: rgba(94, 158, 255, 0.1);
|
||
color: #5E9EFF;
|
||
}
|
||
|
||
[data-theme="dark"] .add-reminder-btn:hover {
|
||
background: rgba(94, 158, 255, 0.2);
|
||
color: #5E9EFF;
|
||
}
|
||
|
||
[data-theme="dark"] .add-reminder-btn.active {
|
||
background: #5E9EFF;
|
||
color: white;
|
||
}
|
||
|
||
[data-theme="dark"] .add-reminder-btn.active:hover {
|
||
background: #4b8fef;
|
||
color: white;
|
||
}
|
||
|
||
[data-theme="dark"] .coming-apps-page {
|
||
background: #1a1a1a;
|
||
}
|
||
|
||
[data-theme="dark"] .header {
|
||
background: #242424;
|
||
}
|
||
|
||
[data-theme="dark"] .header h1 {
|
||
color: #fff;
|
||
}
|
||
|
||
[data-theme="dark"] .back-link {
|
||
color: #ccc;
|
||
background: #333;
|
||
}
|
||
|
||
[data-theme="dark"] .back-link:hover {
|
||
background: #444;
|
||
color: #fff;
|
||
}
|
||
|
||
[data-theme="dark"] .app-tile {
|
||
background: #242424;
|
||
}
|
||
|
||
[data-theme="dark"] .app-tile-header h3 {
|
||
color: #fff;
|
||
}
|
||
|
||
[data-theme="dark"] .no-apps-message {
|
||
background: #242424;
|
||
color: #ccc;
|
||
}
|
||
|
||
[data-theme="dark"] .coming-soon-tag {
|
||
background: rgba(94, 158, 255, 0.1);
|
||
color: #5E9EFF;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.apps-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
// 存储心愿单应用列表
|
||
let wishlistApps = new Set();
|
||
|
||
// 加载心愿单
|
||
function loadWishlist() {
|
||
fetch('/user/wishlist/list')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
// 清空并重新填充心愿单集合
|
||
wishlistApps.clear();
|
||
data.items.forEach(item => wishlistApps.add(item.app_name));
|
||
|
||
// 更新所有按钮状态
|
||
updateAllButtonStates();
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Load wishlist failed:', error);
|
||
});
|
||
}
|
||
|
||
// 更新所有按钮状态
|
||
function updateAllButtonStates() {
|
||
document.querySelectorAll('.add-reminder-btn').forEach(btn => {
|
||
const appName = btn.dataset.appName;
|
||
updateButtonState(btn, wishlistApps.has(appName));
|
||
});
|
||
}
|
||
|
||
// 更新单个按钮状态
|
||
function updateButtonState(button, isActive) {
|
||
const icon = button.querySelector('i');
|
||
if (isActive) {
|
||
button.classList.add('active');
|
||
button.title = '取消提醒';
|
||
icon.className = 'fas fa-check-circle';
|
||
} else {
|
||
button.classList.remove('active');
|
||
button.title = '添加提醒';
|
||
icon.className = 'fas fa-bell';
|
||
}
|
||
}
|
||
|
||
// 切换心愿单状态
|
||
function toggleWishlist(appName) {
|
||
const button = document.querySelector(`.add-reminder-btn[data-app-name="${appName}"]`);
|
||
const isRemoving = wishlistApps.has(appName);
|
||
|
||
if (isRemoving) {
|
||
// 获取项目ID并删除
|
||
fetch('/user/wishlist/list')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
const item = data.items.find(item => item.app_name === appName);
|
||
if (item) {
|
||
deleteFromWishlist(item.id);
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
addToWishlist(appName);
|
||
}
|
||
}
|
||
|
||
// 添加到心愿单
|
||
function addToWishlist(appName) {
|
||
fetch('/user/wishlist/add', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({
|
||
app_name: appName
|
||
})
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
wishlistApps.add(appName);
|
||
updateAllButtonStates();
|
||
showToast('添加成功');
|
||
} else {
|
||
if (data.error.includes('邀请3位好友')) {
|
||
showToast('当前最多添加5个应用,邀请3位好友可提升至20个');
|
||
} else if (data.error.includes('已达到心愿单上限')) {
|
||
showToast('已达到心愿单上限(20个)');
|
||
} else {
|
||
showToast(data.error || '添加失败');
|
||
}
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Add to wishlist failed:', error);
|
||
showToast('添加失败,请稍后重试');
|
||
});
|
||
}
|
||
|
||
// 从心愿单中删除
|
||
function deleteFromWishlist(itemId) {
|
||
fetch(`/user/wishlist/delete/${itemId}`, {
|
||
method: 'POST'
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
loadWishlist(); // 重新加载心愿单以更新状态
|
||
showToast('已取消提醒');
|
||
} else {
|
||
showToast(data.error || '取消失败');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Delete from wishlist failed:', error);
|
||
showToast('取消失败,请稍后重试');
|
||
});
|
||
}
|
||
|
||
// Toast 提示函数
|
||
function showToast(message) {
|
||
const toast = document.getElementById('toast');
|
||
const toastMessage = document.getElementById('toastMessage');
|
||
toastMessage.textContent = message;
|
||
toast.classList.add('show');
|
||
|
||
setTimeout(() => {
|
||
toast.classList.remove('show');
|
||
}, 2000);
|
||
}
|
||
|
||
// 返回按钮处理
|
||
document.querySelector('.back-link').addEventListener('click', function(e) {
|
||
e.preventDefault();
|
||
window.history.back();
|
||
});
|
||
|
||
// 页面加载时获取心愿单
|
||
document.addEventListener('DOMContentLoaded', loadWishlist);
|
||
</script>
|
||
{% endblock %} |