enhance: 优化页面切换效果
This commit is contained in:
parent
4675043d85
commit
b7d9186570
@ -12,6 +12,8 @@ import * as SecureStore from 'expo-secure-store';
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Platform } from 'react-native';
|
import { Platform } from 'react-native';
|
||||||
|
import { TransitionPresets } from '@react-navigation/bottom-tabs';
|
||||||
|
import AskNavbar from '@/components/layout/ask';
|
||||||
|
|
||||||
interface PollingData {
|
interface PollingData {
|
||||||
title: string;
|
title: string;
|
||||||
@ -19,6 +21,7 @@ interface PollingData {
|
|||||||
content: string;
|
content: string;
|
||||||
extra: any;
|
extra: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TabLayout() {
|
export default function TabLayout() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const colorScheme = useColorScheme();
|
const colorScheme = useColorScheme();
|
||||||
@ -171,192 +174,198 @@ export default function TabLayout() {
|
|||||||
}, [token]);
|
}, [token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<>
|
||||||
screenOptions={{
|
<Tabs
|
||||||
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
screenOptions={{
|
||||||
headerShown: false,
|
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
||||||
tabBarButton: HapticTab,
|
headerShown: false,
|
||||||
tabBarBackground: TabBarBackground,
|
tabBarButton: HapticTab,
|
||||||
tabBarStyle: Platform.select({
|
tabBarBackground: TabBarBackground,
|
||||||
ios: {
|
tabBarStyle: Platform.select({
|
||||||
// Use a transparent background on iOS to show the blur effect
|
ios: {
|
||||||
position: 'absolute',
|
// Use a transparent background on iOS to show the blur effect
|
||||||
},
|
position: 'absolute',
|
||||||
default: {},
|
},
|
||||||
}),
|
default: {},
|
||||||
}}
|
}),
|
||||||
>
|
|
||||||
{/* 落地页 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="index"
|
|
||||||
options={{
|
|
||||||
title: 'Memo',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
{/* 登录 */}
|
{/* 落地页 */}
|
||||||
<Tabs.Screen
|
|
||||||
name="login"
|
|
||||||
options={{
|
|
||||||
title: 'Login',
|
|
||||||
href: '/login',
|
|
||||||
// tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* 重置密码 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="reset-password"
|
|
||||||
options={{
|
|
||||||
title: 'reset-password',
|
|
||||||
href: '/reset-password',
|
|
||||||
// tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* loading页面 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="loading"
|
|
||||||
options={{
|
|
||||||
title: 'loading',
|
|
||||||
href: '/loading',
|
|
||||||
// tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* 用户信息收集 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="user-message"
|
|
||||||
options={{
|
|
||||||
title: 'user-message',
|
|
||||||
href: '/user-message',
|
|
||||||
// tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* ask页面 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="ask"
|
|
||||||
options={{
|
|
||||||
title: 'ask',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* memo list */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="memo-list"
|
|
||||||
options={{
|
|
||||||
title: 'memo-list',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* owner */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="owner"
|
|
||||||
options={{
|
|
||||||
title: 'owner',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* 排行榜 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="top"
|
|
||||||
options={{
|
|
||||||
title: 'top',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* 对话详情页 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="chat-details"
|
|
||||||
options={{
|
|
||||||
title: 'chat-details',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* 隐私协议 */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="privacy-policy"
|
|
||||||
options={{
|
|
||||||
title: 'privacy-policy',
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Support Screen */}
|
|
||||||
<Tabs.Screen
|
|
||||||
name="support"
|
|
||||||
options={{
|
|
||||||
title: t('tabTitle', { ns: 'support' }),
|
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
|
||||||
headerShown: false, // 隐藏导航栏
|
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Debug Screen - only in development */}
|
|
||||||
{process.env.NODE_ENV === 'development' && (
|
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="debug"
|
name="index"
|
||||||
options={{
|
options={{
|
||||||
title: 'Debug',
|
title: 'Memo',
|
||||||
tabBarIcon: ({ color, focused }) => (
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
<TabBarIcon name={focused ? 'bug' : 'bug-outline'} color={color} />
|
headerShown: false, // 隐藏导航栏
|
||||||
),
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 登录 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="login"
|
||||||
|
options={{
|
||||||
|
title: 'Login',
|
||||||
|
href: '/login',
|
||||||
|
// tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 重置密码 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="reset-password"
|
||||||
|
options={{
|
||||||
|
title: 'reset-password',
|
||||||
|
href: '/reset-password',
|
||||||
|
// tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* loading页面 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="loading"
|
||||||
|
options={{
|
||||||
|
title: 'loading',
|
||||||
|
href: '/loading',
|
||||||
|
// tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 用户信息收集 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="user-message"
|
||||||
|
options={{
|
||||||
|
title: 'user-message',
|
||||||
|
href: '/user-message',
|
||||||
|
// tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* ask页面 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="ask"
|
||||||
|
options={{
|
||||||
|
title: 'ask',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' }, // 确保在标签栏中不显示
|
||||||
|
...TransitionPresets.ShiftTransition,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* memo list */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="memo-list"
|
||||||
|
options={{
|
||||||
|
title: 'memo-list',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' }, // 确保在标签栏中不显示
|
||||||
|
...TransitionPresets.ShiftTransition,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* owner */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="owner"
|
||||||
|
options={{
|
||||||
|
title: 'owner',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' }, // 确保在标签栏中不显示
|
||||||
|
...TransitionPresets.ShiftTransition,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 排行榜 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="top"
|
||||||
|
options={{
|
||||||
|
title: 'top',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 对话详情页 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="chat-details"
|
||||||
|
options={{
|
||||||
|
title: 'chat-details',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* 隐私协议 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="privacy-policy"
|
||||||
|
options={{
|
||||||
|
title: 'privacy-policy',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 下载页面 */}
|
{/* Support Screen */}
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="download"
|
name="support"
|
||||||
options={{
|
options={{
|
||||||
title: 'download',
|
title: t('tabTitle', { ns: 'support' }),
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
headerShown: false, // 隐藏导航栏
|
headerShown: false, // 隐藏导航栏
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 购买权益页面 */}
|
{/* Debug Screen - only in development */}
|
||||||
<Tabs.Screen
|
{process.env.NODE_ENV === 'development' && (
|
||||||
name="rights"
|
<Tabs.Screen
|
||||||
options={{
|
name="debug"
|
||||||
title: 'rights',
|
options={{
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
title: 'Debug',
|
||||||
headerShown: false, // 隐藏导航栏
|
tabBarIcon: ({ color, focused }) => (
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
<TabBarIcon name={focused ? 'bug' : 'bug-outline'} color={color} />
|
||||||
}}
|
),
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 设置页面 */}
|
{/* 下载页面 */}
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="setting"
|
name="download"
|
||||||
options={{
|
options={{
|
||||||
title: 'setting',
|
title: 'download',
|
||||||
tabBarButton: () => null, // 隐藏底部标签栏
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
headerShown: false, // 隐藏导航栏
|
headerShown: false, // 隐藏导航栏
|
||||||
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Tabs >
|
|
||||||
|
{/* 购买权益页面 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="rights"
|
||||||
|
options={{
|
||||||
|
title: 'rights',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 设置页面 */}
|
||||||
|
<Tabs.Screen
|
||||||
|
name="setting"
|
||||||
|
options={{
|
||||||
|
title: 'setting',
|
||||||
|
tabBarButton: () => null, // 隐藏底部标签栏
|
||||||
|
headerShown: false, // 隐藏导航栏
|
||||||
|
tabBarStyle: { display: 'none' } // 确保在标签栏中不显示
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs >
|
||||||
|
<AskNavbar />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|||||||
import ChatSvg from '@/assets/icons/svg/chat.svg';
|
import ChatSvg from '@/assets/icons/svg/chat.svg';
|
||||||
import ErrorBoundary from '@/components/common/ErrorBoundary';
|
import ErrorBoundary from '@/components/common/ErrorBoundary';
|
||||||
import UploaderProgress from '@/components/file-upload/upload-progress/uploader-progress';
|
import UploaderProgress from '@/components/file-upload/upload-progress/uploader-progress';
|
||||||
import AskNavbar from '@/components/layout/ask';
|
|
||||||
import SkeletonItem from '@/components/memo/SkeletonItem';
|
import SkeletonItem from '@/components/memo/SkeletonItem';
|
||||||
|
|
||||||
// 类型定义
|
// 类型定义
|
||||||
@ -176,7 +176,7 @@ const MemoList = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{/* 上传进度 */}
|
{/* 上传进度 */}
|
||||||
<UploadProgressSection />
|
{/* <UploadProgressSection /> */}
|
||||||
</View>
|
</View>
|
||||||
), [insets.top]);
|
), [insets.top]);
|
||||||
|
|
||||||
@ -218,9 +218,8 @@ const MemoList = () => {
|
|||||||
// 如果组件未完全加载,显示骨架屏
|
// 如果组件未完全加载,显示骨架屏
|
||||||
if (!isMounted) {
|
if (!isMounted) {
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { paddingTop: insets.top }]}>
|
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||||
<SkeletonList />
|
<SkeletonList />
|
||||||
<AskNavbar />
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -257,9 +256,6 @@ const MemoList = () => {
|
|||||||
contentContainerStyle={styles.listContent}
|
contentContainerStyle={styles.listContent}
|
||||||
ItemSeparatorComponent={() => <View style={styles.separator} />}
|
ItemSeparatorComponent={() => <View style={styles.separator} />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 底部导航栏 */}
|
|
||||||
<AskNavbar />
|
|
||||||
</View>
|
</View>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import ConversationsSvg from '@/assets/icons/svg/conversations.svg';
|
import ConversationsSvg from '@/assets/icons/svg/conversations.svg';
|
||||||
import StoriesSvg from '@/assets/icons/svg/stories.svg';
|
import StoriesSvg from '@/assets/icons/svg/stories.svg';
|
||||||
import AskNavbar from '@/components/layout/ask';
|
|
||||||
import CreateCountComponent from '@/components/owner/createCount';
|
import CreateCountComponent from '@/components/owner/createCount';
|
||||||
import MemberCard from '@/components/owner/rights/memberCard';
|
import MemberCard from '@/components/owner/rights/memberCard';
|
||||||
import SettingModal from '@/components/owner/setting';
|
import SettingModal from '@/components/owner/setting';
|
||||||
|
import SkeletonOwner from '@/components/owner/SkeletonOwner';
|
||||||
import UserInfo from '@/components/owner/userName';
|
import UserInfo from '@/components/owner/userName';
|
||||||
import { checkAuthStatus } from '@/lib/auth';
|
import { checkAuthStatus } from '@/lib/auth';
|
||||||
import { fetchApi } from '@/lib/server-api-util';
|
import { fetchApi } from '@/lib/server-api-util';
|
||||||
@ -20,6 +21,9 @@ export default function OwnerPage() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
// 添加页面挂载状态
|
||||||
|
const [isMounted, setIsMounted] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkAuth = async () => {
|
const checkAuth = async () => {
|
||||||
const authStatus = await checkAuthStatus(router);
|
const authStatus = await checkAuthStatus(router);
|
||||||
@ -47,11 +51,17 @@ export default function OwnerPage() {
|
|||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
const [userInfoDetails, setUserInfoDetails] = useState<UserInfoDetails>({} as UserInfoDetails);
|
const [userInfoDetails, setUserInfoDetails] = useState<UserInfoDetails>({} as UserInfoDetails);
|
||||||
const getUserInfo = () => {
|
|
||||||
|
// 优化getUserInfo函数,添加挂载状态检查
|
||||||
|
const getUserInfo = useCallback(() => {
|
||||||
fetchApi("/membership/personal-center-info").then((res) => {
|
fetchApi("/membership/personal-center-info").then((res) => {
|
||||||
setUserInfoDetails(res as UserInfoDetails);
|
// 只有在组件挂载时才更新状态
|
||||||
|
if (isMounted) {
|
||||||
|
setUserInfoDetails(res as UserInfoDetails);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}, [isMounted]);
|
||||||
|
|
||||||
// 设计轮询获取数量统计
|
// 设计轮询获取数量统计
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
@ -70,8 +80,35 @@ export default function OwnerPage() {
|
|||||||
|
|
||||||
// 初始化获取用户信息
|
// 初始化获取用户信息
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getUserInfo();
|
let isActive = true;
|
||||||
}, []);
|
|
||||||
|
const initialize = async () => {
|
||||||
|
try {
|
||||||
|
await getUserInfo();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化失败:', error);
|
||||||
|
} finally {
|
||||||
|
if (isActive) {
|
||||||
|
setIsMounted(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isActive = false;
|
||||||
|
};
|
||||||
|
}, [getUserInfo]);
|
||||||
|
|
||||||
|
// 如果组件未完全加载,显示骨架屏
|
||||||
|
if (!isMounted) {
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||||
|
<SkeletonOwner />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { paddingTop: insets.top }]}>
|
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||||
@ -112,9 +149,6 @@ export default function OwnerPage() {
|
|||||||
{modalVisible && (
|
{modalVisible && (
|
||||||
<SettingModal modalVisible={modalVisible} setModalVisible={setModalVisible} userInfo={userInfoDetails.user_info} />
|
<SettingModal modalVisible={modalVisible} setModalVisible={setModalVisible} userInfo={userInfoDetails.user_info} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 导航栏 */}
|
|
||||||
<AskNavbar />
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,6 +131,11 @@ const AskNavbar = () => {
|
|||||||
}
|
}
|
||||||
}), [width]);
|
}), [width]);
|
||||||
|
|
||||||
|
// 如果当前路径是ask页面,则不渲染导航栏
|
||||||
|
if (pathname != '/memo-list' && pathname != '/owner') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Image source={require('@/assets/images/png/owner/ask.png')} style={{ width: width, height: 80, resizeMode: 'cover' }} />
|
<Image source={require('@/assets/images/png/owner/ask.png')} style={{ width: width, height: 80, resizeMode: 'cover' }} />
|
||||||
|
|||||||
92
components/owner/SkeletonOwner.tsx
Normal file
92
components/owner/SkeletonOwner.tsx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, View } from 'react-native';
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
|
// 骨架屏占位组件
|
||||||
|
const SkeletonItem = () => (
|
||||||
|
<View style={styles.skeletonItem} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const SkeletonOwner = () => {
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, { paddingTop: insets.top }]}>
|
||||||
|
{/* 用户信息骨架屏 */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<View style={styles.userInfoHeader}>
|
||||||
|
<SkeletonItem />
|
||||||
|
<View style={styles.userInfoTextContainer}>
|
||||||
|
<SkeletonItem />
|
||||||
|
<SkeletonItem />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<View style={styles.userInfoStats}>
|
||||||
|
<SkeletonItem />
|
||||||
|
<SkeletonItem />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 会员卡骨架屏 */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<SkeletonItem />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 作品数据骨架屏 */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<View style={styles.countContainer}>
|
||||||
|
<SkeletonItem />
|
||||||
|
<SkeletonItem />
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 排行榜骨架屏 */}
|
||||||
|
<View style={styles.section}>
|
||||||
|
<SkeletonItem />
|
||||||
|
<View style={styles.rankingList}>
|
||||||
|
{Array(3).fill(0).map((_, index) => (
|
||||||
|
<SkeletonItem key={`ranking-${index}`} />
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: 'white',
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
skeletonItem: {
|
||||||
|
backgroundColor: '#E1E1E1',
|
||||||
|
borderRadius: 8,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
userInfoHeader: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
userInfoTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
marginLeft: 16,
|
||||||
|
},
|
||||||
|
userInfoStats: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
},
|
||||||
|
countContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
gap: 16,
|
||||||
|
},
|
||||||
|
rankingList: {
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SkeletonOwner;
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import React, { useMemo } from "react";
|
||||||
import { StyleProp, StyleSheet, View, ViewStyle } from "react-native";
|
import { StyleProp, StyleSheet, View, ViewStyle } from "react-native";
|
||||||
import { ThemedText } from "../ThemedText";
|
import { ThemedText } from "../ThemedText";
|
||||||
|
|
||||||
@ -7,9 +8,17 @@ interface CreateCountProps {
|
|||||||
number: number;
|
number: number;
|
||||||
style?: StyleProp<ViewStyle>;
|
style?: StyleProp<ViewStyle>;
|
||||||
}
|
}
|
||||||
const CreateCountComponent = (props: CreateCountProps) => {
|
|
||||||
|
// 使用React.memo优化组件,避免不必要的重渲染
|
||||||
|
const CreateCountComponent = React.memo((props: CreateCountProps) => {
|
||||||
|
// 预计算样式以提高性能
|
||||||
|
const containerStyle = useMemo(() => [
|
||||||
|
styles.container,
|
||||||
|
props.style
|
||||||
|
], [props.style]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={containerStyle}>
|
||||||
<ThemedText style={styles.number} className="!text-textSecondary">{props.number}</ThemedText>
|
<ThemedText style={styles.number} className="!text-textSecondary">{props.number}</ThemedText>
|
||||||
<View style={styles.header}>
|
<View style={styles.header}>
|
||||||
<View className="mt-1">
|
<View className="mt-1">
|
||||||
@ -19,7 +28,7 @@ const CreateCountComponent = (props: CreateCountProps) => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
@ -39,7 +48,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
shadowOpacity: 0.25,
|
shadowOpacity: 0.25,
|
||||||
shadowRadius: 3.84,
|
shadowRadius: 3.84,
|
||||||
elevation: 5,
|
// elevation: 1,
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@ -63,5 +72,6 @@ const styles = StyleSheet.create({
|
|||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
color: "#4C320C"
|
color: "#4C320C"
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
export default CreateCountComponent;
|
export default CreateCountComponent;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user