feat(health): 新增手腕温度监测和经期双向同步功能

新增手腕温度健康数据追踪,支持Apple Watch睡眠手腕温度数据展示和30天历史趋势分析
实现经期数据与HealthKit的完整双向同步,支持读取、写入和删除经期记录
优化经期预测算法,基于历史数据计算更准确的周期和排卵日预测
重构经期UI组件为模块化结构,提升代码可维护性
添加完整的中英文国际化支持,覆盖所有新增功能界面
This commit is contained in:
richarjiang
2025-12-18 08:40:08 +08:00
parent 9b4a300380
commit 4836058d56
31 changed files with 2249 additions and 539 deletions

View File

@@ -28,6 +28,7 @@ const PREFERENCES_KEYS = {
SHOW_MENSTRUAL_CYCLE_CARD: 'user_preference_show_menstrual_cycle_card',
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',
// 首页身体指标卡片排序设置
STATISTICS_CARD_ORDER: 'user_preference_statistics_card_order',
@@ -46,6 +47,7 @@ export interface StatisticsCardsVisibility {
showMenstrualCycle: boolean;
showWeight: boolean;
showCircumference: boolean;
showWristTemperature: boolean;
}
// 默认卡片顺序
@@ -58,6 +60,7 @@ export const DEFAULT_CARD_ORDER: string[] = [
'water',
'metabolism',
'oxygen',
'temperature',
'menstrual',
'weight',
'circumference',
@@ -109,6 +112,7 @@ const DEFAULT_PREFERENCES: UserPreferences = {
showMenstrualCycle: true,
showWeight: true,
showCircumference: true,
showWristTemperature: true,
// 默认卡片顺序
cardOrder: DEFAULT_CARD_ORDER,
@@ -145,6 +149,7 @@ export const getUserPreferences = async (): Promise<UserPreferences> => {
const showMenstrualCycle = await AsyncStorage.getItem(PREFERENCES_KEYS.SHOW_MENSTRUAL_CYCLE_CARD);
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 cardOrderStr = await AsyncStorage.getItem(PREFERENCES_KEYS.STATISTICS_CARD_ORDER);
const cardOrder = cardOrderStr ? JSON.parse(cardOrderStr) : DEFAULT_PREFERENCES.cardOrder;
@@ -174,6 +179,7 @@ export const getUserPreferences = async (): Promise<UserPreferences> => {
showMenstrualCycle: showMenstrualCycle !== null ? showMenstrualCycle === 'true' : DEFAULT_PREFERENCES.showMenstrualCycle,
showWeight: showWeight !== null ? showWeight === 'true' : DEFAULT_PREFERENCES.showWeight,
showCircumference: showCircumference !== null ? showCircumference === 'true' : DEFAULT_PREFERENCES.showCircumference,
showWristTemperature: showWristTemperature !== null ? showWristTemperature === 'true' : DEFAULT_PREFERENCES.showWristTemperature,
cardOrder,
};
} catch (error) {
@@ -611,6 +617,7 @@ export const getStatisticsCardsVisibility = async (): Promise<StatisticsCardsVis
showMenstrualCycle: userPreferences.showMenstrualCycle,
showWeight: userPreferences.showWeight,
showCircumference: userPreferences.showCircumference,
showWristTemperature: userPreferences.showWristTemperature,
};
} catch (error) {
console.error('获取首页卡片显示设置失败:', error);
@@ -626,6 +633,7 @@ export const getStatisticsCardsVisibility = async (): Promise<StatisticsCardsVis
showMenstrualCycle: DEFAULT_PREFERENCES.showMenstrualCycle,
showWeight: DEFAULT_PREFERENCES.showWeight,
showCircumference: DEFAULT_PREFERENCES.showCircumference,
showWristTemperature: DEFAULT_PREFERENCES.showWristTemperature,
};
}
};
@@ -673,6 +681,7 @@ export const setStatisticsCardVisibility = async (key: keyof StatisticsCardsVisi
case 'showMenstrualCycle': storageKey = PREFERENCES_KEYS.SHOW_MENSTRUAL_CYCLE_CARD; break;
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;
default: return;
}
await AsyncStorage.setItem(storageKey, value.toString());