⚡ 初始提交 - FutureOSS v1.0 插件化运行时框架
一切皆为插件的开发者工具运行时框架
🧩 核心特性:
- 插件热插拔 (importlib 动态加载)
- 依赖自动解析 (拓扑排序 + 循环检测)
- 企业级稳定 (熔断/降级/重试/隔离)
- 事件驱动 (发布/订阅事件总线)
- 完整配置 (YAML 配置 + 热重载)
This commit is contained in:
91
website/community/assets/js/polling-system.js
Normal file
91
website/community/assets/js/polling-system.js
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user