feat: 添加公告功能

This commit is contained in:
2025-12-13 18:40:42 +08:00
parent d7d878dc08
commit 7015de0055
4 changed files with 584 additions and 3 deletions

View File

@@ -621,6 +621,22 @@
<button class="fab" onclick="openAddAccountModal()" title="添加账号"><span class="fab-icon">+</span><span class="fab-text">添加账号</span></button>
<div class="toast-container" id="toastContainer"></div>
<!-- 公告弹窗 -->
<div class="modal-overlay" id="announcementModal" onclick="if(event.target===this)closeAnnouncementOnce()">
<div class="modal" style="max-width: 560px;">
<div class="modal-header">
<h3 class="modal-title" id="announcementModalTitle">系统公告</h3>
</div>
<div class="modal-body">
<div id="announcementModalContent" style="white-space: pre-wrap;"></div>
</div>
<div class="modal-footer">
<button class="btn btn-text" onclick="closeAnnouncementOnce()">当次关闭</button>
<button class="btn btn-primary" onclick="dismissAnnouncementPermanently()">永久关闭</button>
</div>
</div>
</div>
<!-- 添加账号弹窗 -->
<div class="modal-overlay" id="addAccountModal">
<div class="modal">
@@ -1040,10 +1056,63 @@
updateAccountLimitDisplay();
});
}
let currentAnnouncementId = null;
async function checkAnnouncement() {
try {
const response = await fetch('/api/announcements/active');
if (!response.ok) return;
const data = await response.json();
const announcement = data?.announcement;
if (!announcement || !announcement.id) return;
const sessionKey = `announcement_closed_${announcement.id}`;
try {
if (sessionStorage.getItem(sessionKey)) return;
} catch (e) {
// ignore
}
currentAnnouncementId = announcement.id;
const titleEl = document.getElementById('announcementModalTitle');
const contentEl = document.getElementById('announcementModalContent');
if (titleEl) titleEl.textContent = announcement.title || '系统公告';
if (contentEl) contentEl.textContent = announcement.content || '';
openModal('announcementModal');
} catch (e) {
// ignore
}
}
function closeAnnouncementOnce() {
if (currentAnnouncementId) {
try {
sessionStorage.setItem(`announcement_closed_${currentAnnouncementId}`, '1');
} catch (e) {
// ignore
}
}
closeModal('announcementModal');
}
async function dismissAnnouncementPermanently() {
if (!currentAnnouncementId) {
closeModal('announcementModal');
return;
}
try {
await fetch(`/api/announcements/${currentAnnouncementId}/dismiss`, { method: 'POST' });
} catch (e) {
// ignore
}
closeAnnouncementOnce();
}
document.addEventListener('DOMContentLoaded', function() {
initTabs();
loadVipStatus();
loadAccounts(); // 主动加载账号列表
checkAnnouncement();
loadStats();
loadSchedules();
loadScreenshots();
@@ -2086,6 +2155,16 @@
}
function logout() {
try {
for (let i = sessionStorage.length - 1; i >= 0; i--) {
const key = sessionStorage.key(i);
if (key && key.startsWith('announcement_closed_')) {
sessionStorage.removeItem(key);
}
}
} catch (e) {
// ignore
}
fetch('/api/logout', {method: 'POST'})
.then(() => { window.location.href = '/login'; })
.catch(() => { window.location.href = '/login'; });
@@ -2298,4 +2377,4 @@
});
</script>
</body>
</html>
</html>