207 lines
6.0 KiB
JavaScript
207 lines
6.0 KiB
JavaScript
/**
|
||
* bulletin.js - M22公告栏主逻辑
|
||
* 修复URL编码问题 · 频道筛选正常
|
||
*/
|
||
|
||
document.addEventListener('DOMContentLoaded', async () => {
|
||
// 显示骨架屏
|
||
showSkeleton();
|
||
|
||
// 初始化频道
|
||
initializeChannels();
|
||
|
||
// 加载公告数据
|
||
await loadAnnouncements();
|
||
|
||
// 监听路由变化
|
||
window.addEventListener('hashchange', handleRouteChange);
|
||
});
|
||
|
||
// 当前频道
|
||
let currentChannel = '全部';
|
||
|
||
// 所有公告数据
|
||
let allAnnouncements = [];
|
||
|
||
// 初始化频道
|
||
function initializeChannels() {
|
||
const channelTabs = document.querySelectorAll('.channel-tab');
|
||
|
||
// 从URL Hash恢复当前频道(需要解码)
|
||
const rawHash = window.location.hash.slice(1) || '全部';
|
||
currentChannel = decodeURIComponent(rawHash);
|
||
|
||
// 设置激活状态并绑定事件
|
||
channelTabs.forEach(tab => {
|
||
const channel = tab.dataset.channel;
|
||
|
||
if (channel === currentChannel) {
|
||
tab.classList.add('active');
|
||
} else {
|
||
tab.classList.remove('active');
|
||
}
|
||
|
||
// 绑定点击事件
|
||
tab.onclick = function(e) {
|
||
e.preventDefault();
|
||
const clickChannel = this.dataset.channel;
|
||
console.log('点击频道:', clickChannel);
|
||
// 直接设置中文hash,浏览器会自动编码
|
||
window.location.hash = clickChannel;
|
||
};
|
||
});
|
||
}
|
||
|
||
// 显示骨架屏
|
||
function showSkeleton() {
|
||
const skeletonContainer = document.getElementById('skeleton-container');
|
||
if (skeletonContainer) {
|
||
skeletonContainer.style.display = 'block';
|
||
}
|
||
|
||
const bulletinContainer = document.querySelector('.bulletin-container');
|
||
if (bulletinContainer) {
|
||
bulletinContainer.innerHTML = '';
|
||
}
|
||
}
|
||
|
||
// 隐藏骨架屏
|
||
function hideSkeleton() {
|
||
const skeletonContainer = document.getElementById('skeleton-container');
|
||
if (skeletonContainer) {
|
||
skeletonContainer.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
// 渲染公告(带筛选功能)
|
||
function renderAnnouncements(announcements) {
|
||
// 隐藏骨架屏
|
||
hideSkeleton();
|
||
|
||
const container = document.querySelector('.bulletin-container');
|
||
if (!container) return;
|
||
|
||
console.log('当前频道:', currentChannel, '总公告数:', announcements.length);
|
||
|
||
// 根据当前频道筛选
|
||
let filtered = [];
|
||
if (currentChannel === '全部') {
|
||
filtered = announcements;
|
||
} else {
|
||
filtered = announcements.filter(a => a.channel === currentChannel);
|
||
}
|
||
|
||
console.log('筛选后条数:', filtered.length);
|
||
|
||
// 如果没有公告,显示空状态
|
||
if (filtered.length === 0) {
|
||
container.innerHTML = `
|
||
<div class="empty-state">
|
||
<div class="empty-icon">📭</div>
|
||
<div class="empty-title">这里还没有公告</div>
|
||
<div class="empty-desc">当前频道「${currentChannel}」没有公告</div>
|
||
</div>
|
||
`;
|
||
return;
|
||
}
|
||
|
||
// 生成公告HTML
|
||
let html = '';
|
||
for (let i = 0; i < filtered.length; i++) {
|
||
const a = filtered[i];
|
||
html += `
|
||
<article class="bulletin-item">
|
||
<h2 class="bulletin-title">${a.title}</h2>
|
||
<div class="bulletin-meta">
|
||
<span class="bulletin-channel">#${a.channel}</span>
|
||
<time class="bulletin-date">${a.date}</time>
|
||
</div>
|
||
<div class="bulletin-content">${a.content}</div>
|
||
</article>
|
||
`;
|
||
}
|
||
|
||
container.innerHTML = html;
|
||
|
||
// 更新底部计数
|
||
const totalSpan = document.getElementById('totalCount');
|
||
if (totalSpan) {
|
||
totalSpan.textContent = announcements.length;
|
||
}
|
||
}
|
||
|
||
// 路由变化处理
|
||
function handleRouteChange() {
|
||
// 获取hash并解码(比如 %E5%9B%A2%E9%98%9F%E6%B6%88%E6%81%AF -> 团队消息)
|
||
const rawHash = window.location.hash.slice(1) || '全部';
|
||
const newChannel = decodeURIComponent(rawHash);
|
||
|
||
console.log('路由变化 - 原始hash:', rawHash, '解码后:', newChannel, '当前频道:', currentChannel);
|
||
|
||
if (newChannel !== currentChannel) {
|
||
currentChannel = newChannel;
|
||
|
||
// 更新频道激活状态
|
||
document.querySelectorAll('.channel-tab').forEach(tab => {
|
||
const channel = tab.dataset.channel;
|
||
if (channel === newChannel) {
|
||
tab.classList.add('active');
|
||
} else {
|
||
tab.classList.remove('active');
|
||
}
|
||
});
|
||
|
||
// 重新渲染
|
||
if (allAnnouncements && allAnnouncements.length > 0) {
|
||
console.log('重新渲染,当前频道:', currentChannel);
|
||
renderAnnouncements(allAnnouncements);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 加载公告
|
||
async function loadAnnouncements() {
|
||
try {
|
||
const result = await bulletinAPI.getAnnouncements();
|
||
|
||
if (result.success) {
|
||
allAnnouncements = result.data;
|
||
renderAnnouncements(result.data);
|
||
console.log(`[公告加载] 成功 | 条数: ${result.data.length}`);
|
||
|
||
} else {
|
||
showError(result.error);
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('加载公告失败:', error);
|
||
showError({
|
||
title: '🧸 出错了',
|
||
message: '加载公告时遇到问题',
|
||
retryable: true
|
||
});
|
||
}
|
||
}
|
||
|
||
// 显示错误
|
||
function showError(errorInfo) {
|
||
hideSkeleton();
|
||
|
||
const container = document.querySelector('.bulletin-container');
|
||
if (!container) return;
|
||
|
||
const retryButton = errorInfo.retryable ?
|
||
`<button class="retry-btn" onclick="window.loadAnnouncements()">重试</button>` : '';
|
||
|
||
container.innerHTML = `
|
||
<div class="error-state">
|
||
<div class="error-icon">🧸</div>
|
||
<div class="error-title">${errorInfo.title || '哎呀'}</div>
|
||
<div class="error-message">${errorInfo.message || '服务暂时不可用'}</div>
|
||
${retryButton}
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
// 暴露给全局
|
||
window.loadAnnouncements = loadAnnouncements; |