feat(health): 完善HealthKit权限管理和数据获取系统

- 重构权限管理,新增SimpleEventEmitter实现状态监听
- 实现完整的健身圆环数据获取(活动热量、锻炼时间、站立小时)
- 优化组件状态管理,支持实时数据刷新和权限状态响应
- 新增useHealthPermissions Hook,简化权限状态管理
- 完善iOS原生代码,支持按小时统计健身数据
- 优化应用启动时权限初始化流程,避免启动弹窗

BREAKING CHANGE: FitnessRingsCard组件API变更,移除手动传参改为自动获取数据
This commit is contained in:
richarjiang
2025-09-19 14:16:11 +08:00
parent 184fb672b7
commit ccfccca7bc
11 changed files with 1044 additions and 360 deletions

109
utils/SimpleEventEmitter.ts Normal file
View File

@@ -0,0 +1,109 @@
/**
* React Native兼容的EventEmitter实现
*
* 提供与Node.js EventEmitter相似的API但专门为React Native环境设计
* 避免了对Node.js内置模块的依赖
*/
export class SimpleEventEmitter {
private listeners: { [event: string]: ((...args: any[]) => void)[] } = {};
/**
* 添加事件监听器
* @param event 事件名称
* @param listener 监听器函数
*/
on(event: string, listener: (...args: any[]) => void): void {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event].push(listener);
}
/**
* 移除事件监听器
* @param event 事件名称
* @param listener 要移除的监听器函数
*/
off(event: string, listener: (...args: any[]) => void): void {
if (!this.listeners[event]) return;
const index = this.listeners[event].indexOf(listener);
if (index > -1) {
this.listeners[event].splice(index, 1);
}
}
/**
* 触发事件
* @param event 事件名称
* @param args 传递给监听器的参数
*/
emit(event: string, ...args: any[]): void {
if (!this.listeners[event]) return;
// 复制监听器数组,避免在执行过程中数组被修改
const listeners = [...this.listeners[event]];
listeners.forEach(listener => {
try {
listener(...args);
} catch (error) {
console.error(`Error in event listener for event "${event}":`, error);
}
});
}
/**
* 添加一次性事件监听器
* @param event 事件名称
* @param listener 监听器函数(只会执行一次)
*/
once(event: string, listener: (...args: any[]) => void): void {
const onceWrapper = (...args: any[]) => {
this.off(event, onceWrapper);
listener(...args);
};
this.on(event, onceWrapper);
}
/**
* 移除指定事件的所有监听器
* @param event 事件名称(可选,如果未提供则移除所有事件的监听器)
*/
removeAllListeners(event?: string): void {
if (event) {
delete this.listeners[event];
} else {
this.listeners = {};
}
}
/**
* 获取指定事件的监听器数量
* @param event 事件名称
* @returns 监听器数量
*/
listenerCount(event: string): number {
return this.listeners[event]?.length || 0;
}
/**
* 获取指定事件的所有监听器
* @param event 事件名称
* @returns 监听器数组的副本
*/
listeners(event: string): ((...args: any[]) => void)[] {
return this.listeners[event] ? [...this.listeners[event]] : [];
}
/**
* 获取所有事件名称
* @returns 事件名称数组
*/
eventNames(): string[] {
return Object.keys(this.listeners);
}
}
export default SimpleEventEmitter;