Files
digital-pilates/store/index.ts
richarjiang 29942feee9 feat(ui): 添加底部标签栏自定义配置功能和药物堆叠展示
- 新增底部标签栏配置页面,支持切换标签显示/隐藏和恢复默认设置
- 实现已服用药物的堆叠卡片展示,优化药物列表视觉层次
- 集成Redux状态管理底部标签栏配置,支持本地持久化
- 优化个人中心页面背景渐变效果,移除装饰性圆圈元素
- 更新启动页和应用图标为新的品牌视觉
- 药物详情页AI分析加载动画替换为Lottie动画
- 调整药物卡片圆角半径提升视觉一致性
- 新增多语言支持(中英文)用于标签栏配置界面

主要改进:
1. 用户可以自定义底部导航栏显示内容
2. 已完成的药物以堆叠形式展示,节省空间
3. 配置数据通过AsyncStorage持久化保存
4. 支持默认配置恢复功能
2025-11-20 17:55:17 +08:00

125 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { persistActiveFastingSchedule } from '@/utils/fasting';
import { configureStore, createListenerMiddleware } from '@reduxjs/toolkit';
import badgesReducer from './badgesSlice';
import challengesReducer from './challengesSlice';
import checkinReducer, { addExercise, autoSyncCheckin, removeExercise, replaceExercises, setNote, toggleExerciseCompleted } from './checkinSlice';
import circumferenceReducer from './circumferenceSlice';
import exerciseLibraryReducer from './exerciseLibrarySlice';
import fastingReducer, {
clearActiveSchedule,
completeActiveSchedule,
rescheduleActivePlan,
scheduleFastingPlan,
setRecommendedSchedule,
} from './fastingSlice';
import foodLibraryReducer from './foodLibrarySlice';
import foodRecognitionReducer from './foodRecognitionSlice';
import healthReducer from './healthSlice';
import medicationsReducer from './medicationsSlice';
import membershipReducer from './membershipSlice';
import moodReducer from './moodSlice';
import nutritionReducer from './nutritionSlice';
import scheduleExerciseReducer from './scheduleExerciseSlice';
import tabBarConfigReducer from './tabBarConfigSlice';
import trainingPlanReducer from './trainingPlanSlice';
import userReducer from './userSlice';
import waterReducer from './waterSlice';
import workoutReducer from './workoutSlice';
// 创建监听器中间件来处理自动同步
const listenerMiddleware = createListenerMiddleware();
// 监听所有数据变动的 actions触发自动同步
const syncActions = [addExercise, removeExercise, replaceExercises, toggleExerciseCompleted, setNote];
syncActions.forEach(action => {
listenerMiddleware.startListening({
actionCreator: action,
effect: async (action, listenerApi) => {
const state = listenerApi.getState() as any;
const date = action.payload?.date;
if (!date) return;
// 延迟一下,避免在同一事件循环中重复触发
await new Promise(resolve => setTimeout(resolve, 100));
// 检查是否还有待同步的日期
const currentState = listenerApi.getState() as any;
const pendingSyncDates = currentState?.checkin?.pendingSyncDates || [];
if (pendingSyncDates.includes(date)) {
listenerApi.dispatch(autoSyncCheckin({ date }));
}
},
});
});
const persistFastingState = async (listenerApi: any) => {
const state = listenerApi.getState() as { fasting?: { activeSchedule?: any } };
await persistActiveFastingSchedule(state?.fasting?.activeSchedule ?? null);
};
listenerMiddleware.startListening({
actionCreator: scheduleFastingPlan,
effect: async (_, listenerApi) => {
await persistFastingState(listenerApi);
},
});
listenerMiddleware.startListening({
actionCreator: rescheduleActivePlan,
effect: async (_, listenerApi) => {
await persistFastingState(listenerApi);
},
});
listenerMiddleware.startListening({
actionCreator: completeActiveSchedule,
effect: async (_, listenerApi) => {
await persistFastingState(listenerApi);
},
});
listenerMiddleware.startListening({
actionCreator: setRecommendedSchedule,
effect: async (_, listenerApi) => {
await persistFastingState(listenerApi);
},
});
listenerMiddleware.startListening({
actionCreator: clearActiveSchedule,
effect: async () => {
await persistActiveFastingSchedule(null);
},
});
export const store = configureStore({
reducer: {
user: userReducer,
challenges: challengesReducer,
checkin: checkinReducer,
circumference: circumferenceReducer,
health: healthReducer,
mood: moodReducer,
nutrition: nutritionReducer,
trainingPlan: trainingPlanReducer,
scheduleExercise: scheduleExerciseReducer,
exerciseLibrary: exerciseLibraryReducer,
foodLibrary: foodLibraryReducer,
foodRecognition: foodRecognitionReducer,
membership: membershipReducer,
workout: workoutReducer,
water: waterReducer,
fasting: fastingReducer,
medications: medicationsReducer,
badges: badgesReducer,
tabBarConfig: tabBarConfigReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().prepend(listenerMiddleware.middleware),
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;