chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,202 @@
/**
* 事件轮询 Hook
*
* 全局事件轮询逻辑,与 PC 端 useEventPolling.ts 功能一致
* 适配 uni-app x 框架,使用 setInterval 实现轮询
* 使用 eventBus 封装层发布事件(内部基于 uni.$emit
*
* 自动处理的场景:
* - H5页面切换到后台visibilitychange或切换标签页时暂停回来后恢复
* - 小程序:需要在 App.uvue 的 onHide/onShow 中手动调用 stop/start
*
* 使用方式:
* - 在 App.uvue 的 onLaunch 中调用 initEventPolling() 初始化
* - 在 App.uvue 的 onHide 中调用 stopEventPolling()(小程序需要)
* - 在 App.uvue 的 onShow 中调用 startEventPolling()(小程序需要)
*
* 订阅事件:
* - eventBus.on(EVENT_TYPE.RefreshFileList, handler)
* - eventBus.off(EVENT_TYPE.RefreshFileList, handler)
*/
import { apiCollectEvent, apiClearEvent, ApiCollectEventResponse } from '@/servers/event';
import eventBus from '@/utils/eventBus';
import { SUCCESS_CODE } from '@/constants/codes.constants';
import { ACCESS_TOKEN } from '@/constants/home.constants';
// 轮询间隔(毫秒)
const POLLING_INTERVAL = 5000;
// 轮询定时器 ID
let pollingTimerId: number | null = null;
// 是否正在处理事件(避免并发处理)
let isProcessing = false;
// 是否已初始化 H5 可见性监听
let isVisibilityListenerInitialized = false;
// 是否已登录(未登录不轮询)
// function isLoggedIn(): boolean {
// const token = uni.getStorageSync(ACCESS_TOKEN);
// return !!token;
// }
/**
* 执行一次轮询
*/
async function pollOnce(): Promise<void> {
// 未登录不轮询
// if (!isLoggedIn()) {
// return;
// }
// 如果正在处理,跳过本次
if (isProcessing) {
console.log('[EventPolling] 跳过重复的事件处理');
return;
}
try {
const response = await apiCollectEvent();
const data = response as any;
// 检查响应是否有效
if (!data || data.code !== SUCCESS_CODE) {
return;
}
const result: ApiCollectEventResponse = data.data;
// 如果有事件需要处理
if (result?.hasEvent && result?.eventList?.length > 0) {
try {
// 标记开始处理
isProcessing = true;
// 暂停轮询
stopEventPolling();
// 遍历所有事件,使用 eventBus 发布事件
for (const event of result.eventList) {
// console.log('[EventPolling] 发布事件:', event.type, event.event);
eventBus.emit(event.type, event.event);
}
// 清除已处理的事件
await apiClearEvent();
} catch (error) {
console.error('[EventPolling] 处理事件时出错:', error);
} finally {
// 重新开始轮询
startEventPolling();
// 处理完成
isProcessing = false;
}
}
} catch (error) {
console.error('[EventPolling] 轮询请求失败:', error);
}
}
/**
* 处理 H5 页面可见性变化
* 切换标签页或最小化时暂停轮询,回来后恢复
*/
function handleVisibilityChange(): void {
// #ifdef H5 || WEB
if (document.hidden) {
console.log('[EventPolling] H5 页面不可见,暂停轮询');
stopEventPolling();
} else {
console.log('[EventPolling] H5 页面可见,恢复轮询');
startEventPolling();
}
// #endif
}
/**
* 初始化 H5 可见性监听
*/
function initVisibilityListener(): void {
// #ifdef H5 || WEB
if (isVisibilityListenerInitialized) {
return;
}
document.addEventListener('visibilitychange', handleVisibilityChange);
isVisibilityListenerInitialized = true;
console.log('[EventPolling] H5 可见性监听已初始化');
// #endif
}
/**
* 初始化事件轮询(在 App.uvue onLaunch 中调用)
* - H5自动监听 visibilitychange自动处理暂停/恢复
* - 小程序:需要在 onHide/onShow 中手动调用 stop/start
*/
export function initEventPolling(): void {
// 初始化 H5 可见性监听
initVisibilityListener();
// 启动轮询
startEventPolling();
}
/**
* 启动事件轮询
*/
export function startEventPolling(): void {
// 如果已经在轮询,不重复启动
if (pollingTimerId !== null) {
return;
}
// 未登录不启动
// if (!isLoggedIn()) {
// console.log('[EventPolling] 未登录,跳过启动轮询');
// return;
// }
console.log('[EventPolling] 启动事件轮询');
// 立即执行一次
pollOnce();
// 设置定时轮询
pollingTimerId = setInterval(() => {
pollOnce();
}, POLLING_INTERVAL) as unknown as number;
}
/**
* 停止事件轮询
*/
export function stopEventPolling(): void {
if (pollingTimerId !== null) {
console.log('[EventPolling] 停止事件轮询');
clearInterval(pollingTimerId);
pollingTimerId = null;
}
}
/**
* 检查轮询状态
*/
export function isPollingActive(): boolean {
return pollingTimerId !== null;
}
/**
* 销毁事件轮询(移除监听器)
*/
export function destroyEventPolling(): void {
stopEventPolling();
// #ifdef H5 || WEB
if (isVisibilityListenerInitialized) {
document.removeEventListener('visibilitychange', handleVisibilityChange);
isVisibilityListenerInitialized = false;
console.log('[EventPolling] H5 可见性监听已移除');
}
// #endif
}