feat: 更新应用名称及图标,新增HRV数据管理,优化营养记录展示

This commit is contained in:
richarjiang
2025-08-19 19:13:02 +08:00
parent 260546ff46
commit 35cd320ea7
10 changed files with 643 additions and 564 deletions

View File

@@ -6,6 +6,8 @@ const PERMISSIONS: HealthKitPermissions = {
read: [
AppleHealthKit.Constants.Permissions.StepCount,
AppleHealthKit.Constants.Permissions.ActiveEnergyBurned,
AppleHealthKit.Constants.Permissions.SleepAnalysis,
AppleHealthKit.Constants.Permissions.HeartRateVariability,
],
write: [],
},
@@ -14,6 +16,8 @@ const PERMISSIONS: HealthKitPermissions = {
export type TodayHealthData = {
steps: number;
activeEnergyBurned: number; // kilocalories
sleepDuration: number; // 睡眠时长(分钟)
hrv: number | null; // 心率变异性 (ms)
};
export async function ensureHealthPermissions(): Promise<boolean> {
@@ -46,46 +50,147 @@ export async function fetchHealthDataForDate(date: Date): Promise<TodayHealthDat
const end = new Date(date);
end.setHours(23, 59, 59, 999);
const options = { startDate: start.toISOString(), endDate: end.toISOString() } as any;
const options = {
startDate: start.toISOString(),
endDate: end.toISOString()
} as any;
console.log('查询选项:', options);
const steps = await new Promise<number>((resolve) => {
AppleHealthKit.getStepCount(options, (err, res) => {
if (err) {
console.error('获取步数失败:', err);
return resolve(0);
}
if (!res) {
console.warn('步数数据为空');
return resolve(0);
}
console.log('步数数据:', res);
resolve(res.value || 0);
});
});
// 并行获取所有健康数据
const [steps, calories, sleepDuration, hrv] = await Promise.all([
// 获取步数
new Promise<number>((resolve) => {
AppleHealthKit.getStepCount(options, (err, res) => {
if (err) {
console.error('获取步数失败:', err);
return resolve(0);
}
if (!res) {
console.warn('步数数据为空');
return resolve(0);
}
console.log('步数数据:', res);
resolve(res.value || 0);
});
}),
const calories = await new Promise<number>((resolve) => {
AppleHealthKit.getActiveEnergyBurned(options, (err, res) => {
if (err) {
console.error('获取消耗卡路里失败:', err);
return resolve(0);
}
if (!res || !Array.isArray(res) || res.length === 0) {
console.warn('卡路里数据为空或格式错误');
return resolve(0);
}
console.log('卡路里数据:', res);
// 求和该日内的所有记录(单位:千卡)
const total = res.reduce((acc: number, item: any) => acc + (item?.value || 0), 0);
resolve(total);
});
});
// 获取消耗卡路里
new Promise<number>((resolve) => {
AppleHealthKit.getActiveEnergyBurned(options, (err, res) => {
if (err) {
console.error('获取消耗卡路里失败:', err);
return resolve(0);
}
if (!res || !Array.isArray(res) || res.length === 0) {
console.warn('卡路里数据为空或格式错误');
return resolve(0);
}
console.log('卡路里数据:', res);
// 求和该日内的所有记录(单位:千卡)
const total = res.reduce((acc: number, item: any) => acc + (item?.value || 0), 0);
resolve(total);
});
}),
console.log('指定日期健康数据获取完成:', { steps, calories });
return { steps, activeEnergyBurned: calories };
// 获取睡眠时长
new Promise<number>((resolve) => {
AppleHealthKit.getSleepSamples(options, (err, res) => {
if (err) {
console.error('获取睡眠数据失败:', err);
return resolve(0);
}
if (!res || !Array.isArray(res) || res.length === 0) {
console.warn('睡眠数据为空或格式错误');
return resolve(0);
}
console.log('睡眠数据:', res);
// 计算总睡眠时间(单位:分钟)
let totalSleepDuration = 0;
res.forEach((sample: any) => {
if (sample && sample.startDate && sample.endDate) {
const startTime = new Date(sample.startDate).getTime();
const endTime = new Date(sample.endDate).getTime();
const durationMinutes = (endTime - startTime) / (1000 * 60);
totalSleepDuration += durationMinutes;
}
});
resolve(totalSleepDuration);
});
}),
// 获取HRV数据
new Promise<number | null>((resolve) => {
AppleHealthKit.getHeartRateVariabilitySamples(options, (err, res) => {
if (err) {
console.error('获取HRV数据失败:', err);
return resolve(null);
}
if (!res || !Array.isArray(res) || res.length === 0) {
console.warn('HRV数据为空或格式错误');
return resolve(null);
}
console.log('HRV数据:', res);
// 获取最新的HRV值
const latestHrv = res[res.length - 1];
if (latestHrv && latestHrv.value) {
resolve(latestHrv.value);
} else {
resolve(null);
}
});
})
]);
console.log('指定日期健康数据获取完成:', { steps, calories, sleepDuration, hrv });
return { steps, activeEnergyBurned: calories, sleepDuration, hrv };
}
export async function fetchTodayHealthData(): Promise<TodayHealthData> {
return fetchHealthDataForDate(new Date());
}
// 新增专门获取HRV数据的函数
export async function fetchHRVForDate(date: Date): Promise<number | null> {
console.log('开始获取指定日期HRV数据...', date);
const start = new Date(date);
start.setHours(0, 0, 0, 0);
const end = new Date(date);
end.setHours(23, 59, 59, 999);
const options = {
startDate: start.toISOString(),
endDate: end.toISOString()
} as any;
return new Promise<number | null>((resolve) => {
AppleHealthKit.getHeartRateVariabilitySamples(options, (err, res) => {
if (err) {
console.error('获取HRV数据失败:', err);
return resolve(null);
}
if (!res || !Array.isArray(res) || res.length === 0) {
console.warn('HRV数据为空或格式错误');
return resolve(null);
}
console.log('HRV数据:', res);
// 获取最新的HRV值
const latestHrv = res[res.length - 1];
if (latestHrv && latestHrv.value) {
resolve(latestHrv.value);
} else {
resolve(null);
}
});
});
}
// 新增获取今日HRV数据
export async function fetchTodayHRV(): Promise<number | null> {
return fetchHRVForDate(new Date());
}