feat:支持身体围度数据展示
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { api, setAuthToken, STORAGE_KEYS } from '@/services/api';
|
||||
import { updateUser, UpdateUserDto } from '@/services/users';
|
||||
import { BodyMeasurementsDto, updateBodyMeasurements, updateUser, UpdateUserDto } from '@/services/users';
|
||||
import AsyncStorage from '@/utils/kvStore';
|
||||
import { createAsyncThunk, createSelector, createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -53,6 +53,7 @@ function getPreloadedUserData() {
|
||||
export type Gender = 'male' | 'female' | '';
|
||||
|
||||
export type UserProfile = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
email?: string;
|
||||
gender?: Gender;
|
||||
@@ -68,6 +69,12 @@ export type UserProfile = {
|
||||
isVip?: boolean;
|
||||
freeUsageCount?: number;
|
||||
maxUsageCount?: number;
|
||||
chestCircumference?: number; // 胸围
|
||||
waistCircumference?: number; // 腰围
|
||||
upperHipCircumference?: number; // 上臀围
|
||||
armCircumference?: number; // 臂围
|
||||
thighCircumference?: number; // 大腿围
|
||||
calfCircumference?: number; // 小腿围
|
||||
};
|
||||
|
||||
export type WeightHistoryItem = {
|
||||
@@ -87,7 +94,6 @@ export type UserState = {
|
||||
profile: UserProfile;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
privacyAgreed: boolean;
|
||||
weightHistory: WeightHistoryItem[];
|
||||
activityHistory: ActivityHistoryItem[];
|
||||
};
|
||||
@@ -107,7 +113,6 @@ const getInitialState = (): UserState => {
|
||||
},
|
||||
loading: false,
|
||||
error: null,
|
||||
privacyAgreed: preloaded.privacyAgreed,
|
||||
weightHistory: [],
|
||||
activityHistory: [],
|
||||
};
|
||||
@@ -184,38 +189,6 @@ export const login = createAsyncThunk(
|
||||
}
|
||||
);
|
||||
|
||||
// 同步重新hydrate用户数据,避免异步状态更新
|
||||
export const rehydrateUserSync = createAsyncThunk('user/rehydrateSync', async () => {
|
||||
// 立即从预加载的数据获取,如果没有则异步获取
|
||||
if (preloadedUserData) {
|
||||
return preloadedUserData;
|
||||
}
|
||||
|
||||
// 如果预加载的数据不存在,则执行正常的异步加载
|
||||
return await preloadUserData();
|
||||
});
|
||||
|
||||
export const rehydrateUser = createAsyncThunk('user/rehydrate', async () => {
|
||||
const [profileStr, privacyAgreedStr, token] = await Promise.all([
|
||||
AsyncStorage.getItem(STORAGE_KEYS.userProfile),
|
||||
AsyncStorage.getItem(STORAGE_KEYS.privacyAgreed),
|
||||
AsyncStorage.getItem(STORAGE_KEYS.authToken),
|
||||
]);
|
||||
|
||||
let profile: UserProfile = {};
|
||||
if (profileStr) {
|
||||
try { profile = JSON.parse(profileStr) as UserProfile; } catch { profile = {}; }
|
||||
}
|
||||
const privacyAgreed = privacyAgreedStr === 'true';
|
||||
|
||||
// 如果有 token,需要设置到 API 客户端
|
||||
if (token) {
|
||||
await setAuthToken(token);
|
||||
}
|
||||
|
||||
return { profile, privacyAgreed, token } as { profile: UserProfile; privacyAgreed: boolean; token: string | null };
|
||||
});
|
||||
|
||||
export const setPrivacyAgreed = createAsyncThunk('user/setPrivacyAgreed', async () => {
|
||||
await AsyncStorage.setItem(STORAGE_KEYS.privacyAgreed, 'true');
|
||||
return true;
|
||||
@@ -241,8 +214,12 @@ export const fetchMyProfile = createAsyncThunk('user/fetchMyProfile', async (_,
|
||||
await AsyncStorage.setItem(STORAGE_KEYS.userProfile, JSON.stringify(profile ?? {}));
|
||||
return profile;
|
||||
} catch (err: any) {
|
||||
const message = err?.message ?? '获取用户信息失败';
|
||||
return rejectWithValue(message);
|
||||
const profileStr = await AsyncStorage.getItem(STORAGE_KEYS.userProfile),
|
||||
profile = JSON.parse(profileStr ?? '{}');
|
||||
|
||||
return profile
|
||||
// const message = err?.message ?? '获取用户信息失败';
|
||||
// return rejectWithValue(message);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -306,6 +283,19 @@ export const updateWeightRecord = createAsyncThunk(
|
||||
}
|
||||
);
|
||||
|
||||
// 更新用户围度信息
|
||||
export const updateUserBodyMeasurements = createAsyncThunk(
|
||||
'user/updateBodyMeasurements',
|
||||
async (measurementsDto: BodyMeasurementsDto, { rejectWithValue }) => {
|
||||
try {
|
||||
await updateBodyMeasurements(measurementsDto);
|
||||
return measurementsDto;
|
||||
} catch (err: any) {
|
||||
return rejectWithValue(err?.message ?? '更新围度信息失败');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const userSlice = createSlice({
|
||||
name: 'user',
|
||||
initialState,
|
||||
@@ -338,22 +328,6 @@ const userSlice = createSlice({
|
||||
state.loading = false;
|
||||
state.error = (action.payload as string) ?? '登录失败';
|
||||
})
|
||||
.addCase(rehydrateUser.fulfilled, (state, action) => {
|
||||
state.profile = action.payload.profile;
|
||||
state.privacyAgreed = action.payload.privacyAgreed;
|
||||
state.token = action.payload.token;
|
||||
if (!state.profile?.name || !state.profile.name.trim()) {
|
||||
state.profile.name = DEFAULT_MEMBER_NAME;
|
||||
}
|
||||
})
|
||||
.addCase(rehydrateUserSync.fulfilled, (state, action) => {
|
||||
state.profile = action.payload.profile;
|
||||
state.privacyAgreed = action.payload.privacyAgreed;
|
||||
state.token = action.payload.token;
|
||||
if (!state.profile?.name || !state.profile.name.trim()) {
|
||||
state.profile.name = DEFAULT_MEMBER_NAME;
|
||||
}
|
||||
})
|
||||
.addCase(fetchMyProfile.fulfilled, (state, action) => {
|
||||
state.profile = action.payload || {};
|
||||
if (!state.profile?.name || !state.profile.name.trim()) {
|
||||
@@ -367,10 +341,8 @@ const userSlice = createSlice({
|
||||
.addCase(logout.fulfilled, (state) => {
|
||||
state.token = null;
|
||||
state.profile = {};
|
||||
state.privacyAgreed = false;
|
||||
})
|
||||
.addCase(setPrivacyAgreed.fulfilled, (state) => {
|
||||
state.privacyAgreed = true;
|
||||
})
|
||||
.addCase(fetchWeightHistory.fulfilled, (state, action) => {
|
||||
state.weightHistory = action.payload;
|
||||
@@ -408,6 +380,14 @@ const userSlice = createSlice({
|
||||
})
|
||||
.addCase(updateWeightRecord.rejected, (state, action) => {
|
||||
state.error = (action.payload as string) ?? '更新体重记录失败';
|
||||
})
|
||||
.addCase(updateUserBodyMeasurements.fulfilled, (state, action) => {
|
||||
console.log('action.payload', action.payload);
|
||||
|
||||
state.profile = { ...state.profile, ...action.payload };
|
||||
})
|
||||
.addCase(updateUserBodyMeasurements.rejected, (state, action) => {
|
||||
state.error = (action.payload as string) ?? '更新围度信息失败';
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user