feat(hrv): 添加心率变异性监控和压力评估功能

- 新增 HRV 监听服务,实时监控心率变异性数据
- 实现 HRV 到压力指数的转换算法和压力等级评估
- 添加智能通知服务,在压力偏高时推送健康建议
- 优化日志系统,修复日志丢失问题并增强刷新机制
- 改进个人页面下拉刷新,支持并行数据加载
- 优化勋章数据缓存策略,减少不必要的网络请求
- 重构应用初始化流程,优化权限服务和健康监听服务的启动顺序
- 移除冗余日志输出,提升应用性能
This commit is contained in:
richarjiang
2025-11-18 14:08:20 +08:00
parent 3f21f521ea
commit 21e57634e0
15 changed files with 791 additions and 288 deletions

View File

@@ -97,4 +97,11 @@ RCT_EXTERN_METHOD(startSleepObserver:(RCTPromiseResolveBlock)resolver
RCT_EXTERN_METHOD(stopSleepObserver:(RCTPromiseResolveBlock)resolver
rejecter:(RCTPromiseRejectBlock)rejecter)
// HRV Observer Methods
RCT_EXTERN_METHOD(startHRVObserver:(RCTPromiseResolveBlock)resolver
rejecter:(RCTPromiseRejectBlock)rejecter)
RCT_EXTERN_METHOD(stopHRVObserver:(RCTPromiseResolveBlock)resolver
rejecter:(RCTPromiseRejectBlock)rejecter)
@end

View File

@@ -1704,6 +1704,7 @@ class HealthKitManager: RCTEventEmitter {
private var workoutObserverQuery: HKObserverQuery?
private var sleepObserverQuery: HKObserverQuery?
private var hrvObserverQuery: HKObserverQuery?
@objc
func startWorkoutObserver(
@@ -1861,10 +1862,81 @@ private func sendSleepUpdateEvent() {
])
}
// MARK: - HRV Observer Methods
@objc
func startHRVObserver(
_ resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock
) {
guard HKHealthStore.isHealthDataAvailable() else {
rejecter("HEALTHKIT_NOT_AVAILABLE", "HealthKit is not available on this device", nil)
return
}
if let existingQuery = hrvObserverQuery {
healthStore.stop(existingQuery)
hrvObserverQuery = nil
}
let hrvType = ReadTypes.heartRateVariability
hrvObserverQuery = HKObserverQuery(sampleType: hrvType, predicate: nil) { [weak self] (_, completionHandler, error) in
if let error = error {
print("HRV observer error: \(error.localizedDescription)")
completionHandler()
return
}
print("HRV data updated, sending event to React Native")
self?.sendHRVUpdateEvent()
completionHandler()
}
healthStore.enableBackgroundDelivery(for: hrvType, frequency: .immediate) { success, error in
if let error = error {
print("Failed to enable background delivery for HRV: \(error.localizedDescription)")
} else if success {
print("Background delivery for HRV enabled successfully")
}
}
if let query = hrvObserverQuery {
healthStore.execute(query)
}
resolver(["success": true])
}
@objc
func stopHRVObserver(
_ resolver: @escaping RCTPromiseResolveBlock,
rejecter: @escaping RCTPromiseRejectBlock
) {
if let query = hrvObserverQuery {
healthStore.stop(query)
hrvObserverQuery = nil
healthStore.disableBackgroundDelivery(for: ReadTypes.heartRateVariability) { success, error in
if let error = error {
print("Failed to disable background delivery for HRV: \(error.localizedDescription)")
}
}
}
resolver(["success": true])
}
private func sendHRVUpdateEvent() {
sendEvent(withName: "hrvUpdate", body: [
"timestamp": Date().timeIntervalSince1970,
"type": "hrv_data_updated"
])
}
// MARK: - RCTEventEmitter Overrides
override func supportedEvents() -> [String]! {
return ["workoutUpdate", "sleepUpdate"]
return ["workoutUpdate", "sleepUpdate", "hrvUpdate"]
}
override static func requiresMainQueueSetup() -> Bool {