Files
NebulaShell/website/community/assets/js/polling-system.js
Falck 76147bae94 初始提交 - FutureOSS v1.0 插件化运行时框架
一切皆为插件的开发者工具运行时框架

🧩 核心特性:
  - 插件热插拔 (importlib 动态加载)
  - 依赖自动解析 (拓扑排序 + 循环检测)
  - 企业级稳定 (熔断/降级/重试/隔离)
  - 事件驱动 (发布/订阅事件总线)
  - 完整配置 (YAML 配置 + 热重载)
2026-04-06 09:57:10 +08:00

92 lines
2.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* OSS Community - 实时轮询系统
* 每2秒从数据库刷新所有数据
*/
class CommunityPollingSystem {
constructor() {
this.interval = 2000;
this.timer = null;
this.isRunning = false;
this.listeners = { user: [], posts: [], stats: [], categories: [] };
this.cache = { user: null, posts: null, stats: null, categories: null };
}
start() {
if (this.isRunning) return;
this.isRunning = true;
this._fetchAll();
this.timer = setInterval(() => this._fetchAll(), this.interval);
}
stop() {
clearInterval(this.timer);
this.isRunning = false;
this.timer = null;
}
on(event, callback) {
if (this.listeners[event]) this.listeners[event].push(callback);
}
async _fetch(url) {
try {
const res = await fetch(url);
return res.ok ? await res.json() : null;
} catch { return null; }
}
async _fetchAll() {
// 并行请求所有接口
const [userData, postsData, statsData, catsData] = await Promise.all([
this._fetch('api/auth.php?action=current-user'),
this._fetch('api/index.php?action=posts'),
this._fetch('api/index.php?action=stats'),
this._fetch('api/index.php?action=categories')
]);
// 用户数据
if (userData && userData.success) {
const changed = JSON.stringify(userData) !== JSON.stringify(this.cache.user);
this.cache.user = userData;
if (changed) this._notify('user', userData);
}
// 帖子数据(含 views, likes, replies
if (postsData && postsData.posts) {
const changed = JSON.stringify(postsData.posts) !== JSON.stringify(this.cache.posts);
this.cache.posts = postsData.posts;
if (changed) this._notify('posts', postsData);
}
// 统计数据(含 hot_posts
if (statsData) {
const changed = JSON.stringify(statsData) !== JSON.stringify(this.cache.stats);
this.cache.stats = statsData;
if (changed) this._notify('stats', statsData);
}
// 分类
if (catsData && catsData.categories) {
const changed = JSON.stringify(catsData.categories) !== JSON.stringify(this.cache.categories);
this.cache.categories = catsData.categories;
if (changed) this._notify('categories', catsData);
}
}
_notify(event, data) {
(this.listeners[event] || []).forEach(fn => {
try { fn(data); } catch(e) {}
});
}
}
window.Polling = new CommunityPollingSystem();
document.addEventListener('DOMContentLoaded', () => {
const dock = document.getElementById('dock');
if (dock && dock.dataset.loggedIn === '1') {
window.Polling.start();
}
});