Browse Source

购物车价格字体变小

main
Mac 2 weeks ago
parent
commit
f2bb2961a3
  1. 53
      app/screens/HomeScreen.tsx
  2. 28
      app/utils/languageUtils.ts

53
app/screens/HomeScreen.tsx

@ -62,7 +62,6 @@ type SubcategoryItem = {
type CategoryContentType = { type CategoryContentType = {
[key: string]: SubcategoryItem[]; [key: string]: SubcategoryItem[];
}; };
// 懒加载图片组件 - 改进版本 // 懒加载图片组件 - 改进版本
const LazyImage = React.memo( const LazyImage = React.memo(
({ ({
@ -76,16 +75,13 @@ const LazyImage = React.memo(
}) => { }) => {
const [isLoaded, setIsLoaded] = useState(false); const [isLoaded, setIsLoaded] = useState(false);
const [hasError, setHasError] = useState(false); const [hasError, setHasError] = useState(false);
const onLoad = useCallback(() => { const onLoad = useCallback(() => {
setIsLoaded(true); setIsLoaded(true);
}, []); }, []);
const onError = useCallback(() => { const onError = useCallback(() => {
setHasError(true); setHasError(true);
setIsLoaded(true); // Also mark as loaded on error to remove placeholder setIsLoaded(true); // Also mark as loaded on error to remove placeholder
}, []); }, []);
return ( return (
<View style={[style, { overflow: "hidden" }]}> <View style={[style, { overflow: "hidden" }]}>
{/* Show placeholder while image is loading */} {/* Show placeholder while image is loading */}
@ -98,7 +94,6 @@ const LazyImage = React.memo(
]} ]}
/> />
)} )}
{/* Show error state if image failed to load */} {/* Show error state if image failed to load */}
{hasError && ( {hasError && (
<View <View
@ -116,7 +111,6 @@ const LazyImage = React.memo(
</Text> </Text>
</View> </View>
)} )}
{/* Actual image */} {/* Actual image */}
<Image <Image
source={{ uri }} source={{ uri }}
@ -129,12 +123,10 @@ const LazyImage = React.memo(
); );
} }
); );
// 产品骨架屏组件 - 用于加载状态 // 产品骨架屏组件 - 用于加载状态
const ProductSkeleton = React.memo(() => { const ProductSkeleton = React.memo(() => {
// 创建动画值 // 创建动画值
const shimmerAnim = useRef(new Animated.Value(0)).current; const shimmerAnim = useRef(new Animated.Value(0)).current;
// 设置动画效果 // 设置动画效果
useEffect(() => { useEffect(() => {
const shimmerAnimation = Animated.loop( const shimmerAnimation = Animated.loop(
@ -144,20 +136,16 @@ const ProductSkeleton = React.memo(() => {
useNativeDriver: true, useNativeDriver: true,
}) })
); );
shimmerAnimation.start(); shimmerAnimation.start();
return () => { return () => {
shimmerAnimation.stop(); shimmerAnimation.stop();
}; };
}, []); }, []);
// 定义动画插值 // 定义动画插值
const shimmerTranslate = shimmerAnim.interpolate({ const shimmerTranslate = shimmerAnim.interpolate({
inputRange: [0, 1], inputRange: [0, 1],
outputRange: [-200, 200], outputRange: [-200, 200],
}); });
return ( return (
<View style={styles.beautyProductCard1}> <View style={styles.beautyProductCard1}>
<View style={styles.skeletonImage}> <View style={styles.skeletonImage}>
@ -219,7 +207,6 @@ const ProductSkeleton = React.memo(() => {
</View> </View>
); );
}); });
// Define the styles type to fix TypeScript errors // Define the styles type to fix TypeScript errors
type StylesType = { type StylesType = {
safeArea: ViewStyle; safeArea: ViewStyle;
@ -273,6 +260,7 @@ type StylesType = {
productCardList: ViewStyle; productCardList: ViewStyle;
productCardGroup: ViewStyle; productCardGroup: ViewStyle;
beautyProductCard1: ViewStyle; beautyProductCard1: ViewStyle;
productCardGroup1: ViewStyle;
beautyCardContainer1: ViewStyle; beautyCardContainer1: ViewStyle;
vipButtonContainer: ViewStyle; vipButtonContainer: ViewStyle;
vipButton: ViewStyle; vipButton: ViewStyle;
@ -308,7 +296,6 @@ type StylesType = {
imagePickerCancelButton: ViewStyle; imagePickerCancelButton: ViewStyle;
imagePickerCancelText: TextStyle; imagePickerCancelText: TextStyle;
}; };
export const HomeScreen = () => { export const HomeScreen = () => {
const [activeIndex, setActiveIndex] = useState(0); const [activeIndex, setActiveIndex] = useState(0);
const screenWidth = Dimensions.get("window").width; const screenWidth = Dimensions.get("window").width;
@ -339,7 +326,6 @@ export const HomeScreen = () => {
const [galleryUsed, setGalleryUsed] = useState(false); const [galleryUsed, setGalleryUsed] = useState(false);
const [hotTerms, setHotTerms] = useState<string[]>([]); const [hotTerms, setHotTerms] = useState<string[]>([]);
const [isLoadingHotTerms, setIsLoadingHotTerms] = useState(false); const [isLoadingHotTerms, setIsLoadingHotTerms] = useState(false);
// 直接在组件中实现分页加载逻辑 // 直接在组件中实现分页加载逻辑
const [products, setProducts] = useState<Product[]>([]); const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
@ -537,7 +523,6 @@ export const HomeScreen = () => {
setRefreshing(false); setRefreshing(false);
} }
}, [hotTerms, getRandomKeyword, fetchInitialProducts]); }, [hotTerms, getRandomKeyword, fetchInitialProducts]);
const handleProductPress = useCallback( const handleProductPress = useCallback(
(item: Product) => { (item: Product) => {
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
@ -550,7 +535,6 @@ export const HomeScreen = () => {
}, },
[navigation] [navigation]
); );
const categories = [ const categories = [
"Tous", "Tous",
"Bijoux", "Bijoux",
@ -564,7 +548,6 @@ export const HomeScreen = () => {
"Hygiène et Soins pour le corps", "Hygiène et Soins pour le corps",
"Maquillage", "Maquillage",
]; ];
const defaultSubcategories: SubcategoryItem[] = [ const defaultSubcategories: SubcategoryItem[] = [
{ id: 1, title: "Jewelry", icon: "diamond-outline" }, { id: 1, title: "Jewelry", icon: "diamond-outline" },
{ id: 2, title: "Earrings", icon: "ear-outline" }, { id: 2, title: "Earrings", icon: "ear-outline" },
@ -573,7 +556,6 @@ export const HomeScreen = () => {
{ id: 5, title: "Earrings", icon: "ear-outline" }, { id: 5, title: "Earrings", icon: "ear-outline" },
{ id: 6, title: "Bracelet", icon: "watch-outline" }, { id: 6, title: "Bracelet", icon: "watch-outline" },
]; ];
const categoryContent: CategoryContentType = { const categoryContent: CategoryContentType = {
Tous: [], Tous: [],
Bijoux: defaultSubcategories, Bijoux: defaultSubcategories,
@ -587,31 +569,26 @@ export const HomeScreen = () => {
"Hygiène et Soins pour le corps": defaultSubcategories, "Hygiène et Soins pour le corps": defaultSubcategories,
Maquillage: defaultSubcategories, Maquillage: defaultSubcategories,
}; };
useEffect(() => { useEffect(() => {
if (!categoryContent[selectedHorizontalCategory]) { if (!categoryContent[selectedHorizontalCategory]) {
setSelectedHorizontalCategory("Tous"); setSelectedHorizontalCategory("Tous");
} }
}, [selectedHorizontalCategory]); }, [selectedHorizontalCategory]);
const navigateToSearch = useCallback(() => { const navigateToSearch = useCallback(() => {
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
navigation.navigate("Search"); navigation.navigate("Search");
}); });
}, [navigation]); }, [navigation]);
const navigateToShippingDetails = useCallback(() => { const navigateToShippingDetails = useCallback(() => {
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
navigation.navigate("ShippingDetailsSection"); navigation.navigate("ShippingDetailsSection");
}); });
}, [navigation]); }, [navigation]);
const navigateToInquiry = useCallback(() => { const navigateToInquiry = useCallback(() => {
InteractionManager.runAfterInteractions(() => { InteractionManager.runAfterInteractions(() => {
navigation.navigate("InquiryScreen"); navigation.navigate("InquiryScreen");
}); });
}, [navigation]); }, [navigation]);
const scrollToCategory = (category: string) => { const scrollToCategory = (category: string) => {
const categoryIndex = categories.findIndex((c) => c === category); const categoryIndex = categories.findIndex((c) => c === category);
if (categoryIndex !== -1 && horizontalScrollRef.current) { if (categoryIndex !== -1 && horizontalScrollRef.current) {
@ -626,7 +603,6 @@ export const HomeScreen = () => {
}); });
} }
}; };
const renderProductItem = ({ item }: { item: Product }) => ( const renderProductItem = ({ item }: { item: Product }) => (
<TouchableOpacity <TouchableOpacity
onPress={() => handleProductPress(item)} onPress={() => handleProductPress(item)}
@ -645,7 +621,6 @@ export const HomeScreen = () => {
<IconComponent name="image-outline" size={24} color="#999" /> <IconComponent name="image-outline" size={24} color="#999" />
</View> </View>
)} )}
{userStore.user?.user_id && ( {userStore.user?.user_id && (
<View style={styles.vipButtonContainer}> <View style={styles.vipButtonContainer}>
<TouchableOpacity style={styles.vipButton}> <TouchableOpacity style={styles.vipButton}>
@ -677,7 +652,6 @@ export const HomeScreen = () => {
</View> </View>
</TouchableOpacity> </TouchableOpacity>
); );
const renderSkeletonGrid = useCallback(() => { const renderSkeletonGrid = useCallback(() => {
const skeletonArray = Array(8).fill(null); const skeletonArray = Array(8).fill(null);
return ( return (
@ -694,7 +668,6 @@ export const HomeScreen = () => {
</View> </View>
); );
}, []); }, []);
const cleanupImagePickerCache = async () => { const cleanupImagePickerCache = async () => {
try { try {
if (Platform.OS === 'web') { if (Platform.OS === 'web') {
@ -712,7 +685,6 @@ export const HomeScreen = () => {
setGalleryUsed(false); setGalleryUsed(false);
} }
}; };
const handleChooseFromGallery = useCallback(async () => { const handleChooseFromGallery = useCallback(async () => {
setShowImagePickerModal(false); setShowImagePickerModal(false);
setTimeout(async () => { setTimeout(async () => {
@ -722,14 +694,12 @@ export const HomeScreen = () => {
console.log("相册权限被拒绝"); console.log("相册权限被拒绝");
return; return;
} }
const result = await ImagePicker.launchImageLibraryAsync({ const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images, mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true, allowsEditing: true,
aspect: [4, 3], aspect: [4, 3],
quality: 1, quality: 1,
}); });
if (!result.canceled && result.assets && result.assets.length > 0) { if (!result.canceled && result.assets && result.assets.length > 0) {
await cleanupImagePickerCache(); await cleanupImagePickerCache();
navigation.navigate("ImageSearchResultScreen", { navigation.navigate("ImageSearchResultScreen", {
@ -743,7 +713,6 @@ export const HomeScreen = () => {
} }
}, 500); }, 500);
}, []); }, []);
const handleTakePhoto = useCallback(async () => { const handleTakePhoto = useCallback(async () => {
setShowImagePickerModal(false); setShowImagePickerModal(false);
setTimeout(async () => { setTimeout(async () => {
@ -753,14 +722,12 @@ export const HomeScreen = () => {
console.log("相机权限被拒绝"); console.log("相机权限被拒绝");
return; return;
} }
const result = await ImagePicker.launchCameraAsync({ const result = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images, mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true, allowsEditing: true,
aspect: [4, 3], aspect: [4, 3],
quality: 1, quality: 1,
}); });
if (!result.canceled && result.assets && result.assets.length > 0) { if (!result.canceled && result.assets && result.assets.length > 0) {
await cleanupImagePickerCache(); await cleanupImagePickerCache();
navigation.navigate("ImageSearchResultScreen", { navigation.navigate("ImageSearchResultScreen", {
@ -774,25 +741,21 @@ export const HomeScreen = () => {
} }
}, 500); }, 500);
}, []); }, []);
const resetAppState = useCallback(() => { const resetAppState = useCallback(() => {
setGalleryUsed(false); setGalleryUsed(false);
cleanupImagePickerCache(); cleanupImagePickerCache();
Alert.alert("已重置", "现在您可以使用相机功能了"); Alert.alert("已重置", "现在您可以使用相机功能了");
}, []); }, []);
// 优化轮播图切换回调 // 优化轮播图切换回调
const handleCarouselSnap = useCallback((index: number) => { const handleCarouselSnap = useCallback((index: number) => {
setActiveIndex(index); setActiveIndex(index);
}, []); }, []);
const renderItem = ({ item, index }: { item: Product; index: number }) => { const renderItem = ({ item, index }: { item: Product; index: number }) => {
if (index >= products.length && index < products.length + loadingPlaceholders) { if (index >= products.length && index < products.length + loadingPlaceholders) {
return <ProductSkeleton />; return <ProductSkeleton />;
} }
return renderProductItem({ item }); return renderProductItem({ item });
}; };
const renderHeader = useCallback(() => ( const renderHeader = useCallback(() => (
<> <>
<View style={styles.swiperContainer}> <View style={styles.swiperContainer}>
@ -962,7 +925,6 @@ export const HomeScreen = () => {
) : null} ) : null}
</> </>
), [activeIndex, selectedHorizontalCategory]); ), [activeIndex, selectedHorizontalCategory]);
return ( return (
<SafeAreaView style={styles.safeArea}> <SafeAreaView style={styles.safeArea}>
<StatusBar barStyle="dark-content" backgroundColor="#fff" /> <StatusBar barStyle="dark-content" backgroundColor="#fff" />
@ -1179,7 +1141,7 @@ export const HomeScreen = () => {
const rightItem = allItems[i + 1]; const rightItem = allItems[i + 1];
rows.push( rows.push(
<View key={`row-${i}`} style={styles.productCardGroup}> <View key={`row-${i}`} style={styles.productCardGroup1}>
{/* 左侧商品 */} {/* 左侧商品 */}
{leftItem ? ( {leftItem ? (
i >= products.length ? ( i >= products.length ? (
@ -1216,7 +1178,6 @@ export const HomeScreen = () => {
</View> </View>
</ScrollView> </ScrollView>
)} )}
<Modal <Modal
visible={showCategoryModal} visible={showCategoryModal}
animationType="slide" animationType="slide"
@ -1272,7 +1233,6 @@ export const HomeScreen = () => {
</View> </View>
</View> </View>
</Modal> </Modal>
<Modal <Modal
visible={showImagePickerModal} visible={showImagePickerModal}
animationType="slide" animationType="slide"
@ -1310,9 +1270,7 @@ export const HomeScreen = () => {
<Text style={styles.imagePickerText}></Text> <Text style={styles.imagePickerText}></Text>
</TouchableOpacity> </TouchableOpacity>
)} )}
<View style={styles.imagePickerDivider} /> <View style={styles.imagePickerDivider} />
<TouchableOpacity <TouchableOpacity
style={styles.imagePickerOption} style={styles.imagePickerOption}
onPress={handleChooseFromGallery} onPress={handleChooseFromGallery}
@ -1320,9 +1278,7 @@ export const HomeScreen = () => {
<IconComponent name="images-outline" size={24} color="#333" /> <IconComponent name="images-outline" size={24} color="#333" />
<Text style={styles.imagePickerText}>{t("homePage.chooseFromGallery")}</Text> <Text style={styles.imagePickerText}>{t("homePage.chooseFromGallery")}</Text>
</TouchableOpacity> </TouchableOpacity>
<View style={styles.imagePickerDivider} /> <View style={styles.imagePickerDivider} />
<TouchableOpacity <TouchableOpacity
style={styles.imagePickerCancelButton} style={styles.imagePickerCancelButton}
onPress={() => setShowImagePickerModal(false)} onPress={() => setShowImagePickerModal(false)}
@ -1615,6 +1571,11 @@ const styles = StyleSheet.create<StylesType>({
marginBottom: 15, marginBottom: 15,
paddingHorizontal: 15, paddingHorizontal: 15,
}, },
productCardGroup1:{
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 15,
},
beautyProductCard1: { beautyProductCard1: {
width: "48%", width: "48%",
}, },

28
app/utils/languageUtils.ts

@ -55,3 +55,31 @@ export const getSkuTransLanguage = <T extends Record<string, any>>(data: T): str
// 返回匹配的翻译值,如果没有匹配则返回法语 // 返回匹配的翻译值,如果没有匹配则返回法语
return (data[matchedField || 'value_trans'] as string) || ''; return (data[matchedField || 'value_trans'] as string) || '';
}; };
export const getOrderTransLanguage = <T extends Record<string, any>>(data: T): string => {
// 获取当前i18n语言
const currentLang = getCurrentLanguage();
// 特殊处理中文
if (currentLang === 'zh' && 'value' in data) {
return data.value as string;
}
// 获取所有subject_trans开头的字段
const translationFields = Object.keys(data).filter(key =>
key.startsWith('product_name')
);
// 查找匹配的字段
const matchedField = translationFields.find(field => {
// 从字段名中提取语言代码
const langCode = field.replace('product_name', '');
// 如果没有后缀,则为法语
return langCode === '' ? currentLang === 'fr' : langCode === currentLang;
});
// 返回匹配的翻译值,如果没有匹配则返回法语
return (data[matchedField || 'product_name'] as string) || '';
};

Loading…
Cancel
Save