feat(navigation): add profile stack navigator and fix API endpoints
- Add ProfileStackNavigatorComponent with full navigation stack (Profile, Settings, EditProfile, AccountSecurity, MyPosts, Bookmarks, NotificationSettings, BlockedUsers) - Add null checks for response data in authService login, register, and refreshToken methods - Fix postService API routes to use correct endpoints (/posts instead of /posts/cursor) - Remove completed cursor pagination design document
This commit is contained in:
@@ -5,6 +5,6 @@ dist
|
|||||||
dist-web
|
dist-web
|
||||||
dist-android
|
dist-android
|
||||||
dist-android-update.zip
|
dist-android-update.zip
|
||||||
android
|
android
|
||||||
screenshots
|
screenshots
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -40,8 +40,21 @@ export type ScheduleStackParamList = {
|
|||||||
CourseDetail: { course: any; relatedCourses?: any[] };
|
CourseDetail: { course: any; relatedCourses?: any[] };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Profile Stack 类型定义
|
||||||
|
export type ProfileStackParamList = {
|
||||||
|
Profile: undefined;
|
||||||
|
Settings: undefined;
|
||||||
|
EditProfile: undefined;
|
||||||
|
AccountSecurity: undefined;
|
||||||
|
MyPosts: undefined;
|
||||||
|
Bookmarks: undefined;
|
||||||
|
NotificationSettings: undefined;
|
||||||
|
BlockedUsers: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
// ==================== Stack Navigators ====================
|
// ==================== Stack Navigators ====================
|
||||||
const ScheduleStack = createNativeStackNavigator<ScheduleStackParamList>();
|
const ScheduleStack = createNativeStackNavigator<ScheduleStackParamList>();
|
||||||
|
const ProfileStack = createNativeStackNavigator<ProfileStackParamList>();
|
||||||
|
|
||||||
// ==================== 常量 ====================
|
// ==================== 常量 ====================
|
||||||
const TAB_BAR_HEIGHT = 64;
|
const TAB_BAR_HEIGHT = 64;
|
||||||
@@ -80,6 +93,84 @@ function ScheduleStackNavigatorComponent() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profile Stack Navigator 组件
|
||||||
|
*/
|
||||||
|
function ProfileStackNavigatorComponent() {
|
||||||
|
return (
|
||||||
|
<ProfileStack.Navigator
|
||||||
|
screenOptions={{
|
||||||
|
headerStyle: {
|
||||||
|
backgroundColor: colors.background.paper,
|
||||||
|
},
|
||||||
|
headerTintColor: colors.text.primary,
|
||||||
|
headerTitleStyle: {
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
headerBackTitle: '',
|
||||||
|
headerShadowVisible: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="Profile"
|
||||||
|
component={ProfileScreen}
|
||||||
|
options={{
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="Settings"
|
||||||
|
component={SettingsScreen}
|
||||||
|
options={{
|
||||||
|
title: '设置',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="EditProfile"
|
||||||
|
component={EditProfileScreen}
|
||||||
|
options={{
|
||||||
|
title: '编辑资料',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="AccountSecurity"
|
||||||
|
component={AccountSecurityScreen}
|
||||||
|
options={{
|
||||||
|
title: '账号安全',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="MyPosts"
|
||||||
|
component={ProfileScreen}
|
||||||
|
options={{
|
||||||
|
title: '我的帖子',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="Bookmarks"
|
||||||
|
component={ProfileScreen}
|
||||||
|
options={{
|
||||||
|
title: '收藏',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="NotificationSettings"
|
||||||
|
component={NotificationSettingsScreen}
|
||||||
|
options={{
|
||||||
|
title: '通知设置',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfileStack.Screen
|
||||||
|
name="BlockedUsers"
|
||||||
|
component={BlockedUsersScreen}
|
||||||
|
options={{
|
||||||
|
title: '黑名单',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ProfileStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主组件:SimpleMobileTabNavigator
|
* 主组件:SimpleMobileTabNavigator
|
||||||
*/
|
*/
|
||||||
@@ -108,7 +199,7 @@ export function SimpleMobileTabNavigator() {
|
|||||||
case 'ScheduleTab':
|
case 'ScheduleTab':
|
||||||
return <ScheduleStackNavigatorComponent />;
|
return <ScheduleStackNavigatorComponent />;
|
||||||
case 'ProfileTab':
|
case 'ProfileTab':
|
||||||
return <ProfileScreen />;
|
return <ProfileStackNavigatorComponent />;
|
||||||
default:
|
default:
|
||||||
return <HomeScreen />;
|
return <HomeScreen />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,9 @@ class AuthService {
|
|||||||
async login(data: LoginRequest): Promise<AuthResponse> {
|
async login(data: LoginRequest): Promise<AuthResponse> {
|
||||||
const response = await api.post<AuthResponse>('/auth/login', data);
|
const response = await api.post<AuthResponse>('/auth/login', data);
|
||||||
|
|
||||||
|
if (!response.data) {
|
||||||
|
throw new Error('登录响应数据为空');
|
||||||
|
}
|
||||||
if (response.data.token) {
|
if (response.data.token) {
|
||||||
await api.setToken(response.data.token);
|
await api.setToken(response.data.token);
|
||||||
}
|
}
|
||||||
@@ -165,6 +168,9 @@ class AuthService {
|
|||||||
async register(data: RegisterRequest): Promise<AuthResponse> {
|
async register(data: RegisterRequest): Promise<AuthResponse> {
|
||||||
const response = await api.post<AuthResponse>('/auth/register', data);
|
const response = await api.post<AuthResponse>('/auth/register', data);
|
||||||
|
|
||||||
|
if (!response.data) {
|
||||||
|
throw new Error('注册响应数据为空');
|
||||||
|
}
|
||||||
if (response.data.token) {
|
if (response.data.token) {
|
||||||
await api.setToken(response.data.token);
|
await api.setToken(response.data.token);
|
||||||
}
|
}
|
||||||
@@ -233,6 +239,9 @@ class AuthService {
|
|||||||
try {
|
try {
|
||||||
const response = await api.post<RefreshTokenResponse>('/auth/refresh');
|
const response = await api.post<RefreshTokenResponse>('/auth/refresh');
|
||||||
|
|
||||||
|
if (!response.data) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (response.data.token) {
|
if (response.data.token) {
|
||||||
await api.setToken(response.data.token);
|
await api.setToken(response.data.token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,19 +287,17 @@ class PostService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取帖子列表(游标分页)
|
* 获取帖子列表(游标分页)
|
||||||
* GET /api/v1/posts/cursor
|
* GET /api/v1/posts
|
||||||
* @param params 游标分页请求参数(包含 post_type 可选:recommend, follow, hot, latest)
|
* @param params 游标分页请求参数(包含 post_type 可选:recommend, follow, hot, latest)
|
||||||
*/
|
*/
|
||||||
async getPostsCursor(
|
async getPostsCursor(
|
||||||
params: CursorPaginationRequest = {}
|
params: CursorPaginationRequest = {}
|
||||||
): Promise<CursorPaginationResponse<Post>> {
|
): Promise<CursorPaginationResponse<Post>> {
|
||||||
try {
|
try {
|
||||||
const response = await api.get<CursorPaginationResponse<Post>>('/posts/cursor', {
|
const response = await api.get<CursorPaginationResponse<Post>>('/posts', {
|
||||||
params: {
|
cursor: params.cursor,
|
||||||
cursor: params.cursor,
|
page_size: params.page_size,
|
||||||
page_size: params.page_size,
|
post_type: params.post_type,
|
||||||
post_type: params.post_type,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -315,7 +313,7 @@ class PostService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索帖子(游标分页)
|
* 搜索帖子(游标分页)
|
||||||
* GET /api/v1/posts/search/cursor
|
* GET /api/v1/posts/search
|
||||||
* @param query 搜索关键词
|
* @param query 搜索关键词
|
||||||
* @param params 游标分页请求参数
|
* @param params 游标分页请求参数
|
||||||
*/
|
*/
|
||||||
@@ -324,11 +322,9 @@ class PostService {
|
|||||||
params: CursorPaginationRequest = {}
|
params: CursorPaginationRequest = {}
|
||||||
): Promise<CursorPaginationResponse<Post>> {
|
): Promise<CursorPaginationResponse<Post>> {
|
||||||
try {
|
try {
|
||||||
const response = await api.get<CursorPaginationResponse<Post>>('/posts/search/cursor', {
|
const response = await api.get<CursorPaginationResponse<Post>>('/posts/search', {
|
||||||
params: {
|
...params,
|
||||||
...params,
|
keyword: query,
|
||||||
keyword: query,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -344,7 +340,7 @@ class PostService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户帖子列表(游标分页)
|
* 获取用户帖子列表(游标分页)
|
||||||
* GET /api/v1/users/:id/posts/cursor
|
* GET /api/v1/users/:id/posts
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
* @param params 游标分页请求参数
|
* @param params 游标分页请求参数
|
||||||
*/
|
*/
|
||||||
@@ -354,8 +350,8 @@ class PostService {
|
|||||||
): Promise<CursorPaginationResponse<Post>> {
|
): Promise<CursorPaginationResponse<Post>> {
|
||||||
try {
|
try {
|
||||||
const response = await api.get<CursorPaginationResponse<Post>>(
|
const response = await api.get<CursorPaginationResponse<Post>>(
|
||||||
`/users/${userId}/posts/cursor`,
|
`/users/${userId}/posts`,
|
||||||
{ params }
|
params
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user