From 2a9db5b070826916b2c72c4b8bf6f4401ece8ae9 Mon Sep 17 00:00:00 2001 From: jinyaqiu Date: Tue, 29 Jul 2025 15:55:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=BC=E8=88=AA=E6=A0=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/layout/ask.tsx | 207 ++++++++++++++++++++++++++------------ 1 file changed, 143 insertions(+), 64 deletions(-) diff --git a/components/layout/ask.tsx b/components/layout/ask.tsx index 3a8445b..d0c36de 100644 --- a/components/layout/ask.tsx +++ b/components/layout/ask.tsx @@ -3,87 +3,166 @@ import ChatNotInSvg from "@/assets/icons/svg/chatNotIn.svg"; import PersonInSvg from "@/assets/icons/svg/personIn.svg"; import PersonNotInSvg from "@/assets/icons/svg/personNotIn.svg"; import { router, usePathname } from "expo-router"; -import React from 'react'; -import { Dimensions, Image, Platform, TouchableOpacity, View } from 'react-native'; -import { Circle, Ellipse, G, Mask, Path, Rect, Svg } from 'react-native-svg'; +import React, { useCallback, useEffect, useMemo } from 'react'; +import { Dimensions, Image, StyleSheet, TouchableOpacity, View } from 'react-native'; +import Svg, { Circle, Ellipse, G, Mask, Path, Rect } from "react-native-svg"; + +// 使用 React.memo 包装 SVG 组件,避免不必要的重渲染 +const TabIcon = React.memo(({ isActive, ActiveIcon, InactiveIcon }: { + isActive: boolean; + ActiveIcon: React.FC<{ width: number; height: number }>; + InactiveIcon: React.FC<{ width: number; height: number }>; +}) => { + const Icon = isActive ? ActiveIcon : InactiveIcon; + return ; +}); + +// 提取 SVG 组件,避免重复渲染 +const CenterButtonSvg = React.memo(() => ( + + + + + + + + + + + + + + + + + + + + +)); const AskNavbar = () => { // 获取设备尺寸 - const { width } = Dimensions.get('window'); - // 获取路由 + const { width } = useMemo(() => Dimensions.get('window'), []); const pathname = usePathname(); - return ( - { + const preloadPages = async () => { + try { + await Promise.all([ + router.prefetch('/memo-list'), + router.prefetch('/ask'), + router.prefetch('/owner') + ]); + } catch (error) { + console.warn('预加载页面失败:', error); + } + }; + preloadPages(); + }, []); + + // 使用 useCallback 缓存导航函数 + const navigateTo = useCallback((route: string) => { + if (route === '/ask') { + router.push({ + pathname: '/ask', + params: { newSession: "true" } + }); + } else { + router.push(route as any); + } + }, []); + + // 使用 useMemo 缓存样式对象 + const styles = useMemo(() => StyleSheet.create({ + container: { + position: 'absolute', + bottom: 0, + left: 0, + right: 0, + backgroundColor: 'white', shadowColor: '#000', - shadowOffset: { width: 0, height: -4 }, // Negative height for bottom shadow + shadowOffset: { width: 0, height: -4 }, shadowOpacity: 0.1, shadowRadius: 8, - elevation: 10, // For Android - }}> - {/* */} + elevation: 10, + }, + backgroundImage: { + width, + height: 80, + resizeMode: 'cover' + }, + navButton: { + padding: 16 + }, + navContainer: { + position: 'absolute', + bottom: 0, + left: 0, + right: 0, + height: 80, // Set a fixed height for the navbar + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 32, + backgroundColor: 'transparent', // Make sure it's transparent + }, + centerButton: { + position: 'absolute', + left: width / 2, + top: -42.5, // Adjust this value to move the button up or down + marginLeft: -42.5, // Half of the button width (85/2) + width: 85, + height: 85, + justifyContent: 'center', + alignItems: 'center', + shadowColor: '#FFB645', + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.3, + shadowRadius: 8, + elevation: 8, + borderRadius: 50, + backgroundColor: 'transparent', + zIndex: 10, + } + }), [width]); + + return ( + - - router.push('/memo-list')} style={{ padding: 16 }}> - {pathname === "/memo-list" ? : } + + navigateTo('/memo-list')} + style={styles.navButton} + > + { - router.push({ - pathname: '/ask', - params: { newSession: "true" } - }); - }} - className={`${Platform.OS === 'web' ? '-mt-[4rem]' : width <= 375 ? '-mt-[5rem]' : '-mt-[5rem]'}`} + onPress={() => navigateTo('/ask')} + style={styles.centerButton} > - - - - - - - - - - - - - - - - - - - - - - - - - - + - router.push('/owner')} style={{ padding: 16 }}> - - {pathname === "/owner" ? : } - {/* */} - + + navigateTo('/owner')} + style={styles.navButton} + > + ); }; -export default AskNavbar; \ No newline at end of file +export default React.memo(AskNavbar); \ No newline at end of file