feat(health): 新增日照时长监测卡片与 HealthKit 集成

- iOS 端集成 HealthKit 日照时间 (TimeInDaylight) 数据获取接口
- 新增 SunlightCard 组件,支持查看今日数据及最近30天历史趋势图表
- 更新统计页和自定义设置页,支持开启/关闭日照卡片
- 优化 HealthDataCard 组件,支持自定义图标组件和副标题显示
- 更新多语言文件及应用版本号至 1.1.6
This commit is contained in:
richarjiang
2025-12-19 17:38:16 +08:00
parent e51aca2fdb
commit 17664c679d
15 changed files with 851 additions and 7 deletions

View File

@@ -29,6 +29,7 @@ const PREFERENCES_KEYS = {
SHOW_WEIGHT_CARD: 'user_preference_show_weight_card',
SHOW_CIRCUMFERENCE_CARD: 'user_preference_show_circumference_card',
SHOW_WRIST_TEMPERATURE_CARD: 'user_preference_show_wrist_temperature_card',
SHOW_SUNLIGHT_CARD: 'user_preference_show_sunlight_card',
// 首页身体指标卡片排序设置
STATISTICS_CARD_ORDER: 'user_preference_statistics_card_order',
@@ -48,6 +49,7 @@ export interface StatisticsCardsVisibility {
showWeight: boolean;
showCircumference: boolean;
showWristTemperature: boolean;
showSunlight: boolean;
}
// 默认卡片顺序
@@ -56,6 +58,7 @@ export const DEFAULT_CARD_ORDER: string[] = [
'steps',
'stress',
'sleep',
'sunlight',
'fitness',
'water',
'metabolism',
@@ -113,6 +116,7 @@ const DEFAULT_PREFERENCES: UserPreferences = {
showWeight: true,
showCircumference: true,
showWristTemperature: true,
showSunlight: true,
// 默认卡片顺序
cardOrder: DEFAULT_CARD_ORDER,
@@ -150,6 +154,7 @@ export const getUserPreferences = async (): Promise<UserPreferences> => {
const showWeight = await AsyncStorage.getItem(PREFERENCES_KEYS.SHOW_WEIGHT_CARD);
const showCircumference = await AsyncStorage.getItem(PREFERENCES_KEYS.SHOW_CIRCUMFERENCE_CARD);
const showWristTemperature = await AsyncStorage.getItem(PREFERENCES_KEYS.SHOW_WRIST_TEMPERATURE_CARD);
const showSunlight = await AsyncStorage.getItem(PREFERENCES_KEYS.SHOW_SUNLIGHT_CARD);
const cardOrderStr = await AsyncStorage.getItem(PREFERENCES_KEYS.STATISTICS_CARD_ORDER);
const cardOrder = cardOrderStr ? JSON.parse(cardOrderStr) : DEFAULT_PREFERENCES.cardOrder;
@@ -180,6 +185,7 @@ export const getUserPreferences = async (): Promise<UserPreferences> => {
showWeight: showWeight !== null ? showWeight === 'true' : DEFAULT_PREFERENCES.showWeight,
showCircumference: showCircumference !== null ? showCircumference === 'true' : DEFAULT_PREFERENCES.showCircumference,
showWristTemperature: showWristTemperature !== null ? showWristTemperature === 'true' : DEFAULT_PREFERENCES.showWristTemperature,
showSunlight: showSunlight !== null ? showSunlight === 'true' : DEFAULT_PREFERENCES.showSunlight,
cardOrder,
};
} catch (error) {
@@ -618,6 +624,7 @@ export const getStatisticsCardsVisibility = async (): Promise<StatisticsCardsVis
showWeight: userPreferences.showWeight,
showCircumference: userPreferences.showCircumference,
showWristTemperature: userPreferences.showWristTemperature,
showSunlight: userPreferences.showSunlight,
};
} catch (error) {
console.error('获取首页卡片显示设置失败:', error);
@@ -634,6 +641,7 @@ export const getStatisticsCardsVisibility = async (): Promise<StatisticsCardsVis
showWeight: DEFAULT_PREFERENCES.showWeight,
showCircumference: DEFAULT_PREFERENCES.showCircumference,
showWristTemperature: DEFAULT_PREFERENCES.showWristTemperature,
showSunlight: DEFAULT_PREFERENCES.showSunlight,
};
}
};
@@ -682,6 +690,7 @@ export const setStatisticsCardVisibility = async (key: keyof StatisticsCardsVisi
case 'showWeight': storageKey = PREFERENCES_KEYS.SHOW_WEIGHT_CARD; break;
case 'showCircumference': storageKey = PREFERENCES_KEYS.SHOW_CIRCUMFERENCE_CARD; break;
case 'showWristTemperature': storageKey = PREFERENCES_KEYS.SHOW_WRIST_TEMPERATURE_CARD; break;
case 'showSunlight': storageKey = PREFERENCES_KEYS.SHOW_SUNLIGHT_CARD; break;
default: return;
}
await AsyncStorage.setItem(storageKey, value.toString());